diff --git a/README.md b/README.md index 5e67821d..ab9cfdb7 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x * __Raspberry Pi__ * [__RP2040__](https://github.com/arduino/ArduinoCore-mbed) - Raspberry Pi Pico and Arduino Nano RP2040 Connect + * [__Raspberry Pi__](https://github.com/me-no-dev/RasPiArduino) - Arduino framework for RaspberryPI * __Heltec__ * [__CubeCell__](https://github.com/HelTecAutomation/CubeCell-Arduino) - ASR650X series (CubeCell-Board, CubeCell-Capsule, CubeCell-Module etc.) diff --git a/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino b/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino index e52630a5..65ae79a2 100644 --- a/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino +++ b/examples/CC1101/CC1101_Receive_Interrupt/CC1101_Receive_Interrupt.ino @@ -82,6 +82,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino b/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino index 29719ade..1d993a77 100644 --- a/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino +++ b/examples/CC1101/CC1101_Transmit_Interrupt/CC1101_Transmit_Interrupt.ino @@ -75,6 +75,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/RF69/RF69_Receive_Interrupt/RF69_Receive_Interrupt.ino b/examples/RF69/RF69_Receive_Interrupt/RF69_Receive_Interrupt.ino index 12d5de5d..da520351 100644 --- a/examples/RF69/RF69_Receive_Interrupt/RF69_Receive_Interrupt.ino +++ b/examples/RF69/RF69_Receive_Interrupt/RF69_Receive_Interrupt.ino @@ -74,6 +74,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino b/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino index eb54a541..6ae3fa1c 100644 --- a/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino +++ b/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino @@ -91,6 +91,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino b/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino index ed658daa..f7763773 100644 --- a/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino +++ b/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino @@ -71,6 +71,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX126x/SX126x_Receive_Interrupt/SX126x_Receive_Interrupt.ino b/examples/SX126x/SX126x_Receive_Interrupt/SX126x_Receive_Interrupt.ino index d50f2849..4132617c 100644 --- a/examples/SX126x/SX126x_Receive_Interrupt/SX126x_Receive_Interrupt.ino +++ b/examples/SX126x/SX126x_Receive_Interrupt/SX126x_Receive_Interrupt.ino @@ -88,6 +88,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX126x/SX126x_Transmit_Interrupt/SX126x_Transmit_Interrupt.ino b/examples/SX126x/SX126x_Transmit_Interrupt/SX126x_Transmit_Interrupt.ino index 19e76817..69fd17c7 100644 --- a/examples/SX126x/SX126x_Transmit_Interrupt/SX126x_Transmit_Interrupt.ino +++ b/examples/SX126x/SX126x_Transmit_Interrupt/SX126x_Transmit_Interrupt.ino @@ -80,6 +80,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX127x/SX127x_Channel_Activity_Detection_Interrupt/SX127x_Channel_Activity_Detection_Interrupt.ino b/examples/SX127x/SX127x_Channel_Activity_Detection_Interrupt/SX127x_Channel_Activity_Detection_Interrupt.ino index 30f945e4..55372452 100644 --- a/examples/SX127x/SX127x_Channel_Activity_Detection_Interrupt/SX127x_Channel_Activity_Detection_Interrupt.ino +++ b/examples/SX127x/SX127x_Channel_Activity_Detection_Interrupt/SX127x_Channel_Activity_Detection_Interrupt.ino @@ -79,6 +79,9 @@ volatile bool enableInterrupt = true; // is detected within timeout period // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlagTimeout(void) { // check if the interrupt is enabled if(!enableInterrupt) { @@ -115,14 +118,14 @@ void loop() { // LoRa preamble was detected Serial.print(F("[SX1278] Preamble detected!")); - + } - + // check if we need to restart channel activity detection if(detectedFlag || timeoutFlag) { // start scanning the channel Serial.print(F("[SX1278] Starting scan for LoRa preamble ... ")); - + // start scanning current channel int state = radio.startChannelScan(); if (state == RADIOLIB_ERR_NONE) { @@ -131,6 +134,6 @@ void loop() { Serial.print(F("failed, code ")); Serial.println(state); } - + } } diff --git a/examples/SX127x/SX127x_PingPong/SX127x_PingPong.ino b/examples/SX127x/SX127x_PingPong/SX127x_PingPong.ino index cd505a06..e403c902 100644 --- a/examples/SX127x/SX127x_PingPong/SX127x_PingPong.ino +++ b/examples/SX127x/SX127x_PingPong/SX127x_PingPong.ino @@ -48,7 +48,7 @@ void setFlag(void) { return; } - // we sent aor received packet, set the flag + // we sent or received packet, set the flag operationDone = true; } @@ -105,17 +105,17 @@ void loop() { if (transmissionState == RADIOLIB_ERR_NONE) { // packet was successfully sent Serial.println(F("transmission finished!")); - + } else { Serial.print(F("failed, code ")); Serial.println(transmissionState); - + } // listen for response radio.startReceive(); transmitFlag = false; - + } else { // the previous operation was reception // print data and send another packet @@ -125,21 +125,21 @@ void loop() { if (state == RADIOLIB_ERR_NONE) { // packet was successfully received Serial.println(F("[SX1278] Received packet!")); - + // print data of the packet Serial.print(F("[SX1278] Data:\t\t")); Serial.println(str); - + // print RSSI (Received Signal Strength Indicator) Serial.print(F("[SX1278] RSSI:\t\t")); Serial.print(radio.getRSSI()); Serial.println(F(" dBm")); - + // print SNR (Signal-to-Noise Ratio) Serial.print(F("[SX1278] SNR:\t\t")); Serial.print(radio.getSNR()); Serial.println(F(" dB")); - + } // wait a second before transmitting again @@ -154,6 +154,6 @@ void loop() { // we're ready to process more packets, // enable interrupt service routine enableInterrupt = true; - + } } diff --git a/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino b/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino new file mode 100644 index 00000000..3aeca4a8 --- /dev/null +++ b/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino @@ -0,0 +1,180 @@ +/* + RadioLib SX127x Transmit with Frequency Hopping Example + + This example transmits packets using SX1278 LoRa radio module. + Each packet contains up to 256 bytes of data, in the form of: + - Arduino String + - null-terminated char array (C-string) + - arbitrary binary data (byte array) + + Other modules from SX127x/RFM9x family can also be used. + + For default module settings, see the wiki page + https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx127xrfm9x---lora-modem + + For full API reference, see the GitHub Pages + https://jgromes.github.io/RadioLib/ + + SX127x supports FHSS or Frequency Hopping Spread Spectrum. + Once a hopping period is set and a transmission is started, the radio + will begin triggering interrupts every hop period where the radio frequency + is changed to the next channel. +*/ + +#include + +// SX1278 has the following connections: +// NSS pin: 10 +// DIO0 pin: 2 +// RESET pin: 9 +// DIO1 pin: 3 +SX1278 radio = new Module(10, 2, 9, 3); + +// or using RadioShield +// https://github.com/jgromes/RadioShield +//SX1278 radio = RadioShield.ModuleA; + +// flag to indicate that a packet was received +volatile bool receivedFlag = false; + +// flag to indicate frequency must be changed +volatile bool fhssChangeFlag = false; + +// the channel frequencies can be generated randomly or hard coded +// NOTE: The frequency list MUST be the same on both sides! +float channels[] = { 433.0, 433.4, 433.2, 433.6, 434.0, 433.8 }; +int numberOfChannels = sizeof(channels) / sizeof(float); + +// counter to keep track of how many frequency hops were performed +int hopsCompleted = 0; + +// this function is called when a complete packet +// is received by the module +// IMPORTANT: this function MUST be 'void' type +// and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif +void setRxFlag(void) { + receivedFlag = true; +} + +// this function is called when FhssChangeChannel interrupt occurs +// (at the beginning of each transmission) +// IMPORTANT: this function MUST be 'void' type +// and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif +void setFHSSFlag(void) { + fhssChangeFlag = true; +} + +void setup() { + Serial.begin(9600); + + // begin radio on home channel + Serial.print(F("[SX1278] Initializing ... ")); + int state = radio.begin(channels[0]); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set hop period in symbols + // this will also enable FHSS + state = radio.setFHSSHoppingPeriod(9); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set the function to call when reception is finished + radio.setDio0Action(setRxFlag); + + // set the function to call when we need to hcange frequency + radio.setDio1Action(setFHSSFlag); + + // start listening for LoRa packets + Serial.print(F("[SX1278] Starting to listen ... ")); + state = radio.startReceive(); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } +} + +void loop() { + // check if the reception flag is set + if (receivedFlag == true) { + // you can read received data as an Arduino String + String str; + int state = radio.readData(str); + + // you can also read received data as byte array + /* + byte byteArr[8]; + int state = radio.readData(byteArr, 8); + */ + + if (state == RADIOLIB_ERR_NONE) { + // packet was successfully received + Serial.println(F("[SX1278] Received packet!")); + + // print data of the packet + Serial.print(F("[SX1278] Data:\t\t")); + Serial.println(str); + + } else if (state == RADIOLIB_ERR_CRC_MISMATCH) { + // packet was received, but is malformed + Serial.println(F("[SX1278] CRC error!")); + + } else { + // some other error occurred + Serial.print(F("[SX1278] Failed, code ")); + Serial.println(state); + + } + + // print the number of hops it took + Serial.print(F("[SX1278] Hops completed: ")); + Serial.println(hopsCompleted); + + // reset the counter + hopsCompleted = 0; + + // put the module back to listen mode + radio.startReceive(); + + // we're ready to receive more packets, clear the flag + receivedFlag = false; + } + + // check if we need to do another frequency hop + if (fhssChangeFlag == true) { + // we do, change it now + int state = radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); + if (state != RADIOLIB_ERR_NONE) { + Serial.print(F("[SX1278] Failed to change frequency, code ")); + Serial.println(state); + } + + // increment the counter + hopsCompleted++; + + // clear the FHSS interrupt + radio.clearFHSSInt(); + + // we're ready to do another hop, clear the flag + fhssChangeFlag = false; + } +} diff --git a/examples/SX127x/SX127x_Receive_Interrupt/SX127x_Receive_Interrupt.ino b/examples/SX127x/SX127x_Receive_Interrupt/SX127x_Receive_Interrupt.ino index 9db3eaf3..e3228970 100644 --- a/examples/SX127x/SX127x_Receive_Interrupt/SX127x_Receive_Interrupt.ino +++ b/examples/SX127x/SX127x_Receive_Interrupt/SX127x_Receive_Interrupt.ino @@ -85,6 +85,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino b/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino new file mode 100644 index 00000000..b6182af5 --- /dev/null +++ b/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino @@ -0,0 +1,180 @@ +/* + RadioLib SX127x Transmit with Frequency Hopping Example + + This example transmits packets using SX1278 LoRa radio module. + Each packet contains up to 256 bytes of data, in the form of: + - Arduino String + - null-terminated char array (C-string) + - arbitrary binary data (byte array) + + Other modules from SX127x/RFM9x family can also be used. + + For default module settings, see the wiki page + https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx127xrfm9x---lora-modem + + For full API reference, see the GitHub Pages + https://jgromes.github.io/RadioLib/ + + SX127x supports FHSS or Frequency Hopping Spread Spectrum. + Once a hopping period is set and a transmission is started, the radio + will begin triggering interrupts every hop period where the radio frequency + is changed to the next channel. +*/ + +#include + +// SX1278 has the following connections: +// NSS pin: 10 +// DIO0 pin: 2 +// RESET pin: 9 +// DIO1 pin: 3 +SX1278 radio = new Module(10, 2, 9, 3); + +// or using RadioShield +// https://github.com/jgromes/RadioShield +//SX1278 radio = RadioShield.ModuleA; + +// flag to indicate that a packet was received +volatile bool transmittedFlag = false; + +// flag to indicate frequency must be changed +volatile bool fhssChangeFlag = false; + +// the channel frequencies can be generated randomly or hard coded +// NOTE: The frequency list MUST be the same on both sides! +float channels[] = { 433.0, 433.4, 433.2, 433.6, 434.0, 433.8 }; +int numberOfChannels = sizeof(channels) / sizeof(float); + +// counter to keep track of how many frequency hops were performed +int hopsCompleted = 0; + +// counter that increments with each sent packet +int packetCounter = 0; + +// save transmission state between loops +int transmissionState = RADIOLIB_ERR_NONE; + +// this is the packet that will be sent +String longPacket = "Let's create a really long packet to trigger \ +lots of hop interrupts. A packet can be up to 256 bytes long. \ +This packet is 222 bytes so using sf = 9, bw = 125, timeOnAir is \ +1488ms. 1488ms / (9*4.10ms) = 40 hops. Counter: "; + +// this function is called when a complete packet +// is transmitted by the module +// IMPORTANT: this function MUST be 'void' type +// and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif +void setTxFlag(void) { + transmittedFlag = true; +} + +// this function is called when FhssChangeChannel interrupt occurs +// (at the beginning of each transmission) +// IMPORTANT: this function MUST be 'void' type +// and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif +void setFHSSFlag(void) { + fhssChangeFlag = true; +} + +void setup() { + Serial.begin(9600); + + // begin radio on home channel + Serial.print(F("[SX1278] Initializing ... ")); + int state = radio.begin(channels[0]); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set hop period in symbols + // this will also enable FHSS + state = radio.setFHSSHoppingPeriod(9); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + + // set the function to call when transmission is finished + radio.setDio0Action(setTxFlag); + + // set the function to call when we need to hcange frequency + radio.setDio1Action(setFHSSFlag); + + // start transmitting the first packet + Serial.print(F("[SX1278] Sending first packet ... ")); + transmissionState = radio.startTransmit(longPacket + packetCounter); +} + +void loop() { + // check if the transmission flag is set + if (transmittedFlag == true) { + // reset flag + transmittedFlag = false; + + if (transmissionState == RADIOLIB_ERR_NONE) { + // packet was successfully sent + Serial.println(F("transmission finished!")); + + } else { + Serial.print(F("failed, code ")); + Serial.println(transmissionState); + + } + + // The channel is automatically reset to 0 upon completion + Serial.print(F("[SX1278] Radio is on channel: ")); + Serial.println(radio.getFHSSChannel()); + + // print the number of hops it took + Serial.print(F("[SX1278] Hops completed: ")); + Serial.println(hopsCompleted); + + // reset the counter + hopsCompleted = 0; + + // return to home channel before the next transaction + radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); + + // wait a second before transmitting again + delay(1000); + + // increment the packet counter + packetCounter++; + + // send another packet + Serial.print(F("[SX1278] Sending another packet ... ")); + transmissionState = radio.startTransmit(longPacket + packetCounter); + } + + // check if we need to do another frequency hop + if (fhssChangeFlag == true) { + // we do, change it now + int state = radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); + if (state != RADIOLIB_ERR_NONE) { + Serial.print(F("[SX1278] Failed to change frequency, code ")); + Serial.println(state); + } + + // increment the counter + hopsCompleted++; + + // clear the FHSS interrupt + radio.clearFHSSInt(); + + // we're ready to do another hop, clear the flag + fhssChangeFlag = false; + } +} diff --git a/examples/SX127x/SX127x_Transmit_Interrupt/SX127x_Transmit_Interrupt.ino b/examples/SX127x/SX127x_Transmit_Interrupt/SX127x_Transmit_Interrupt.ino index b218a0a7..f0fe3e8b 100644 --- a/examples/SX127x/SX127x_Transmit_Interrupt/SX127x_Transmit_Interrupt.ino +++ b/examples/SX127x/SX127x_Transmit_Interrupt/SX127x_Transmit_Interrupt.ino @@ -77,6 +77,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino b/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino index 9bc9eaaa..274121df 100644 --- a/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino +++ b/examples/SX128x/SX128x_Receive_Interrupt/SX128x_Receive_Interrupt.ino @@ -85,6 +85,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/SX128x/SX128x_Transmit_Interrupt/SX128x_Transmit_Interrupt.ino b/examples/SX128x/SX128x_Transmit_Interrupt/SX128x_Transmit_Interrupt.ino index b23fb0c1..55d44faa 100644 --- a/examples/SX128x/SX128x_Transmit_Interrupt/SX128x_Transmit_Interrupt.ino +++ b/examples/SX128x/SX128x_Transmit_Interrupt/SX128x_Transmit_Interrupt.ino @@ -77,6 +77,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/Si443x/Si443x_Receive_Interrupt/Si443x_Receive_Interrupt.ino b/examples/Si443x/Si443x_Receive_Interrupt/Si443x_Receive_Interrupt.ino index 16c1af41..061ee094 100644 --- a/examples/Si443x/Si443x_Receive_Interrupt/Si443x_Receive_Interrupt.ino +++ b/examples/Si443x/Si443x_Receive_Interrupt/Si443x_Receive_Interrupt.ino @@ -76,6 +76,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/Si443x/Si443x_Transmit_Interrupt/Si443x_Transmit_Interrupt.ino b/examples/Si443x/Si443x_Transmit_Interrupt/Si443x_Transmit_Interrupt.ino index 4703233a..7f6877c6 100644 --- a/examples/Si443x/Si443x_Transmit_Interrupt/Si443x_Transmit_Interrupt.ino +++ b/examples/Si443x/Si443x_Transmit_Interrupt/Si443x_Transmit_Interrupt.ino @@ -75,6 +75,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/nRF24/nRF24_Receive_Interrupt/nRF24_Receive_Interrupt.ino b/examples/nRF24/nRF24_Receive_Interrupt/nRF24_Receive_Interrupt.ino index cafa2964..9e73394a 100644 --- a/examples/nRF24/nRF24_Receive_Interrupt/nRF24_Receive_Interrupt.ino +++ b/examples/nRF24/nRF24_Receive_Interrupt/nRF24_Receive_Interrupt.ino @@ -94,6 +94,9 @@ volatile bool enableInterrupt = true; // is received by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/examples/nRF24/nRF24_Transmit_Interrupt/nRF24_Transmit_Interrupt.ino b/examples/nRF24/nRF24_Transmit_Interrupt/nRF24_Transmit_Interrupt.ino index 9b6720c5..14d0c072 100644 --- a/examples/nRF24/nRF24_Transmit_Interrupt/nRF24_Transmit_Interrupt.ino +++ b/examples/nRF24/nRF24_Transmit_Interrupt/nRF24_Transmit_Interrupt.ino @@ -90,6 +90,9 @@ volatile bool enableInterrupt = true; // is transmitted by the module // IMPORTANT: this function MUST be 'void' type // and MUST NOT have any arguments! +#if defined(ESP8266) || defined(ESP32) + ICACHE_RAM_ATTR +#endif void setFlag(void) { // check if the interrupt is enabled if(!enableInterrupt) { diff --git a/keywords.txt b/keywords.txt index 9167c2a6..31db163d 100644 --- a/keywords.txt +++ b/keywords.txt @@ -142,6 +142,10 @@ setDirectAction KEYWORD2 readBit KEYWORD2 enableBitSync KEYWORD2 disableBitSync KEYWORD2 +setFHSSHoppingPeriod KEYWORD2 +getFHSSHoppingPeriod KEYWORD2 +getFHSSChannel KEYWORD2 +clearFHSSInt KEYWORD2 # RF69-specific setAESKey KEYWORD2 diff --git a/src/BuildOpt.h b/src/BuildOpt.h index cc40c7a3..37f3a426 100644 --- a/src/BuildOpt.h +++ b/src/BuildOpt.h @@ -734,6 +734,60 @@ #undef yield #endif +#elif defined(RASPI) + // RaspiDuino framework (https://github.com/me-no-dev/RasPiArduino) + #define RADIOLIB_PLATFORM "RasPiArduino" + #define RADIOLIB_PIN_TYPE uint8_t + #define RADIOLIB_PIN_MODE uint8_t + #define RADIOLIB_PIN_STATUS uint8_t + #define RADIOLIB_INTERRUPT_STATUS RADIOLIB_PIN_STATUS + #define RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(p) digitalPinToInterrupt(p) + #define RADIOLIB_NC (0xFF) + #define RADIOLIB_DEFAULT_SPI SPI + #define RADIOLIB_DEFAULT_SPI_SETTINGS SPISettings(2000000, MSBFIRST, SPI_MODE0) + #define RADIOLIB_NONVOLATILE PROGMEM + #define RADIOLIB_NONVOLATILE_READ_BYTE(addr) pgm_read_byte(addr) + #define RADIOLIB_TYPE_ALIAS(type, alias) using alias = type; + + // Arduino API callbacks + #define RADIOLIB_CB_ARGS_PIN_MODE (void, pinMode, uint8_t pin, uint8_t mode) + #define RADIOLIB_CB_ARGS_DIGITAL_WRITE (void, digitalWrite, uint8_t pin, uint8_t value) + #define RADIOLIB_CB_ARGS_DIGITAL_READ (int, digitalRead, uint8_t pin) + #define RADIOLIB_CB_ARGS_TONE (void, tone, uint8_t _pin, unsigned int frequency, unsigned long duration) + #define RADIOLIB_CB_ARGS_NO_TONE (void, noTone, uint8_t _pin) + #define RADIOLIB_CB_ARGS_ATTACH_INTERRUPT (void, attachInterrupt, uint8_t interruptNum, void (*userFunc)(void), int mode) + #define RADIOLIB_CB_ARGS_DETACH_INTERRUPT (void, detachInterrupt, uint8_t interruptNum) + #define RADIOLIB_CB_ARGS_YIELD (void, yield, void) + #define RADIOLIB_CB_ARGS_DELAY (void, delay, uint32_t ms) + #define RADIOLIB_CB_ARGS_DELAY_MICROSECONDS (void, delayMicroseconds, unsigned int us) + #define RADIOLIB_CB_ARGS_MILLIS (unsigned long, millis, void) + #define RADIOLIB_CB_ARGS_MICROS (unsigned long, micros, void) + #define RADIOLIB_CB_ARGS_SPI_BEGIN (void, SPIbegin, void) + #define RADIOLIB_CB_ARGS_SPI_BEGIN_TRANSACTION (void, SPIbeginTransaction, void) + #define RADIOLIB_CB_ARGS_SPI_TRANSFER (uint8_t, SPItransfer, uint8_t b) + #define RADIOLIB_CB_ARGS_SPI_END_TRANSACTION (void, SPIendTransaction, void) + #define RADIOLIB_CB_ARGS_SPI_END (void, SPIend, void) + + // let's start off easy - no tone on this platform, that can happen + #define RADIOLIB_TONE_UNSUPPORTED + + // hmm, no yield either - weird on something like Raspberry PI, but sure, we can handle it + #define RADIOLIB_YIELD_UNSUPPORTED + + // aight, getting to the juicy stuff - PGM_P seems missing, that's the first time + #define PGM_P const char * + + // ... and for the grand finale, we have millis() and micros() DEFINED AS MACROS! + #if defined(millis) + #undef millis + inline unsigned long millis() { return((unsigned long)(STCV / 1000)); }; + #endif + + #if defined(micros) + #undef micros + inline unsigned long micros() { return((unsigned long)(STCV)); }; + #endif + #else // other Arduino platforms not covered by the above list - this may or may not work #define RADIOLIB_PLATFORM "Unknown Arduino" diff --git a/src/modules/SX127x/SX1278.cpp b/src/modules/SX127x/SX1278.cpp index 317c38ee..685fe175 100644 --- a/src/modules/SX127x/SX1278.cpp +++ b/src/modules/SX127x/SX1278.cpp @@ -314,6 +314,11 @@ int16_t SX1278::setDataShaping(uint8_t sh) { // check modulation if(SX127x::_ook) { + // we're in OOK mode, the only thing we can do is disable + if(sh == RADIOLIB_SHAPING_NONE) { + return(setDataShapingOOK(0)); + } + return(RADIOLIB_ERR_INVALID_MODULATION); } diff --git a/src/modules/SX127x/SX127x.cpp b/src/modules/SX127x/SX127x.cpp index 24323447..1db50c20 100644 --- a/src/modules/SX127x/SX127x.cpp +++ b/src/modules/SX127x/SX127x.cpp @@ -375,7 +375,12 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) { int16_t modem = getActiveModem(); if(modem == RADIOLIB_SX127X_LORA) { // set DIO pin mapping - state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_RX_DONE | RADIOLIB_SX127X_DIO1_RX_TIMEOUT, 7, 4); + if(_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) { + state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_RX_DONE | RADIOLIB_SX127X_DIO1_FHSS_CHANGE_CHANNEL, 7, 4); + } + else { + state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_RX_DONE | RADIOLIB_SX127X_DIO1_RX_TIMEOUT, 7, 4); + } // set expected packet length for SF6 if(_sf == 6) { @@ -448,7 +453,12 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) { } // set DIO mapping - _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_TX_DONE, 7, 6); + if(_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) { + _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_TX_DONE | RADIOLIB_SX127X_DIO1_FHSS_CHANGE_CHANNEL, 7, 4); + } + else { + _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_TX_DONE, 7, 6); + } // apply fixes to errata RADIOLIB_ERRATA_SX127X(false); @@ -987,8 +997,12 @@ int16_t SX127x::setOOK(bool enableOOK) { } int16_t SX127x::setFrequencyRaw(float newFreq) { - // set mode to standby - int16_t state = setMode(RADIOLIB_SX127X_STANDBY); + int16_t state = RADIOLIB_ERR_NONE; + + // set mode to standby if not FHSS + if(_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) == RADIOLIB_SX127X_HOP_PERIOD_OFF) { + state = setMode(RADIOLIB_SX127X_STANDBY); + } // calculate register values uint32_t FRF = (newFreq * (uint32_t(1) << RADIOLIB_SX127X_DIV_EXPONENT)) / RADIOLIB_SX127X_CRYSTAL_FREQ; @@ -1353,4 +1367,25 @@ void SX127x::readBit(RADIOLIB_PIN_TYPE pin) { updateDirectBuffer((uint8_t)digitalRead(pin)); } +int16_t SX127x::setFHSSHoppingPeriod(uint8_t freqHoppingPeriod) { + return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD, freqHoppingPeriod)); +} + +uint8_t SX127x::getFHSSHoppingPeriod(void) { + return(_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD)); +} + +uint8_t SX127x::getFHSSChannel(void) { + return(_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_CHANNEL, 5, 0)); +} + +void SX127x::clearFHSSInt(void) { + int16_t modem = getActiveModem(); + if(modem == RADIOLIB_SX127X_LORA) { + _mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS, getIRQFlags() | RADIOLIB_SX127X_CLEAR_IRQ_FLAG_FHSS_CHANGE_CHANNEL); + } else if(modem == RADIOLIB_SX127X_FSK_OOK) { + return; //These are not the interrupts you are looking for + } +} + #endif diff --git a/src/modules/SX127x/SX127x.h b/src/modules/SX127x/SX127x.h index ea1ecf66..be3e2d0b 100644 --- a/src/modules/SX127x/SX127x.h +++ b/src/modules/SX127x/SX127x.h @@ -1073,6 +1073,34 @@ class SX127x: public PhysicalLayer { */ void readBit(RADIOLIB_PIN_TYPE pin); + /*! + \brief Sets the hopping period and enables FHSS + + \param freqHoppingPeriod Integer multiple of symbol periods between hops + + \returns \ref status_codes + */ + int16_t setFHSSHoppingPeriod(uint8_t freqHoppingPeriod); + + /*! + \brief Gets FHSS hopping period + + \returns 8 bit period + */ + uint8_t getFHSSHoppingPeriod(void); + + /*! + \brief Gets the FHSS channel in use + + \returns 6 bit channel number + */ + uint8_t getFHSSChannel(void); + + /*! + \brief Clear the FHSS interrupt + */ + void clearFHSSInt(void); + #if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL) protected: #endif diff --git a/src/modules/Si443x/Si443x.cpp b/src/modules/Si443x/Si443x.cpp index 1e4221e9..90bba72e 100644 --- a/src/modules/Si443x/Si443x.cpp +++ b/src/modules/Si443x/Si443x.cpp @@ -61,6 +61,8 @@ int16_t Si443x::begin(float br, float freqDev, float rxBw, uint8_t preambleLen) state = setEncoding(0); RADIOLIB_ASSERT(state); + state = variablePacketLengthMode(); + return(state); } @@ -233,8 +235,9 @@ int16_t Si443x::startTransmit(uint8_t* data, size_t len, uint8_t addr) { clearIRQFlags(); // set packet length - /// \todo variable packet length - _mod->SPIwriteRegister(RADIOLIB_SI443X_REG_TRANSMIT_PACKET_LENGTH, len); + if (_packetLengthConfig == RADIOLIB_SI443X_FIXED_PACKET_LENGTH_OFF) { + _mod->SPIwriteRegister(RADIOLIB_SI443X_REG_TRANSMIT_PACKET_LENGTH, len); + } /// \todo use header as address field? (void)addr; @@ -591,6 +594,14 @@ void Si443x::readBit(RADIOLIB_PIN_TYPE pin) { updateDirectBuffer((uint8_t)digitalRead(pin)); } +int16_t Si443x::fixedPacketLengthMode(uint8_t len) { + return(Si443x::setPacketMode(RADIOLIB_SI443X_FIXED_PACKET_LENGTH_ON, len)); +} + +int16_t Si443x::variablePacketLengthMode(uint8_t maxLen) { + return(Si443x::setPacketMode(RADIOLIB_SI443X_FIXED_PACKET_LENGTH_OFF, maxLen)); +} + int16_t Si443x::setFrequencyRaw(float newFreq) { // set mode to standby int16_t state = standby(); @@ -619,6 +630,25 @@ int16_t Si443x::setFrequencyRaw(float newFreq) { return(state); } +int16_t Si443x::setPacketMode(uint8_t mode, uint8_t len) { + // check packet length + if (len > RADIOLIB_SI443X_MAX_PACKET_LENGTH) { + return(RADIOLIB_ERR_PACKET_TOO_LONG); + } + + // set to fixed packet length + int16_t state = _mod->SPIsetRegValue(RADIOLIB_SI443X_REG_HEADER_CONTROL_2, mode, 3, 3); + RADIOLIB_ASSERT(state); + + // set length to register + state = _mod->SPIsetRegValue(RADIOLIB_SI443X_REG_TRANSMIT_PACKET_LENGTH, len); + RADIOLIB_ASSERT(state); + + // update cached value + _packetLengthConfig = mode; + return(state); +} + bool Si443x::findChip() { uint8_t i = 0; bool flagFound = false; diff --git a/src/modules/Si443x/Si443x.h b/src/modules/Si443x/Si443x.h index 9a5c0df1..40feceef 100644 --- a/src/modules/Si443x/Si443x.h +++ b/src/modules/Si443x/Si443x.h @@ -816,6 +816,24 @@ class Si443x: public PhysicalLayer { */ void readBit(RADIOLIB_PIN_TYPE pin); + /*! + \brief Set modem in fixed packet length mode. + + \param len Packet length. + + \returns \ref status_codes + */ + int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_SI443X_MAX_PACKET_LENGTH); + + /*! + \brief Set modem in variable packet length mode. + + \param len Maximum packet length. + + \returns \ref status_codes + */ + int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SI443X_MAX_PACKET_LENGTH); + #if !defined(RADIOLIB_GODMODE) && !defined(RADIOLIB_LOW_LEVEL) protected: #endif @@ -831,8 +849,10 @@ class Si443x: public PhysicalLayer { size_t _packetLength = 0; bool _packetLengthQueried = false; + uint8_t _packetLengthConfig = RADIOLIB_SI443X_FIXED_PACKET_LENGTH_ON; int16_t setFrequencyRaw(float newFreq); + int16_t setPacketMode(uint8_t mode, uint8_t len); #if !defined(RADIOLIB_GODMODE) private: