| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- // Copyright 2021 IOsetting <iosetting(at)outlook.com>
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "xl2400.h"
- __IDATA uint8_t cbuf[2], xbuf[XL2400_PL_WIDTH_MAX + 1];
- /**
- * Emulate SPI Write on GPIO pins
- */
- void XL2400_WriteByte(uint8_t value)
- {
- uint8_t i = 0;
- XL2400_CLK_LOW();
- XL2400_DATA_OUT();
- for (i = 0; i < 8; i++)
- {
- XL2400_CLK_LOW();
- if (value & 0x80)
- {
- XL2400_DATA_HIGH();
- }
- else
- {
- XL2400_DATA_LOW();
- }
- XL2400_CLK_HIGH();
- value = value << 1;
- }
- XL2400_CLK_LOW();
- }
- /**
- * Emulate SPI Read on GPIO pins
- */
- uint8_t XL2400_ReadByte(void)
- {
- uint8_t i = 0, RxData;
- XL2400_DATA_IN();
- XL2400_CLK_LOW();
- for (i = 0; i < 8; i++)
- {
- RxData = RxData << 1;
- XL2400_CLK_HIGH();
- if (XL2400_DATA_READ())
- {
- RxData |= 0x01;
- }
- else
- {
- RxData &= 0xfe;
- }
- XL2400_CLK_LOW();
- }
- XL2400_CLK_LOW();
- return RxData;
- }
- void XL2400_WriteReg(uint8_t reg,uint8_t value)
- {
- XL2400_NSS_LOW();
- XL2400_WriteByte(reg);
- XL2400_WriteByte(value);
- XL2400_NSS_HIGH();
- }
- uint8_t XL2400_ReadReg(uint8_t reg)
- {
- uint8_t reg_val;
- XL2400_NSS_LOW();
- XL2400_WriteByte(reg);
- reg_val = XL2400_ReadByte();
- XL2400_NSS_HIGH();
- return reg_val;
- }
- void XL2400_WriteFromBuf(uint8_t reg, const uint8_t *pBuf, uint8_t len)
- {
- uint8_t ctr;
- XL2400_NSS_LOW();
- XL2400_WriteByte(reg);
- for (ctr = 0; ctr < len; ctr++)
- {
- XL2400_WriteByte(*pBuf++);
- }
- XL2400_NSS_HIGH();
- }
- void XL2400_ReadToBuf(uint8_t reg, uint8_t *pBuf, uint8_t len)
- {
- uint8_t ctr;
- XL2400_NSS_LOW();
- XL2400_WriteByte(reg);
- for (ctr = 0; ctr < len; ctr++)
- {
- pBuf[ctr] = XL2400_ReadByte();
- }
- XL2400_NSS_HIGH();
- }
- void XL2400_CE_Low(void)
- {
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
- *(cbuf + 1) &= 0xBF;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
- }
- void XL2400_CE_High(void)
- {
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
- *(cbuf + 1) |= 0x40;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
- }
- uint8_t XL2400_SPI_Test(void)
- {
- uint8_t i;
- const uint8_t *ptr = (const uint8_t *)XL2400_TEST_ADDR;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_TX_ADDR, ptr, 5);
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_TX_ADDR, xbuf, 5);
- for (i = 0; i < 5; i++) {
- UART1_TxHex(*(xbuf + i));
- if (*(xbuf + i) != *ptr++) return HAL_ERROR;
- }
- return HAL_OK;
- }
- void XL2400_Init(void)
- {
- // Analog config
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
- *(xbuf + 4) &= ~0x04;
- *(xbuf + 12) |= 0x40;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
- // Switch to software CE control, wake up RF
- XL2400_WakeUp();
- // Enable Auto ACK Pipe 0
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_AA, 0x3F);
- // Enable Pipe 0
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_RXADDR, 0x3F);
- // Address Width, 5 bytes
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_AW, 0xAF);
- // Retries and interval
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_RETR, 0x33);
- // RF Data Rate 1Mbps
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, 0x22);
- // Number of bytes in RX payload, pipe 0 and pipe 1
- *(cbuf + 0) = XL2400_PLOAD_WIDTH;
- *(cbuf + 1) = XL2400_PLOAD_WIDTH;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_PW_PX, cbuf, 2);
- // Dynamic payload width: off
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_DYNPD, 0x00);
- // Other features
- //bit7&6=00 return status when send register address
- //bit5=0 long data pack off
- //bit4=1 FEC off
- //bit3=1 FEATURE on
- //bit2=0 Dynamic length off
- //bit1=0 ACK without payload
- //bit0=0 W_TX_PAYLOAD_NOACK off
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_FEATURE, 0x18);
- // Enable RSSI
- *(cbuf + 0) = 0x10;
- *(cbuf + 1) = 0x00;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RSSI, cbuf, 2);
- }
- void XL2400_SetChannel(uint8_t channel)
- {
- if (channel > 80) channel = 80;
- // AFC reset
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 0x06);
- // AFC on
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, 0x0E);
- // Frequency(MHz) 2400:0x960 -> 2480:0x9B0
- *(cbuf + 0) = 0x60 + channel;
- *(cbuf + 1) = 0x09;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, cbuf, 2);
- // AFC Locked
- *(cbuf + 1) |= 0x20;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, cbuf, 2);
- }
- void XL2400_SetTxAddress(uint8_t *address)
- {
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_TX_ADDR, address, 5);
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_ADDR_P0, address, 5);
- }
- void XL2400_SetRxAddress(uint8_t *address)
- {
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_ADDR_P1, address, 5);
- }
- void XL2400_SetPower(uint8_t power)
- {
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_CH, xbuf, 3);
- *(xbuf + 2) = power;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_CH, xbuf, 3);
- }
- void XL2400_Sleep(void)
- {
- XL2400_CE_Low();
- XL2400_ClearStatus();
- *(xbuf + 0) = 0x7C;
- *(xbuf + 1) = 0x82;
- *(xbuf + 2) = 0x03;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, xbuf, 3);
- }
- void XL2400_WakeUp(void)
- {
- *(xbuf + 0) = 0x7E;
- *(xbuf + 1) = 0x82;
- *(xbuf + 2) = 0x0B;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, xbuf, 3);
- XL2400_CE_Low();
- XL2400_ClearStatus();
- }
- uint8_t XL2400_RxCalibrate(void)
- {
- uint8_t i, j;
- for (i = 0; i < 10; i++)
- {
- SYS_Delay(2);
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
- *(cbuf + 1) |= 0x90;
- *(cbuf + 1) &= ~0x20;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
- *(cbuf + 1) |= 0x40;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
- SYS_Delay(1);
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_FIFO_STATUS, cbuf, 2);
- if (*(cbuf + 1) & 0x20)
- {
- j = *(cbuf + 1) << 3;
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
- *(cbuf + 1) &= 0x8F;
- *(cbuf + 1) |= 0x20;
- *(cbuf + 0) &= 0x07;
- *(cbuf + 0) |= j;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG3, cbuf, 2);
- return HAL_OK;
- }
- }
- return HAL_ERROR;
- }
- void XL2400_SetTxMode(void)
- {
- XL2400_CE_Low();
- XL2400_ClearStatus();
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7E);
- XL2400_RxCalibrate();
- SYS_Delay(2);
- }
- void XL2400_SetRxMode(void)
- {
- XL2400_CE_Low();
- XL2400_ClearStatus();
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7F);
- // XL2400_RxCalibrate();
- XL2400_CE_High();
- SYS_Delay(1);
- }
- uint8_t XL2400_Tx(uint8_t *ucPayload, uint8_t length)
- {
- uint8_t y = 100, status = 0;
- XL2400_ClearStatus();
- XL2400_WriteFromBuf(XL2400_CMD_W_TX_PAYLOAD, ucPayload, length);
- XL2400_CE_High();
- // Retry until timeout
- while (y--)
- {
- SYS_DelayUs(100);
- status = XL2400_ReadStatus();
- // If TX successful or retry timeout, exit
- if ((status & (MAX_RT_FLAG | TX_DS_FLAG)) != 0)
- {
- break;
- }
- }
- XL2400_CE_Low();
- return status;
- }
- uint8_t XL2400_Rx(void)
- {
- uint8_t i, status, rxplWidth;
- status = XL2400_ReadStatus();
- if (status & RX_DR_FLAG)
- {
- XL2400_CE_Low();
- rxplWidth = XL2400_ReadReg(XL2400_CMD_R_RX_PL_WID);
- XL2400_ReadToBuf(XL2400_CMD_R_RX_PAYLOAD, xbuf, rxplWidth);
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_STATUS, status);
- // UART1_TxChar('>');
- // for (i = 0; i < rxplWidth; i++)
- // {
- // UART1_TxHex(*(xbuf + i));
- // }
- }
- return status;
- }
- uint8_t XL2400_ReadStatus(void)
- {
- return XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_STATUS);
- }
- void XL2400_ClearStatus(void)
- {
- XL2400_WriteReg(XL2400_CMD_FLUSH_TX, XL2400_CMD_NOP);
- XL2400_WriteReg(XL2400_CMD_FLUSH_RX, XL2400_CMD_NOP);
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_STATUS, 0x70);
- }
- void XL2400_FlushRxTX(void)
- {
- XL2400_WriteReg(XL2400_CMD_FLUSH_TX, XL2400_CMD_NOP);
- XL2400_WriteReg(XL2400_CMD_FLUSH_RX, XL2400_CMD_NOP);
- }
- void XL2400_CarrierTest(void)
- {
- XL2400_CE_Low();
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
- *(xbuf + 12) |= 0x40;
- *(xbuf + 4) &= ~0x04;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
- XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_TXPROC_CFG, 0x00);
- *(xbuf + 0) = 0x01;
- *(xbuf + 1) = 0x00;
- XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, xbuf, 2);
- XL2400_ClearStatus();
- }
- uint8_t XL2400_PrintStatus(void)
- {
- uint8_t i, status;
- UART1_TxString("Bytes from low to high: 0,1,2,3,...\r\n[Config]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, xbuf, 3);
- for (i = 0; i < 3; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [EN_AA]");
- UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_EN_AA));
- UART1_TxString(" [EN_RxAddr]");
- UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_EN_RXADDR));
- UART1_TxString(" [AddrWidth]");
- UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_SETUP_AW));
- UART1_TxString(" [Retry]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_SETUP_RETR, xbuf, 4);
- for (i = 0; i < 4; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString("\r\n[RF_Channel]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_CH, xbuf, 3);
- for (i = 0; i < 3; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [RF_Setup]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RF_SETUP, xbuf, 2);
- for (i = 0; i < 2; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [Observe_Tx]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_OBSERVE_TX, xbuf, 4);
- for (i = 0; i < 4; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [RSSI]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RSSI, xbuf, 2);
- for (i = 0; i < 2; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString("\r\n[TxAddr] ");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_TX_ADDR, xbuf, 5);
- for (i = 0; i < 5; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString("\r\n[RxAddrP0]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P0, xbuf, 5);
- for (i = 0; i < 5; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [RxAddrP1]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P1, xbuf, 5);
- for (i = 0; i < 5; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [RxAddrP2-P5]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_ADDR_P2_P5, xbuf, 4);
- for (i = 0; i < 4; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString("\r\n[RxPloadWidth_P0-P5]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_RX_PW_PX, xbuf, 6);
- for (i = 0; i < 6; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString("\r\n[FIFO_Status]");
- XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_FIFO_STATUS, xbuf, 3);
- for (i = 0; i < 3; i++) {
- UART1_TxHex(*(xbuf + i));
- }
- UART1_TxString(" [DynPloadWidth]");
- UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_DYNPD));
- UART1_TxString(" [Feature]");
- UART1_TxHex(XL2400_ReadReg(XL2400_CMD_R_REGISTER | XL2400_REG_FEATURE));
- status = XL2400_ReadStatus();
- UART1_TxString("\r\n[Status]");
- UART1_TxHex(status);
- UART1_TxString("\r\n\r\n");
- return status;
- }
|