morse_code.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include "morse_code_worker.h"
  2. #include <furi.h>
  3. #include <gui/gui.h>
  4. #include <gui/elements.h>
  5. #include <input/input.h>
  6. #include <stdlib.h>
  7. #include <furi_hal.h>
  8. #include <string.h>
  9. static const float MORSE_CODE_VOLUMES[] = {0, .25, .5, .75, 1};
  10. typedef struct {
  11. FuriString* words;
  12. uint8_t volume;
  13. uint32_t dit_delta;
  14. } MorseCodeModel;
  15. typedef struct {
  16. MorseCodeModel* model;
  17. FuriMutex** model_mutex;
  18. FuriMessageQueue* input_queue;
  19. ViewPort* view_port;
  20. Gui* gui;
  21. MorseCodeWorker* worker;
  22. } MorseCode;
  23. static void render_callback(Canvas* const canvas, void* ctx) {
  24. MorseCode* morse_code = ctx;
  25. furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
  26. // border around the edge of the screen
  27. canvas_set_font(canvas, FontPrimary);
  28. //write words
  29. elements_multiline_text_aligned(canvas, 64, 30, AlignCenter, AlignCenter, furi_string_get_cstr(morse_code->model->words));
  30. // volume view_port
  31. uint8_t vol_bar_x_pos = 124;
  32. uint8_t vol_bar_y_pos = 0;
  33. const uint8_t volume_h =
  34. (64 / (COUNT_OF(MORSE_CODE_VOLUMES) - 1)) * morse_code->model->volume;
  35. canvas_draw_frame(canvas, vol_bar_x_pos, vol_bar_y_pos, 4, 64);
  36. canvas_draw_box(canvas, vol_bar_x_pos, vol_bar_y_pos + (64 - volume_h), 4, volume_h);
  37. //dit bpm
  38. canvas_draw_str_aligned(
  39. canvas, 0, 10, AlignLeft, AlignCenter, furi_string_get_cstr(furi_string_alloc_printf("Dit: %ld ms", morse_code->model->dit_delta)));
  40. //button info
  41. elements_button_center(canvas, "Press/Hold");
  42. furi_mutex_release(morse_code->model_mutex);
  43. }
  44. static void input_callback(InputEvent* input_event, void* ctx) {
  45. MorseCode* morse_code = ctx;
  46. furi_message_queue_put(morse_code->input_queue, input_event, FuriWaitForever);
  47. }
  48. static void morse_code_worker_callback(
  49. FuriString* words,
  50. void* context) {
  51. MorseCode* morse_code = context;
  52. furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
  53. morse_code->model->words = words;
  54. furi_mutex_release(morse_code->model_mutex);
  55. view_port_update(morse_code->view_port);
  56. }
  57. MorseCode* morse_code_alloc() {
  58. MorseCode* instance = malloc(sizeof(MorseCode));
  59. instance->model = malloc(sizeof(MorseCodeModel));
  60. instance->model->words = furi_string_alloc_set_str("");
  61. instance->model->volume = 3;
  62. instance->model->dit_delta = 150;
  63. instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  64. instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  65. instance->worker = morse_code_worker_alloc();
  66. morse_code_worker_set_callback(instance->worker, morse_code_worker_callback, instance);
  67. instance->view_port = view_port_alloc();
  68. view_port_draw_callback_set(instance->view_port, render_callback, instance);
  69. view_port_input_callback_set(instance->view_port, input_callback, instance);
  70. // Open GUI and register view_port
  71. instance->gui = furi_record_open(RECORD_GUI);
  72. gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
  73. return instance;
  74. }
  75. void morse_code_free(MorseCode* instance) {
  76. gui_remove_view_port(instance->gui, instance->view_port);
  77. furi_record_close(RECORD_GUI);
  78. view_port_free(instance->view_port);
  79. morse_code_worker_free(instance->worker);
  80. furi_message_queue_free(instance->input_queue);
  81. furi_mutex_free(instance->model_mutex);
  82. free(instance->model);
  83. free(instance);
  84. }
  85. int32_t morse_code_app() {
  86. MorseCode* morse_code = morse_code_alloc();
  87. InputEvent input;
  88. morse_code_worker_start(morse_code->worker);
  89. morse_code_worker_set_volume(
  90. morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
  91. morse_code_worker_set_dit_delta(morse_code->worker, morse_code->model->dit_delta);
  92. while(furi_message_queue_get(morse_code->input_queue, &input, FuriWaitForever) == FuriStatusOk){
  93. furi_check(furi_mutex_acquire(morse_code->model_mutex, FuriWaitForever) == FuriStatusOk);
  94. if(input.key == InputKeyBack) {
  95. furi_mutex_release(morse_code->model_mutex);
  96. break;
  97. }else if(input.key == InputKeyOk){
  98. if(input.type == InputTypePress)
  99. morse_code_worker_play(morse_code->worker, true);
  100. else if(input.type == InputTypeRelease)
  101. morse_code_worker_play(morse_code->worker, false);
  102. }else if(input.key == InputKeyUp && input.type == InputTypePress){
  103. if(morse_code->model->volume < COUNT_OF(MORSE_CODE_VOLUMES) - 1)
  104. morse_code->model->volume++;
  105. morse_code_worker_set_volume(
  106. morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
  107. }else if(input.key == InputKeyDown && input.type == InputTypePress){
  108. if(morse_code->model->volume > 0)
  109. morse_code->model->volume--;
  110. morse_code_worker_set_volume(
  111. morse_code->worker, MORSE_CODE_VOLUMES[morse_code->model->volume]);
  112. }else if(input.key == InputKeyLeft && input.type == InputTypePress){
  113. if(morse_code->model->dit_delta > 10)
  114. morse_code->model->dit_delta-=10;
  115. morse_code_worker_set_dit_delta(
  116. morse_code->worker, morse_code->model->dit_delta);
  117. }
  118. else if(input.key == InputKeyRight && input.type == InputTypePress){
  119. if(morse_code->model->dit_delta >= 10)
  120. morse_code->model->dit_delta+=10;
  121. morse_code_worker_set_dit_delta(
  122. morse_code->worker, morse_code->model->dit_delta);
  123. }
  124. FURI_LOG_D("Input", "%s %s %ld", input_get_key_name(input.key), input_get_type_name(input.type), input.sequence);
  125. furi_mutex_release(morse_code->model_mutex);
  126. view_port_update(morse_code->view_port);
  127. }
  128. morse_code_worker_stop(morse_code->worker);
  129. morse_code_free(morse_code);
  130. return 0;
  131. }