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++

#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--;
}
}
}