From 6d927a91f9644a86d8f9a4511f0c9bc0fd84aa13 Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Sun, 2 Nov 2025 20:50:05 -0800 Subject: [PATCH] ports/alif: Add 250ms time limited moving average. The image turning green previously was caused by the rgb stats not being sampled continously (only every 100 frames) coupled with only happening on snapshot. As such, any algorithm causing the fps to slow down would lower the update freq. The new average solution ensures that the rgb average is smoothed over many frames and only keeps the last 250ms of history. --- common/omv_csi.c | 8 ++++++++ ports/alif/omv_csi.c | 22 +++++++++++++++------- ports/alif/omv_portconfig.h | 12 +++++++++--- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/common/omv_csi.c b/common/omv_csi.c index 805d0724c..beaa7cc0c 100644 --- a/common/omv_csi.c +++ b/common/omv_csi.c @@ -65,6 +65,8 @@ #define OMV_CSI_CLK_TOLERANCE (500000) #endif +#define OMV_CSI_RGB_AVG_MAX_MS (250) + #ifndef __weak #define __weak __attribute__((weak)) #endif @@ -322,6 +324,12 @@ __weak int omv_csi_reset(omv_csi_t *csi, bool hard) { NULL, NULL }; + #if defined(OMV_CSI_RGB_AVG_SIZE) + // Setup AWB moving average. + csi->awb_enabled = true; + rgb_moving_average_init(&csi->rgb_avg, OMV_CSI_RGB_AVG_MAX_MS, OMV_CSI_RGB_AVG_SIZE, csi->rgb_avg_buf); + #endif // defined(OMV_CSI_RGB_AVG_SIZE) + // Restore shutdown state on reset. if (!csi->power_on) { omv_csi_shutdown(csi, false); diff --git a/ports/alif/omv_csi.c b/ports/alif/omv_csi.c index 5907a34c7..3b392abde 100644 --- a/ports/alif/omv_csi.c +++ b/ports/alif/omv_csi.c @@ -48,6 +48,7 @@ #include "omv_gpu.h" #include "omv_i2c.h" #include "omv_csi.h" +#include "average.h" #include "unaligned_memcpy.h" // Bits missing from cpi.h @@ -230,10 +231,7 @@ static uint32_t omv_csi_get_fb_offset(omv_csi_t *csi) { int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) { CPI_Type *cpi = csi->base; framebuffer_t *fb = csi->fb; - vbuffer_t *buffer = NULL; - static uint32_t frames = 0; - static uint32_t r_stat, gb_stat, gr_stat, b_stat; // Configure and re/start the capture if it's not alrady active // and there are no pending buffers (from non-blocking capture). @@ -390,13 +388,23 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) { // Set the target pixel format before debayer. dst_image->pixfmt = fb->pixfmt; - // Update AWB stats every n frames. - if ((frames++ % 100) == 0) { - omv_csi_ioctl(csi, OMV_CSI_IOCTL_GET_RGB_STATS, &r_stat, &gb_stat, &gr_stat, &b_stat); + uint32_t r_stat, g_stat, b_stat; + if (csi->awb_enabled) { + uint32_t gb_stat, gr_stat; + int ret = omv_csi_ioctl(csi, OMV_CSI_IOCTL_GET_RGB_STATS, &r_stat, &gb_stat, &gr_stat, &b_stat); + + if (ret != 0) { + return ret; + } + + g_stat = (gb_stat + gr_stat) / 2; + rgb_moving_average_update(&csi->rgb_avg, &r_stat, &g_stat, &b_stat, mp_hal_ticks_ms()); + } else { + rgb_moving_average_get(&csi->rgb_avg, &r_stat, &g_stat, &b_stat); } // Debayer frame. - imlib_debayer_image_awb(dst_image, &src_image, false, r_stat, (gb_stat + gr_stat) / 2, b_stat); + imlib_debayer_image_awb(dst_image, &src_image, false, r_stat, g_stat, b_stat); } return 0; } diff --git a/ports/alif/omv_portconfig.h b/ports/alif/omv_portconfig.h index 122190db5..c45058675 100644 --- a/ports/alif/omv_portconfig.h +++ b/ports/alif/omv_portconfig.h @@ -34,6 +34,7 @@ #define __OMV_PORTCONFIG_H__ #include +#include "average.h" #include "clk.h" #include "i2c.h" #include "i3c.h" @@ -137,9 +138,14 @@ struct { \ uint8_t datasize; \ }; -#define OMV_CSI_PORT_BITS \ - struct { \ - CPI_Type *base; \ +#define OMV_CSI_RGB_AVG_SIZE (60) + +#define OMV_CSI_PORT_BITS \ + struct { \ + CPI_Type *base; \ + bool awb_enabled; \ + rgb_moving_average_t rgb_avg; \ + rgb_moving_average_val_t rgb_avg_buf[OMV_CSI_RGB_AVG_SIZE]; \ }; #endif // __OMV_PORTCONFIG_H__