sc7-testo-firmware/src/userio.c

124 lines
3.1 KiB
C
Raw Normal View History

/*
* userio.c: reacting when you fiddle with buttons, switches, and knobs
*
* mode switch: modes are changed only when the button is not being
* pushed, as button being pushed negates the mode switch response.
* for the mode to change, the mode switch must be in the new position
* without wavering for at least 3 rounds. this will prevent the
* mode from changing by someone fucking around with the button or
* when the button is used normally.
*
* button: is connected to mode switch ADC. if below threshold, then
* we can be certain button is pushed. we still wait a debounce
* round to ensure button is pushed. our code can fire events on
* either button being held or button being released. the actual
* push event does not do anything with this code.
*
* settings knobs: these are used by the settings module which works
* with the other modules and the button for setting user settings.
* the values are scaled from the ADC value, with bounds being set
* on the low and high ends and further scaled for usability.
* please read the manual if you want to know what settings do.
*
* file creation: 20231015 0122
*/
#include <stdint.h>
#include <stdlib.h>
#include "adc.h"
#include "testo.h"
#define MODE_CONT 0
#define MODE_CONT_TARGET 3072 // (4096 * (1 - (1 / 4)))
#define MODE_FUN 1
#define MODE_FUN_TARGET 2731 // (4096 * (1 - (1 / 3)))
#define MODE_DIODE 2
#define MODE_DIODE_TARGET 2048 // (4096 * 1 - ((1 / 2)))
#define MODE_SET_LIMIT 60 // 3x worst case expected (1% tol)
#define MODE_CHANGE_TICKS 4 // how many samples before switching modes
#define MODE_ANALOG_MIN 20
uint8_t mode;
uint8_t mode_next;
uint8_t mode_count;
static const int16_t mode_targets[] = {
MODE_CONT_TARGET, MODE_FUN_TARGET, MODE_DIODE_TARGET
};
uint8_t knob[2];
uint8_t btn = 0;
uint16_t btn_held = 0;
void userio_update()
{
}
void userio_parse()
{
uint8_t i;
volatile int16_t m, w;
// button
// debounce is handled by the fact that we've had to have averaged
// about 16ms of measured hold time below the zero threshold.
m = adc_avg[ADC_SET_MODE];
if (m < MODE_ANALOG_MIN) {
// button is pushed
btn = 1;
if (btn_held != 0xffff) btn_held++;
} else if (btn == 1) {
// button is released
btn = 0;
}
// mode
if (!btn) {
for (i = 0; i < 4; i++) {
// clear mode_count if we aren't actively changing modes
if (i == 3) {
mode_count = 0;
break;
}
// normalize mode selection
w = abs(m - mode_targets[i]);
// determine if we mode switch
if (w < MODE_SET_LIMIT) {
// currently in this mode? if so, ignore it
if (mode == i) continue;
// is the next mode set to this item?
if (mode_next == i) {
// increment the verification count
mode_count++;
if (mode_count >= MODE_CHANGE_TICKS) {
// we've got enough data to do a change of mode
mode = i;
mode_count = 0;
}
} else {
// set the next mode to the newly selected mode
mode_next = i;
mode_count = 0;
}
break;
}
}
}
}