Skip to content

Instantly share code, notes, and snippets.

@MrTrick
Created November 18, 2012 14:22
Show Gist options
  • Save MrTrick/4105542 to your computer and use it in GitHub Desktop.
Save MrTrick/4105542 to your computer and use it in GitHub Desktop.
1 Button debouncing library
/*
* 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;
}
//////////////////////////////////////////////////////////////////////////
/*
* 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