Search code examples
c++arduinoesp8266esp32arduino-esp8266

How do I port C++ code to Esp8266 and Esp32 using interrupts from code written for older boards


I am trying to port some C++ Arduino code to more recent ESP8266 and ESP32 boards. I have checked already the Arduino Stack Exchange forum unfortunately without results

Porting this C++ code from older Arduino to Esp8266/Esp32 does not work, I have added also the compiling errors at the bottom of this question:

/*  rcTiming.ino -- JW, 30 November 2015 -- 
 * Uses pin-change interrupts on A0-A4 to time RC pulses
 *
 * Ref: https://arduino.stackexchange.com/questions/18183/read-rc-receiver-channels-using-interrupt-instead-of-pulsein
 *
 */
#include <Streaming.h>
static   byte rcOld;        // Prev. states of inputs
volatile unsigned long rcRises[4]; // times of prev. rising edges
volatile unsigned long rcTimes[4]; // recent pulse lengths
volatile unsigned int  rcChange=0; // Change-counter

// Be sure to call setup_rcTiming() from setup()
void setup_rcTiming() {
  rcOld = 0;
  pinMode(A0, INPUT);  // pin 14, A0, PC0, for pin-change interrupt
  pinMode(A1, INPUT);  // pin 15, A1, PC1, for pin-change interrupt
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  PCMSK1 |= 0x0F;       // Four-bit mask for four channels
  PCIFR  |= 0x02;       // clear pin-change interrupts if any
  PCICR  |= 0x02;       // enable pin-change interrupts
}
// Define the service routine for PCI vector 1
ISR(PCINT1_vect) {
  byte rcNew = PINC & 15;   // Get low 4 bits, A0-A3
  byte changes = rcNew^rcOld;   // Notice changed bits
  byte channel = 0;
  unsigned long now = micros(); // micros() is ok in int routine
 while (changes) {
    if ((changes & 1)) {  // Did current channel change?
      if ((rcNew & (1<<channel))) { // Check rising edge
        rcRises[channel] = now;     // Is rising edge
      } else {              // Is falling edge
        rcTimes[channel] = now-rcRises[channel];
      }
    }
    changes >>= 1;      // shift out the done bit
    ++channel;
    ++rcChange;
  }
  rcOld = rcNew;        // Save new state
}

void setup() {
  Serial.begin(115200);
  Serial.println("Starting RC Timing Test");
   setup_rcTiming();
}

void loop() {
  unsigned long rcT[4]; // copy of recent pulse lengths
  unsigned int rcN;
  if (rcChange) {

    // Data is subject to races if interrupted, so off interrupts
    cli();          // Disable interrupts
    rcN = rcChange;
    rcChange = 0;       // Zero the change counter
    rcT[0] = rcTimes[0];
    rcT[1] = rcTimes[1];
    rcT[2] = rcTimes[2];
    rcT[3] = rcTimes[3];
    sei();          // reenable interrupts

    Serial << "t=" << millis() << " " << rcT[0] << " " << rcT[1]
       << " " << rcT[2] << " " << rcT[3] << " " << rcN << endl;
  }
  sei();            // reenable interrupts
}

The compiling error is:

expected constructor, destructor, or type conversion before '(' token

at line:

ISR(PCINT1_vect) {

I am seeking suggestions to get it working thank you.


Solution

  • All ESP32 GPIO pins are interrupt-capable pins. You can use interrupts, but in a different way.

    attachInterrupt(GPIOPin, ISR, Mode);
    

    Mode – Defines when the interrupt should be triggered. Five constants are predefined as valid values:HIGH, LOW, CHANGE, RISING, FALLING

    void IRAM_ATTR ISR() {
    Statements;
    }
    

    Interrupt service routines should have the IRAM_ATTR attribute, according to the ESP32 documentation