Wake on keypress - pin change interrupt

I'm building a Roku IR remote which uses a 4x3 keypad for channel number input. I've got it working, but now need to do the sleep/wake stuff. For the wakeup, I want to enable pin change interrupts on the three Column pins, which would be set up as INPUT-PULLUP. The four Row pins would be set as OUTPUT, LOW. So pressing any key during sleep will bring one of the Column pins low, which would trigger the pin change interrupt and wake up the processor. Then the keypad.h library would take over and process the keypress.

The problem is that after waking, a number of keypresses will need to be processed before sending the IR commands and going back to sleep, and I need to disable the pin change interrupt while all that is going on. It seems to me that the best place to disable the interrupt is inside the ISR so switch bounce would not produce any additional triggers. In fact, that would be the only instruction in the ISR. Then I would re-enable the interrupt just before sleeping.

Does this make sense? Then the question is whether it matters which register I change to disable the interrupt. I could disable pin change interrupts by clearing PCICR, or I could clear the mask value in the relevant PCMSKx register. Would either work? Does it make any difference which one I use?

And then is there any way to tell the IDE not to include all the register pushing and popping that it automatically adds to an ISR? I'm only going to write an immediate value to a processor register, so there should be no need for the pushing and popping.

Edit: To match the keypad library, during sleep the Row pins would be INPUT-PULLUP, and the Column pins would be OUTPUT, LOW.

Yes, you can use pin change to wake the processor and your approach sounds reasonable. wake up, disable further interrupts, do your IR thing, re-enable interrupts, sleep.

I am not aware of any way to change the compilers code for an ISR unless you want to write the entire thing in assembly?

Take a look at the avr/interrupt.h documentation for avr-libc. Arduino uses avr-libc.


Take a look at the avr/interrupt.h documentation for avr-libc. Arduino uses avr-libc.

AVR Libc Home Page

Thanks very much. It looks like a "naked" ISR would do away with all the stack activity.

Ok, I got it done. When going to sleep, I have all of the columns set as OUTPUT, LOW. The rows are INPUT_PULLUP, with pin change interrupt enable on all rows. When any key is pressed, its row goes low, which wakes the processor. The ISR for the relevant pin change interrupt port disables PCI by clearing the mask bits for the row lines, and also clears any flag bits that may be set. This prevents any switch bounce from triggering another interrupt. And it all works fine.

It turns out that the only registers pushed to the stack in the ISR are r0 and r1 plus the registers actually used. So I don't think a naked ISR is really necessary.