3 Commits

3 changed files with 1530 additions and 747 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,9 +7,9 @@
static const uint8_t GAUGE_COUNT = 5;
// Backlight/status LEDs use an addressable strip. Indicator LEDs are
// single-colour active-high outputs on per-gauge pins. The command protocol
// single-colour active-high PWM outputs on per-gauge pins. The command protocol
// still exposes one logical LED segment per gauge.
static const uint8_t LED_DATA_PIN = 22;
static const uint8_t LED_DATA_PIN = A8;
static const uint8_t BREATHE_FRAME_MS = 16;
static const uint8_t LED_SHOW_MIN_INTERVAL_MS = 16;
static const uint8_t LED_SHOW_MOTION_INTERVAL_MS = 50;
@@ -161,6 +161,9 @@ uint8_t ledLocalIdx[TOTAL_LEDS];
bool ledIsIndicator[TOTAL_LEDS];
bool ledRgSwap[TOTAL_LEDS];
BlinkState blinkState[TOTAL_LEDS];
volatile uint8_t indicatorPwmLevel[TOTAL_INDICATOR_LEDS];
volatile uint8_t* indicatorPwmPort[TOTAL_INDICATOR_LEDS];
uint8_t indicatorPwmMask[TOTAL_INDICATOR_LEDS];
bool mainLedsDirty = false;
unsigned long lastLedShowMs = 0;
@@ -185,18 +188,16 @@ inline int8_t indicatorPinFor(uint8_t gaugeIdx, uint8_t localIdx) {
return -1;
}
inline bool indicatorIsOn(uint8_t localIdx, CRGB color) {
if (localIdx == 3) return color.r >= 128;
if (localIdx == 4) return color.g >= 128;
return false;
inline uint8_t indicatorLevel(uint8_t localIdx, CRGB color) {
if (localIdx == 3) return color.r;
if (localIdx == 4) return color.g;
return 0;
}
inline void writeIndicatorLed(uint8_t globalIdx, CRGB color) {
uint8_t gaugeIdx = ledGaugeIdx[globalIdx];
uint8_t localIdx = ledLocalIdx[globalIdx];
int8_t pin = indicatorPinFor(gaugeIdx, localIdx);
if (pin >= 0) {
digitalWrite(pin, indicatorIsOn(localIdx, color) ? HIGH : LOW);
uint8_t pwmIdx = ledPhysicalIdx[globalIdx];
if (pwmIdx < TOTAL_INDICATOR_LEDS) {
indicatorPwmLevel[pwmIdx] = indicatorLevel(ledLocalIdx[globalIdx], color);
}
}
@@ -480,7 +481,29 @@ void setupStepperTimer() {
SREG = oldSreg;
}
inline void updateIndicatorPwmIsr() {
static uint8_t phase = 0;
phase++;
for (uint8_t i = 0; i < TOTAL_INDICATOR_LEDS; i++) {
volatile uint8_t* port = indicatorPwmPort[i];
if (port == nullptr) continue;
uint8_t mask = indicatorPwmMask[i];
uint8_t level = indicatorPwmLevel[i];
if (level == 0) {
*port &= ~mask;
} else if (level == 255 || phase < level) {
*port |= mask;
} else {
*port &= ~mask;
}
}
}
ISR(TIMER1_COMPA_vect) {
updateIndicatorPwmIsr();
for (uint8_t i = 0; i < GAUGE_COUNT; i++) {
StepperRuntime& s = steppers[i];
bool pulseJustEnded = false;
@@ -1219,6 +1242,7 @@ void setup() {
// offsets for the addressable main strip.
uint8_t ledOff = 0;
uint8_t mainLedOff = 0;
uint8_t indicatorLedOff = 0;
for (uint8_t i = 0; i < GAUGE_COUNT; i++) {
gaugeLedCount[i] = cstrLen(gaugePins[i].ledOrder);
gaugeLedOffset[i] = ledOff;
@@ -1232,9 +1256,17 @@ void setup() {
ledIsIndicator[globalIdx] = indicator;
ledRgSwap[globalIdx] = gaugePins[i].ledOrder[localIdx] == 'G' ||
gaugePins[i].ledOrder[localIdx] == 'g';
ledPhysicalIdx[globalIdx] = indicator
? 0
: mainLedOff + localIdx - (localIdx > 4 ? 2 : 0);
if (indicator) {
ledPhysicalIdx[globalIdx] = indicatorLedOff;
int8_t pin = indicatorPinFor(i, localIdx);
if (pin >= 0) {
indicatorPwmPort[indicatorLedOff] = portOutputRegister(digitalPinToPort(pin));
indicatorPwmMask[indicatorLedOff] = digitalPinToBitMask(pin);
}
indicatorLedOff++;
} else {
ledPhysicalIdx[globalIdx] = mainLedOff + localIdx - (localIdx > 4 ? 2 : 0);
}
}
ledOff += gaugeLedCount[i];