Implemented promiscuous mode for CC1101 and RF69

This commit is contained in:
Federico Maggi 2019-11-12 17:56:36 +01:00
parent cc39929704
commit 35361ce198
4 changed files with 290 additions and 15 deletions

View file

@ -4,6 +4,8 @@ CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_CRYSTAL_FREQ, CC1101_DIV_E
_mod = module; _mod = module;
_packetLengthQueried = false; _packetLengthQueried = false;
_packetLengthConfig = CC1101_LENGTH_CONFIG_VARIABLE; _packetLengthConfig = CC1101_LENGTH_CONFIG_VARIABLE;
_syncWordLength = CC1101_DEFAULT_SYNC_WORD_LENGTH;
} }
int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t power) { int16_t CC1101::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
@ -441,13 +443,37 @@ int16_t CC1101::setOutputPower(int8_t power) {
return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw)); return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw));
} }
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL) { int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits) {
// set sync word if(maxErrBits > 1) {
int16_t state = SPIsetRegValue(CC1101_REG_SYNC1, syncH); return(ERR_INVALID_SYNC_WORD);
state |= SPIsetRegValue(CC1101_REG_SYNC0, syncL); }
// sync word must not contain value 0x00
for(uint8_t i = 0; i < len; i++) {
if(syncWord[i] == 0x00) {
return(ERR_INVALID_SYNC_WORD);
}
}
_syncWordLength = len;
// enable sync word filtering
int16_t state = enableSyncWordFiltering(maxErrBits);
if (state != ERR_NONE) {
return(state); return(state);
} }
// set sync word register
_mod->SPIwriteRegisterBurst(CC1101_REG_SYNC1, syncWord, len);
return(ERR_NONE);
}
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits) {
uint8_t syncWord[] = { syncH, syncL };
return(setSyncWord(syncWord, sizeof(syncWord), maxErrBits));
}
int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) { int16_t CC1101::setNodeAddress(uint8_t nodeAddr, uint8_t numBroadcastAddrs) {
if(!(numBroadcastAddrs > 0) && (numBroadcastAddrs <= 2)) { if(!(numBroadcastAddrs > 0) && (numBroadcastAddrs <= 2)) {
return(ERR_INVALID_NUM_BROAD_ADDRS); return(ERR_INVALID_NUM_BROAD_ADDRS);
@ -547,6 +573,76 @@ int16_t CC1101::variablePacketLengthMode(uint8_t maxLen) {
return(state); return(state);
} }
int16_t CC1101::enableSyncWordFiltering(uint8_t maxErrBits) {
if (maxErrBits > 1) {
return(ERR_INVALID_SYNC_WORD);
}
if (maxErrBits == 0) {
if (_syncWordLength == 1) {
// in 16 bit sync word, expect all 16 bits
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_16_16, 2, 0));
} else if (_syncWordLength == 2) {
// there's no 32 of 32 case, so we resort to 30 of 32 bits required
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_30_32, 2, 0));
}
}
if (maxErrBits == 1) {
if (_syncWordLength == 1) {
// in 16 bit sync word, expect at least 15 bits
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_15_16, 2, 0));
} else if (_syncWordLength == 2) {
// in 32 bits sync word (16 + 16), expect 30 of 32 to match
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_30_32, 2, 0));
}
}
return(ERR_NONE);
}
int16_t CC1101::disableSyncWordFiltering() {
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_NONE, 2, 0));
}
int16_t CC1101::enableCrcFiltering() {
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON, 2, 2));
}
int16_t CC1101::disableCrcFiltering() {
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_OFF, 2, 2));
}
int16_t CC1101::promiscuousMode(bool promiscuous) {
int16_t state = ERR_NONE;
if (_promiscuous == promiscuous) {
return(state);
}
if (promiscuous == true) {
// disable preamble and sync word filtering and insertion
state = disableSyncWordFiltering();
if (state != ERR_NONE) {
return(state);
}
// disable CRC filtering
state = disableCrcFiltering();
} else {
// enable preamble and sync word filtering and insertion
state = enableSyncWordFiltering();
if (state != ERR_NONE) {
return(state);
}
// enable CRC filtering
state = enableCrcFiltering();
}
return(state);
}
int16_t CC1101::config() { int16_t CC1101::config() {
// enable automatic frequency synthesizer calibration // enable automatic frequency synthesizer calibration
int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4); int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4);

View file

@ -10,6 +10,9 @@
#define CC1101_CRYSTAL_FREQ 26.0 #define CC1101_CRYSTAL_FREQ 26.0
#define CC1101_DIV_EXPONENT 16 #define CC1101_DIV_EXPONENT 16
#define CC1101_MAX_PACKET_LENGTH 63 #define CC1101_MAX_PACKET_LENGTH 63
#define CC1101_MAX_SYNC_WORD_LENGTH 2
#define CC1101_DEFAULT_SYNC_WORD_LENGTH 2
#define CC1101_DEFAULT_SYNC_WORD { 0xD3, 0x91 }
// CC1101 SPI commands // CC1101 SPI commands
#define CC1101_CMD_READ 0b10000000 #define CC1101_CMD_READ 0b10000000
@ -237,7 +240,7 @@
#define CC1101_MOD_FORMAT_MFSK 0b01110000 // 6 4 MFSK - only for data rates above 26 kBaud #define CC1101_MOD_FORMAT_MFSK 0b01110000 // 6 4 MFSK - only for data rates above 26 kBaud
#define CC1101_MANCHESTER_EN_OFF 0b00000000 // 3 3 Manchester encoding: disabled (default) #define CC1101_MANCHESTER_EN_OFF 0b00000000 // 3 3 Manchester encoding: disabled (default)
#define CC1101_MANCHESTER_EN_ON 0b00001000 // 3 3 enabled #define CC1101_MANCHESTER_EN_ON 0b00001000 // 3 3 enabled
#define CC1101_SYNC_MODE_NONE 0b00000000 // 2 0 synchronization: no preamble sync #define CC1101_SYNC_MODE_NONE 0b00000000 // 2 0 synchronization: no preamble/sync
#define CC1101_SYNC_MODE_15_16 0b00000001 // 2 0 15/16 sync word bits #define CC1101_SYNC_MODE_15_16 0b00000001 // 2 0 15/16 sync word bits
#define CC1101_SYNC_MODE_16_16 0b00000010 // 2 0 16/16 sync word bits (default) #define CC1101_SYNC_MODE_16_16 0b00000010 // 2 0 16/16 sync word bits (default)
#define CC1101_SYNC_MODE_30_32 0b00000011 // 2 0 30/32 sync word bits #define CC1101_SYNC_MODE_30_32 0b00000011 // 2 0 30/32 sync word bits
@ -694,9 +697,24 @@ class CC1101: public PhysicalLayer {
\param syncL LSB of the sync word. \param syncL LSB of the sync word.
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t setSyncWord(uint8_t syncH, uint8_t syncL); int16_t setSyncWord(uint8_t syncH, uint8_t syncL, uint8_t maxErrBits = 0);
/*!
\brief Sets 1 or 2 bytes of sync word.
\param syncWord Pointer to the array of sync word bytes.
\param len Sync word length in bytes.
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
\returns \ref status_codes
*/
int16_t setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits = 0);
/*! /*!
\brief Sets node and broadcast addresses. Calling this method will also enable address filtering. \brief Sets node and broadcast addresses. Calling this method will also enable address filtering.
@ -757,6 +775,45 @@ class CC1101: public PhysicalLayer {
*/ */
int16_t variablePacketLengthMode(uint8_t maxLen = CC1101_MAX_PACKET_LENGTH); int16_t variablePacketLengthMode(uint8_t maxLen = CC1101_MAX_PACKET_LENGTH);
/*!
\brief Enable sync word filtering and generation.
\param len Size of sync word (1 or 2 bytes).
\returns \ref status_codes
*/
int16_t enableSyncWordFiltering(uint8_t len = CC1101_DEFAULT_SYNC_WORD_LENGTH);
/*!
\brief Disable preamble and sync word filtering and generation.
\returns \ref status_codes
*/
int16_t disableSyncWordFiltering();
/*!
\brief Enable CRC filtering and generation.
\returns \ref status_codes
*/
int16_t enableCrcFiltering();
/*!
\brief Disable CRC filtering and generation.
\returns \ref status_codes
*/
int16_t disableCrcFiltering();
/*!
\brief Set modem in "sniff" mode: no packet filtering (e.g., no preamble, sync word, address, CRC).
\param promiscuous Set or unset promiscuous mode.
\returns \ref status_codes
*/
int16_t promiscuousMode(bool promiscuous = true);
private: private:
Module* _mod; Module* _mod;
@ -768,6 +825,10 @@ class CC1101: public PhysicalLayer {
bool _packetLengthQueried; bool _packetLengthQueried;
uint8_t _packetLengthConfig; uint8_t _packetLengthConfig;
bool _promiscuous;
uint8_t _syncWordLength;
int16_t config(); int16_t config();
int16_t directMode(); int16_t directMode();
void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant); void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant);

View file

@ -3,8 +3,13 @@
RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) { RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) {
_mod = module; _mod = module;
_tempOffset = 0; _tempOffset = 0;
_packetLengthQueried = false; _packetLengthQueried = false;
_packetLengthConfig = RF69_PACKET_FORMAT_VARIABLE; _packetLengthConfig = RF69_PACKET_FORMAT_VARIABLE;
_promiscuous = false;
_syncWordLength = RF69_DEFAULT_SYNC_WORD_LENGTH;
} }
int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t power) { int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t power) {
@ -87,8 +92,8 @@ int16_t RF69::begin(float freq, float br, float rxBw, float freqDev, int8_t powe
} }
// default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library // default sync word values 0x2D01 is the same as the default in LowPowerLab RFM69 library
uint8_t syncWord[] = {0x2D, 0x01}; uint8_t syncWord[] = RF69_DEFAULT_SYNC_WORD;
state = setSyncWord(syncWord, 2); state = setSyncWord(syncWord, sizeof(syncWord));
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -495,7 +500,7 @@ int16_t RF69::setOutputPower(int8_t power) {
int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) { int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
// check constraints // check constraints
if((maxErrBits > 7) || (len > 8)) { if((maxErrBits > 7) || (len > RF69_MAX_SYNC_WORD_LENGTH)) {
return(ERR_INVALID_SYNC_WORD); return(ERR_INVALID_SYNC_WORD);
} }
@ -506,13 +511,14 @@ int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
} }
} }
// enable sync word recognition _syncWordLength = len;
int16_t state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (len - 1) << 3 | maxErrBits, 7, 0);
int16_t state = enableSyncWordFiltering(maxErrBits);
if (state != ERR_NONE) { if (state != ERR_NONE) {
return(state); return(state);
} }
// set sync word // set sync word register
_mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len); _mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len);
return(ERR_NONE); return(ERR_NONE);
} }
@ -636,6 +642,71 @@ int16_t RF69::variablePacketLengthMode(uint8_t maxLen) {
return(state); return(state);
} }
int16_t RF69::enableSyncWordFiltering(uint8_t maxErrBits) {
// enable sync word recognition
int16_t state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (_syncWordLength - 1) << 3 | maxErrBits, 7, 0);
if(state != ERR_NONE) {
return(state);
}
return(state);
}
int16_t RF69::disableSyncWordFiltering() {
// disable preamble detection and generation
int16_t state = _mod->SPIsetRegValue(RF69_REG_PREAMBLE_LSB, 0, 7, 0);
state |= _mod->SPIsetRegValue(RF69_REG_PREAMBLE_MSB, 0, 7, 0);
if (state != ERR_NONE) {
return(state);
}
// disable sync word detection and generation
state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_OFF | RF69_FIFO_FILL_CONDITION, 7, 6);
if (state != ERR_NONE) {
return(state);
}
return(state);
}
int16_t RF69::enableCrcFiltering() {
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_CRC_ON), 4, 4);
}
int16_t RF69::disableCrcFiltering() {
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_CRC_OFF), 4, 4);
}
int16_t RF69::promiscuousMode(bool promiscuous) {
int16_t state = ERR_NONE;
if (_promiscuous == promiscuous) {
return(state);
}
if (promiscuous == true) {
// disable preamble and sync word filtering and insertion
state = disableSyncWordFiltering();
if (state != ERR_NONE) {
return(state);
}
// disable CRC filtering
state = disableCrcFiltering();
} else {
// enable preamble and sync word filtering and insertion
state = enableSyncWordFiltering();
if (state != ERR_NONE) {
return(state);
}
// enable CRC filtering
state = enableCrcFiltering();
}
return(state);
}
int16_t RF69::config() { int16_t RF69::config() {
int16_t state = ERR_NONE; int16_t state = ERR_NONE;

View file

@ -10,6 +10,10 @@
#define RF69_CRYSTAL_FREQ 32.0 #define RF69_CRYSTAL_FREQ 32.0
#define RF69_DIV_EXPONENT 19 #define RF69_DIV_EXPONENT 19
#define RF69_MAX_PACKET_LENGTH 64 #define RF69_MAX_PACKET_LENGTH 64
#define RF69_MAX_PREAMBLE_LENGTH 4
#define RF69_MAX_SYNC_WORD_LENGTH 8
#define RF69_DEFAULT_SYNC_WORD_LENGTH 2
#define RF69_DEFAULT_SYNC_WORD { 0x2D, 0x01 }
// RF69 register map // RF69 register map
#define RF69_REG_FIFO 0x00 #define RF69_REG_FIFO 0x00
@ -646,7 +650,7 @@ class RF69: public PhysicalLayer {
int16_t setOutputPower(int8_t power); int16_t setOutputPower(int8_t power);
/*! /*!
\brief Sets sync word. Up to 8 bytes can be set as snyc word. \brief Sets sync word. Up to 8 bytes can be set as sync word.
\param syncWord Pointer to the array of sync word bytes. \param syncWord Pointer to the array of sync word bytes.
@ -724,6 +728,45 @@ class RF69: public PhysicalLayer {
*/ */
int16_t variablePacketLengthMode(uint8_t maxLen = RF69_MAX_PACKET_LENGTH); int16_t variablePacketLengthMode(uint8_t maxLen = RF69_MAX_PACKET_LENGTH);
/*!
\brief Enable sync word filtering and generation.
\param numBits Sync word length in bits.
\returns \ref status_codes
*/
int16_t enableSyncWordFiltering(uint8_t numBits = 16);
/*!
\brief Disable preamble and sync word filtering and generation.
\returns \ref status_codes
*/
int16_t disableSyncWordFiltering();
/*!
\brief Enable CRC filtering and generation.
\returns \ref status_codes
*/
int16_t enableCrcFiltering();
/*!
\brief Disable CRC filtering and generation.
\returns \ref status_codes
*/
int16_t disableCrcFiltering();
/*!
\brief Set modem in "sniff" mode: no packet filtering (e.g., no preamble, sync word, address, CRC).
\param promiscuous Set or unset promiscuous mode.
\returns \ref status_codes
*/
int16_t promiscuousMode(bool promiscuous = true);
protected: protected:
Module* _mod; Module* _mod;
@ -735,6 +778,10 @@ class RF69: public PhysicalLayer {
bool _packetLengthQueried; bool _packetLengthQueried;
uint8_t _packetLengthConfig; uint8_t _packetLengthConfig;
bool _promiscuous;
uint8_t _syncWordLength;
int16_t config(); int16_t config();
int16_t directMode(); int16_t directMode();