#ifndef __Buttons
#define __Buttons

#include <stdint.h>
#include <avr/io.h>


// Some code borrowed from Peter Dannegger:
// http://www.avrfreaks.net/forum/advanced-button-scan-routine
//
// While his version is optimized well, I found it hard to follow the logic
// enough to customize it for my needs, so I went with a less optimized version.
// It's good enough for this purpose.

// Last reported state
#define BSFLastReported _BV(1)

// Event flags, cleared when polled
#define BSFPressed _BV(2)
#define BSFRepeated _BV(3)
#define BSFReleased _BV(4)

// If not set repeats are disabled while the button is pressed
#define BSFRepeatEnabled _BV(5)


typedef struct
{
  // Bitmask according to BSF defines above
  uint8_t flags;

  // How many ticks the last state has been stable for
  uint8_t debounceTicks;

  // How many ticks remaining for the next repeat event
  uint8_t repeatTicks;
} ButtonState;


extern ButtonState buttonUp;
extern ButtonState buttonDown;
extern ButtonState buttonOption;



// 8MHz
#define XTAL 8e6

#ifndef BUTTON_UP
#define BUTTON_UP PB1
#endif

#ifndef BUTTON_DOWN
#define BUTTON_DOWN PB3
#endif

#ifndef BUTTON_OPTION
#define BUTTON_OPTION PB4
#endif

#define BUTTON_ALL (_BV(BUTTON_UP) | _BV(BUTTON_DOWN) | _BV(BUTTON_OPTION))


// after 20ms (if the timer runs every 10ms, 20ms is the minimum)
#define DEBOUNCE_TIME 2

// after 500ms
#define REPEAT_START 50

// every 200ms
#define REPEAT_NEXT 20

extern void buttons_init();
extern void buttons_reset();

// Returns true if sleep should be prevented
extern uint8_t buttons_active();


// Note: these functions act on events, not on the current state.
// Calling them will reset the corresponding event and further calls
// will return false until the event triggers again.

extern uint8_t button_is_pressed(ButtonState* state);
extern uint8_t button_is_released(ButtonState* state);
extern uint8_t button_is_repeated(ButtonState* state);

extern uint8_t button_is_pressed_or_repeated(ButtonState* state);

extern uint8_t button_is_pressed_short(ButtonState* state);
extern uint8_t button_is_pressed_long(ButtonState* state);

#endif