CLI (), SEI () and PIND equivalent commands on GIGA R1 - Mbed OS?

Hi there,
I successfully have implemented a rotary encoder example sketch of Nick Gammon on a AVR Board (Nano) in one of my projects. So now I am tryin to transfer the code onto the GIGA...

The sketch is using commands as CLI() and SEI() in the context of interrupts. As well there is used the command PIND to read portPin status.
As those commands doesn't work with Mbed OS anymore, how could I make it work again?

Could I just substitute CLI() with NoInterrupts() and SEI() with Interrupts()?
And is there any equivalent command to PIND in Mbed OS to read portPins?

I am pretty much a beginner and hope to get helped out.

PS: I also have an open thread going in on in the German section about this. You may check it out in the link below. I've got some quite good ideas about workarounds there, but also I am still looking for answers to my question mentioned above.

Verwendung von CLI(), SEI() und "PIND" auf GIGA R1?

Thanks in advance :slightly_smiling_face:

We tend to dislike double posts.

Cross-posting is against the Arduino forum rules. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend a lot of time investigating and writing a detailed answer on one topic, without knowing that someone else already did the same in the other topic.

1 Like

Thanks for your statement! I am aware about the difficulties of cross-postings. For this reason I mentioned the link here to the posting in the German section for cross-checking (because I don't wanna waste anybody's time).
As I wrote, there I got some hints for workarounds but not the answers to my questions. That's why I was hoping being helped here. If I have broken the rules, my apologies.

Not only you can use noInterrupts() and interrupts() but you definitely should use them because they are the cross-architecture portable functions provided by the Arduino API.

Regarding PIND, if digitalRead() and digitalWrite() are not an option for you, I believe you should have a look at PortInOut provided by mbed, but I'm personally not much familiar with that :slight_smile:

1 Like

Hi Alessandro, thanks for your quick and helpful reply!
I definitely will try that and take it to my heart using noInterrupts() and interrupts() in the future.
I was wondering why N. Gammon was using PIND instead of digitalRead() and digitalWrite() in his sketch. I guess for quicker interaction. But as the GIGA is powerful, I will give it a try with digitalRead() and digitalWrite().
Good hint with PortInOut ... I will definitely have a closer look on that one!

I appreciate your help - thanks!

Direct port manipulation is often abused, but makes sense if you're writing highly optimized code and want to change multiple pins at the same time. It's the efficiency vs portability dilemma :slight_smile:
More information here https://docs.arduino.cc/hacking/software/PortManipulation

Okay, I got you on that! :slightly_smiling_face:
It looks like the N.Gammon-sketch does read the status of 2 interrupt pins at the same time:

Thanks for the link about PortManipulation by the way!

/*******Interrupt-based Rotary Encoder Sketch*******
by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence
*/

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent

void setup() {
  pinMode(pinA, INPUT); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pinB, INPUT); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
  attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
  Serial.begin(115200); // start the serial monitor link
}

void PinA(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
  if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    if (encoderPos > 0) encoderPos=encoderPos-5; //decrement the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void PinB(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
  if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    if (encoderPos < 180) encoderPos=encoderPos+5; //increment the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void loop(){
  if(oldEncPos != encoderPos) {
    Serial.println(encoderPos);
    oldEncPos = encoderPos;
    
  }
}

Hi All,

I just Wrote a Program which Writes a Byte to the Desired Digital Port.

Thanks Paul

//********************
//********************
//********************
// This Program Outputs a Byte to the "GIOJ" Port Pins: D38 (PJ7), D37 (PJ6), D35 (PJ5), D33 (PJ4), D31 (PJ3), D29 (PJ2), D27 (PJ1), D25 (PJ0) 
//********************
//********************
//********************

//Set Byte_Test to Word for "Serial.println"
word Byte_Test;

void setup() {

  Serial.begin(9600);

  Serial.println("Encoder Test --> Giga Direct Port Manipulation!!!");

//********************
//********************
//********************

//Set Desired Byte Pins to OUTPUT
  pinMode(25, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(29, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(35, OUTPUT);
  pinMode(37, OUTPUT);
  pinMode(38, OUTPUT);

}

void loop() {
 //Serial.println("Encoder Test --> Giga Direct Port Manipulation!!!"); 

//********************
//********************
//********************

//Copy 'n' Paste Code that Actually Works!!!!
//GPIOJ->ODR = (0b00000001); // Turns on: D25 (PJ0)
//GPIOJ->ODR = (0b00000010); // Turns on: D27 (PJ1)
//GPIOJ->ODR = (0b00000011); // Turns on: D27 (PJ1), D25 (PJ0)
//GPIOJ->ODR = (0b00000100); // Turns on: D29 (PJ2)
//GPIOJ->ODR = (0b00000101); // Turns on: D29 (PJ2), D25 (PJ0)
//GPIOJ->ODR = (0b00000110); // Turns on: D29 (PJ2), D27 (PJ1)
//GPIOJ->ODR = (0b00000111); // Turns on: D29 (PJ2), D27 (PJ1), D25 (PJ0) 
//GPIOJ->ODR = (0b00001000); // Turns on: D31 (PJ3)
//GPIOJ->ODR = (0b00001001); // Turns on: D31 (PJ3), D25 (PJ0)
//GPIOJ->ODR = (0b00001010); // Turns on: D31 (PJ3), D27 (PJ1)
//GPIOJ->ODR = (0b00001011); // Turns on: D31 (PJ3), D27 (PJ1), D25 (PJ0)
//GPIOJ->ODR = (0b00001100); // Turns on: D31 (PJ3), D29 (PJ2)
//GPIOJ->ODR = (0b00001101); // Turns on: D31 (PJ3), D29 (PJ2), D25 (PJ0)
//GPIOJ->ODR = (0b00001110); // Turns on: D31 (PJ3), D29 (PJ2), D27 (PJ1)
//GPIOJ->ODR = (0b00001111); // Turns on: D31 (PJ3), D29 (PJ2), D27 (PJ1), D25 (PJ0)
//   *
//   *
//   *
//GPIOJ->ODR = (0b11111111); // Turns on: D38 (PJ7), D37 (PJ6), D35 (PJ5), D33 (PJ4), D31 (PJ3), D29 (PJ2), D27 (PJ1), D25 (PJ0)

//********************
//********************
//********************

//Set GIPO "J" Port to Desired Byte
//This Turns On / Off Desired Digital Ports
GPIOJ->ODR = (0b00000111); // Turns on: D29 (PJ2), D27 (PJ1), D25 (PJ0) 

//Set "Byte_Test" to Desired Byte
Byte_Test =  (GPIOJ->ODR);

//Prints "Byte_Test" to "Serial Monitor" in HEX      
Serial.println( Byte_Test, HEX );

}