/* * btn.c * * handles buttons as well as the * DIP switches (in case action is desired by hot-switching) */ #include #include "btn.h" struct Btn btn[BTN_COUNT] = {0}; void btn_init() { uint8_t i; // this function assumes GPIO has been configured already // initialize default setup btn[0]._pintype = BTN1_PIN; btn[1]._pintype = BTN2_PIN; btn[2]._pintype = DIP1_PIN; btn[3]._pintype = DIP2_PIN; btn[4]._pintype = DIP3_PIN; for (i = 0; i < BTN_COUNT; i++) { btn[i]._mask = BTN_RELEASE; // ignore any currently pressed buttons if (!(BTN_PORT->INDR & (1 << (btn[i]._pintype & BTN_PIN_MASK)))) { btn[0]._mask |= BTN_IGNORE; } } } void btn_poll() { uint8_t i; uint8_t ignore; uint8_t pushed; for (i = 0; i < BTN_COUNT; i++) { ignore = btn[i]._mask & BTN_IGNORE; // active low type buttons pushed = BTN_PORT->INDR & (1 << (btn[i]._pintype & BTN_PIN_MASK)) ? 0 : 1; if (pushed) { // hold counter if (btn[i]._count < 0xffff) btn[i]._count++; // pushed long enough? if (btn[i]._count < BTN_DEBOUNCE) continue; // first push? if (!(btn[i]._mask & BTN_PUSH)) { btn[i]._mask = BTN_PUSH | ignore; if (btn[i].cb_push && !ignore) { 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 if (btn[i].repeat > btn[i]._count) { btn[i]._count = 0; } else btn[i]._count -= btn[i].repeat; } } else { // is not pushed if (!(btn[i]._mask & BTN_RELEASE)) { // note: release will remove ignore status 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); } } } } }