/*
 * btn.h
 *
 *  Created on: Aug 3, 2023
 *      Author: true
 */

#ifndef CODE_INC_BTN_H_
#define CODE_INC_BTN_H_


#define BTN_MODE			0
#define BTN_PROG			1
#define BTN_SET				2

#define BTN_COUNT			3

#define BTN_PUSH			(1 << 0)
#define BTN_HELD			(1 << 1)
#define BTN_HELDRT			(1 << 2)
#define BTN_RELEASE			(1 << 3)

#define BTN_PUSH_CB			(1 << 4)
#define BTN_HELD_CB			(1 << 5)
#define BTN_HELDRT_CB		(1 << 6)
#define BTN_RELEASE_CB		(1 << 7)

#define BTN_DEBOUNCE		11			// how many button ticks to wait before registering press
#define BTN_MAX_HOLD		(512*30)	// longest reported / processed hold time (30s)
#define BTN_HOLD_SHIFT		5			// rshift value to get 1/16th sec hold time

#define BTN_HOLD_0_25S	4
#define BTN_HOLD_0_50S	8
#define BTN_HOLD_1_00S	16
#define BTN_HOLD_1_50S	24
#define BTN_HOLD_2_00S	(16 * 2)
#define BTN_HOLD_3_00S	(16 * 3)
#define BTN_HOLD_4_00S	(16 * 4)
#define BTN_HOLD_5_00S	(16 * 5)



typedef struct Btn_t {
	uint16_t state;			// current state of button (pushed, held, callback done, etc)
	uint16_t held;			// current hold counts, in button tickrate
	uint16_t hold_thresh;	// hold time trigger threshold in 1/16 second increments
	uint16_t hold_retrig;	// hold time retrigger threshold in button ticks, 0 disables
	uint16_t hold_rt_ctr;	// hold retrigger counter

	void (*push_cb)(uint8_t);
	void (*held_cb)(uint8_t);
	void (*release_cb)(uint8_t);
} Btn_t;

/*
 * as long as button is pushed, .held will be incrementing
 * when .held exceeds debounce, a BTN_PUSH event will occur and push_cb will be called
 * .held will continue to increment while being held until BTN_MAX_HOLD is reached
 * when .hold_thresh is matched, a BTN_HELD event will occur and held_cb will be called
 * at this point, .hold_rt_ctr will begin counting with each button tick
 * when .hold_rt_ctr matches .hold_retrig, held_cb will be called again, and .hold_rt_ctr will be 0'd
 * even after .held stops counting, the .hold_rt_ctr will continue to run
 * if .hold_thresh is 0, then no BTN_HELD event will occur, and thus no retriggering either
 * if .hold_retrig is 0, then BTN_HELD will occur, but retriggers will not occur
 * upon release, BTN_RELEASED event will occur and release_cb will be called
 * after finishing release callback, .state will be cleared, .held will be 0
 */



extern Btn_t btn[BTN_COUNT];


void btn_init();
void btn_tick();
void btn_callback();


#endif /* CODE_INC_BTN_H_ */
