Last active
March 12, 2024 19:21
-
-
Save partlyhuman/84b3c332570cb6bc810407a901f57f60 to your computer and use it in GitHub Desktop.
Power/media button for arcade cabinet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Connect a rotary encoder to pins 2, 3, 4 | |
// Made for a MAME cabinet to act as a volume controller | |
// Adds additional functions when encoder button depressed | |
// | |
// Arduino libraries required: | |
// EncoderTool https://www.arduino.cc/reference/en/libraries/encodertool/ | |
// HID-Project https://www.arduino.cc/reference/en/libraries/hid-project/ | |
// | |
#include <HID-Project.h> | |
#include <EncoderTool.h> | |
#define DEBUG | |
using namespace EncoderTool; | |
PolledEncoder encoder; | |
volatile bool button_down = false; | |
volatile unsigned long up_time = 0; | |
volatile unsigned long down_time = 0; | |
volatile int presses = 0; | |
const unsigned long POWER_OFF_HOLD_MS = 2000; | |
const unsigned long DOUBLE_PRESS_CANCEL_MS = 250; | |
void onEncoder(int position, int delta) { | |
Consumer.write(delta > 0 ? MEDIA_VOLUME_UP : MEDIA_VOLUME_DOWN); | |
} | |
void onButtonChanged(signed char state) { | |
button_down = state == LOW; | |
if (button_down) { | |
down_time = millis(); | |
} else { | |
up_time = millis(); | |
presses++; | |
} | |
} | |
void onButtonSequence(int num) { | |
#ifdef DEBUG | |
Serial.print("Acting on multi tap "); | |
Serial.print(num); | |
Serial.println(); | |
#endif | |
switch (num) { | |
case 2: | |
Keyboard.press(KEY_ESC); | |
Keyboard.releaseAll(); | |
break; | |
case 3: | |
Keyboard.press(KEY_LEFT_ALT); | |
Keyboard.press(KEY_F4); | |
Keyboard.releaseAll(); | |
break; | |
} | |
} | |
void onButtonHold() { | |
#ifdef DEBUG | |
Serial.println("LONG PRESS!"); | |
#endif | |
// Don't interpret this as a click in any way | |
button_down = false; | |
presses = -1; | |
System.write(SYSTEM_POWER_DOWN); | |
// Keyboard.press(CONSUMER_POWER); | |
// Keyboard.releaseAll(); | |
} | |
void setup() { | |
#ifdef DEBUG | |
Serial.begin(9600); | |
#endif | |
Keyboard.begin(); | |
Consumer.begin(); | |
System.begin(); | |
encoder.begin(3, 2, 4); | |
encoder.attachCallback(onEncoder); | |
encoder.attachButtonCallback(onButtonChanged); | |
} | |
void loop() { | |
encoder.tick(); | |
if (button_down && millis() > down_time + POWER_OFF_HOLD_MS) { | |
// Detect long-held button (still down) | |
onButtonHold(); | |
} | |
if (!button_down && presses > 0 && millis() > up_time + DOUBLE_PRESS_CANCEL_MS) { | |
// Send accumulated multi-clicks or if just one, cancel multi-click | |
onButtonSequence(presses); | |
presses = 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment