#include #include #include // -------------------- Joystick Setup -------------------- Joystick_ Joystick( JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 34, // total buttons (matrix + encoders + latching toggle) 0, // hat switches false, false, false, // X, Y, Z axes false, false, false, // Rx, Ry, Rz false, false, // rudder, throttle false, false, false // accelerator, brake, steering ); // -------------------- Button Matrix -------------------- const byte ROWS = 5; const byte COLS = 5; byte rowPins[ROWS] = {A3, A2, A1, A0, 15}; byte colPins[COLS] = {14, 16, 10, 9, 8}; // Keymap: assign button numbers (0–24) to matrix char keys[ROWS][COLS] = { {0, 1, 2, 3, 4}, {5, 6, 7, 8, 9}, {10, 11, 12, 13, 14}, {15, 16, 17, 18, 19}, {20, 21, 22, 23, 24} }; Keypad buttonBox = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // -------------------- Encoders -------------------- Encoder enc1(7, 6); Encoder enc2(5, 4); Encoder enc3(3, 2); Encoder enc4(0, 1); // RX=0, TX=1 long lastPos[4] = {0, 0, 0, 0}; // Map encoders to joystick buttons int encBtnA[4] = {25, 27, 29, 31}; int encBtnB[4] = {26, 28, 30, 32}; // -------------------- Latching Toggle -------------------- const int latchingButtonNumber = 5; // matrix key number of the latching toggle // -------------------- Setup -------------------- void setup() { Joystick.begin(); for (int i = 0; i < 34; i++) { Joystick.setButton(i, 0); } } // -------------------- Pulse Helper -------------------- void pulseButton(int btn) { Joystick.setButton(btn, 1); Joystick.sendState(); delay(15); // long enough for USB HID to catch Joystick.setButton(btn, 0); Joystick.sendState(); } // -------------------- Loop -------------------- void loop() { // --- Scan Button Matrix --- if (buttonBox.getKeys()) { for (int i = 0; i < LIST_MAX; i++) { if (buttonBox.key[i].stateChanged) { int btn = buttonBox.key[i].kchar; // Special handling for the latching toggle if (btn == latchingButtonNumber) { // Any change = one pulse pulseButton(5); } else { // Normal momentary buttons if (buttonBox.key[i].kstate == PRESSED) { Joystick.setButton(btn, 1); } else if (buttonBox.key[i].kstate == RELEASED) { Joystick.setButton(btn, 0); } } } } } // --- Handle Encoders --- long newPos; newPos = enc1.read(); if (newPos != lastPos[0]) { if (newPos > lastPos[0]) pulseButton(encBtnA[0]); else pulseButton(encBtnB[0]); lastPos[0] = newPos; } newPos = enc2.read(); if (newPos != lastPos[1]) { if (newPos > lastPos[1]) pulseButton(encBtnA[1]); else pulseButton(encBtnB[1]); lastPos[1] = newPos; } newPos = enc3.read(); if (newPos != lastPos[2]) { if (newPos > lastPos[2]) pulseButton(encBtnA[2]); else pulseButton(encBtnB[2]); lastPos[2] = newPos; } newPos = enc4.read(); if (newPos != lastPos[3]) { if (newPos > lastPos[3]) pulseButton(encBtnA[3]); else pulseButton(encBtnB[3]); lastPos[3] = newPos; } delay(1); // keep loop fast but not too tight }