subghz_frequency_analyzer.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. } SubGhzFrequencyAnalyzerModel;
  24. void subghz_frequency_analyzer_set_callback(
  25. SubGhzFrequencyAnalyzer* subghz_frequency_analyzer,
  26. SubGhzFrequencyAnalyzerCallback callback,
  27. void* context) {
  28. furi_assert(subghz_frequency_analyzer);
  29. furi_assert(callback);
  30. subghz_frequency_analyzer->callback = callback;
  31. subghz_frequency_analyzer->context = context;
  32. }
  33. void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, float rssi) {
  34. uint8_t x = 48;
  35. uint8_t y = 56;
  36. uint8_t column_number = 0;
  37. if(rssi) {
  38. rssi = (rssi + 90) / 3;
  39. for(size_t i = 1; i < (uint8_t)rssi; i++) {
  40. if(i > 20) break;
  41. if(i % 4) {
  42. column_number++;
  43. canvas_draw_box(canvas, x + 2 * i, y - column_number, 2, 4 + column_number);
  44. }
  45. }
  46. }
  47. }
  48. void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel* model) {
  49. char buffer[64];
  50. canvas_set_color(canvas, ColorBlack);
  51. canvas_set_font(canvas, FontSecondary);
  52. canvas_draw_str(canvas, 20, 8, "Frequency Analyzer");
  53. canvas_draw_str(canvas, 28, 60, "RSSI");
  54. subghz_frequency_analyzer_draw_rssi(canvas, model->rssi);
  55. //Frequency
  56. canvas_set_font(canvas, FontBigNumbers);
  57. snprintf(
  58. buffer,
  59. sizeof(buffer),
  60. "%03ld.%03ld",
  61. model->frequency / 1000000 % 1000,
  62. model->frequency / 1000 % 1000);
  63. canvas_draw_str(canvas, 8, 35, buffer);
  64. canvas_draw_icon(canvas, 96, 24, &I_MHz_25x11);
  65. }
  66. bool subghz_frequency_analyzer_input(InputEvent* event, void* context) {
  67. furi_assert(context);
  68. if(event->key == InputKeyBack) {
  69. return false;
  70. }
  71. return true;
  72. }
  73. void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency, float rssi) {
  74. SubGhzFrequencyAnalyzer* instance = context;
  75. if((rssi == 0.f) && (instance->locked)) {
  76. if(instance->callback) {
  77. instance->callback(SubGhzCustomEventSceneAnalyzerUnlock, instance->context);
  78. }
  79. } else if((rssi != 0.f) && (!instance->locked)) {
  80. if(instance->callback) {
  81. instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context);
  82. }
  83. }
  84. instance->locked = (rssi != 0.f);
  85. with_view_model(
  86. instance->view, (SubGhzFrequencyAnalyzerModel * model) {
  87. model->rssi = rssi;
  88. model->frequency = frequency;
  89. return true;
  90. });
  91. }
  92. void subghz_frequency_analyzer_enter(void* context) {
  93. furi_assert(context);
  94. SubGhzFrequencyAnalyzer* instance = context;
  95. //Start worker
  96. instance->worker = subghz_frequency_analyzer_worker_alloc(instance->context);
  97. subghz_frequency_analyzer_worker_set_pair_callback(
  98. instance->worker,
  99. (SubGhzFrequencyAnalyzerWorkerPairCallback)subghz_frequency_analyzer_pair_callback,
  100. instance);
  101. subghz_frequency_analyzer_worker_start(instance->worker);
  102. with_view_model(
  103. instance->view, (SubGhzFrequencyAnalyzerModel * model) {
  104. model->rssi = 0;
  105. model->frequency = 0;
  106. return true;
  107. });
  108. }
  109. void subghz_frequency_analyzer_exit(void* context) {
  110. furi_assert(context);
  111. SubGhzFrequencyAnalyzer* instance = context;
  112. //Stop worker
  113. if(subghz_frequency_analyzer_worker_is_running(instance->worker)) {
  114. subghz_frequency_analyzer_worker_stop(instance->worker);
  115. }
  116. subghz_frequency_analyzer_worker_free(instance->worker);
  117. with_view_model(
  118. instance->view, (SubGhzFrequencyAnalyzerModel * model) {
  119. model->rssi = 0;
  120. return true;
  121. });
  122. }
  123. SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
  124. SubGhzFrequencyAnalyzer* instance = malloc(sizeof(SubGhzFrequencyAnalyzer));
  125. // View allocation and configuration
  126. instance->view = view_alloc();
  127. view_allocate_model(
  128. instance->view, ViewModelTypeLocking, sizeof(SubGhzFrequencyAnalyzerModel));
  129. view_set_context(instance->view, instance);
  130. view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_frequency_analyzer_draw);
  131. view_set_input_callback(instance->view, subghz_frequency_analyzer_input);
  132. view_set_enter_callback(instance->view, subghz_frequency_analyzer_enter);
  133. view_set_exit_callback(instance->view, subghz_frequency_analyzer_exit);
  134. with_view_model(
  135. instance->view, (SubGhzFrequencyAnalyzerModel * model) {
  136. model->rssi = 0;
  137. return true;
  138. });
  139. return instance;
  140. }
  141. void subghz_frequency_analyzer_free(SubGhzFrequencyAnalyzer* instance) {
  142. furi_assert(instance);
  143. view_free(instance->view);
  144. free(instance);
  145. }
  146. View* subghz_frequency_analyzer_get_view(SubGhzFrequencyAnalyzer* instance) {
  147. furi_assert(instance);
  148. return instance->view;
  149. }