dc33-retro-tech-addon/firmware/retro_tech_fw/code/src/btn.c
true f8a987a592 soft I2C implemented, LEDs are now lighting
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
2025-07-24 06:19:24 -07:00

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);
}
}
}
}
}