api-hal-subghz.c 8.8 KB

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