Test for PinDetect library. Use constant "#define DIRECTINT" to compile two different versions of the program comparing the status registers related to the interrupt states when using the PinDetect Libraries vs the InterruptIn library.
Dependencies: C12832_lcd PinDetect mbed
Fork of Bootcamp-Pushbutton_Debounce_Interrupt by
main.cpp@2:aca93337a0e1, 2014-02-17 (annotated)
- Committer:
- nleoni
- Date:
- Mon Feb 17 06:35:57 2014 +0000
- Revision:
- 2:aca93337a0e1
- Parent:
- 1:d5bb7a2e46c2
Test for PinDetect Library; use "#define DIRECTINT" constant to compile two versions which show how the library works vs the actual InterruptIn library.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
4180_1 | 0:cc87c48aa43c | 1 | #include "mbed.h" |
4180_1 | 0:cc87c48aa43c | 2 | #include "PinDetect.h" |
nleoni | 2:aca93337a0e1 | 3 | #include "C12832_lcd.h" |
nleoni | 2:aca93337a0e1 | 4 | |
nleoni | 2:aca93337a0e1 | 5 | //Napoleon Leoni |
nleoni | 2:aca93337a0e1 | 6 | //***************************************************************************// |
nleoni | 2:aca93337a0e1 | 7 | //Test program for debounce on interrupt. Here I test the PinDetect Library // |
nleoni | 2:aca93337a0e1 | 8 | //To check whether indeed the library is attaching the debounced pin to an // |
nleoni | 2:aca93337a0e1 | 9 | //interrupt. The conclusion as shown below is that it is NOT!, the PinDetect // |
nleoni | 2:aca93337a0e1 | 10 | //has some nice features like key_pressed or key_pressedheld detection // |
nleoni | 2:aca93337a0e1 | 11 | //but they are all working on polling the specified debounced pin on a Timer // |
nleoni | 2:aca93337a0e1 | 12 | //interrupt, which by default is set every 20 ms. This is not the same as // |
nleoni | 2:aca93337a0e1 | 13 | //trigering an Interrupt on a leading or trailing edge of GPIO pin // |
nleoni | 2:aca93337a0e1 | 14 | // |
nleoni | 2:aca93337a0e1 | 15 | // |
nleoni | 2:aca93337a0e1 | 16 | // TESTS RUN // |
nleoni | 2:aca93337a0e1 | 17 | // I print to the LCD three important LPC1768 registers: |
nleoni | 2:aca93337a0e1 | 18 | // ISER0..Interrupt set Enable register(address 0xE000E100), for this program |
nleoni | 2:aca93337a0e1 | 19 | // the important bits are #4..Timer 3 interrupt and #21 External interrupt 3. |
nleoni | 2:aca93337a0e1 | 20 | // Note that all GPIO interrupts are attached to the External Interrupt 3 |
nleoni | 2:aca93337a0e1 | 21 | // hardware EINT3. contents of ISER0 are accesible via: *(NVIC->ISER) |
nleoni | 2:aca93337a0e1 | 22 | // |
nleoni | 2:aca93337a0e1 | 23 | // IntEnR..GPIO interrupt enable on rising, shows which pins are attached to EINT3 |
nleoni | 2:aca93337a0e1 | 24 | // on their rising edge (these are only for mbed pins mapped to LPC pins on Port 0) |
nleoni | 2:aca93337a0e1 | 25 | // its contents are available using th macro LPC_GPIOINT->IO0IntEnR |
nleoni | 2:aca93337a0e1 | 26 | // IntEnF..GPIO interrupt enable on falling, shows which pins are attached to EINT3 |
nleoni | 2:aca93337a0e1 | 27 | // on their falling edge (these are only for mbed pins mapped to LPC pins on Port 0) |
nleoni | 2:aca93337a0e1 | 28 | // its contents are available using th macro LPC_GPIOINT->IO0IntEnF |
nleoni | 2:aca93337a0e1 | 29 | // |
nleoni | 2:aca93337a0e1 | 30 | // Note the mapping below of MBED pins to the IntEnR/IntEnF bits: |
nleoni | 2:aca93337a0e1 | 31 | // IntEnR/IntEnF bit LPC GPIO MBED GPIO PIN |
nleoni | 2:aca93337a0e1 | 32 | // 0 P[0].0 p9 |
nleoni | 2:aca93337a0e1 | 33 | // 1 P[0].1 p10 |
nleoni | 2:aca93337a0e1 | 34 | // 4 P[0].4 p30 |
nleoni | 2:aca93337a0e1 | 35 | // 5 P[0].5 p29 |
nleoni | 2:aca93337a0e1 | 36 | // 6 P[0].6 p8 |
nleoni | 2:aca93337a0e1 | 37 | // 7 P[0].7 p7 |
nleoni | 2:aca93337a0e1 | 38 | // 8 P[0].8 p6 |
nleoni | 2:aca93337a0e1 | 39 | // 9 P[0].9 p5 |
nleoni | 2:aca93337a0e1 | 40 | // 10 P[0].10 p28 |
nleoni | 2:aca93337a0e1 | 41 | // 11 P[0].11 p27 |
nleoni | 2:aca93337a0e1 | 42 | // 12 P[0].12 p27 |
nleoni | 2:aca93337a0e1 | 43 | // 15 P[0].15 p13 |
nleoni | 2:aca93337a0e1 | 44 | // 16 P[0].16 p14 |
nleoni | 2:aca93337a0e1 | 45 | // 17 P[0].17 p12 |
nleoni | 2:aca93337a0e1 | 46 | // 18 P[0].18 p11 |
nleoni | 2:aca93337a0e1 | 47 | // 23 P[0].23 p15 |
nleoni | 2:aca93337a0e1 | 48 | // 24 P[0].24 p16 |
nleoni | 2:aca93337a0e1 | 49 | // 25 P[0].25 p17 |
nleoni | 2:aca93337a0e1 | 50 | // 26 P[0].26 p18 |
nleoni | 2:aca93337a0e1 | 51 | // 30 P[0].30 p19 |
nleoni | 2:aca93337a0e1 | 52 | // 31 P[0].31 p20 |
nleoni | 2:aca93337a0e1 | 53 | //*********************************************************************************** |
nleoni | 2:aca93337a0e1 | 54 | // Test description Resulting Register Values Analysis |
nleoni | 2:aca93337a0e1 | 55 | // 1 DIRECTINT not defined ISER0 0x0000 0010 No GPIO interrupts enabled nor attached |
nleoni | 2:aca93337a0e1 | 56 | // so only pinDetect(14) IO0IntEnR 0x0000 0000 only TIMER 3 Interrupt enabled so the pinDetect |
nleoni | 2:aca93337a0e1 | 57 | // is used IO0IntEnF 0x0000 0000 libary is simply polling the pin on a timer interrupt and |
nleoni | 2:aca93337a0e1 | 58 | // debouncing it. |
nleoni | 2:aca93337a0e1 | 59 | // |
nleoni | 2:aca93337a0e1 | 60 | // 2 DIRECTINT defined ISER0 0x0020 0010(when enabled) GPIO interrupt is enabled and disabled periodically |
nleoni | 2:aca93337a0e1 | 61 | // 0x0000 0010(when disabled) when disabled the joystick up/down motion does not trigger |
nleoni | 2:aca93337a0e1 | 62 | // so we define InterruptIn IO0IntEnR 0x0080 0000 LED1 as expected, however the pindetect functionality continues |
nleoni | 2:aca93337a0e1 | 63 | // on pins 12 and 15 IO0IntEnF 0x0002 0000 to work a further confirmation that the library is not working with |
nleoni | 2:aca93337a0e1 | 64 | // an interrupt on the GPIO specified pin. Note that p15 is attached to |
nleoni | 2:aca93337a0e1 | 65 | // a rising edge GPIO interrupt and p12 to a falling edge interrupt. |
nleoni | 2:aca93337a0e1 | 66 | //*********************************************************************************** |
nleoni | 2:aca93337a0e1 | 67 | |
nleoni | 2:aca93337a0e1 | 68 | #define DIRECTINT //constant to compare interrupt registers when using pindetect vs. using InterrupIn library |
4180_1 | 0:cc87c48aa43c | 69 | |
4180_1 | 0:cc87c48aa43c | 70 | DigitalOut myled(LED1); |
4180_1 | 0:cc87c48aa43c | 71 | DigitalOut myled2(LED2); |
4180_1 | 0:cc87c48aa43c | 72 | DigitalOut myled3(LED3); |
4180_1 | 0:cc87c48aa43c | 73 | DigitalOut myled4(LED4); |
nleoni | 2:aca93337a0e1 | 74 | C12832_LCD lcd; |
4180_1 | 0:cc87c48aa43c | 75 | |
nleoni | 2:aca93337a0e1 | 76 | #ifdef DIRECTINT |
nleoni | 2:aca93337a0e1 | 77 | InterruptIn down(p12); // DOWN of joystickn note that mbed p12 corresponds to lpc P0[17], should appear as 0x0002 0000 in register LPC_GPIOINT->IO0IntEnR/F |
nleoni | 2:aca93337a0e1 | 78 | InterruptIn fire(p15); // up of joystickn note that mbed p15 corresponds to lpc P0[23], should appear as 0x0080 0000 in register LPC_GPIOINT->IO0IntEnR/F |
nleoni | 2:aca93337a0e1 | 79 | #endif |
nleoni | 2:aca93337a0e1 | 80 | |
nleoni | 2:aca93337a0e1 | 81 | |
nleoni | 2:aca93337a0e1 | 82 | PinDetect pb(p14); // center of joystickn note that mbed p14 corresponds to lpc P0[16] should appear as 0x0001 0000 in register LPC_GPIOINT->IO0IntEnR/F |
nleoni | 2:aca93337a0e1 | 83 | |
nleoni | 2:aca93337a0e1 | 84 | void ISR1() { //interrupt service routine used to turn on LED 1 on rising edge of joystick up |
nleoni | 2:aca93337a0e1 | 85 | myled = 1; |
nleoni | 2:aca93337a0e1 | 86 | } |
nleoni | 2:aca93337a0e1 | 87 | |
nleoni | 2:aca93337a0e1 | 88 | void ISR2() { //interrupt service routing used to turn off LED 1 on falling |
nleoni | 2:aca93337a0e1 | 89 | myled = 0; |
nleoni | 2:aca93337a0e1 | 90 | } |
nleoni | 2:aca93337a0e1 | 91 | |
4180_1 | 0:cc87c48aa43c | 92 | // SPST Pushbutton debounced count demo using interrupts and callback |
4180_1 | 0:cc87c48aa43c | 93 | // no external PullUp resistor needed |
4180_1 | 0:cc87c48aa43c | 94 | // Pushbutton from P8 to GND. |
4180_1 | 0:cc87c48aa43c | 95 | // A pb hit generates an interrupt and activates the callback function |
4180_1 | 0:cc87c48aa43c | 96 | // after the switch is debounced |
4180_1 | 0:cc87c48aa43c | 97 | |
4180_1 | 0:cc87c48aa43c | 98 | // Global count variable |
4180_1 | 0:cc87c48aa43c | 99 | int volatile count=0; |
4180_1 | 0:cc87c48aa43c | 100 | |
4180_1 | 0:cc87c48aa43c | 101 | // Callback routine is interrupt activated by a debounced pb hit |
4180_1 | 0:cc87c48aa43c | 102 | void pb_hit_callback (void) { |
4180_1 | 0:cc87c48aa43c | 103 | count++; |
4180_1 | 0:cc87c48aa43c | 104 | myled4 = count & 0x01; |
4180_1 | 0:cc87c48aa43c | 105 | myled3 = (count & 0x02)>>1; |
4180_1 | 0:cc87c48aa43c | 106 | myled2 = (count & 0x04)>>2; |
4180_1 | 0:cc87c48aa43c | 107 | } |
4180_1 | 0:cc87c48aa43c | 108 | |
nleoni | 2:aca93337a0e1 | 109 | int main() |
nleoni | 2:aca93337a0e1 | 110 | { |
nleoni | 2:aca93337a0e1 | 111 | #ifdef DIRECTINT |
nleoni | 2:aca93337a0e1 | 112 | fire.rise(&ISR1); |
nleoni | 2:aca93337a0e1 | 113 | down.fall(&ISR2); |
nleoni | 2:aca93337a0e1 | 114 | #endif |
4180_1 | 0:cc87c48aa43c | 115 | // Use internal pullup for pushbutton |
avnisha | 1:d5bb7a2e46c2 | 116 | //pb.mode(PullUp); // don't do this for app board |
4180_1 | 0:cc87c48aa43c | 117 | // Delay for initial pullup to take effect |
4180_1 | 0:cc87c48aa43c | 118 | wait(.01); |
4180_1 | 0:cc87c48aa43c | 119 | // Setup Interrupt callback function for a pb hit |
4180_1 | 0:cc87c48aa43c | 120 | pb.attach_deasserted(&pb_hit_callback); |
4180_1 | 0:cc87c48aa43c | 121 | // Start sampling pb input using interrupts |
4180_1 | 0:cc87c48aa43c | 122 | pb.setSampleFrequency(); |
4180_1 | 0:cc87c48aa43c | 123 | |
4180_1 | 0:cc87c48aa43c | 124 | //Blink myled in main routine forever while responding to pb changes |
4180_1 | 0:cc87c48aa43c | 125 | // via interrupts that activate the callback counter function |
nleoni | 2:aca93337a0e1 | 126 | bool disableInterrupt=false; |
nleoni | 2:aca93337a0e1 | 127 | int counter=0,tdelay=10; |
4180_1 | 0:cc87c48aa43c | 128 | while (1) { |
nleoni | 2:aca93337a0e1 | 129 | wait(1); |
nleoni | 2:aca93337a0e1 | 130 | lcd.cls(); |
nleoni | 2:aca93337a0e1 | 131 | lcd.locate(0,1); |
nleoni | 2:aca93337a0e1 | 132 | lcd.printf("ISER0=%#010X",*(NVIC->ISER)); //NVIC->ISER holds the address of the ISER0 register |
nleoni | 2:aca93337a0e1 | 133 | lcd.locate(0,10); |
nleoni | 2:aca93337a0e1 | 134 | lcd.printf("IO0 INTEN R=%#010X",LPC_GPIOINT->IO0IntEnR); //This address holds GPIO interrupt attach on rise edge state. |
nleoni | 2:aca93337a0e1 | 135 | lcd.locate(0,20); |
nleoni | 2:aca93337a0e1 | 136 | lcd.printf("IO0 INTEN F=%#010X",LPC_GPIOINT->IO0IntEnF ); //This address holds GPIO interrupt attach on falling edge state |
nleoni | 2:aca93337a0e1 | 137 | |
nleoni | 2:aca93337a0e1 | 138 | #ifdef DIRECTINT |
nleoni | 2:aca93337a0e1 | 139 | //This section of coe periodically (every 10 seconds) toggles the external interrupt 3 EINT3 |
nleoni | 2:aca93337a0e1 | 140 | //state between enabled and disabled. This is the hardware interrupt used for th GPIO pins |
nleoni | 2:aca93337a0e1 | 141 | counter++; |
nleoni | 2:aca93337a0e1 | 142 | if(counter>=tdelay){ |
nleoni | 2:aca93337a0e1 | 143 | disableInterrupt=!disableInterrupt; |
nleoni | 2:aca93337a0e1 | 144 | if(disableInterrupt) NVIC_DisableIRQ(EINT3_IRQn); //disable EINT3 |
nleoni | 2:aca93337a0e1 | 145 | if(!disableInterrupt) NVIC_EnableIRQ(EINT3_IRQn); //re-enable EINT3 |
nleoni | 2:aca93337a0e1 | 146 | counter=0; |
nleoni | 2:aca93337a0e1 | 147 | } |
nleoni | 2:aca93337a0e1 | 148 | #endif |
4180_1 | 0:cc87c48aa43c | 149 | } |
4180_1 | 0:cc87c48aa43c | 150 | |
4180_1 | 0:cc87c48aa43c | 151 | } |