subghz_read_raw.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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. struct SubghzReadRAW {
  12. View* view;
  13. SubghzReadRAWCallback callback;
  14. void* context;
  15. };
  16. typedef struct {
  17. string_t frequency_str;
  18. string_t preset_str;
  19. string_t sample_write;
  20. uint8_t* rssi_history;
  21. bool rssi_history_end;
  22. uint8_t ind_write;
  23. uint8_t ind_sin;
  24. SubghzReadRAWStatus satus;
  25. } SubghzReadRAWModel;
  26. void subghz_read_raw_set_callback(
  27. SubghzReadRAW* subghz_read_raw,
  28. SubghzReadRAWCallback callback,
  29. void* context) {
  30. furi_assert(subghz_read_raw);
  31. furi_assert(callback);
  32. subghz_read_raw->callback = callback;
  33. subghz_read_raw->context = context;
  34. }
  35. void subghz_read_raw_add_data_statusbar(
  36. SubghzReadRAW* instance,
  37. const char* frequency_str,
  38. const char* preset_str) {
  39. furi_assert(instance);
  40. with_view_model(
  41. instance->view, (SubghzReadRAWModel * model) {
  42. string_set(model->frequency_str, frequency_str);
  43. string_set(model->preset_str, preset_str);
  44. return true;
  45. });
  46. }
  47. void subghz_read_raw_add_data_rssi(SubghzReadRAW* instance, float rssi) {
  48. furi_assert(instance);
  49. uint8_t u_rssi = 0;
  50. if(rssi < -90) {
  51. u_rssi = 0;
  52. } else {
  53. u_rssi = (uint8_t)((rssi + 90) / 2.7);
  54. }
  55. //if(u_rssi > 34) u_rssi = 34;
  56. with_view_model(
  57. instance->view, (SubghzReadRAWModel * model) {
  58. model->rssi_history[model->ind_write++] = u_rssi;
  59. if(model->ind_write > SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE) {
  60. model->rssi_history_end = true;
  61. model->ind_write = 0;
  62. }
  63. return true;
  64. });
  65. }
  66. void subghz_read_raw_update_sample_write(SubghzReadRAW* instance, size_t sample) {
  67. furi_assert(instance);
  68. with_view_model(
  69. instance->view, (SubghzReadRAWModel * model) {
  70. string_printf(model->sample_write, "%d spl.", sample);
  71. return false;
  72. });
  73. }
  74. void subghz_read_raw_stop_send(SubghzReadRAW* instance) {
  75. furi_assert(instance);
  76. with_view_model(
  77. instance->view, (SubghzReadRAWModel * model) {
  78. if(model->satus == SubghzReadRAWStatusTXRepeat) {
  79. // Start TX
  80. instance->callback(SubghzCustomEventViewReadRAWSendStart, instance->context);
  81. } else {
  82. model->satus = SubghzReadRAWStatusIDLE;
  83. }
  84. return true;
  85. });
  86. }
  87. void subghz_read_raw_update_sin(SubghzReadRAW* instance) {
  88. furi_assert(instance);
  89. with_view_model(
  90. instance->view, (SubghzReadRAWModel * model) {
  91. if(model->ind_sin++ > 62) {
  92. model->ind_sin = 0;
  93. }
  94. return true;
  95. });
  96. }
  97. static int8_t subghz_read_raw_tab_sin(uint8_t x) {
  98. const uint8_t tab_sin[64] = {0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37,
  99. 40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 73,
  100. 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102,
  101. 104, 106, 107, 109, 111, 112, 113, 115, 116, 117, 118, 120, 121,
  102. 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127};
  103. int8_t r = tab_sin[((x & 0x40) ? -x - 1 : x) & 0x3f];
  104. if(x & 0x80) return -r;
  105. return r;
  106. }
  107. void subghz_read_raw_draw_sin(Canvas* canvas, SubghzReadRAWModel* model) {
  108. #define SUBGHZ_RAW_SIN_AMPLITUDE 11
  109. for(int i = 113; i > 0; i--) {
  110. canvas_draw_line(
  111. canvas,
  112. i,
  113. 32 - subghz_read_raw_tab_sin(i + model->ind_sin * 16) / SUBGHZ_RAW_SIN_AMPLITUDE,
  114. i + 1,
  115. 32 + subghz_read_raw_tab_sin((i + model->ind_sin * 16 + 1) * 2) /
  116. SUBGHZ_RAW_SIN_AMPLITUDE);
  117. canvas_draw_line(
  118. canvas,
  119. i + 1,
  120. 32 - subghz_read_raw_tab_sin((i + model->ind_sin * 16)) / SUBGHZ_RAW_SIN_AMPLITUDE,
  121. i + 2,
  122. 32 + subghz_read_raw_tab_sin((i + model->ind_sin * 16 + 1) * 2) /
  123. SUBGHZ_RAW_SIN_AMPLITUDE);
  124. }
  125. }
  126. void subghz_read_raw_draw_scale(Canvas* canvas, SubghzReadRAWModel* model) {
  127. #define SUBGHZ_RAW_TOP_SCALE 14
  128. #define SUBGHZ_RAW_END_SCALE 115
  129. if(model->rssi_history_end == false) {
  130. for(int i = SUBGHZ_RAW_END_SCALE; i > 0; i -= 15) {
  131. canvas_draw_line(canvas, i, SUBGHZ_RAW_TOP_SCALE, i, SUBGHZ_RAW_TOP_SCALE + 4);
  132. canvas_draw_line(canvas, i - 5, SUBGHZ_RAW_TOP_SCALE, i - 5, SUBGHZ_RAW_TOP_SCALE + 2);
  133. canvas_draw_line(
  134. canvas, i - 10, SUBGHZ_RAW_TOP_SCALE, i - 10, SUBGHZ_RAW_TOP_SCALE + 2);
  135. }
  136. } else {
  137. for(int i = SUBGHZ_RAW_END_SCALE - model->ind_write % 15; i > -15; i -= 15) {
  138. canvas_draw_line(canvas, i, SUBGHZ_RAW_TOP_SCALE, i, SUBGHZ_RAW_TOP_SCALE + 4);
  139. if(SUBGHZ_RAW_END_SCALE > i + 5)
  140. canvas_draw_line(
  141. canvas, i + 5, SUBGHZ_RAW_TOP_SCALE, i + 5, SUBGHZ_RAW_TOP_SCALE + 2);
  142. if(SUBGHZ_RAW_END_SCALE > i + 10)
  143. canvas_draw_line(
  144. canvas, i + 10, SUBGHZ_RAW_TOP_SCALE, i + 10, SUBGHZ_RAW_TOP_SCALE + 2);
  145. }
  146. }
  147. }
  148. void subghz_read_raw_draw_rssi(Canvas* canvas, SubghzReadRAWModel* model) {
  149. int ind = 0;
  150. int base = 0;
  151. if(model->rssi_history_end == false) {
  152. for(int i = model->ind_write; i >= 0; i--) {
  153. canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]);
  154. }
  155. if(model->ind_write > 3) {
  156. canvas_draw_line(canvas, model->ind_write, 47, model->ind_write, 13);
  157. canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12);
  158. canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13);
  159. }
  160. } else {
  161. base = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - model->ind_write;
  162. for(int i = SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE; i >= 0; i--) {
  163. ind = i - base;
  164. if(ind < 0) ind += SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE;
  165. canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]);
  166. }
  167. canvas_draw_line(
  168. canvas, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 47, SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE, 13);
  169. canvas_draw_line(
  170. canvas,
  171. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 2,
  172. 12,
  173. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 2,
  174. 12);
  175. canvas_draw_line(
  176. canvas,
  177. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE - 1,
  178. 13,
  179. SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE + 1,
  180. 13);
  181. }
  182. }
  183. void subghz_read_raw_draw(Canvas* canvas, SubghzReadRAWModel* model) {
  184. canvas_set_color(canvas, ColorBlack);
  185. canvas_set_font(canvas, FontSecondary);
  186. canvas_draw_str(canvas, 5, 8, string_get_cstr(model->frequency_str));
  187. canvas_draw_str(canvas, 40, 8, string_get_cstr(model->preset_str));
  188. canvas_draw_str_aligned(
  189. canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write));
  190. canvas_draw_line(canvas, 0, 14, 115, 14);
  191. canvas_draw_line(canvas, 0, 48, 115, 48);
  192. canvas_draw_line(canvas, 115, 14, 115, 48);
  193. if((model->satus == SubghzReadRAWStatusTX) || (model->satus == SubghzReadRAWStatusTXRepeat)) {
  194. subghz_read_raw_draw_sin(canvas, model);
  195. } else {
  196. subghz_read_raw_draw_rssi(canvas, model);
  197. subghz_read_raw_draw_scale(canvas, model);
  198. }
  199. if(model->satus == SubghzReadRAWStatusIDLE) {
  200. elements_button_left(canvas, "Erase");
  201. elements_button_center(canvas, "Send");
  202. elements_button_right(canvas, "Save");
  203. } else if(model->satus == SubghzReadRAWStatusStart) {
  204. elements_button_left(canvas, "Config");
  205. elements_button_center(canvas, "REC");
  206. } else if(
  207. (model->satus == SubghzReadRAWStatusTX) || (model->satus == SubghzReadRAWStatusTXRepeat)) {
  208. elements_button_center(canvas, "Send");
  209. } else {
  210. elements_button_center(canvas, "Stop");
  211. }
  212. canvas_set_font_direction(canvas, 3);
  213. canvas_draw_str(canvas, 126, 40, "RSSI");
  214. canvas_set_font_direction(canvas, 0);
  215. }
  216. bool subghz_read_raw_input(InputEvent* event, void* context) {
  217. furi_assert(context);
  218. SubghzReadRAW* instance = context;
  219. if((event->key == InputKeyOk) &&
  220. (event->type == InputTypeLong || event->type == InputTypeRepeat)) {
  221. //we check that if we hold the transfer button,
  222. //further check of events is not needed, we exit
  223. return false;
  224. } else if(event->key == InputKeyOk && event->type == InputTypePress) {
  225. with_view_model(
  226. instance->view, (SubghzReadRAWModel * model) {
  227. uint8_t ret = false;
  228. if(model->satus == SubghzReadRAWStatusIDLE) {
  229. // Start TX
  230. instance->callback(SubghzCustomEventViewReadRAWSendStart, instance->context);
  231. instance->callback(SubghzCustomEventViewReadRAWVibro, instance->context);
  232. model->satus = SubghzReadRAWStatusTXRepeat;
  233. ret = true;
  234. } else if(model->satus == SubghzReadRAWStatusTX) {
  235. model->satus = SubghzReadRAWStatusTXRepeat;
  236. }
  237. return ret;
  238. });
  239. } else if(event->key == InputKeyOk && event->type == InputTypeRelease) {
  240. with_view_model(
  241. instance->view, (SubghzReadRAWModel * model) {
  242. if(model->satus == SubghzReadRAWStatusTXRepeat) {
  243. // Stop repeat TX
  244. model->satus = SubghzReadRAWStatusTX;
  245. }
  246. return false;
  247. });
  248. } else if(event->key == InputKeyBack && event->type == InputTypeShort) {
  249. with_view_model(
  250. instance->view, (SubghzReadRAWModel * model) {
  251. if(model->satus == SubghzReadRAWStatusREC) {
  252. //Stop REC
  253. instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
  254. model->satus = SubghzReadRAWStatusIDLE;
  255. } else {
  256. //Exit
  257. instance->callback(SubghzCustomEventViewReadRAWBack, instance->context);
  258. }
  259. return true;
  260. });
  261. } else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
  262. with_view_model(
  263. instance->view, (SubghzReadRAWModel * model) {
  264. if(model->satus == SubghzReadRAWStatusStart) {
  265. //Config
  266. instance->callback(SubghzCustomEventViewReadRAWConfig, instance->context);
  267. } else if(model->satus == SubghzReadRAWStatusIDLE) {
  268. //Erase
  269. model->satus = SubghzReadRAWStatusStart;
  270. model->rssi_history_end = false;
  271. model->ind_write = 0;
  272. string_set(model->sample_write, "0 spl.");
  273. instance->callback(SubghzCustomEventViewReadRAWErase, instance->context);
  274. }
  275. return true;
  276. });
  277. } else if(event->key == InputKeyRight && event->type == InputTypeShort) {
  278. with_view_model(
  279. instance->view, (SubghzReadRAWModel * model) {
  280. //Save
  281. if(model->satus == SubghzReadRAWStatusIDLE) {
  282. instance->callback(SubghzCustomEventViewReadRAWSave, instance->context);
  283. }
  284. return true;
  285. });
  286. } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
  287. with_view_model(
  288. instance->view, (SubghzReadRAWModel * model) {
  289. if(model->satus == SubghzReadRAWStatusStart) {
  290. //Record
  291. instance->callback(SubghzCustomEventViewReadRAWREC, instance->context);
  292. model->satus = SubghzReadRAWStatusREC;
  293. model->ind_write = 0;
  294. model->rssi_history_end = false;
  295. } else if(
  296. (model->satus != SubghzReadRAWStatusTX) &&
  297. (model->satus != SubghzReadRAWStatusTXRepeat)) {
  298. //Stop
  299. instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
  300. model->satus = SubghzReadRAWStatusIDLE;
  301. }
  302. return true;
  303. });
  304. }
  305. return true;
  306. }
  307. void subghz_read_raw_set_status(SubghzReadRAW* instance, SubghzReadRAWStatus satus) {
  308. furi_assert(instance);
  309. if(satus == SubghzReadRAWStatusStart) {
  310. with_view_model(
  311. instance->view, (SubghzReadRAWModel * model) {
  312. model->satus = SubghzReadRAWStatusStart;
  313. model->rssi_history_end = false;
  314. model->ind_write = 0;
  315. string_set(model->sample_write, "0 spl.");
  316. return true;
  317. });
  318. } else if(satus == SubghzReadRAWStatusIDLE) {
  319. with_view_model(
  320. instance->view, (SubghzReadRAWModel * model) {
  321. model->satus = SubghzReadRAWStatusIDLE;
  322. return true;
  323. });
  324. }
  325. }
  326. void subghz_read_raw_enter(void* context) {
  327. furi_assert(context);
  328. //SubghzReadRAW* instance = context;
  329. }
  330. void subghz_read_raw_exit(void* context) {
  331. furi_assert(context);
  332. SubghzReadRAW* instance = context;
  333. with_view_model(
  334. instance->view, (SubghzReadRAWModel * model) {
  335. if(model->satus != SubghzReadRAWStatusIDLE &&
  336. model->satus != SubghzReadRAWStatusStart) {
  337. instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
  338. model->satus = SubghzReadRAWStatusStart;
  339. }
  340. return true;
  341. });
  342. }
  343. SubghzReadRAW* subghz_read_raw_alloc() {
  344. SubghzReadRAW* instance = furi_alloc(sizeof(SubghzReadRAW));
  345. // View allocation and configuration
  346. instance->view = view_alloc();
  347. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzReadRAWModel));
  348. view_set_context(instance->view, instance);
  349. view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_read_raw_draw);
  350. view_set_input_callback(instance->view, subghz_read_raw_input);
  351. view_set_enter_callback(instance->view, subghz_read_raw_enter);
  352. view_set_exit_callback(instance->view, subghz_read_raw_exit);
  353. with_view_model(
  354. instance->view, (SubghzReadRAWModel * model) {
  355. string_init(model->frequency_str);
  356. string_init(model->preset_str);
  357. string_init(model->sample_write);
  358. model->rssi_history = furi_alloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
  359. return true;
  360. });
  361. return instance;
  362. }
  363. void subghz_read_raw_free(SubghzReadRAW* instance) {
  364. furi_assert(instance);
  365. with_view_model(
  366. instance->view, (SubghzReadRAWModel * model) {
  367. string_clear(model->frequency_str);
  368. string_clear(model->preset_str);
  369. string_clear(model->sample_write);
  370. free(model->rssi_history);
  371. return true;
  372. });
  373. view_free(instance->view);
  374. free(instance);
  375. }
  376. View* subghz_read_raw_get_view(SubghzReadRAW* instance) {
  377. furi_assert(instance);
  378. return instance->view;
  379. }