Skip to content

Instantly share code, notes, and snippets.

@bart9h
Last active January 16, 2018 20:55
Show Gist options
  • Save bart9h/663f8346bd3a8908037730fd88edd8ac to your computer and use it in GitHub Desktop.
Save bart9h/663f8346bd3a8908037730fd88edd8ac to your computer and use it in GitHub Desktop.
//{{{ button123.h
#ifndef button123_h_included
#define button123_h_included
/*
* Usage:
*
* Button123_State button1, button2;
*
* void start() {
* button123_init (&button1, MY_BUTTON1_PIN);
* button123_init (&button2, MY_BUTTON2_PIN);
* }
*
* void loop() {
*
* int button1_event = button123_read(&button1);
* int button2_event = button123_read(&button2);
*
* if (button1_event == 2)
* Serial.println("Got two clicks on button 1");
*
* if (button2_event == -1)
* Serial.println("Got a long press on button 2");
* }
*
*/
#include <stdbool.h>
#include <stdint.h>
/* Data structure to hold a button state and configuration. */
typedef struct {
/* state */
unsigned long last_debounce_ms;
bool last_debounced_read;
int clicks;
bool long_press;
/* config */
uint8_t port;
unsigned long debounce_threshold_ms;
unsigned long long_threshold_ms;
} Button123_State;
/* button123_read() returns:
* -1 for long a press,
* 0 for no event,
* n>0 for n consecutive button clicks
*/
int button123_read (Button123_State*);
void button123_init (Button123_State*, uint8_t port);
void button123_set_debounce_threshold (Button123_State*, unsigned long);
void button123_set_long_threshold (Button123_State*, unsigned long);
#define BUTTON123_DEFAULT_DEBOUNCE_THRESHOLD_MS 50
#define BUTTON123_DEFAULT_LONG_THRESHOLD_MS 2000
#endif
//}}}
//{{{ button123.c
//#include "button123.h"
void button123_init (Button123_State* button, uint8_t port)
{
button->clicks = 0;
button->last_debounce_ms = 0;
button->last_debounced_read = false;
button->long_press = false;
button->port = port;
button->long_threshold_ms = BUTTON123_DEFAULT_LONG_THRESHOLD_MS;
button->debounce_threshold_ms = BUTTON123_DEFAULT_DEBOUNCE_THRESHOLD_MS;
}
int button123_read (Button123_State* button)
{
bool button_read = digitalRead(button->port);
unsigned long curr_ms = millis();
long dt = curr_ms - button->last_debounce_ms;
int rc = 0;
if (button_read != button->last_debounced_read) {
if (dt > button->debounce_threshold_ms) {
if (!button_read) {
if (button->long_press)
button->long_press = false;
else
++button->clicks;
}
button->last_debounce_ms = curr_ms;
button->last_debounced_read = button_read;
}
}
else if (dt > button->long_threshold_ms) {
if (button_read) {
if (button->clicks == 0) {
if (!button->long_press)
rc = -1;
button->long_press = true;
}
}
else if (button->clicks > 0) {
rc = button->clicks;
button->clicks = 0;
}
}
return rc;
}
void button123_set_debounce_threshold (Button123_State* button, unsigned long debounce_threshold_ms)
{
button->debounce_threshold_ms = debounce_threshold_ms;
}
void button123_set_long_threshold (Button123_State* button, unsigned long long_threshold_ms)
{
button->long_threshold_ms = long_threshold_ms;
}
//}}}
#define BUTTON 2
#define LED 13
Button123_State button;
int state;
bool blink (const char* s, int n)
{
return (s[(millis()/100)%n] == '1');
}
void setup()
{
button123_init(&button, BUTTON);
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT);
}
void loop()
{
int event = button123_read(&button);
if (event == -1)
state = (state == -1) ? -2 : -1;
else if (event > 0)
state = event;
digitalWrite(LED,
(state == -1) ? HIGH :
(state == -2) ? LOW :
(state == 1) ? blink("1110000000", 10) :
(state == 2) ? blink("111001110000000", 15) :
(state == 3) ? blink("11100111001110000000", 20) :
blink("10", 2));
}
// vim:fdm=marker:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment