knx/src/knx/rf_physical_layer_cc1101.cpp
2021-02-08 20:54:49 +01:00

757 lines
30 KiB
C++

#ifndef DeviceFamily_CC13X0
#include "config.h"
#ifdef USE_RF
#include "rf_physical_layer_cc1101.h"
#include "rf_data_link_layer.h"
#include "bits.h"
#include "platform.h"
#include <stdio.h>
#include <string.h>
// Table for encoding 4-bit data into a 8-bit Manchester encoding.
const uint8_t RfPhysicalLayerCC1101::manchEncodeTab[16] = {0xAA, // 0x0 Manchester encoded
0xA9, // 0x1 Manchester encoded
0xA6, // 0x2 Manchester encoded
0xA5, // 0x3 Manchester encoded
0x9A, // 0x4 Manchester encoded
0x99, // 0x5 Manchester encoded
0x96, // 0x6 Manchester encoded
0x95, // 0x7 Manchester encoded
0x6A, // 0x8 Manchester encoded
0x69, // 0x9 Manchester encoded
0x66, // 0xA Manchester encoded
0x65, // 0xB Manchester encoded
0x5A, // 0xC Manchester encoded
0x59, // 0xD Manchester encoded
0x56, // 0xE Manchester encoded
0x55}; // 0xF Manchester encoded
// Table for decoding 4-bit Manchester encoded data into 2-bit
// data. 0xFF indicates invalid Manchester encoding
const uint8_t RfPhysicalLayerCC1101::manchDecodeTab[16] = {0xFF, // Manchester encoded 0x0 decoded
0xFF, // Manchester encoded 0x1 decoded
0xFF, // Manchester encoded 0x2 decoded
0xFF, // Manchester encoded 0x3 decoded
0xFF, // Manchester encoded 0x4 decoded
0x03, // Manchester encoded 0x5 decoded
0x02, // Manchester encoded 0x6 decoded
0xFF, // Manchester encoded 0x7 decoded
0xFF, // Manchester encoded 0x8 decoded
0x01, // Manchester encoded 0x9 decoded
0x00, // Manchester encoded 0xA decoded
0xFF, // Manchester encoded 0xB decoded
0xFF, // Manchester encoded 0xC decoded
0xFF, // Manchester encoded 0xD decoded
0xFF, // Manchester encoded 0xE decoded
0xFF};// Manchester encoded 0xF decoded
// Product = CC1101
// Chip version = A (VERSION = 0x04)
// Crystal accuracy = 10 ppm
// X-tal frequency = 26 MHz
// RF output power = + 10 dBm
// RX filterbandwidth = 270 kHz
// Deviation = 47 kHz
// Datarate = 32.73 kBaud
// Modulation = (0) 2-FSK
// Manchester enable = (0) Manchester disabled
// RF Frequency = 868.299866 MHz
// Channel spacing = 199.951172 kHz
// Channel number = 0
// Optimization = -
// Sync mode = (5) 15/16 + carrier-sense above threshold
// Format of RX/TX data = (0) Normal mode, use FIFOs for RX and TX
// CRC operation = (0) CRC disabled for TX and RX
// Forward Error Correction = (0) FEC disabled
// Length configuration = (0) Fixed length packets, length configured in PKTLEN register.
// Packetlength = 255
// Preamble count = (2) 4 bytes
// Append status = 0
// Address check = (0) No address check
// FIFO autoflush = 0
// Device address = 0
// GDO0 signal selection = ( 6) Asserts when sync word has been sent / received, and de-asserts at the end of the packet
// GDO2 signal selection = ( 0) Asserts when RX FiFO threshold
const uint8_t RfPhysicalLayerCC1101::cc1101_2FSK_32_7_kb[CFG_REGISTER] = {
0x00, // IOCFG2 GDO2 Output Pin Configuration
0x2E, // IOCFG1 GDO1 Output Pin Configuration
0x06, // IOCFG0 GDO0 Output Pin Configuration
0x40, // FIFOTHR RX FIFO and TX FIFO Thresholds // 4 bytes in RX FIFO (2 bytes manchester encoded)
0x76, // SYNC1 Sync Word
0x96, // SYNC0 Sync Word
0xFF, // PKTLEN Packet Length
0x00, // PKTCTRL1 Packet Automation Control
0x00, // PKTCTRL0 Packet Automation Control
0x00, // ADDR Device Address
0x00, // CHANNR Channel Number
0x08, // FSCTRL1 Frequency Synthesizer Control
0x00, // FSCTRL0 Frequency Synthesizer Control
0x21, // FREQ2 Frequency Control Word
0x65, // FREQ1 Frequency Control Word
0x6A, // FREQ0 Frequency Control Word
0x6A, // MDMCFG4 Modem Configuration
0x4A, // MDMCFG3 Modem Configuration
0x05, // MDMCFG2 Modem Configuration
0x22, // MDMCFG1 Modem Configuration
0xF8, // MDMCFG0 Modem Configuration
0x47, // DEVIATN Modem Deviation Setting
0x07, // MCSM2 Main Radio Control State Machine Configuration
0x30, // MCSM1 Main Radio Control State Machine Configuration (IDLE after TX and RX)
0x18, // MCSM0 Main Radio Control State Machine Configuration
0x2E, // FOCCFG Frequency Offset Compensation Configuration
0x6D, // BSCFG Bit Synchronization Configuration
0x43, // AGCCTRL2 AGC Control 0x04, // AGCCTRL2 magn target 33dB vs 36dB (max LNA+LNA2 gain vs. ) (highest gain cannot be used vs. all gain settings)
0x40, // AGCCTRL1 AGC Control 0x09, // AGCCTRL1 carrier sense threshold disabled vs. 7dB below magn target (LNA prio strat. 1 vs 0)
0x91, // AGCCTRL0 AGC Control 0xB2, // AGCCTRL0 channel filter samples 16 vs.32
0x87, // WOREVT1 High Byte Event0 Timeout
0x6B, // WOREVT0 Low Byte Event0 Timeout
0xFB, // WORCTRL Wake On Radio Control
0xB6, // FREND1 Front End RX Configuration
0x10, // FREND0 Front End TX Configuration
0xE9, // FSCAL3 Frequency Synthesizer Calibration 0xEA, // FSCAL3
0x2A, // FSCAL2 Frequency Synthesizer Calibration
0x00, // FSCAL1 Frequency Synthesizer Calibration
0x1F, // FSCAL0 Frequency Synthesizer Calibration
0x41, // RCCTRL1 RC Oscillator Configuration
0x00, // RCCTRL0 RC Oscillator Configuration
0x59, // FSTEST Frequency Synthesizer Calibration Control
0x7F, // PTEST Production Test
0x3F, // AGCTEST AGC Test
0x81, // TEST2 Various Test Settings
0x35, // TEST1 Various Test Settings
0x09 // TEST0 Various Test Settings
};
//Patable index: -30 -20- -15 -10 0 5 7 10 dBm
const uint8_t RfPhysicalLayerCC1101::paTablePower868[8] = {0x03,0x17,0x1D,0x26,0x50,0x86,0xCD,0xC0};
RfPhysicalLayerCC1101::RfPhysicalLayerCC1101(RfDataLinkLayer& rfDataLinkLayer, Platform& platform)
: RfPhysicalLayer(rfDataLinkLayer, platform)
{
}
void RfPhysicalLayerCC1101::manchEncode(uint8_t *uncodedData, uint8_t *encodedData)
{
uint8_t data0, data1;
// - Shift to get 4-bit data values
data1 = (((*uncodedData) >> 4) & 0x0F);
data0 = ((*uncodedData) & 0x0F);
// - Perform Manchester encoding -
*encodedData = (manchEncodeTab[data1]);
*(encodedData + 1) = manchEncodeTab[data0];
}
bool RfPhysicalLayerCC1101::manchDecode(uint8_t *encodedData, uint8_t *decodedData)
{
uint8_t data0, data1, data2, data3;
// - Shift to get 4 bit data and decode
data3 = ((*encodedData >> 4) & 0x0F);
data2 = ( *encodedData & 0x0F);
data1 = ((*(encodedData + 1) >> 4) & 0x0F);
data0 = ((*(encodedData + 1)) & 0x0F);
// Check for invalid Manchester encoding
if ( (manchDecodeTab[data3] == 0xFF ) | (manchDecodeTab[data2] == 0xFF ) |
(manchDecodeTab[data1] == 0xFF ) | (manchDecodeTab[data0] == 0xFF ) )
{
return false;
}
// Shift result into a byte
*decodedData = (manchDecodeTab[data3] << 6) | (manchDecodeTab[data2] << 4) |
(manchDecodeTab[data1] << 2) | manchDecodeTab[data0];
return true;
}
uint8_t RfPhysicalLayerCC1101::sIdle()
{
uint8_t marcState;
uint32_t timeStart;
spiWriteStrobe(SIDLE); //sets to idle first. must be in
marcState = 0xFF; //set unknown/dummy state value
timeStart = millis();
while((marcState != MARCSTATE_IDLE) && ((millis() - timeStart) < CC1101_TIMEOUT)) //0x01 = sidle
{
marcState = (spiReadRegister(MARCSTATE) & MARCSTATE_BITMASK); //read out state of cc1101 to be sure in RX
}
//print("marcstate: 0x");
//println(marcState, HEX);
if(marcState != MARCSTATE_IDLE)
{
println("Timeout when trying to set idle state.");
return false;
}
return true;
}
uint8_t RfPhysicalLayerCC1101::sReceive()
{
uint8_t marcState;
uint32_t timeStart;
spiWriteStrobe(SRX); //writes receive strobe (receive mode)
marcState = 0xFF; //set unknown/dummy state value
timeStart = millis();
while((marcState != MARCSTATE_RX) && ((millis() - timeStart) < CC1101_TIMEOUT)) //0x0D = RX
{
marcState = (spiReadRegister(MARCSTATE) & MARCSTATE_BITMASK); //read out state of cc1101 to be sure in RX
}
//print("marcstate: 0x");
//println(marcState, HEX);
if(marcState != MARCSTATE_RX)
{
println("Timeout when trying to set receive state.");
return false;
}
return true;
}
void RfPhysicalLayerCC1101::spiWriteRegister(uint8_t spi_instr, uint8_t value)
{
uint8_t tbuf[2] = {0};
tbuf[0] = spi_instr | WRITE_SINGLE_BYTE;
tbuf[1] = value;
uint8_t len = 2;
digitalWrite(SPI_SS_PIN, LOW);
_platform.readWriteSpi(tbuf, len);
digitalWrite(SPI_SS_PIN, HIGH);
}
uint8_t RfPhysicalLayerCC1101::spiReadRegister(uint8_t spi_instr)
{
uint8_t value;
uint8_t rbuf[2] = {0};
rbuf[0] = spi_instr | READ_SINGLE_BYTE;
uint8_t len = 2;
digitalWrite(SPI_SS_PIN, LOW);
_platform.readWriteSpi(rbuf, len);
digitalWrite(SPI_SS_PIN, HIGH);
value = rbuf[1];
//printf("SPI_arr_0: 0x%02X\n", rbuf[0]);
//printf("SPI_arr_1: 0x%02X\n", rbuf[1]);
return value;
}
uint8_t RfPhysicalLayerCC1101::spiWriteStrobe(uint8_t spi_instr)
{
uint8_t tbuf[1] = {0};
tbuf[0] = spi_instr;
//printf("SPI_data: 0x%02X\n", tbuf[0]);
digitalWrite(SPI_SS_PIN, LOW);
_platform.readWriteSpi(tbuf, 1);
digitalWrite(SPI_SS_PIN, HIGH);
return tbuf[0];
}
void RfPhysicalLayerCC1101::spiReadBurst(uint8_t spi_instr, uint8_t *pArr, uint8_t len)
{
uint8_t rbuf[len + 1];
rbuf[0] = spi_instr | READ_BURST;
digitalWrite(SPI_SS_PIN, LOW);
_platform.readWriteSpi(rbuf, len + 1);
digitalWrite(SPI_SS_PIN, HIGH);
for (uint8_t i=0; i<len ;i++ )
{
pArr[i] = rbuf[i+1];
//printf("SPI_arr_read: 0x%02X\n", pArr[i]);
}
}
void RfPhysicalLayerCC1101::spiWriteBurst(uint8_t spi_instr, const uint8_t *pArr, uint8_t len)
{
uint8_t tbuf[len + 1];
tbuf[0] = spi_instr | WRITE_BURST;
for (uint8_t i=0; i<len ;i++ )
{
tbuf[i+1] = pArr[i];
//printf("SPI_arr_write: 0x%02X\n", tbuf[i+1]);
}
digitalWrite(SPI_SS_PIN, LOW);
_platform.readWriteSpi(tbuf, len + 1);
digitalWrite(SPI_SS_PIN, HIGH);
}
void RfPhysicalLayerCC1101::powerDownCC1101()
{
// Set IDLE state first
sIdle();
delayMicroseconds(100);
// CC1101 Power Down
spiWriteStrobe(SPWD);
}
void RfPhysicalLayerCC1101::setOutputPowerLevel(int8_t dBm)
{
uint8_t pa = 0xC0;
if (dBm <= -30) pa = 0x00;
else if (dBm <= -20) pa = 0x01;
else if (dBm <= -15) pa = 0x02;
else if (dBm <= -10) pa = 0x03;
else if (dBm <= 0) pa = 0x04;
else if (dBm <= 5) pa = 0x05;
else if (dBm <= 7) pa = 0x06;
else if (dBm <= 10) pa = 0x07;
spiWriteRegister(FREND0, pa);
}
bool RfPhysicalLayerCC1101::InitChip()
{
// Setup SPI and GPIOs
_platform.setupSpi();
pinMode(GPIO_GDO2_PIN, INPUT);
pinMode(GPIO_GDO0_PIN, INPUT);
pinMode(SPI_SS_PIN, OUTPUT);
// Toggle chip select signal as described in CC11xx manual
digitalWrite(SPI_SS_PIN, HIGH);
delayMicroseconds(30);
digitalWrite(SPI_SS_PIN, LOW);
delayMicroseconds(30);
digitalWrite(SPI_SS_PIN, HIGH);
delayMicroseconds(45);
// Send SRES command
digitalWrite(SPI_SS_PIN, LOW);
delay(10); // Normally we would have to poll MISO here: while(_platform.readGpio(SPI_MISO_PIN));
spiWriteStrobe(SRES);
// Wait for chip to finish internal reset
delay(10); // Normally we would have to poll MISO here: while(_platform.readGpio(SPI_MISO_PIN));
digitalWrite(SPI_SS_PIN, HIGH);
// Flush the FIFOs
spiWriteStrobe(SFTX);
delayMicroseconds(100);
spiWriteStrobe(SFRX);
delayMicroseconds(100);
uint8_t partnum = spiReadRegister(PARTNUM); //reads CC1101 partnumber;
uint8_t version = spiReadRegister(VERSION); //reads CC1101 version number;
// Checks if valid chip ID is found. Usually 0x03 or 0x14. if not -> abort
if(version == 0x00 || version == 0xFF)
{
println("No CC11xx found!");
stopChip();
return false;
}
print("Partnumber: 0x");
println(partnum, HEX);
print("Version : 0x");
println(version, HEX);
// Set modulation mode 2FSK, 32768kbit/s
spiWriteBurst(WRITE_BURST,cc1101_2FSK_32_7_kb,CFG_REGISTER);
// Set PA table
spiWriteBurst(PATABLE_BURST, paTablePower868, 8);
// Set ISM band to 868.3MHz
spiWriteRegister(FREQ2,0x21);
spiWriteRegister(FREQ1,0x65);
spiWriteRegister(FREQ0,0x6A);
// Set channel 0 in ISM band
spiWriteRegister(CHANNR, 0);
// Set PA to 0dBm as default
setOutputPowerLevel(0);
return true;
}
void RfPhysicalLayerCC1101::stopChip()
{
powerDownCC1101();
_platform.closeSpi();
}
void RfPhysicalLayerCC1101::showRegisterSettings()
{
uint8_t config_reg_verify[CFG_REGISTER];
uint8_t Patable_verify[CFG_REGISTER];
spiReadBurst(READ_BURST,config_reg_verify,CFG_REGISTER); //reads all 47 config register from cc1101
spiReadBurst(PATABLE_BURST,Patable_verify,8); //reads output power settings from cc1101
println("Config Register:");
printHex("", config_reg_verify, CFG_REGISTER);
println("PaTable:");
printHex("", Patable_verify, 8);
}
void RfPhysicalLayerCC1101::loop()
{
switch (_loopState)
{
case TX_START:
{
prevStatusGDO0 = 0;
prevStatusGDO2 = 0;
// Set sync word in TX mode
// The same sync word is used in RX mode, but we use it in different way here:
// Important: the TX FIFO must provide the last byte of the
// sync word
spiWriteRegister(SYNC1, 0x54);
spiWriteRegister(SYNC0, 0x76);
// Set TX FIFO threshold to 33 bytes
spiWriteRegister(FIFOTHR, 0x47);
// Set GDO2 to be TX FIFO threshold signal
spiWriteRegister(IOCFG2, 0x02);
// Set GDO0 to be packet transmitted signal
spiWriteRegister(IOCFG0, 0x06);
// Flush TX FIFO
spiWriteStrobe(SFTX);
_rfDataLinkLayer.loadNextTxFrame(&sendBuffer, &sendBufferLength);
// Calculate total number of bytes in the KNX RF packet from L-field
pktLen = PACKET_SIZE(sendBuffer[0]);
// Check for valid length
if ((pktLen == 0) || (pktLen > 290))
{
println("TX packet length error!");
break;
}
// Manchester encoded data takes twice the space plus
// 1 byte for postamble and 1 byte (LSB) of the synchronization word
bytesLeft = (2 * pktLen) + 2;
// Last byte of synchronization word
buffer[0] = 0x96;
// Manchester encode packet
for (int i = 0; i < pktLen; i++)
{
manchEncode(&sendBuffer[i], &buffer[1 + i*2]);
}
// Append the postamble sequence
buffer[1 + bytesLeft - 1] = 0x55;
// Fill TX FIFO
pByteIndex = &buffer[0];
// Set fixed packet length mode if less than 256 bytes to transmit
if (bytesLeft < 256)
{
spiWriteRegister(PKTLEN, bytesLeft);
spiWriteRegister(PKTCTRL0, 0x00); // Set fixed pktlen mode
fixedLengthMode = true;
}
else // Else set infinite length mode
{
uint8_t fixedLength = bytesLeft % 256;
spiWriteRegister(PKTLEN, fixedLength);
spiWriteRegister(PKTCTRL0, 0x02);
fixedLengthMode = false;
}
uint8_t bytesToWrite = MIN(64, bytesLeft);
spiWriteBurst(TXFIFO_BURST, pByteIndex, bytesToWrite);
pByteIndex += bytesToWrite;
bytesLeft -= bytesToWrite;
// Enable transmission of packet
spiWriteStrobe(STX);
_loopState = TX_ACTIVE;
}
// Fall through
case TX_ACTIVE:
{
// Check if we have an incomplete packet transmission
if (syncStart && (millis() - packetStartTime > TX_PACKET_TIMEOUT))
{
println("TX packet timeout!");
// Set transceiver to IDLE (no RX or TX)
sIdle();
_loopState = TX_END;
break;
}
// Detect falling edge 1->0 on GDO2
statusGDO2 = digitalRead(GPIO_GDO2_PIN);
if(prevStatusGDO2 != statusGDO2)
{
prevStatusGDO2 = statusGDO2;
// Check if signal GDO2 is de-asserted (TX FIFO is below threshold of 33 bytes, i.e. TX FIFO is half full)
if(statusGDO2 == 0)
{
// - TX FIFO half full detected (< 33 bytes)
// Write data fragment to TX FIFO
uint8_t bytesToWrite = MIN(64, bytesLeft);
spiWriteBurst(TXFIFO_BURST, pByteIndex, bytesToWrite);
pByteIndex += bytesToWrite;
bytesLeft -= bytesToWrite;
// Set fixed length mode if less than 256 left to transmit
if ( (bytesLeft < (256 - 64)) && !fixedLengthMode )
{
spiWriteRegister(PKTCTRL0, 0x00); // Set fixed pktlen mode
fixedLengthMode = true;
}
}
}
// Detect falling edge 1->0 on GDO0
statusGDO0 = digitalRead(GPIO_GDO0_PIN);
if(prevStatusGDO0 != statusGDO0)
{
prevStatusGDO0 = statusGDO0;
// If GDO0 is de-asserted: TX packet complete or TX FIFO underflow
if (statusGDO0 == 0x00)
{
// There might be an TX FIFO underflow
uint8_t chipStatusBytes = spiWriteStrobe(SNOP);
if ((chipStatusBytes & CHIPSTATUS_STATE_BITMASK) == CHIPSTATUS_STATE_TX_UNDERFLOW)
{
println("TX FIFO underflow!");
// Set transceiver to IDLE (no RX or TX)
sIdle();
}
_loopState = TX_END;
}
else
{
// GDO0 asserted because sync word was transmitted
//println("TX Syncword!");
// wait for TX_PACKET_TIMEOUT milliseconds
// Complete packet must have been transmitted within this time
packetStartTime = millis();
syncStart = true;
}
}
}
break;
case TX_END:
{
// free buffer
delete sendBuffer;
// Go back to RX after TX
_loopState = RX_START;
}
break;
case RX_START:
{
prevStatusGDO2 = 0;
prevStatusGDO0 = 0;
syncStart = false;
packetStart = true;
fixedLengthMode = false;
pByteIndex = buffer;
bytesLeft = 0;
pktLen = 0;
// Set sync word in RX mode
// The same sync word is used in TX mode, but we use it in different way
spiWriteRegister(SYNC1, 0x76);
spiWriteRegister(SYNC0, 0x96);
// Set GDO2 to be RX FIFO threshold signal
spiWriteRegister(IOCFG2, 0x00);
// Set GDO0 to be packet received signal
spiWriteRegister(IOCFG0, 0x06);
// Set RX FIFO threshold to 4 bytes
spiWriteRegister(FIFOTHR, 0x40);
// Set infinite pktlen mode
spiWriteRegister(PKTCTRL0, 0x02);
// Flush RX FIFO
spiWriteStrobe(SFRX);
// Start RX
sReceive();
_loopState = RX_ACTIVE;
}
break;
case RX_ACTIVE:
{
if (!_rfDataLinkLayer.isTxQueueEmpty() && !syncStart)
{
sIdle();
_loopState = TX_START;
break;
}
// Check if we have an incomplete packet reception
// This is related to CC1101 errata "Radio stays in RX state instead of entering RXFIFO_OVERFLOW state"
if (syncStart && (millis() - packetStartTime > RX_PACKET_TIMEOUT))
{
println("RX packet timeout!");
//uint8_t marcState = (spiReadRegister(MARCSTATE) & MARCSTATE_BITMASK); //read out state of cc1101 to be sure in RX
//print("marcstate: 0x");
//println(marcState, HEX);
sIdle();
_loopState = RX_START;
break;
}
// Detect rising edge 0->1 on GDO2
statusGDO2 = digitalRead(GPIO_GDO2_PIN);
if(prevStatusGDO2 != statusGDO2)
{
prevStatusGDO2 = statusGDO2;
// Check if signal GDO2 is asserted (RX FIFO is equal to or above threshold of 4 bytes)
if(statusGDO2 == 1)
{
if (packetStart)
{
// - RX FIFO 4 bytes detected -
// Calculate the total length of the packet, and set fixed mode if less
// than 255 bytes to receive
// Read the 2 first bytes
spiReadBurst(RXFIFO_BURST, pByteIndex, 2);
// Decode the L-field
if (!manchDecode(&buffer[0], &packet[0]))
{
//println("Could not decode L-field: manchester code violation");
_loopState = RX_START;
break;
}
// Get bytes to receive from L-field, multiply by 2 because of manchester code
pktLen = 2 * PACKET_SIZE(packet[0]);
// - Length mode -
if (pktLen < 256)
{
// Set fixed packet length mode is less than 256 bytes
spiWriteRegister(PKTLEN, pktLen);
spiWriteRegister(PKTCTRL0, 0x00); // Set fixed pktlen mode
fixedLengthMode = true;
}
else
{
// Infinite packet length mode is more than 255 bytes
// Calculate the PKTLEN value
uint8_t fixedLength = pktLen % 256;
spiWriteRegister(PKTLEN, fixedLength);
}
pByteIndex += 2;
bytesLeft = pktLen - 2;
// Set RX FIFO threshold to 32 bytes
packetStart = false;
spiWriteRegister(FIFOTHR, 0x47);
}
else
{
// - RX FIFO Half Full detected -
// Read out the RX FIFO and set fixed mode if less
// than 255 bytes to receive
// - Length mode -
// Set fixed packet length mode if less than 256 bytes
if ((bytesLeft < 256 ) && !fixedLengthMode)
{
spiWriteRegister(PKTCTRL0, 0x00); // Set fixed pktlen mode
fixedLengthMode = true;
}
// Read out the RX FIFO
// Do not empty the FIFO (See the CC110x or 2500 Errata Note)
spiReadBurst(RXFIFO_BURST, pByteIndex, 32 - 1);
bytesLeft -= (32 - 1);
pByteIndex += (32 - 1);
}
}
}
// Detect falling edge 1->0 on GDO0
statusGDO0 = digitalRead(GPIO_GDO0_PIN);
if(prevStatusGDO0 != statusGDO0)
{
prevStatusGDO0 = statusGDO0;
// If GDO0 is de-asserted: RX packet complete or RX FIFO overflow
if (statusGDO0 == 0x00)
{
// There might be an RX FIFO overflow
uint8_t chipStatusBytes = spiWriteStrobe(SNOP);
if ((chipStatusBytes & CHIPSTATUS_STATE_BITMASK) == CHIPSTATUS_STATE_RX_OVERFLOW)
{
println("RX FIFO overflow!");
_loopState = RX_START;
break;
}
// Check if we are in the middle of the packet reception
if (!packetStart)
{
// Complete packet received
// Read out remaining bytes in the RX FIFO
spiReadBurst(RXFIFO_BURST, pByteIndex, bytesLeft);
_loopState = RX_END;
}
}
else
{
// GDO0 asserted because sync word was received and recognized
//println("RX Syncword!");
// wait for RX_PACKET_TIMEOUT milliseconds
// Complete packet must have been received within this time
packetStartTime = millis();
syncStart = true;
}
}
}
break;
case RX_END:
{
uint16_t pLen = PACKET_SIZE(packet[0]);
// Decode the first block (always 10 bytes + 2 bytes CRC)
bool decodeOk = true;
for (uint16_t i = 1; i < pLen; i++)
{
// Check for manchester violation, abort if there is one
if(!manchDecode(&buffer[i*2], &packet[i]))
{
println("Could not decode packet: manchester code violation");
decodeOk = false;
break;
}
}
if (decodeOk)
{
_rfDataLinkLayer.frameBytesReceived(&packet[0], pLen);
}
_loopState = RX_START;
}
break;
}
}
#endif // USE_RF
#endif // DeviceFamily_CC13X0