morse_code_worker.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "morse_code_worker.h"
  2. #include <furi_hal.h>
  3. #include <lib/flipper_format/flipper_format.h>
  4. #define TAG "MorseCodeWorker"
  5. #define MORSE_CODE_VERSION 0
  6. //A-Z0-1
  7. const char morse_array[36][6] = {".-", "-...", "-.-.", "-..", ".", "..-.",
  8. "--.", "....", "..", ".---", "-.-", ".-..",
  9. "--", "-.", "---", ".--.", "--.-", ".-.",
  10. "...", "-", "..-", "...-", ".--", "-..-",
  11. "-.--", "--..", ".----", "..---", "...--", "....-",
  12. ".....", "-....", "--...", "---..", "----.", "-----"};
  13. const char symbol_array[36] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
  14. 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  15. 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
  16. struct MorseCodeWorker {
  17. FuriThread* thread;
  18. MorseCodeWorkerCallback callback;
  19. void* callback_context;
  20. bool is_running;
  21. bool play;
  22. float volume;
  23. uint32_t dit_delta;
  24. FuriString* buffer;
  25. FuriString* words;
  26. };
  27. void morse_code_worker_fill_buffer(MorseCodeWorker* instance, uint32_t duration) {
  28. FURI_LOG_D("MorseCode: Duration", "%ld", duration);
  29. if(duration <= instance->dit_delta)
  30. furi_string_push_back(instance->buffer, *DOT);
  31. else if(duration <= (instance->dit_delta * 3))
  32. furi_string_push_back(instance->buffer, *LINE);
  33. else
  34. furi_string_reset(instance->buffer);
  35. if(furi_string_size(instance->buffer) > 5) furi_string_reset(instance->buffer);
  36. FURI_LOG_D("MorseCode: Buffer", "%s", furi_string_get_cstr(instance->buffer));
  37. }
  38. void morse_code_worker_fill_letter(MorseCodeWorker* instance) {
  39. if(furi_string_size(instance->words) > 63) furi_string_reset(instance->words);
  40. for(size_t i = 0; i < sizeof(morse_array); i++) {
  41. if(furi_string_cmp_str(instance->buffer, morse_array[i]) == 0) {
  42. furi_string_push_back(instance->words, symbol_array[i]);
  43. break;
  44. }
  45. }
  46. furi_string_reset(instance->buffer);
  47. FURI_LOG_D("MorseCode: Words", "%s", furi_string_get_cstr(instance->words));
  48. }
  49. static int32_t morse_code_worker_thread_callback(void* context) {
  50. furi_assert(context);
  51. MorseCodeWorker* instance = context;
  52. bool was_playing = false;
  53. uint32_t start_tick = 0;
  54. uint32_t end_tick = 0;
  55. bool pushed = true;
  56. bool spaced = true;
  57. while(instance->is_running) {
  58. furi_delay_ms(SLEEP);
  59. if(instance->play) {
  60. if(!was_playing) {
  61. start_tick = furi_get_tick();
  62. if(furi_hal_speaker_acquire(1000)) {
  63. furi_hal_speaker_start(FREQUENCY, instance->volume);
  64. }
  65. was_playing = true;
  66. }
  67. } else {
  68. if(was_playing) {
  69. pushed = false;
  70. spaced = false;
  71. if(furi_hal_speaker_is_mine()) {
  72. furi_hal_speaker_stop();
  73. furi_hal_speaker_release();
  74. }
  75. end_tick = furi_get_tick();
  76. was_playing = false;
  77. morse_code_worker_fill_buffer(instance, end_tick - start_tick);
  78. start_tick = 0;
  79. }
  80. }
  81. if(!pushed) {
  82. if(end_tick + (instance->dit_delta * 3) < furi_get_tick()) {
  83. //NEW LETTER
  84. if(!furi_string_empty(instance->buffer)) {
  85. morse_code_worker_fill_letter(instance);
  86. if(instance->callback)
  87. instance->callback(instance->words, instance->callback_context);
  88. } else {
  89. spaced = true;
  90. }
  91. pushed = true;
  92. }
  93. }
  94. if(!spaced) {
  95. if(end_tick + (instance->dit_delta * 7) < furi_get_tick()) {
  96. //NEW WORD
  97. furi_string_push_back(instance->words, *SPACE);
  98. if(instance->callback)
  99. instance->callback(instance->words, instance->callback_context);
  100. spaced = true;
  101. }
  102. }
  103. }
  104. return 0;
  105. }
  106. MorseCodeWorker* morse_code_worker_alloc() {
  107. MorseCodeWorker* instance = malloc(sizeof(MorseCodeWorker));
  108. instance->thread = furi_thread_alloc();
  109. furi_thread_set_name(instance->thread, "MorseCodeWorker");
  110. furi_thread_set_stack_size(instance->thread, 1024);
  111. furi_thread_set_context(instance->thread, instance);
  112. furi_thread_set_callback(instance->thread, morse_code_worker_thread_callback);
  113. instance->play = false;
  114. instance->volume = 1.0f;
  115. instance->dit_delta = 150;
  116. instance->buffer = furi_string_alloc_set_str("");
  117. instance->words = furi_string_alloc_set_str("");
  118. return instance;
  119. }
  120. void morse_code_worker_free(MorseCodeWorker* instance) {
  121. furi_assert(instance);
  122. furi_string_free(instance->buffer);
  123. furi_string_free(instance->words);
  124. furi_thread_free(instance->thread);
  125. free(instance);
  126. }
  127. void morse_code_worker_set_callback(
  128. MorseCodeWorker* instance,
  129. MorseCodeWorkerCallback callback,
  130. void* context) {
  131. furi_assert(instance);
  132. instance->callback = callback;
  133. instance->callback_context = context;
  134. }
  135. void morse_code_worker_play(MorseCodeWorker* instance, bool play) {
  136. furi_assert(instance);
  137. instance->play = play;
  138. }
  139. void morse_code_worker_set_volume(MorseCodeWorker* instance, float level) {
  140. furi_assert(instance);
  141. instance->volume = level;
  142. }
  143. void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta) {
  144. furi_assert(instance);
  145. instance->dit_delta = delta;
  146. }
  147. void morse_code_worker_reset_text(MorseCodeWorker* instance) {
  148. furi_assert(instance);
  149. furi_string_reset(instance->buffer);
  150. furi_string_reset(instance->words);
  151. }
  152. void morse_code_worker_start(MorseCodeWorker* instance) {
  153. furi_assert(instance);
  154. furi_assert(instance->is_running == false);
  155. instance->is_running = true;
  156. furi_thread_start(instance->thread);
  157. FURI_LOG_D("MorseCode: Start", "is Running");
  158. }
  159. void morse_code_worker_stop(MorseCodeWorker* instance) {
  160. furi_assert(instance);
  161. furi_assert(instance->is_running == true);
  162. instance->play = false;
  163. instance->is_running = false;
  164. furi_thread_join(instance->thread);
  165. FURI_LOG_D("MorseCode: Stop", "Stop");
  166. }