#include "inputs.h" #include "hardware/gpio.h" #include "pico/time.h" static const uint8_t ROWS[3] = {2, 3, 5}; static const uint8_t COLS[4] = {6, 7, 8, 9}; static const uint8_t SWITCHES[3] = {13, 14, 12}; /* IN_SEED, IN_RUN, IN_PUSH */ #define DEBOUNCE_MS 10 /* a change must hold this long to count */ #define LOCKOUT_MS 40 /* then the input ignores further changes this long (worn switches chatter) */ /* (1,1) KICK (1,2) KICK 2 (1,3) SNARE (1,4) none; (2,1) HAT (2,2) HAT 16 (2,3) PERC (2,4) GHOST; (3,1) BASS (3,2) MEL A (3,3) MEL B (3,4) PAD */ const int8_t INPUT_KEY_TRACK[12] = { 0, 1, 2, -1, 4, 5, 6, 3, 7, 8, 9, 10 }; static uint32_t state; static uint8_t count[IN_COUNT], lockout[IN_COUNT]; static void input_pullup(uint pin){ gpio_init(pin); gpio_set_dir(pin, GPIO_IN); gpio_pull_up(pin); } void inputs_init(void){ int i; for(i = 0; i < 3; i++) input_pullup(ROWS[i]); for(i = 0; i < 4; i++){ input_pullup(COLS[i]); gpio_put(COLS[i], 0); } /* idle: Hi-Z with pull-up (E9) */ for(i = 0; i < 3; i++) input_pullup(SWITCHES[i]); } static uint32_t raw_read(void){ uint32_t raw = 0; int r, c; for(c = 0; c < 4; c++){ gpio_set_dir(COLS[c], GPIO_OUT); /* output latch is already 0: drive low */ busy_wait_us(5); /* settle */ for(r = 0; r < 3; r++) if(!gpio_get(ROWS[r])) raw |= 1u << (r * 4 + c); gpio_set_dir(COLS[c], GPIO_IN); /* back to Hi-Z, pull-up holds it high */ } for(r = 0; r < 3; r++) if(!gpio_get(SWITCHES[r])) raw |= 1u << (IN_SEED + r); return raw; } uint32_t inputs_scan(void){ uint32_t raw = raw_read(); int i; for(i = 0; i < IN_COUNT; i++){ uint32_t bit = 1u << i; if(lockout[i]){ lockout[i]--; count[i] = 0; continue; } if((raw & bit) != (state & bit)){ if(++count[i] >= DEBOUNCE_MS){ state ^= bit; count[i] = 0; lockout[i] = LOCKOUT_MS; } } else count[i] = 0; } return state; }