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