lt8920.cpp 9.0 KB

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