Pin change interrupt,

It took me some time to get a sample code running to fix this, probably because it been many years since writing any C and even more years fiddling with stuff on register level, this on a SV-328.

Long story short questions:
Will the ISR() handle (restore) register values changes for example in SREG when exiting or do I have to save/restore those?
To get a working I looked for some samples on a simple pin change code but did not really find a simple sample for Orangutan.

So very long time since writing any C here is what I came up with, (working :wink: )

“Old style”

#include <pololu/orangutan.h>
#include <avr/interrupt.h>  

ISR(PCINT1_vect)
{ 
		clear();
		print("PCINT1");
		delay_ms(1000);
}  


int main()  
{  
	DDRC  = 0b01101111;	//PC4 = INT12 = Input
	PORTC = 0b00010000;	//PC4 set High
	PCICR |= _BV(PCIE1);	//Enable PCINT1
	PCMSK1 |= _BV(PCINT12);	//Trigger on change of PCINT12 (PC4)
	SREG = ( 1<<SREG_I );	//Enable interrupts

	while(1)  
	{  
		clear();
		print("Waiting");
		delay_ms(1000);
    	}  
}

“Semi Old style”

#include <pololu/orangutan.h>
#include <avr/interrupt.h>  

ISR(PCINT1_vect)
{ 
		clear();
		print("PCINT1");
		delay_ms(1000);
}  


int main()  
{  
	set_digital_input(IO_C4, PULL_UP_ENABLED);
	PCICR |= _BV(PCIE1);	//Enable PCINT1
	PCMSK1 |= _BV(PCINT12);	//Trigger on change of PCINT12 (PC4)

	sei();			//Enable interrupts

	while(1)  
	{  
		clear();
		print("Waiting");
		delay_ms(1000);
    	}  
}

Is there some other syntax (“new”) to use for example turn on PCINT1?

If I mask two pins lets say PCINT11 (PC3) & PCINT12 (PC4) is the triggering pin held somewhere to read out to see which pin caused the interrupt to the service routine, and this for the duration in ISR()?

As I said, oldtimer just getting started again :wink:


SV-328
How much current can be drawn from the IO pin’s? (single/total)
SVP-1284
How much current can be drawn from the IO pin’s? (single/total)

ted

Hello.

Just like with function calls, the compiler takes care of pushing SREG and the registers it uses onto the stack (i.e. saving them) at the beginning of an ISR and popping them off the stack (i.e. restoring them) before returning. Unless you explicitly use a special attribute, the compiler also automatically takes the extra step of clearing the global interrupt enable in SREG at the beginning of the ISR and enabling it again at the end of the ISR. If you write your own ISR in assembly, you’ll need to take care of the saving and restoring yourself.

The Pololu AVR library doesn’t have any generic code for using pin-change interrupts. It does have a PulseIn library for timing digital pulses using pin-change interrupts. Your code is ok for testing purposes, but, in general, I strongly recommend that you approach interrupts with a “get in and get out” mindset. While the ISR is running, no other interrupts will be serviced, so the best practice is typically to keep your ISRs as short and quick as possible. This also helps you avoid problems that might occur if the ISR is triggered during some crucial, time-sensitive part of your main program.

No, you need to figure out the source of the pin change yourself. One way to do this is to store the input state of your masked pins in a volatile global right before you enable the pin-change interrupt, and then compare that variable to the input state of those pins at the beginning of your ISR to see what changed. Don’t forget to update your global variable in the ISR to reflect the new state! If you don’t want to have to worry about this, you can use external interrupts or you can use pins from different ports. If you take this approach, each pin will have its own ISR, so you’ll automatically know which pin changed.

You can find information like this in the Electrical Characteristics section of the appropriate AVR datasheet (linked from the resources tab of the Orangutan product pages). The absolute maximum current per I/O pin is 40 mA, but the output voltage will drop as the current goes up, so you will probably not see a full 5 V at 40 mA. The test conditions for many of the DC characteristics listed in the datasheets involve a current of 20 or -20 mA. The total current draw per port is also capped at 100 mA or 150 mA, depending on the AVR and whether you are sourcing or sinking. Please see the datasheets for more information (let me know if you have trouble finding the information).

- Ben