Git Product home page Git Product logo

radiolib's Introduction

RadioLib Build Status PlatformIO Registry Component Registry

One radio library to rule them all!

Universal wireless communication library for embedded devices

See the Wiki and FAQ for further information. See the GitHub Pages for detailed and up-to-date API reference.

RadioLib allows its users to integrate all sorts of different wireless communication modules, protocols and even digital modes into a single consistent system. Want to add a Bluetooth interface to your LoRa network? Sure thing! Do you just want to go really old-school and play around with radio teletype, slow-scan TV, or even Hellschreiber using nothing but a cheap radio module? Why not!

RadioLib natively supports Arduino, but can run in non-Arduino environments as well! See this Wiki page and examples/NonArduino.

RadioLib was originally created as a driver for RadioShield, but it can be used to control as many different wireless modules as you like - or at least as many as your microcontroller can handle!

Supported modules:

  • CC1101 FSK radio module
  • LLCC68 LoRa module
  • LR11x0 series LoRa/GFSK modules (LR1110, LR1120, LR1121)
  • nRF24L01 2.4 GHz module
  • RF69 FSK/OOK radio module
  • RFM2x series FSK modules (RFM22, RM23)
  • RFM9x series LoRa modules (RFM95, RM96, RFM97, RFM98)
  • Si443x series FSK modules (Si4430, Si4431, Si4432)
  • STM32WL integrated microcontroller/LoRa module
  • SX126x series LoRa modules (SX1261, SX1262, SX1268)
  • SX127x series LoRa modules (SX1272, SX1273, SX1276, SX1277, SX1278, SX1279)
  • SX128x series LoRa/GFSK/BLE/FLRC modules (SX1280, SX1281, SX1282)
  • SX123x FSK/OOK radio modules (SX1231, SX1233)

Supported protocols and digital modes:

  • AX.25 using 2-FSK or AFSK for modules:
    SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x, Si443x, LR11x0 and SX128x
  • RTTY using 2-FSK or AFSK for modules:
    SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
  • Morse Code using 2-FSK or AFSK for modules:
    SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
  • SSTV using 2-FSK or AFSK for modules:
    SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x and Si443x
  • Hellschreiber using 2-FSK or AFSK for modules:
    SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
  • APRS using AFSK for modules:
    SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
  • POCSAG using 2-FSK for modules:
    SX127x, RFM9x, RF69, SX1231, CC1101, nRF24L01, RFM2x and Si443x
  • LoRaWAN using LoRa for modules:
    SX127x, RFM9x, SX126x, LR11x0 and SX128x
    • NOTE: LoRaWAN support is currently in beta, feedback via Issues and Discussions is appreciated!

Supported Arduino platforms:

  • Arduino

    • AVR - Arduino Uno, Mega, Leonardo, Pro Mini, Nano etc.
    • mbed - Arduino Nano 33 BLE and Arduino Portenta H7
    • megaAVR - Arduino Uno WiFi Rev.2 and Nano Every
    • SAM - Arduino Due
    • SAMD - Arduino Zero, MKR boards, M0 Pro etc.
    • Renesas - Arduino Uno R4
  • Adafruit

    • SAMD - Adafruit Feather M0 and M4 boards (Feather, Metro, Gemma, Trinket etc.)
    • nRF52 - Adafruit Feather nRF528x, Bluefruit and CLUE
  • Espressif

  • Intel

  • SparkFun

    • Apollo3 - Sparkfun Artemis Redboard
  • ST Microelectronics

  • MCUdude

    • MegaCoreX - megaAVR-0 series (ATmega4809, ATmega3209 etc.)
    • MegaCore - AVR (ATmega1281, ATmega640 etc.)
  • Raspberry Pi

  • Heltec

    • CubeCell - ASR650X series (CubeCell-Board, CubeCell-Capsule, CubeCell-Module etc.)
  • PJRC

    • Teensy - Teensy 2.x, 3.x and 4.x boards

The list above is by no means exhaustive - RadioLib code is independent of the used platform! Compilation of all examples is tested for all platforms officially supported prior to releasing new version. In addition, RadioLib includes an internal hardware abstraction layer, which allows it to be easily ported even to non-Arduino environments.

radiolib's People

Contributors

aguglie avatar alistair23 avatar barrypsmith avatar beegee-tokyo avatar caveman99 avatar cpainchaud avatar cterwilliger avatar darksidelemm avatar fiorixf1 avatar g4lile0 avatar gasagna avatar headboffin avatar jaimi5 avatar jasonrj avatar jgamage91 avatar jgromes avatar kihunsong22 avatar loopj avatar matthias-bs avatar matthijskooijman avatar mesteery avatar mmrein avatar naggie avatar nicklasb avatar nseidle avatar obones avatar per1234 avatar phretor avatar stevencellist avatar yeckel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

radiolib's Issues

Get by without SS("ChipSelect")?

Hi, and thanks for a nice library!
I'm have very few pins to spare on my ESP32, I need to run SPI with the fewest pins possible.
I need to find pins for MOSI, MISO, SCK, but the RST I'm connecting to the ESP32 "Reset" pin.
And what about the "SS" ("CS"), since I'm only running ONE device on my SPI bus, do I really need to set this?? Can't I hardwire SS to VCC or GND on the SX1278 module and enter SS=-1 when initializing the library? All feedback is welcome since I'm a total newbee on LoRa.

RFM95 aka SX127x not detected

Using SparkFun LoRa Gateway - 1-Channel (ESP32)
NSS = 16, DIO0 = 26, DIO1 = 33, DIO2 = 32 according to schematic
Setting up the connection to the RFM95 module:

RFM95 lora = new Module(16, 26, 33, 32);

void setup() {
    int state = lora.begin(868.0, 125.0, 9, 5, 0x3444, 22, 8);
    if (state == ERR_NONE)
    {
        Serial.println("success!");
    }
    else
    {
        Serial.print("failed: ");
        printError(state);
        return false;
    }
...
}

fails with

=====================================
RFM95 sender test
=====================================
DeviceID: 84 0D 8E 0C 56 3C 00 00
Initialize RFM95 
SX127x not found! (1 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (2 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (3 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (4 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (5 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (6 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (7 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (8 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (9 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
SX127x not found! (10 of 10 tries) SX127X_REG_VERSION == 0x00, expected 0x0011
No SX127x found!
failed: SX127x not found

Using the abandoned library RadioHead
Setup with

// Singleton instance of the radio driver
RH_RF95 rf95(16, 26);
// 16 = NSS, 26 = INT

void setup() {
  // Init the RFM95 module
  if (!rf95.init())
  {
    Serial.println("[RFM95] init failed");
    delay(500);
  }
}

works perfect, log output:

RH_RF95::init() started
RH_RF95::init() success

Any idea?

AX.25 support

RadioLib could be extended to provide hardware-agnostic AX.25 driver, which is currently not available.

RTTY Decoding

Hey, I am trying to decode the RTTY example using MMTTY and FLDigi but I cannot seem to get it to successfully decode. I suspect this is due to it being ASCII and not Baudot ITA2, do you have an implementation for ITA2 or can you share how to decode the rtty? thanks!

Issue with Interrupts using SX1262MB2CAS Shield from Semtech

Hi

I can't for the life of me get the Transmit or Interrupt examples working. Seems the library is not firing the interrupt.

This is what I am using:
https://www.mouser.com/ProductDetail/Semtech/SX1262MB2CAS?qs=qSfuJ%252Bfl%2Fd69tTGSeW1ezg%3D%3D&gclid=CjwKCAjwyqTqBRAyEiwA8K_4O7C7a8jZO-cE0LqnMlDPHCW88X2zbjaKHPTFOQHc3fD0QoWU1JnpBhoCh3AQAvD_BwE

The regular examples work fine.
I am on an Arduino Uno and the initialization I am using is as follows:
SX1262 lora = new Module(7, 5, -1, 3);

int state = lora.begin(915.0, 125.0, 9, 5, SX126X_SYNC_WORD_PRIVATE, 22);

Any help will be greatly appreciated.

RadioLib receive function returning strings containing garbage data

Hi,

I have switched to using char*'s instead of String objects. But the function provided as

for (int i = 0; i < 25; i++)
{
     char rxTransmission[20];
     int state = LORA.receive(rxTransmission, 20);

    if (state == ERR_NONE)
    {
          Serial.println(rxTransmission);
     }
}

returns data like this:

HELLOWORLD☐?☐?

when sent transmissions of:

HELLOWORLD

Any ideas?

Thanks,
Richard

-- edit --

When using it in this mode:


char rxTransmission[64];

for (int i = 0; i < 25; i++)
{
    int state = lora.receive(rxTransmission, 20);
    if (state == ERR_NONE)
    {
        Serial.println(rxTransmission)
    }
}

The result is "HELLOWORLDD"

Non-blocking morse implementation.

We are trying to use task scheduler in our application. However, the blocking functions like delay() and tone() cause problems in timing. Can the morse protocol be remade using millis or some other non-blocking function?

Semtech DRF1278DM - Connection UART

Hi there,

Trying to work out how to use a Semtech DRF1278DM http://www.dorji.com/products-detail.php?ProId=34 with an Arduino Nano, I've read the other posts on here regarding how LoRaLib won't do UART and only SPI but the KiteLib link just redirects to the main LoRaLib page!

So if the LoRaLib library now supports the DRF1278DM module and not just the raw SX1278 board, how would you go about connecting it up, as it doesn't have the standard SCK and MOSI pins?

Would it just be like this?
SX1278 lora = new LoRa(11, 10); // RX-TX
or
SX1278 lora = new LoRa(11, 10, 9); // RX-TX+Enable

Cheers Benjamin!

Issue with the receving example code on SX1262

Describe the bug
I'm not sure if this is a bug or I'm missing something. However, when I use the SX1262 module and try to setup a receving example, the begin returns an error code of -20. From what I read on the wiki pages, this error is happening because "User tried to execute modem-exclusive method on a wrong modem." But, I know that the SX1262 supports both Lora mode and FSK mode, and therefore that should just work.

To Reproduce
Use the Example code from SX1262_Receive.

Expected behavior
I should be able to recevie stuff.

Screenshots
If applicable, add screenshots to help explain your problem.
image

Additional info (please complete):

  • MCU: STM32F103RB
  • Wireless module type SX1262
  • Arduino IDE version 1.8.9
  • Library version: latest

Thanks for your help!

SX126x cannot wake from sleep

Describe the bug
SX126x modules cannot be woken with the library, instead one must manually wake the unit with a digital write to its select pin.

It looks like in SX126x::SPItransfer, moving the line digitalWrite(_mod->getCs(), LOW); to run before the Wait for BUSY loop will fix this (first sentence in datasheet section 8.2.2) but I'm not sure if there's a reason it needs to be where it is.

To Reproduce

#include <RadioLib.h>

#define LORA_CHECK(A) { auto res = A; if(res) { Serial.print("FAILED " #A ": "); Serial.println(res); } } while(0)

#define BUSY 4
#define DIO1 2
#define DIO2 -1
#define SELECT 9
SX1262 lora = new Module(SELECT, DIO1, DIO2, BUSY);

void setup() {
  Serial.begin(9600);
  delay(10);
  LORA_CHECK(lora.begin());
  LORA_CHECK(lora.sleep());
  //digitalWrite(SELECT, LOW); //Uncomment this and everything works
  LORA_CHECK(lora.standby()); //Fails with -705
  Serial.println("Setup done. If no errors show, everything worked.");
}

void loop() {}

Expected behavior
The module can be woken from sleep by asking it to return to standby

Additional info (please complete):

  • MCU: Ardiuno Nano
  • Wireless module type: SX1262
  • Arduino IDE version: 1.8.10
  • Library version: tip of trunk as of writing. Checkin 300e7f4

SX126x sleep() function takes always 5 seconds

Feature request:

Add parameter for SX126x::sleep(void) to skip waiting for BUSY line of SX126x chip.

Why?

In battery powered systems you don't want to wait for the SX126x chip to go to sleep and instead just send the command and then put yourself to sleep.

Scenario:

I am working on a code for a battery powered sensor node.
The node wakes up every 30 seconds, reads a sensor, sends the sensor values over LoRa and goes to sleep again.
Right now I am measuring the time that the node is awake and found something strange.

void goToSleep(void)
{
  time_t sendToSleep = millis();
  // Send the LoRa module to sleep
  lora.sleep();
  Serial.printf("Set Lora to sleep took %ldms\n", (millis() - sendToSleep));
  Serial.printf("Sleeping after %ldms\n", (millis() - wakeup));
  // Go back to bed
  time_t awakeTime = millis() - wakeup;
  esp_sleep_enable_timer_wakeup((sleepForMillis - awakeTime) * uS_TO_mS_FACTOR);
  esp_deep_sleep_start();
}

where wakeup = millis() is done as first thing when entering setup().
The output is always

=====================================
LoRa sensor node test
=====================================
Temp 29.89
Humid 98.50
Finished reading sensor after 1010ms
CAD finished after 24ms
Transmit finished after 70ms
Set Lora to sleep took 5000ms
Sleeping after 6104ms

So putting the SX126x to sleep takes nearly 5 times as long as reading the sensors and sending the data.
I tried to track down why it takes so long and found that in sleep() the command is waiting for BUSY line to go low before returning.
When I change the sleep() function to

int16_t SX126x::sleep() {
  uint8_t data[] = {SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF};
  int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, data, 1, true);

  // wait for SX126x to safely enter sleep mode
  delayMicroseconds(500);

  return(state);
}

forcing the SPIwriteCommand to NOT wait for BUSY going low, I can reduce my awake time by 4 seconds to

=====================================
LoRa sensor node test
=====================================
Temp 30.0
Humid 98.50
Finished reading sensor after 1010ms
CAD finished after 24ms
Transmit finished after 70ms
Set Lora to sleep took 0ms
Sleeping after 1104ms

Proposal

Change

int16_t SX126x::sleep() {
  uint8_t data[] = {SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF};
  int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, data, 1);

  // wait for SX126x to safely enter sleep mode
  delayMicroseconds(500);

  return(state);
}

to

int16_t SX126x::sleep(bool waitForBusy) {
  uint8_t data[] = {SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF};
  int16_t state = SPIwriteCommand(SX126X_CMD_SET_SLEEP, data, 1, waitForBusy);

  // wait for SX126x to safely enter sleep mode
  delayMicroseconds(500);

  return(state);
}

with a declaration as

    /*!
      \brief Sets the module to sleep mode.

      \returns \ref status_codes
    */
    int16_t sleep(bool waitForBusy = true);

If you agree that this makes sense, I can submit a pull request for it.

Support for MSK,GMSK.

Docs claim that Semetech chips have capabilities for MSK and GMSK. Can those be invoked using some settings in code?

RTTY in RFM69

I couldn´t use RTTY with RFM69 Module.
From the example code (https://github.com/jgromes/RadioLib/blob/master/examples/RTTY/RTTY_Transmit/RTTY_Transmit.ino ) i change to:

RF69 fsk = new Module(10,2 ,3 );

'get error in compilation:
radiolib_rtty:46: error: 'class RF69' has no member named 'beginFSK'
int state = fsk.beginFSK();
exit status 1
'class RF69' has no member named 'beginFSK''

Documentation say:
RTTY for modules: SX127x, RFM9x, SX126x, RF69, SX1231, CC1101 and nRF24L01

I´m doing something wrong?

Yield-based vs multi-core approach to async TX

Is your feature request related to a problem? Please describe.
No, pure enhancement.

Describe the solution you'd like
The transmit blocks the core until TX is fully completed. Is this based on the assumption that the WiFi (for instance) and other tasks will run independently on CPU0? Have you considered reading the radio state before starting a transmission and don't block but use IRQs to mark a successfull TX?

Describe alternatives you've considered
Using ESP8266 and some of Arduino's yield.

Example: Example: https://github.com/trendmicro/RadioHAL/blob/master/src/RH_CC1120.cpp#L274

What do you think? My apologies if there is a discussion board/ML/chat to discuss this prior to open an issue: I haven't found any. In that case, please point me there and just close this issue.

SX126x - add possibility to set SyncWord length in bits

Length of SyncWord on SX126x radios is being set as a value in bits, which is solved in library simply by:

// update packet parameters
_syncWordLength = len * 8;
state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);

As I would like to use this feature, I would consider changing:

int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len)

to:

int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len, bool lenInBits)

for example. Then do obvious things in the code (I'll try to write up actual code later on today).

What do you think?

scanChannel without timeout in while, infinty loop.

Hi,
I am using arduino pro micro - atmega32u4 (INT0 and INT1 are pins exchanged in relation to arduino uno) and in scanChannel the code gets stuck in while waiting for an activity in INT0. In the comment says have timeout but do not have, should not have a timout? I am only with a radio and now I have no way to test if with channel activity it would pass this condition.

thank you! and congratulations to cubeSat

int16_t SX126x::scanChannel()
{
  // check active modem
  if (getPacketType() != SX126X_PACKET_TYPE_LORA)
  {
    return (ERR_WRONG_MODEM);
  }

  // set mode to standby
  int16_t state = standby();
  if (state != ERR_NONE)
  {
    return (state);
  }

  // set DIO pin mapping
  // state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED);
  // Use DIO1 only for both CAD DONE and CAD DETECTED interrupts
  state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE);
  if (state != ERR_NONE)
  {
    return (state);
  }

  // clear interrupt flags
  state = clearIrqStatus();
  if (state != ERR_NONE)
  {
    return (state);
  }

  // set mode to CAD
  state = setCad();
  if (state != ERR_NONE)
  {
    return (state);
  }

  // wait for channel activity detected or timeout
  while (!digitalRead(_mod->getInt0()))
  {
    // No need to check DIO2
    // if(digitalRead(_mod->getInt1())) {
    //   clearIrqStatus();
    //   return(LORA_DETECTED);
    // }
  }

  // Get the CAD result
  uint16_t cadResult = getIrqStatus();
  if (cadResult == 0x8000)
  {
    clearIrqStatus();
    return (CHANNEL_FREE);
  }
  else // cadResult == 0x8001
  {
    clearIrqStatus();
    return (LORA_DETECTED);
  }
  return (CHANNEL_FREE);
}

SX126x - Set DIO3 as output

I have another weird module, a combined nRF52832 and SX1262 module named Insight ISP4520.
This module uses DIO3 as a power supply for the antenna switch:
ISP4520-SX162X

They have a sample code how to set DIO3 as output and put it to high level:

static void SX126xDio3Control (bool state)
{
    uint8_t reg_0x0580;
    uint8_t reg_0x0583;
    uint8_t reg_0x0584;
    uint8_t reg_0x0585;
    uint8_t reg_0x0920;

    if (state)
    {
        // Configure DIO3 as output

        // Read 0x0580
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0580 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0580 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0);
        reg_0x0580 = SpiInOut(&SX126x.Spi, 0);
        GpioWrite(&SX126x.Spi.Nss, 1);

        // Read 0x0583
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0583 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0583 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0);
        reg_0x0583 = SpiInOut(&SX126x.Spi, 0);
        GpioWrite(&SX126x.Spi.Nss, 1);

        // Read 0x0584
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0584 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0584 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0);
        reg_0x0584 = SpiInOut(&SX126x.Spi, 0);
        GpioWrite(&SX126x.Spi.Nss, 1);

        // Read 0x0585
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0585 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0585 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0);
        reg_0x0585 = SpiInOut(&SX126x.Spi, 0);
        GpioWrite(&SX126x.Spi.Nss, 1);

        // Write 0x0580
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0580 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0580 & 0x00FF);
        SpiInOut(&SX126x.Spi, reg_0x0580 | 0x08);
        GpioWrite (&SX126x.Spi.Nss, 1);

        // Write 0x0583
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0583 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0583 & 0x00FF);
        SpiInOut(&SX126x.Spi, reg_0x0583 & ~0x08);
        GpioWrite (&SX126x.Spi.Nss, 1);

        // Write 0x0584
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0584 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0584 & 0x00FF);
        SpiInOut(&SX126x.Spi, reg_0x0584 & ~0x08);
        GpioWrite (&SX126x.Spi.Nss, 1);

        // Write 0x0585
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0585 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0585 & 0x00FF);
        SpiInOut(&SX126x.Spi, reg_0x0585 & ~0x08);
        GpioWrite (&SX126x.Spi.Nss, 1);

        // Write 0x0920
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0x06);
        GpioWrite (&SX126x.Spi.Nss, 1);

        // Set DIO3 High
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0);
        reg_0x0920 = SpiInOut(&SX126x.Spi, 0);
        GpioWrite(&SX126x.Spi.Nss, 1);

        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
        SpiInOut(&SX126x.Spi, reg_0x0920 | 0x08);
        GpioWrite (&SX126x.Spi.Nss, 1);
    }
    else
    {
        // Set DIO3 Low
        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_READ_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
        SpiInOut(&SX126x.Spi, 0);
        reg_0x0920 = SpiInOut(&SX126x.Spi, 0);
        GpioWrite(&SX126x.Spi.Nss, 1);

        SX126xWaitOnBusy();
        GpioWrite(&SX126x.Spi.Nss, 0);
        SpiInOut(&SX126x.Spi, RADIO_WRITE_REGISTER);
        SpiInOut(&SX126x.Spi, (0x0920 & 0xFF00) >> 8);
        SpiInOut(&SX126x.Spi, 0x0920 & 0x00FF);
        SpiInOut(&SX126x.Spi, reg_0x0920 & ~0x08);
        GpioWrite (&SX126x.Spi.Nss, 1);        
    }
}

but I have problems to transform this to work within your library.

I didn't find a readRegister() only a writeRegister() function. So I tried to write readRegister(), but found that the SPItransfer when in read mode only transfers the command, but for reading the registers after the command it is required to send the register address.
image
So I needed to write a SPItransferAddr(uint8_t cmd, uint8_t addr1, uint8_t addr2, bool write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, bool waitForBusy) functions that sends the two address bytes after the command and then reads the register values.
After I got that to work I changed above code to work with your library and added it as a function setDio3AsOutput(bool enable).

Not sure if others need something like that, but here are the functions I added:

SX126x::readRegister

int16_t SX126x::readRegister(uint16_t addr, uint8_t *data, uint8_t numBytes)
{
  uint8_t *dat = new uint8_t[numBytes];
  int16_t state = SPItransferAddr(SX126X_CMD_READ_REGISTER,
                                  (uint8_t)((addr >> 8) & 0xFF),
                                  (uint8_t)(addr & 0xFF),
                                  false,
                                  NULL,
                                  dat,
                                  numBytes,
                                  true);
  memcpy(data, dat, numBytes);
  delete[] dat;
  return (state);
}

int16_t SX126x::SPItransferAddr

int16_t SX126x::SPItransferAddr(uint8_t cmd, uint8_t addr1, uint8_t addr2, bool write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, bool waitForBusy)
{
  // get pointer to used SPI interface and the settings
  SPIClass *spi = _mod->getSpi();
  SPISettings spiSettings = _mod->getSpiSettings();

  // ensure BUSY is low (state meachine ready)
  // TODO timeout
  while (digitalRead(_mod->getRx()))
    ;

  // start transfer
  digitalWrite(_mod->getCs(), LOW);
  spi->beginTransaction(spiSettings);

  // send command byte
  spi->transfer(cmd);
  DEBUG_PRINT(cmd, HEX);
  DEBUG_PRINT('\t');
  // send addr byte 1
  spi->transfer(addr1);
  DEBUG_PRINT(addr1, HEX);
  DEBUG_PRINT('\t');
  // send addr byte 2
  spi->transfer(addr2);
  DEBUG_PRINT(addr2, HEX);
  DEBUG_PRINT('\t');

  // variable to save error during SPI transfer
  uint8_t status = 0;

  // send/receive all bytes
  if (write)
  {
    for (uint8_t n = 0; n < numBytes; n++)
    {
      // send byte
      uint8_t in = spi->transfer(dataOut[n]);
      DEBUG_PRINT(dataOut[n], HEX);
      DEBUG_PRINT('\t');
      DEBUG_PRINT(in, HEX);
      DEBUG_PRINT('\t');

      // check status
      if (((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
          ((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
          ((in & 0b00001110) == SX126X_STATUS_CMD_FAILED))
      {
        status = in;
      }
    }
    DEBUG_PRINTLN();
  }
  else
  {
    // skip the first byte for read-type commands (status-only)
    uint8_t in = spi->transfer(SX126X_CMD_NOP);
    DEBUG_PRINT(SX126X_CMD_NOP, HEX);
    DEBUG_PRINT('\t');
    DEBUG_PRINT(in, HEX);
    DEBUG_PRINT('\t')

    // check status
    if (((in & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT) ||
        ((in & 0b00001110) == SX126X_STATUS_CMD_INVALID) ||
        ((in & 0b00001110) == SX126X_STATUS_CMD_FAILED))
    {
      status = in;
    }
    for (uint8_t n = 0; n < numBytes; n++)
    {
      dataIn[n] = spi->transfer(SX126X_CMD_NOP);
      DEBUG_PRINT(SX126X_CMD_NOP, HEX);
      DEBUG_PRINT('\t');
      DEBUG_PRINT(dataIn[n], HEX);
      DEBUG_PRINT('\t');
    }
    DEBUG_PRINTLN();
  }

  // stop transfer
  spi->endTransaction();
  digitalWrite(_mod->getCs(), HIGH);

  // wait for BUSY to go high and then low
  // TODO timeout
  if (waitForBusy)
  {
    delayMicroseconds(1);
    while (digitalRead(_mod->getRx()))
      ;
  }

  // parse status
  switch (status)
  {
  case SX126X_STATUS_CMD_TIMEOUT:
    return (ERR_SPI_CMD_TIMEOUT);
  case SX126X_STATUS_CMD_INVALID:
    return (ERR_SPI_CMD_INVALID);
  case SX126X_STATUS_CMD_FAILED:
    return (ERR_SPI_CMD_FAILED);
  default:
    return (ERR_NONE);
  }
}

SX126x::setDio3AsOutput

int16_t SX126x::setDio3AsOutput(bool enable)
{
  uint8_t reg_0x0580;
  uint8_t reg_0x0583;
  uint8_t reg_0x0584;
  uint8_t reg_0x0585;
  uint8_t reg_0x0920;
  int state;

  if (enable)
  {
    state = readRegister(0x0580, &reg_0x0580, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = readRegister(0x0583, &reg_0x0583, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = readRegister(0x0584, &reg_0x0584, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = readRegister(0x0585, &reg_0x0585, 1);
    if (state != ERR_NONE)
    {
      return state;
    }

    // Set the register values
    reg_0x0580 = reg_0x0580 | 0x08;
    reg_0x0583 = reg_0x0583 & ~0x08;
    reg_0x0584 = reg_0x0584 & ~0x08;
    reg_0x0585 = reg_0x0585 & ~0x08;
    reg_0x0920 = 0x08;

    state = writeRegister(0x0580, &reg_0x0580, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = writeRegister(0x0583, &reg_0x0583, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = writeRegister(0x0584, &reg_0x0584, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = writeRegister(0x0585, &reg_0x0585, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    state = writeRegister(0x0920, &reg_0x0920, 1);
    if (state != ERR_NONE)
    {
      return state;
    }
    return ERR_NONE;
  }
  else
  {
    {
      state = readRegister(0x0920, &reg_0x0920, 1);
      if (state != ERR_NONE)
      {
        return state;
      }
      reg_0x0920 = reg_0x0920 & ~0x08;
      state = writeRegister(0x0920, &reg_0x0920, 1);
      if (state != ERR_NONE)
      {
        return state;
      }
    }
  }
  return ERR_NONE;
}

PS: I have no idea where Insight got the register addresses 0x0580, 0x0583, 0x0584, 0x0585 and 0x0920 from. They are not in the datasheets. I guess they got it from Semtech directly.

Packet size sent and packet size received differ in size

Not sure if it is a bug or a limitation.

I send a structure with the size of 34 bytes

struct dataPckg
{
    char rcvAddr[8];
    char sendAddr[8];
    char type;
    char data[16];
    char term = 0;
} dataPckgStruct;

from a nRF52 with a SX1262 attached with

int state = lora.startTransmit((const char *)&outPckg, 34);

or from an ESP32 with a SX1262 attached with

lora.transmit((const char *)&outPckg, 34);

Log output of the data sent looks like this:

Sending Package:
Rcv:    FF FF FF FF FF FF FF FF
Sender: F7 BC C6 FA A5 6C CB 4E
Type:   0
Data:
12 00 00 00
00 00 00 00
00 00 00 00
00 00 00 ED

Inside the library when the data is written to the SX1262 buffer I put an additional debug output with the buffer content:

FF FF FF FF
FF FF FF FF
F7 BC C6 FA
A5 6C CB 4E
00
12 00 00 00
00 00 00 00
00 00 00 00
00 00 00 ED

So at that point the data is still complete.

CAD is done before sending and the channel is available.
For receiving I use interrupt driven method and then

int state = lora.readData((uint8_t *)&inPckg, 34);

to get the data.

For the receiving side I added some debug output into SX126x.cpp into readData()

  size_t length = rxBufStatus[0];
Serial.printf("Receiving %d bytes, wanted %d\n", length, len);
  // read packet data
  if(len == 0) {
    // argument 'len' equal to zero indicates String call, which means dynamically allocated data array
    // dispose of the original and create a new one
    delete[] data;
    data = new uint8_t[length + 1];
  }
  state = readBuffer(data, length);
for(int idx=0; idx<length; idx++)
{
Serial.printf("%02X ", data[idx]);
}
Serial.println("\n===================");

On the ESP32 I receive

Receiving 16 bytes, wanted 34
FF FF FF FF FF FF FF FF F7 BC C6 FA A5 6C CB 4E 
===================

On the nRF52 I receive

Receiving 17 bytes, wanted 34
F7 BC C6 FA A5 6C CB 4E FF FF FF FF FF FF FF FF 01 
===================

And it is always 16 bytes on the ESP32 and 17 bytes on the nRF52.

Kind of lost here. What could be the cause. I know from the datasheet that the Data buffer of the SX1262 is 256 byte large. But I do not know how it is setup by the library. Maybe the RX buffer is set too small???

Runtime Transmit error

Hey Jgromes,
I seem to be having a runtime error when I try to use the Kitelibe Library with RTTY instead of LoRaLib. It is the same exact piece of code and the only difference is the library and the Lora module declaration

#include <SoftwareSerial.h>
#include <KiteLib.h>
#include <TinyGPS.h>
 
TinyGPS gps;
SoftwareSerial ss(6, 5);
SX1278 lora = new Module(7, 3, 2);
 
void setup()
{
  Serial.begin(115200);
  ss.begin(9600);
 
 int  state = lora.begin(434.0, 62.5, 12, 8, 0x13, 10);
  if (state == ERR_NONE)
  {
    Serial.println(F("success!"));
  }
  else
  {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }
}
 
void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;
 
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      if (gps.encode(c))
        newData = true;
    }
  }
 
  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flat, 7);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flon, 6);
    Serial.print(" ALT=");
    Serial.print(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0.00 : gps.f_altitude());
 
    String transmissionMessage = String("");
   
    transmissionMessage += String(";");
    if (0==1)
    {
      transmissionMessage += String("0.0");
    }
    else
    {
      transmissionMessage += String(flat, 4);
    }
 
    transmissionMessage += String(";");
    if (0==1)
    {
      transmissionMessage += String("0.0");
    }
    else
    {
      transmissionMessage += String(flon,4);
    }
 
    transmissionMessage += String(";");
    if (0==1)
    {
      transmissionMessage += String("0.0");
    }
    else
    {
      transmissionMessage += String(gps.f_altitude());
    }
 
    int state = lora.transmit(transmissionMessage);
   if (state == ERR_NONE) {
    // the packet was successfully transmitted
    Serial.println(" success!");

    // print measured data rate
    Serial.print("Datarate:\t");
    Serial.print(lora.dataRate);
    Serial.println(" bps");

  } else if (state == ERR_PACKET_TOO_LONG) {
    // the supplied packet was longer than 256 bytes
    Serial.println(" too long!");

  } else if (state == ERR_TX_TIMEOUT) {
    // timeout occured while transmitting packet
    Serial.println(" timeout!");

 
  }
 }
} 

This code shown above transmits once and then locks up the loop.

#include <SoftwareSerial.h>
#include <KiteLib.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(6, 5);
SX1278 lora = new Module(7, 3, 2);
RTTYClient rtty(&lora);
void setup()
{
 Serial.begin(115200);
 ss.begin(9600);

int  state = lora.begin(434.0, 62.5, 12, 8, 0x13, 10);
 if (state == ERR_NONE)
 {
   Serial.println(F("success!"));
 }
 else
 {
   Serial.print(F("failed, code "));
   Serial.println(state);
   while (true);
 }
}

void loop()
{
 bool newData = false;
 unsigned long chars;
 unsigned short sentences, failed;

 for (unsigned long start = millis(); millis() - start < 1000;)
 {
   while (ss.available())
   {
     char c = ss.read();
     if (gps.encode(c))
       newData = true;
   }
 }

 if (newData)
 {
   float flat, flon;
   unsigned long age;
   gps.f_get_position(&flat, &flon, &age);
   Serial.print("LAT=");
   Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flat, 7);
   Serial.print(" LON=");
   Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.00 : flon, 6);
   Serial.print(" ALT=");
   Serial.print(gps.f_altitude() == TinyGPS::GPS_INVALID_F_ALTITUDE ? 0.00 : gps.f_altitude());

   String transmissionMessage = String("");
  
   transmissionMessage += String(";");
   if (0==1)
   {
     transmissionMessage += String("0.0");
   }
   else
   {
     transmissionMessage += String(flat, 4);
   }

   transmissionMessage += String(";");
   if (0==1)
   {
     transmissionMessage += String("0.0");
   }
   else
   {
     transmissionMessage += String(flon,4);
   }

   transmissionMessage += String(";");
   if (0==1)
   {
     transmissionMessage += String("0.0");
   }
   else
   {
     transmissionMessage += String(gps.f_altitude());
   }
int state = lora.begin(434.0, 62.5, 12, 8, 0x13, 10);
    state = lora.transmit(transmissionMessage);
  if (state == ERR_NONE) {
   // the packet was successfully transmitted
   Serial.println(" success!");

   // print measured data rate
   Serial.print("Datarate:\t");
   Serial.print(lora.dataRate);
   Serial.println(" bps");

 } else if (state == ERR_PACKET_TOO_LONG) {
   // the supplied packet was longer than 256 bytes
   Serial.println(" too long!");

 } else if (state == ERR_TX_TIMEOUT) {
   // timeout occured while transmitting packet
   Serial.println(" timeout!");

    rtty.begin(434, 183, 45, 5);
  
   rtty.println(transmissionMessage);

 lora.standby();

 Serial.println(F("done!"));

 // wait for a second before transmitting again
 delay(1000);
 }
}
} 

This is ultimately what I am trying to achieve but it gets locked after the LoRa transmission.

Thank you very much Jgromes, hope I'm not disturbing too much with these questions :)

Best Regards,
Julian

SX126x Receive Interrupt output packet is incorrect and repeats

Issue: When using the SX126x receive interrupt example, the received data is incorrect and repeats for 3 to 20 seconds. Below is a snippit of the transmitted and received data. Is there something I am doing wrong to cause this?

radiocapture

Setup:

  • Transmitter: Ebyte E22-900M30S (SX1262) connected to Adafruit Feather Adalogger 32u4
  • Reveiver: Ebyte E22-900M22S (SX1262) connected to Arduino Nano

Some other facts:

  • The reveive interrupt is triggered at every transmission.
  • I don't have the probelm with the normal receive example.
  • I have swapped the code on the microcontrollers and the problem still exists.
  • Code is modified to support the Ebyte modules. Thank you to everyone on #12 for the code.

Transmitter:

/*
   RadioLib SX126x Receive Example

   This example listens for LoRa transmissions using SX126x Lora modules.
   To successfully receive data, the following settings have to be the same
   on both transmitter and receiver:
    - carrier frequency
    - bandwidth
    - spreading factor
    - coding rate
    - sync word
    - preamble length

   Other modules from SX126x family can also be used.

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/RadioLib/
*/

// include the library
#include <RadioLib.h>

void enableRX(void);
void enableTX(void);

#define RADIO_RXEN 11
#define RADIO_TXEN 12

SX1262 lora = new Module(10, 2, -1, 5);

void setup() {
  Serial.begin(115200);
  delay(1000);
  pinMode(13, OUTPUT);
  Serial.println("Tets");

  
  Serial.print(F("[SX1262] Initializing ... "));

  int state = lora.begin(915.0, 125.0, 7, 5, 0x1424, 22, 8);
  //lora.setCurrentLimit(65);

  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  if (lora.setTCXO(2.4) == ERR_INVALID_TCXO_VOLTAGE)
  {
    Serial.println(F("Selected TCXO voltage is invalid for this module!"));
  }

  enableTX();

}

void loop() {
  unsigned long p = millis();
  String k = String(p);
  int state = lora.transmit(k);
  Serial.println("Transmitting: " + String(p));


  delay(1000);
}

void enableRX(void)
{
  digitalWrite(RADIO_RXEN, HIGH);
  digitalWrite(RADIO_TXEN, LOW);
  delay(100);
}

void enableTX(void)
{
  digitalWrite(RADIO_RXEN, LOW);
  digitalWrite(RADIO_TXEN, HIGH);
  delay(100);
}

Receiver:

/*
   RadioLib SX126x Receive with Interrupts Example

   This example listens for LoRa transmissions and tries to
   receive them. Once a packet is received, an interrupt is
   triggered. To successfully receive data, the following
   settings have to be the same on both transmitter
   and receiver:
    - carrier frequency
    - bandwidth
    - spreading factor
    - coding rate
    - sync word

   Other modules from SX126x/RFM9x family can also be used.

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/RadioLib/
*/

// include the library
#include <RadioLib.h>

void enableRX(void);
void enableTX(void);

// GPIOs to control E22 RX_EN and TX_EN
#define RADIO_RXEN 4
#define RADIO_TXEN 7

// SX1262 has the following connections:
// NSS pin:   10
// DIO1 pin:  2
// DIO2 pin:  3
// BUSY pin:  9
SX1262 lora = new Module(10, 2, -1, 5);

// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 lora = RadioShield.ModuleA;

void setup() {
  Serial.begin(115200);

  Serial.print(F("[SX1262] Initializing ... "));

  int state = lora.begin(915.0, 125.0, 7, 5, 0x1424, 22, 8);
  //lora.setCurrentLimit(11.9);
  
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  if (lora.setTCXO(2.4) == ERR_INVALID_TCXO_VOLTAGE)
  {
    Serial.println(F("Selected TCXO voltage is invalid for this module!"));
  }

  enableRX();

  lora.setDio1Action(setFlag);

  // start listening for LoRa packets
  Serial.print(F("[SX1262] Starting to listen ... "));
  state = lora.startReceive();
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

}

// flag to indicate that a packet was received
volatile bool receivedFlag = false;

// disable interrupt when it's not needed
volatile bool enableInterrupt = true;

// 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!
void setFlag(void) {
  // check if the interrupt is enabled
  if(!enableInterrupt) {
    return;
  }

  // we got a packet, set the flag
  receivedFlag = true;
}

void loop() {
  // check if the flag is set
  if(receivedFlag) {
    // disable the interrupt service routine while
    // processing the data
    enableInterrupt = false;

    // reset flag
    receivedFlag = false;

    // you can read received data as an Arduino String
    String str = "";
    int state = lora.readData(str);

    if (state == ERR_NONE) {
      // packet was successfully received
     // Serial.println(F("[SX1262] Received packet!"));

      // print data of the packet
      Serial.print(F("Receiving:\t"));
      Serial.println(str);

    } else if (state == ERR_CRC_MISMATCH) {
      // packet was received, but is malformed
      Serial.println(F("CRC error!"));

    } else {
      // some other error occurred
      Serial.print(F("failed, code "));
      Serial.println(state);

    }

    // we're ready to receive more packets,
    // enable interrupt service routine
    enableInterrupt = true;
  }

}

void enableRX(void)
{
  digitalWrite(RADIO_RXEN, HIGH);
  digitalWrite(RADIO_TXEN, LOW);
  delay(100);
}

void enableTX(void)
{
  digitalWrite(RADIO_RXEN, LOW);
  digitalWrite(RADIO_TXEN, HIGH);
  delay(100);
}

scanChannel without using DIO2

As on some modules DIO2 is not available because it is used to switch the RF antenna between RX and TX.
This means scanChannel() function cannot be used.

As simple workaround could be to change scanChannel() to use only DIO1 as IRQ input.
Example code how it works (tested on eByte E22 module which uses DIO2 as RF antenna switch):

int16_t SX126x::scanChannel()
{
  // check active modem
  if (getPacketType() != SX126X_PACKET_TYPE_LORA)
  {
    return (ERR_WRONG_MODEM);
  }

  // set mode to standby
  int16_t state = standby();
  if (state != ERR_NONE)
  {
    return (state);
  }

  // set DIO pin mapping
  // state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED);
  // Use DIO1 only for both CAD DONE and CAD DETECTED interrupts
  state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE);
  if (state != ERR_NONE)
  {
    return (state);
  }

  // clear interrupt flags
  state = clearIrqStatus();
  if (state != ERR_NONE)
  {
    return (state);
  }

  // set mode to CAD
  state = setCad();
  if (state != ERR_NONE)
  {
    return (state);
  }

  // wait for channel activity detected or timeout
  while (!digitalRead(_mod->getInt0()))
  {
    // No need to check DIO2
    // if(digitalRead(_mod->getInt1())) {
    //   clearIrqStatus();
    //   return(LORA_DETECTED);
    // }
  }

  // Get the CAD result
  uint16_t cadResult = getIrqStatus();
  if (cadResult == 0x8000)
  {
    clearIrqStatus();
    return (CHANNEL_FREE);
  }
  else // cadResult == 0x8001
  {
    clearIrqStatus();
    return (LORA_DETECTED);
  }
  return (CHANNEL_FREE);
}

RTTY DECODER

Hi,
is it possible to decode RTTY directly? I have a module with sx1276, esp32 and oled display. I would like to receive and decode itty directly on board and show messages on display. Can you explain how to make it with your library? rtty.read() is not implemented.

Thanks

433MHz Lora with cheap sensors-outlets

SX126x Datasheet Updates and Errata

Looks like SX126x datasheets were changed quite a bit since SX126x was implemented - thanks a lot, Semtech. This includes previously undocumented registers, fixes to errata and possibly some other things.

Current SX126x driver should be revised to make sure it's up-to-date with the latest datasheet revision.

How can I get the raw data on DIO2 with interrupt ?

I'm using a ESP32 and a RFM69. I saw something about use the receiveDirect() for this. But I dont know how to use. When I try to see the DIO1 there is the clock (I guess). But in the DIO2 there is noise.

My goal is capture the signal of a RF garage control or similar devices.

Running LORA.receive(str) timeout extension using loop error

Hi,

I'm trying to extend the timeout for the receive function by putting it in a for loop. It can receive the first message fine, but in the next loops, it receives garbage?

Receiver

int state = 0;
String str = "";
for (int i = 0; i < 10; i++)
{
    state = LORA.receive(str);
    if (state == ERR_NONE)
    {
         Serial.println(str);
     }
}

Transmitter

void loop()
{
    int state = LORA.transmit("hello world!");
    if (state == ERR_NONE) Serial.println("Success");
}

Thanks,
Richard

SX1262 RX timeout

I have a Dorji SX1262 (868) I can't make it work in RX mode. The TX is working "SX126x_Transmit.ino" using "lora.setTCXO(1.6);"

ESP32 with Dorji DRF1262 (DIO2 not connected)
My RX sketch (not working):

#include <Arduino.h>
#include <WiFi.h>
#include <RadioLib.h>

time_t updateTime;
// Flag for sending finished
bool sendDone = false;

SPIClass *loraSPI = new SPIClass(HSPI);

//                      NSS DIO1 DIO2 BUSY
SX1262 lora = new Module(15, 22, -1, 21, *loraSPI);
int PIN_LORA_RESET = 19;

#define ssid = "MyWiFi"
#define pass = "qwerty123"
WiFiClient client;
struct tm timeinfo;
uint8_t dataMsg[6];
char ackMsg[] = "ACK";
long timeSinceLastPacket = 0;
uint16_t nodeId = 0;
char timeStamp[32];


void setup()
{
  
  pinMode(PIN_LORA_RESET, OUTPUT);
  digitalWrite(PIN_LORA_RESET, LOW);
  delay(100);
  digitalWrite(PIN_LORA_RESET, HIGH);

  Serial.begin(115200);

// initialize SX1262 
  // carrier frequency:           868.0 MHz
  // bandwidth:                   125.0 kHz
  // spreading factor:            7
  // coding rate:                 5
  // sync word:                   0x1424 (private network)
  // output power:                22 dBm
  // current limit:               60 mA
  // preamble length:             8 symbols
  // CRC:                         enabled
 
 // Initialize LoRa
  Serial.println(F("[SX1262] Initializing ... "));
 
  int state = lora.begin(868.0, 125.0, 7); //SF7
 
  if (state == ERR_NONE) {
    Serial.println(F("LORA  init success!"));
  } else {
    Serial.print(F("init failed, code "));Serial.println(state);
  }

  if (lora.setTCXO(1.6) == ERR_INVALID_TCXO_VOLTAGE)
  {
    Serial.println(F("Selected TCXO voltage is invalid for this module!"));
  }
}

void loop() {
  Serial.print(F("[SX1262] Waiting for incoming transmission ... "));

  String str;
  int state = lora.receive(str);

  if (state == ERR_NONE) {
    // packet was successfully received
    Serial.println(F("success!"));

    // print the data of the packet
    Serial.print(F("[SX1262] Data:\t\t")); Serial.println(str);

    // print the RSSI (Received Signal Strength Indicator)
    // of the last received packet
    Serial.print(F("[SX1262] RSSI:\t\t")); Serial.print(lora.getRSSI()); Serial.println(F(" dBm"));

    // print the SNR (Signal-to-Noise Ratio)
    // of the last received packet
    Serial.print(F("[SX1262] SNR:\t\t")); Serial.print(lora.getSNR()); Serial.println(F(" dB"));

  } else if (state == ERR_RX_TIMEOUT) {
    // timeout occurred while waiting for a packet
    Serial.println(F("timeout!"));

  } else if (state == ERR_CRC_MISMATCH) {
    // packet was received, but is malformed
    Serial.println(F("CRC error!"));

  } else {
    // some other error occurred
    Serial.print(F("failed, code ")); Serial.println(state);

  }
}

Output of that sketch:

[SX1262] Waiting for incoming transmission ... timeout!
[SX1262] Waiting for incoming transmission ... timeout!
[SX1262] Waiting for incoming transmission ... timeout!
... 

By the way I have another device transmitting over 868Mhz SF7 "helloworld" (tested and working)

Any Idea how to fix it?

LoRaWAN support

RadioLib could be extended to support LoRaWAN networks (and it's been on the TODO/WIP list for quite a while now).

ESP8266 platform compatibility

Hi, i am using a sx1272 module (ra-01) with a esp12f as microcontroller.
I tried to compile a simple code but the ARDUINO IDE gave me this error:

command-line>:0:9: error: expected identifier before numeric constant
/home/alexis/Arduino/libraries/RadioLib/src/modules/ESP8266.h:13:7: note: in expansion of macro 'ESP8266'
class ESP8266: public TransportLayer {
^
command-line>:0:9: error: expected unqualified-id before numeric constant
/home/alexis/Arduino/libraries/RadioLib/src/modules/ESP8266.h:13:7: note: in expansion of macro 'ESP8266'
class ESP8266: public TransportLayer {
^
exit status 1
Error compilando para la tarjeta Generic ESP8266 Module.

Code: (reduced for simplicity)

#include <RadioLib.h>

void setup() {
}

void loop() {
}

Any ideas? Thank you

Newbie starting point - module connection or pin definitions ?

Where do you have the pin connection info for non KiteShield hook ups ?
I'm trying to use the RFM69_receive example, with an Arduino UNO pinout compatible board (a Wemos D1) and a RFM69 breakout board to suit (but not your shield).
What Arduino pins go to the SPI pins on the RFM69 module for your code examples ?
I looked over all the files but came up blank...
Thanks,
Martin
(A newbie RF module user :)

SX126x.h setPacketParamsFSK() defaults to WHITENING_ON

This can be considered bug or feature, so I'll leave it as a general question.

Is there a reason why whitening on SX126x defaults to ON? This got me stuck for few days until I found it, now I'm finally receiving some data that starts to make sense (I'm missing first byte of data, but that may be another issue).

Can we add a method that sets the whitening? Something like:

int16_t setWhitening(bool whiteningEnabled);

I'm also not sure about other default values defined by:

int16_t setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t payloadLength = 0xFF, uint8_t packetType = SX126X_GFSK_PACKET_VARIABLE, uint8_t preambleDetectorLength = SX126X_GFSK_PREAMBLE_DETECT_16, uint8_t whitening = SX126X_GFSK_WHITENING_ON);

Doesn't it work the way that whenever the

setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp);

is used in code (setCRC(), disableAddressFiltering(), setSyncWord() etc.), it will actually use those defaults?

EDIT: And the missing first byte is because of SX126X_GFSK_PACKET_VARIABLE. So I guess we should think about how to implement these settings too.

SX126x CAD

Hi friends
I have been paying attention to your project! When I used the SX1261, I encountered such a problem: when the parameters are set, the CAD is turned on, and the CAD Detect interrupt occurs to enable the receiving mode.

If I use CAD Only mode, it will receive normally, but the packet loss rate is very high;
If you are using the CAD Rx mode, rxtimeout will be generated continuously.
I hope to seek some help, thank you.

The length byte is optional and should be written/read only if the module is in variable-length mode

Is your feature request related to a problem? Please describe.
Pure enhancement.

Describe the solution you'd like
As for the filter byte, the length byte should be optional, as stated in the specs: it's written only if the application protocol is in variable-length mode. Also, is there any reason why the filter reg value is not cached on the MCU memory? It would save one SPI read, and in high throughput transmissions it may make a difference.

I'm talking about CC1101 or RFM69, and similar modules.

sx1278 signal strength related functions

Hi jgromes! we are actually using the sx1278 for 433MHz FSK with RadioLib, but we need the signal strength information, we have already check the register map for FSK in the sx1278 and RSSI value and RSSI configuration is available. Do you have a function to read this in the receiver? or can you make that available? The parameters related to RSSI available from the register map are:

  • RssiOffset
  • RssiSmoothing
  • RssiCollisionThreshold
  • RssiThreshold
  • RssiValue
  • TimeoutRxRssi
  • Rssi

Regards

CC1101 goes to Standby after receiving a packet.

Hi Jan,
I've a question about the implementation of the CC1101 receive flow,
Why does the readData() method put the radio back in idle mode after a packet is read from RX FIFO?

I think this way the example will not work properly since the radio is put in receive mode only once , then data is read using readData whose side effect is to put radio back in IDLE. This way (I suppose) no other packet will be received.

Unfortunately I cannot test it with a real radio at the moment.
Thankyou

lilygo ttgo t-deer gives error -12 on "in range" frequency

Bought 3 units with the same radio label:TTGO 433 470 MHz Modle LoRa32 radio module, SX1278

I have one unit which gives error -12 when I set the LoRa frequency to anything between 432 and 470 MHz and no error when I set 868 - 880 MHz however it does not transmit on that 868 MHz frequency.

The code sends RTTY and LoRa alternating (for radiotracker under a balloon) and RTTY does transmit on 432 MHz without problems.

`// Default RTTY settings. Change when needed
#define RTTY_FREQUENCY 432.762
#define RTTY_SHIFT 600
#define RTTY_BAUD 75
#define RTTY_STOPBITS 1

// Default LORA settings. Change when needed
#define LORA_FREQUENCY 869.662
#define LORA_BANDWIDTH 125.0
#define LORA_SPREADFACTOR 9
#define LORA_CODERATE 7`

I have no clue why this does happen.
The first hardware board from the same seller does not give this error and does transmit on 432.762 if I set that frequency.

Running the same board with Stuart Robinson tracker software does do tranmist both LoRa and RTTY on 432.762 if I set that frequency.

Any idea what could be the issue ?

Carrier-sense multiple access (CSMA / being polite)

Is your feature request related to a problem? Please describe.
The radios don't wait until the channel is clear before transmitting. If a unit starts to transmit halfway through a packet directed to it, it will miss that packet. It might also cause other stations to miss the packet it interrupts, or its packet might not be heard (or both).

Describe the solution you'd like
An implementation of p-persistence CSMA:

  • Radio will transmit only if it detects the channel is not busy
  • If the channel is busy, radio waits until the end of the transmission then waits a random amount of time before attempting to transmit (so that two radios waiting on the same message don't collide when they both immediately start transmitting)

Configuration parameters might include:

  • bool performCSMA: Whether this feature should be active or whether the unit will transmit regardless.
  • float timeslotPeriod: How large a timeslot to use to perform the p-persistence algorithm. If the consumer does not provide this, RadioLib could use an appropriate value based on the estimated time on air of the packet to send (and the assumption that other packets on the network will be comparable size).
  • float p: probability of transmitting in any given timeslot. if p=1 this reduces to 1-persitence (transmit as soon as the channel is clear).

Describe alternatives you've considered
The isChannelBusy() proposed in #67 could be the standard function that physical layers expose if they are able to be used with feature. This can be implemented without the complex functionality described there, it just won't be as good.

Additional context
https://en.wikipedia.org/wiki/Carrier-sense_multiple_access

I'm going to write this code anyway, if there's interest in including it in this library we can figure out a good interface before I get started.

Question for SX126x module: IRQs and DIO2

I am connecting a eByte E22-900M22 module with the SX1262 chip. This module has DIO1 and DIO2 exposed, but DIO2 (in my setup) is used to control the RX/TX direction of the antenna. DIO3 is not available.

The initialization routine for the SX1262 module asks for 2 interrupt inputs. But I can only assign DIO1.

Questions:

  • Will it work with only one IRQ?
  • If it should work, how do I initialize the module?
  • Does the library setup DIO2 to control the antenna? Do I have to set a flag to activate this feature?

The code is based on the SX126x_Receive.ino and SX126x_Transmit.ino examples:

#include <Arduino.h>
#include <SPI.h>

#include <RadioLib.h>

// SX1262 module is in slot A on the shield
SX1262 lora = new Module(5, 25, 25, 22, SPI);

void setFlag(void);
void printError(int errNo);
#define LED_RED 16
#define RADIO_RXEN 27
#define RADIO_TXEN 26

// flag to indicate that a packet was received
volatile bool receivedFlag = false;

// disable interrupt when it's not needed
volatile bool enableInterrupt = true;

uint8_t dataBuffer[1024];

void setup()
{
  pinMode(LED_RED, OUTPUT);
  pinMode(RADIO_RXEN, OUTPUT);
  pinMode(RADIO_TXEN, INPUT);
  digitalWrite(LED_RED, HIGH);
  digitalWrite(RADIO_RXEN, HIGH);
  // digitalWrite(RADIO_TXEN, LOW);

  SPI.begin(18, 19, 23, 5);

  Serial.begin(115200);
  Serial.println("=====================================");
  Serial.println("SX126x receiver test");
  Serial.println("=====================================");

  int state = lora.begin(915.0, 125.0, 6, 5, 0x3444, 22, 8);
  // int state = lora.begin();
  if (state == ERR_NONE)
  {
    Serial.println("success!");
  }
  else
  {
    Serial.print("failed: ");
    printError(state);
  }

  // set the function that will be called
  // when new packet is received
  lora.setDio1Action(setFlag);
  lora.setDio2Action(setFlag);

  digitalWrite(RADIO_RXEN, HIGH);

  // start listening for LoRa packets
  // Serial.print("[SX1262] Starting to listen ... ");
  // state = lora.startReceive();
  // if (state == ERR_NONE)
  // {
  //   Serial.println("success!");
  // }
  // else
  // {
  //   Serial.print("failed: ");
  //   printError(state);
  // }

  /// \todo add WiFi connection here
}

void loop()
{
  // put your main code here, to run repeatedly:
  digitalWrite(LED_RED, !digitalRead(LED_RED));
  delay(500);

  int result = lora.receive(dataBuffer, 1024);
  if ((result != ERR_NONE) && (result != ERR_RX_TIMEOUT))
  {
  Serial.print("Receive error: ");
  printError(result);
  }
  else if (result == ERR_NONE)
  {
    Serial.println("Received==>");
    Serial.println(String((char *)dataBuffer));
  }

  // check if the flag is set
  if (receivedFlag)
  {
    // disable the interrupt service routine while
    // processing the data
    enableInterrupt = false;

    // reset flag
    receivedFlag = false;

    // you can read received data as an Arduino String
    String str;
    int state = lora.readData(str);

    // you can also read received data as byte array
    /*
      byte byteArr[8];
      int state = lora.receive(byteArr, 8);
    */

    if (state == ERR_NONE)
    {
      // packet was successfully received
      Serial.println("[SX1262] Received packet!");

      // print data of the packet
      Serial.print("[SX1262] Data:\t\t");
      Serial.println(str);

      // print RSSI (Received Signal Strength Indicator)
      Serial.print("[SX1262] RSSI:\t\t");
      Serial.print(lora.getRSSI());
      Serial.println(" dBm");

      // print SNR (Signal-to-Noise Ratio)
      Serial.print("[SX1262] SNR:\t\t");
      Serial.print(lora.getSNR());
      Serial.println(F(" dBm"));
    }
    else if (state == ERR_CRC_MISMATCH)
    {
      // packet was received, but is malformed
      Serial.println(F("CRC error!"));
    }

    // we're ready to receive more packets,
    // enable interrupt service routine
    enableInterrupt = true;
  }
}

// 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!
void setFlag(void)
{
  // check if the interrupt is enabled
  if (!enableInterrupt)
  {
    return;
  }

  // we got a packet, set the flag
  receivedFlag = true;
}

void printError(int errNo)
{
  switch (errNo)
  {
  case ERR_NONE:
    Serial.println("Success!");
    break;
  case ERR_UNKNOWN:
    Serial.println("Unknown error");
    break;
  case ERR_CHIP_NOT_FOUND:
    Serial.println("SX127x not found");
    break;
  case ERR_EEPROM_NOT_INITIALIZED:
    Serial.println("EEPROM not initialized");
    break;
  case ERR_PACKET_TOO_LONG:
    Serial.println("TX packet too long");
    break;
  case ERR_TX_TIMEOUT:
    Serial.println("TX timeout");
    break;
  case ERR_RX_TIMEOUT:
    Serial.println("RX timeout");
    break;
  case ERR_CRC_MISMATCH:
    Serial.println("CRC error");
    break;
  case ERR_INVALID_BANDWIDTH:
    Serial.println("Invalid bandwidth");
    break;
  case ERR_INVALID_SPREADING_FACTOR:
    Serial.println("Invalid spreading factor");
    break;
  case ERR_INVALID_CODING_RATE:
    Serial.println("Invalid coding rate");
    break;
  case ERR_INVALID_BIT_RANGE:
    Serial.println("Invalid bit range (internal error)");
    break;
  case ERR_INVALID_FREQUENCY:
    Serial.println("Invalid frequence value");
    break;
  case ERR_INVALID_OUTPUT_POWER:
    Serial.println("Invalid output power");
    break;
  case PREAMBLE_DETECTED:
    Serial.println("Channel is in use");
    break;
  case CHANNEL_FREE:
    Serial.println("Channel is free");
    break;
  case ERR_SPI_WRITE_FAILED:
    Serial.println("SPI write error");
    break;
  case ERR_INVALID_CURRENT_LIMIT:
    Serial.println("Invalid current limit");
    break;
  case ERR_INVALID_PREAMBLE_LENGTH:
    Serial.println("Invalid preamble length");
    break;
  case ERR_INVALID_GAIN:
    Serial.println("Invalid gain");
    break;
  case ERR_WRONG_MODEM:
    Serial.println("Wrong modem command");
    break;
  case ERR_INVALID_BIT_RATE:
    Serial.println("Invalid bit rate");
    break;
  case ERR_INVALID_FREQUENCY_DEVIATION:
    Serial.println("Invalid frequence deviation");
    break;
  case ERR_INVALID_BIT_RATE_BW_RATIO:
    Serial.println("Invalid bit rate bandwidth ratio");
    break;
  case ERR_INVALID_RX_BANDWIDTH:
    Serial.println("Invalid RX bandwidth");
    break;
  case ERR_INVALID_SYNC_WORD:
    Serial.println("FSK sync word invalid");
    break;
  case ERR_INVALID_DATA_SHAPING:
    Serial.println("Invalid FSK data shaping");
    break;
  case ERR_INVALID_MODULATION:
    Serial.println("Invalid modulation");
    break;
  case ERR_AT_FAILED:
    Serial.println("AT command failed");
    break;
  case ERR_URL_MALFORMED:
    Serial.println("Invalid URL");
    break;
  case ERR_RESPONSE_MALFORMED_AT:
    Serial.println("Malformed AT command");
    break;
  case ERR_RESPONSE_MALFORMED:
    Serial.println("Malformed response");
    break;
  case ERR_MQTT_CONN_VERSION_REJECTED:
    Serial.println("MQTT connection rejected due to version mismatch");
    break;
  case ERR_MQTT_CONN_ID_REJECTED:
    Serial.println("MQTT connection rejected due to unknown ID");
    break;
  case ERR_MQTT_CONN_SERVER_UNAVAILABLE:
    Serial.println("MQTT server unavailable");
    break;
  case ERR_MQTT_CONN_BAD_USERNAME_PASSWORD:
    Serial.println("MQTT username/password incorrect");
    break;
  // case ERR_MQTT_CONN_NOT_AUTHORIZED:
  //   Serial.println("Unauthorized connection to MQTT broker");
  //   break;
  case ERR_MQTT_UNEXPECTED_PACKET_ID:
    Serial.println("Unexpected MQTT packet ID");
    break;
  case ERR_MQTT_NO_NEW_PACKET_AVAILABLE:
    Serial.println("No packet available");
    break;
  // case MQTT_SUBS_SUCCESS_QOS_0:
  //   Serial.println("MQTT QoS 0 subscription success");
  //   break;
  case MQTT_SUBS_SUCCESS_QOS_1:
    Serial.println("MQTT QoS 1 subscription success");
    break;
  case MQTT_SUBS_SUCCESS_QOS_2:
    Serial.println("MQTT QoS 2 subscription success");
    break;
  case ERR_MQTT_SUBS_FAILED:
    Serial.println("MQTT subscription failed");
    break;
  case ERR_CMD_MODE_FAILED:
    Serial.println("Command failure");
    break;
  case ERR_FRAME_MALFORMED:
    Serial.println("Frame malformed");
    break;
  case ERR_FRAME_INCORRECT_CHECKSUM:
    Serial.println("Frame checksum error");
    break;
  case ERR_FRAME_UNEXPECTED_ID:
    Serial.println("Unexpected ID");
    break;
  case ERR_FRAME_NO_RESPONSE:
    Serial.println("Frame timeout");
    break;
  case ERR_INVALID_RTTY_SHIFT:
    Serial.println("Invalid RTTY shift");
    break;
  case ERR_UNSUPPORTED_ENCODING:
    Serial.println("Unsupported encoding");
    break;
  case ERR_INVALID_DATA_RATE:
    Serial.println("Invalid data rate");
    break;
  case ERR_INVALID_ADDRESS_WIDTH:
    Serial.println("Invalid address width");
    break;
  case ERR_INVALID_PIPE_NUMBER:
    Serial.println("Invalid pipe number");
    break;
  case ERR_INVALID_NUM_BROAD_ADDRS:
    Serial.println("Invalid broadcast address");
    break;
  case ERR_INVALID_CRC_CONFIGURATION:
    Serial.println("Invalid CRC configuration");
    break;
  case LORA_DETECTED:
    Serial.println("Scan found LoRa transmission");
    break;
  case ERR_INVALID_TCXO_VOLTAGE:
    Serial.println("Invalid TCXO voltage");
    break;
  case ERR_INVALID_MODULATION_PARAMETERS:
    Serial.println("Invalid modulation parameter");
    break;
  case ERR_SPI_CMD_TIMEOUT:
    Serial.println("SPI timeout");
    break;
  case ERR_SPI_CMD_INVALID:
    Serial.println("SPI received invalid command");
    break;
  case ERR_SPI_CMD_FAILED:
    Serial.println("SPI CMD failed");
    break;
  }
}

SX1262 TransmitDirect?

Can this function be implemented in the SX1262 module? Looks like DIO2 is already occupied by the RF switch.

RTTY on CC1101?

Hi! I'm looking for a solution to transmit RTTY teletype telemetry through a CC1101 equipped shield. I see that you're working on something that might satisfy my needs. What's the outlook and is there maybe an ETA?

Also, is KiteShield needed to use your library?

Add function to set DIO2 as RF switch control

Hope I am not getting annoying with my issues.

I got my Insight DSP4520 modules. These modules combines a nRF52 and a SX1262 into one package.
Unfortunately on these boards the DIO2 is used as RF switch control and this cannot be changed.
Is there any hope that I can change the library to setup DIO2 as RF switch control?
I found in SX126x.cpp this:

int16_t SX126x::config(uint8_t modem) {
  // set DIO2 as IRQ
  uint8_t* data = new uint8_t[1];
  data[0] = SX126X_DIO2_AS_IRQ;
  Serial.println("Setting DIO2 as RF switch control");
  int16_t state = SPIwriteCommand(SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, data, 1);
  if(state != ERR_NONE) {
    return(state);
  }
...

and

int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
  uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
                     (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
                     (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
                     (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
  return(SPIwriteCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, data, 8));
}

I changed it to

int16_t SX126x::config(uint8_t modem) {
  // set DIO2 as IRQ
  uint8_t* data = new uint8_t[1];
#ifdef DSP4520
  data[0] = SX126X_DIO2_AS_RF_SWITCH;
#else
  data[0] = SX126X_DIO2_AS_IRQ;
  Serial.println("Setting DIO2 as RF switch control");
#endif
  int16_t state = SPIwriteCommand(SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, data, 1);
  if(state != ERR_NONE) {
    return(state);
  }
...

and

int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
#ifdef DSP4520
  // This will break the CAD functionality
  dio2Mask = dio2Mask = SX126X_IRQ_NONE;
  Serial.println("Setting DIO2 to SX126X_IRQ_NONE");
  uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
                     (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
                     (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
                     (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
#else
  uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
                     (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
                     (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
                     (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
#endif
  return(SPIwriteCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, data, 8));
}

Just for testing.
But that might not be the only functions that needs to be changed. Can you point me to where I should search for additional locations that needs to be changed.
I know that this will break the CAD function, but I really would like to use your library, because it is much easier to setup than the SEMTECH example library for the SX126x chips.

If I get it to work, I will think about how to make this configurable (e.g. in the begin() function) and prepare a pull-request.

SX126x non-interrupting scanChannel() alternative

Is your feature request related to a problem? Please describe.
The SX126x scanChannel function will interrupt a receive in progress that might have been started with startReceive, causing the packet that is being received to be dropped.

Describe the solution you'd like
A method isChannelBusy() that, if in receive mode, will query whether a preamble has been recently detected (see additional context below) and return that there is traffic without interrupting the receive.

If the unit is not in receive mode, isChannelBusy() will return the result of scanChannel().

Describe alternatives you've considered
Can't really think of much.

Additional context
CSMA #68 is the motivation for this.

I've already got this written: In startReceive, an additonal IRQ flag is set up so we get notification of Preamble Detected. A custom ISR is attached to DIO1 that tracks the preamble, and calls the consumer defined function when Rx Done is signalled.

isChannelBusy looks if a preamble has been detected without a Rx Done recently (there's a timeout for in case we get a false preamble detection or never get Rx Done), and returns that the channel is busy if that's the case.

To avoid breaking existing code, an optional parameter can be added to startReceive to indicate whether to attach our own ISR to track preamble detection. I would like to add two other new functions too: setRxDoneAction and setTxDoneAction; these would supersede setDio1Action (maybe that could be declared deprecated?).

Let me know if there's interest and I'll spend the time polishing up my code to put it into a PR.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.