/* * 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 #include #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; } } } }