morse_code_worker.c 5.5 KB

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