2018-02-22 19:36:55 +00:00
|
|
|
/*
|
2020-07-08 15:37:44 +00:00
|
|
|
RGBled
|
|
|
|
|
2018-02-22 19:36:55 +00:00
|
|
|
This sketch demonstrates controlling the Arduboy's RGB LED,
|
|
|
|
in both analog and digital modes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2020-07-08 15:37:44 +00:00
|
|
|
Written in 2018 by Scott Allen saydisp-git@yahoo.ca
|
|
|
|
|
|
|
|
To the extent possible under law, the author(s) have dedicated all copyright
|
|
|
|
and related and neighboring rights to this software to the public domain
|
|
|
|
worldwide. This software is distributed without any warranty.
|
|
|
|
|
|
|
|
You should have received a copy of the CC0 Public Domain Dedication along with
|
|
|
|
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
2018-02-22 19:36:55 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Arduboy2.h>
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-25 23:13:05 +00:00
|
|
|
// Draw the information for one digital color
|
2018-02-22 19:36:55 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|