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