/* This sketch demonstrates controlling the Arduboy's RGB LED, in both analog and digital modes. */ /* To the extent possible under law, Scott Allen has waived all copyright and related or neighboring rights to this BeepDemo program. */ #include // The frame rate determines the button auto-repeat rate #define FRAME_RATE 25 // The increment/decrement amount when auto-repeating #define REPEAT_AMOUNT 3 // Delay time before button auto-repeat starts, in milliseconds #define REPEAT_DELAY 700 // Calculation of the number of frames to wait before button auto-repeat starts #define DELAY_FRAMES (REPEAT_DELAY / (1000 / FRAME_RATE)) #define ANALOG false #define DIGITAL true #define ANALOG_MAX 255 // Color array index enum class Color { RED, GREEN, BLUE, COUNT }; // Map LED color index to LED name const byte LEDpin[(byte)(Color::COUNT)] = { RED_LED, GREEN_LED, BLUE_LED }; Arduboy2 arduboy; // Analog LED values byte analogValue[3] = { 0, 0, 0}; // Digital LED states byte digitalState[3] = { RGB_OFF, RGB_OFF, RGB_OFF }; byte analogSelected = (byte)(Color::RED); byte digitalSelected = (byte)(Color::RED); boolean controlMode = ANALOG; // Button repeat handling unsigned int delayCount = 0; boolean repeating = false; // ============================= SETUP =================================== void setup() { arduboy.begin(); arduboy.setFrameRate(FRAME_RATE); analogSet(); } // ======================================================================= // =========================== MAIN LOOP ================================= void loop() { if (!arduboy.nextFrame()) { return; } arduboy.pollButtons(); // Toggle analog/digital control mode if (arduboy.justPressed(A_BUTTON)) { if ((controlMode = !controlMode) == DIGITAL) { arduboy.freeRGBled(); digitalSet(); } else { analogSet(); } } // Reset to Analog mode and all LEDs off if (arduboy.justPressed(B_BUTTON)) { reset(); } // Handle D-pad buttons for current mode if (controlMode == ANALOG) { modeAnalog(); } else { modeDigital(); } // Handle delay before button auto-repeat starts if ((delayCount != 0) && (--delayCount == 0)) { repeating = true; } renderScreen(); // Render and display the entire screen } // ======================================================================= // Analog control void modeAnalog() { if (arduboy.justPressed(RIGHT_BUTTON)) { valueInc(1); startButtonDelay(); } else if (arduboy.justPressed(LEFT_BUTTON)) { valueDec(1); startButtonDelay(); } else if (repeating && arduboy.pressed(RIGHT_BUTTON)) { valueInc(REPEAT_AMOUNT); } else if (repeating && arduboy.pressed(LEFT_BUTTON)) { valueDec(REPEAT_AMOUNT); } else if (arduboy.justPressed(DOWN_BUTTON)) { analogSelectInc(); } else if (arduboy.justPressed(UP_BUTTON)) { analogSelectDec(); } else if (repeating) { stopButtonRepeat(); } } // Digital control void modeDigital() { if (arduboy.justPressed(RIGHT_BUTTON) || arduboy.justPressed(LEFT_BUTTON)) { digitalState[digitalSelected] = (digitalState[digitalSelected] == RGB_ON) ? RGB_OFF : RGB_ON; arduboy.digitalWriteRGB(LEDpin[digitalSelected], digitalState[digitalSelected]); } else if (arduboy.justPressed(DOWN_BUTTON)) { digitalSelectInc(); } else if (arduboy.justPressed(UP_BUTTON)) { digitalSelectDec(); } } // Reset to analog mode and turn all LEDs off void reset() { digitalState[(byte)(Color::RED)] = RGB_OFF; digitalState[(byte)(Color::GREEN)] = RGB_OFF; digitalState[(byte)(Color::BLUE)] = RGB_OFF; digitalSet(); analogValue[(byte)(Color::RED)] = 0; analogValue[(byte)(Color::GREEN)] = 0; analogValue[(byte)(Color::BLUE)] = 0; analogSet(); digitalSelected = (byte)(Color::RED); analogSelected = (byte)(Color::RED); controlMode = ANALOG; } // Increment the selected analog LED value by the specified amount // and update the LED void valueInc(byte amount) { if ((ANALOG_MAX - analogValue[analogSelected]) <= amount) { analogValue[analogSelected] = ANALOG_MAX; } else { analogValue[analogSelected] += amount; } arduboy.setRGBled(LEDpin[analogSelected], analogValue[analogSelected]); } // Decrement the selected analog LED value by the specified amount // and update the LED void valueDec(byte amount) { if (analogValue[analogSelected] <= amount) { analogValue[analogSelected] = 0; } else { analogValue[analogSelected] -= amount; } arduboy.setRGBled(LEDpin[analogSelected], analogValue[analogSelected]); } // Select the next analog color index with wrap void analogSelectInc() { selectInc(analogSelected); } // Select the previous analog color index with wrap void analogSelectDec() { selectDec(analogSelected); } // Select the next digital color index with wrap void digitalSelectInc() { selectInc(digitalSelected); } // Select the previous digital color index with wrap void digitalSelectDec() { selectDec(digitalSelected); } // Select the next color index with wrap void selectInc(byte &index) { if (++index == (byte)(Color::COUNT)) { index = 0; } } // Select the previous color index with wrap void selectDec(byte &index) { if (index == 0) { index = ((byte)(Color::COUNT) - 1); } else { index--; } } // Update all LEDs in analog mode void analogSet() { arduboy.setRGBled(analogValue[(byte)(Color::RED)], analogValue[(byte)(Color::GREEN)], analogValue[(byte)(Color::BLUE)]); } // Update all LEDs in digital mode void digitalSet() { arduboy.digitalWriteRGB(digitalState[(byte)(Color::RED)], digitalState[(byte)(Color::GREEN)], digitalState[(byte)(Color::BLUE)]); } // Start the button auto-repeat delay void startButtonDelay() { delayCount = DELAY_FRAMES; repeating = false; } // Stop the button auto-repeat or delay void stopButtonRepeat() { delayCount = 0; repeating = false; } // Render and display the screen void renderScreen() { arduboy.setCursor(12, 0); arduboy.print(F("RGB LED")); arduboy.setCursor(15, 56); arduboy.print(F("A:Mode B:Reset")); arduboy.setCursor(74, 0); if (controlMode == ANALOG) { arduboy.print(F(" Analog")); drawAnalog(9, Color::RED, "Red:"); drawAnalog(25, Color::GREEN, "Green:"); drawAnalog(41, Color::BLUE, "Blue:"); } else { // Digital arduboy.print(F("Digital")); drawDigital(9, Color::RED, "Red:"); drawDigital(25, Color::GREEN, "Green:"); drawDigital(41, Color::BLUE, "Blue:"); } arduboy.display(CLEAR_BUFFER); } // Draw the information for one analog color void drawAnalog(int y, Color color, const char* name) { byte value = analogValue[(byte)color]; arduboy.setCursor(0, y); arduboy.print(name); arduboy.setCursor(42, y); printValue(value); if (analogSelected == (byte)color) { arduboy.print(F(" <--")); } drawBar(y + 8, color, value); } // Draw the value bar for an analog color void drawBar(int y, Color color, byte value) { byte barLength = value / 2; if (barLength == 0) { return; } if (analogSelected == (byte)color) { arduboy.fillRect(0, y, barLength, 5); } else { arduboy.drawRect(0, y, barLength, 5); } } // Draw the informaton for one digital color void drawDigital(int y, Color color, const char* name) { byte state = digitalState[(byte)color]; arduboy.setCursor(34, y + 3); arduboy.print(name); arduboy.setCursor(76, y + 3); if (state == RGB_ON) { arduboy.print(F("ON ")); arduboy.fillCircle(22, y + 6, 4); } else { arduboy.print(F("OFF")); arduboy.drawCircle(22, y + 6, 4); } if (digitalSelected == (byte)color) { arduboy.print(F(" <--")); arduboy.drawRect(16, y, 13, 13); } } // Print a byte in decimal and hex void printValue(byte val) { if (val < 100) { arduboy.print(' '); } if (val < 10) { arduboy.print(' '); } arduboy.print(val); arduboy.print(F(" 0x")); if (val < 0x10) { arduboy.print('0'); } arduboy.print(val, HEX); }