I've been tinkering with a third GBZ (even though my second isn't finished ) - really because I had all the parts and I wanted to test the super cheap pro-micro clones I got. In doing this I've written quite a nice little program for handling multiple input modes - accessed by long-pressing a tactile "function button" placed in the GB power input hole (credit to Macx). This button itself has multiple functions based on click, double-click and long-press via the OneButton library.
Pressing the function button once sends RETURN double clicking sends ESCAPE and long pressing steps through the control modes, gamepad, keyboard, alternate, etc.
My rational for doing this is to support both gamepad and keyboards modes - extra keyboards etc that may have one off requirements can easily be added.
Anyhow here is the code/hardware I have put together in testing, hopefully it should be fairly self explanatory.
Really I thought I'd share to see what others think and because the code at least may be of use to others.
...one idea I had was to also make the start and select buttons "OneButtons" too - so that they also have double-click, etc.
Software:
Code: Select all
#include <OneButton.h>
#include <Keyboard.h>
#include <Bounce2.h>
#include <Gamepad.h>
#define A 10
#define B 16
#define X 8
#define Y 9
#define START 14
#define SELECT 15
#define UP 20
#define DOWN 19
#define RIGHT 18
#define LEFT 21
#define R1 2
#define R2 3
#define L1 4
#define L2 5
#define FN 1
const int pins[] = { A, B, X, Y, START, SELECT, UP, DOWN, LEFT, RIGHT, L1, L2, R1, R2 };
const char keys1[] = { 'a', 'b', 'x', 'y', '1', '5', KEY_UP_ARROW, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_RIGHT_ARROW, KEY_F1, KEY_F2, KEY_F11, KEY_F12 };
const char keys2[] = { 'p', 'l', 'o', 'k', 'v', 'b', 'w', 's', 'a', 'd', 'q', 'e', KEY_F5, KEY_F11 };
enum Mode { pad = 0, keyboard, keyboard2, _END };
const int NUM_PINS = sizeof(pins) / sizeof(int);
struct Button { int number; Bounce* bounce; };
Gamepad gamepad;
Button buttons[NUM_PINS];
OneButton fnButton(FN, true);
Mode mode = pad;
void setup() {
fnButton.attachClick([]() { Keyboard.write(KEY_RETURN); });
fnButton.attachDoubleClick([]() { Keyboard.write(KEY_ESC); });
fnButton.attachLongPressStart([]() { mode = (mode < _END - 1) ? mode + 1 : pad; });
for (int i = 0; i < NUM_PINS; i++, buttons[i]) {
pinMode(pins[i], INPUT_PULLUP);
Button *e = new Button;
e->number = i;
e->bounce = new Bounce(pins[i], 10);
buttons[i] = *e;
}
}
void loop() {
fnButton.tick();
for (int i = 0; i < NUM_PINS; i++) {
buttons[i].bounce->update();
int change = !buttons[i].bounce->read();
switch (mode) {
case pad: gamepad.setButtonState(buttons[i].number, change); break;
case keyboard: if (change) Keyboard.write(keys1[i]); break;
case keyboard2: if (change) Keyboard.write(keys2[i]); break;
}
}
}