subghz_read_raw.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #include "subghz_read_raw.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 <gui/elements.h>
  8. #include <lib/subghz/protocols/subghz_protocol_princeton.h>
  9. #include <assets_icons.h>
  10. #define SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE 100
  11. typedef enum {
  12. SubghzReadRAWStatusStart,
  13. SubghzReadRAWStatusIDLE,
  14. SubghzReadRAWStatusREC,
  15. //SubghzReadRAWStatusShowName,
  16. } SubghzReadRAWStatus;
  17. struct SubghzReadRAW {
  18. View* view;
  19. SubghzReadRAWCallback callback;
  20. void* context;
  21. };
  22. typedef struct {
  23. string_t frequency_str;
  24. string_t preset_str;
  25. string_t sample_write;
  26. uint8_t* rssi_history;
  27. bool rssi_history_end;
  28. uint8_t ind_write;
  29. SubghzReadRAWStatus satus;
  30. } SubghzReadRAWModel;
  31. void subghz_read_raw_set_callback(
  32. SubghzReadRAW* subghz_read_raw,
  33. SubghzReadRAWCallback callback,
  34. void* context) {
  35. furi_assert(subghz_read_raw);
  36. furi_assert(callback);
  37. subghz_read_raw->callback = callback;
  38. subghz_read_raw->context = context;
  39. }
  40. void subghz_read_raw_add_data_statusbar(
  41. SubghzReadRAW* instance,
  42. const char* frequency_str,
  43. const char* preset_str) {
  44. furi_assert(instance);
  45. with_view_model(
  46. instance->view, (SubghzReadRAWModel * model) {
  47. string_set(model->frequency_str, frequency_str);
  48. string_set(model->preset_str, preset_str);
  49. return true;
  50. });
  51. }
  52. void subghz_read_raw_add_data_rssi(SubghzReadRAW* instance, float rssi) {
  53. furi_assert(instance);
  54. uint8_t u_rssi = 0;
  55. if(rssi < -90) {
  56. u_rssi = 0;
  57. } else {
  58. u_rssi = (uint8_t)((rssi + 90) / 2.7);
  59. }
  60. //if(u_rssi > 34) u_rssi = 34;
  61. with_view_model(
  62. instance->view, (SubghzReadRAWModel * model) {
  63. model->rssi_history[model->ind_write++] = u_rssi;
  64. if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) {
  65. model->rssi_history_end = true;
  66. model->ind_write = 0;
  67. }
  68. return true;
  69. });
  70. }
  71. void subghz_read_raw_update_sample_write(SubghzReadRAW* instance, size_t sample) {
  72. furi_assert(instance);
  73. with_view_model(
  74. instance->view, (SubghzReadRAWModel * model) {
  75. string_printf(model->sample_write, "%d spl.", sample);
  76. return false;
  77. });
  78. }
  79. void subghz_read_raw_draw_rssi(Canvas* canvas, SubghzReadRAWModel* model) {
  80. int ind = 0;
  81. int base = 0;
  82. if(model->rssi_history_end == false) {
  83. for(int i = model->ind_write; i >= 0; i--) {
  84. canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]);
  85. }
  86. if(model->ind_write > 3) {
  87. canvas_draw_line(canvas, model->ind_write, 47, model->ind_write, 13);
  88. canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12);
  89. canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13);
  90. }
  91. } else {
  92. base = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - model->ind_write;
  93. for(int i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i >= 0; i--) {
  94. ind = i - base;
  95. if(ind < 0) ind += SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE;
  96. canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]);
  97. }
  98. canvas_draw_line(
  99. canvas, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 47, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 13);
  100. canvas_draw_line(
  101. canvas,
  102. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 2,
  103. 12,
  104. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 2,
  105. 12);
  106. canvas_draw_line(
  107. canvas,
  108. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1,
  109. 13,
  110. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1,
  111. 13);
  112. }
  113. }
  114. void subghz_read_raw_draw(Canvas* canvas, SubghzReadRAWModel* model) {
  115. canvas_set_color(canvas, ColorBlack);
  116. canvas_set_font(canvas, FontSecondary);
  117. canvas_draw_str(canvas, 5, 8, string_get_cstr(model->frequency_str));
  118. canvas_draw_str(canvas, 40, 8, string_get_cstr(model->preset_str));
  119. canvas_draw_str_aligned(
  120. canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write));
  121. canvas_draw_line(canvas, 0, 14, 115, 14);
  122. subghz_read_raw_draw_rssi(canvas, model);
  123. canvas_draw_line(canvas, 0, 48, 115, 48);
  124. canvas_draw_line(canvas, 115, 14, 115, 48);
  125. if(model->satus == SubghzReadRAWStatusIDLE) {
  126. elements_button_left(canvas, "Config");
  127. elements_button_center(canvas, "REC");
  128. elements_button_right(canvas, "More");
  129. } else if(model->satus == SubghzReadRAWStatusStart) {
  130. elements_button_left(canvas, "Config");
  131. elements_button_center(canvas, "REC");
  132. } else {
  133. elements_button_center(canvas, "Stop");
  134. }
  135. canvas_set_font_direction(canvas, 3);
  136. canvas_draw_str(canvas, 126, 40, "RSSI");
  137. canvas_set_font_direction(canvas, 0);
  138. }
  139. bool subghz_read_raw_input(InputEvent* event, void* context) {
  140. furi_assert(context);
  141. SubghzReadRAW* instance = context;
  142. if(event->key == InputKeyBack && event->type == InputTypeShort) {
  143. instance->callback(SubghzCustomEventViewReadRAWBack, instance->context);
  144. } else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
  145. with_view_model(
  146. instance->view, (SubghzReadRAWModel * model) {
  147. if(model->satus == SubghzReadRAWStatusIDLE ||
  148. model->satus == SubghzReadRAWStatusStart) {
  149. instance->callback(SubghzCustomEventViewReadRAWConfig, instance->context);
  150. }
  151. return true;
  152. });
  153. } else if(event->key == InputKeyRight && event->type == InputTypeShort) {
  154. with_view_model(
  155. instance->view, (SubghzReadRAWModel * model) {
  156. if(model->satus == SubghzReadRAWStatusIDLE) {
  157. instance->callback(SubghzCustomEventViewReadRAWMore, instance->context);
  158. }
  159. return true;
  160. });
  161. } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
  162. with_view_model(
  163. instance->view, (SubghzReadRAWModel * model) {
  164. if(model->satus == SubghzReadRAWStatusIDLE ||
  165. model->satus == SubghzReadRAWStatusStart) {
  166. instance->callback(SubghzCustomEventViewReadRAWREC, instance->context);
  167. model->satus = SubghzReadRAWStatusREC;
  168. model->ind_write = 0;
  169. model->rssi_history_end = false;
  170. } else {
  171. instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
  172. model->satus = SubghzReadRAWStatusIDLE;
  173. }
  174. return true;
  175. });
  176. }
  177. return true;
  178. }
  179. void subghz_read_raw_enter(void* context) {
  180. furi_assert(context);
  181. SubghzReadRAW* instance = context;
  182. with_view_model(
  183. instance->view, (SubghzReadRAWModel * model) {
  184. model->satus = SubghzReadRAWStatusStart;
  185. model->rssi_history = furi_alloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
  186. model->rssi_history_end = false;
  187. model->ind_write = 0;
  188. string_set(model->sample_write, "0 spl.");
  189. return true;
  190. });
  191. }
  192. void subghz_read_raw_exit(void* context) {
  193. furi_assert(context);
  194. SubghzReadRAW* instance = context;
  195. with_view_model(
  196. instance->view, (SubghzReadRAWModel * model) {
  197. if(model->satus != SubghzReadRAWStatusIDLE &&
  198. model->satus != SubghzReadRAWStatusStart) {
  199. instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
  200. model->satus = SubghzReadRAWStatusStart;
  201. }
  202. string_clean(model->frequency_str);
  203. string_clean(model->preset_str);
  204. string_clean(model->sample_write);
  205. free(model->rssi_history);
  206. return true;
  207. });
  208. }
  209. SubghzReadRAW* subghz_read_raw_alloc() {
  210. SubghzReadRAW* instance = furi_alloc(sizeof(SubghzReadRAW));
  211. // View allocation and configuration
  212. instance->view = view_alloc();
  213. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzReadRAWModel));
  214. view_set_context(instance->view, instance);
  215. view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_read_raw_draw);
  216. view_set_input_callback(instance->view, subghz_read_raw_input);
  217. view_set_enter_callback(instance->view, subghz_read_raw_enter);
  218. view_set_exit_callback(instance->view, subghz_read_raw_exit);
  219. with_view_model(
  220. instance->view, (SubghzReadRAWModel * model) {
  221. string_init(model->frequency_str);
  222. string_init(model->preset_str);
  223. string_init(model->sample_write);
  224. return true;
  225. });
  226. return instance;
  227. }
  228. void subghz_read_raw_free(SubghzReadRAW* instance) {
  229. furi_assert(instance);
  230. with_view_model(
  231. instance->view, (SubghzReadRAWModel * model) {
  232. string_clear(model->frequency_str);
  233. string_clear(model->preset_str);
  234. string_clear(model->sample_write);
  235. return true;
  236. });
  237. view_free(instance->view);
  238. free(instance);
  239. }
  240. View* subghz_read_raw_get_view(SubghzReadRAW* instance) {
  241. furi_assert(instance);
  242. return instance->view;
  243. }