chipKIT32 / chipKIT-core

Downloadable chipKIT core for use with Arduino 1.6 - 1.8+ IDE, PlatformIO, and UECIDE
http://chipkit.net/
Apache License 2.0
59 stars 53 forks source link

CHANGE option for attachInterrupt() is not implemented #463

Open EmbeddedMan opened 3 years ago

EmbeddedMan commented 3 years ago

chipKIT currently has no ability to trigger interrupts on CHANGE, only on RISING or FALLING (since that's all that the hardware supports). It might be possible to add support for CHANGE through software.

JacobChrist commented 3 years ago

I could be mistaken but it appears that every GPIO pin of the PIC32MX has individually selectable change notice interrupt capability. My only lack of clarity is if this is truly implemented on every GPIO pin of every processor but I suspect that it is. To use it though requires some pooling the interrupt flags in the interrupt to see which pin triggered it.

majenkotech commented 3 years ago

Older MX chips ('795 and the like) have change notification on some pins, but not all. The newer ones have it on all pins. But CN is awkward to use as there is one ISR per port, not per pin, which adds overhead in working out what pin actually caused the interrupt. And on the older chips there's no direct relationship between CN number and pin number, so that has to be looked up in a table. Not always desirable when you want interrupts to respond quickly.

JacobChrist commented 3 years ago

So I was able to turn an edge triggered interrupt into a change interrupt by adding the following function to WInterrupts.c

int  getInterruptMode(uint8_t interruptNum)
{
    return intmode[interruptNum];
}

Adding a prototype to wiring.h

int  getInterruptMode(uint8_t interruptNum);

The using the interrupt like this:

void isr0() 
{ 
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // toggle pin 1
  Serial.print("ISR0 ");
  if(getInterruptMode(digitalPinToInterrupt(24)) == FALLING)
  {
    Serial.print("FALLING EDGE");
    attachInterrupt(digitalPinToInterrupt(24), isr0, RISING);
  }
  else
  {
    Serial.print("RISING EDGE");
    attachInterrupt(digitalPinToInterrupt(24), isr0, FALLING);
  }
  Serial.println();
}

void setup() 
{ 
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(PIN_INT0, INPUT);         // Interrupt pin must be an input
  digitalWrite(1, LOW);

  Serial.begin(115200);  // Open the Serial Port
  while(!Serial);
  delay(100);  // Give the serial terminal chance to open
  // Fubraino Mini 2.0 Interrupt Pins: 0, 3, 4, 6, 24
  attachInterrupt(digitalPinToInterrupt(24), isr0, FALLING);
}

void loop() 
{
  delay(1000);
}

EDIT: Example code snip tested on a Fubarino Mini 2.0

EmbeddedMan commented 3 years ago

This would be a nice addition to the core Jacob. Would you be willing to prepare a PR?

EmbeddedMan commented 3 years ago

If not, then maybe just edit the Fubarino Wiki with this example so that others can easily follow in your footsteps?

JacobChrist commented 3 years ago

So my issue has always been setting up a clean ways to commit changes to the core from Windows. Tonight I got the IDE setup on one of my Linux servers and I'm going to take a crack at it. Ultimately it would be nice to implement the CHANGE mode in the core and hide the details from the users.

majenkotech commented 3 years ago

Theoretically you can also emulate CHANGE mode interrupts on ICx pins...