Instantly share code, notes, and snippets.
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save MrTrick/4105542 to your computer and use it in GitHub Desktop.
1 Button debouncing library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* button.c | |
* | |
* Created: 18/11/2012 12:42:18 AM | |
* Author: MrTrick | |
*/ | |
/************************************************************************/ | |
/* SYSTEM INCLUDES */ | |
/************************************************************************/ | |
#include <avr/io.h> | |
#include <avr/interrupt.h> | |
/************************************************************************/ | |
/* PROJECTS INCLUDES */ | |
/************************************************************************/ | |
#include "button.h" | |
#include "gpio.h" | |
/************************************************************************/ | |
/* CONFIGURATION/INITIALISATION */ | |
/************************************************************************/ | |
////////////////////////// | |
// PIN | |
////////////////////////// | |
//PIN is D3, PCINT19 | |
#define BUTTON_PIN GPIO(D, 3, GPIO_DIR_IN, GPIO_INIT_PULLUP) | |
#define BUTTON_PIN_ACTIVE_LOW true | |
#define BUTTON_PC_VECT PCINT2_vect //for 16-23 | |
/** | |
* Configure masks and interrupts | |
*/ | |
inline void button_init_pin() { | |
PCMSK2 |= (1<<PCINT19); // Enable the PCINT19 mask | |
PCICR |= (1<<PCIE2); // Enable Pin change interrupt 2 | |
//(The associated flag is PCIFR.PCIF2) | |
} | |
////////////////////////// | |
// TIMING | |
////////////////////////// | |
//TCCR0B control values | |
#define BUTTON_TIMER_OFF ((0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(0<<CS00)) //Timer stopped | |
#define BUTTON_TIMER_ON ((0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(0<<CS01)|(1<<CS00)) //Normal operation, with 1/1024 prescaling | |
#define BUTTON_CYCLES_HOLD 60 //Approx 2 seconds | |
#define BUTTON_CYCLES_REPEAT 20 //Approx 0.7 seconds | |
/** | |
* Configure timer0 | |
*/ | |
inline void button_init_timer() { | |
//Interrupts at 8MHz / 256 / 1024 = 32ms interrupt intervals | |
// TCCR0A default, TCNT0 default (count register), OCR0x not used | |
TCCR0B = BUTTON_TIMER_OFF; // The timer is initially off | |
BIT_SET_HI(TIMSK0, TOIE0); // Enable the interrupt | |
} | |
/************************************************************************/ | |
/* VARIABLES */ | |
/************************************************************************/ | |
/** | |
* Track the number of timer overflows; every 32ms | |
*/ | |
unsigned char button_cycle = 0; | |
/** | |
* Store the last event | |
*/ | |
volatile unsigned char button_last_event = 0; | |
/************************************************************************/ | |
/* LOCAL FUNCTIONS */ | |
/************************************************************************/ | |
/** | |
* Check the pin state | |
*/ | |
inline bool button_pin_pressed() { | |
#if(BUTTON_PIN_ACTIVE_LOW) | |
return gpio_pin_is_lo(BUTTON_PIN); | |
#else | |
return gpio_pin_is_hi(BUTTON_PIN); | |
#endif; | |
} | |
/** | |
* Reset and start the timer | |
*/ | |
inline void button_timer_start() { | |
TCNT0 = 0; | |
button_cycle = 0; | |
TCCR0B = BUTTON_TIMER_ON; | |
} | |
/** | |
* Stop the timer | |
*/ | |
inline void button_timer_stop() { | |
TCCR0B = BUTTON_TIMER_OFF; | |
} | |
/** | |
* Check the timer state | |
*/ | |
inline bool button_timer_running() { | |
return !(TCCR0B == BUTTON_TIMER_OFF); | |
} | |
/** | |
* Interrupt handler - on pin change | |
*/ | |
ISR(BUTTON_PC_VECT) { | |
//On pin press, start debouncing if not already | |
if (button_pin_pressed() && !button_timer_running()) { | |
button_timer_start(); | |
} | |
} | |
/** | |
* Interrupt handler - on timer overflow (32ms) | |
*/ | |
ISR(TIMER0_OVF_vect) { | |
//Was the button released, or is it a false alarm? | |
if (!button_pin_pressed()) { | |
if (button_cycle > 0) | |
button_last_event = BUTTON_EVENT_RELEASE; | |
button_timer_stop(); | |
return; | |
} | |
// | |
switch (button_cycle++) { | |
// Was the button just pressed? | |
case 0: | |
button_last_event = BUTTON_EVENT_PRESS; | |
break; | |
// Was the button held long enough? | |
case BUTTON_CYCLES_HOLD: | |
button_last_event = BUTTON_EVENT_HOLD; | |
break; | |
// Was it held that long, and then repeated? | |
case BUTTON_CYCLES_HOLD + BUTTON_CYCLES_REPEAT: | |
button_last_event = BUTTON_EVENT_REPEAT; | |
button_cycle -= BUTTON_CYCLES_REPEAT; // Rewind so it will repeat again | |
break; | |
} | |
} | |
/************************************************************************/ | |
/* GLOBAL FUNCTIONS */ | |
/************************************************************************/ | |
/** | |
* Configure the button | |
*/ | |
void button_init() { | |
button_init_pin(); | |
button_init_timer(); | |
} | |
/** | |
* Fetch the last button event, and clear it. | |
*/ | |
unsigned char button_read_event() { | |
unsigned char event = button_last_event; | |
button_last_event = BUTTON_EVENT_NONE; | |
return event; | |
} | |
////////////////////////////////////////////////////////////////////////// |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* button.h | |
* | |
* Created: 18/11/2012 12:42:01 AM | |
* Author: MrTrick | |
*/ | |
#ifndef BUTTON_H_ | |
#define BUTTON_H_ | |
/************************************************************************/ | |
/* CONSTANTS */ | |
/************************************************************************/ | |
#define BUTTON_EVENT_NONE 0 | |
#define BUTTON_EVENT_PRESS 1<<0 | |
#define BUTTON_EVENT_HOLD 1<<1 | |
#define BUTTON_EVENT_REPEAT 1<<2 | |
#define BUTTON_EVENT_RELEASE 1<<3 | |
/************************************************************************/ | |
/* GLOBAL FUNCTIONS */ | |
/************************************************************************/ | |
/** | |
* Configure the button | |
*/ | |
void button_init(); | |
/** | |
* Fetch the last button event, and clear it. | |
*/ | |
unsigned char button_read_event(); | |
#endif /* BUTTON_H_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment