xl2400.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. // Copyright 2021 IOsetting <iosetting(at)outlook.com>
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "xl2400.h"
  15. __IDATA uint8_t cbuf[2], xbuf[XL2400_PL_WIDTH_MAX + 1];
  16. uint8_t *xbuf_data = xbuf + 1;
  17. void XL2400_WriteReg(uint8_t reg, uint8_t value)
  18. {
  19. XL2400_CSN = 0;
  20. cbuf[0] = reg;
  21. cbuf[1] = value;
  22. SPI_TxRxBytes(cbuf, 2);
  23. XL2400_CSN = 1;
  24. }
  25. uint8_t XL2400_ReadReg(uint8_t reg)
  26. {
  27. XL2400_CSN = 0;
  28. cbuf[0] = reg;
  29. cbuf[1] = XL2400_CMD_NOP;
  30. SPI_TxRxBytes(cbuf, 2);
  31. XL2400_CSN = 1;
  32. return cbuf[1];
  33. }
  34. void XL2400_WriteFromBuf(uint8_t reg, const uint8_t *pBuf, uint8_t len)
  35. {
  36. XL2400_CSN = 0;
  37. xbuf[0] = reg;
  38. memcpy(xbuf_data, pBuf, len);
  39. SPI_TxRxBytes(xbuf, len + 1);
  40. XL2400_CSN = 1;
  41. }
  42. void XL2400_ReadToBuf(uint8_t reg, uint8_t len)
  43. {
  44. XL2400_CSN = 0;
  45. memset(xbuf, XL2400_CMD_NOP, XL2400_PL_WIDTH_MAX + 1);
  46. xbuf[0] = reg;
  47. SPI_TxRxBytes(xbuf, len + 1);
  48. XL2400_CSN = 1;
  49. }
  50. void XL2400_WriteBack(uint8_t reg, uint8_t len)
  51. {
  52. XL2400_CSN = 0;
  53. xbuf[0] = reg;
  54. SPI_TxRxBytes(xbuf, len + 1);
  55. XL2400_CSN = 1;
  56. }
  57. void XL2400_CE_Low(void)
  58. {
  59. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, 2);
  60. *(xbuf_data + 1) &= 0xBF;
  61. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 2);
  62. }
  63. void XL2400_CE_High(void)
  64. {
  65. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, 2);
  66. *(xbuf_data + 1) |= 0x40;
  67. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 2);
  68. }
  69. uint8_t XL2400_SPI_Test(void)
  70. {
  71. uint8_t i;
  72. const uint8_t *ptr = (const uint8_t *)XL2400_TEST_ADDR;
  73. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_TX_ADDR, ptr, 5);
  74. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_TX_ADDR, 5);
  75. for (i = 0; i < 5; i++) {
  76. UART1_TxHex(*(xbuf_data + i));
  77. if (*(xbuf_data + i) != *ptr++) return HAL_ERROR;
  78. }
  79. return HAL_OK;
  80. }
  81. void XL2400_Init(void)
  82. {
  83. // Analog config
  84. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, 13);
  85. *(xbuf_data + 4) &= ~0x04;
  86. *(xbuf_data + 12) |= 0x40;
  87. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 13);
  88. // Switch to software CE control, wake up RF
  89. XL2400_WakeUp();
  90. // Enable Auto ACK Pipe 0
  91. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_AA, 0x3F);
  92. // Enable Pipe 0
  93. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_RXADDR, 0x3F);
  94. // Address Width, 5 bytes
  95. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_AW, 0xAF);
  96. // Retries and interval
  97. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_RETR, 0x33);
  98. // RF Data Rate 1Mbps
  99. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, 0x22);
  100. // Number of bytes in RX payload, pipe 0 and pipe 1
  101. *(xbuf_data + 0) = XL2400_PLOAD_WIDTH;
  102. *(xbuf_data + 1) = XL2400_PLOAD_WIDTH;
  103. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_RX_PW_PX, 2);
  104. // Dynamic payload width: off
  105. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_DYNPD, 0x00);
  106. // Other features
  107. //bit7&6=00 return status when send register address
  108. //bit5=0 long data pack off
  109. //bit4=1 FEC off
  110. //bit3=1 FEATURE on
  111. //bit2=0 Dynamic length off
  112. //bit1=0 ACK without payload
  113. //bit0=0 W_TX_PAYLOAD_NOACK off
  114. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_FEATURE, 0x18);
  115. // Enable RSSI
  116. *(xbuf_data + 0) = 0x10;
  117. *(xbuf_data + 1) = 0x00;
  118. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_RSSI, 2);
  119. }
  120. void XL2400_SetChannel(uint8_t channel)
  121. {
  122. if (channel > 80) channel = 80;
  123. // AFC reset
  124. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 0x06);
  125. // AFC on
  126. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 0x0E);
  127. // Frequency(MHz) 2400:0x960 -> 2480:0x9B0
  128. *(xbuf_data + 0) = 0x60 + channel;
  129. *(xbuf_data + 1) = 0x09;
  130. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, 2);
  131. // AFC Locked
  132. *(xbuf_data + 1) |= 0x20;
  133. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, 2);
  134. }
  135. void XL2400_SetTxAddress(uint8_t *address)
  136. {
  137. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_TX_ADDR, address, 5);
  138. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_ADDR_P0, address, 5);
  139. }
  140. void XL2400_SetRxAddress(uint8_t *address)
  141. {
  142. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_ADDR_P1, address, 5);
  143. }
  144. void XL2400_SetPower(uint8_t power)
  145. {
  146. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_CH, 3);
  147. *(xbuf_data + 2) = power;
  148. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, 3);
  149. }
  150. void XL2400_Sleep(void)
  151. {
  152. XL2400_CE_Low();
  153. XL2400_ClearStatus();
  154. *(xbuf_data + 0) = 0x7C;
  155. *(xbuf_data + 1) = 0x82;
  156. *(xbuf_data + 2) = 0x03;
  157. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 3);
  158. }
  159. void XL2400_WakeUp(void)
  160. {
  161. *(xbuf_data + 0) = 0x7E;
  162. *(xbuf_data + 1) = 0x82;
  163. *(xbuf_data + 2) = 0x0B;
  164. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 3);
  165. XL2400_CE_Low();
  166. XL2400_ClearStatus();
  167. }
  168. uint8_t XL2400_RxCalibrate(void)
  169. {
  170. uint8_t i, j;
  171. for (i = 0; i < 10; i++)
  172. {
  173. SYS_Delay(2);
  174. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG3, 2);
  175. *(xbuf_data + 1) |= 0x90;
  176. *(xbuf_data + 1) &= ~0x20;
  177. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, 2);
  178. *(xbuf_data + 1) |= 0x40;
  179. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, 2);
  180. SYS_Delay(1);
  181. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_FIFO_STATUS, 2);
  182. if (*(xbuf_data + 1) & 0x20)
  183. {
  184. j = *(xbuf_data + 1) << 3;
  185. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG3, 2);
  186. *(xbuf_data + 1) &= 0x8F;
  187. *(xbuf_data + 1) |= 0x20;
  188. *(xbuf_data + 0) &= 0x07;
  189. *(xbuf_data + 0) |= j;
  190. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, 2);
  191. return HAL_OK;
  192. }
  193. }
  194. return HAL_ERROR;
  195. }
  196. void XL2400_SetTxMode(void)
  197. {
  198. XL2400_CE_Low();
  199. XL2400_ClearStatus();
  200. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7E);
  201. XL2400_RxCalibrate();
  202. SYS_Delay(2);
  203. }
  204. void XL2400_SetRxMode(void)
  205. {
  206. XL2400_CE_Low();
  207. XL2400_ClearStatus();
  208. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7F);
  209. XL2400_RxCalibrate();
  210. XL2400_CE_High();
  211. SYS_Delay(1);
  212. }
  213. uint8_t XL2400_Tx(uint8_t *ucPayload, uint8_t length)
  214. {
  215. uint8_t y = 100, status = 0;
  216. XL2400_ClearStatus();
  217. XL2400_WriteFromBuf(XL2400_CMD_W_TX_PAYLOAD, ucPayload, length);
  218. XL2400_CE_High();
  219. SYS_DelayUs(100);
  220. // Retry until timeout
  221. while (y--)
  222. {
  223. SYS_DelayUs(100);
  224. status = XL2400_ReadStatus();
  225. // If TX successful or retry timeout, exit
  226. if ((status & (MAX_RT_FLAG | TX_DS_FLAG)) != 0)
  227. {
  228. break;
  229. }
  230. }
  231. XL2400_CE_Low();
  232. return status;
  233. }
  234. uint8_t XL2400_Rx(void)
  235. {
  236. uint8_t i, status, rxplWidth;
  237. status = XL2400_ReadStatus();
  238. if (status & RX_DR_FLAG)
  239. {
  240. XL2400_CE_Low();
  241. rxplWidth = XL2400_ReadReg(XL2400_CMD_R_RX_PL_WID);
  242. XL2400_ReadToBuf(XL2400_CMD_R_RX_PAYLOAD, rxplWidth);
  243. XL2400_ClearStatus();
  244. UART1_TxChar('>');
  245. for (i = 0; i < rxplWidth; i++)
  246. {
  247. UART1_TxHex(*(xbuf_data + i));
  248. }
  249. }
  250. return status;
  251. }
  252. uint8_t XL2400_ReadStatus(void)
  253. {
  254. return XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_STATUS);
  255. }
  256. void XL2400_ClearStatus(void)
  257. {
  258. XL2400_WriteReg(XL2400_CMD_FLUSH_TX, XL2400_CMD_NOP);
  259. XL2400_WriteReg(XL2400_CMD_FLUSH_RX, XL2400_CMD_NOP);
  260. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_STATUS, 0x70);
  261. }
  262. void XL2400_FlushRxTX(void)
  263. {
  264. XL2400_WriteReg(XL2400_CMD_FLUSH_TX, XL2400_CMD_NOP);
  265. XL2400_WriteReg(XL2400_CMD_FLUSH_RX, XL2400_CMD_NOP);
  266. }
  267. void XL2400_CarrierTest(void)
  268. {
  269. XL2400_CE_Low();
  270. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, 13);
  271. *(xbuf_data + 12) |= 0x40;
  272. *(xbuf_data + 4) &= ~0x04;
  273. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 13);
  274. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_TXPROC_CFG, 0x00);
  275. *(xbuf_data + 0) = 0x01;
  276. *(xbuf_data + 1) = 0x00;
  277. XL2400_WriteBack(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, 2);
  278. XL2400_ClearStatus();
  279. }
  280. uint8_t XL2400_PrintStatus(void)
  281. {
  282. uint8_t i, status;
  283. UART1_TxString("Bytes from low to high: 0,1,2,3,...\r\n[Config]");
  284. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, 3);
  285. for (i = 0; i < 3; i++) {
  286. UART1_TxHex(*(xbuf_data + i));
  287. }
  288. UART1_TxString(" [EN_AA]");
  289. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_EN_AA));
  290. UART1_TxString(" [EN_RxAddr]");
  291. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_EN_RXADDR));
  292. UART1_TxString(" [AddrWidth]");
  293. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_SETUP_AW));
  294. UART1_TxString(" [Retry]");
  295. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_SETUP_RETR, 4);
  296. for (i = 0; i < 4; i++) {
  297. UART1_TxHex(*(xbuf_data + i));
  298. }
  299. UART1_TxString("\r\n[RF_Channel]");
  300. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_CH, 3);
  301. for (i = 0; i < 3; i++) {
  302. UART1_TxHex(*(xbuf_data + i));
  303. }
  304. UART1_TxString(" [RF_Setup]");
  305. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_SETUP, 2);
  306. for (i = 0; i < 2; i++) {
  307. UART1_TxHex(*(xbuf_data + i));
  308. }
  309. UART1_TxString(" [Observe_Tx]");
  310. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_OBSERVE_TX, 4);
  311. for (i = 0; i < 4; i++) {
  312. UART1_TxHex(*(xbuf_data + i));
  313. }
  314. UART1_TxString(" [RSSI]");
  315. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RSSI, 2);
  316. for (i = 0; i < 2; i++) {
  317. UART1_TxHex(*(xbuf_data + i));
  318. }
  319. UART1_TxString("\r\n[TxAddr] ");
  320. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_TX_ADDR, 5);
  321. for (i = 0; i < 5; i++) {
  322. UART1_TxHex(*(xbuf_data + i));
  323. }
  324. UART1_TxString("\r\n[RxAddrP0]");
  325. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P0, 5);
  326. for (i = 0; i < 5; i++) {
  327. UART1_TxHex(*(xbuf_data + i));
  328. }
  329. UART1_TxString(" [RxAddrP1]");
  330. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P1, 5);
  331. for (i = 0; i < 5; i++) {
  332. UART1_TxHex(*(xbuf_data + i));
  333. }
  334. UART1_TxString(" [RxAddrP2-P5]");
  335. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P2_P5, 4);
  336. for (i = 0; i < 4; i++) {
  337. UART1_TxHex(*(xbuf_data + i));
  338. }
  339. UART1_TxString("\r\n[RxPloadWidth_P0-P5]");
  340. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_PW_PX, 6);
  341. for (i = 0; i < 6; i++) {
  342. UART1_TxHex(*(xbuf_data + i));
  343. }
  344. UART1_TxString("\r\n[FIFO_Status]");
  345. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_FIFO_STATUS, 3);
  346. for (i = 0; i < 3; i++) {
  347. UART1_TxHex(*(xbuf_data + i));
  348. }
  349. UART1_TxString(" [DynPloadWidth]");
  350. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_DYNPD));
  351. UART1_TxString(" [Feature]");
  352. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_FEATURE));
  353. status = XL2400_ReadStatus();
  354. UART1_TxString("\r\n[Status]");
  355. UART1_TxHex(status);
  356. UART1_TxString("\r\n\r\n");
  357. return status;
  358. }