Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "TrinketHidCombo.h"
- #define PIN_ENCODER_A 0
- #define PIN_ENCODER_B 2
- #define TRINKET_PINx PINB
- #define buttonPin 1
- static uint8_t enc_prev_pos = 0;
- static uint8_t enc_flags = 0;
- static char sw_was_pressed = 0;
- void setup()
- {
- // set pins as input with internal pull-up resistors enabled
- pinMode(PIN_ENCODER_A, INPUT);
- pinMode(PIN_ENCODER_B, INPUT);
- // KY040 already has pullup resistors
- /*
- digitalWrite(PIN_ENCODER_A, HIGH);
- digitalWrite(PIN_ENCODER_B, HIGH);
- */
- //*
- pinMode(buttonPin, INPUT);
- // the switch is active-high, not active-low, shares led, led acts as pull-down resistor
- // digitalWrite(PIN_ENCODER_SWITCH, LOW);
- //*/
- TrinketHidCombo.begin(); // start the USB device engine and enumerate
- // get an initial reading on the encoder pins
- if (digitalRead(PIN_ENCODER_A) == LOW) {
- enc_prev_pos |= (1 << 0);
- }
- if (digitalRead(PIN_ENCODER_B) == LOW) {
- enc_prev_pos |= (1 << 1);
- }
- }
- void loop()
- {
- int8_t enc_action = 0; // 1 or -1 if moved, sign is direction
- // note: for better performance, the code will now use
- // direct port access techniques
- // http://www.arduino.cc/en/Reference/PortManipulation
- uint8_t enc_cur_pos = 0;
- // read in the encoder state first
- if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_A)) {
- enc_cur_pos |= (1 << 0);
- }
- if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_B)) {
- enc_cur_pos |= (1 << 1);
- }
- // if any rotation at all
- if (enc_cur_pos != enc_prev_pos)
- {
- if (enc_prev_pos == 0x00)
- {
- // this is the first edge
- if (enc_cur_pos == 0x01) {
- enc_flags |= (1 << 0);
- }
- else if (enc_cur_pos == 0x02) {
- enc_flags |= (1 << 1);
- }
- }
- if (enc_cur_pos == 0x03)
- {
- // this is when the encoder is in the middle of a "step"
- enc_flags |= (1 << 4);
- }
- else if (enc_cur_pos == 0x00)
- {
- // this is the final edge
- if (enc_prev_pos == 0x02) {
- enc_flags |= (1 << 2);
- }
- else if (enc_prev_pos == 0x01) {
- enc_flags |= (1 << 3);
- }
- // check the first and last edge
- // or maybe one edge is missing, if missing then require the middle state
- // this will reject bounces and false movements
- if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4))) {
- enc_action = 1;
- }
- else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4))) {
- enc_action = 1;
- }
- else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4))) {
- enc_action = -1;
- }
- else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4))) {
- enc_action = -1;
- }
- enc_flags = 0; // reset for next time
- }
- }
- enc_prev_pos = enc_cur_pos;
- if (enc_action > 0) {
- TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
- // delay(5);
- // TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
- }
- else if (enc_action < 0) {
- TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
- // delay(5);
- // TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
- }
- int b = checkButton();
- if (b == 1) TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE); // Click Event - Pause/resume
- else if (b == 2) TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK); // DoubleClick Event - Next Track
- else if (b == 3) TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE); // Hold Event - mute/unmute
- else if (b == 4) ; // LongHold Event
- else ;
- // if (bit_is_set(TRINKET_PINx, PIN_ENCODER_SWITCH))
- /*
- if (digitalRead(PIN_ENCODER_SWITCH)) {
- if (sw_was_pressed == 0) { // Button on, but was off (press)
- TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE);
- delay(5); // debounce
- }
- sw_was_pressed = 1;
- } else {
- if (sw_was_pressed != 0) { // Button off, but was pressed (released)
- delay(5); // debounce
- }
- sw_was_pressed = 0;
- }
- */
- //else
- TrinketHidCombo.poll(); // do nothing, check if USB needs anything done
- }
- //=================================================
- // MULTI-CLICK: One Button, Multiple Events
- // Button timing variables
- int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
- int DCgap = 250; // max ms between clicks for a double click event
- int holdTime = 1000; // ms hold period: how long to wait for press+hold event
- int longHoldTime = 3000; // ms long hold period: how long to wait for press+hold event
- // Button variables
- boolean buttonVal = HIGH; // value read from button
- boolean buttonLast = HIGH; // buffered value of the button's previous state
- boolean DCwaiting = false; // whether we're waiting for a double click (down)
- boolean DConUp = false; // whether to register a double click on next release, or whether to wait and click
- boolean singleOK = true; // whether it's OK to do a single click
- long downTime = -1; // time the button was pressed down
- long upTime = -1; // time the button was released
- boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
- boolean waitForUp = false; // when held, whether to wait for the up event
- boolean holdEventPast = false; // whether or not the hold event happened already
- boolean longHoldEventPast = false;// whether or not the long hold event happened already
- int checkButton() {
- int event = 0;
- buttonVal = digitalRead(buttonPin);
- // Button pressed down
- if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
- {
- downTime = millis();
- ignoreUp = false;
- waitForUp = false;
- singleOK = true;
- holdEventPast = false;
- longHoldEventPast = false;
- if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true) DConUp = true;
- else DConUp = false;
- DCwaiting = false;
- }
- // Button released
- else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
- {
- if (not ignoreUp)
- {
- upTime = millis();
- if (DConUp == false) DCwaiting = true;
- else
- {
- event = 2;
- DConUp = false;
- DCwaiting = false;
- singleOK = false;
- }
- }
- }
- // Test for normal click event: DCgap expired
- if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
- {
- event = 1;
- DCwaiting = false;
- }
- // Test for hold
- if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
- // Trigger "normal" hold
- if (not holdEventPast)
- {
- event = 3;
- waitForUp = true;
- ignoreUp = true;
- DConUp = false;
- DCwaiting = false;
- //downTime = millis();
- holdEventPast = true;
- }
- // Trigger "long" hold
- if ((millis() - downTime) >= longHoldTime)
- {
- if (not longHoldEventPast)
- {
- event = 4;
- longHoldEventPast = true;
- }
- }
- }
- buttonLast = buttonVal;
- return event;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement