diff --git a/firmware/pulsating-sketch/pulsating-sketch.ino b/firmware/pulsating-sketch/pulsating-sketch.ino new file mode 100644 index 0000000..327a963 --- /dev/null +++ b/firmware/pulsating-sketch/pulsating-sketch.ino @@ -0,0 +1,126 @@ +const uint16_t PWM_MAX_VALUE = 128; +const uint16_t PWM_CYCLE = 30; // us + +// digitalWrite is too slow… +inline void set_pin(uint8_t pin) { + if(pin < 8) { + PORTA |= 1 << pin; + } else { + PORTB |= 1 << (10 - pin); + } +} +inline void reset_pin(uint8_t pin) { + if(pin < 8) { + PORTA &= ~(1 << pin); + } else { + PORTB &= ~(1 << (10 - pin)); + } +} + +struct PwmPin { + uint8_t location; + uint16_t value; + uint16_t tick; +}; + +enum Leds { + LED_LEFT_R, + LED_LEFT_B, + LED_RIGHT_R, + LED_RIGHT_B, + LED_TOP_R, + LED_TOP_B, +}; + +PwmPin pins[] = { + { 0, 20, 0}, + { 1, 20, 0}, + { 2, 10, 0}, + { 3, 10, 0}, + {10, 5, 0}, + { 9, 5, 0}, +}; + +unsigned long last_micros = 0; +void pwm_tick() { + if(micros() - last_micros > PWM_CYCLE) { + for(auto& pin : pins) { + if(pin.tick < pin.value) { + set_pin(pin.location); + } else { + reset_pin(pin.location); + } + + pin.tick = (pin.tick + 1) % PWM_MAX_VALUE; + } + + last_micros = micros(); + } +} + +void setup() { + for(auto& pin : pins) { + pinMode(pin.location, OUTPUT); + } +} + + +struct FadeStep { + uint16_t target; + uint16_t step_width; +}; + +FadeStep pulsating_pattern_top[] = { + {21, 1}, + {2, 1}, + {0, 0}, +}; +FadeStep pulsating_pattern_left[] = { + {35, 1}, + {6, 1}, + {0, 0}, +}; +FadeStep pulsating_pattern_right[] = { + {40, 1}, + {9, 1}, + {0, 0}, +}; + +struct PatternState { + uint8_t pin; + FadeStep* pattern_start; + FadeStep* pattern_current; +}; + +PatternState patterns[] = { + {LED_TOP_R, pulsating_pattern_top, pulsating_pattern_top}, + {LED_TOP_B, pulsating_pattern_top, pulsating_pattern_top}, + {LED_LEFT_R, pulsating_pattern_left, pulsating_pattern_left}, + {LED_LEFT_B, pulsating_pattern_left, pulsating_pattern_left}, + {LED_RIGHT_R, pulsating_pattern_right, pulsating_pattern_right}, + {LED_RIGHT_B, pulsating_pattern_right, pulsating_pattern_right}, +}; + +unsigned long last_millis = 0; +void loop() { + pwm_tick(); + + if(millis() - last_millis > 100) { + for(auto& pattern : patterns) { + if(pins[pattern.pin].value > pattern.pattern_current->target) { + pins[pattern.pin].value = max(pins[pattern.pin].value - pattern.pattern_current->step_width, pattern.pattern_current->target); + } else if(pins[pattern.pin].value < pattern.pattern_current->target) { + pins[pattern.pin].value = min(pins[pattern.pin].value + pattern.pattern_current->step_width, pattern.pattern_current->target); + } + + if(pins[pattern.pin].value == pattern.pattern_current->target) { + pattern.pattern_current = pattern.pattern_current + 1; + if(pattern.pattern_current->step_width == 0) { + pattern.pattern_current = pattern.pattern_start; + } + } + } + + last_millis = millis(); + } +}