You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
4.5 KiB
C++
275 lines
4.5 KiB
C++
#define RED_LED 5
|
|
#define GREEN_LED 3
|
|
#define BLUE_LED 6
|
|
#define STATUS_LED 4
|
|
|
|
#define MAX_NUMBER_DIGITS 4
|
|
|
|
using namespace std;
|
|
|
|
int tps = 33;
|
|
unsigned long current_ms = millis();
|
|
unsigned long tick_interval_tracker = 0;
|
|
unsigned int tick_interval = 1000 / tps;
|
|
|
|
int leds[] = {RED_LED, GREEN_LED, BLUE_LED};
|
|
int led_iterator = 0;
|
|
int mode = 0; // 0 = breathe, 1 = set color
|
|
float current_vals[] = {0, 0, 0};
|
|
|
|
int breathe_increments[] = {1, 2, 4};
|
|
int breathe_directions[] = {0, 0, 0};
|
|
|
|
int target_vals[] = {0, 0, 0};
|
|
int fade_ticks = 0;
|
|
int fade_ms = 0;
|
|
float fade_increments[] = {0, 0, 0};
|
|
|
|
char current_char = ' ';
|
|
char command = ' ';
|
|
char arg = ' ';
|
|
char current_number_string[MAX_NUMBER_DIGITS + 1];
|
|
int position = 0;
|
|
int current_number_len = 0;
|
|
int parsed_number = 0;
|
|
bool end_of_line = 0;
|
|
|
|
void setup() {
|
|
|
|
Serial.begin(9600);
|
|
Serial.println("ready.");
|
|
|
|
pinMode(RED_LED, OUTPUT);
|
|
pinMode(GREEN_LED, OUTPUT);
|
|
pinMode(BLUE_LED, OUTPUT);
|
|
pinMode(STATUS_LED, OUTPUT);
|
|
|
|
reset_number_string();
|
|
|
|
}
|
|
|
|
void loop() {
|
|
|
|
if (Serial.available()) {
|
|
|
|
current_char = Serial.read();
|
|
|
|
if (position == 0) {
|
|
|
|
switch (current_char) {
|
|
|
|
case 'F':
|
|
case 'T':
|
|
case 'B':
|
|
command = current_char;
|
|
break;
|
|
|
|
default:
|
|
Serial.println("invalid command.");
|
|
Serial.flush();
|
|
|
|
command = arg = ' ';
|
|
position = parsed_number = 0;
|
|
|
|
reset_number_string();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (current_char) {
|
|
|
|
case '0' ... '9':
|
|
if (current_number_len < MAX_NUMBER_DIGITS) {
|
|
|
|
current_number_len++;
|
|
current_number_string[current_number_len - 1] = current_char;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'R':
|
|
case 'G':
|
|
case 'B':
|
|
case 'T':
|
|
case 'I':
|
|
arg = current_char;
|
|
break;
|
|
|
|
case ' ':
|
|
if (current_number_len > 0) parsed_number = atoi(current_number_string);
|
|
if (arg != ' ') callback();
|
|
|
|
arg = current_char = ' ';
|
|
reset_number_string();
|
|
|
|
break;
|
|
|
|
case '\n':
|
|
if (current_number_len > 0) parsed_number = atoi(current_number_string);
|
|
end_of_line = true;
|
|
callback();
|
|
|
|
command = arg = ' ';
|
|
position = parsed_number = 0;
|
|
reset_number_string();
|
|
|
|
break;
|
|
|
|
default:
|
|
Serial.println("invalid syntax.");
|
|
Serial.flush();
|
|
|
|
command = arg = ' ';
|
|
position = parsed_number = 0;
|
|
|
|
reset_number_string();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (current_char == '\n') {
|
|
|
|
end_of_line = false;
|
|
Serial.println("ok.");
|
|
|
|
} else position++;
|
|
|
|
}
|
|
|
|
if (millis() - tick_interval_tracker >= tick_interval) {
|
|
|
|
tick_interval_tracker += tick_interval;
|
|
execute_tick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void callback() {
|
|
|
|
switch (command) {
|
|
|
|
case 'B':
|
|
mode = 0;
|
|
break;
|
|
|
|
case 'F':
|
|
switch (arg) {
|
|
|
|
case 'T':
|
|
fade_ms = parsed_number;
|
|
break;
|
|
|
|
case 'R':
|
|
target_vals[0] = parsed_number;
|
|
break;
|
|
|
|
case 'G':
|
|
target_vals[1] = parsed_number;
|
|
break;
|
|
|
|
case 'B':
|
|
target_vals[2] = parsed_number;
|
|
break;
|
|
|
|
}
|
|
|
|
if (end_of_line == true) {
|
|
|
|
if (fade_ms <= tick_interval) {
|
|
|
|
mode = 1;
|
|
fade_ticks = 0;
|
|
|
|
} else {
|
|
|
|
mode = 1;
|
|
fade_ticks = ceil(fade_ms / (float) tick_interval);
|
|
|
|
led_iterator = 0;
|
|
while (led_iterator < 3) {
|
|
|
|
fade_increments[led_iterator] = -((current_vals[led_iterator] - target_vals[led_iterator]) / (float) fade_ticks);
|
|
led_iterator++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
if (arg == 'R') {
|
|
|
|
tps = parsed_number;
|
|
tick_interval = 1000 / tps;
|
|
|
|
} else if (arg == 'I') {
|
|
|
|
tick_interval = parsed_number;
|
|
tps = 1000 / tick_interval;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void reset_number_string() {
|
|
|
|
for (int i = 0; i < MAX_NUMBER_DIGITS; i++) current_number_string[i] = ' ';
|
|
current_number_string[MAX_NUMBER_DIGITS] = '\0';
|
|
current_number_len = 0;
|
|
|
|
}
|
|
|
|
void execute_tick() {
|
|
|
|
if (mode == 0) {
|
|
|
|
led_iterator = 0;
|
|
while (led_iterator < 3) {
|
|
|
|
if (current_vals[led_iterator] <= 0 || current_vals[led_iterator] >= 255) breathe_increments[led_iterator] = -breathe_increments[led_iterator];
|
|
analogWrite(leds[led_iterator], current_vals[led_iterator]);
|
|
current_vals[led_iterator] = constrain(current_vals[led_iterator] + breathe_increments[led_iterator], 0, 255);
|
|
|
|
led_iterator++;
|
|
|
|
}
|
|
|
|
} else if (mode == 1) {
|
|
|
|
if (fade_ticks > 0) {
|
|
|
|
led_iterator = 0;
|
|
while (led_iterator < 3) {
|
|
|
|
current_vals[led_iterator] += fade_increments[led_iterator];
|
|
analogWrite(leds[led_iterator], current_vals[led_iterator]);
|
|
|
|
led_iterator++;
|
|
|
|
}
|
|
|
|
fade_ticks--;
|
|
|
|
} else if (fade_ticks == 0) {
|
|
|
|
Serial.println("done.");
|
|
fade_ticks--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|