cc1101.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "cc1101.h"
  2. #include <cmsis_os2.h>
  3. #include <furi_hal_delay.h>
  4. #include <assert.h>
  5. #include <string.h>
  6. CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe) {
  7. uint8_t tx[1] = {strobe};
  8. CC1101Status rx[1] = {0};
  9. while(furi_hal_gpio_read(handle->miso))
  10. ;
  11. furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT);
  12. assert(rx[0].CHIP_RDYn == 0);
  13. return rx[0];
  14. }
  15. CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) {
  16. uint8_t tx[2] = {reg, data};
  17. CC1101Status rx[2] = {0};
  18. while(furi_hal_gpio_read(handle->miso))
  19. ;
  20. furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
  21. assert((rx[0].CHIP_RDYn | rx[1].CHIP_RDYn) == 0);
  22. return rx[1];
  23. }
  24. CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data) {
  25. assert(sizeof(CC1101Status) == 1);
  26. uint8_t tx[2] = {reg | CC1101_READ, 0};
  27. CC1101Status rx[2] = {0};
  28. while(furi_hal_gpio_read(handle->miso))
  29. ;
  30. furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
  31. assert((rx[0].CHIP_RDYn) == 0);
  32. *data = *(uint8_t*)&rx[1];
  33. return rx[0];
  34. }
  35. uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle) {
  36. uint8_t partnumber = 0;
  37. cc1101_read_reg(handle, CC1101_STATUS_PARTNUM | CC1101_BURST, &partnumber);
  38. return partnumber;
  39. }
  40. uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle) {
  41. uint8_t version = 0;
  42. cc1101_read_reg(handle, CC1101_STATUS_VERSION | CC1101_BURST, &version);
  43. return version;
  44. }
  45. uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle) {
  46. uint8_t rssi = 0;
  47. cc1101_read_reg(handle, CC1101_STATUS_RSSI | CC1101_BURST, &rssi);
  48. return rssi;
  49. }
  50. void cc1101_reset(FuriHalSpiBusHandle* handle) {
  51. cc1101_strobe(handle, CC1101_STROBE_SRES);
  52. }
  53. CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle) {
  54. return cc1101_strobe(handle, CC1101_STROBE_SNOP);
  55. }
  56. void cc1101_shutdown(FuriHalSpiBusHandle* handle) {
  57. cc1101_strobe(handle, CC1101_STROBE_SPWD);
  58. }
  59. void cc1101_calibrate(FuriHalSpiBusHandle* handle) {
  60. cc1101_strobe(handle, CC1101_STROBE_SCAL);
  61. }
  62. void cc1101_switch_to_idle(FuriHalSpiBusHandle* handle) {
  63. cc1101_strobe(handle, CC1101_STROBE_SIDLE);
  64. }
  65. void cc1101_switch_to_rx(FuriHalSpiBusHandle* handle) {
  66. cc1101_strobe(handle, CC1101_STROBE_SRX);
  67. }
  68. void cc1101_switch_to_tx(FuriHalSpiBusHandle* handle) {
  69. cc1101_strobe(handle, CC1101_STROBE_STX);
  70. }
  71. void cc1101_flush_rx(FuriHalSpiBusHandle* handle) {
  72. cc1101_strobe(handle, CC1101_STROBE_SFRX);
  73. }
  74. void cc1101_flush_tx(FuriHalSpiBusHandle* handle) {
  75. cc1101_strobe(handle, CC1101_STROBE_SFTX);
  76. }
  77. uint32_t cc1101_set_frequency(FuriHalSpiBusHandle* handle, uint32_t value) {
  78. uint64_t real_value = (uint64_t)value * CC1101_FDIV / CC1101_QUARTZ;
  79. // Sanity check
  80. assert((real_value & CC1101_FMASK) == real_value);
  81. cc1101_write_reg(handle, CC1101_FREQ2, (real_value >> 16) & 0xFF);
  82. cc1101_write_reg(handle, CC1101_FREQ1, (real_value >> 8) & 0xFF);
  83. cc1101_write_reg(handle, CC1101_FREQ0, (real_value >> 0) & 0xFF);
  84. uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV;
  85. return (uint32_t)real_frequency;
  86. }
  87. uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t value) {
  88. uint64_t real_value = value * CC1101_IFDIV / CC1101_QUARTZ;
  89. assert((real_value & 0xFF) == real_value);
  90. cc1101_write_reg(handle, CC1101_FSCTRL0, (real_value >> 0) & 0xFF);
  91. uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_IFDIV;
  92. return (uint32_t)real_frequency;
  93. }
  94. void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]) {
  95. uint8_t tx[9] = {CC1101_PATABLE | CC1101_BURST};
  96. CC1101Status rx[9] = {0};
  97. memcpy(&tx[1], &value[0], 8);
  98. while(furi_hal_gpio_read(handle->miso))
  99. ;
  100. furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT);
  101. assert((rx[0].CHIP_RDYn | rx[8].CHIP_RDYn) == 0);
  102. }
  103. uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size) {
  104. uint8_t buff_tx[64];
  105. uint8_t buff_rx[64];
  106. buff_tx[0] = CC1101_FIFO | CC1101_BURST;
  107. memcpy(&buff_tx[1], data, size);
  108. // Start transaction
  109. // Wait IC to become ready
  110. while(furi_hal_gpio_read(handle->miso))
  111. ;
  112. // Tell IC what we want
  113. furi_hal_spi_bus_trx(handle, buff_tx, (uint8_t*)buff_rx, size + 1, CC1101_TIMEOUT);
  114. return size;
  115. }
  116. uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size) {
  117. uint8_t buff_tx[64];
  118. buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST;
  119. uint8_t buff_rx[2];
  120. // Start transaction
  121. // Wait IC to become ready
  122. while(furi_hal_gpio_read(handle->miso))
  123. ;
  124. // First byte - packet length
  125. furi_hal_spi_bus_trx(handle, buff_tx, buff_rx, 2, CC1101_TIMEOUT);
  126. // Check that the packet is placed in the receive buffer
  127. if(buff_rx[1] > 64) {
  128. *size = 64;
  129. } else {
  130. *size = buff_rx[1];
  131. }
  132. furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT);
  133. return *size;
  134. }