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


#include <stdint.h>

#include "hk32f030m.h"
#include "btn.h"



// static uint8_t mode = BTN_MODE_IDLE;



Btn_t btn[BTN_COUNT] = {0};



void btn_init()
{

}

static void btn_check(uint8_t idx, uint8_t state)
{
	if (!state) {	// buttons active low
		if (btn[idx].held < BTN_MAX_HOLD) {
			btn[idx].held++;
		}
	} else {
		btn[idx].held = 0;
		btn[idx].hold_rt_ctr = 0;
	}
}

void btn_tick()
{
	uint8_t i;

	// increment hold
	btn_check(BTN_MODE, GPIOA->IDR & 0x4);
	btn_check(BTN_PROG, GPIOA->IDR & 0x2);
	btn_check(BTN_SET,  GPIOA->IDR & 0x8);

	// process
	for (i = 0; i < BTN_COUNT; i++) {
		// test for hold / release, can only happen after push
		if ((btn[i].state & BTN_PUSH) || (btn[i].state & BTN_HELD)) {
			// release first
			if (btn[i].held == 0) {
				// yes, released
				btn[i].state |= BTN_RELEASE;

			// do we trigger hold?
			} else if (btn[i].hold_thresh && (btn[i].held >> BTN_HOLD_SHIFT) >= btn[i].hold_thresh) {
				// yes, held, but only set if we didn't already
				if (!(btn[i].state & BTN_HELD)) {
					btn[i].state |= BTN_HELD;
				} else if (btn[i].hold_retrig) {
					// retrigger counter
					btn[i].hold_rt_ctr++;
					if (btn[i].hold_rt_ctr == btn[i].hold_retrig) {
						// clear held callback
						btn[i].state |= BTN_HELDRT;
						btn[i].hold_rt_ctr = 0;
					}
				}
			}
		} else {
			// push
			if (btn[i].held == BTN_DEBOUNCE) {
				btn[i].state = BTN_PUSH;
			}
		}
	}
}

void btn_callback()
{
	uint8_t i;
	uint8_t s;

	for (i = 0; i < BTN_COUNT; i++) {
		s = btn[i].state;

		if ((s & BTN_PUSH) && !(s & BTN_PUSH_CB)) {
			btn[i].state |= BTN_PUSH_CB;
			if (btn[i].push_cb) {
				btn[i].push_cb(i);
			}
		}

		if ((s & BTN_HELD) && !(s & BTN_HELD_CB)) {
			btn[i].state |= BTN_HELD_CB;
			if (btn[i].held_cb) {
				btn[i].held_cb(i);
			}
		}

		if ((s & BTN_HELDRT) && !(s & BTN_HELDRT_CB)) {
			btn[i].state |= BTN_HELDRT_CB;
			if (btn[i].held_cb) {
				btn[i].held_cb(i);
			}
		}

		if ((s & BTN_RELEASE) && !(s & BTN_RELEASE_CB)) {
			btn[i].state |= BTN_RELEASE_CB;
			if (btn[i].release_cb) {
				btn[i].release_cb(i);
			}
		}
	}
}

