api-hal-subghz.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include "api-hal-subghz.h"
  2. #include <api-hal-gpio.h>
  3. #include <api-hal-spi.h>
  4. #include <api-hal-interrupt.h>
  5. #include <api-hal-resources.h>
  6. #include <furi.h>
  7. #include <cc1101.h>
  8. #include <stdio.h>
  9. static volatile SubGhzState api_hal_subghz_state = SubGhzStateInit;
  10. static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = {
  11. /* Base setting */
  12. { CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
  13. { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time
  14. /* Async OOK Specific things */
  15. { CC1101_MDMCFG2, 0x30 }, // ASK/OOK, No preamble/sync
  16. { CC1101_PKTCTRL0, 0x32 }, // Async, no CRC, Infinite
  17. { CC1101_FREND0, 0x01 }, // OOK/ASK PATABLE
  18. /* End */
  19. { 0, 0 },
  20. };
  21. static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = {
  22. 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  23. };
  24. static const uint8_t api_hal_subghz_preset_mp_regs[][2] = {
  25. { CC1101_IOCFG0, 0x0D },
  26. { CC1101_FIFOTHR, 0x07 },
  27. { CC1101_PKTCTRL0, 0x32 },
  28. //{ CC1101_FSCTRL1, 0x0E },
  29. { CC1101_FSCTRL1, 0x06 },
  30. { CC1101_FREQ2, 0x10 },
  31. { CC1101_FREQ1, 0xB0 },
  32. { CC1101_FREQ0, 0x7F },
  33. { CC1101_MDMCFG4, 0x17 },
  34. { CC1101_MDMCFG3, 0x32 },
  35. { CC1101_MDMCFG2, 0x30 }, //<---OOK/ASK
  36. { CC1101_MDMCFG1, 0x23 },
  37. { CC1101_MDMCFG0, 0xF8 },
  38. { CC1101_MCSM0, 0x18 },
  39. { CC1101_FOCCFG, 0x18 },
  40. { CC1101_AGCTRL2, 0x07 },
  41. { CC1101_AGCTRL1, 0x00 },
  42. { CC1101_AGCTRL0, 0x91 },
  43. { CC1101_WORCTRL, 0xFB },
  44. { CC1101_FREND1, 0xB6 },
  45. //{ CC1101_FREND0, 0x11 },
  46. { CC1101_FREND0, 0x01 },
  47. { CC1101_FSCAL3, 0xE9 },
  48. { CC1101_FSCAL2, 0x2A },
  49. { CC1101_FSCAL1, 0x00 },
  50. { CC1101_FSCAL0, 0x1F },
  51. { CC1101_TEST2, 0x88 },
  52. { CC1101_TEST1, 0x31 },
  53. { CC1101_TEST0, 0x09 },
  54. /* End */
  55. { 0, 0 },
  56. };
  57. static const uint8_t api_hal_subghz_preset_mp_patable[8] = {
  58. 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  59. };
  60. static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = {
  61. /* Base setting */
  62. { CC1101_IOCFG0, 0x06 }, // GD0 as async serial data output/input
  63. { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time
  64. /* Magic */
  65. { CC1101_TEST2, 0x81},
  66. { CC1101_TEST1, 0x35},
  67. { CC1101_TEST0, 0x09},
  68. /* End */
  69. { 0, 0 },
  70. };
  71. static const uint8_t api_hal_subghz_preset_2fsk_packet_patable[8] = {
  72. 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  73. };
  74. void api_hal_subghz_init() {
  75. furi_assert(api_hal_subghz_state == SubGhzStateInit);
  76. api_hal_subghz_state = SubGhzStateIdle;
  77. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  78. // Reset
  79. hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  80. cc1101_reset(device);
  81. cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance);
  82. // Prepare GD0 for power on self test
  83. hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
  84. // GD0 low
  85. cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW);
  86. while(hal_gpio_read(&gpio_cc1101_g0) != false);
  87. // GD0 high
  88. cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
  89. while(hal_gpio_read(&gpio_cc1101_g0) != true);
  90. // Reset GD0 to floating state
  91. cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance);
  92. hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  93. // RF switches
  94. hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  95. hal_gpio_init(&gpio_rf_sw_1, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
  96. // Go to sleep
  97. cc1101_shutdown(device);
  98. api_hal_spi_device_return(device);
  99. }
  100. void api_hal_subghz_sleep() {
  101. furi_assert(api_hal_subghz_state == SubGhzStateIdle);
  102. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  103. cc1101_switch_to_idle(device);
  104. cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance);
  105. hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  106. cc1101_shutdown(device);
  107. api_hal_spi_device_return(device);
  108. }
  109. void api_hal_subghz_dump_state() {
  110. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  111. printf(
  112. "[api_hal_subghz] cc1101 chip %d, version %d\r\n",
  113. cc1101_get_partnumber(device),
  114. cc1101_get_version(device)
  115. );
  116. api_hal_spi_device_return(device);
  117. }
  118. void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset) {
  119. if(preset == ApiHalSubGhzPresetOokAsync) {
  120. api_hal_subghz_load_registers(api_hal_subghz_preset_ook_async_regs);
  121. api_hal_subghz_load_patable(api_hal_subghz_preset_ook_async_patable);
  122. } else if(preset == ApiHalSubGhzPreset2FskPacket) {
  123. api_hal_subghz_load_registers(api_hal_subghz_preset_2fsk_packet_regs);
  124. api_hal_subghz_load_patable(api_hal_subghz_preset_2fsk_packet_patable);
  125. } else if(preset == ApiHalSubGhzPresetMP) {
  126. api_hal_subghz_load_registers(api_hal_subghz_preset_mp_regs);
  127. api_hal_subghz_load_patable(api_hal_subghz_preset_mp_patable);
  128. }
  129. }
  130. uint8_t api_hal_subghz_get_status() {
  131. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  132. CC1101StatusRaw st;
  133. st.status = cc1101_get_status(device);
  134. api_hal_spi_device_return(device);
  135. return st.status_raw;
  136. }
  137. void api_hal_subghz_load_registers(const uint8_t data[][2]) {
  138. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  139. cc1101_reset(device);
  140. uint32_t i = 0;
  141. while (data[i][0]) {
  142. cc1101_write_reg(device, data[i][0], data[i][1]);
  143. i++;
  144. }
  145. api_hal_spi_device_return(device);
  146. }
  147. void api_hal_subghz_load_patable(const uint8_t data[8]) {
  148. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  149. cc1101_set_pa_table(device, data);
  150. api_hal_spi_device_return(device);
  151. }
  152. void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size) {
  153. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  154. cc1101_flush_tx(device);
  155. cc1101_write_fifo(device, data, size);
  156. api_hal_spi_device_return(device);
  157. }
  158. void api_hal_subghz_flush_rx() {
  159. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  160. cc1101_flush_rx(device);
  161. api_hal_spi_device_return(device);
  162. }
  163. void api_hal_subghz_read_packet(uint8_t* data, uint8_t* size) {
  164. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  165. cc1101_read_fifo(device, data, size);
  166. api_hal_spi_device_return(device);
  167. }
  168. void api_hal_subghz_shutdown() {
  169. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  170. // Reset and shutdown
  171. cc1101_shutdown(device);
  172. api_hal_spi_device_return(device);
  173. }
  174. void api_hal_subghz_reset() {
  175. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  176. hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  177. cc1101_switch_to_idle(device);
  178. cc1101_reset(device);
  179. cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance);
  180. api_hal_spi_device_return(device);
  181. }
  182. void api_hal_subghz_idle() {
  183. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  184. cc1101_switch_to_idle(device);
  185. api_hal_spi_device_return(device);
  186. }
  187. void api_hal_subghz_rx() {
  188. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  189. cc1101_switch_to_rx(device);
  190. api_hal_spi_device_return(device);
  191. }
  192. void api_hal_subghz_tx() {
  193. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  194. cc1101_switch_to_tx(device);
  195. api_hal_spi_device_return(device);
  196. }
  197. float api_hal_subghz_get_rssi() {
  198. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  199. int32_t rssi_dec = cc1101_get_rssi(device);
  200. api_hal_spi_device_return(device);
  201. float rssi = rssi_dec;
  202. if(rssi_dec >= 128) {
  203. rssi = ((rssi - 256.0f) / 2.0f) - 74.0f;
  204. } else {
  205. rssi = (rssi / 2.0f) - 74.0f;
  206. }
  207. return rssi;
  208. }
  209. uint32_t api_hal_subghz_set_frequency_and_path(uint32_t value) {
  210. value = api_hal_subghz_set_frequency(value);
  211. if(value >= 300000000 && value <= 348000335) {
  212. api_hal_subghz_set_path(ApiHalSubGhzPath315);
  213. } else if(value >= 387000000 && value <= 464000000) {
  214. api_hal_subghz_set_path(ApiHalSubGhzPath433);
  215. } else if(value >= 779000000 && value <= 928000000) {
  216. api_hal_subghz_set_path(ApiHalSubGhzPath868);
  217. } else {
  218. furi_check(0);
  219. }
  220. return value;
  221. }
  222. uint32_t api_hal_subghz_set_frequency(uint32_t value) {
  223. const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
  224. // Compensate rounding
  225. if (value % cc1101_get_frequency_step(device) > (cc1101_get_frequency_step(device) / 2)) {
  226. value += cc1101_get_frequency_step(device);
  227. }
  228. uint32_t real_frequency = cc1101_set_frequency(device, value);
  229. cc1101_calibrate(device);
  230. api_hal_spi_device_return(device);
  231. return real_frequency;
  232. }
  233. void api_hal_subghz_set_path(ApiHalSubGhzPath path) {
  234. if (path == ApiHalSubGhzPath433) {
  235. hal_gpio_write(&gpio_rf_sw_0, 0);
  236. hal_gpio_write(&gpio_rf_sw_1, 1);
  237. } else if (path == ApiHalSubGhzPath315) {
  238. hal_gpio_write(&gpio_rf_sw_0, 1);
  239. hal_gpio_write(&gpio_rf_sw_1, 0);
  240. } else if (path == ApiHalSubGhzPath868) {
  241. hal_gpio_write(&gpio_rf_sw_0, 1);
  242. hal_gpio_write(&gpio_rf_sw_1, 1);
  243. } else if (path == ApiHalSubGhzPathIsolate) {
  244. hal_gpio_write(&gpio_rf_sw_0, 0);
  245. hal_gpio_write(&gpio_rf_sw_1, 0);
  246. } else {
  247. furi_check(0);
  248. }
  249. }
  250. void api_hal_subghz_set_async_rx_callback(ApiHalSubGhzCaptureCallback callback, void* context) {}
  251. void api_hal_subghz_start_async_rx() {}
  252. void api_hal_subghz_stop_async_rx() {}
  253. void api_hal_subghz_start_async_tx(uint32_t* buffer, size_t buffer_size, size_t repeat) {}
  254. void api_hal_subghz_wait_async_tx() {}
  255. void api_hal_subghz_stop_async_tx() {}