cc1101.c 4.9 KB

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