Skip to content

Instantly share code, notes, and snippets.

@nadavmatalon
Last active February 21, 2021 21:39
Show Gist options
  • Save nadavmatalon/c7e6a7d7f7243ed1ad0845fbd1b3840d to your computer and use it in GitHub Desktop.
Save nadavmatalon/c7e6a7d7f7243ed1ad0845fbd1b3840d to your computer and use it in GitHub Desktop.
AVR: GPIOR (General Purpose I/O Register)
/*
GPIOR
-----
Three general purpose I/O registers that can be used for storing any information (GPIOR0, GPIOR1 and GPIOR2)
These registers are particularly useful for storing global variables and status flags, since they are accessible
to bit-specific instructions such as SBI, CBI, SBIC, SBIS, SBRC, and SBRS.
Note that only GPIOR0 is bit-addressable
References:
https://gcc.gnu.org/onlinedocs/gcc/Global-Register-Variables.html#Global%20Reg%20Vars
http://arduino.stackexchange.com/questions/8758/arduino-interruption-on-pin-change
The following code illustrates how to tie the value of a given register to GPIOR0 so that the latter can serve
as a status flag container or a similar purpose.
In other words, this means that instead of setting up a 'flag variable' and then having to manually update it
before reading it, it is possible to just read the value of GPIOR0 which gets updated automatically by the ISR
*/
void setup() {
DDRD &= ~bit(DDD2); // pinMode(digital pin 2, INPUT)
EICRA |= bit(ISC00); // trigger INT0 on any state CHANGE
EIMSK |= bit(INT0); // enable external interrupt INT0
}
void loop() {
if (GPIOR0) { // if PIND2 is LOW...
// ...place code here...
} else if { // if PIND2 is HIGH...
// ...place code here...
}
}
ISR(INT0_vect, ISR_NAKED) { // Part I of ISR for INT0 - GPIOR0[0] will hold inverse state of PIND2
asm volatile ( // bitWrite(GPIOR0, 0, ~PIND2)
" sbic %[pin], %[bit] \n" // if !bitRead(PIND, 2), skip the next instruction
" cbi %[gpio], 0 \n" // bitClear(GPIO0, 0)
" sbis %[pin], %[bit] \n" // if bitRead(PIND, 2), skip the next instruction
" sbi %[gpio], 0 \n" // bitSet(GPIO0, 0)
" rjmp INT0_vect_part_2 \n" // move on to part 2 of the ISR for INT0 (required for compilation)
:: [pin] "I" (_SFR_IO_ADDR(PIND)), // selected register to be tied to GPIOR0 (in this case: PIND)
[bit] "I" (2), // specific bit number in above register to be tied to bit 0 of GPIOR0 (in this case: 2)
[gpio] "I" (_SFR_IO_ADDR(GPIOR0))); // selected GPIOR (in this case: GPIOR0)
}
ISR(INT0_vect_part_2) { // Part II of ISR for INT0
// ...additional ISR code here if relevant...
// (if not needed, may be left empty, but must not be deleted as required for compilation)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment