I have a CC1101-based design that sniffs network traffic coming from some low-power motes. My sniffer device needs to stay in Rx mode forever except for sending some wireless commands. The following are the read/write functions:
/**
* sendData
*
* Send data packet via RF
*
* 'packet' Packet to be transmitted
*
* Return:
* True if the transmission succeeds
* False otherwise
*/
boolean CC1101::sendData(CCPACKET packet)
{
byte marcState;
// Enter RX state
setRxState();
// Check that the RX state has been entered
while ((readStatusReg(CC1101_MARCSTATE) & 0x1F) != 0x0D)
delay(1);
delayMicroseconds(500);
// Set data length at the first position of the TX FIFO
writeReg(CC1101_TXFIFO, packet.length);
// Write data into the TX FIFO
writeBurstReg(CC1101_TXFIFO, packet.data, packet.length);
// CCA enabled: will enter TX state only if the channel is clear
//cmdStrobe(CC1101_STX);
setTxState();
// Check that TX state is being entered (state = RXTX_SETTLING)
marcState = readStatusReg(CC1101_MARCSTATE) & 0x1F;
if((marcState != 0x13) && (marcState != 0x14) && (marcState != 0x15))
{
setIdleState(); // Enter IDLE state
flushTxFifo(); // Flush Tx FIFO
setRxState(); // Back to RX state
return false;
}
// Wait for the sync word to be transmitted
wait_GDO0_high();
// Wait until the end of the packet transmission
wait_GDO0_low();
// Enter back into RX state
setRxState();
// Check that the TX FIFO is empty
if((readStatusReg(CC1101_TXBYTES) & 0x7F) == 0)
return true;
return false;
}
/**
* receiveData
*
* Read data packet from RX FIFO
*
* 'packet' Container for the packet received
*
* Return:
* Amount of bytes received
*/
byte CC1101::receiveData(CCPACKET * packet)
{
byte val;
// Rx FIFO overflow?
if ((readStatusReg(CC1101_MARCSTATE) & 0x1F) == 0x11)
{
setIdleState(); // Enter IDLE state
flushRxFifo(); // Flush Rx FIFO
packet->length = 0;
}
// Any byte waiting to be read?
else if (readStatusReg(CC1101_RXBYTES) & 0x7F)
{
// Read data length
packet->length = readConfigReg(CC1101_RXFIFO);
// If packet is too long
if (packet->length > CC1101_DATA_LEN)
packet->length = 0; // Discard packet
else
{
// Read data packet
readBurstReg(packet->data, CC1101_RXFIFO, packet->length);
// Read RSSI
packet->rssi = readConfigReg(CC1101_RXFIFO);
// Read LQI and CRC_OK
val = readConfigReg(CC1101_RXFIFO);
packet->lqi = val & 0x7F;
packet->crc_ok = bitRead(val, 7);
}
}
else
packet->length = 0;
// Back to RX state
setRxState();
return packet->length;
}
Everything starts working as expected. My device receives wireless packets and transmits commands without problems. However, after some hours without transmitting, my device stops receiving packets. I've checked multiple times that, when the problem occurs, this device is still in reception mode (MARCSTATE = 0x0D) and RXBYTES > 0 (and not overflowed) so I don't really know what could be happening. I've noted however that transmitting a packet (above senData function) takes the CC1101 IC out from the locked state, so it becomes immediately able to receive packets again.
As a side note, before the locking problem, my device is frequently entering the "Rx FIFO overflow" state, maybe due to local wireless traffic coming from some unknown devices. Nevertheless, "receiveData" always flushes the FIFO when the overflow occurs. Mizanur Chowdhury from TI has suggested me a couple of things (thanks Mizanur!):
1. Check for a possible calibration-related problem. I need to say that MCSM0.FS_AUTOCAL = 1 for this device so calibration should be performed automatically when going from IDLE to RX or TX.
2. Check for the RX_FIFO Overflow issue described in errata note:http://www.ti.com/lit/er/swrz020b/swrz020b.pdf
Well, I've checked both the above possibilites but running periodic calibrations (SCAL strobe) and flushing the RXFIFO after each reception do not solve the problem. Only sending a packet unlocks the CC1101 from its uncertain passive state so if I find myself unable to solve the problem I'm thinking in sending a heartbeat packet periodically as a way to prevent the CC1101 IC from get blocked on the reception side forever. But before doing this workaround I'd like to get some feedback from this community.
Thank you very much for your ideas!