copied over and modified for use my CH59x soft I2C. CH32X GPIO does not have an open drain mode, so I have to implement this with RMW to the mode register. After doing this and adding missing functions needed for existing code, LED writes and EEPROM reads and writes. using the AWU for system timing so the clock speed can change. existing issues: - changing clock speed divider in soft i2c routines causes the system to crash - ADC seems to be reading, but result isn't being used
102 lines
2.7 KiB
C
102 lines
2.7 KiB
C
/*
|
|
* Created on: Jul 27, 2024
|
|
*
|
|
* generic button handler like I do on most of my projects
|
|
*/
|
|
|
|
#include <ch32x035.h>
|
|
|
|
#include "btn.h"
|
|
|
|
|
|
|
|
struct Btn btn[BTN_COUNT] = {0};
|
|
|
|
|
|
|
|
void btn_init()
|
|
{
|
|
uint8_t i;
|
|
|
|
// configure default setup
|
|
for (i = 0; i < BTN_COUNT; i++) {
|
|
btn[i]._mask = BTN_RELEASE;
|
|
}
|
|
|
|
btn[0]._pintype = BTN0_PIN | BTN_ACTIVE_LO;
|
|
btn[1]._pintype = BTN1_PIN | BTN_ACTIVE_LO;
|
|
btn[2]._pintype = BTN2_PIN | BTN_ACTIVE_LO;
|
|
|
|
// check button, and ignore if held
|
|
if (!(BTN_PORT->INDR & (1 << BTN1_PIN))) {
|
|
btn[0]._mask |= BTN_IGNORE;
|
|
}
|
|
}
|
|
|
|
void btn_poll()
|
|
{
|
|
uint8_t i;
|
|
uint8_t r;
|
|
uint8_t ignore;
|
|
|
|
uint8_t pushed;
|
|
|
|
for (i = 0; i < BTN_COUNT; i++) {
|
|
pushed = 0;
|
|
|
|
ignore = btn[i]._mask & BTN_IGNORE;
|
|
r = BTN_PORT->INDR & (1 << (btn[i]._pintype & BTN_PIN_MASK));
|
|
|
|
// active low type buttons
|
|
if (!r && (btn[i]._pintype & BTN_ACTIVE_LO)) pushed = 1;
|
|
// active high type buttons
|
|
if (r && !(btn[i]._pintype & BTN_ACTIVE_LO)) pushed = 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|