diff --git a/.gitignore b/.gitignore index f1723db9..58d33796 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ # Debug decoder extras/decoder/log.txt extras/decoder/out.txt + +# PlatformIO +.pio* diff --git a/src/modules/CC1101/CC1101.cpp b/src/modules/CC1101/CC1101.cpp index 3248e929..4fe96dbf 100644 --- a/src/modules/CC1101/CC1101.cpp +++ b/src/modules/CC1101/CC1101.cpp @@ -262,19 +262,32 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) { int16_t state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); RADIOLIB_ASSERT(state); + // data put on FIFO. + uint8_t dataSent = 0; + // optionally write packet length if (_packetLengthConfig == CC1101_LENGTH_CONFIG_VARIABLE) { + + // enforce variable len limit. + if (len > CC1101_MAX_PACKET_LENGTH - 1) { + return (ERR_PACKET_TOO_LONG); + } + SPIwriteRegister(CC1101_REG_FIFO, len); + dataSent += 1; } // check address filtering uint8_t filter = SPIgetRegValue(CC1101_REG_PKTCTRL1, 1, 0); if(filter != CC1101_ADR_CHK_NONE) { SPIwriteRegister(CC1101_REG_FIFO, addr); + dataSent += 1; } - // write packet to FIFO - SPIwriteRegisterBurst(CC1101_REG_FIFO, data, len); + // fill the FIFO. + uint8_t initialWrite = min((uint8_t)len, (uint8_t)(CC1101_FIFO_SIZE - dataSent)); + SPIwriteRegisterBurst(CC1101_REG_FIFO, data, initialWrite); + dataSent += initialWrite; // set RF switch (if present) _mod->setRfSwitchState(LOW, HIGH); @@ -282,7 +295,29 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) { // set mode to transmit SPIsendCommand(CC1101_CMD_TX); - return(state); + // keep feeding the FIFO until the packet is over. + while (dataSent < len) { + // get number of bytes in FIFO. + uint8_t bytesInFIFO = SPIgetRegValue(CC1101_REG_TXBYTES, 6, 0); + + // if there's room then put other data. + if (bytesInFIFO < CC1101_FIFO_SIZE) { + uint8_t bytesToWrite = min((uint8_t)(CC1101_FIFO_SIZE - bytesInFIFO), (uint8_t)(len - dataSent)); + SPIwriteRegisterBurst(CC1101_REG_FIFO, &data[dataSent], bytesToWrite); + dataSent += bytesToWrite; + } else { + // wait for radio to send some data. + /* + * Does this work for all rates? If 1 ms is longer than the 1ms delay + * then the entire FIFO will be transmitted during that delay. + * + * TODO: test this on real hardware + */ + delayMicroseconds(250); + } + } + + return (state); } int16_t CC1101::startReceive() { @@ -292,8 +327,9 @@ int16_t CC1101::startReceive() { // flush Rx FIFO SPIsendCommand(CC1101_CMD_FLUSH_RX); - // set GDO0 mapping - int state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_SYNC_WORD_SENT_OR_RECEIVED); + // set GDO0 mapping: Asserted when RX FIFO > 4 bytes. + int16_t state = SPIsetRegValue(CC1101_REG_IOCFG0, CC1101_GDOX_RX_FIFO_FULL_OR_PKT_END); + state |= SPIsetRegValue(CC1101_REG_FIFOTHR, CC1101_FIFO_THR_TX_61_RX_4, 3, 0); RADIOLIB_ASSERT(state); // set RF switch (if present) @@ -308,8 +344,8 @@ int16_t CC1101::startReceive() { int16_t CC1101::readData(uint8_t* data, size_t len) { // get packet length size_t length = len; - if(len == CC1101_MAX_PACKET_LENGTH) { - length = getPacketLength(); + if (len == CC1101_MAX_PACKET_LENGTH) { + length = getPacketLength(true); } // check address filtering @@ -318,28 +354,69 @@ int16_t CC1101::readData(uint8_t* data, size_t len) { SPIreadRegister(CC1101_REG_FIFO); } - // read packet data - SPIreadRegisterBurst(CC1101_REG_FIFO, length, data); + uint8_t bytesInFIFO = SPIgetRegValue(CC1101_REG_RXBYTES, 6, 0); + size_t readBytes = 0; + uint32_t lastPop = millis(); - // read RSSI byte - _rawRSSI = SPIgetRegValue(CC1101_REG_FIFO); + // keep reading from FIFO until we get all the packet. + while (readBytes < length) { + if (bytesInFIFO == 0) { + if (millis() - lastPop > 5) { + // readData was required to read a packet longer than the one received. + RADIOLIB_DEBUG_PRINTLN(F("No data for more than 5mS. Stop here.")); + break; + } else { + /* + * Does this work for all rates? If 1 ms is longer than the 1ms delay + * then the entire FIFO will be transmitted during that delay. + * + * TODO: drop this delay(1) or come up with a better solution: + */ + delay(1); + bytesInFIFO = SPIgetRegValue(CC1101_REG_RXBYTES, 6, 0); + continue; + } + } + + // read the minimum between "remaining length" and bytesInFifo + uint8_t bytesToRead = min((uint8_t)(length - readBytes), bytesInFIFO); + SPIreadRegisterBurst(CC1101_REG_FIFO, bytesToRead, &(data[readBytes])); + readBytes += bytesToRead; + lastPop = millis(); + + // Get how many bytes are left in FIFO. + bytesInFIFO = SPIgetRegValue(CC1101_REG_RXBYTES, 6, 0); + } + + // check if status bytes are enabled (default: CC1101_APPEND_STATUS_ON) + bool isAppendStatus = SPIgetRegValue(CC1101_REG_PKTCTRL1, 2, 2) == CC1101_APPEND_STATUS_ON; + + // If status byte is enabled at least 2 bytes (2 status bytes + any following packet) will remain in FIFO. + if (bytesInFIFO >= 2 && isAppendStatus) { + // read RSSI byte + _rawRSSI = SPIgetRegValue(CC1101_REG_FIFO); // read LQI and CRC byte uint8_t val = SPIgetRegValue(CC1101_REG_FIFO); _rawLQI = val & 0x7F; - // flush Rx FIFO - SPIsendCommand(CC1101_CMD_FLUSH_RX); + // check CRC + if (_crcOn && (val & CC1101_CRC_OK) == CC1101_CRC_ERROR) { + return (ERR_CRC_MISMATCH); + } + } // clear internal flag so getPacketLength can return the new packet length _packetLengthQueried = false; - // set mode to standby - standby(); + // Flush then standby according to RXOFF_MODE (default: CC1101_RXOFF_IDLE) + if (SPIgetRegValue(CC1101_REG_MCSM1, 3, 2) == CC1101_RXOFF_IDLE) { - // check CRC - if (_crcOn && (val & 0b10000000) == 0b00000000) { - return (ERR_CRC_MISMATCH); + // flush Rx FIFO + SPIsendCommand(CC1101_CMD_FLUSH_RX); + + // set mode to standby + standby(); } return(ERR_NONE); @@ -609,7 +686,6 @@ int16_t CC1101::setOOK(bool enableOOK) { state = SPIsetRegValue(CC1101_REG_FREND0, 1, 2, 0); RADIOLIB_ASSERT(state); - // update current modulation _modulation = CC1101_MOD_FORMAT_ASK_OOK; } else { @@ -628,7 +704,6 @@ int16_t CC1101::setOOK(bool enableOOK) { return(setOutputPower(_power)); } - float CC1101::getRSSI() const { float rssi; if(_rawRSSI >= 128) { @@ -715,9 +790,15 @@ int16_t CC1101::setPromiscuousMode(bool promiscuous) { state = setCrcFiltering(true); } + _promiscuous = promiscuous; + return(state); } +bool CC1101::getPromiscuousMode() { + return (_promiscuous); +} + int16_t CC1101::setDataShaping(uint8_t sh) { // set mode to standby int16_t state = standby(); diff --git a/src/modules/CC1101/CC1101.h b/src/modules/CC1101/CC1101.h index d14f3182..55ffaa71 100644 --- a/src/modules/CC1101/CC1101.h +++ b/src/modules/CC1101/CC1101.h @@ -8,9 +8,10 @@ // CC1101 physical layer properties #define CC1101_FREQUENCY_STEP_SIZE 396.7285156 -#define CC1101_MAX_PACKET_LENGTH 63 +#define CC1101_MAX_PACKET_LENGTH 255 #define CC1101_CRYSTAL_FREQ 26.0 #define CC1101_DIV_EXPONENT 16 +#define CC1101_FIFO_SIZE 64 // CC1101 SPI commands #define CC1101_CMD_READ 0b10000000 @@ -168,7 +169,7 @@ #define CC1101_RX_ATTEN_6_DB 0b00010000 // 5 4 6 dB #define CC1101_RX_ATTEN_12_DB 0b00100000 // 5 4 12 dB #define CC1101_RX_ATTEN_18_DB 0b00110000 // 5 4 18 dB -#define CC1101_FIFO_THR 0b00000111 // 5 4 Rx FIFO threshold [bytes] = CC1101_FIFO_THR * 4; Tx FIFO threshold [bytes] = 65 - (CC1101_FIFO_THR * 4) +#define CC1101_FIFO_THR_TX_61_RX_4 0b00000000 // 3 0 TX fifo threshold: 61, RX fifo threshold: 4 // CC1101_REG_SYNC1 #define CC1101_SYNC_WORD_MSB 0xD3 // 7 0 sync word MSB @@ -599,9 +600,9 @@ class CC1101: public PhysicalLayer { \param func ISR to call. - \param dir Signal change direction. Defaults to FALLING. + \param dir Signal change direction. Defaults to RISING. */ - void setGdo0Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir = FALLING); + void setGdo0Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir = RISING); /*! \brief Clears interrupt service routine to call when GDO0 activates. @@ -846,6 +847,13 @@ class CC1101: public PhysicalLayer { */ int16_t setPromiscuousMode(bool promiscuous = true); + /*! + \brief Get whether the modem is in promiscuous mode: no packet filtering (e.g., no preamble, sync word, address, CRC). + + \returns Whether the modem is in promiscuous mode + */ + bool getPromiscuousMode(); + /*! \brief Sets Gaussian filter bandwidth-time product that will be used for data shaping. Allowed value is RADIOLIB_SHAPING_0_5. Set to RADIOLIB_SHAPING_NONE to disable data shaping. diff --git a/src/modules/RF69/RF69.cpp b/src/modules/RF69/RF69.cpp index e6777e2b..aa5ec80a 100644 --- a/src/modules/RF69/RF69.cpp +++ b/src/modules/RF69/RF69.cpp @@ -407,6 +407,9 @@ int16_t RF69::setFrequency(float freq) { _mod->SPIwriteRegister(RF69_REG_FRF_MSB, (FRF & 0xFF0000) >> 16); _mod->SPIwriteRegister(RF69_REG_FRF_MID, (FRF & 0x00FF00) >> 8); _mod->SPIwriteRegister(RF69_REG_FRF_LSB, FRF & 0x0000FF); + + _freq = freq; + return(ERR_NONE); } diff --git a/src/modules/RF69/RF69.h b/src/modules/RF69/RF69.h index bb0e8009..fab56900 100644 --- a/src/modules/RF69/RF69.h +++ b/src/modules/RF69/RF69.h @@ -878,6 +878,7 @@ class RF69: public PhysicalLayer { protected: #endif + float _freq = 0; float _br = 0; float _rxBw = 0; bool _ook = false;