Advertisement
Guest User

volumeknob.ino

a guest
Nov 22nd, 2017
434
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.30 KB | None | 0 0
  1. #include "TrinketHidCombo.h"
  2. #define PIN_ENCODER_A 0
  3. #define PIN_ENCODER_B 2
  4. #define TRINKET_PINx PINB
  5. #define buttonPin 1
  6.  
  7. static uint8_t enc_prev_pos = 0;
  8. static uint8_t enc_flags = 0;
  9. static char sw_was_pressed = 0;
  10.  
  11. void setup()
  12. {
  13.   // set pins as input with internal pull-up resistors enabled
  14.   pinMode(PIN_ENCODER_A, INPUT);
  15.   pinMode(PIN_ENCODER_B, INPUT);  
  16.   // KY040 already has pullup resistors
  17.   /*
  18.   digitalWrite(PIN_ENCODER_A, HIGH);
  19.   digitalWrite(PIN_ENCODER_B, HIGH);
  20.   */
  21.   //*
  22.   pinMode(buttonPin, INPUT);
  23.   // the switch is active-high, not active-low, shares led, led acts as pull-down resistor
  24.   // digitalWrite(PIN_ENCODER_SWITCH, LOW);
  25.   //*/
  26.   TrinketHidCombo.begin(); // start the USB device engine and enumerate
  27.   // get an initial reading on the encoder pins
  28.   if (digitalRead(PIN_ENCODER_A) == LOW) {
  29.     enc_prev_pos |= (1 << 0);
  30.   }
  31.   if (digitalRead(PIN_ENCODER_B) == LOW) {
  32.     enc_prev_pos |= (1 << 1);
  33.   }
  34. }
  35.  
  36. void loop()
  37. {
  38.   int8_t enc_action = 0; // 1 or -1 if moved, sign is direction
  39.   // note: for better performance, the code will now use
  40.   // direct port access techniques
  41.   // http://www.arduino.cc/en/Reference/PortManipulation
  42.   uint8_t enc_cur_pos = 0;
  43.   // read in the encoder state first
  44.   if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_A)) {
  45.     enc_cur_pos |= (1 << 0);
  46.   }
  47.   if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_B)) {
  48.     enc_cur_pos |= (1 << 1);
  49.   }
  50.   // if any rotation at all
  51.   if (enc_cur_pos != enc_prev_pos)
  52.   {
  53.     if (enc_prev_pos == 0x00)
  54.     {
  55.       // this is the first edge
  56.       if (enc_cur_pos == 0x01) {
  57.         enc_flags |= (1 << 0);
  58.       }
  59.       else if (enc_cur_pos == 0x02) {
  60.         enc_flags |= (1 << 1);
  61.       }
  62.     }
  63.     if (enc_cur_pos == 0x03)
  64.     {
  65.       // this is when the encoder is in the middle of a "step"
  66.       enc_flags |= (1 << 4);
  67.     }
  68.     else if (enc_cur_pos == 0x00)
  69.     {
  70.       // this is the final edge
  71.       if (enc_prev_pos == 0x02) {
  72.         enc_flags |= (1 << 2);
  73.       }
  74.       else if (enc_prev_pos == 0x01) {
  75.         enc_flags |= (1 << 3);
  76.       }
  77.       // check the first and last edge
  78.       // or maybe one edge is missing, if missing then require the middle state
  79.       // this will reject bounces and false movements
  80.       if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4))) {
  81.         enc_action = 1;
  82.       }
  83.       else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4))) {
  84.         enc_action = 1;
  85.       }
  86.       else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4))) {
  87.         enc_action = -1;
  88.       }
  89.       else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4))) {
  90.         enc_action = -1;
  91.       }
  92.       enc_flags = 0; // reset for next time
  93.     }
  94.   }
  95.   enc_prev_pos = enc_cur_pos;
  96.   if (enc_action > 0) {
  97.     TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
  98.     // delay(5);
  99.     // TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
  100.   }
  101.   else if (enc_action < 0) {
  102.     TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
  103.     // delay(5);
  104.     // TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
  105.   }
  106.  
  107.    int b = checkButton();
  108.    if (b == 1) TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE); // Click Event - Pause/resume
  109.    else if (b == 2) TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK); // DoubleClick Event - Next Track
  110.    else if (b == 3) TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE); // Hold Event - mute/unmute
  111.    else if (b == 4) ; // LongHold Event
  112.    else ;
  113.  
  114.   // if (bit_is_set(TRINKET_PINx, PIN_ENCODER_SWITCH))
  115.   /*
  116.   if (digitalRead(PIN_ENCODER_SWITCH)) {
  117.     if (sw_was_pressed == 0) { // Button on, but was off (press)
  118.       TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE);
  119.       delay(5); // debounce
  120.     }
  121.     sw_was_pressed = 1;
  122.   } else {
  123.     if (sw_was_pressed != 0) { // Button off, but was pressed (released)
  124.       delay(5); // debounce
  125.     }
  126.     sw_was_pressed = 0;
  127.   }
  128.   */
  129.   //else
  130.   TrinketHidCombo.poll(); // do nothing, check if USB needs anything done
  131. }
  132.  
  133. //=================================================
  134. //  MULTI-CLICK:  One Button, Multiple Events
  135.  
  136. // Button timing variables
  137. int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
  138. int DCgap = 250;            // max ms between clicks for a double click event
  139. int holdTime = 1000;        // ms hold period: how long to wait for press+hold event
  140. int longHoldTime = 3000;    // ms long hold period: how long to wait for press+hold event
  141.  
  142. // Button variables
  143. boolean buttonVal = HIGH;   // value read from button
  144. boolean buttonLast = HIGH;  // buffered value of the button's previous state
  145. boolean DCwaiting = false;  // whether we're waiting for a double click (down)
  146. boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
  147. boolean singleOK = true;    // whether it's OK to do a single click
  148. long downTime = -1;         // time the button was pressed down
  149. long upTime = -1;           // time the button was released
  150. boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
  151. boolean waitForUp = false;        // when held, whether to wait for the up event
  152. boolean holdEventPast = false;    // whether or not the hold event happened already
  153. boolean longHoldEventPast = false;// whether or not the long hold event happened already
  154.  
  155. int checkButton() {    
  156.    int event = 0;
  157.    buttonVal = digitalRead(buttonPin);
  158.    // Button pressed down
  159.    if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
  160.    {
  161.        downTime = millis();
  162.        ignoreUp = false;
  163.        waitForUp = false;
  164.        singleOK = true;
  165.        holdEventPast = false;
  166.        longHoldEventPast = false;
  167.        if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
  168.        else  DConUp = false;
  169.        DCwaiting = false;
  170.    }
  171.    // Button released
  172.    else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
  173.    {        
  174.        if (not ignoreUp)
  175.        {
  176.            upTime = millis();
  177.            if (DConUp == false) DCwaiting = true;
  178.            else
  179.            {
  180.                event = 2;
  181.                DConUp = false;
  182.                DCwaiting = false;
  183.                singleOK = false;
  184.            }
  185.        }
  186.    }
  187.    // Test for normal click event: DCgap expired
  188.    if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
  189.    {
  190.        event = 1;
  191.        DCwaiting = false;
  192.    }
  193.    // Test for hold
  194.    if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
  195.        // Trigger "normal" hold
  196.        if (not holdEventPast)
  197.        {
  198.            event = 3;
  199.            waitForUp = true;
  200.            ignoreUp = true;
  201.            DConUp = false;
  202.            DCwaiting = false;
  203.            //downTime = millis();
  204.            holdEventPast = true;
  205.        }
  206.        // Trigger "long" hold
  207.        if ((millis() - downTime) >= longHoldTime)
  208.        {
  209.            if (not longHoldEventPast)
  210.            {
  211.                event = 4;
  212.                longHoldEventPast = true;
  213.            }
  214.        }
  215.    }
  216.    buttonLast = buttonVal;
  217.    return event;
  218. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement