mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
First Update
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
App(
|
||||
appid="Morse_Code",
|
||||
name="Morse Code",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="morse_code_app",
|
||||
cdefines=["APP_MORSE_CODE"],
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
stack_size=1 * 1024,
|
||||
order=20,
|
||||
fap_icon="morse_code_10px.png",
|
||||
fap_category="Music"
|
||||
|
||||
)
|
||||
@@ -1,166 +0,0 @@
|
||||
#include "morse_code_worker.h"
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/elements.h>
|
||||
#include <input/input.h>
|
||||
#include <stdlib.h>
|
||||
#include <furi_hal.h>
|
||||
#include <string.h>
|
||||
|
||||
static const float MORSE_CODE_VOLUMES[] = {0, .25, .5, .75, 1};
|
||||
|
||||
typedef struct {
|
||||
FuriString* words;
|
||||
uint8_t volume;
|
||||
uint32_t dit_delta;
|
||||
} MorseCodeModel;
|
||||
|
||||
typedef struct {
|
||||
MorseCodeModel* model;
|
||||
FuriMutex** model_mutex;
|
||||
|
||||
FuriMessageQueue* input_queue;
|
||||
|
||||
ViewPort* view_port;
|
||||
Gui* gui;
|
||||
|
||||
MorseCodeWorker* worker;
|
||||
} MorseCode;
|
||||
|
||||
static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
MorseCode* morse_code = ctx;
|
||||
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
// border around the edge of the screen
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
//write words
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words));
|
||||
|
||||
// volume view_port
|
||||
uint8_t vol_bar_x_pos = 124;
|
||||
uint8_t vol_bar_y_pos = 0;
|
||||
const uint8_t volume_h = (64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume;
|
||||
canvas_draw_frame(canvas, vol_bar_x_pos, vol_bar_y_pos, 4, 64);
|
||||
canvas_draw_box(canvas, vol_bar_x_pos, vol_bar_y_pos + (64 - volume_h), 4, volume_h);
|
||||
|
||||
//dit bpm
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
0,
|
||||
10,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
furi_string_get_cstr(
|
||||
furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta)));
|
||||
|
||||
//button info
|
||||
elements_button_center(canvas, "Press/Hold");
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
MorseCode* morse_code = ctx;
|
||||
furi_message_queue_put(morse_code->input_queue, input_event, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void morse_code_worker_callback(FuriString* words, void* context) {
|
||||
MorseCode* morse_code = context;
|
||||
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
morse_code->model->words = words;
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
view_port_update(morse_code->view_port);
|
||||
}
|
||||
|
||||
MorseCode* morse_code_alloc() {
|
||||
MorseCode* instance = malloc(sizeof(MorseCode));
|
||||
|
||||
instance->model = malloc(sizeof(MorseCodeModel));
|
||||
instance->model->words = furi_string_alloc_set_str("");
|
||||
instance->model->volume = 3;
|
||||
instance->model->dit_delta = 150;
|
||||
instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
|
||||
instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||
|
||||
instance->worker = morse_code_worker_alloc();
|
||||
|
||||
morse_code_worker_set_callback(instance->worker, morse_code_worker_callback, instance);
|
||||
|
||||
instance->view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(instance->view_port, render_callback, instance);
|
||||
view_port_input_callback_set(instance->view_port, input_callback, instance);
|
||||
|
||||
// Open GUI and register view_port
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void morse_code_free(MorseCode* instance) {
|
||||
gui_remove_view_port(instance->gui, instance->view_port);
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(instance->view_port);
|
||||
|
||||
morse_code_worker_free(instance->worker);
|
||||
|
||||
furi_message_queue_free(instance->input_queue);
|
||||
|
||||
furi_mutex_free(instance->model_mutex);
|
||||
|
||||
free(instance->model);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
int32_t morse_code_app() {
|
||||
MorseCode* morse_code = morse_code_alloc();
|
||||
InputEvent input;
|
||||
morse_code_worker_start(morse_code->worker);
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) ==
|
||||
FuriStatusOk) {
|
||||
furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
if(input.key == InputKeyBack && input.type == InputTypeLong) {
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
break;
|
||||
} else if(input.key == InputKeyBack && input.type == InputTypeShort) {
|
||||
morse_code_worker_reset_text(morse_code->worker);
|
||||
} else if(input.key == InputKeyOk) {
|
||||
if(input.type == InputTypePress)
|
||||
morse_code_worker_play(morse_code->worker, true);
|
||||
else if(input.type == InputTypeRelease)
|
||||
morse_code_worker_play(morse_code->worker, false);
|
||||
} else if(input.key == InputKeyUp && input.type == InputTypePress) {
|
||||
if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1)
|
||||
morse_code->model->volume++;
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
} else if(input.key == InputKeyDown && input.type == InputTypePress) {
|
||||
if(morse_code->model->volume > 0) morse_code->model->volume--;
|
||||
morse_code_worker_set_volume(
|
||||
morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
|
||||
} else if(input.key == InputKeyLeft && input.type == InputTypePress) {
|
||||
if(morse_code->model->dit_delta > 10) morse_code->model->dit_delta -= 10;
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
} else if(input.key == InputKeyRight && input.type == InputTypePress) {
|
||||
if(morse_code->model->dit_delta >= 10) morse_code->model->dit_delta += 10;
|
||||
morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
|
||||
}
|
||||
|
||||
FURI_LOG_D(
|
||||
"Input",
|
||||
"%s %s %ld",
|
||||
input_get_key_name(input.key),
|
||||
input_get_type_name(input.type),
|
||||
input.sequence);
|
||||
|
||||
furi_mutex_release(morse_code->model_mutex);
|
||||
view_port_update(morse_code->view_port);
|
||||
}
|
||||
morse_code_worker_stop(morse_code->worker);
|
||||
morse_code_free(morse_code);
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 168 B |
@@ -1,170 +0,0 @@
|
||||
#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]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
furi_string_reset(instance->buffer);
|
||||
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_string_free(instance->buffer);
|
||||
furi_string_free(instance->words);
|
||||
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_reset_text(MorseCodeWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_string_reset(instance->buffer);
|
||||
furi_string_reset(instance->words);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define FREQUENCY 261.63f
|
||||
#define SLEEP 10
|
||||
#define DOT "."
|
||||
#define LINE "-"
|
||||
#define SPACE " "
|
||||
|
||||
typedef void (*MorseCodeWorkerCallback)(FuriString* buffer, void* context);
|
||||
|
||||
typedef struct MorseCodeWorker MorseCodeWorker;
|
||||
|
||||
MorseCodeWorker* morse_code_worker_alloc();
|
||||
|
||||
void morse_code_worker_free(MorseCodeWorker* instance);
|
||||
|
||||
void morse_code_worker_set_callback(
|
||||
MorseCodeWorker* instance,
|
||||
MorseCodeWorkerCallback callback,
|
||||
void* context);
|
||||
|
||||
void morse_code_worker_start(MorseCodeWorker* instance);
|
||||
|
||||
void morse_code_worker_stop(MorseCodeWorker* instance);
|
||||
|
||||
void morse_code_worker_play(MorseCodeWorker* instance, bool play);
|
||||
|
||||
void morse_code_worker_reset_text(MorseCodeWorker* instance);
|
||||
|
||||
void morse_code_worker_set_volume(MorseCodeWorker* instance, float level);
|
||||
|
||||
void morse_code_worker_set_dit_delta(MorseCodeWorker* instance, uint32_t delta);
|
||||
Reference in New Issue
Block a user