From 154da940bf460314e1fba2876127479f3f9ef50a Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Sun, 28 Apr 2024 23:56:58 -0400 Subject: [PATCH 01/12] Add AnalogClock2D --- wled00/FX.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 3 ++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5592f7ba8d..5e52be9a00 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4861,6 +4861,46 @@ static const char _data_FX_MODE_FLOWSTRIPE[] PROGMEM = "Flow Stripe@Hue speed,Ef #define XY(x,y) SEGMENT.XY(x,y) +///////////////////////////// +// 2D Analog Clock // +///////////////////////////// +uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi13) + if (!strip.isMatrix) return mode_static(); // not a 2D set-up + + const uint16_t cols = SEGMENT.virtualWidth(); + const uint16_t rows = SEGMENT.virtualHeight(); + const uint16_t centerX = (cols >> 1) - 1; + const uint16_t centerY = (rows >> 1) - 1; + const uint16_t radius = min(centerX, centerY); + + auto hours_in_day = (localTime / (60 * 60)) % 12; + float hour_angle = radians(360 * hours_in_day / 12 - 90); + uint16_t hour_len = radius * 0.5; + uint16_t hour_x = centerX + hour_len * cos_t(hour_angle); + uint16_t hour_y = centerY + hour_len * sin_t(hour_angle); + + auto minutes_in_day = (localTime / (60)) % 60; + float minute_angle = radians(360 * minutes_in_day / 60 - 90); + uint16_t minute_len = radius * 0.7; + uint16_t minute_x = centerX + minute_len * cos_t(minute_angle); + uint16_t minute_y = centerY + minute_len * sin_t(minute_angle); + + auto seconds_in_day = (localTime) % 60; + float second_angle = radians(360 * seconds_in_day / 60 - 90); + uint16_t second_len = radius * 0.9; + uint16_t second_x = centerX + second_len * cos_t(second_angle); + uint16_t second_y = centerY + second_len * sin_t(second_angle); + + SEGMENT.fill(BLACK); + SEGMENT.draw_circle(centerX, centerY, radius, DARKSLATEGRAY); + SEGMENT.drawLine(centerX, centerY, second_x, second_y, BLUE); + SEGMENT.drawLine(centerX, centerY, minute_x, minute_y, GREEN); + SEGMENT.drawLine(centerX, centerY, hour_x, hour_y, RED); + + return FRAMETIME; +} // mode_2DAnalogClock() +static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "AnalogClock2D"; + // Black hole uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up @@ -8092,6 +8132,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_2DGEQ, &mode_2DGEQ, _data_FX_MODE_2DGEQ); // audio + addEffect(FX_MODE_2DANALOGCLOCK, &mode_2DAnalogClock, _data_FX_MODE_2DANALOGCLOCK); addEffect(FX_MODE_2DNOISE, &mode_2Dnoise, _data_FX_MODE_2DNOISE); addEffect(FX_MODE_2DFIRENOISE, &mode_2Dfirenoise, _data_FX_MODE_2DFIRENOISE); diff --git a/wled00/FX.h b/wled00/FX.h index 106a6712c0..3d627dca94 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -313,8 +313,9 @@ #define FX_MODE_WAVESINS 184 #define FX_MODE_ROCKTAVES 185 #define FX_MODE_2DAKEMI 186 +#define FX_MODE_2DANALOGCLOCK 187 -#define MODE_COUNT 187 +#define MODE_COUNT 188 typedef enum mapping1D2D { M12_Pixels = 0, From 7e8a667ac3873c7f5c3b24be778c46dd532eefb0 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 29 Apr 2024 00:24:27 -0400 Subject: [PATCH 02/12] Nicer clock face --- wled00/FX.cpp | 2 +- wled00/FX.h | 1 + wled00/FX_2Dfcn.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5e52be9a00..b95d065b92 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4892,7 +4892,7 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 uint16_t second_y = centerY + second_len * sin_t(second_angle); SEGMENT.fill(BLACK); - SEGMENT.draw_circle(centerX, centerY, radius, DARKSLATEGRAY); + SEGMENT.draw_circle_antialiased(centerX, centerY, radius, DARKSLATEGRAY); SEGMENT.drawLine(centerX, centerY, second_x, second_y, BLUE); SEGMENT.drawLine(centerX, centerY, minute_x, minute_y, GREEN); SEGMENT.drawLine(centerX, centerY, hour_x, hour_y, RED); diff --git a/wled00/FX.h b/wled00/FX.h index 3d627dca94..fd997dee9a 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -626,6 +626,7 @@ typedef struct Segment { void moveY(int8_t delta, bool wrap = false); void move(uint8_t dir, uint8_t delta, bool wrap = false); void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); + void draw_circle_antialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c); inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index e14b68f4f1..2eb856fd6b 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -471,6 +471,32 @@ void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { } } +void Segment::draw_circle_antialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { + if (!isActive() || radius == 0) return; // not active + const uint16_t cols = virtualWidth(); + const uint16_t rows = virtualHeight(); + // Bresenham’s Algorithm + int d = 3 - (2*radius); + int y = radius, x = 0; + while (y >= x) { + setPixelColorXY(((float)cx+x-0.5)/cols, ((float)cy+y-0.5)/rows, col, true); + setPixelColorXY(((float)cx-x+0.5)/cols, ((float)cy+y-0.5)/rows, col, true); + setPixelColorXY(((float)cx+x-0.5)/cols, ((float)cy-y+0.5)/rows, col, true); + setPixelColorXY(((float)cx-x+0.5)/cols, ((float)cy-y+0.5)/rows, col, true); + setPixelColorXY(((float)cx+y-0.5)/cols, ((float)cy+x-0.5)/rows, col, true); + setPixelColorXY(((float)cx-y+0.5)/cols, ((float)cy+x-0.5)/rows, col, true); + setPixelColorXY(((float)cx+y-0.5)/cols, ((float)cy-x+0.5)/rows, col, true); + setPixelColorXY(((float)cx-y+0.5)/cols, ((float)cy-x+0.5)/rows, col, true); + x++; + if (d > 0) { + y--; + d += 4 * (x - y) + 10; + } else { + d += 4 * x + 6; + } + } +} + // by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { if (!isActive() || radius == 0) return; // not active From 5d93543f5ce2f2ef1a5f8b61f9931ca416251776 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 29 Apr 2024 00:24:40 -0400 Subject: [PATCH 03/12] Reduce processor workload --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b95d065b92..2a7958b266 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4897,7 +4897,7 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 SEGMENT.drawLine(centerX, centerY, minute_x, minute_y, GREEN); SEGMENT.drawLine(centerX, centerY, hour_x, hour_y, RED); - return FRAMETIME; + return (1000 / WLED_FPS); // calculate once per second } // mode_2DAnalogClock() static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "AnalogClock2D"; From 8930a6ed5a9b175097a097023e8440b4205d1842 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 29 Apr 2024 01:07:41 -0400 Subject: [PATCH 04/12] Move 'hours' and 'minutes' hand as a ratio of next tick --- wled00/FX.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2a7958b266..491c33e8e1 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4874,18 +4874,19 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 const uint16_t radius = min(centerX, centerY); auto hours_in_day = (localTime / (60 * 60)) % 12; - float hour_angle = radians(360 * hours_in_day / 12 - 90); + auto minutes_in_day = (localTime / (60)) % 60; + auto seconds_in_day = (localTime) % 60; + + float hour_angle = radians(360 * (hours_in_day + minutes_in_day / 60.0) / 12 - 90); uint16_t hour_len = radius * 0.5; uint16_t hour_x = centerX + hour_len * cos_t(hour_angle); uint16_t hour_y = centerY + hour_len * sin_t(hour_angle); - auto minutes_in_day = (localTime / (60)) % 60; - float minute_angle = radians(360 * minutes_in_day / 60 - 90); + float minute_angle = radians(360 * (minutes_in_day + seconds_in_day / 60.0) / 60 - 90); uint16_t minute_len = radius * 0.7; uint16_t minute_x = centerX + minute_len * cos_t(minute_angle); uint16_t minute_y = centerY + minute_len * sin_t(minute_angle); - auto seconds_in_day = (localTime) % 60; float second_angle = radians(360 * seconds_in_day / 60 - 90); uint16_t second_len = radius * 0.9; uint16_t second_x = centerX + second_len * cos_t(second_angle); From 3473794e9a5ec618efc56b5eb2e7e9568a195a11 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 29 Apr 2024 01:14:33 -0400 Subject: [PATCH 05/12] Fill entire area --- wled00/FX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 491c33e8e1..56778d5096 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4869,8 +4869,8 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); - const uint16_t centerX = (cols >> 1) - 1; - const uint16_t centerY = (rows >> 1) - 1; + const uint16_t centerX = cols >> 1; + const uint16_t centerY = rows >> 1; const uint16_t radius = min(centerX, centerY); auto hours_in_day = (localTime / (60 * 60)) % 12; From 2ee702e4a2c5f4d92e97b5a01758dcc4d38af388 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 29 Apr 2024 23:17:21 -0400 Subject: [PATCH 06/12] Add 'drawLineAntialiased' Nicer way for the hands of the clock to be displayed. --- wled00/FX.cpp | 6 +++--- wled00/FX.h | 1 + wled00/FX_2Dfcn.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 56778d5096..cf015d4d9f 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4894,9 +4894,9 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 SEGMENT.fill(BLACK); SEGMENT.draw_circle_antialiased(centerX, centerY, radius, DARKSLATEGRAY); - SEGMENT.drawLine(centerX, centerY, second_x, second_y, BLUE); - SEGMENT.drawLine(centerX, centerY, minute_x, minute_y, GREEN); - SEGMENT.drawLine(centerX, centerY, hour_x, hour_y, RED); + SEGMENT.drawLineAntialiased(centerX, centerY, second_x, second_y, BLUE); + SEGMENT.drawLineAntialiased(centerX, centerY, minute_x, minute_y, GREEN); + SEGMENT.drawLineAntialiased(centerX, centerY, hour_x, hour_y, RED); return (1000 / WLED_FPS); // calculate once per second } // mode_2DAnalogClock() diff --git a/wled00/FX.h b/wled00/FX.h index fd997dee9a..fa389a6e9d 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -630,6 +630,7 @@ typedef struct Segment { void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c); inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline + void drawLineAntialiased(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c); void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, int8_t rotate = 0); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate); } // automatic inline diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 2eb856fd6b..011248331a 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -539,6 +539,33 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 } } +//line function +void Segment::drawLineAntialiased(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { + if (!isActive()) return; // not active + const uint16_t cols = virtualWidth(); + const uint16_t rows = virtualHeight(); + if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return; + const int16_t dx = abs(x1-x0), sx = x0= -dx) { + if(x0 == x1) break; + if (e2+dy < ed) setPixelColorXY(x0,y0+sy, color_blend(c,getPixelColorXY(x0,y0+sy), 0xFFFF * (e2+dy)/ed, true)); + err -= dy; x0 += sx; + } + if (e2 <= dy) { + if (y0 == y1) break; + if (dx-e2 < ed) setPixelColorXY(x2+sx, y0, color_blend(c,getPixelColorXY(x2+sx,y0), 0xFFFF * (dx-e2)/ed, true)); + err += dx; y0 += sy; + } + } +} + #include "src/font/console_font_4x6.h" #include "src/font/console_font_5x8.h" #include "src/font/console_font_5x12.h" From fd16120c8a5d23b291a2b8ff6ac733b403504d13 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Tue, 30 Apr 2024 00:08:01 -0400 Subject: [PATCH 07/12] Don't give config parameters --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index cf015d4d9f..cb3a28aa27 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4900,7 +4900,7 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 return (1000 / WLED_FPS); // calculate once per second } // mode_2DAnalogClock() -static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "AnalogClock2D"; +static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "AnalogClock2D@;"; // Black hole uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline From 1b799f708c0e3375ae95b92443d7ac380a4ca011 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Tue, 30 Apr 2024 00:47:23 -0400 Subject: [PATCH 08/12] Fixes for compilation errors on '0_15' branch --- wled00/FX.cpp | 8 ++++++-- wled00/FX.h | 4 +++- wled00/FX_2Dfcn.cpp | 8 +++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index cb3a28aa27..6baad63292 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4861,6 +4861,7 @@ static const char _data_FX_MODE_FLOWSTRIPE[] PROGMEM = "Flow Stripe@Hue speed,Ef #define XY(x,y) SEGMENT.XY(x,y) +#ifdef WLED_USE_AA_PIXELS ///////////////////////////// // 2D Analog Clock // ///////////////////////////// @@ -4893,14 +4894,15 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 uint16_t second_y = centerY + second_len * sin_t(second_angle); SEGMENT.fill(BLACK); - SEGMENT.draw_circle_antialiased(centerX, centerY, radius, DARKSLATEGRAY); + SEGMENT.drawCircleAntialiased(centerX, centerY, radius, 0x333333); SEGMENT.drawLineAntialiased(centerX, centerY, second_x, second_y, BLUE); SEGMENT.drawLineAntialiased(centerX, centerY, minute_x, minute_y, GREEN); SEGMENT.drawLineAntialiased(centerX, centerY, hour_x, hour_y, RED); return (1000 / WLED_FPS); // calculate once per second } // mode_2DAnalogClock() -static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "AnalogClock2D@;"; +static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "Analog Clock 2D@;"; +#endif // Black hole uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline @@ -8133,7 +8135,9 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_2DGEQ, &mode_2DGEQ, _data_FX_MODE_2DGEQ); // audio +#ifdef WLED_USE_AA_PIXELS addEffect(FX_MODE_2DANALOGCLOCK, &mode_2DAnalogClock, _data_FX_MODE_2DANALOGCLOCK); +#endif addEffect(FX_MODE_2DNOISE, &mode_2Dnoise, _data_FX_MODE_2DNOISE); addEffect(FX_MODE_2DFIRENOISE, &mode_2Dfirenoise, _data_FX_MODE_2DFIRENOISE); diff --git a/wled00/FX.h b/wled00/FX.h index fa389a6e9d..80ae7fb10d 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -626,7 +626,9 @@ typedef struct Segment { void moveY(int8_t delta, bool wrap = false); void move(uint8_t dir, uint8_t delta, bool wrap = false); void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); - void draw_circle_antialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); + #ifdef WLED_USE_AA_PIXELS + void drawCircleAntialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); + #endif void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c); void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c); inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 011248331a..bea70c7ca0 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -370,7 +370,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) { for (unsigned j = 0; j < dim1; j++) { unsigned x = vertical ? i : j; unsigned y = vertical ? j : i; - setPixelColorXY(x, y, tmp[j]); + setPixelColorXY((int)x, (int)y, tmp[j]); } } @@ -471,7 +471,8 @@ void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { } } -void Segment::draw_circle_antialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { +#ifdef WLED_USE_AA_PIXELS +void Segment::drawCircleAntialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { if (!isActive() || radius == 0) return; // not active const uint16_t cols = virtualWidth(); const uint16_t rows = virtualHeight(); @@ -496,6 +497,7 @@ void Segment::draw_circle_antialiased(uint16_t cx, uint16_t cy, uint8_t radius, } } } +#endif // by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { @@ -517,7 +519,7 @@ void Segment::nscale8(uint8_t scale) { const unsigned cols = virtualWidth(); const unsigned rows = virtualHeight(); for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) { - setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale)); + setPixelColorXY((int)x, (int)y, CRGB(getPixelColorXY(x, y)).nscale8(scale)); } } From aab45aff7df0c38bc50fddd19374c07a0fe34960 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Thu, 2 May 2024 00:05:10 -0400 Subject: [PATCH 09/12] Addressing PR comments --- wled00/FX.cpp | 6 +++--- wled00/FX_2Dfcn.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 6baad63292..040accfaf6 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4874,9 +4874,9 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 const uint16_t centerY = rows >> 1; const uint16_t radius = min(centerX, centerY); - auto hours_in_day = (localTime / (60 * 60)) % 12; - auto minutes_in_day = (localTime / (60)) % 60; - auto seconds_in_day = (localTime) % 60; + time_t hours_in_day = (localTime / (60 * 60)) % 12; + time_t minutes_in_day = (localTime / (60)) % 60; + time_t seconds_in_day = (localTime) % 60; float hour_angle = radians(360 * (hours_in_day + minutes_in_day / 60.0) / 12 - 90); uint16_t hour_len = radius * 0.5; diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index bea70c7ca0..394dbd1080 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -550,7 +550,7 @@ void Segment::drawLineAntialiased(uint16_t x0, uint16_t y0, uint16_t x1, uint16_ const int16_t dx = abs(x1-x0), sx = x0 Date: Fri, 10 May 2024 00:12:32 +0200 Subject: [PATCH 10/12] Update - use options - replace AA functions --- wled00/FX.cpp | 60 +++++++++++++++++++++++---------------------- wled00/FX.h | 5 ++-- wled00/FX_2Dfcn.cpp | 55 ----------------------------------------- 3 files changed, 33 insertions(+), 87 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index aca16ef81e..a5f9d1c51b 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4861,48 +4861,52 @@ static const char _data_FX_MODE_FLOWSTRIPE[] PROGMEM = "Flow Stripe@Hue speed,Ef #define XY(x,y) SEGMENT.XY(x,y) -#ifdef WLED_USE_AA_PIXELS ///////////////////////////// // 2D Analog Clock // ///////////////////////////// uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi13) - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up - const uint16_t cols = SEGMENT.virtualWidth(); - const uint16_t rows = SEGMENT.virtualHeight(); - const uint16_t centerX = cols >> 1; - const uint16_t centerY = rows >> 1; - const uint16_t radius = min(centerX, centerY); + const int cols = SEGMENT.virtualWidth(); + const int rows = SEGMENT.virtualHeight(); + const int centerX = (cols-!(cols%2)) >> 1; // use odd sized circle + const int centerY = (rows-!(rows%2)) >> 1; // use odd sized circle + const int radius = min(centerX, centerY); + const bool soft = radius > 6 && SEGMENT.check2; + + SEGMENT.fadeToBlackBy(240); + SEGMENT.drawCircle(centerX, centerY, radius, DARKGREY, soft); + if (radius > 8) SEGMENT.drawCircle(centerX, centerY, radius-1, DARKGREY, soft); // thicker circle time_t hours_in_day = (localTime / (60 * 60)) % 12; time_t minutes_in_day = (localTime / (60)) % 60; time_t seconds_in_day = (localTime) % 60; - float hour_angle = radians(360 * (hours_in_day + minutes_in_day / 60.0) / 12 - 90); - uint16_t hour_len = radius * 0.5; - uint16_t hour_x = centerX + hour_len * cos_t(hour_angle); - uint16_t hour_y = centerY + hour_len * sin_t(hour_angle); + float hour_angle = radians(30.0f * (hours_in_day + minutes_in_day / 60.0f) - 90.0f); + int hour_len = radius / 2; + int hour_x = centerX + hour_len * cos_t(hour_angle); + int hour_y = centerY + hour_len * sin_t(hour_angle); - float minute_angle = radians(360 * (minutes_in_day + seconds_in_day / 60.0) / 60 - 90); - uint16_t minute_len = radius * 0.7; - uint16_t minute_x = centerX + minute_len * cos_t(minute_angle); - uint16_t minute_y = centerY + minute_len * sin_t(minute_angle); + float minute_angle = radians(6.0f * (minutes_in_day + seconds_in_day / 60.0f) - 90.0f); + int minute_len = (radius * 7) / 10; + int minute_x = centerX + minute_len * cos_t(minute_angle); + int minute_y = centerY + minute_len * sin_t(minute_angle); - float second_angle = radians(360 * seconds_in_day / 60 - 90); - uint16_t second_len = radius * 0.9; - uint16_t second_x = centerX + second_len * cos_t(second_angle); - uint16_t second_y = centerY + second_len * sin_t(second_angle); + if (SEGMENT.check1) { + float second_angle = radians(6.0f * seconds_in_day - 90.0f); + int second_len = (radius * 9) / 10; + int second_x = centerX + second_len * cos_t(second_angle); + int second_y = centerY + second_len * sin_t(second_angle); + SEGMENT.drawLine(centerX, centerY, second_x, second_y, SEGCOLOR(2), soft); + } - SEGMENT.fill(BLACK); - SEGMENT.drawCircleAntialiased(centerX, centerY, radius, 0x333333); - SEGMENT.drawLineAntialiased(centerX, centerY, second_x, second_y, BLUE); - SEGMENT.drawLineAntialiased(centerX, centerY, minute_x, minute_y, GREEN); - SEGMENT.drawLineAntialiased(centerX, centerY, hour_x, hour_y, RED); + SEGMENT.drawLine(centerX, centerY, minute_x, minute_y, SEGCOLOR(1), soft); + SEGMENT.drawLine(centerX, centerY, hour_x, hour_y, SEGCOLOR(0), soft); - return (1000 / WLED_FPS); // calculate once per second + return FRAMETIME; } // mode_2DAnalogClock() -static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "Analog Clock 2D@;"; -#endif +static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "Analog Clock@,,,,,Seconds,Soft;Hour,Minute,Second;;2;o1=1,o2=1"; + // Black hole uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline @@ -8139,9 +8143,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_2DGEQ, &mode_2DGEQ, _data_FX_MODE_2DGEQ); // audio -#ifdef WLED_USE_AA_PIXELS addEffect(FX_MODE_2DANALOGCLOCK, &mode_2DAnalogClock, _data_FX_MODE_2DANALOGCLOCK); -#endif addEffect(FX_MODE_2DNOISE, &mode_2Dnoise, _data_FX_MODE_2DNOISE); addEffect(FX_MODE_2DFIRENOISE, &mode_2Dfirenoise, _data_FX_MODE_2DFIRENOISE); diff --git a/wled00/FX.h b/wled00/FX.h index fba6a5ec92..2f95291a31 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -179,7 +179,7 @@ #define FX_MODE_TWO_DOTS 50 #define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity) #define FX_MODE_RUNNING_DUAL 52 -// #define FX_MODE_HALLOWEEN 53 // removed in 0.14! +#define FX_MODE_2DANALOGCLOCK 53 // was HALLOWEEN, removed in 0.14! #define FX_MODE_TRICOLOR_CHASE 54 #define FX_MODE_TRICOLOR_WIPE 55 #define FX_MODE_TRICOLOR_FADE 56 @@ -317,9 +317,8 @@ #define FX_MODE_WAVESINS 184 #define FX_MODE_ROCKTAVES 185 #define FX_MODE_2DAKEMI 186 -#define FX_MODE_2DANALOGCLOCK 187 -#define MODE_COUNT 188 +#define MODE_COUNT 187 typedef enum mapping1D2D { M12_Pixels = 0, diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 877d49da64..b262c157d9 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -483,34 +483,6 @@ void Segment::drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, } } -#ifdef WLED_USE_AA_PIXELS -void Segment::drawCircleAntialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) { - if (!isActive() || radius == 0) return; // not active - const uint16_t cols = virtualWidth(); - const uint16_t rows = virtualHeight(); - // Bresenham’s Algorithm - int d = 3 - (2*radius); - int y = radius, x = 0; - while (y >= x) { - setPixelColorXY(((float)cx+x-0.5)/cols, ((float)cy+y-0.5)/rows, col, true); - setPixelColorXY(((float)cx-x+0.5)/cols, ((float)cy+y-0.5)/rows, col, true); - setPixelColorXY(((float)cx+x-0.5)/cols, ((float)cy-y+0.5)/rows, col, true); - setPixelColorXY(((float)cx-x+0.5)/cols, ((float)cy-y+0.5)/rows, col, true); - setPixelColorXY(((float)cx+y-0.5)/cols, ((float)cy+x-0.5)/rows, col, true); - setPixelColorXY(((float)cx-y+0.5)/cols, ((float)cy+x-0.5)/rows, col, true); - setPixelColorXY(((float)cx+y-0.5)/cols, ((float)cy-x+0.5)/rows, col, true); - setPixelColorXY(((float)cx-y+0.5)/cols, ((float)cy-x+0.5)/rows, col, true); - x++; - if (d > 0) { - y--; - d += 4 * (x - y) + 10; - } else { - d += 4 * x + 6; - } - } -} -#endif - // by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs void Segment::fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, bool soft) { if (!isActive() || radius == 0) return; // not active @@ -584,33 +556,6 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3 } } -//line function -void Segment::drawLineAntialiased(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) { - if (!isActive()) return; // not active - const uint16_t cols = virtualWidth(); - const uint16_t rows = virtualHeight(); - if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return; - const int16_t dx = abs(x1-x0), sx = x0= -dx) { - if(x0 == x1) break; - if (e2+dy < ed) setPixelColorXY(x0,y0+sy, color_blend(c,getPixelColorXY(x0,y0+sy), 0xFFFF * (e2+dy)/ed, true)); - err -= dy; x0 += sx; - } - if (e2 <= dy) { - if (y0 == y1) break; - if (dx-e2 < ed) setPixelColorXY(x2+sx, y0, color_blend(c,getPixelColorXY(x2+sx,y0), 0xFFFF * (dx-e2)/ed, true)); - err += dx; y0 += sy; - } - } -} - #include "src/font/console_font_4x6.h" #include "src/font/console_font_5x8.h" #include "src/font/console_font_5x12.h" From d5faa26524de87f71d8ec16a92498df083480bc8 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 13 May 2024 22:14:01 -0400 Subject: [PATCH 11/12] Update the default colors --- wled00/FX.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a5f9d1c51b..75230fdb42 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4874,6 +4874,12 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 const int radius = min(centerX, centerY); const bool soft = radius > 6 && SEGMENT.check2; + if ((SEGENV.call == 0) && (SEGMENT.colors[0] == 0xFFA000) && (SEGMENT.colors[1] == BLACK) && (SEGMENT.colors[2] == BLACK)) { // set up defaults + SEGMENT.colors[0] = RED; + SEGMENT.colors[1] = GREEN; + SEGMENT.colors[2] = BLUE; + } + SEGMENT.fadeToBlackBy(240); SEGMENT.drawCircle(centerX, centerY, radius, DARKGREY, soft); if (radius > 8) SEGMENT.drawCircle(centerX, centerY, radius-1, DARKGREY, soft); // thicker circle From c9c0d7d52415b6eca290738fee0d0ac560258409 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 13 May 2024 22:15:58 -0400 Subject: [PATCH 12/12] Only update those colors that are set to default Note that by default, 0xFFAA00 is ultimately set, not DEFAULT_COLOR (0xFFA000). Probably something to do with brightness. --- wled00/FX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 75230fdb42..ca18881a51 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4874,10 +4874,10 @@ uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi1 const int radius = min(centerX, centerY); const bool soft = radius > 6 && SEGMENT.check2; - if ((SEGENV.call == 0) && (SEGMENT.colors[0] == 0xFFA000) && (SEGMENT.colors[1] == BLACK) && (SEGMENT.colors[2] == BLACK)) { // set up defaults - SEGMENT.colors[0] = RED; - SEGMENT.colors[1] = GREEN; - SEGMENT.colors[2] = BLUE; + if (SEGENV.call == 0) { // set up defaults + if (SEGMENT.colors[0] == DEFAULT_COLOR) SEGMENT.colors[0] = RED; + if (SEGMENT.colors[1] == BLACK) SEGMENT.colors[1] = GREEN; + if (SEGMENT.colors[2] == BLACK) SEGMENT.colors[2] = BLUE; } SEGMENT.fadeToBlackBy(240);