Merge pull request #66 from rfquack/master
Revisioned promiscious-mode implementation for CC1101 and RF69 #63
This commit is contained in:
commit
e48275e998
5 changed files with 284 additions and 15 deletions
|
@ -90,6 +90,10 @@ setDataShapingOOK KEYWORD2
|
|||
setCRC KEYWORD2
|
||||
variablePacketLengthMode KEYWORD2
|
||||
fixedPacketLengthMode KEYWORD2
|
||||
setCrcFiltering KEYWORD2
|
||||
enableSyncWordFiltering KEYWORD2
|
||||
disableSyncWordFiltering KEYWORD2
|
||||
setPromiscuous KEYWORD2
|
||||
|
||||
# RF69-specific
|
||||
setAESKey KEYWORD2
|
||||
|
|
|
@ -4,6 +4,8 @@ CC1101::CC1101(Module* module) : PhysicalLayer(CC1101_CRYSTAL_FREQ, CC1101_DIV_E
|
|||
_mod = module;
|
||||
_packetLengthQueried = false;
|
||||
_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) {
|
||||
|
@ -441,11 +443,35 @@ int16_t CC1101::setOutputPower(int8_t power) {
|
|||
return(SPIsetRegValue(CC1101_REG_PATABLE, powerRaw));
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t syncH, uint8_t syncL) {
|
||||
// set sync word
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_SYNC1, syncH);
|
||||
state |= SPIsetRegValue(CC1101_REG_SYNC0, syncL);
|
||||
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits) {
|
||||
if((maxErrBits > 1) || (len > CC1101_MAX_SYNC_WORD_LENGTH)) {
|
||||
return(ERR_INVALID_SYNC_WORD);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -547,6 +573,76 @@ int16_t CC1101::variablePacketLengthMode(uint8_t maxLen) {
|
|||
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 {
|
||||
// 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 {
|
||||
// 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_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t CC1101::disableSyncWordFiltering() {
|
||||
return(SPIsetRegValue(CC1101_REG_MDMCFG2, CC1101_SYNC_MODE_NONE, 2, 0));
|
||||
}
|
||||
|
||||
int16_t CC1101::setCrcFiltering(bool crcOn) {
|
||||
if (crcOn == true) {
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_ON, 2, 2));
|
||||
} else {
|
||||
return(SPIsetRegValue(CC1101_REG_PKTCTRL0, CC1101_CRC_OFF, 2, 2));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setPromiscuousMode(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 = setCrcFiltering(false);
|
||||
} else {
|
||||
// enable preamble and sync word filtering and insertion
|
||||
state = enableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// enable CRC filtering
|
||||
state = setCrcFiltering(true);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::config() {
|
||||
// enable automatic frequency synthesizer calibration
|
||||
int16_t state = SPIsetRegValue(CC1101_REG_MCSM0, CC1101_FS_AUTOCAL_IDLE_TO_RXTX, 5, 4);
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#define CC1101_CRYSTAL_FREQ 26.0
|
||||
#define CC1101_DIV_EXPONENT 16
|
||||
#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
|
||||
#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_MANCHESTER_EN_OFF 0b00000000 // 3 3 Manchester encoding: disabled (default)
|
||||
#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_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
|
||||
|
@ -694,9 +697,24 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
\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
|
||||
*/
|
||||
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.
|
||||
|
@ -757,6 +775,40 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = CC1101_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 maxErrBits = 0);
|
||||
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering();
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
||||
\param crcOn Set or unset promiscuous mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool crcOn = true);
|
||||
|
||||
/*!
|
||||
\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 setPromiscuousMode(bool promiscuous = true);
|
||||
|
||||
private:
|
||||
Module* _mod;
|
||||
|
||||
|
@ -768,6 +820,10 @@ class CC1101: public PhysicalLayer {
|
|||
bool _packetLengthQueried;
|
||||
uint8_t _packetLengthConfig;
|
||||
|
||||
bool _promiscuous;
|
||||
|
||||
uint8_t _syncWordLength;
|
||||
|
||||
int16_t config();
|
||||
int16_t directMode();
|
||||
void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant);
|
||||
|
|
|
@ -3,8 +3,13 @@
|
|||
RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT, RF69_MAX_PACKET_LENGTH) {
|
||||
_mod = module;
|
||||
_tempOffset = 0;
|
||||
|
||||
_packetLengthQueried = false;
|
||||
_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) {
|
||||
|
@ -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
|
||||
uint8_t syncWord[] = {0x2D, 0x01};
|
||||
state = setSyncWord(syncWord, 2);
|
||||
uint8_t syncWord[] = RF69_DEFAULT_SYNC_WORD;
|
||||
state = setSyncWord(syncWord, sizeof(syncWord));
|
||||
if(state != ERR_NONE) {
|
||||
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) {
|
||||
// check constraints
|
||||
if((maxErrBits > 7) || (len > 8)) {
|
||||
if((maxErrBits > 7) || (len > RF69_MAX_SYNC_WORD_LENGTH)) {
|
||||
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
|
||||
int16_t state = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | (len - 1) << 3 | maxErrBits, 7, 0);
|
||||
if(state != ERR_NONE) {
|
||||
_syncWordLength = len;
|
||||
|
||||
int16_t state = enableSyncWordFiltering(maxErrBits);
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// set sync word
|
||||
// set sync word register
|
||||
_mod->SPIwriteRegisterBurst(RF69_REG_SYNC_VALUE_1, syncWord, len);
|
||||
return(ERR_NONE);
|
||||
}
|
||||
|
@ -636,6 +642,71 @@ int16_t RF69::variablePacketLengthMode(uint8_t maxLen) {
|
|||
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::setCrcFiltering(bool crcOn) {
|
||||
if (crcOn == true) {
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_CRC_ON, 4, 4));
|
||||
} else {
|
||||
return(_mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_CRC_OFF, 4, 4));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t RF69::setPromiscuousMode(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 = setCrcFiltering(false);
|
||||
} else {
|
||||
// enable preamble and sync word filtering and insertion
|
||||
state = enableSyncWordFiltering();
|
||||
if (state != ERR_NONE) {
|
||||
return(state);
|
||||
}
|
||||
|
||||
// enable CRC filtering
|
||||
state = setCrcFiltering(true);
|
||||
}
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::config() {
|
||||
int16_t state = ERR_NONE;
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#define RF69_CRYSTAL_FREQ 32.0
|
||||
#define RF69_DIV_EXPONENT 19
|
||||
#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
|
||||
#define RF69_REG_FIFO 0x00
|
||||
|
@ -646,7 +650,7 @@ class RF69: public PhysicalLayer {
|
|||
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.
|
||||
|
||||
|
@ -724,6 +728,40 @@ class RF69: public PhysicalLayer {
|
|||
*/
|
||||
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 maxErrBits = 0);
|
||||
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering();
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
||||
\param crcOn Set or unset promiscuous mode.
|
||||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool crcOn = true);
|
||||
|
||||
/*!
|
||||
\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 setPromiscuousMode(bool promiscuous = true);
|
||||
|
||||
protected:
|
||||
Module* _mod;
|
||||
|
||||
|
@ -735,6 +773,10 @@ class RF69: public PhysicalLayer {
|
|||
bool _packetLengthQueried;
|
||||
uint8_t _packetLengthConfig;
|
||||
|
||||
bool _promiscuous;
|
||||
|
||||
uint8_t _syncWordLength;
|
||||
|
||||
int16_t config();
|
||||
int16_t directMode();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue