├── ArduinoCode ├── ReadMe ├── Rotary-shortcut-1-capslock.ino ├── Rotary-shortcut-1.ino ├── Rotary-shortcut-3-locks-jog.ino ├── i2cEncoderLibV2.cpp └── i2cEncoderLibV2.h ├── Circuit-diagram.jpg ├── README.md ├── STL ├── Knob.stl ├── README ├── shortcut-inner.stl └── shortcut-outer.stl ├── rotary-caps.jpg └── shortcut.jpg /ArduinoCode/ReadMe: -------------------------------------------------------------------------------- 1 | Arduino Code including two i2c Libraries ((i2cEncoderLibV2.cpp and i2cEncoderLibV2.h) 2 | that need to be placed in same directory as main code. 3 | 4 | Rotary-shortcut-1-capslock.ino adds functionality for ring to light up blue when caps lock key is on. 5 | 6 | Rotary-shortcut-3-locks-jog.ino gives an indication of caps lock, scroll lock, and num lock. 7 | Does away with game functionality as shown in the demo video, but replaces it with a "jog" function 8 | that adjusts volume up and down intermittently to keep computer awake (in case your power management is 9 | acting screwy). 10 | -------------------------------------------------------------------------------- /ArduinoCode/Rotary-shortcut-1-capslock.ino: -------------------------------------------------------------------------------- 1 | //Need to include i2cEncoderLibV2.cpp and i2cEncoderLibV2.h in same directory 2 | 3 | //Initial setup ============================================================================= 4 | 5 | #include 6 | #include "i2cEncoderLibV2.h" 7 | #include 8 | #ifdef __AVR__ 9 | #include 10 | #endif 11 | #include "HID-Project.h" 12 | 13 | #define PINRGB 4 14 | #define NUMPIXELSRGB 12 15 | 16 | int xMovements[] = {-3, -8, -14, -16, -19, -19, -16, -14, -8, -3, 3, 8, 14, 16, 19, 19, 16, 14, 8, 3, -3}; 17 | int yMovements[] = {19, 16, 14, 8, 3, -3, -8, -14, -16, -19, -19, -16, -14, -8, -3, 3, 8, 14, 16, 19, 19}; 18 | int controlMode = 0; 19 | int sensorValue; 20 | int sensorValue1; 21 | 22 | i2cEncoderLibV2 Encoder(0x00); 23 | const int IntPin = A2; // Definition of the interrupt pin on PICO 24 | 25 | Adafruit_NeoPixel pixelsRGB = Adafruit_NeoPixel(NUMPIXELSRGB, PINRGB, NEO_RGB + NEO_KHZ800); 26 | 27 | //End Initial Setup ========================================================================== 28 | 29 | void setup() { 30 | // initialize serial communication at 9600 bits per second: 31 | Serial.begin(9600); 32 | pinMode(A0, INPUT_PULLUP); //define analog pin 0 as pullup input 33 | pinMode(A1, INPUT_PULLUP); //define analog pin 1 as pullup input 34 | pinMode(IntPin, INPUT); //sets A2 as int pin for I2C encoder 35 | pixelsRGB.begin(); // This initializes the NeoPixel library as pixelsRGB object. 36 | 37 | //setup for encoder 38 | Encoder.begin(INT_DATA | WRAP_ENABLE | DIRE_LEFT | IPUP_ENABLE | RMOD_X1 | STD_ENCODER); 39 | Encoder.writeCounter((int32_t)0); /* Reset the counter value */ 40 | Encoder.writeMax((int32_t)19); /* Set the maximum threshold*/ 41 | Encoder.writeMin((int32_t) 0); /* Set the minimum threshold */ 42 | Encoder.writeStep((int32_t)1); /* Set the step to 1*/ 43 | Encoder.writeInterruptConfig(0xff); /* Enable all the interrupt */ 44 | Encoder.writeAntibouncingPeriod(20); /* Set an anti-bouncing of 200ms */ 45 | Encoder.writeDoublePushPeriod(50); /*Set a period for the double push of 500ms */ 46 | 47 | //setup keyboard and mouse input 48 | Mouse.begin(); 49 | Keyboard.begin(); 50 | } 51 | 52 | //Start Main Loop ========================================================================= 53 | 54 | void loop() { 55 | 56 | //caps lock code ========================================================================== 57 | 58 | if (BootKeyboard.getLeds() & LED_CAPS_LOCK){ 59 | Serial.println("capsLock"); 60 | for(int x = 0; x <12; x++){ 61 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,0,10)); 62 | } 63 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 64 | } 65 | 66 | //scroll lock code ======================================================================= 67 | 68 | else if (BootKeyboard.getLeds() & LED_SCROLL_LOCK){ 69 | Serial.println("capsLock"); 70 | for(int x = 0; x <12; x++){ 71 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(10,0,0)); 72 | } 73 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 74 | } 75 | 76 | //acts normally if num lock is on and other locks off =================================== 77 | 78 | else if (BootKeyboard.getLeds() & LED_NUM_LOCK) { 79 | int pixelNumber = map(Encoder.readCounterByte(), 0, 19, 0, 11); 80 | for(int x = 0; x <12; x++){ 81 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,0,0)); // Red *red/green may be reversed depending on your strip 82 | } 83 | pixelsRGB.setPixelColor(pixelNumber, pixelsRGB.Color(10,0,0)); 84 | if (pixelNumber != 11) pixelsRGB.setPixelColor(pixelNumber + 1, pixelsRGB.Color(0,10,0)); 85 | if (pixelNumber == 11) pixelsRGB.setPixelColor(0, pixelsRGB.Color(0,10,0)); 86 | if (pixelNumber != 0) pixelsRGB.setPixelColor(pixelNumber - 1, pixelsRGB.Color(0, 10, 0)); 87 | if (pixelNumber == 0) pixelsRGB.setPixelColor(11, pixelsRGB.Color(0, 10, 0)); 88 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 89 | } 90 | 91 | //lights up leds red if no num lock =============================================================== 92 | 93 | else { 94 | Serial.println("no num lock"); 95 | for(int x = 0; x <12; x++){ 96 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,10,0)); 97 | } 98 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 99 | } 100 | 101 | //end NeoPixel lighting code=================================================================== 102 | 103 | sensorValue = digitalRead(A0); 104 | sensorValue1 = digitalRead(A1); 105 | uint8_t enc_cnt; //read encoder input 106 | //Serial.print("sensorValue "); 107 | //Serial.println(sensorValue); 108 | //Serial.print("sensorValue1 "); 109 | //Serial.println(sensorValue1); 110 | //Serial.print("EncoderPUSHP "); 111 | //Serial.println(Encoder.readStatus(PUSHP)); 112 | //Serial.print("controlMode "); 113 | //Serial.println(controlMode); 114 | delay(10); 115 | if (controlMode == 0) volume(); 116 | if (controlMode == 1) game(); 117 | } 118 | 119 | void volume() { 120 | if (sensorValue == 0 && sensorValue1 == 0){ 121 | controlMode = 1; 122 | delay(250); 123 | } 124 | else if (digitalRead(IntPin) == LOW) { 125 | if (Encoder.updateStatus()) { 126 | if (Encoder.readStatus(RINC)) { 127 | Serial.print("Increment: "); 128 | Serial.println(Encoder.readCounterByte()); 129 | Consumer.write(MEDIA_VOLUME_UP); 130 | delay(1); 131 | } 132 | if (Encoder.readStatus(RDEC)) { 133 | Serial.print("Decrement: "); 134 | Serial.println(Encoder.readCounterByte()); 135 | Consumer.write(MEDIA_VOLUME_DOWN); 136 | delay(1); 137 | } 138 | if (Encoder.readStatus(PUSHR)) { 139 | Serial.println("Push button Released"); 140 | delay(1); 141 | } 142 | 143 | if (Encoder.readStatus(PUSHP)) { 144 | Serial.println("Push button Pressed"); 145 | Consumer.write(MEDIA_PLAY_PAUSE); 146 | delay(1); 147 | } 148 | } 149 | } 150 | else if (sensorValue1 == 0){ 151 | Consumer.write(MEDIA_NEXT); 152 | delay(250); 153 | 154 | } 155 | else if (sensorValue == 0){ 156 | Consumer.write(MEDIA_PREVIOUS); 157 | delay(250); 158 | } 159 | } 160 | 161 | void game() { 162 | //homing routine ===================================================== 163 | if (sensorValue == 0 && sensorValue1 == 0){ 164 | Mouse.move(60, 0); 165 | delay(250); 166 | } 167 | //end homing routine ================================================= 168 | sensorValue = digitalRead(A0); 169 | sensorValue1 = digitalRead(A1); 170 | uint8_t enc_cnt; //read encoder input 171 | if (digitalRead(IntPin) == LOW) { 172 | if (Encoder.updateStatus()) { 173 | if (Encoder.readStatus(RINC)) { 174 | Serial.print("Increment: "); 175 | Serial.println(Encoder.readCounterByte()); 176 | Mouse.move(xMovements[Encoder.readCounterByte()], yMovements[Encoder.readCounterByte()]); 177 | Serial.println(xMovements[Encoder.readCounterByte()]); 178 | Serial.println(yMovements[Encoder.readCounterByte()]); 179 | delay(1); 180 | } 181 | if (Encoder.readStatus(RDEC)) { 182 | Serial.print("Decrement: "); 183 | Serial.println(Encoder.readCounterByte()); 184 | Mouse.move(-xMovements[Encoder.readCounterByte()+1], -yMovements[Encoder.readCounterByte()+1]); 185 | Serial.println(Encoder.readCounterByte()); 186 | Serial.println(-xMovements[Encoder.readCounterByte()+1]); 187 | Serial.println(-yMovements[Encoder.readCounterByte()+1]); 188 | delay(1); 189 | } 190 | if (Encoder.readStatus(PUSHP)) { 191 | Serial.println("Push button Pressed"); 192 | if (sensorValue == 0 && sensorValue1 == 0 ){ 193 | controlMode = 0; 194 | delay(250); 195 | } 196 | else { 197 | Mouse.press(); 198 | delay(1); 199 | } 200 | } 201 | if (Encoder.readStatus(PUSHR)) { 202 | Serial.println("Push button Released"); 203 | Mouse.release(); 204 | delay(1); 205 | } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /ArduinoCode/Rotary-shortcut-1.ino: -------------------------------------------------------------------------------- 1 | //Need to include i2cEncoderLibV2.cpp and i2cEncoderLibV2.h in same directory 2 | 3 | //Initial setup ============================================================================= 4 | 5 | #include 6 | #include "i2cEncoderLibV2.h" 7 | #include 8 | #ifdef __AVR__ 9 | #include 10 | #endif 11 | #include "HID-Project.h" 12 | 13 | #define PINRGB 4 14 | #define NUMPIXELSRGB 12 15 | 16 | int xMovements[] = {-3, -8, -14, -16, -19, -19, -16, -14, -8, -3, 3, 8, 14, 16, 19, 19, 16, 14, 8, 3, -3}; 17 | int yMovements[] = {19, 16, 14, 8, 3, -3, -8, -14, -16, -19, -19, -16, -14, -8, -3, 3, 8, 14, 16, 19, 19}; 18 | int controlMode = 0; 19 | int sensorValue; 20 | int sensorValue1; 21 | 22 | i2cEncoderLibV2 Encoder(0x00); 23 | const int IntPin = A2; // Definition of the interrupt pin on PICO 24 | 25 | Adafruit_NeoPixel pixelsRGB = Adafruit_NeoPixel(NUMPIXELSRGB, PINRGB, NEO_RGB + NEO_KHZ800); 26 | 27 | //End Initial Setup ========================================================================== 28 | 29 | void setup() { 30 | // initialize serial communication at 9600 bits per second: 31 | Serial.begin(9600); 32 | pinMode(A0, INPUT_PULLUP); //define analog pin 0 as pullup input 33 | pinMode(A1, INPUT_PULLUP); //define analog pin 1 as pullup input 34 | pinMode(IntPin, INPUT); //sets A2 as int pin for I2C encoder 35 | pixelsRGB.begin(); // This initializes the NeoPixel library as pixelsRGB object. 36 | 37 | //setup for encoder 38 | Encoder.begin(INT_DATA | WRAP_ENABLE | DIRE_LEFT | IPUP_ENABLE | RMOD_X1 | STD_ENCODER); 39 | Encoder.writeCounter((int32_t)0); /* Reset the counter value */ 40 | Encoder.writeMax((int32_t)19); /* Set the maximum threshold*/ 41 | Encoder.writeMin((int32_t) 0); /* Set the minimum threshold */ 42 | Encoder.writeStep((int32_t)1); /* Set the step to 1*/ 43 | Encoder.writeInterruptConfig(0xff); /* Enable all the interrupt */ 44 | Encoder.writeAntibouncingPeriod(20); /* Set an anti-bouncing of 200ms */ 45 | Encoder.writeDoublePushPeriod(50); /*Set a period for the double push of 500ms */ 46 | 47 | //setup keyboard and mouse input 48 | Mouse.begin(); 49 | Keyboard.begin(); 50 | } 51 | 52 | //Start Main Loop ========================================================================= 53 | 54 | void loop() { 55 | 56 | //lights loop in both modes =============================================================== 57 | 58 | int pixelNumber = map(Encoder.readCounterByte(), 0, 19, 0, 11); 59 | for(int x = 0; x <12; x++){ 60 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,0,0)); // Red *red/green may be reversed depending on your strip 61 | } 62 | pixelsRGB.setPixelColor(pixelNumber, pixelsRGB.Color(10,0,0)); 63 | if (pixelNumber != 11) pixelsRGB.setPixelColor(pixelNumber + 1, pixelsRGB.Color(0,10,0)); 64 | if (pixelNumber == 11) pixelsRGB.setPixelColor(0, pixelsRGB.Color(0,10,0)); 65 | if (pixelNumber != 0) pixelsRGB.setPixelColor(pixelNumber - 1, pixelsRGB.Color(0, 10, 0)); 66 | if (pixelNumber == 0) pixelsRGB.setPixelColor(11, pixelsRGB.Color(0, 10, 0)); 67 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 68 | 69 | //end NeoPixel lighting code=================================================================== 70 | 71 | sensorValue = digitalRead(A0); 72 | sensorValue1 = digitalRead(A1); 73 | uint8_t enc_cnt; //read encoder input 74 | Serial.print("sensorValue "); 75 | Serial.println(sensorValue); 76 | Serial.print("sensorValue1 "); 77 | Serial.println(sensorValue1); 78 | Serial.print("EncoderPUSHP "); 79 | Serial.println(Encoder.readStatus(PUSHP)); 80 | Serial.print("controlMode "); 81 | Serial.println(controlMode); 82 | delay(10); 83 | if (controlMode == 0) volume(); 84 | if (controlMode == 1) game(); 85 | } 86 | 87 | void volume() { 88 | if (sensorValue == 0 && sensorValue1 == 0){ 89 | controlMode = 1; 90 | delay(250); 91 | } 92 | else if (digitalRead(IntPin) == LOW) { 93 | if (Encoder.updateStatus()) { 94 | if (Encoder.readStatus(RINC)) { 95 | Serial.print("Increment: "); 96 | Serial.println(Encoder.readCounterByte()); 97 | Consumer.write(MEDIA_VOLUME_UP); 98 | delay(1); 99 | } 100 | if (Encoder.readStatus(RDEC)) { 101 | Serial.print("Decrement: "); 102 | Serial.println(Encoder.readCounterByte()); 103 | Consumer.write(MEDIA_VOLUME_DOWN); 104 | delay(1); 105 | } 106 | if (Encoder.readStatus(PUSHR)) { 107 | Serial.println("Push button Released"); 108 | delay(1); 109 | } 110 | 111 | if (Encoder.readStatus(PUSHP)) { 112 | Serial.println("Push button Pressed"); 113 | Consumer.write(MEDIA_PLAY_PAUSE); 114 | delay(1); 115 | } 116 | } 117 | } 118 | else if (sensorValue1 == 0){ 119 | Consumer.write(MEDIA_NEXT); 120 | delay(250); 121 | 122 | } 123 | else if (sensorValue == 0){ 124 | Consumer.write(MEDIA_PREVIOUS); 125 | delay(250); 126 | } 127 | } 128 | 129 | void game() { 130 | //homing routine ===================================================== 131 | if (sensorValue == 0 && sensorValue1 == 0){ 132 | Mouse.move(60, 0); 133 | delay(250); 134 | } 135 | //end homing routine ================================================= 136 | sensorValue = digitalRead(A0); 137 | sensorValue1 = digitalRead(A1); 138 | uint8_t enc_cnt; //read encoder input 139 | if (digitalRead(IntPin) == LOW) { 140 | if (Encoder.updateStatus()) { 141 | if (Encoder.readStatus(RINC)) { 142 | Serial.print("Increment: "); 143 | Serial.println(Encoder.readCounterByte()); 144 | Mouse.move(xMovements[Encoder.readCounterByte()], yMovements[Encoder.readCounterByte()]); 145 | Serial.println(xMovements[Encoder.readCounterByte()]); 146 | Serial.println(yMovements[Encoder.readCounterByte()]); 147 | delay(1); 148 | } 149 | if (Encoder.readStatus(RDEC)) { 150 | Serial.print("Decrement: "); 151 | Serial.println(Encoder.readCounterByte()); 152 | Mouse.move(-xMovements[Encoder.readCounterByte()+1], -yMovements[Encoder.readCounterByte()+1]); 153 | Serial.println(Encoder.readCounterByte()); 154 | Serial.println(-xMovements[Encoder.readCounterByte()+1]); 155 | Serial.println(-yMovements[Encoder.readCounterByte()+1]); 156 | delay(1); 157 | } 158 | if (Encoder.readStatus(PUSHP)) { 159 | Serial.println("Push button Pressed"); 160 | if (sensorValue == 0 && sensorValue1 == 0 ){ 161 | controlMode = 0; 162 | delay(250); 163 | } 164 | else { 165 | Mouse.press(); 166 | delay(1); 167 | } 168 | } 169 | if (Encoder.readStatus(PUSHR)) { 170 | Serial.println("Push button Released"); 171 | Mouse.release(); 172 | delay(1); 173 | } 174 | } 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /ArduinoCode/Rotary-shortcut-3-locks-jog.ino: -------------------------------------------------------------------------------- 1 | //Need to include i2cEncoderLibV2.cpp and i2cEncoderLibV2.h in same directory 2 | 3 | //Initial setup ============================================================================= 4 | 5 | #include 6 | #include "i2cEncoderLibV2.h" 7 | #include 8 | #ifdef __AVR__ 9 | #include 10 | #endif 11 | #include "HID-Project.h" 12 | 13 | #define PINRGB 4 14 | #define NUMPIXELSRGB 12 15 | 16 | int xMovements[] = {-3, -8, -14, -16, -19, -19, -16, -14, -8, -3, 3, 8, 14, 16, 19, 19, 16, 14, 8, 3, -3}; 17 | int yMovements[] = {19, 16, 14, 8, 3, -3, -8, -14, -16, -19, -19, -16, -14, -8, -3, 3, 8, 14, 16, 19, 19}; 18 | int controlMode = 0; 19 | int sensorValue; 20 | int sensorValue1; 21 | int brightness = 0; 22 | int interval = 150; 23 | unsigned long jogTime = 60000; 24 | unsigned long previousMillis = 0; 25 | unsigned long previousMillis1 = 0; 26 | 27 | i2cEncoderLibV2 Encoder(0x00); 28 | const int IntPin = A2; // Definition of the interrupt pin on PICO 29 | 30 | Adafruit_NeoPixel pixelsRGB = Adafruit_NeoPixel(NUMPIXELSRGB, PINRGB, NEO_RGB + NEO_KHZ800); 31 | 32 | //End Initial Setup ========================================================================== 33 | 34 | void setup() { 35 | // initialize serial communication at 9600 bits per second: 36 | Serial.begin(9600); 37 | pinMode(A0, INPUT_PULLUP); //define analog pin 0 as pullup input 38 | pinMode(A1, INPUT_PULLUP); //define analog pin 1 as pullup input 39 | pinMode(IntPin, INPUT); //sets A2 as int pin for I2C encoder 40 | pixelsRGB.begin(); // This initializes the NeoPixel library as pixelsRGB object. 41 | 42 | //setup for encoder 43 | Encoder.begin(INT_DATA | WRAP_ENABLE | DIRE_LEFT | IPUP_ENABLE | RMOD_X1 | STD_ENCODER); 44 | Encoder.writeCounter((int32_t)0); /* Reset the counter value */ 45 | Encoder.writeMax((int32_t)19); /* Set the maximum threshold*/ 46 | Encoder.writeMin((int32_t) 0); /* Set the minimum threshold */ 47 | Encoder.writeStep((int32_t)1); /* Set the step to 1*/ 48 | Encoder.writeInterruptConfig(0xff); /* Enable all the interrupt */ 49 | Encoder.writeAntibouncingPeriod(20); /* Set an anti-bouncing of 200ms */ 50 | Encoder.writeDoublePushPeriod(50); /*Set a period for the double push of 500ms */ 51 | 52 | //setup keyboard and mouse input 53 | Mouse.begin(); 54 | Keyboard.begin(); 55 | } 56 | 57 | //Start Main Loop ========================================================================= 58 | 59 | void loop() { 60 | 61 | //caps lock code ========================================================================== 62 | 63 | if (BootKeyboard.getLeds() & LED_CAPS_LOCK){ 64 | int pixelNumber = map(Encoder.readCounterByte(), 0, 19, 0, 11); 65 | Serial.println("capsLock"); 66 | for(int x = 0; x <12; x++){ 67 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,0,10)); 68 | } 69 | pixelsRGB.setPixelColor(pixelNumber, pixelsRGB.Color(0,0,10)); 70 | if (pixelNumber != 11) pixelsRGB.setPixelColor(pixelNumber + 1, pixelsRGB.Color(0,10,0)); 71 | if (pixelNumber == 11) pixelsRGB.setPixelColor(0, pixelsRGB.Color(0,10,0)); 72 | if (pixelNumber != 0) pixelsRGB.setPixelColor(pixelNumber - 1, pixelsRGB.Color(0, 10, 0)); 73 | if (pixelNumber == 0) pixelsRGB.setPixelColor(11, pixelsRGB.Color(0, 10, 0)); 74 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 75 | } 76 | 77 | //scroll lock code ======================================================================= 78 | 79 | else if (BootKeyboard.getLeds() & LED_SCROLL_LOCK){ 80 | int pixelNumber = map(Encoder.readCounterByte(), 0, 19, 0, 11); 81 | Serial.println("Scroll Lock"); 82 | for(int x = 0; x <12; x++){ 83 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(10,0,0)); 84 | } 85 | pixelsRGB.setPixelColor(pixelNumber, pixelsRGB.Color(10,0,0)); 86 | if (pixelNumber != 11) pixelsRGB.setPixelColor(pixelNumber + 1, pixelsRGB.Color(0,10,0)); 87 | if (pixelNumber == 11) pixelsRGB.setPixelColor(0, pixelsRGB.Color(0,10,0)); 88 | if (pixelNumber != 0) pixelsRGB.setPixelColor(pixelNumber - 1, pixelsRGB.Color(0, 10, 0)); 89 | if (pixelNumber == 0) pixelsRGB.setPixelColor(11, pixelsRGB.Color(0, 10, 0)); 90 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 91 | } 92 | 93 | //acts normally if num lock is on and other locks off =================================== 94 | 95 | else if (BootKeyboard.getLeds() & LED_NUM_LOCK) { 96 | int pixelNumber = map(Encoder.readCounterByte(), 0, 19, 0, 11); 97 | for(int x = 0; x <12; x++){ 98 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,0,0)); // Red *red/green may be reversed depending on your strip 99 | } 100 | pixelsRGB.setPixelColor(pixelNumber, pixelsRGB.Color(10,0,0)); 101 | if (pixelNumber != 11) pixelsRGB.setPixelColor(pixelNumber + 1, pixelsRGB.Color(0,10,0)); 102 | if (pixelNumber == 11) pixelsRGB.setPixelColor(0, pixelsRGB.Color(0,10,0)); 103 | if (pixelNumber != 0) pixelsRGB.setPixelColor(pixelNumber - 1, pixelsRGB.Color(0, 10, 0)); 104 | if (pixelNumber == 0) pixelsRGB.setPixelColor(11, pixelsRGB.Color(0, 10, 0)); 105 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 106 | } 107 | 108 | //lights up leds red if no num lock =============================================================== 109 | 110 | else { 111 | int pixelNumber = map(Encoder.readCounterByte(), 0, 19, 0, 11); 112 | unsigned long currentMillis = millis(); 113 | if(currentMillis - previousMillis > interval){ 114 | brightness +=1; 115 | previousMillis = millis(); 116 | } 117 | if(brightness > 20){ 118 | brightness = 0; 119 | } 120 | int LEDLevel = abs(9-brightness); 121 | //Serial.println("no num lock"); 122 | for(int x = 0; x <12; x++){ 123 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,LEDLevel,0)); 124 | } 125 | pixelsRGB.setPixelColor(pixelNumber, pixelsRGB.Color(0,10,0)); 126 | if (pixelNumber != 11) pixelsRGB.setPixelColor(pixelNumber + 1, pixelsRGB.Color(0,10,0)); 127 | if (pixelNumber == 11) pixelsRGB.setPixelColor(0, pixelsRGB.Color(0,10,0)); 128 | if (pixelNumber != 0) pixelsRGB.setPixelColor(pixelNumber - 1, pixelsRGB.Color(0, 10, 0)); 129 | if (pixelNumber == 0) pixelsRGB.setPixelColor(11, pixelsRGB.Color(0, 10, 0)); 130 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 131 | delay(5); 132 | } 133 | 134 | //end NeoPixel lighting code=================================================================== 135 | 136 | sensorValue = digitalRead(A0); 137 | sensorValue1 = digitalRead(A1); 138 | if (sensorValue == 0 && sensorValue1 == 0 && controlMode == 1) controlMode = 0; 139 | else if (sensorValue == 0 && sensorValue1 == 0 && controlMode == 0) controlMode = 1; 140 | uint8_t enc_cnt; //read encoder input 141 | //Serial.print("sensorValue "); 142 | //Serial.println(sensorValue); 143 | //Serial.print("sensorValue1 "); 144 | //Serial.println(sensorValue1); 145 | //Serial.print("EncoderPUSHP "); 146 | //Serial.println(Encoder.readStatus(PUSHP)); 147 | //Serial.print("controlMode "); 148 | //Serial.println(controlMode); 149 | //delay(1); 150 | volume(); 151 | if (controlMode == 1) game(); 152 | } 153 | 154 | void volume() { 155 | if (digitalRead(IntPin) == LOW) { 156 | if (Encoder.updateStatus()) { 157 | if (Encoder.readStatus(RINC)) { 158 | Serial.print("Increment: "); 159 | Serial.println(Encoder.readCounterByte()); 160 | Consumer.write(MEDIA_VOLUME_UP); 161 | delay(1); 162 | } 163 | if (Encoder.readStatus(RDEC)) { 164 | Serial.print("Decrement: "); 165 | Serial.println(Encoder.readCounterByte()); 166 | Consumer.write(MEDIA_VOLUME_DOWN); 167 | delay(1); 168 | } 169 | if (Encoder.readStatus(PUSHR)) { 170 | Serial.println("Push button Released"); 171 | delay(1); 172 | } 173 | 174 | if (Encoder.readStatus(PUSHP)) { 175 | Serial.println("Push button Pressed"); 176 | Consumer.write(MEDIA_PLAY_PAUSE); 177 | delay(1); 178 | } 179 | } 180 | } 181 | else if (sensorValue1 == 0){ 182 | Consumer.write(MEDIA_NEXT); 183 | delay(250); 184 | 185 | } 186 | else if (sensorValue == 0){ 187 | Consumer.write(MEDIA_PREVIOUS); 188 | delay(250); 189 | } 190 | } 191 | 192 | void game() { 193 | unsigned long currentMillis = millis(); 194 | for(int x = 7; x <9; x++){ 195 | pixelsRGB.setPixelColor(x, pixelsRGB.Color(0,0,12)); 196 | } 197 | pixelsRGB.show(); // This sends the updated pixel color to the hardware. 198 | if(currentMillis - previousMillis1 > jogTime){ 199 | //works well now, could change it to toggle scroll lock on and off to make it even less interesting?? 200 | BootKeyboard.write(KEY_SCROLL_LOCK); 201 | delay(10); 202 | BootKeyboard.write(KEY_SCROLL_LOCK); 203 | previousMillis1 = millis(); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /ArduinoCode/i2cEncoderLibV2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: i2cEncoderLibV2.h 3 | // VERSION: 0.1.. 4 | // PURPOSE: Library for I2C Encoder V2 board with Arduino 5 | // LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html) 6 | // 7 | // DATASHEET: 8 | // 9 | // URL: 10 | // 11 | // AUTHOR: 12 | // Simone Caron 13 | // 14 | 15 | #include "i2cEncoderLibV2.h" 16 | #include 17 | 18 | /*********************************** Public functions *************************************/ 19 | /** Class costructor **/ 20 | i2cEncoderLibV2::i2cEncoderLibV2(uint8_t add) { 21 | _add = add; 22 | } 23 | 24 | /** Used for initialize the encoder **/ 25 | void i2cEncoderLibV2::begin(uint8_t conf) { 26 | 27 | Wire.begin(); 28 | writeEncoder(REG_GCONF, conf); 29 | _gconf = conf; 30 | } 31 | 32 | /*********************************** Read functions *************************************/ 33 | 34 | /** Return the GP1 Configuration**/ 35 | uint8_t i2cEncoderLibV2::readGP1conf(void) { 36 | return (readEncoderByte(REG_GP1CONF)); 37 | } 38 | 39 | /** Return the GP1 Configuration**/ 40 | uint8_t i2cEncoderLibV2::readGP2conf(void) { 41 | return (readEncoderByte(REG_GP2CONF)); 42 | } 43 | 44 | /** Return the GP1 Configuration**/ 45 | uint8_t i2cEncoderLibV2::readGP3conf(void) { 46 | return (readEncoderByte(REG_GP3CONF)); 47 | } 48 | 49 | /** Return the INT pin configuration**/ 50 | uint8_t i2cEncoderLibV2::readInterruptConfig(void) { 51 | return (readEncoderByte(REG_INTCONF)); 52 | } 53 | 54 | 55 | /** Return true if the status of the econder changed, otherwise return false **/ 56 | bool i2cEncoderLibV2::updateStatus(void) { 57 | _stat = readEncoderByte(REG_ESTATUS); 58 | 59 | if (_stat == 0) { 60 | _stat2 = 0; 61 | return false; 62 | } 63 | if ((_stat & INT2) != 0) { 64 | _stat2 = readEncoderByte(REG_I2STATUS); 65 | } else { 66 | _stat2 = 0; 67 | } 68 | return true; 69 | } 70 | 71 | /** Check if a particular status match, return true is match otherwise false. Before require updateStatus() **/ 72 | bool i2cEncoderLibV2::readStatus(uint8_t s) { 73 | if ((_stat & s) != 0) { 74 | return true; 75 | } 76 | return false; 77 | } 78 | 79 | /** Return the status of the encoder **/ 80 | uint8_t i2cEncoderLibV2::readStatus(void) { 81 | return _stat; 82 | } 83 | 84 | 85 | /** Check if a particular status of the Int2 match, return true is match otherwise false. Before require updateStatus() **/ 86 | bool i2cEncoderLibV2::readInt2(uint8_t s) { 87 | if ((_stat2 & s) != 0) { 88 | return true; 89 | } 90 | return false; 91 | } 92 | 93 | /** Return the Int2 status of the encoder. Before require updateStatus() **/ 94 | uint8_t i2cEncoderLibV2::readInt2(void) { 95 | return _stat2; 96 | } 97 | 98 | /** Return Fade process status **/ 99 | uint8_t i2cEncoderLibV2::readFadeStatus(void) { 100 | return readEncoderByte(REG_FSTATUS); 101 | } 102 | 103 | /** Check if a particular status of the Fade process match, return true is match otherwise false. **/ 104 | bool i2cEncoderLibV2::readFadeStatus(uint8_t s) { 105 | if ((readEncoderByte(REG_FSTATUS) & s) == 1) 106 | return true; 107 | 108 | return false; 109 | } 110 | 111 | /** Return the PWM LED R value **/ 112 | uint8_t i2cEncoderLibV2::readLEDR(void) { 113 | return ((uint8_t) readEncoderByte(REG_RLED)); 114 | } 115 | 116 | /** Return the PWM LED G value **/ 117 | uint8_t i2cEncoderLibV2::readLEDG(void) { 118 | return ((uint8_t) readEncoderByte(REG_GLED)); 119 | } 120 | 121 | /** Return the PWM LED B value **/ 122 | uint8_t i2cEncoderLibV2::readLEDB(void) { 123 | return ((uint8_t) readEncoderByte(REG_BLED)); 124 | } 125 | 126 | /** Return the 32 bit value of the encoder counter **/ 127 | float i2cEncoderLibV2::readCounterFloat(void) { 128 | return (readEncoderFloat(REG_CVALB4)); 129 | } 130 | 131 | /** Return the 32 bit value of the encoder counter **/ 132 | int32_t i2cEncoderLibV2::readCounterLong(void) { 133 | return ((int32_t) readEncoderLong(REG_CVALB4)); 134 | } 135 | 136 | /** Return the 16 bit value of the encoder counter **/ 137 | int16_t i2cEncoderLibV2::readCounterInt(void) { 138 | return ((int16_t) readEncoderInt(REG_CVALB2)); 139 | } 140 | 141 | /** Return the 8 bit value of the encoder counter **/ 142 | int8_t i2cEncoderLibV2::readCounterByte(void) { 143 | return ((int8_t) readEncoderByte(REG_CVALB1)); 144 | } 145 | 146 | /** Return the Maximum threshold of the counter **/ 147 | int32_t i2cEncoderLibV2::readMax(void) { 148 | return ((int32_t) readEncoderLong(REG_CMAXB4)); 149 | } 150 | 151 | /** Return the Minimum threshold of the counter **/ 152 | int32_t i2cEncoderLibV2::readMin(void) { 153 | return ((int32_t) readEncoderLong(REG_CMINB4)); 154 | } 155 | 156 | /** Return the Maximum threshold of the counter **/ 157 | float i2cEncoderLibV2::readMaxFloat(void) { 158 | return (readEncoderFloat(REG_CMAXB4)); 159 | } 160 | 161 | /** Return the Minimum threshold of the counter **/ 162 | float i2cEncoderLibV2::readMinFloat(void) { 163 | return (readEncoderFloat(REG_CMINB4)); 164 | 165 | } 166 | 167 | /** Return the Steps increment **/ 168 | int32_t i2cEncoderLibV2::readStep(void) { 169 | return (readEncoderInt(REG_ISTEPB4)); 170 | } 171 | 172 | /** Return the Steps increment, in float variable **/ 173 | float i2cEncoderLibV2::readStepFloat(void) { 174 | return (readEncoderFloat(REG_ISTEPB4)); 175 | 176 | } 177 | 178 | /** Read GP1 register value **/ 179 | uint8_t i2cEncoderLibV2::readGP1(void) { 180 | return (readEncoderByte(REG_GP1REG)); 181 | } 182 | 183 | /** Read GP2 register value **/ 184 | uint8_t i2cEncoderLibV2::readGP2(void) { 185 | return (readEncoderByte(REG_GP2REG)); 186 | } 187 | 188 | /** Read GP3 register value **/ 189 | uint8_t i2cEncoderLibV2::readGP3(void) { 190 | return (readEncoderByte(REG_GP3REG)); 191 | } 192 | 193 | /** Read Anti-bouncing period register **/ 194 | uint8_t i2cEncoderLibV2::readAntibouncingPeriod(void) { 195 | return (readEncoderByte(REG_ANTBOUNC)); 196 | } 197 | 198 | /** Read Double push period register **/ 199 | uint8_t i2cEncoderLibV2::readDoublePushPeriod(void) { 200 | return (readEncoderByte(REG_DPPERIOD)); 201 | } 202 | 203 | /** Read the fade period of the RGB LED**/ 204 | uint8_t i2cEncoderLibV2::readFadeRGB(void) { 205 | return (readEncoderByte(REG_FADERGB)); 206 | } 207 | 208 | /** Read the fade period of the GP LED**/ 209 | uint8_t i2cEncoderLibV2::readFadeGP(void) { 210 | return (readEncoderByte(REG_FADEGP)); 211 | } 212 | 213 | /** Read the EEPROM memory**/ 214 | uint8_t i2cEncoderLibV2::readEEPROM(uint8_t add) { 215 | if (add <= 0x7f) { 216 | if ((_gconf & EEPROM_BANK1) != 0) { 217 | _gconf = _gconf & 0xBF; 218 | writeEncoder(REG_GCONF, _gconf); 219 | } 220 | return (readEncoderByte((REG_EEPROMS + add))); 221 | } else { 222 | if ((_gconf & EEPROM_BANK1) == 0) { 223 | _gconf = _gconf | 0x40; 224 | writeEncoder(REG_GCONF, _gconf); 225 | } 226 | return (readEncoderByte(add)); 227 | } 228 | } 229 | 230 | /*********************************** Write functions *************************************/ 231 | /** Write the GP1 configuration**/ 232 | void i2cEncoderLibV2::writeGP1conf(uint8_t gp1) { 233 | writeEncoder(REG_GP1CONF, gp1); 234 | } 235 | 236 | /** Write the GP2 configuration**/ 237 | void i2cEncoderLibV2::writeGP2conf(uint8_t gp2) { 238 | writeEncoder(REG_GP2CONF, gp2); 239 | } 240 | 241 | /** Write the GP3 configuration**/ 242 | void i2cEncoderLibV2::writeGP3conf(uint8_t gp3) { 243 | writeEncoder(REG_GP3CONF, gp3); 244 | } 245 | 246 | /** Write the interrupt configuration **/ 247 | void i2cEncoderLibV2::writeInterruptConfig(uint8_t interrupt) { 248 | writeEncoder(REG_INTCONF, interrupt); 249 | } 250 | 251 | /** Write the counter value **/ 252 | void i2cEncoderLibV2::writeCounter(int32_t value) { 253 | writeEncoder(REG_CVALB4, value); 254 | } 255 | 256 | /** Write the counter value **/ 257 | void i2cEncoderLibV2::writeCounter(float value) { 258 | writeEncoder(REG_CVALB4, value); 259 | } 260 | 261 | /** Write the maximum threshold value **/ 262 | void i2cEncoderLibV2::writeMax(int32_t max) { 263 | writeEncoder(REG_CMAXB4, max); 264 | } 265 | 266 | /** Write the maximum threshold value **/ 267 | void i2cEncoderLibV2::writeMax(float max) { 268 | writeEncoder(REG_CMAXB4, max); 269 | } 270 | 271 | /** Write the minimum threshold value **/ 272 | void i2cEncoderLibV2::writeMin(int32_t min) { 273 | writeEncoder(REG_CMINB4, min); 274 | } 275 | 276 | /** Write the minimum threshold value **/ 277 | void i2cEncoderLibV2::writeMin(float min) { 278 | writeEncoder(REG_CMINB4, min); 279 | } 280 | 281 | /** Write the Step increment value **/ 282 | void i2cEncoderLibV2::writeStep(int32_t step) { 283 | writeEncoder(REG_ISTEPB4, step); 284 | } 285 | 286 | /** Write the Step increment value **/ 287 | void i2cEncoderLibV2::writeStep(float step) { 288 | writeEncoder(REG_ISTEPB4, step); 289 | } 290 | 291 | /** Write the PWM value of the RGB LED red **/ 292 | void i2cEncoderLibV2::writeLEDR(uint8_t rled) { 293 | writeEncoder(REG_RLED, rled); 294 | } 295 | 296 | /** Write the PWM value of the RGB LED green **/ 297 | void i2cEncoderLibV2::writeLEDG(uint8_t gled) { 298 | writeEncoder(REG_GLED, gled); 299 | } 300 | 301 | /** Write the PWM value of the RGB LED blue **/ 302 | void i2cEncoderLibV2::writeLEDB(uint8_t bled) { 303 | writeEncoder(REG_BLED, bled); 304 | } 305 | 306 | /** Write 24bit color code **/ 307 | void i2cEncoderLibV2::writeRGBCode(uint32_t rgb) { 308 | writeEncoder24bit(REG_RLED, rgb); 309 | } 310 | 311 | /** Write GP1 register, used when GP1 is set to output or PWM **/ 312 | void i2cEncoderLibV2::writeGP1(uint8_t gp1) { 313 | writeEncoder(REG_GP1REG, gp1); 314 | } 315 | 316 | /** Write GP2 register, used when GP2 is set to output or PWM **/ 317 | void i2cEncoderLibV2::writeGP2(uint8_t gp2) { 318 | writeEncoder(REG_GP2REG, gp2); 319 | } 320 | 321 | /** Write GP3 register, used when GP3 is set to output or PWM **/ 322 | void i2cEncoderLibV2::writeGP3(uint8_t gp3) { 323 | writeEncoder(REG_GP3REG, gp3); 324 | } 325 | 326 | /** Write Anti-bouncing period register **/ 327 | void i2cEncoderLibV2::writeAntibouncingPeriod(uint8_t bounc) { 328 | writeEncoder(REG_ANTBOUNC, bounc); 329 | } 330 | 331 | /** Write Anti-bouncing period register **/ 332 | void i2cEncoderLibV2::writeDoublePushPeriod(uint8_t dperiod) { 333 | writeEncoder(REG_DPPERIOD, dperiod); 334 | } 335 | 336 | /** Write Fade timing in ms **/ 337 | void i2cEncoderLibV2::writeFadeRGB(uint8_t fade) { 338 | writeEncoder(REG_FADERGB, fade); 339 | } 340 | 341 | /** Write Fade timing in ms **/ 342 | void i2cEncoderLibV2::writeFadeGP(uint8_t fade) { 343 | writeEncoder(REG_FADEGP, fade); 344 | } 345 | 346 | /** Write the EEPROM memory**/ 347 | void i2cEncoderLibV2::writeEEPROM(uint8_t add, uint8_t data) { 348 | if (add <= 0x7f) { 349 | if ((_gconf & EEPROM_BANK1) != 0) { 350 | _gconf = _gconf & 0xBF; 351 | writeEncoder(REG_GCONF, _gconf); 352 | } 353 | writeEncoder((REG_EEPROMS + add), data); 354 | } else { 355 | if ((_gconf & EEPROM_BANK1) == 0) { 356 | _gconf = _gconf | 0x40; 357 | writeEncoder(REG_GCONF, _gconf); 358 | } 359 | writeEncoder(add, data); 360 | } 361 | } 362 | 363 | /*********************************** Private functions *************************************/ 364 | /***************************** Read function to the encoder ********************************/ 365 | 366 | /** Read 1 byte from the encoder **/ 367 | uint8_t i2cEncoderLibV2::readEncoderByte(uint8_t reg) { 368 | byte rdata = 0xFF; 369 | 370 | Wire.beginTransmission(_add); 371 | Wire.write(reg); 372 | Wire.endTransmission(); 373 | Wire.requestFrom(_add, 1); 374 | if (Wire.available()) { 375 | rdata = Wire.read(); 376 | } 377 | // delay(5); 378 | return rdata; 379 | } 380 | 381 | /** Read 2 bytes from the encoder **/ 382 | int16_t i2cEncoderLibV2::readEncoderInt(uint8_t reg) { 383 | Wire.beginTransmission(_add); 384 | Wire.write(reg); 385 | Wire.endTransmission(); 386 | Wire.requestFrom(_add, 4); 387 | if (Wire.available()) { 388 | _tem_data.bval[1] = Wire.read(); 389 | _tem_data.bval[0] = Wire.read(); 390 | } 391 | return ((int16_t) _tem_data.val); 392 | } 393 | 394 | /** Read 4 bytes from the encoder **/ 395 | int32_t i2cEncoderLibV2::readEncoderLong(uint8_t reg) { 396 | 397 | Wire.beginTransmission(_add); 398 | Wire.write(reg); 399 | Wire.endTransmission(); 400 | Wire.requestFrom(_add, 4); 401 | if (Wire.available()) { 402 | _tem_data.bval[3] = Wire.read(); 403 | _tem_data.bval[2] = Wire.read(); 404 | _tem_data.bval[1] = Wire.read(); 405 | _tem_data.bval[0] = Wire.read(); 406 | } 407 | return ((int32_t) _tem_data.val); 408 | } 409 | 410 | /** Read 4 bytes from the encoder **/ 411 | float i2cEncoderLibV2::readEncoderFloat(uint8_t reg) { 412 | Wire.beginTransmission(_add); 413 | Wire.write(reg); 414 | Wire.endTransmission(); 415 | Wire.requestFrom(_add, 4); 416 | if (Wire.available()) { 417 | _tem_data.bval[3] = Wire.read(); 418 | _tem_data.bval[2] = Wire.read(); 419 | _tem_data.bval[1] = Wire.read(); 420 | _tem_data.bval[0] = Wire.read(); 421 | } 422 | return ((float) _tem_data.fval); 423 | } 424 | 425 | /***************************** Write function to the encoder ********************************/ 426 | /** Send to the encoder 1 byte **/ 427 | void i2cEncoderLibV2::writeEncoder(uint8_t reg, uint8_t data) { 428 | 429 | Wire.beginTransmission(_add); 430 | Wire.write(reg); 431 | Wire.write(data); 432 | Wire.endTransmission(); 433 | // delay(1); 434 | 435 | } 436 | 437 | 438 | 439 | 440 | /** Send to the encoder 4 byte **/ 441 | void i2cEncoderLibV2::writeEncoder(uint8_t reg, int32_t data) { 442 | uint8_t temp[4]; 443 | _tem_data.val = data; 444 | temp[0] = _tem_data.bval[3]; 445 | temp[1] = _tem_data.bval[2]; 446 | temp[2] = _tem_data.bval[1]; 447 | temp[3] = _tem_data.bval[0]; 448 | Wire.beginTransmission(_add); 449 | Wire.write(reg); 450 | Wire.write(temp, 4); 451 | Wire.endTransmission(); 452 | // delay(1); 453 | 454 | } 455 | 456 | /** Send to the encoder 4 byte for floating number **/ 457 | void i2cEncoderLibV2::writeEncoder(uint8_t reg, float data) { 458 | 459 | uint8_t temp[4]; 460 | _tem_data.fval = data; 461 | temp[0] = _tem_data.bval[3]; 462 | temp[1] = _tem_data.bval[2]; 463 | temp[2] = _tem_data.bval[1]; 464 | temp[3] = _tem_data.bval[0]; 465 | Wire.beginTransmission(_add); 466 | Wire.write(reg); 467 | Wire.write(temp, 4); 468 | Wire.endTransmission(); 469 | // delay(1); 470 | 471 | } 472 | 473 | 474 | /** Send to the encoder 3 byte **/ 475 | void i2cEncoderLibV2::writeEncoder24bit(uint8_t reg, uint32_t data) { 476 | uint8_t temp[3]; 477 | _tem_data.val = data; 478 | temp[0] = _tem_data.bval[2]; 479 | temp[1] = _tem_data.bval[1]; 480 | temp[2] = _tem_data.bval[0]; 481 | Wire.beginTransmission(_add); 482 | Wire.write(reg); 483 | Wire.write(temp, 3); 484 | Wire.endTransmission(); 485 | // delay(1); 486 | 487 | } 488 | -------------------------------------------------------------------------------- /ArduinoCode/i2cEncoderLibV2.h: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: i2cEncoderLibV2.h 3 | // VERSION: 0.1.. 4 | // PURPOSE: Libreary for the i2c encoder board with arduinp 5 | // LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html) 6 | // 7 | // DATASHEET: 8 | // 9 | // URL: 10 | // 11 | // AUTHOR: 12 | // Simone Caron 13 | // 14 | 15 | #ifndef i2cEncoderLibV2_H 16 | #define i2cEncoderLibV2_H 17 | 18 | #if (ARDUINO >= 100) 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | /*Encoder register definition*/ 25 | #define REG_GCONF 0x00 26 | #define REG_GP1CONF 0x01 27 | #define REG_GP2CONF 0x02 28 | #define REG_GP3CONF 0x03 29 | #define REG_INTCONF 0x04 30 | #define REG_ESTATUS 0x05 31 | #define REG_I2STATUS 0x06 32 | #define REG_FSTATUS 0x07 33 | #define REG_CVALB4 0x08 34 | #define REG_CVALB3 0x09 35 | #define REG_CVALB2 0x0A 36 | #define REG_CVALB1 0x0B 37 | #define REG_CMAXB4 0x0C 38 | #define REG_CMAXB3 0x0D 39 | #define REG_CMAXB2 0x0E 40 | #define REG_CMAXB1 0x0F 41 | #define REG_CMINB4 0x10 42 | #define REG_CMINB3 0x11 43 | #define REG_CMINB2 0x12 44 | #define REG_CMINB1 0x13 45 | #define REG_ISTEPB4 0x14 46 | #define REG_ISTEPB3 0x15 47 | #define REG_ISTEPB2 0x16 48 | #define REG_ISTEPB1 0x17 49 | #define REG_RLED 0x18 50 | #define REG_GLED 0x19 51 | #define REG_BLED 0x1A 52 | #define REG_GP1REG 0x1B 53 | #define REG_GP2REG 0x1C 54 | #define REG_GP3REG 0x1D 55 | #define REG_ANTBOUNC 0x1E 56 | #define REG_DPPERIOD 0x1F 57 | #define REG_FADERGB 0x20 58 | #define REG_FADEGP 0x21 59 | #define REG_EEPROMS 0x80 60 | 61 | /* Encoder configuration bit. Use with GCONF */ 62 | #define FLOAT_DATA 0x01 63 | #define INT_DATA 0x00 64 | 65 | #define WRAP_ENABLE 0x02 66 | #define WRAP_DISABLE 0x00 67 | 68 | #define DIRE_LEFT 0x04 69 | #define DIRE_RIGHT 0x00 70 | 71 | #define IPUP_DISABLE 0x08 72 | #define IPUP_ENABLE 0x00 73 | 74 | #define RMOD_X2 0x10 75 | #define RMOD_X1 0x00 76 | 77 | #define RGB_ENCODER 0x20 78 | #define STD_ENCODER 0x00 79 | 80 | #define EEPROM_BANK1 0x40 81 | #define EEPROM_BANK2 0x00 82 | 83 | #define RESET 0x80 84 | 85 | /* Encoder status bits and setting. Use with: INTCONF for set and with ESTATUS for read the bits */ 86 | #define PUSHR 0x01 87 | #define PUSHP 0x02 88 | #define PUSHD 0x04 89 | #define RINC 0x08 90 | #define RDEC 0x10 91 | #define RMAX 0x20 92 | #define RMIN 0x40 93 | #define INT2 0x80 94 | 95 | /* Encoder Int2 bits. Use to read the bits of I2STATUS */ 96 | #define GP1_POS 0x01 97 | #define GP1_NEG 0x02 98 | #define GP2_POS 0x04 99 | #define GP2_NEG 0x08 100 | #define GP3_POS 0x10 101 | #define GP3_NEG 0x20 102 | #define FADE_INT 0x40 103 | 104 | /* Encoder Fade status bits. Use to read the bits of FSTATUS */ 105 | #define FADE_R 0x01 106 | #define FADE_G 0x02 107 | #define FADE_B 0x04 108 | #define FADE_GP1 0x08 109 | #define FADE_GP2 0x10 110 | #define FADE_GP3 0x20 111 | 112 | /* GPIO Configuration. USe with GP1CONF,GP2CONF,GP3CONF */ 113 | #define GP_PWM 0x00 114 | #define GP_OUT 0x01 115 | #define GP_AN 0x02 116 | #define GP_IN 0x03 117 | 118 | #define GP_PULL_EN 0x04 119 | #define GP_PULL_DI 0x00 120 | 121 | #define GP_INT_DI 0x00 122 | #define GP_INT_PE 0x08 123 | #define GP_INT_NE 0x10 124 | #define GP_INT_BE 0x18 125 | 126 | 127 | 128 | 129 | union Data_v { 130 | float fval; 131 | int32_t val; 132 | uint8_t bval[4]; 133 | }; 134 | 135 | class i2cEncoderLibV2 136 | { 137 | public: 138 | i2cEncoderLibV2(uint8_t add); 139 | void begin( uint8_t conf); 140 | 141 | /** Read functions **/ 142 | /** Configuration function **/ 143 | uint8_t readGP1conf(void); 144 | uint8_t readGP2conf(void); 145 | uint8_t readGP3conf(void); 146 | uint8_t readInterruptConfig(void); 147 | 148 | /** Status function **/ 149 | bool updateStatus(void); 150 | bool readStatus(uint8_t s); 151 | uint8_t readStatus(void); 152 | 153 | bool readInt2(uint8_t s); 154 | uint8_t readInt2(void); 155 | 156 | bool readFadeStatus(uint8_t s); 157 | uint8_t readFadeStatus(void); 158 | 159 | /** Encoder functions **/ 160 | float readCounterFloat(void); 161 | int32_t readCounterLong(void); 162 | int16_t readCounterInt(void); 163 | int8_t readCounterByte(void); 164 | 165 | int32_t readMax(void); 166 | float readMaxFloat(void); 167 | 168 | int32_t readMin(void); 169 | float readMinFloat(void); 170 | 171 | int32_t readStep(void); 172 | float readStepFloat(void); 173 | 174 | /** RGB LED Functions **/ 175 | uint8_t readLEDR(void); 176 | uint8_t readLEDG(void); 177 | uint8_t readLEDB(void); 178 | 179 | /** GP LED Functions **/ 180 | uint8_t readGP1(void); 181 | uint8_t readGP2(void); 182 | uint8_t readGP3(void); 183 | 184 | /** Timing registers **/ 185 | uint8_t readAntibouncingPeriod(void); 186 | uint8_t readDoublePushPeriod(void); 187 | uint8_t readFadeRGB(void); 188 | uint8_t readFadeGP(void); 189 | 190 | /** EEPROM register **/ 191 | uint8_t readEEPROM(uint8_t add); 192 | 193 | 194 | uint8_t readEncoderByte(uint8_t reg); 195 | int16_t readEncoderInt(uint8_t reg); 196 | int32_t readEncoderLong(uint8_t reg); 197 | 198 | /****** Write functions ********/ 199 | void writeGP1conf(uint8_t gp1); 200 | void writeGP2conf(uint8_t gp2); 201 | void writeGP3conf(uint8_t gp3); 202 | void writeInterruptConfig(uint8_t interrupt); 203 | 204 | /** Encoder functions **/ 205 | void writeCounter(int32_t counter); 206 | void writeCounter(float counter); 207 | 208 | void writeMax(int32_t max); 209 | void writeMax(float max); 210 | 211 | void writeMin(int32_t min); 212 | void writeMin(float min); 213 | 214 | void writeStep(int32_t step); 215 | void writeStep(float step); 216 | 217 | /** RGB LED Functions **/ 218 | void writeLEDR(uint8_t rled); 219 | void writeLEDG(uint8_t gled); 220 | void writeLEDB(uint8_t bled); 221 | void writeRGBCode(uint32_t rgb); 222 | 223 | /** GP LED Functions **/ 224 | void writeGP1(uint8_t gp1); 225 | void writeGP2(uint8_t gp2); 226 | void writeGP3(uint8_t gp3); 227 | 228 | /** Timing registers **/ 229 | void writeAntibouncingPeriod(uint8_t bounc); 230 | void writeDoublePushPeriod(uint8_t dperiod); 231 | void writeFadeRGB(uint8_t fade); 232 | void writeFadeGP(uint8_t fade); 233 | 234 | /** EEPROM register **/ 235 | void writeEEPROM(uint8_t add, uint8_t data); 236 | 237 | private: 238 | uint8_t _add = 0x00; 239 | uint8_t _stat = 0x00; 240 | uint8_t _stat2 = 0x00; 241 | uint8_t _gconf = 0x00; 242 | union Data_v _tem_data; 243 | 244 | float readEncoderFloat(uint8_t reg); 245 | void writeEncoder(uint8_t reg, uint8_t data); 246 | void writeEncoder(uint8_t reg, int32_t data); 247 | void writeEncoder(uint8_t reg, float data); 248 | void writeEncoder24bit(uint8_t reg, uint32_t data); 249 | 250 | }; 251 | 252 | #endif 253 | -------------------------------------------------------------------------------- /Circuit-diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeremySCook/RotaryControl/061fe71509a7efe10a77fcc3ec582291b6549cab/Circuit-diagram.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Tech Adjacent](https://img.shields.io/badge/Tech%20Adjacent%20With%20Jeremy%20Cook-[Substack]-blue?style=flat-square&logo=substack)](https://techadjacent.substack.com/) 2 | 3 | # RotaryControl 4 | 5 | * 6 | * 7 | ### New Version: Enhanced [JC Pro Macro 2](https://www.tindie.com/products/jeremycook/jc-pro-macro-2-rotarygpio-macro-keyboard-kit/) for sale on Tindie with all kinds of fun features. 8 | * 9 | * 10 | 11 | ![image](shortcut.jpg) 12 | 13 | ### Build videos 14 | 15 | https://www.youtube.com/playlist?list=PLUSVaS5vtdgQBRD3hqpD_LZi0aTD-GRQe 16 | 17 | ### Purchased Electronics Needed 18 | 19 | 5x7 Perf board \ 20 | I2C Rotary Encoder: https://www.tindie.com/products/Saimon/i2cencoder-v2-connect-multiple-encoder-on-i2c-bus/ \ 21 | MellBell PICO: https://mellbell.cc/products/pico \ 22 | NeoPixel Ring: https://www.adafruit.com/product/1643 \ 23 | Rotary Encoder \ 24 | Encoder knob: https://www.ebay.com/itm/K9-0-25-Dia-Black-Aluminum-Rotary-Control-Potentiometer-Knob-25mm-x-15mm/253315168134 \ 25 | Pushbuttons \ 26 | Wire 27 | 28 | ### 3D Print Stuff 29 | 30 | Clear PLA https://amzn.to/2MXi3qr (Amazon Affiliate) \ 31 | Black PLA https://amzn.to/31PlYd2 (Amazon Affiliate) \ 32 | Plasti Dip Spray https://amzn.to/34lU22f (Amazon Affiliate - not sure if this is the correct type) 33 | 34 | ### Wiring Diagram 35 | 36 | ![image](Circuit-diagram.jpg) 37 | 38 | ### Other Info 39 | 40 | This post was helpful to figure out how to use the caps lock functionality: https://www.instructables.com/id/USB-Volume-Control-and-Caps-Lock-LED-Simple-Cheap-/ \ 41 | Code referenced in [Arrow Encoder article](https://www.arrow.com/en/research-and-events/articles/rotary-encoders-how-to-pair-with-an-arduino-board): https://github.com/JeremySCook/ArduinoEncoder 42 | 43 | [![Tech Adjacent](https://img.shields.io/badge/Tech%20Adjacent%20With%20Jeremy%20Cook-[Substack]-blue?style=flat-square&logo=substack)](https://techadjacent.substack.com/) 44 | -------------------------------------------------------------------------------- /STL/Knob.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeremySCook/RotaryControl/061fe71509a7efe10a77fcc3ec582291b6549cab/STL/Knob.stl -------------------------------------------------------------------------------- /STL/README: -------------------------------------------------------------------------------- 1 | 3D print files 2 | -------------------------------------------------------------------------------- /STL/shortcut-inner.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeremySCook/RotaryControl/061fe71509a7efe10a77fcc3ec582291b6549cab/STL/shortcut-inner.stl -------------------------------------------------------------------------------- /STL/shortcut-outer.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeremySCook/RotaryControl/061fe71509a7efe10a77fcc3ec582291b6549cab/STL/shortcut-outer.stl -------------------------------------------------------------------------------- /rotary-caps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeremySCook/RotaryControl/061fe71509a7efe10a77fcc3ec582291b6549cab/rotary-caps.jpg -------------------------------------------------------------------------------- /shortcut.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JeremySCook/RotaryControl/061fe71509a7efe10a77fcc3ec582291b6549cab/shortcut.jpg --------------------------------------------------------------------------------