Encoder debouncing and minor cleanup

This commit is contained in:
Nicholas G
2021-11-07 22:07:32 -05:00
parent 6334b8916f
commit 1d3f150dfb
4 changed files with 38 additions and 34 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Pico-Game-Controller
Code for a keyboard or game controller using a Raspberry Pi Pico. Capable of handling 11 buttons, 10 LEDs, 1 WS2812B RGB strip, and 2 encoders. Developed with SDVX and IIDX in mind - see branches release/pocket-sdvx-pico and release/pocket-iidx for preconfigured versions.
Code for a keyboard or game controller using a Raspberry Pi Pico. Capable of handling 11 buttons, 10 LEDs, 1 WS2812B RGB strip, and 2 encoders. Developed with SDVX and IIDX in mind - see branches release/pocket-sdvx-pico and release/pocket-iidx for preconfigured versions.
Demo of this firmware running on Pocket SDVX Pico, purchasable at https://discord.gg/MmuKd73XbY
@@ -16,6 +16,7 @@ Currently working/fixed:
- sdvx/iidx spoof - Tested on EAC - checkout branches release/pocket-sdvx-pico or release/pocket-iidx
- 1000hz polling
- Reversable Encoders with debouncing
- Switch debouncing
- Switch and LED pins are now staggered for easier wiring
- Fix 0-~71% encoder rollover in gamepad mode, uint32 max val isn't divisible evenly by ppr\*4 for joystick - thanks friends
- HID LEDs now have labels, thanks CrazyRedMachine
@@ -25,7 +26,6 @@ TODO:
- refactor ws2812b into a seperate file for cleaner code & implement more RGB modes
- store configuration settings in a text file? consider implementing littlefs https://github.com/littlefs-project/littlefs https://www.raspberrypi.org/forums/viewtopic.php?t=313009 https://www.raspberrypi.org/forums/viewtopic.php?p=1894014#p1894014
- Store last mode in flash memory (probably implement into above TODO if possible) https://www.raspberrypi.org/forums/viewtopic.php?t=305570
- debounce on switches
How to Use:
Binary file not shown.
+1
View File
@@ -6,6 +6,7 @@
#define ENC_GPIO_SIZE 2 // Number of encoders
#define ENC_PPR 600 // Encoder PPR
#define ENC_DEBOUNCE true // Encoder Debouncing
#define SW_DEBOUNCE_TIME_US 4000 // Switch debounce delay in us
#define ENC_PULSE (ENC_PPR * 4) // 4 pulses per PPR
#define REACTIVE_TIMEOUT_MAX 500000 // Cycles before HID falls back to reactive
#define WS2812B_LED_SIZE 10 // Number of WS2812B LEDs
+35 -32
View File
@@ -26,11 +26,11 @@ uint32_t enc_val[ENC_GPIO_SIZE];
uint32_t prev_enc_val[ENC_GPIO_SIZE];
int cur_enc_val[ENC_GPIO_SIZE];
bool sw_val[SW_GPIO_SIZE];
bool prev_sw_val[SW_GPIO_SIZE];
uint64_t sw_timestamp[SW_GPIO_SIZE];
bool kbm_report;
bool leds_changed;
unsigned long reactive_timeout_count = REACTIVE_TIMEOUT_MAX;
void (*loop_mode)();
@@ -114,23 +114,20 @@ void update_lights() {
if (reactive_timeout_count < REACTIVE_TIMEOUT_MAX) {
reactive_timeout_count++;
}
if (leds_changed) {
for (int i = 0; i < LED_GPIO_SIZE; i++) {
if (reactive_timeout_count >= REACTIVE_TIMEOUT_MAX) {
if (sw_val[i]) {
gpio_put(LED_GPIO[i], 1);
} else {
gpio_put(LED_GPIO[i], 0);
}
for (int i = 0; i < LED_GPIO_SIZE; i++) {
if (reactive_timeout_count >= REACTIVE_TIMEOUT_MAX) {
if (!gpio_get(SW_GPIO[i])) {
gpio_put(LED_GPIO[i], 1);
} else {
if (lights_report.lights.buttons[i] == 0) {
gpio_put(LED_GPIO[i], 0);
} else {
gpio_put(LED_GPIO[i], 1);
}
gpio_put(LED_GPIO[i], 0);
}
} else {
if (lights_report.lights.buttons[i] == 0) {
gpio_put(LED_GPIO[i], 0);
} else {
gpio_put(LED_GPIO[i], 1);
}
}
leds_changed = false;
}
}
@@ -147,7 +144,13 @@ void joy_mode() {
if (tud_hid_ready()) {
uint16_t translate_buttons = 0;
for (int i = SW_GPIO_SIZE - 1; i >= 0; i--) {
translate_buttons = (translate_buttons << 1) | (sw_val[i] ? 1 : 0);
if (!gpio_get(SW_GPIO[i]) &&
time_us_64() - sw_timestamp[i] >= SW_DEBOUNCE_TIME_US) {
translate_buttons =
(translate_buttons << 1) | (!gpio_get(SW_GPIO[i]) ? 1 : 0);
} else {
translate_buttons <<= 1;
}
}
report.buttons = translate_buttons;
@@ -177,7 +180,8 @@ void key_mode() {
/*------------- Keyboard -------------*/
uint8_t nkro_report[32] = {0};
for (int i = 0; i < SW_GPIO_SIZE; i++) {
if (sw_val[i]) {
if (!gpio_get(SW_GPIO[i]) &&
time_us_64() - sw_timestamp[i] >= SW_DEBOUNCE_TIME_US) {
uint8_t bit = SW_KEYCODE[i] % 8;
uint8_t byte = (SW_KEYCODE[i] / 8) + 1;
if (SW_KEYCODE[i] >= 240 && SW_KEYCODE[i] <= 247) {
@@ -209,14 +213,16 @@ void key_mode() {
/**
* Update Input States
* Note: Switches are pull up, negate value
**/
void update_inputs() {
for (int i = 0; i < SW_GPIO_SIZE; i++) {
sw_val[i] = !gpio_get(SW_GPIO[i]); // Switches are pull up, negate value
// If switch gets pressed, record timestamp
if (prev_sw_val[i] == false && !gpio_get(SW_GPIO[i]) == true) {
sw_timestamp[i] = time_us_64();
}
prev_sw_val[i] = !gpio_get(SW_GPIO[i]);
}
// Update LEDs if input changed while in reactive mode
if (reactive_timeout_count >= REACTIVE_TIMEOUT_MAX) leds_changed = true;
}
/**
@@ -251,9 +257,7 @@ void init() {
// Setup Encoders
for (int i = 0; i < ENC_GPIO_SIZE; i++) {
enc_val[i] = 0;
prev_enc_val[i] = 0;
cur_enc_val[i] = 0;
enc_val[i], prev_enc_val[i], cur_enc_val[i] = 0;
encoders_program_init(pio, i, offset, ENC_GPIO[i], ENC_DEBOUNCE);
dma_channel_config c = dma_channel_get_default_config(i);
@@ -280,7 +284,8 @@ void init() {
// Setup Button GPIO
for (int i = 0; i < SW_GPIO_SIZE; i++) {
sw_val[i] = false;
prev_sw_val[i] = false;
sw_timestamp[i] = 0;
gpio_init(SW_GPIO[i]);
gpio_set_function(SW_GPIO[i], GPIO_FUNC_SIO);
gpio_set_dir(SW_GPIO[i], GPIO_IN);
@@ -294,16 +299,15 @@ void init() {
}
// Set listener bools
leds_changed = false;
kbm_report = false;
// Joy/KB Mode Switching
if (gpio_get(SW_GPIO[0])) {
loop_mode = &joy_mode;
joy_mode_check = true;
} else {
if (!gpio_get(SW_GPIO[0])) {
loop_mode = &key_mode;
joy_mode_check = false;
} else {
loop_mode = &joy_mode;
joy_mode_check = true;
}
}
@@ -368,6 +372,5 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
lights_report.raw[i] = buffer[i + 1];
}
reactive_timeout_count = 0;
leds_changed = true;
}
}