lt8920.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include "stm32l0xx_hal.h"
  2. #include "lt8920.h"
  3. #include "lt8920_trs.h"
  4. #include <stdio.h>
  5. #undef DBG
  6. #define DBG if(0)
  7. void LT8920::dump_register(uint8_t reg)
  8. {
  9. uint16_t r = readRegister(reg);
  10. printf("reg: %u, value: %X\r\n", reg, r);
  11. }
  12. LT8920::LT8920(void)
  13. {
  14. _channel = DEFAULT_CHANNEL;
  15. LT8920_CS_HIGH;
  16. }
  17. void LT8920::begin()
  18. {
  19. LT8920_RESET_LOW;
  20. HAL_Delay(200);
  21. LT8920_RESET_HIGH;
  22. HAL_Delay(200);
  23. //setup
  24. writeRegister(0, 0x6fe0);
  25. writeRegister(1, 0x5681);
  26. writeRegister(2, 0x6617);
  27. writeRegister(4, 0x9cc9); //why does this differ from powerup (5447)
  28. writeRegister(5, 0x6637); //why does this differ from powerup (f000)
  29. writeRegister(8, 0x6c90); //power (default 71af) UNDOCUMENTED
  30. setCurrentControl(4, 0); // power & gain.
  31. writeRegister(10, 0x7ffd); //bit 0: XTAL OSC enable
  32. writeRegister(11, 0x0000); //bit 8: Power down RSSI (0= RSSI operates normal)
  33. writeRegister(12, 0x0000);
  34. writeRegister(13, 0x48bd); //(default 4855)
  35. writeRegister(22, 0x00ff);
  36. writeRegister(23, 0x8005); //bit 2: Calibrate VCO before each Rx/Tx enable
  37. writeRegister(24, 0x0067);
  38. writeRegister(25, 0x1659);
  39. writeRegister(26, 0x19e0);
  40. writeRegister(27, 0x1300); //bits 5:0, Crystal Frequency adjust
  41. writeRegister(28, 0x1800);
  42. //fedcba9876543210
  43. writeRegister(32, 0x5000); //AAABBCCCDDEEFFFG A preamble length, B, syncword length, c trailer length, d packet type
  44. // E FEC_type, F BRCLK_SEL, G reserved
  45. //0x5000 = 0101 0000 0000 0000 = preamble 010 (3 bytes), B 10 (48 bits)
  46. writeRegister(33, 0x3fc7);
  47. writeRegister(34, 0x2000); //
  48. writeRegister(35, 0x0300); //POWER mode, bit 8/9 on = retransmit = 3x (default)
  49. setSyncWord(0x03805a5a03800380);
  50. writeRegister(40, 0x4401); //max allowed error bits = 0 (01 = 0 error bits)
  51. writeRegister(R_PACKETCONFIG, PACKETCONFIG_CRC_ON |
  52. PACKETCONFIG_PACK_LEN_ENABLE | PACKETCONFIG_FW_TERM_TX);
  53. writeRegister(42, 0xfdb0);
  54. writeRegister(43, 0x000f);
  55. //setDataRate(LT8920_1MBPS);
  56. writeRegister(R_FIFO, 0x0000); //TXRX_FIFO_REG (FIFO queue)
  57. writeRegister(R_FIFO_CONTROL, 0x8080); //Fifo Rx/Tx queue reset
  58. HAL_Delay(200);
  59. writeRegister(R_CHANNEL, _BV(CHANNEL_TX_BIT)); //set TX mode. (TX = bit 8, RX = bit 7, so RX would be 0x0080)
  60. HAL_Delay(2);
  61. writeRegister(R_CHANNEL, _channel); // Frequency = 2402 + channel
  62. }
  63. void LT8920::setChannel(uint8_t channel)
  64. {
  65. _channel = channel;
  66. writeRegister(R_CHANNEL, (_channel & CHANNEL_MASK));
  67. }
  68. uint8_t LT8920::getChannel()
  69. {
  70. return _channel;
  71. }
  72. void LT8920::setCurrentControl(uint8_t power, uint8_t gain)
  73. {
  74. writeRegister(R_CURRENT,
  75. ((power << CURRENT_POWER_SHIFT) & CURRENT_POWER_MASK) |
  76. ((gain << CURRENT_GAIN_SHIFT) & CURRENT_GAIN_MASK));
  77. }
  78. bool LT8920::setDataRate(DataRate rate)
  79. {
  80. uint16_t newValue;
  81. switch (rate)
  82. {
  83. case LT8920_1MBPS:
  84. newValue = DATARATE_1MBPS;
  85. break;
  86. case LT8920_250KBPS:
  87. newValue = DATARATE_250KBPS;
  88. break;
  89. case LT8920_125KBPS:
  90. newValue = DATARATE_125KBPS;
  91. break;
  92. case LT8920_62KBPS:
  93. newValue = DATARATE_62KBPS;
  94. break;
  95. default:
  96. return false;
  97. }
  98. writeRegister(R_DATARATE, newValue);
  99. return ( (readRegister(R_DATARATE) & DATARATE_MASK) == (newValue & DATARATE_MASK));
  100. }
  101. LT8920::DataRate LT8920::getDataRate()
  102. {
  103. uint16_t value = readRegister(R_DATARATE) & DATARATE_MASK;
  104. switch (value)
  105. {
  106. case DATARATE_1MBPS:
  107. return LT8920_1MBPS;
  108. case DATARATE_250KBPS:
  109. return LT8920_250KBPS;
  110. case DATARATE_125KBPS:
  111. return LT8920_125KBPS;
  112. case DATARATE_62KBPS:
  113. return LT8920_62KBPS;
  114. default :
  115. return LT8920_ERROR;
  116. }
  117. }
  118. uint16_t LT8920::readRegister(uint8_t reg)
  119. {
  120. LT8920_CS_LOW;
  121. lt_spi_transfer_byte(REGISTER_READ | (REGISTER_MASK & reg));
  122. uint8_t high = lt_spi_transfer_byte(0x00);
  123. uint8_t low = lt_spi_transfer_byte(0x00);
  124. LT8920_CS_HIGH;
  125. DBG printf("reg: %X = %X\r\n", reg, (high << 8 | low));
  126. return (high << 8 | low);
  127. }
  128. uint8_t LT8920::writeRegister(uint8_t reg, uint16_t data)
  129. {
  130. uint8_t high = data >> 8;
  131. uint8_t low = data & 0xFF;
  132. return writeRegister2(reg, high, low);
  133. }
  134. uint8_t LT8920::writeRegister2(uint8_t reg, uint8_t high, uint8_t low)
  135. {
  136. // char sbuf[32];
  137. // sprintf_P(sbuf, PSTR("%d => %02x%02x"), reg, high, low);
  138. // Serial.println(sbuf);
  139. LT8920_CS_LOW;
  140. uint8_t result = lt_spi_transfer_byte(REGISTER_WRITE | (REGISTER_MASK & reg));
  141. lt_spi_transfer_byte(high);
  142. lt_spi_transfer_byte(low);
  143. LT8920_CS_HIGH;
  144. return result;
  145. }
  146. void LT8920::sleep()
  147. {
  148. //set bit 14 on register 35.
  149. writeRegister(35, readRegister(35) | _BV(14));
  150. }
  151. void LT8920::whatsUp(void)
  152. {
  153. uint16_t mode = readRegister(R_CHANNEL);
  154. DBG printf("Tx_EN = %u, Rx_EN = %u\r\n", (mode & _BV(CHANNEL_TX_BIT)), (mode & _BV(CHANNEL_RX_BIT)));
  155. DBG printf("Channel = %u\r\n", (mode & CHANNEL_MASK));
  156. //read the status register.
  157. uint16_t state = readRegister(R_STATUS);
  158. bool crc_error = state & _BV(15);
  159. bool fec23_error = state & _BV(14);
  160. uint8_t framer_st = (state & 0b0011111100000000) >> 8;
  161. bool pkt_flag = state & _BV(6);
  162. bool fifo_flag = state & _BV(5);
  163. DBG printf("CRC = %u, FEC = %u, FRAMER_ST = %u, PKT = %u, FIFO = %u\r\n",
  164. crc_error, fec23_error, framer_st, pkt_flag, fifo_flag);
  165. uint16_t fifo = readRegister(R_FIFO_CONTROL);
  166. DBG printf("FIFO_WR_PTR = %X, FIFO_RD_PTR = %X\r\n",
  167. ((fifo >> 8) & 0b111111), (fifo & 0b111111));
  168. }
  169. bool LT8920::available()
  170. {
  171. //read the PKT_FLAG state; this can also be done with a hard wire.
  172. if (LT8920_GET_PKT != 0) {
  173. return true;
  174. }
  175. return false;
  176. }
  177. int LT8920::read(uint8_t *buffer, size_t maxBuffer)
  178. {
  179. uint16_t value = readRegister(R_STATUS);
  180. uint8_t pos = 0;
  181. if (bitRead(value, STATUS_CRC_BIT) == 0)
  182. {
  183. //CRC ok
  184. uint16_t data = readRegister(R_FIFO);
  185. uint8_t packetSize = data >> 8;
  186. if (maxBuffer < packetSize + 1) {
  187. //BUFFER TOO SMALL
  188. return -2;
  189. }
  190. buffer[pos++] = (data & 0xFF);
  191. while (pos < packetSize)
  192. {
  193. data = readRegister(R_FIFO);
  194. buffer[pos++] = data >> 8;
  195. buffer[pos++] = data & 0xFF;
  196. }
  197. return packetSize;
  198. }
  199. else {
  200. //CRC error
  201. return -1;
  202. }
  203. }
  204. void LT8920::startListening()
  205. {
  206. writeRegister(R_CHANNEL, _channel & CHANNEL_MASK); // turn off rx/tx
  207. HAL_Delay(3);
  208. writeRegister(R_FIFO_CONTROL, 0x0080); //flush rx
  209. writeRegister(R_CHANNEL, (_channel & CHANNEL_MASK) | _BV(CHANNEL_RX_BIT)); //enable RX
  210. HAL_Delay(5);
  211. }
  212. /* set the BRCLK_SEL value */
  213. void LT8920::setClock(uint8_t clock)
  214. {
  215. //register 32, bits 3:1.
  216. uint16_t val = readRegister(35);
  217. val &= 0b1111111111110001;
  218. val |= ((clock & 0x07) << 1);;
  219. writeRegister(35, val);
  220. }
  221. bool LT8920::sendPacket(uint8_t *data, size_t packetSize)
  222. {
  223. if (packetSize < 1 || packetSize > 255)
  224. {
  225. return false;
  226. }
  227. writeRegister(R_CHANNEL, 0x0000);
  228. writeRegister(R_FIFO_CONTROL, 0x8000); //flush tx
  229. // packets are sent in 16bit words, and the first word will be the packet size.
  230. // start spitting out words until we are done.
  231. uint8_t pos = 0;
  232. writeRegister2(R_FIFO, packetSize, data[pos++]);
  233. while (pos < packetSize)
  234. {
  235. uint8_t msb = data[pos++];
  236. uint8_t lsb = data[pos++];
  237. writeRegister2(R_FIFO, msb, lsb);
  238. }
  239. writeRegister(R_CHANNEL, (_channel & CHANNEL_MASK) | _BV(CHANNEL_TX_BIT)); //enable TX
  240. // Wait until the packet is sent.
  241. while (LT8920_GET_PKT == 0)
  242. {
  243. //do nothing.
  244. }
  245. return true;
  246. }
  247. void LT8920::setSyncWord(uint64_t syncWord)
  248. {
  249. writeRegister(R_SYNCWORD1, syncWord);
  250. writeRegister(R_SYNCWORD2, syncWord >> 16);
  251. writeRegister(R_SYNCWORD3, syncWord >> 32);
  252. writeRegister(R_SYNCWORD4, syncWord >> 48);
  253. }
  254. void LT8920::setSyncWordLength(uint8_t option)
  255. {
  256. option &= 0x03;
  257. option <<= 11;
  258. writeRegister(32, (readRegister(32) & 0b0001100000000000) | option);
  259. }
  260. uint8_t LT8920::getRSSI()
  261. {
  262. // RSSI: 15:10
  263. uint16_t value = readRegister(6);
  264. return (value >> 10);
  265. }
  266. void LT8920::scanRSSI(uint16_t *buffer, uint8_t start_channel, uint8_t num_channels)
  267. {
  268. uint8_t pos = 0;
  269. // writeRegister(R_CHANNEL, _BV(CHANNEL_RX_BIT));
  270. //
  271. // //add read mode.
  272. writeRegister(R_FIFO_CONTROL, 0x8080); //flush rx
  273. // writeRegister(R_CHANNEL, 0x0000);
  274. //set number of channels to scan.
  275. writeRegister(42, (readRegister(42) & 0b0000001111111111) | ((num_channels-1 & 0b111111) << 10));
  276. //set channel scan offset.
  277. writeRegister(43, (readRegister(43) & 0b0000000011111111) | ((start_channel & 0b1111111) << 8));
  278. writeRegister(43, (readRegister(43) & 0b0111111111111111) | _BV(15));
  279. while (LT8920_GET_PKT == 0) {}
  280. //read the results.
  281. while (pos < num_channels)
  282. {
  283. uint16_t data = readRegister(R_FIFO);
  284. buffer[pos++] = data >> 8;
  285. }
  286. }