From 1a2ce7e7c0f58428e861b81e381bfe7ca7d0a47b Mon Sep 17 00:00:00 2001 From: lucavanstraaten Date: Tue, 28 Apr 2026 21:18:35 +0200 Subject: [PATCH] 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 --- src/main.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1ab47fa..9a76a36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,24 @@ 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(uint64_t value, uint64_t maxVal) { + if (maxVal == 0) { setStatus(16, 0, 16); return; } // magenta = unknown range + uint16_t hue = (uint16_t)((value * 360) / maxVal); // 0-359 + 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; + } +} + // ========================================================================= // CORE 1: SSI worker // ========================================================================= @@ -105,6 +123,7 @@ void requestSsiRead(uint8_t bits, uint16_t half_us, uint64_t& outValue, uint32_t void handleCommand(const String& cmd) { if (!cmd.startsWith("READ ")) { + setStatus(16, 0, 0); // red = error Serial.println("ERR unknown command. Use: READ "); return; } @@ -112,6 +131,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 "); return; } @@ -120,19 +140,24 @@ void handleCommand(const String& cmd) { int halfUs = cmd.substring(secondSpace + 1).toInt(); if (bits < 1 || bits > 64) { + setStatus(16, 0, 0); // red = error Serial.println("ERR bits must be 1..64"); return; } if (halfUs < 1 || halfUs > 10000) { + setStatus(16, 0, 0); // red = error Serial.println("ERR half_us must be 1..10000"); return; } - setStatus(0, 0, 16); // blue = reading + setStatus(0, 0, 16); // blue = reading uint64_t value; uint32_t took; requestSsiRead((uint8_t)bits, (uint16_t)halfUs, value, took); - setStatus(0, 16, 0); // green = idle + + // Show encoder position as hue (full range = 2^bits - 1) + uint64_t maxVal = (bits < 64) ? ((1ull << bits) - 1) : UINT64_MAX; + setPositionColor(value, maxVal); Serial.printf("OK bits=%d half_us=%d hex=0x%llX dec=%llu took=%luus\n", bits, halfUs, value, value, took);