LoRa stack and DIOs

Dear All,

There are two popular open source options of LoRa stack for SX1276 chip as an end device:

  1. IBM “LoRa WAN in C” (http://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html)
  2. Semtech “LoRaMac-node” (https://github.com/Lora-net/LoRaMac-node)

If I got it right, the IBM version uses only the DIO 0-2 pins on SX1276 while the Semtech implementation uses all DIO 0-5 pins.

The custom schematic with SX1276 I have uses only DIO 0-2 pins so using of IBM stack seems to be natural. However, the Semtech stack provides ping-pong example between two nodes which I would like to use (IBM stack’s examples seem to work only with gateway).

So my questions are:

  1. how hard will it be to adapt Semtech LoraMac-node stack so that it uses only DIO 0-2 pins?
  2. I guess a simple DIO remapping will not do the job and one will have to modify all those parts of the LoraMac-node stack where DIO 3-5 pins are used?

Any hint would be of great help!

Thanks a lot in advance.

  1. how hard will it be to adapt Semtech LoraMac-node stack so that it uses only DIO 0-2 pins?

SX1276 has the following usages on the pins in LoRa mode (which is used most of the time):

  • ModeReady (IRQ)
  • ClkOut
  • PllLock (IRQ)
  • ValidHeader (IRQ)
  • PayloadCrcError (IRQ)

The IRQ’s can however be read from the SX1276 by reading register 0x12 (LoRa) or register 0x3e or 0x3f (FSK/OOK). So it should be possible to access all status bits without these pins only perhaps some timing issues may occur.
I am not so much into LoRaMac-node code to help you any further, I have only used LMiC. So this is not of much help I guess.

  1. I guess a simple DIO remapping will not do the job and one will have to modify all those parts of the LoraMac-node stack where DIO 3-5 pins are used?

Just asking, but how many uses of these IRQ’s are there in LoRaMac-node code? My guess: not so many.

2 Likes

In the last lines of this file are the functions:
SX1276OnDio3Irq, SX1276OnDio4Irq and SX1276OnDio5Irq. In these functions lie the clue to what the DIO’s are used for.

DIO3: FSK nothing, LoRa CADDETECTED or CADDONE
DIO4: FSK PreambleDetected, LoRa nothing
DIO5: FSK nothing, LoRa nothing

1 Like

Thank you so much for your time and the clues.

May I ask why have you chosen LMiC instead of LoraMac? I know that LMiC got available earlier than LoraMac and this is one of the reasons that many people started using LMiC.

Just wanted to make sure that people selected LMiC not because the current version of LoraMac has drawbacks or is buggy/inconsistent.

Thanks very much again for your very helpful comments.

Hi @davhak,

I chose to use LMiC because it was very clear to me how to implement this in my project, also there is a clear discription on how to create the HAL. LoRaMAC-node gave so many files I was kind of lost and didn’t know how to use it.

1 Like

Dear @scle,

Thanks a lot for your comments.
I agree that LMiC code is simpler and probably better documented.

May I also ask whether you tried a node-to-node connection with LMiC (i.e. without gateway)?
All the examples of LMiC involve gateway while LoraMac has a ping-pong example.
I think that missing of ping-pong example in LMiC has nothing to do with its way of implementation of the stack (i.e. it is just an unfortunate omission). Could you please also comment on this?

Thanks so much for your time and help.

I didn’t do node-to-node communication, if you mean talking in LoRaWAN protocol but then node-to-node?

I did do node-to-node communication with raw LoRa, spi register writes. But not in combination with LoRaWAN, so I didn’t actually combine the code. You would have to build in this behaviour, since the library assumes total control over the SX1272/6.

1 Like

Dear @scle,

Thank you very much for all your comments and time.

For future readers of this thread, https://github.com/matthijskooijman/arduino-lmic/tree/master/examples/raw is an LMiC ping-pong example.

A simple search shows this:
// Initialize Radio driver RadioEvents.TxDone = OnRadioTxDone; RadioEvents.RxDone = OnRadioRxDone; RadioEvents.RxError = OnRadioRxError; RadioEvents.TxTimeout = OnRadioTxTimeout; RadioEvents.RxTimeout = OnRadioRxTimeout; Radio.Init( &RadioEvents );

I have never seen the DIO3 interrupt being called, so I guesss this should work

I looked at both LMIC and the SemTech code. The Semtech code looked clearer to me. It has very clear identifiable HAL, radio and MAC layers and I had things working in a very short time. The availability of the simple node to node examples helped a lot.
But as always YMMV :wink:

As LMiC did not allow node-to-node connection I also switched afterwards to LoraMac-node and could establish node-to-node transaction relatively easy.

Likely this question isn’t relevant any longer, but to handle an inAir9b that only uses DIO0 to DIO3, there’s an mbed Semtech stack library available at www.pyocd.org/users/modtronix/code/SX1276Lib_modtronix/.The library itself is now somewhat out of date but can at least be used to help identify the code changes needed. Best wishes, Ron.

1 Like

Guys,
just for information I’ve made a PR, now LMIC can works with absolutely NO DIO connection or even 1 instead of 3 (making a diode OR between DIO0/DIO1/DIO2) You can read about this here

2 Likes

My understanding is both LoRaWAN and LMIC only use DIO0 (Tx-Done or Rx-Done) or DIO1 (Time-outs); and though LoRaWAN has call-backs for the other interrupts, they aren’t used. Indeed, even DIO1 is not necessary in LoRaWAN as it uses software timers (timeServer.c in the Utilities directory calls HW_RTC_GetTimerElapsedTime() which ultimately gets the time from the RTC clock). I apologise if there is no interest in this due to a stale topic.

LoRaWan in mbed has this :

void SX1276_LoRaRadio::handle_dio3_irq(void)
{
    switch (_rf_settings.modem) {
        case MODEM_FSK:
            break;
        case MODEM_LORA:
            if ((read_register(REG_LR_IRQFLAGS) & RFLR_IRQFLAGS_CADDETECTED)
                    == RFLR_IRQFLAGS_CADDETECTED) {
                // Clear Irq
                write_to_register(REG_LR_IRQFLAGS,
                        RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE);
                if ((_radio_events != NULL)
                        && (_radio_events->cad_done)) {
                    _radio_events->cad_done(true);
                }
            } else {
                // Clear Irq
                write_to_register(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE);
                if ((_radio_events != NULL)
                        && (_radio_events->cad_done)) {
                    _radio_events->cad_done(false);
                }
            }
            break;
        default:
            break;
    }
} 

RFLR_IRQFLAGS_CADDETECTED is set up before transmitting, it seems to want to finish CADDETECTED before transmitting.

The mbed LoRaWan code is pretty IRQ heavy, i’m assuming this is to eliminate polling and lower power consumption.

We do NOT duplicate posts here, it wastes volunteers time.

From the other topic you created that I replied to:

Via the data sheet?

If we tell you one register read, what if you need to ask another, and another …