/* * Created on: Jul 27, 2024 * * generic button handler like I do on most of my projects */ #include #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); } } } } }