dc32-retro-tech-addon/firmware/retro_tech_fw/user/src/btn.c

88 lines
2.3 KiB
C
Raw Normal View History

/*
* Created on: Jul 27, 2024
*
* generic button handler like I do on most of my projects
*/
#include <ch32v00x.h>
#include "btn.h"
struct Btn btn[BTN_COUNT] = {0};
void btn_init()
{
uint8_t i;
// configure GPIO
BTN_PORT->BSHR = (BTN1_PUPD << BTN1_PIN) | (BTN2_PUPD << BTN2_PIN);
BTN_PORT->CFGLR &= ~((0xff << (BTN1_PIN*4)) | ((0xff << (BTN2_PIN*4))));
BTN_PORT->CFGLR |= (0x80 << (BTN1_PIN*4)) | (0x80 << (BTN2_PIN*4));
// configure default setup
for (i = 0; i < BTN_COUNT; i++) {
btn[i]._mask = 0;
}
btn[0]._pintype = BTN1_PIN | 0x10;
btn[1]._pintype = BTN2_PIN;
}
void btn_poll()
{
uint8_t i;
uint8_t r;
uint8_t ignore;
for (i = 0; i < BTN_COUNT; i++) {
ignore = btn[i]._mask & BTN_IGNORE;
r = BTN_PORT->INDR & (1 << (btn[i]._pintype & 0xf));
if ((!r && (btn[i]._pintype & 0x10)) || (r && !(btn[i]._pintype & 0x10))) {
// is pushed
if (btn[i]._count < BTN_DEBOUNCE) continue;
// hold counter
if (btn[i]._count < 0xffff) btn[i]._count++;
// first push?
if (!btn[i]._mask & BTN_PUSH) {
btn[i]._mask = BTN_PUSH;
if (btn[i].cb_push) {
btn[i].cb_push(i);
btn[i]._mask |= (BTN_PUSH << 4);
}
} else if (btn[i]._count >= btn[i].hold) {
// held to count limit
// if button is not repeatable, do not retrigger
if ((btn[i]._mask && BTN_HOLD) && !btn[i].repeat) continue;
btn[i]._mask |= BTN_HOLD;
// call callback only if not in ignore state
if (btn[i].cb_hold && !ignore) {
btn[i].cb_hold(i);
btn[i]._mask |= (BTN_HOLD << 4);
}
// apply repeat rate to count
btn[i]._count -= btn[i].repeat;
}
} else {
// is not pushed
if (!btn[i]._mask & BTN_RELEASE) {
btn[i]._mask = BTN_RELEASE;
btn[i]._count = 0;
// call callback only if not in ignore state
if (btn[i].cb_release && !ignore) {
btn[i].cb_release(i);
btn[i]._mask |= (BTN_RELEASE << 4);
}
}
}
}
}