subghz_tx_rx_worker.c 8.3 KB

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