subghz_tx_rx_worker.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "subghz_tx_rx_worker.h"
  2. #include <furi.h>
  3. #define TAG "SubGhzTxRxWorker"
  4. #define SUBGHZ_TXRX_WORKER_BUF_SIZE 2048
  5. //you can not set more than 62 because it will not fit into the FIFO CC1101
  6. #define SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE 60
  7. #define SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40
  8. struct SubGhzTxRxWorker {
  9. FuriThread* thread;
  10. FuriStreamBuffer* stream_tx;
  11. FuriStreamBuffer* stream_rx;
  12. volatile bool worker_running;
  13. volatile bool worker_stoping;
  14. SubGhzTxRxWorkerStatus status;
  15. uint32_t frequency;
  16. SubGhzTxRxWorkerCallbackHaveRead callback_have_read;
  17. void* context_have_read;
  18. };
  19. bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
  20. furi_assert(instance);
  21. bool ret = false;
  22. size_t stream_tx_free_byte = furi_stream_buffer_spaces_available(instance->stream_tx);
  23. if(size && (stream_tx_free_byte >= size)) {
  24. if(furi_stream_buffer_send(
  25. instance->stream_tx, data, size, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) ==
  26. size) {
  27. ret = true;
  28. }
  29. }
  30. return ret;
  31. }
  32. size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) {
  33. furi_assert(instance);
  34. return furi_stream_buffer_bytes_available(instance->stream_rx);
  35. }
  36. size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
  37. furi_assert(instance);
  38. return furi_stream_buffer_receive(instance->stream_rx, data, size, 0);
  39. }
  40. void subghz_tx_rx_worker_set_callback_have_read(
  41. SubGhzTxRxWorker* instance,
  42. SubGhzTxRxWorkerCallbackHaveRead callback,
  43. void* context) {
  44. furi_assert(instance);
  45. furi_assert(callback);
  46. furi_assert(context);
  47. instance->callback_have_read = callback;
  48. instance->context_have_read = context;
  49. }
  50. bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* size) {
  51. uint8_t timeout = 100;
  52. bool ret = false;
  53. if(instance->status != SubGhzTxRxWorkerStatusRx) {
  54. furi_hal_subghz_rx();
  55. instance->status = SubGhzTxRxWorkerStatusRx;
  56. furi_delay_tick(1);
  57. }
  58. //waiting for reception to complete
  59. while(furi_hal_gpio_read(&gpio_cc1101_g0)) {
  60. furi_delay_tick(1);
  61. if(!--timeout) {
  62. FURI_LOG_W(TAG, "RX cc1101_g0 timeout");
  63. furi_hal_subghz_flush_rx();
  64. furi_hal_subghz_rx();
  65. break;
  66. }
  67. }
  68. if(furi_hal_subghz_rx_pipe_not_empty()) {
  69. FURI_LOG_I(
  70. TAG,
  71. "RSSI: %03.1fdbm LQI: %d",
  72. (double)furi_hal_subghz_get_rssi(),
  73. furi_hal_subghz_get_lqi());
  74. if(furi_hal_subghz_is_rx_data_crc_valid()) {
  75. furi_hal_subghz_read_packet(data, size);
  76. ret = true;
  77. }
  78. furi_hal_subghz_flush_rx();
  79. furi_hal_subghz_rx();
  80. }
  81. return ret;
  82. }
  83. void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
  84. uint8_t timeout = 200;
  85. if(instance->status != SubGhzTxRxWorkerStatusIDLE) {
  86. furi_hal_subghz_idle();
  87. }
  88. furi_hal_subghz_write_packet(data, size);
  89. furi_hal_subghz_tx(); //start send
  90. instance->status = SubGhzTxRxWorkerStatusTx;
  91. while(!furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
  92. furi_delay_tick(1);
  93. if(!--timeout) {
  94. FURI_LOG_W(TAG, "TX !cc1101_g0 timeout");
  95. break;
  96. }
  97. }
  98. while(furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet
  99. furi_delay_tick(1);
  100. if(!--timeout) {
  101. FURI_LOG_W(TAG, "TX cc1101_g0 timeout");
  102. break;
  103. }
  104. }
  105. furi_hal_subghz_idle();
  106. instance->status = SubGhzTxRxWorkerStatusIDLE;
  107. }
  108. /** Worker thread
  109. *
  110. * @param context
  111. * @return exit code
  112. */
  113. static int32_t subghz_tx_rx_worker_thread(void* context) {
  114. SubGhzTxRxWorker* instance = context;
  115. FURI_LOG_I(TAG, "Worker start");
  116. furi_hal_subghz_reset();
  117. furi_hal_subghz_idle();
  118. furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync);
  119. //furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync);
  120. furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
  121. furi_hal_subghz_set_frequency_and_path(instance->frequency);
  122. furi_hal_subghz_flush_rx();
  123. uint8_t data[SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE + 1] = {0};
  124. size_t size_tx = 0;
  125. uint8_t size_rx[1] = {0};
  126. uint8_t timeout_tx = 0;
  127. bool callback_rx = false;
  128. while(instance->worker_running) {
  129. //transmit
  130. size_tx = furi_stream_buffer_bytes_available(instance->stream_tx);
  131. if(size_tx > 0 && !timeout_tx) {
  132. timeout_tx = 10; //20ms
  133. if(size_tx > SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) {
  134. furi_stream_buffer_receive(
  135. instance->stream_tx,
  136. &data,
  137. SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE,
  138. SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
  139. subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE);
  140. } else {
  141. //todo checking that he managed to write all the data to the TX buffer
  142. furi_stream_buffer_receive(
  143. instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
  144. subghz_tx_rx_worker_tx(instance, data, size_tx);
  145. }
  146. } else {
  147. //recive
  148. if(subghz_tx_rx_worker_rx(instance, data, size_rx)) {
  149. if(furi_stream_buffer_spaces_available(instance->stream_rx) >= size_rx[0]) {
  150. if(instance->callback_have_read &&
  151. furi_stream_buffer_bytes_available(instance->stream_rx) == 0) {
  152. callback_rx = true;
  153. }
  154. //todo checking that he managed to write all the data to the RX buffer
  155. furi_stream_buffer_send(
  156. instance->stream_rx,
  157. &data,
  158. size_rx[0],
  159. SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
  160. if(callback_rx) {
  161. instance->callback_have_read(instance->context_have_read);
  162. callback_rx = false;
  163. }
  164. } else {
  165. //todo RX buffer overflow
  166. }
  167. }
  168. }
  169. if(timeout_tx) timeout_tx--;
  170. furi_delay_tick(1);
  171. }
  172. furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
  173. furi_hal_subghz_sleep();
  174. FURI_LOG_I(TAG, "Worker stop");
  175. return 0;
  176. }
  177. SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() {
  178. SubGhzTxRxWorker* instance = malloc(sizeof(SubGhzTxRxWorker));
  179. instance->thread =
  180. furi_thread_alloc_ex("SubGhzTxRxWorker", 2048, subghz_tx_rx_worker_thread, instance);
  181. instance->stream_tx =
  182. furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
  183. instance->stream_rx =
  184. furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
  185. instance->status = SubGhzTxRxWorkerStatusIDLE;
  186. instance->worker_stoping = true;
  187. return instance;
  188. }
  189. void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) {
  190. furi_assert(instance);
  191. furi_assert(!instance->worker_running);
  192. furi_stream_buffer_free(instance->stream_tx);
  193. furi_stream_buffer_free(instance->stream_rx);
  194. furi_thread_free(instance->thread);
  195. free(instance);
  196. }
  197. bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) {
  198. furi_assert(instance);
  199. furi_assert(!instance->worker_running);
  200. bool res = false;
  201. furi_stream_buffer_reset(instance->stream_tx);
  202. furi_stream_buffer_reset(instance->stream_rx);
  203. instance->worker_running = true;
  204. if(furi_hal_region_is_frequency_allowed(frequency)) {
  205. instance->frequency = frequency;
  206. res = true;
  207. }
  208. furi_thread_start(instance->thread);
  209. return res;
  210. }
  211. void subghz_tx_rx_worker_stop(SubGhzTxRxWorker* instance) {
  212. furi_assert(instance);
  213. furi_assert(instance->worker_running);
  214. instance->worker_running = false;
  215. furi_thread_join(instance->thread);
  216. }
  217. bool subghz_tx_rx_worker_is_running(SubGhzTxRxWorker* instance) {
  218. furi_assert(instance);
  219. return instance->worker_running;
  220. }