LED: show encoder position as hue after each read

- Add setPositionColor(): maps SSI value to HSV hue (0=red, 120=green, 240=blue)
- LED takes the position hue as its resting colour between reads
- Blue during active read unchanged
- All error paths now flash red before printing ERR
This commit is contained in:
lucavanstraaten 2026-04-28 21:16:59 +02:00
parent a8633962f2
commit a618cb238f

View file

@ -27,6 +27,25 @@ void setStatus(uint8_t r, uint8_t g, uint8_t b) {
led.show();
}
// Map encoder position to a colour on the HSV wheel (brightness fixed at ~20/255).
// hue 0-359: 0=red, 120=green, 240=blue
void setPositionColor(uint32_t value, uint32_t maxVal) {
if (maxVal == 0) { setStatus(16, 0, 16); return; } // magenta = unknown range
uint16_t hue = (uint16_t)(((uint32_t)value * 360) / maxVal); // 0-359
// HSV → RGB with S=1, V=20
uint8_t sector = hue / 60;
uint8_t frac = (uint8_t)(((hue % 60) * 255) / 60);
uint8_t v = 20, p = 0, q = (uint8_t)(v * (255 - frac) / 255), t = (uint8_t)(v * frac / 255);
switch (sector % 6) {
case 0: setStatus(v, t, p); break;
case 1: setStatus(q, v, p); break;
case 2: setStatus(p, v, t); break;
case 3: setStatus(p, q, v); break;
case 4: setStatus(t, p, v); break;
case 5: setStatus(v, p, q); break;
}
}
void ssi_pio_init(uint half_us) {
// pioasm generates these helpers in ssi.pio.h
ssi_offset = pio_add_program(ssi_pio, &ssi_master_program);
@ -85,6 +104,7 @@ uint32_t ssi_pio_read(uint8_t bits) {
void handleCommand(const String& cmd) {
if (!cmd.startsWith("READ ")) {
setStatus(16, 0, 0); // red = error
Serial.println("ERR unknown command. Use: READ <bits> <half_us>");
return;
}
@ -92,6 +112,7 @@ void handleCommand(const String& cmd) {
int firstSpace = cmd.indexOf(' ');
int secondSpace = cmd.indexOf(' ', firstSpace + 1);
if (secondSpace < 0) {
setStatus(16, 0, 0); // red = error
Serial.println("ERR usage: READ <bits> <half_us>");
return;
}
@ -100,21 +121,25 @@ void handleCommand(const String& cmd) {
int halfUs = cmd.substring(secondSpace + 1).toInt();
if (bits < 1 || bits > 32) {
setStatus(16, 0, 0); // red = error
Serial.println("ERR bits must be 1..32 (PIO ISR limit)");
return;
}
if (halfUs < 1 || halfUs > 10000) {
setStatus(16, 0, 0); // red = error
Serial.println("ERR half_us must be 1..10000");
return;
}
ssi_pio_reconfigure_speed(halfUs);
setStatus(0, 0, 16);
setStatus(0, 0, 16); // blue = reading
uint32_t t0 = micros();
uint32_t value = ssi_pio_read((uint8_t)bits);
uint32_t took = micros() - t0;
setStatus(0, 16, 0);
// Show encoder position as hue (full range = 2^bits - 1)
setPositionColor(value, (1ul << bits) - 1);
Serial.printf("OK bits=%d half_us=%d hex=0x%lX dec=%lu took=%luus\n",
bits, halfUs, value, value, took);