xl2400.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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. /**
  17. * Emulate SPI Write on GPIO pins
  18. */
  19. void XL2400_WriteByte(uint8_t value)
  20. {
  21. uint8_t i = 0;
  22. XL2400_CLK_LOW();
  23. XL2400_DATA_OUT();
  24. for (i = 0; i < 8; i++)
  25. {
  26. XL2400_CLK_LOW();
  27. if (value & 0x80)
  28. {
  29. XL2400_DATA_HIGH();
  30. }
  31. else
  32. {
  33. XL2400_DATA_LOW();
  34. }
  35. XL2400_CLK_HIGH();
  36. value = value << 1;
  37. }
  38. XL2400_CLK_LOW();
  39. }
  40. /**
  41. * Emulate SPI Read on GPIO pins
  42. */
  43. uint8_t XL2400_ReadByte(void)
  44. {
  45. uint8_t i = 0, RxData;
  46. XL2400_DATA_IN();
  47. XL2400_CLK_LOW();
  48. for (i = 0; i < 8; i++)
  49. {
  50. RxData = RxData << 1;
  51. XL2400_CLK_HIGH();
  52. if (XL2400_DATA_READ())
  53. {
  54. RxData |= 0x01;
  55. }
  56. else
  57. {
  58. RxData &= 0xfe;
  59. }
  60. XL2400_CLK_LOW();
  61. }
  62. XL2400_CLK_LOW();
  63. return RxData;
  64. }
  65. void XL2400_WriteReg(uint8_t reg,uint8_t value)
  66. {
  67. XL2400_NSS_LOW();
  68. XL2400_WriteByte(reg);
  69. XL2400_WriteByte(value);
  70. XL2400_NSS_HIGH();
  71. }
  72. uint8_t XL2400_ReadReg(uint8_t reg)
  73. {
  74. uint8_t reg_val;
  75. XL2400_NSS_LOW();
  76. XL2400_WriteByte(reg);
  77. reg_val = XL2400_ReadByte();
  78. XL2400_NSS_HIGH();
  79. return reg_val;
  80. }
  81. void XL2400_WriteFromBuf(uint8_t reg, const uint8_t *pBuf, uint8_t len)
  82. {
  83. uint8_t ctr;
  84. XL2400_NSS_LOW();
  85. XL2400_WriteByte(reg);
  86. for (ctr = 0; ctr < len; ctr++)
  87. {
  88. XL2400_WriteByte(*pBuf++);
  89. }
  90. XL2400_NSS_HIGH();
  91. }
  92. void XL2400_ReadToBuf(uint8_t reg, uint8_t *pBuf, uint8_t len)
  93. {
  94. uint8_t ctr;
  95. XL2400_NSS_LOW();
  96. XL2400_WriteByte(reg);
  97. for (ctr = 0; ctr < len; ctr++)
  98. {
  99. pBuf[ctr] = XL2400_ReadByte();
  100. }
  101. XL2400_NSS_HIGH();
  102. }
  103. void XL2400_CE_Low(void)
  104. {
  105. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
  106. *(cbuf + 1) &= 0xBF;
  107. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
  108. }
  109. void XL2400_CE_High(void)
  110. {
  111. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
  112. *(cbuf + 1) |= 0x40;
  113. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
  114. }
  115. uint8_t XL2400_SPI_Test(void)
  116. {
  117. uint8_t i;
  118. const uint8_t *ptr = (const uint8_t *)XL2400_TEST_ADDR;
  119. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_TX_ADDR, ptr, 5);
  120. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_TX_ADDR, xbuf, 5);
  121. for (i = 0; i < 5; i++) {
  122. UART1_TxHex(*(xbuf + i));
  123. if (*(xbuf + i) != *ptr++) return HAL_ERROR;
  124. }
  125. return HAL_OK;
  126. }
  127. void XL2400_Init(void)
  128. {
  129. // Analog config
  130. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
  131. *(xbuf + 4) &= ~0x04;
  132. *(xbuf + 12) |= 0x40;
  133. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
  134. // Switch to software CE control, wake up RF
  135. XL2400_WakeUp();
  136. // Enable Auto ACK Pipe 0
  137. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_AA, 0x3F);
  138. // Enable Pipe 0
  139. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_RXADDR, 0x3F);
  140. // Address Width, 5 bytes
  141. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_AW, 0xAF);
  142. // Retries and interval
  143. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_RETR, 0x33);
  144. // RF Data Rate 1Mbps
  145. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, 0x22);
  146. // Number of bytes in RX payload, pipe 0 and pipe 1
  147. *(cbuf + 0) = XL2400_PLOAD_WIDTH;
  148. *(cbuf + 1) = XL2400_PLOAD_WIDTH;
  149. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_PW_PX, cbuf, 2);
  150. // Dynamic payload width: off
  151. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_DYNPD, 0x00);
  152. // Other features
  153. //bit7&6=00 return status when send register address
  154. //bit5=0 long data pack off
  155. //bit4=1 FEC off
  156. //bit3=1 FEATURE on
  157. //bit2=0 Dynamic length off
  158. //bit1=0 ACK without payload
  159. //bit0=0 W_TX_PAYLOAD_NOACK off
  160. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_FEATURE, 0x18);
  161. // Enable RSSI
  162. *(cbuf + 0) = 0x10;
  163. *(cbuf + 1) = 0x00;
  164. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RSSI, cbuf, 2);
  165. }
  166. void XL2400_SetChannel(uint8_t channel)
  167. {
  168. if (channel > 80) channel = 80;
  169. // AFC reset
  170. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 0x06);
  171. // AFC on
  172. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 0x0E);
  173. // Frequency(MHz) 2400:0x960 -> 2480:0x9B0
  174. *(cbuf + 0) = 0x60 + channel;
  175. *(cbuf + 1) = 0x09;
  176. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, cbuf, 2);
  177. // AFC Locked
  178. *(cbuf + 1) |= 0x20;
  179. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, cbuf, 2);
  180. }
  181. void XL2400_SetTxAddress(uint8_t *address)
  182. {
  183. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_TX_ADDR, address, 5);
  184. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_ADDR_P0, address, 5);
  185. }
  186. void XL2400_SetRxAddress(uint8_t *address)
  187. {
  188. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_ADDR_P1, address, 5);
  189. }
  190. void XL2400_SetPower(uint8_t power)
  191. {
  192. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_CH, xbuf, 3);
  193. *(xbuf + 2) = power;
  194. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, xbuf, 3);
  195. }
  196. void XL2400_Sleep(void)
  197. {
  198. XL2400_CE_Low();
  199. XL2400_ClearStatus();
  200. *(xbuf + 0) = 0x7C;
  201. *(xbuf + 1) = 0x82;
  202. *(xbuf + 2) = 0x03;
  203. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, xbuf, 3);
  204. }
  205. void XL2400_WakeUp(void)
  206. {
  207. *(xbuf + 0) = 0x7E;
  208. *(xbuf + 1) = 0x82;
  209. *(xbuf + 2) = 0x0B;
  210. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, xbuf, 3);
  211. XL2400_CE_Low();
  212. XL2400_ClearStatus();
  213. }
  214. uint8_t XL2400_RxCalibrate(void)
  215. {
  216. uint8_t i, j;
  217. for (i = 0; i < 10; i++)
  218. {
  219. SYS_Delay(2);
  220. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
  221. *(cbuf + 1) |= 0x90;
  222. *(cbuf + 1) &= ~0x20;
  223. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
  224. *(cbuf + 1) |= 0x40;
  225. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
  226. SYS_Delay(1);
  227. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_FIFO_STATUS, cbuf, 2);
  228. if (*(cbuf + 1) & 0x20)
  229. {
  230. j = *(cbuf + 1) << 3;
  231. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
  232. *(cbuf + 1) &= 0x8F;
  233. *(cbuf + 1) |= 0x20;
  234. *(cbuf + 0) &= 0x07;
  235. *(cbuf + 0) |= j;
  236. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
  237. return HAL_OK;
  238. }
  239. }
  240. return HAL_ERROR;
  241. }
  242. void XL2400_SetTxMode(void)
  243. {
  244. XL2400_CE_Low();
  245. XL2400_ClearStatus();
  246. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7E);
  247. XL2400_RxCalibrate();
  248. SYS_Delay(2);
  249. }
  250. void XL2400_SetRxMode(void)
  251. {
  252. XL2400_CE_Low();
  253. XL2400_ClearStatus();
  254. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7F);
  255. // XL2400_RxCalibrate();
  256. XL2400_CE_High();
  257. SYS_Delay(1);
  258. }
  259. uint8_t XL2400_Tx(uint8_t *ucPayload, uint8_t length)
  260. {
  261. uint8_t y = 100, status = 0;
  262. XL2400_ClearStatus();
  263. XL2400_WriteFromBuf(XL2400_CMD_W_TX_PAYLOAD, ucPayload, length);
  264. XL2400_CE_High();
  265. // Retry until timeout
  266. while (y--)
  267. {
  268. SYS_DelayUs(100);
  269. status = XL2400_ReadStatus();
  270. // If TX successful or retry timeout, exit
  271. if ((status & (MAX_RT_FLAG | TX_DS_FLAG)) != 0)
  272. {
  273. break;
  274. }
  275. }
  276. XL2400_CE_Low();
  277. return status;
  278. }
  279. uint8_t XL2400_Rx(void)
  280. {
  281. uint8_t i, status, rxplWidth;
  282. status = XL2400_ReadStatus();
  283. if (status & RX_DR_FLAG)
  284. {
  285. XL2400_CE_Low();
  286. rxplWidth = XL2400_ReadReg(XL2400_CMD_R_RX_PL_WID);
  287. XL2400_ReadToBuf(XL2400_CMD_R_RX_PAYLOAD, xbuf, rxplWidth);
  288. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_STATUS, status);
  289. // UART1_TxChar('>');
  290. // for (i = 0; i < rxplWidth; i++)
  291. // {
  292. // UART1_TxHex(*(xbuf + i));
  293. // }
  294. }
  295. return status;
  296. }
  297. uint8_t XL2400_ReadStatus(void)
  298. {
  299. return XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_STATUS);
  300. }
  301. void XL2400_ClearStatus(void)
  302. {
  303. XL2400_WriteReg(XL2400_CMD_FLUSH_TX, XL2400_CMD_NOP);
  304. XL2400_WriteReg(XL2400_CMD_FLUSH_RX, XL2400_CMD_NOP);
  305. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_STATUS, 0x70);
  306. }
  307. void XL2400_FlushRxTX(void)
  308. {
  309. XL2400_WriteReg(XL2400_CMD_FLUSH_TX, XL2400_CMD_NOP);
  310. XL2400_WriteReg(XL2400_CMD_FLUSH_RX, XL2400_CMD_NOP);
  311. }
  312. void XL2400_CarrierTest(void)
  313. {
  314. XL2400_CE_Low();
  315. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
  316. *(xbuf + 12) |= 0x40;
  317. *(xbuf + 4) &= ~0x04;
  318. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
  319. XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_TXPROC_CFG, 0x00);
  320. *(xbuf + 0) = 0x01;
  321. *(xbuf + 1) = 0x00;
  322. XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, xbuf, 2);
  323. XL2400_ClearStatus();
  324. }
  325. uint8_t XL2400_PrintStatus(void)
  326. {
  327. uint8_t i, status;
  328. UART1_TxString("Bytes from low to high: 0,1,2,3,...\r\n[Config]");
  329. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, xbuf, 3);
  330. for (i = 0; i < 3; i++) {
  331. UART1_TxHex(*(xbuf + i));
  332. }
  333. UART1_TxString(" [EN_AA]");
  334. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_EN_AA));
  335. UART1_TxString(" [EN_RxAddr]");
  336. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_EN_RXADDR));
  337. UART1_TxString(" [AddrWidth]");
  338. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_SETUP_AW));
  339. UART1_TxString(" [Retry]");
  340. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_SETUP_RETR, xbuf, 4);
  341. for (i = 0; i < 4; i++) {
  342. UART1_TxHex(*(xbuf + i));
  343. }
  344. UART1_TxString("\r\n[RF_Channel]");
  345. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_CH, xbuf, 3);
  346. for (i = 0; i < 3; i++) {
  347. UART1_TxHex(*(xbuf + i));
  348. }
  349. UART1_TxString(" [RF_Setup]");
  350. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_SETUP, xbuf, 2);
  351. for (i = 0; i < 2; i++) {
  352. UART1_TxHex(*(xbuf + i));
  353. }
  354. UART1_TxString(" [Observe_Tx]");
  355. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_OBSERVE_TX, xbuf, 4);
  356. for (i = 0; i < 4; i++) {
  357. UART1_TxHex(*(xbuf + i));
  358. }
  359. UART1_TxString(" [RSSI]");
  360. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RSSI, xbuf, 2);
  361. for (i = 0; i < 2; i++) {
  362. UART1_TxHex(*(xbuf + i));
  363. }
  364. UART1_TxString("\r\n[TxAddr] ");
  365. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_TX_ADDR, xbuf, 5);
  366. for (i = 0; i < 5; i++) {
  367. UART1_TxHex(*(xbuf + i));
  368. }
  369. UART1_TxString("\r\n[RxAddrP0]");
  370. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P0, xbuf, 5);
  371. for (i = 0; i < 5; i++) {
  372. UART1_TxHex(*(xbuf + i));
  373. }
  374. UART1_TxString(" [RxAddrP1]");
  375. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P1, xbuf, 5);
  376. for (i = 0; i < 5; i++) {
  377. UART1_TxHex(*(xbuf + i));
  378. }
  379. UART1_TxString(" [RxAddrP2-P5]");
  380. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P2_P5, xbuf, 4);
  381. for (i = 0; i < 4; i++) {
  382. UART1_TxHex(*(xbuf + i));
  383. }
  384. UART1_TxString("\r\n[RxPloadWidth_P0-P5]");
  385. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_PW_PX, xbuf, 6);
  386. for (i = 0; i < 6; i++) {
  387. UART1_TxHex(*(xbuf + i));
  388. }
  389. UART1_TxString("\r\n[FIFO_Status]");
  390. XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_FIFO_STATUS, xbuf, 3);
  391. for (i = 0; i < 3; i++) {
  392. UART1_TxHex(*(xbuf + i));
  393. }
  394. UART1_TxString(" [DynPloadWidth]");
  395. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_DYNPD));
  396. UART1_TxString(" [Feature]");
  397. UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_FEATURE));
  398. status = XL2400_ReadStatus();
  399. UART1_TxString("\r\n[Status]");
  400. UART1_TxHex(status);
  401. UART1_TxString("\r\n\r\n");
  402. return status;
  403. }