subghz_frequency_analyzer.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "subghz_frequency_analyzer.h"
  2. #include "../subghz_i.h"
  3. #include <math.h>
  4. #include <furi.h>
  5. #include <furi_hal.h>
  6. #include <input/input.h>
  7. #include <notification/notification_messages.h>
  8. #include "../helpers/subghz_frequency_analyzer_worker.h"
  9. #include <assets_icons.h>
  10. typedef enum {
  11. SubGhzFrequencyAnalyzerStatusIDLE,
  12. } SubGhzFrequencyAnalyzerStatus;
  13. struct SubGhzFrequencyAnalyzer {
  14. View* view;
  15. SubGhzFrequencyAnalyzerWorker* worker;
  16. SubGhzFrequencyAnalyzerCallback callback;
  17. void* context;
  18. bool locked;
  19. };
  20. typedef struct {
  21. uint32_t frequency;
  22. float rssi;
  23. uint32_t history_frequency[3];
  24. bool signal;
  25. } SubGhzFrequencyAnalyzerModel;
  26. void subghz_frequency_analyzer_set_callback(
  27. SubGhzFrequencyAnalyzer* subghz_frequency_analyzer,
  28. SubGhzFrequencyAnalyzerCallback callback,
  29. void* context) {
  30. furi_assert(subghz_frequency_analyzer);
  31. furi_assert(callback);
  32. subghz_frequency_analyzer->callback = callback;
  33. subghz_frequency_analyzer->context = context;
  34. }
  35. void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, float rssi) {
  36. uint8_t x = 20;
  37. uint8_t y = 64;
  38. uint8_t column_number = 0;
  39. if(rssi) {
  40. rssi = (rssi + 90) / 3;
  41. for(size_t i = 1; i < (uint8_t)rssi; i++) {
  42. if(i > 20) break;
  43. if(i % 4) {
  44. column_number++;
  45. canvas_draw_box(canvas, x + 2 * i, y - column_number, 2, 4 + column_number);
  46. }
  47. }
  48. }
  49. }
  50. static void subghz_frequency_analyzer_history_frequency_draw(
  51. Canvas* canvas,
  52. SubGhzFrequencyAnalyzerModel* model) {
  53. char buffer[64];
  54. uint8_t x = 66;
  55. uint8_t y = 43;
  56. canvas_set_font(canvas, FontKeyboard);
  57. for(uint8_t i = 0; i < 3; i++) {
  58. if(model->history_frequency[i]) {
  59. snprintf(
  60. buffer,
  61. sizeof(buffer),
  62. "%03ld.%03ld",
  63. model->history_frequency[i] / 1000000 % 1000,
  64. model->history_frequency[i] / 1000 % 1000);
  65. canvas_draw_str(canvas, x, y + i * 10, buffer);
  66. } else {
  67. canvas_draw_str(canvas, x, y + i * 10, "---.---");
  68. }
  69. canvas_draw_str(canvas, x + 44, y + i * 10, "MHz");
  70. }
  71. canvas_set_font(canvas, FontSecondary);
  72. }
  73. void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel* model) {
  74. char buffer[64];
  75. canvas_set_color(canvas, ColorBlack);
  76. canvas_set_font(canvas, FontSecondary);
  77. canvas_draw_str(canvas, 20, 8, "Frequency Analyzer");
  78. canvas_draw_str(canvas, 0, 64, "RSSI");
  79. subghz_frequency_analyzer_draw_rssi(canvas, model->rssi);
  80. subghz_frequency_analyzer_history_frequency_draw(canvas, model);
  81. //Frequency
  82. canvas_set_font(canvas, FontBigNumbers);
  83. snprintf(
  84. buffer,
  85. sizeof(buffer),
  86. "%03ld.%03ld",
  87. model->frequency / 1000000 % 1000,
  88. model->frequency / 1000 % 1000);
  89. if(model->signal) {
  90. canvas_draw_box(canvas, 4, 12, 121, 22);
  91. canvas_set_color(canvas, ColorWhite);
  92. } else {
  93. }
  94. canvas_draw_str(canvas, 8, 30, buffer);
  95. canvas_draw_icon(canvas, 96, 19, &I_MHz_25x11);
  96. }
  97. bool subghz_frequency_analyzer_input(InputEvent* event, void* context) {
  98. furi_assert(context);
  99. if(event->key == InputKeyBack) {
  100. return false;
  101. }
  102. return true;
  103. }
  104. void subghz_frequency_analyzer_pair_callback(
  105. void* context,
  106. uint32_t frequency,
  107. float rssi,
  108. bool signal) {
  109. SubGhzFrequencyAnalyzer* instance = context;
  110. if((rssi == 0.f) && (instance->locked)) {
  111. if(instance->callback) {
  112. instance->callback(SubGhzCustomEventSceneAnalyzerUnlock, instance->context);
  113. }
  114. //update history
  115. with_view_model(
  116. instance->view,
  117. SubGhzFrequencyAnalyzerModel * model,
  118. {
  119. model->history_frequency[2] = model->history_frequency[1];
  120. model->history_frequency[1] = model->history_frequency[0];
  121. model->history_frequency[0] = model->frequency;
  122. },
  123. false);
  124. } else if((rssi != 0.f) && (!instance->locked)) {
  125. if(instance->callback) {
  126. instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context);
  127. }
  128. }
  129. instance->locked = (rssi != 0.f);
  130. with_view_model(
  131. instance->view,
  132. SubGhzFrequencyAnalyzerModel * model,
  133. {
  134. model->rssi = rssi;
  135. model->frequency = frequency;
  136. model->signal = signal;
  137. },
  138. true);
  139. }
  140. void subghz_frequency_analyzer_enter(void* context) {
  141. furi_assert(context);
  142. SubGhzFrequencyAnalyzer* instance = context;
  143. //Start worker
  144. instance->worker = subghz_frequency_analyzer_worker_alloc(instance->context);
  145. subghz_frequency_analyzer_worker_set_pair_callback(
  146. instance->worker,
  147. (SubGhzFrequencyAnalyzerWorkerPairCallback)subghz_frequency_analyzer_pair_callback,
  148. instance);
  149. subghz_frequency_analyzer_worker_start(instance->worker);
  150. with_view_model(
  151. instance->view,
  152. SubGhzFrequencyAnalyzerModel * model,
  153. {
  154. model->rssi = 0;
  155. model->frequency = 0;
  156. model->history_frequency[2] = 0;
  157. model->history_frequency[1] = 0;
  158. model->history_frequency[0] = 0;
  159. },
  160. true);
  161. }
  162. void subghz_frequency_analyzer_exit(void* context) {
  163. furi_assert(context);
  164. SubGhzFrequencyAnalyzer* instance = context;
  165. //Stop worker
  166. if(subghz_frequency_analyzer_worker_is_running(instance->worker)) {
  167. subghz_frequency_analyzer_worker_stop(instance->worker);
  168. }
  169. subghz_frequency_analyzer_worker_free(instance->worker);
  170. with_view_model(
  171. instance->view, SubGhzFrequencyAnalyzerModel * model, { model->rssi = 0; }, true);
  172. }
  173. SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
  174. SubGhzFrequencyAnalyzer* instance = malloc(sizeof(SubGhzFrequencyAnalyzer));
  175. // View allocation and configuration
  176. instance->view = view_alloc();
  177. view_allocate_model(
  178. instance->view, ViewModelTypeLocking, sizeof(SubGhzFrequencyAnalyzerModel));
  179. view_set_context(instance->view, instance);
  180. view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_frequency_analyzer_draw);
  181. view_set_input_callback(instance->view, subghz_frequency_analyzer_input);
  182. view_set_enter_callback(instance->view, subghz_frequency_analyzer_enter);
  183. view_set_exit_callback(instance->view, subghz_frequency_analyzer_exit);
  184. with_view_model(
  185. instance->view, SubGhzFrequencyAnalyzerModel * model, { model->rssi = 0; }, true);
  186. return instance;
  187. }
  188. void subghz_frequency_analyzer_free(SubGhzFrequencyAnalyzer* instance) {
  189. furi_assert(instance);
  190. view_free(instance->view);
  191. free(instance);
  192. }
  193. View* subghz_frequency_analyzer_get_view(SubGhzFrequencyAnalyzer* instance) {
  194. furi_assert(instance);
  195. return instance->view;
  196. }