[SX127x] Sync with LoRaLib v8.0.1

This commit is contained in:
jgromes 2019-03-22 19:01:56 +01:00
parent 943ea7ac03
commit 7a768c8ed6
13 changed files with 307 additions and 78 deletions

View file

@ -29,6 +29,7 @@ void setup() {
// current limit: 100 mA // current limit: 100 mA
// data shaping: Gaussian, BT = 0.3 // data shaping: Gaussian, BT = 0.3
// sync word: 0x2D 0x01 // sync word: 0x2D 0x01
// OOK modulation: false
int state = fsk.beginFSK(); int state = fsk.beginFSK();
if (state == ERR_NONE) { if (state == ERR_NONE) {
Serial.println(F("success!")); Serial.println(F("success!"));
@ -61,6 +62,19 @@ void setup() {
while (true); while (true);
} }
// FSK modulation can be changed to OOK
// NOTE: When using OOK, the maximum bit rate is only 32.768 kbps!
// Also, data shaping changes from Gaussian filter to
// simple filter with cutoff frequency. Make sure to call
// setDataShapingOOK() to set the correct shaping!
state = fsk.setOOK(true);
state = fsk.setDataShapingOOK(1);
if (state != ERR_NONE) {
Serial.print(F("Unable to change modulation, code "));
Serial.println(state);
while (true);
}
#warning "This sketch is just an API guide! Read the note at line 6." #warning "This sketch is just an API guide! Read the note at line 6."
} }

View file

@ -48,6 +48,9 @@ void loop() {
Serial.print(F("[SX1278] Waiting for incoming transmission ... ")); Serial.print(F("[SX1278] Waiting for incoming transmission ... "));
// you can receive data as an Arduino String // you can receive data as an Arduino String
// NOTE: receive() is a blocking method!
// See example ReceiveInterrupt for details
// on non-blocking reception method.
String str; String str;
int state = lora.receive(str); int state = lora.receive(str);

View file

@ -45,6 +45,9 @@ void loop() {
// you can transmit C-string or Arduino string up to // you can transmit C-string or Arduino string up to
// 256 characters long // 256 characters long
// NOTE: transmit() is a blocking method!
// See example SX127x_Transmit_Interrupt for details
// on non-blocking transmission method.
int state = lora.transmit("Hello World!"); int state = lora.transmit("Hello World!");
// you can also transmit byte array up to 256 bytes long // you can also transmit byte array up to 256 bytes long

View file

@ -79,6 +79,9 @@ setNodeAddress KEYWORD2
setBroadcastAddress KEYWORD2 setBroadcastAddress KEYWORD2
disableAddressFiltering KEYWORD2 disableAddressFiltering KEYWORD2
setDataShaping KEYWORD2 setDataShaping KEYWORD2
setOOK KEYWORD2
setDataShapingOOK KEYWORD2
setCRC KEYWORD2
# RF69-specific # RF69-specific
setAESKey KEYWORD2 setAESKey KEYWORD2
@ -162,6 +165,7 @@ ERR_INVALID_BIT_RATE_BW_RATIO LITERAL1
ERR_INVALID_RX_BANDWIDTH LITERAL1 ERR_INVALID_RX_BANDWIDTH LITERAL1
ERR_INVALID_SYNC_WORD LITERAL1 ERR_INVALID_SYNC_WORD LITERAL1
ERR_INVALID_DATA_SHAPING LITERAL1 ERR_INVALID_DATA_SHAPING LITERAL1
ERR_INVALID_MODULATION LITERAL1
ERR_AT_FAILED LITERAL1 ERR_AT_FAILED LITERAL1
ERR_URL_MALFORMED LITERAL1 ERR_URL_MALFORMED LITERAL1

View file

@ -10,20 +10,22 @@ Module::Module(int rx, int tx) {
ModuleSerial = new SoftwareSerial(_rx, _tx); ModuleSerial = new SoftwareSerial(_rx, _tx);
} }
Module::Module(int cs, int int0, int int1) { Module::Module(int cs, int int0, int int1, SPIClass& spi) {
_cs = cs; _cs = cs;
_rx = -1; _rx = -1;
_tx = -1; _tx = -1;
_int0 = int0; _int0 = int0;
_int1 = int1; _int1 = int1;
_spi = &spi;
} }
Module::Module(int cs, int rx, int tx, int int0, int int1) { Module::Module(int cs, int rx, int tx, int int0, int int1, SPIClass& spi) {
_cs = cs; _cs = cs;
_rx = rx; _rx = rx;
_tx = tx; _tx = tx;
_int0 = int0; _int0 = int0;
_int1 = int1; _int1 = int1;
_spi = &spi;
ModuleSerial = new SoftwareSerial(_rx, _tx); ModuleSerial = new SoftwareSerial(_rx, _tx);
} }
@ -33,7 +35,7 @@ void Module::init(uint8_t interface, uint8_t gpio) {
case USE_SPI: case USE_SPI:
pinMode(_cs, OUTPUT); pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);
SPI.begin(); _spi->begin();
break; break;
case USE_UART: case USE_UART:
ModuleSerial->begin(baudrate); ModuleSerial->begin(baudrate);
@ -58,6 +60,11 @@ void Module::init(uint8_t interface, uint8_t gpio) {
} }
} }
void Module::term() {
// stop SPI
_spi->end();
}
void Module::ATemptyBuffer() { void Module::ATemptyBuffer() {
while(ModuleSerial->available() > 0) { while(ModuleSerial->available() > 0) {
ModuleSerial->read(); ModuleSerial->read();
@ -160,39 +167,47 @@ int16_t Module::SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t
} }
void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) { void Module::SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes) {
digitalWrite(_cs, LOW); SPItransfer(SPIreadCommand, reg, NULL, inBytes, numBytes);
SPI.transfer(reg | SPIreadCommand);
for(uint8_t i = 0; i < numBytes; i++) {
inBytes[i] = SPI.transfer(reg);
}
digitalWrite(_cs, HIGH);
} }
uint8_t Module::SPIreadRegister(uint8_t reg) { uint8_t Module::SPIreadRegister(uint8_t reg) {
uint8_t inByte; uint8_t resp;
digitalWrite(_cs, LOW); SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0)); return(resp);
SPI.transfer(reg | SPIreadCommand);
SPI.endTransaction();
inByte = SPI.transfer(0x00);
digitalWrite(_cs, HIGH);
return(inByte);
} }
void Module::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes) { void Module::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes) {
digitalWrite(_cs, LOW); SPItransfer(SPIwriteCommand, reg, data, NULL, numBytes);
SPI.transfer(reg | SPIwriteCommand);
for(uint8_t i = 0; i < numBytes; i++) {
SPI.transfer(data[i]);
}
digitalWrite(_cs, HIGH);
} }
void Module::SPIwriteRegister(uint8_t reg, uint8_t data) { void Module::SPIwriteRegister(uint8_t reg, uint8_t data) {
digitalWrite(_cs, LOW); SPItransfer(SPIwriteCommand, reg, &data, NULL, 1);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0)); }
SPI.transfer(reg | SPIwriteCommand);
SPI.transfer(data); void Module::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {
SPI.endTransaction(); // start SPI transaction
digitalWrite(_cs, HIGH); _spi->beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
// pull CS low
digitalWrite(_cs, LOW);
// send SPI register address with access command
_spi->transfer(reg | cmd);
// send data or get response
if(cmd == SPIwriteCommand) {
for(size_t n = 0; n < numBytes; n++) {
_spi->transfer(dataOut[n]);
}
} else if (cmd == SPIreadCommand) {
for(size_t n = 0; n < numBytes; n++) {
dataIn[n] = _spi->transfer(0x00);
}
}
// release CS
digitalWrite(_cs, HIGH);
// end SPI transaction
_spi->endTransaction();
} }

View file

@ -10,8 +10,8 @@
class Module { class Module {
public: public:
Module(int tx, int rx); Module(int tx, int rx);
Module(int cs, int int0, int int1); Module(int cs, int int0, int int1, SPIClass& spi = SPI);
Module(int cs, int rx, int tx, int int0, int int1); Module(int cs, int rx, int tx, int int0, int int1, SPIClass& spi = SPI);
SoftwareSerial* ModuleSerial; SoftwareSerial* ModuleSerial;
@ -22,6 +22,7 @@ class Module {
uint8_t SPIwriteCommand = 0b10000000; uint8_t SPIwriteCommand = 0b10000000;
void init(uint8_t interface, uint8_t gpio); void init(uint8_t interface, uint8_t gpio);
void term();
void ATemptyBuffer(); void ATemptyBuffer();
bool ATgetResponse(); bool ATgetResponse();
@ -37,6 +38,8 @@ class Module {
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes); void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes);
void SPIwriteRegister(uint8_t reg, uint8_t data); void SPIwriteRegister(uint8_t reg, uint8_t data);
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes);
int getCs() const { return(_cs); } int getCs() const { return(_cs); }
int getInt0() const { return(_int0); } int getInt0() const { return(_int0); }
int getInt1() const { return(_int1); } int getInt1() const { return(_int1); }
@ -48,6 +51,8 @@ class Module {
int _int0; int _int0;
int _int1; int _int1;
SPIClass* _spi;
uint32_t _ATtimeout = 15000; uint32_t _ATtimeout = 15000;
}; };

View file

@ -70,6 +70,7 @@
#define ERR_INVALID_RX_BANDWIDTH -104 #define ERR_INVALID_RX_BANDWIDTH -104
#define ERR_INVALID_SYNC_WORD -105 #define ERR_INVALID_SYNC_WORD -105
#define ERR_INVALID_DATA_SHAPING -106 #define ERR_INVALID_DATA_SHAPING -106
#define ERR_INVALID_MODULATION -107
// ESP8266 status codes // ESP8266 status codes
#define ERR_AT_FAILED -201 #define ERR_AT_FAILED -201

View file

@ -58,9 +58,9 @@ int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
return(state); return(state);
} }
int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t currentLimit, float sh) { int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t power, uint8_t currentLimit, bool enableOOK) {
// execute common part // execute common part
int16_t state = SX127x::beginFSK(SX1272_CHIP_VERSION, br, rxBw, freqDev, currentLimit); int16_t state = SX127x::beginFSK(SX1272_CHIP_VERSION, br, rxBw, freqDev, currentLimit, enableOOK);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -82,11 +82,6 @@ int16_t SX1272::beginFSK(float freq, float br, float rxBw, float freqDev, int8_t
return(state); return(state);
} }
state = setDataShaping(sh);
if(state != ERR_NONE) {
return(state);
}
return(state); return(state);
} }
@ -268,6 +263,11 @@ int16_t SX1272::setDataShaping(float sh) {
return(ERR_WRONG_MODEM); return(ERR_WRONG_MODEM);
} }
// check modulation
if(!SX127x::_ook) {
return(ERR_INVALID_MODULATION);
}
// set mode to standby // set mode to standby
int16_t state = SX127x::standby(); int16_t state = SX127x::standby();
@ -286,6 +286,39 @@ int16_t SX1272::setDataShaping(float sh) {
return(state); return(state);
} }
int16_t SX1272::setDataShapingOOK(uint8_t sh) {
// check active modem
if(getActiveModem() != SX127X_FSK_OOK) {
return(ERR_WRONG_MODEM);
}
// check modulation
if(!SX127x::_ook) {
return(ERR_INVALID_MODULATION);
}
// set mode to standby
int16_t state = SX127x::standby();
// set data shaping
switch(sh) {
case 0:
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1272_NO_SHAPING, 4, 3);
break;
case 1:
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1272_OOK_FILTER_BR, 4, 3);
break;
case 2:
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1272_OOK_FILTER_2BR, 4, 3);
break;
default:
state = ERR_INVALID_DATA_SHAPING;
break;
}
return(state);
}
int8_t SX1272::getRSSI() { int8_t SX1272::getRSSI() {
// check active modem // check active modem
if(getActiveModem() != SX127X_LORA) { if(getActiveModem() != SX127X_LORA) {
@ -304,6 +337,24 @@ int8_t SX1272::getRSSI() {
return(lastPacketRSSI); return(lastPacketRSSI);
} }
int16_t SX1272::setCRC(bool enableCRC) {
if(getActiveModem() == SX127X_LORA) {
// set LoRa CRC
if(enableCRC) {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_RX_CRC_MODE_ON, 2, 2));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1272_RX_CRC_MODE_OFF, 2, 2));
}
} else {
// set FSK CRC
if(enableCRC) {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4));
}
}
}
int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) { int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) {
// set mode to standby // set mode to standby
int16_t state = SX127x::standby(); int16_t state = SX127x::standby();
@ -319,7 +370,7 @@ int16_t SX1272::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
// write registers // write registers
if(newSpreadingFactor == SX127X_SF_6) { if(newSpreadingFactor == SX127X_SF_6) {
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_IMPL_MODE | SX1272_RX_CRC_MODE_OFF, 2, 1); state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1272_HEADER_IMPL_MODE | SX1272_RX_CRC_MODE_ON, 2, 1);
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE, 7, 3); state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE, 7, 3);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0); state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6); state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6);

View file

@ -148,11 +148,11 @@ class SX1272: public SX127x {
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA. \param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
Set to 0 to disable OCP (not recommended). Set to 0 to disable OCP (not recommended).
\param sh Gaussian shaping bandwidth-time product that will be used for data shaping. Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping. \param enableOOK Use OOK modulation instead of FSK.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t beginFSK(float freq = 915.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 13, uint8_t currentLimit = 100, float sh = 0.3); int16_t beginFSK(float freq = 915.0, float br = 48.0, float rxBw = 125.0, float freqDev = 50.0, int8_t power = 13, uint8_t currentLimit = 100, bool enableOOK = false);
// configuration methods // configuration methods
@ -212,8 +212,8 @@ class SX1272: public SX127x {
int16_t setGain(uint8_t gain); int16_t setGain(uint8_t gain);
/*! /*!
\brief Sets gaussian shaping bandwidth-time product that will be used for data shaping. \brief Sets Gaussian filter bandwidth-time product that will be used for data shaping.
Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping. Only available in FSK mode. Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping. Only available in FSK mode with FSK modulation.
\param sh Gaussian shaping bandwidth-time product that will be used for data shaping \param sh Gaussian shaping bandwidth-time product that will be used for data shaping
@ -221,12 +221,32 @@ class SX1272: public SX127x {
*/ */
int16_t setDataShaping(float sh); int16_t setDataShaping(float sh);
/*!
\brief Sets filter cutoff frequency that will be used for data shaping.
Allowed values are 1 for frequency equal to bit rate and 2 for frequency equal to 2x bit rate. Set to 0 to disable data shaping.
Only available in FSK mode with OOK modulation.
\param sh Cutoff frequency that will be used for data shaping
\returns \ref status_codes
*/
int16_t setDataShapingOOK(uint8_t sh);
/*! /*!
\brief Gets recorded signal strength indicator of the latest received packet. \brief Gets recorded signal strength indicator of the latest received packet.
\returns Last packet recorded signal strength indicator (RSSI). \returns Last packet recorded signal strength indicator (RSSI).
*/ */
int8_t getRSSI(); int8_t getRSSI();
/*!
\brief Enables/disables CRC check of received packets.
\param enableCRC Enable (true) or disable (false) CRC.
\returns \ref status_codes
*/
int16_t setCRC(bool enableCRC);
protected: protected:
int16_t setBandwidthRaw(uint8_t newBandwidth); int16_t setBandwidthRaw(uint8_t newBandwidth);

View file

@ -51,9 +51,9 @@ int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
return(state); return(state);
} }
int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t currentLimit, float sh) { int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint8_t currentLimit, bool enableOOK) {
// execute common part // execute common part
int16_t state = SX127x::beginFSK(SX1278_CHIP_VERSION, br, freqDev, rxBw, currentLimit); int16_t state = SX127x::beginFSK(SX1278_CHIP_VERSION, br, freqDev, rxBw, currentLimit, enableOOK);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
@ -75,11 +75,6 @@ int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
return(state); return(state);
} }
state = setDataShaping(sh);
if(state != ERR_NONE) {
return(state);
}
return(state); return(state);
} }
@ -338,6 +333,11 @@ int16_t SX1278::setDataShaping(float sh) {
return(ERR_WRONG_MODEM); return(ERR_WRONG_MODEM);
} }
// check modulation
if(SX127x::_ook) {
return(ERR_INVALID_MODULATION);
}
// set mode to standby // set mode to standby
int16_t state = SX127x::standby(); int16_t state = SX127x::standby();
@ -356,6 +356,38 @@ int16_t SX1278::setDataShaping(float sh) {
return(state); return(state);
} }
int16_t SX1278::setDataShapingOOK(uint8_t sh) {
// check active modem
if(getActiveModem() != SX127X_FSK_OOK) {
return(ERR_WRONG_MODEM);
}
// check modulation
if(!SX127x::_ook) {
return(ERR_INVALID_MODULATION);
}
// set mode to standby
int16_t state = SX127x::standby();
// set data shaping
switch(sh) {
case 0:
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_NO_SHAPING, 6, 5);
break;
case 1:
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_OOK_FILTER_BR, 6, 5);
break;
case 2:
state |= _mod->SPIsetRegValue(SX127X_REG_PA_RAMP, SX1278_OOK_FILTER_2BR, 6, 5);
break;
default:
return(ERR_INVALID_DATA_SHAPING);
}
return(state);
}
int8_t SX1278::getRSSI() { int8_t SX1278::getRSSI() {
// check active modem // check active modem
if(getActiveModem() != SX127X_LORA) { if(getActiveModem() != SX127X_LORA) {
@ -381,6 +413,24 @@ int8_t SX1278::getRSSI() {
return(lastPacketRSSI); return(lastPacketRSSI);
} }
int16_t SX1278::setCRC(bool enableCRC) {
if(getActiveModem() == SX127X_LORA) {
// set LoRa CRC
if(enableCRC) {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_ON, 2, 2));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX1278_RX_CRC_MODE_OFF, 2, 2));
}
} else {
// set FSK CRC
if(enableCRC) {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_ON, 4, 4));
} else {
return(_mod->SPIsetRegValue(SX127X_REG_PACKET_CONFIG_1, SX127X_CRC_OFF, 4, 4));
}
}
}
int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) { int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) {
// set mode to standby // set mode to standby
int16_t state = SX127x::standby(); int16_t state = SX127x::standby();
@ -397,12 +447,12 @@ int16_t SX1278::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
// write registers // write registers
if(newSpreadingFactor == SX127X_SF_6) { if(newSpreadingFactor == SX127X_SF_6) {
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1278_HEADER_IMPL_MODE, 0, 0); state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1278_HEADER_IMPL_MODE, 0, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_OFF, 7, 2); state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, SX127X_SF_6 | SX127X_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_ON, 7, 2);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0); state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6); state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_6);
} else { } else {
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1278_HEADER_EXPL_MODE, 0, 0); state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_1, SX1278_HEADER_EXPL_MODE, 0, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | SX127X_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_OFF, 7, 2); state |= _mod->SPIsetRegValue(SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | SX127X_TX_MODE_SINGLE | SX1278_RX_CRC_MODE_ON, 7, 2);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0); state |= _mod->SPIsetRegValue(SX127X_REG_DETECT_OPTIMIZE, SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12); state |= _mod->SPIsetRegValue(SX127X_REG_DETECTION_THRESHOLD, SX127X_DETECTION_THRESHOLD_SF_7_12);
} }

View file

@ -157,11 +157,11 @@ class SX1278: public SX127x {
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA. \param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
Set to 0 to disable OCP (not recommended). Set to 0 to disable OCP (not recommended).
\param sh Gaussian shaping bandwidth-time product that will be used for data shaping. Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping. \param enableOOK Use OOK modulation instead of FSK.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 13, uint8_t currentLimit = 100, float sh = 0.3); int16_t beginFSK(float freq = 434.0, float br = 48.0, float freqDev = 50.0, float rxBw = 125.0, int8_t power = 13, uint8_t currentLimit = 100, bool enableOOK = false);
// configuration methods // configuration methods
@ -221,8 +221,8 @@ class SX1278: public SX127x {
int16_t setGain(uint8_t gain); int16_t setGain(uint8_t gain);
/*! /*!
\brief Sets gaussian shaping bandwidth-time product that will be used for data shaping. \brief Sets Gaussian filter bandwidth-time product that will be used for data shaping.
Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping. Only available in FSK mode. Allowed values are 0.3, 0.5 or 1.0. Set to 0 to disable data shaping. Only available in FSK mode with FSK modulation.
\param sh Gaussian shaping bandwidth-time product that will be used for data shaping \param sh Gaussian shaping bandwidth-time product that will be used for data shaping
@ -230,12 +230,32 @@ class SX1278: public SX127x {
*/ */
int16_t setDataShaping(float sh); int16_t setDataShaping(float sh);
/*!
\brief Sets filter cutoff frequency that will be used for data shaping.
Allowed values are 1 for frequency equal to bit rate and 2 for frequency equal to 2x bit rate. Set to 0 to disable data shaping.
Only available in FSK mode with OOK modulation.
\param sh Cutoff frequency that will be used for data shaping
\returns \ref status_codes
*/
int16_t setDataShapingOOK(uint8_t sh);
/*! /*!
\brief Gets recorded signal strength indicator of the latest received packet. \brief Gets recorded signal strength indicator of the latest received packet.
\returns Last packet recorded signal strength indicator (RSSI). \returns Last packet recorded signal strength indicator (RSSI).
*/ */
int8_t getRSSI(); int8_t getRSSI();
/*!
\brief Enables/disables CRC check of received packets.
\param enableCRC Enable (true) or disable (false) CRC.
\returns \ref status_codes
*/
int16_t setCRC(bool enableCRC);
protected: protected:
int16_t setBandwidthRaw(uint8_t newBandwidth); int16_t setBandwidthRaw(uint8_t newBandwidth);

View file

@ -10,11 +10,11 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
// try to find the SX127x chip // try to find the SX127x chip
if(!SX127x::findChip(chipVersion)) { if(!SX127x::findChip(chipVersion)) {
DEBUG_PRINTLN(F("No SX127x found!")); DEBUG_PRINTLN("No SX127x found!");
SPI.end(); _mod->term();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } else {
DEBUG_PRINTLN(F("Found SX127x!")); DEBUG_PRINTLN("Found SX127x!");
} }
// check active modem // check active modem
@ -48,17 +48,17 @@ int16_t SX127x::begin(uint8_t chipVersion, uint8_t syncWord, uint8_t currentLimi
return(state); return(state);
} }
int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit) { int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, bool enableOOK) {
// set module properties // set module properties
_mod->init(USE_SPI, INT_BOTH); _mod->init(USE_SPI, INT_BOTH);
// try to find the SX127x chip // try to find the SX127x chip
if(!SX127x::findChip(chipVersion)) { if(!SX127x::findChip(chipVersion)) {
DEBUG_PRINTLN(F("No SX127x found!")); DEBUG_PRINTLN("No SX127x found!");
SPI.end(); _mod->term();
return(ERR_CHIP_NOT_FOUND); return(ERR_CHIP_NOT_FOUND);
} else { } else {
DEBUG_PRINTLN(F("Found SX127x!")); DEBUG_PRINTLN("Found SX127x!");
} }
// check currently active modem // check currently active modem
@ -104,6 +104,12 @@ int16_t SX127x::beginFSK(uint8_t chipVersion, float br, float freqDev, float rxB
// disable address filtering // disable address filtering
state = disableAddressFiltering(); state = disableAddressFiltering();
if(state != ERR_NONE) {
return(state);
}
// enable/disable OOK
state = setOOK(enableOOK);
return(state); return(state);
} }
@ -208,6 +214,7 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
while(!digitalRead(_mod->getInt0())) { while(!digitalRead(_mod->getInt0())) {
if(millis() - start > timeout) { if(millis() - start > timeout) {
clearIRQFlags(); clearIRQFlags();
standby();
return(ERR_TX_TIMEOUT); return(ERR_TX_TIMEOUT);
} }
} }
@ -215,7 +222,10 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
// clear interrupt flags // clear interrupt flags
clearIRQFlags(); clearIRQFlags();
return(ERR_NONE); // set mode to standby to disable transmitter
state |= standby();
return(state);
} }
return(ERR_UNKNOWN); return(ERR_UNKNOWN);
@ -785,8 +795,14 @@ int16_t SX127x::setBitRate(float br) {
} }
// check allowed bitrate // check allowed bitrate
if((br < 1.2) || (br > 300.0)) { if(_ook) {
return(ERR_INVALID_BIT_RATE); if((br < 1.2) || (br > 32.768)) {
return(ERR_INVALID_BIT_RATE);
}
} else {
if((br < 1.2) || (br > 300.0)) {
return(ERR_INVALID_BIT_RATE);
}
} }
// set mode to STANDBY // set mode to STANDBY
@ -794,12 +810,13 @@ int16_t SX127x::setBitRate(float br) {
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }
// set bit rate // set bit rate
uint16_t bitRate = 32000 / br; uint16_t bitRate = (SX127X_CRYSTAL_FREQ * 1000.0) / br;
state = _mod->SPIsetRegValue(SX127X_REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8, 7, 0); state = _mod->SPIsetRegValue(SX127X_REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8, 7, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_BITRATE_LSB, bitRate & 0x00FF, 7, 0); state |= _mod->SPIsetRegValue(SX127X_REG_BITRATE_LSB, bitRate & 0x00FF, 7, 0);
// TODO: fractional part of bit rate setting
// TODO: fractional part of bit rate setting (not in OOK)
if(state == ERR_NONE) { if(state == ERR_NONE) {
SX127x::_br = br; SX127x::_br = br;
} }
@ -899,7 +916,7 @@ int16_t SX127x::setSyncWord(uint8_t* syncWord, size_t len) {
} }
// set sync word // set sync word
_mod->SPIwriteRegisterBurst(SX127X_SYNC_VALUE_1, syncWord, len); _mod->SPIwriteRegisterBurst(SX127X_REG_SYNC_VALUE_1, syncWord, len);
return(ERR_NONE); return(ERR_NONE);
} }
@ -957,6 +974,26 @@ int16_t SX127x::disableAddressFiltering() {
return(_mod->SPIsetRegValue(SX127X_REG_BROADCAST_ADRS, 0x00)); return(_mod->SPIsetRegValue(SX127X_REG_BROADCAST_ADRS, 0x00));
} }
int16_t SX127x::setOOK(bool enableOOK) {
// check active modem
if(getActiveModem() != SX127X_FSK_OOK) {
return(ERR_WRONG_MODEM);
}
// set OOK and if successful, save the new setting
int16_t state = ERR_NONE;
if(enableOOK) {
state = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX127X_MODULATION_OOK, 6, 5, 5);
} else {
state = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX127X_MODULATION_FSK, 6, 5, 5);
}
if(state == ERR_NONE) {
_ook = enableOOK;
}
return(state);
}
int16_t SX127x::setFrequencyRaw(float newFreq) { int16_t SX127x::setFrequencyRaw(float newFreq) {
// set mode to standby // set mode to standby
int16_t state = setMode(SX127X_STANDBY); int16_t state = setMode(SX127X_STANDBY);
@ -978,14 +1015,8 @@ int16_t SX127x::config() {
} }
int16_t SX127x::configFSK() { int16_t SX127x::configFSK() {
// set FSK modulation
int16_t state = _mod->SPIsetRegValue(SX127X_REG_OP_MODE, SX127X_MODULATION_FSK, 6, 5, 5);
if(state != ERR_NONE) {
return(state);
}
// set RSSI threshold // set RSSI threshold
state = _mod->SPIsetRegValue(SX127X_REG_RSSI_THRESH, SX127X_RSSI_THRESHOLD); int16_t state = _mod->SPIsetRegValue(SX127X_REG_RSSI_THRESH, SX127X_RSSI_THRESHOLD);
if(state != ERR_NONE) { if(state != ERR_NONE) {
return(state); return(state);
} }

View file

@ -572,9 +572,11 @@ class SX127x: public PhysicalLayer {
\param currentLimit Trim value for OCP (over current protection) in mA. \param currentLimit Trim value for OCP (over current protection) in mA.
\param enableOOK Flag to specify OOK mode. This modulation is similar to FSK.
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit); int16_t beginFSK(uint8_t chipVersion, float br, float freqDev, float rxBw, uint8_t currentLimit, bool enableOOK);
/*! /*!
\brief Binary transmit method. Will transmit arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem. \brief Binary transmit method. Will transmit arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
@ -848,6 +850,15 @@ class SX127x: public PhysicalLayer {
*/ */
int16_t disableAddressFiltering(); int16_t disableAddressFiltering();
/*!
\brief Enables/disables OOK modulation instead of FSK.
\param enableOOK Enable (true) or disable (false) OOK.
\returns \ref status_codes
*/
int16_t setOOK(bool enableOOK);
#ifdef RADIOLIB_DEBUG #ifdef RADIOLIB_DEBUG
void regDump(); void regDump();
#endif #endif
@ -861,6 +872,7 @@ class SX127x: public PhysicalLayer {
uint8_t _cr; uint8_t _cr;
float _br; float _br;
float _rxBw; float _rxBw;
bool _ook;
int16_t tx(char* data, uint8_t length); int16_t tx(char* data, uint8_t length);
int16_t rxSingle(char* data, uint8_t* length); int16_t rxSingle(char* data, uint8_t* length);