From 039bb091933a9567a675eabf554d55fca0d59747 Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Sat, 7 Feb 2026 22:57:23 +0100 Subject: [PATCH 1/7] ambient leds: remove second loop pass for more consistent cpu time --- workspace/all/common/api.c | 48 +++++++++++++++----------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 2c3b06636..5d4df3f45 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -455,11 +455,14 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he } const uint16_t *pixels = (const uint16_t *)data; - int pixel_count = width * height; + int pixel_count = 0; uint64_t total_r = 0; uint64_t total_g = 0; uint64_t total_b = 0; + uint64_t total_rc = 0; + uint64_t total_gc = 0; + uint64_t total_bc = 0; uint32_t colorful_pixel_count = 0; for (unsigned y = 0; y < height; y++) @@ -480,44 +483,31 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he uint8_t min_c = fminf(fminf(r, g), b); uint8_t saturation = max_c == 0 ? 0 : (max_c - min_c) * 255 / max_c; + total_r += r; + total_g += g; + total_b += b; + pixel_count++; if (saturation > 50 && max_c > 50) { - total_r += r; - total_g += g; - total_b += b; + total_rc += r; + total_gc += g; + total_bc += b; colorful_pixel_count++; } } } - if (colorful_pixel_count == 0) + if (colorful_pixel_count > 0) { - - colorful_pixel_count = pixel_count; - total_r = total_g = total_b = 0; - for (unsigned y = 0; y < height; y++) - { - for (unsigned x = 0; x < width; x++) - { - uint16_t pixel = pixels[y * (pitch / 2) + x]; - uint8_t r = ((pixel & 0xF800) >> 11) << 3; - uint8_t g = ((pixel & 0x07E0) >> 5) << 2; - uint8_t b = (pixel & 0x001F) << 3; - - r |= r >> 5; - g |= g >> 6; - b |= b >> 5; - - total_r += r; - total_g += g; - total_b += b; - } - } + total_r = total_rc; + total_g = total_gc; + total_b = total_bc; + pixel_count = colorful_pixel_count; } - uint8_t avg_r = total_r / colorful_pixel_count; - uint8_t avg_g = total_g / colorful_pixel_count; - uint8_t avg_b = total_b / colorful_pixel_count; + uint8_t avg_r = total_r / pixel_count; + uint8_t avg_g = total_g / pixel_count; + uint8_t avg_b = total_b / pixel_count; return (avg_r << 16) | (avg_g << 8) | avg_b; } From 13f3b7f28348cf1a76b7f633cd3728b13093a62b Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Mon, 9 Feb 2026 14:21:17 +0100 Subject: [PATCH 2/7] ambient leds: do not implicit cast to float for min() or max() --- workspace/all/common/api.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 5d4df3f45..fd70a9fec 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -479,8 +479,14 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he g |= g >> 6; b |= b >> 5; - uint8_t max_c = fmaxf(fmaxf(r, g), b); - uint8_t min_c = fminf(fminf(r, g), b); + // max_c = max(max(r, g), b) + uint8_t max_c = r > g ? r : g; + max_c = max_c > b ? max_c : b; + + // min_c = min(min(r, g), b) + uint8_t min_c = r < g ? r : g; + min_c = min_c < b ? min_c : b; + uint8_t saturation = max_c == 0 ? 0 : (max_c - min_c) * 255 / max_c; total_r += r; From eefe64593f3781c255bc3fe8e6c4004978ae1cb3 Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Mon, 9 Feb 2026 17:30:55 +0100 Subject: [PATCH 3/7] ambient leds: don't sample every pixel, blend result with previous frame to reduce ensuing flicker --- workspace/all/common/api.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index fd70a9fec..850d75d29 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -465,9 +465,9 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he uint64_t total_bc = 0; uint32_t colorful_pixel_count = 0; - for (unsigned y = 0; y < height; y++) + for (unsigned y = 0; y < height; y+=8) { - for (unsigned x = 0; x < width; x++) + for (unsigned x = 0; x < width; x+=8) { uint16_t pixel = pixels[y * (pitch / 2) + x]; @@ -511,11 +511,26 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he pixel_count = colorful_pixel_count; } - uint8_t avg_r = total_r / pixel_count; - uint8_t avg_g = total_g / pixel_count; - uint8_t avg_b = total_b / pixel_count; + uint8_t ambient_r = total_r / pixel_count; + uint8_t ambient_g = total_g / pixel_count; + uint8_t ambient_b = total_b / pixel_count; - return (avg_r << 16) | (avg_g << 8) | avg_b; + // keep track of last invocation's values + // in order to blend them + static uint16_t amb_prev_r = 0; + static uint16_t amb_prev_g = 0; + static uint16_t amb_prev_b = 0; + + uint32_t average_color = (((amb_prev_r + ambient_r) / 2) << 16) | + (((amb_prev_g + ambient_g) / 2) << 8) | + ((amb_prev_b + ambient_b) / 2); + + amb_prev_r = ambient_r; + amb_prev_g = ambient_g; + amb_prev_b = ambient_b; + + //uint32_t retval = + return average_color; } void GFX_setAmbientColor(const void *data, unsigned width, unsigned height, size_t pitch, int mode) From ae0b76abcb60d54fd6b5ff01a2fd9a9bc5b2a352 Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Tue, 10 Feb 2026 16:35:45 +0100 Subject: [PATCH 4/7] ambient leds: move function call to 32bpp area for consistency between RGB565 and RGB888 cores --- workspace/all/common/api.c | 14 +++++--------- workspace/all/minarch/minarch.c | 11 ++++++----- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 850d75d29..a8d2b5108 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -454,7 +454,7 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he return 0; } - const uint16_t *pixels = (const uint16_t *)data; + const uint32_t *pixels = (const uint32_t *)data; int pixel_count = 0; uint64_t total_r = 0; @@ -469,15 +469,11 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he { for (unsigned x = 0; x < width; x+=8) { - uint16_t pixel = pixels[y * (pitch / 2) + x]; + uint32_t pixel = pixels[y * (pitch / 4) + x]; - uint8_t r = ((pixel & 0xF800) >> 11) << 3; - uint8_t g = ((pixel & 0x07E0) >> 5) << 2; - uint8_t b = (pixel & 0x001F) << 3; - - r |= r >> 5; - g |= g >> 6; - b |= b >> 5; + uint8_t r = pixel & 0xFF; + uint8_t g = (pixel >> 8) & 0xFF; + uint8_t b = (pixel >> 16) & 0xFF; // max_c = max(max(r, g), b) uint8_t max_c = r > g ? r : g; diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index 0ce92f1be..1c3240969 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -5928,11 +5928,6 @@ static void video_refresh_callback(const void* data, unsigned width, unsigned he } } - // Set ambient lighting color (if enabled) - if (ambient_mode && !fast_forward && data) { - GFX_setAmbientColor(data, width, height, pitch, ambient_mode); - } - // Handle NULL data by reusing last frame if (!data) { data = lastframe; @@ -5950,6 +5945,12 @@ static void video_refresh_callback(const void* data, unsigned width, unsigned he } pitch = width * sizeof(Uint32); + // Set ambient lighting color (if enabled) + if (ambient_mode && !fast_forward && data) { + GFX_setAmbientColor(data, width, height, pitch, ambient_mode); + } + + // Render the frame video_refresh_callback_main(data, width, height, pitch); } From e67d2b8fae7306f2f6ae3649109ac548eb572588 Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Tue, 10 Feb 2026 16:36:24 +0100 Subject: [PATCH 5/7] ambient leds: downsample to 7x7 instead of 8x8 to de-emphasize negative effects of scrolling 2D tiles --- workspace/all/common/api.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index a8d2b5108..0d1a4f11c 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -465,9 +465,11 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he uint64_t total_bc = 0; uint32_t colorful_pixel_count = 0; - for (unsigned y = 0; y < height; y+=8) + // Downsample 7x7 instead of 8x8 to de-emphasize effect of + // repeated scrolling tiles (intentionally interfere with patterns) + for (unsigned y = 0; y < height; y+=7) { - for (unsigned x = 0; x < width; x+=8) + for (unsigned x = 0; x < width; x+=7) { uint32_t pixel = pixels[y * (pitch / 4) + x]; From 9390908968fe2b226e4ff00c9d06426b4ba326ed Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Tue, 10 Feb 2026 17:34:14 +0100 Subject: [PATCH 6/7] ambient leds: don't override user brightness setting --- workspace/all/common/api.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index 0d1a4f11c..fc1a4838b 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -542,22 +542,18 @@ void GFX_setAmbientColor(const void *data, unsigned width, unsigned height, size { (lightsAmbient)[2].color1 = dominant_color; (lightsAmbient)[2].effect = 4; - (lightsAmbient)[2].brightness = 100; } if (mode == 1 || mode == 3) { (lightsAmbient)[0].color1 = dominant_color; (lightsAmbient)[0].effect = 4; - (lightsAmbient)[0].brightness = 100; (lightsAmbient)[1].color1 = dominant_color; (lightsAmbient)[1].effect = 4; - (lightsAmbient)[1].brightness = 100; } if (mode == 1 || mode == 4 || mode == 5) { (lightsAmbient)[3].color1 = dominant_color; (lightsAmbient)[3].effect = 4; - (lightsAmbient)[3].brightness = 100; } } From 35e2436338575619c3b779d907b743f6278836fb Mon Sep 17 00:00:00 2001 From: "Dr. Flarp" Date: Fri, 13 Feb 2026 07:14:56 -0500 Subject: [PATCH 7/7] ambient leds: comments, cleanup --- workspace/all/common/api.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index fc1a4838b..3d14f58fc 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -460,9 +460,9 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he uint64_t total_r = 0; uint64_t total_g = 0; uint64_t total_b = 0; - uint64_t total_rc = 0; - uint64_t total_gc = 0; - uint64_t total_bc = 0; + uint64_t total_rcolor = 0; + uint64_t total_gcolor = 0; + uint64_t total_bcolor = 0; uint32_t colorful_pixel_count = 0; // Downsample 7x7 instead of 8x8 to de-emphasize effect of @@ -473,6 +473,7 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he { uint32_t pixel = pixels[y * (pitch / 4) + x]; + // input pixel format: AABBGGRR uint8_t r = pixel & 0xFF; uint8_t g = (pixel >> 8) & 0xFF; uint8_t b = (pixel >> 16) & 0xFF; @@ -484,7 +485,7 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he // min_c = min(min(r, g), b) uint8_t min_c = r < g ? r : g; min_c = min_c < b ? min_c : b; - + uint8_t saturation = max_c == 0 ? 0 : (max_c - min_c) * 255 / max_c; total_r += r; @@ -493,9 +494,9 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he pixel_count++; if (saturation > 50 && max_c > 50) { - total_rc += r; - total_gc += g; - total_bc += b; + total_rcolor += r; + total_gcolor += g; + total_bcolor += b; colorful_pixel_count++; } } @@ -503,10 +504,10 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he if (colorful_pixel_count > 0) { - total_r = total_rc; - total_g = total_gc; - total_b = total_bc; - pixel_count = colorful_pixel_count; + total_r = total_rcolor; + total_g = total_gcolor; + total_b = total_bcolor; + pixel_count = colorful_pixel_count; } uint8_t ambient_r = total_r / pixel_count; @@ -518,16 +519,15 @@ uint32_t GFX_extract_average_color(const void *data, unsigned width, unsigned he static uint16_t amb_prev_r = 0; static uint16_t amb_prev_g = 0; static uint16_t amb_prev_b = 0; - + uint32_t average_color = (((amb_prev_r + ambient_r) / 2) << 16) | - (((amb_prev_g + ambient_g) / 2) << 8) | - ((amb_prev_b + ambient_b) / 2); + (((amb_prev_g + ambient_g) / 2) << 8) | + ((amb_prev_b + ambient_b) / 2); amb_prev_r = ambient_r; amb_prev_g = ambient_g; amb_prev_b = ambient_b; - //uint32_t retval = return average_color; }