Skip to content

Interruptions

Similar to GPIOs, interrupts can be configured from the conf-user.h configuration file.

This is the default configuration

#define ISR_MODE ISR_SIMPLE
#define ISR_PIN NMI  // ISR SIMPLE
#define ISR_PINS -1  // ISR ADVANCED
Property Desc
ISR_MODE Select interruption mode, two possible options: ISR_SIMPLE or ISR_ADVANCED
ISR_PIN Interruption pin number when ISR_MODE=ISR_SIMPLE
ISR_PINS Comma separated list of interruption pins when ISR_MODE=ISR_ADVANCED

Configuration

The simple mode only allows you to create an interruption on a single pin. It is recommended to use this mode when working with a microcontroller with very few resources or when we simply need a single interrupt and want to save RAM memory.

Configuration for simple mode

#define ISR_MODE ISR_SIMPLE
#define ISR_PIN NMI
#define ISR_PINS -1

The ISR_PINS macro will be discarded and not taken into account.

Configuration for advance mode

Suppose we want to activate an interruption at the IO0 and IO1 pins, we could set it up like this:

#define ISR_MODE ISR_ADVANCED
#define ISR_PIN -1
#define ISR_PINS IO0, IO1

In the advanced mode, up to 5 interruptions can be created using the macro ISR_PINS. It can be set to -1 to disable all interruptions. It is important not to exceed the limit of 5 interruptions. For example the following setting may lead to unexpected behavior:

#define ISR_MODE ISR_ADVANCED
// error, there are 6 pins
#define ISR_PINS IO0, IO1, IO2, IO3, IO4, IO5

How to Detect an Interruption

A few lines of code in the main.cpp will be enough to detect when an interrupt has occurred:

Check first that the configuration is correct in conf-user.h:

#define ISR_MODE ISR_SIMPLE
#define ISR_PIN NMI

Now create the onIsr() method in the main.cpp, it will be in charge of receiving the interruption.

#include "rhomb.iot.h"

uint8_t onIsr(uint8_t pinNumber) {
  // Check if interruption is on pin NMI
  if (pinNumber == NMI) {
    echo::info("Interruption Fired on pin NMI!");
  }
  return 0;
}

void setup() {
  core::setup();

  // register our interruption callback
  puf::on(EV_ISR, onIsr);
}

void loop() {
  core::loop();
}

First we have created the onIsr() method which accepts a parameter, which will be the pin number that has caused the interruption. Then, in the setup(), we have created a subscription to the EV_ISR event so that our method is executed when the interruption occurs.

The same code can also be written with a lambda function:

#include "rhomb.iot.h"

void setup() {
  core::setup();
  puf::on(EV_ISR, [](uint8_t pinNumber) -> uint8_t {
    if (pinNumber == NMI) {
      echo::info("Interruption Fired on pin NMI!");
    }
    return 0;
  });
}

[...]

With the advanced mode, a switch statement can be used to detect the pin that has generated the interruption:

// conf-user.h
#define ISR_MODE ISR_ADVANCED
#define ISR_PINS IO0, IO1

// main.cpp
#include "rhomb.iot.h"

uint8_t onIsr(uint8_t pinNumber) {
  switch (pinNumber) {
    case IO0:
      echo::info("Interruption on IO0");
      break;
    case IO1:
      echo::info("Interruption on IO1");
      break;
    default:
      echo::info("Unknow interruption on pin number", pinNumber);
  }
  return 0;
}


void setup() {
  core::setup();
  puf::on(EV_ISR, onIsr);
}

[...]

Detect button pressed/released

Rhomb.IoT interrupts allow you to know the time or duration of the interruption for example to known how many time a button has been pressed.

The operation is simple, when you press the button a first event is generated to indicate that the interruption has started, when you lift your finger from the button a second event will be generated again from which you can get the total duration of the interruption (how long you have been pressing the button)

We use the object isr::last for this:

uint8_t onIsr(uint8_t pinNumber) {
  echo::info("New interruption on pin", pinNumber);
  if (isr::last.duration == 0) {
    // first event of the button (press/down)
    echo::info("Button pressed");
  } else if (isr::last.duration > 0) {
    // second event (release/up)
    echo::info("Button released, duration", isr::last.duration);
  }
  return 0;
}

void setup() {
  core::setup();
  puf::on(EV_ISR, onIsr);
}

Knowing the duration of the interruption time can be useful to apply multiple actions on the same button/pin depending on the duration of time.

Comments