Pushbuttons

There are 4 pushbuttons labelled KEY[0] through KEY[3] on the board. KEY[0] through KEY[3] can be simultaneously read as bits 0 to 3 of a memory-mapped register. Corresponding bits in the Interrupt Mask Register and Edge Capture Register support the use of interrupts. They are active high, so when a button is pressed its value is 1, and it is 0 otherwise. The pushbuttons are debounced in hardware.

DevicePushbutton Keys
Configuration32-bit wide register (only bits 0 through 3 used)
Input/OutputInput
Address Base0xFF200050
Address Map
AddressR/WDescription
baseR/WData Register for reading values from the buttons
base+4R/WNot used
base+8R/WInterrupt Mask Register enables interrupts for each button
base+12R/WEdge Capture Register, a bit is high if corresponding button changed its value from 1 to 0. Writing here clears this register.
InitializationNone
Interrupts
TriggeredNegative edge (when any interrupt-enabled button changes its value from 1 to 0)
IRQ Line1
EnableSet bits in Interrupt Mask Register that correspond to button you want to interrupt on
AcknowledgeWrite to Edge Capture Register (which clears it)
Hardware SetupNone
Reference

Notes

Acknowledging interrupts - Interrupts are triggered when any bit in the Edge Capture Register is high. So make sure you clear it before you enable interrupts and before you exit your interrupt handler.

Assembly Example: Read in buttons into r3

.equ ADDR_PUSHBUTTONS, 0xFF200050

  movia r2,ADDR_PUSHBUTTONS
  ldwio r3,(r2)   # Read in buttons - active low 

Assembly Example: Enable Interrupts

.equ ADDR_PUSHBUTTONS, 0xFF200050
.equ IRQ_PUSHBUTTONS, 0x02

  movia r2,ADDR_PUSHBUTTONS
  movia r3,0xE
  stwio r3,8(r2)  # Enable interrupts on pushbuttons 1,2, and 3
  stwio r0,12(r2) # Clear edge capture register to prevent unexpected interrupt

  movia r2,IRQ_PUSHBUTTONS
  wrctl ctl3,r2   # Enable bit 1 - Pushbuttons use IRQ 1

  movia r2,1
  wrctl ctl0,r2   # Enable global Interrupts on Processor 

C Example: Reading the Pushbuttons

#define PUSHBUTTONS ((volatile long *) 0xFF200050)
#define RLEDs ((volatile long *) 0xFF200000)
int main()
{ 
   long PBval;

   while (1)
   {
      PBval = *PUSHBUTTONS;
      // Display the state of the buttons on red LEDs
      *RLEDs = PBval;
   }
}

C Example: Checking for Pushbutton releases

#define PB_EDGECAPTURE ((volatile long *) 0xFF20005C)
#define RLEDs ((volatile long *) 0xFF200000)
int main()
{ 
	long PBreleases;
	int i;

	*PB_EDGECAPTURE = 0; //clear out any changes so far 
	while (1)
	{
		PBreleases = *PB_EDGECAPTURE;
		// Display the state of the change register on red LEDs
		*RLEDs = PBreleases;
		if (PBreleases)
		{
			// Delay, so that we can observe the change on the LEDs
			for (i=0; i<10000000;i++);
			*PB_EDGECAPTURE = 0; //reset the changes for next round
		}
	}
}