subghz_i.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "subghz_i.h"
  2. #include <math.h>
  3. #include <furi.h>
  4. #include <furi-hal.h>
  5. #include <input/input.h>
  6. #include <gui/elements.h>
  7. #include <notification/notification-messages.h>
  8. #include "file-worker.h"
  9. #include "../notification/notification.h"
  10. #include "views/subghz_receiver.h"
  11. void subghz_begin(FuriHalSubGhzPreset preset) {
  12. furi_hal_subghz_reset();
  13. furi_hal_subghz_idle();
  14. furi_hal_subghz_load_preset(preset);
  15. hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
  16. }
  17. uint32_t subghz_rx(void* context, uint32_t frequency) {
  18. furi_assert(context);
  19. SubGhzWorker* worker = context;
  20. furi_hal_subghz_idle();
  21. uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
  22. hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
  23. furi_hal_subghz_flush_rx();
  24. furi_hal_subghz_rx();
  25. furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, worker);
  26. subghz_worker_start(worker);
  27. return value;
  28. }
  29. uint32_t subghz_tx(uint32_t frequency) {
  30. furi_hal_subghz_idle();
  31. uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
  32. hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  33. hal_gpio_write(&gpio_cc1101_g0, true);
  34. furi_hal_subghz_tx();
  35. return value;
  36. }
  37. void subghz_idle(void) {
  38. furi_hal_subghz_idle();
  39. }
  40. void subghz_rx_end(void* context) {
  41. furi_assert(context);
  42. SubGhzWorker* worker = context;
  43. if(subghz_worker_is_running(worker)) {
  44. subghz_worker_stop(worker);
  45. furi_hal_subghz_stop_async_rx();
  46. }
  47. }
  48. void subghz_sleep(void) {
  49. furi_hal_subghz_sleep();
  50. }
  51. void subghz_frequency_preset_to_str(void* context, string_t output) {
  52. furi_assert(context);
  53. SubGhz* subghz = context;
  54. string_cat_printf(
  55. output,
  56. "Frequency: %d\n"
  57. "Preset: %d\n",
  58. (int)subghz->frequency,
  59. (int)subghz->preset);
  60. }
  61. void subghz_transmitter_tx_start(void* context) {
  62. SubGhz* subghz = context;
  63. subghz->encoder = subghz_protocol_encoder_common_alloc();
  64. subghz->encoder->repeat = 200; //max repeat with the button held down
  65. //get upload
  66. if(subghz->protocol_result->get_upload_protocol) {
  67. if(subghz->protocol_result->get_upload_protocol(subghz->protocol_result, subghz->encoder)) {
  68. if(subghz->preset) {
  69. subghz_begin(subghz->preset);
  70. } else {
  71. subghz_begin(FuriHalSubGhzPresetOok650Async);
  72. }
  73. if(subghz->frequency) {
  74. subghz_tx(subghz->frequency);
  75. } else {
  76. subghz_tx(433920000);
  77. }
  78. //Start TX
  79. furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, subghz->encoder);
  80. }
  81. }
  82. }
  83. void subghz_transmitter_tx_stop(void* context) {
  84. SubGhz* subghz = context;
  85. //Stop TX
  86. furi_hal_subghz_stop_async_tx();
  87. subghz_protocol_encoder_common_free(subghz->encoder);
  88. //if protocol dynamic then we save the last upload
  89. if(subghz->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) {
  90. subghz_save_protocol_to_file(subghz, subghz->text_store);
  91. }
  92. notification_message(subghz->notifications, &sequence_reset_red);
  93. }
  94. bool subghz_key_load(SubGhz* subghz, const char* file_path) {
  95. furi_assert(subghz);
  96. furi_assert(file_path);
  97. FileWorker* file_worker = file_worker_alloc(false);
  98. // Load device data
  99. bool loaded = false;
  100. string_t path;
  101. string_init_set_str(path, file_path);
  102. string_t temp_str;
  103. string_init(temp_str);
  104. int res = 0;
  105. int data = 0;
  106. do {
  107. if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
  108. break;
  109. }
  110. // Read and parse frequency from 1st line
  111. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  112. break;
  113. }
  114. res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data);
  115. if(res != 1) {
  116. break;
  117. }
  118. subghz->frequency = (uint32_t)data;
  119. // Read and parse preset from 2st line
  120. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  121. break;
  122. }
  123. res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data);
  124. if(res != 1) {
  125. break;
  126. }
  127. subghz->preset = (FuriHalSubGhzPreset)data;
  128. // Read and parse name protocol from 2st line
  129. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  130. break;
  131. }
  132. // strlen("Protocol: ") = 10
  133. string_right(temp_str, 10);
  134. subghz->protocol_result =
  135. subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str));
  136. if(subghz->protocol_result == NULL) {
  137. break;
  138. }
  139. if(!subghz->protocol_result->to_load_protocol_from_file(
  140. file_worker, subghz->protocol_result)) {
  141. break;
  142. }
  143. loaded = true;
  144. } while(0);
  145. if(!loaded) {
  146. file_worker_show_error(file_worker, "Cannot parse\nfile");
  147. }
  148. string_clear(temp_str);
  149. string_clear(path);
  150. file_worker_close(file_worker);
  151. file_worker_free(file_worker);
  152. return loaded;
  153. }
  154. bool subghz_save_protocol_to_file(void* context, const char* dev_name) {
  155. SubGhz* subghz = context;
  156. furi_assert(subghz->protocol_result);
  157. FileWorker* file_worker = file_worker_alloc(false);
  158. string_t dev_file_name;
  159. string_init(dev_file_name);
  160. string_t temp_str;
  161. string_init(temp_str);
  162. bool saved = false;
  163. do {
  164. // Create subghz folder directory if necessary
  165. if(!file_worker_mkdir(file_worker, SUBGHZ_APP_FOLDER)) {
  166. break;
  167. }
  168. // Create saved directory if necessary
  169. if(!file_worker_mkdir(file_worker, SUBGHZ_APP_PATH_FOLDER)) {
  170. break;
  171. }
  172. // First remove subghz device file if it was saved
  173. string_printf(
  174. dev_file_name, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, dev_name, SUBGHZ_APP_EXTENSION);
  175. if(!file_worker_remove(file_worker, string_get_cstr(dev_file_name))) {
  176. break;
  177. }
  178. // Open file
  179. if(!file_worker_open(
  180. file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
  181. break;
  182. }
  183. //Get string frequency preset protocol
  184. subghz_frequency_preset_to_str(subghz, temp_str);
  185. if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
  186. break;
  187. }
  188. //Get string save
  189. subghz->protocol_result->to_save_string(subghz->protocol_result, temp_str);
  190. // Prepare and write data to file
  191. if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
  192. break;
  193. }
  194. saved = true;
  195. } while(0);
  196. string_clear(temp_str);
  197. string_clear(dev_file_name);
  198. file_worker_close(file_worker);
  199. file_worker_free(file_worker);
  200. return saved;
  201. }
  202. bool subghz_load_protocol_from_file(SubGhz* subghz) {
  203. furi_assert(subghz);
  204. FileWorker* file_worker = file_worker_alloc(false);
  205. string_t protocol_file_name;
  206. string_init(protocol_file_name);
  207. string_t temp_str;
  208. string_init(temp_str);
  209. int sscanf_res = 0;
  210. int data = 0;
  211. // Input events and views are managed by file_select
  212. bool res = file_worker_file_select(
  213. file_worker,
  214. SUBGHZ_APP_PATH_FOLDER,
  215. SUBGHZ_APP_EXTENSION,
  216. subghz->text_store,
  217. sizeof(subghz->text_store),
  218. NULL);
  219. if(res) {
  220. // Get key file path
  221. string_printf(
  222. protocol_file_name,
  223. "%s/%s%s",
  224. SUBGHZ_APP_PATH_FOLDER,
  225. subghz->text_store,
  226. SUBGHZ_APP_EXTENSION);
  227. } else {
  228. string_clear(temp_str);
  229. string_clear(protocol_file_name);
  230. file_worker_close(file_worker);
  231. file_worker_free(file_worker);
  232. return res;
  233. }
  234. res = false;
  235. do {
  236. if(!file_worker_open(
  237. file_worker, string_get_cstr(protocol_file_name), FSAM_READ, FSOM_OPEN_EXISTING)) {
  238. break;
  239. }
  240. // Read and parse frequency from 1st line
  241. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  242. break;
  243. }
  244. sscanf_res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data);
  245. if(sscanf_res != 1) {
  246. break;
  247. }
  248. subghz->frequency = (uint32_t)data;
  249. // Read and parse preset from 2st line
  250. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  251. break;
  252. }
  253. sscanf_res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data);
  254. if(sscanf_res != 1) {
  255. break;
  256. }
  257. subghz->preset = (FuriHalSubGhzPreset)data;
  258. // Read and parse name protocol from 3st line
  259. if(!file_worker_read_until(file_worker, temp_str, '\n')) {
  260. break;
  261. }
  262. // strlen("Protocol: ") = 10
  263. string_right(temp_str, 10);
  264. subghz->protocol_result =
  265. subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str));
  266. if(subghz->protocol_result == NULL) {
  267. break;
  268. }
  269. if(!subghz->protocol_result->to_load_protocol_from_file(
  270. file_worker, subghz->protocol_result)) {
  271. break;
  272. }
  273. res = true;
  274. } while(0);
  275. if(!res) {
  276. file_worker_show_error(file_worker, "Cannot parse\nfile");
  277. }
  278. string_clear(temp_str);
  279. string_clear(protocol_file_name);
  280. file_worker_close(file_worker);
  281. file_worker_free(file_worker);
  282. return res;
  283. }
  284. uint32_t subghz_random_serial(void) {
  285. static bool rand_generator_inited = false;
  286. if(!rand_generator_inited) {
  287. srand(DWT->CYCCNT);
  288. rand_generator_inited = true;
  289. }
  290. return (uint32_t)rand();
  291. }