From 785e943f05418b690c455b3f88e80d9167ba3cbc Mon Sep 17 00:00:00 2001 From: "Kwabena W. Agyeman" Date: Wed, 21 Oct 2020 06:39:01 -0700 Subject: [PATCH] Fix RGB565 Inversion from camera --- src/omv/ov2640.c | 1 + src/omv/ov2640_regs.h | 2 +- src/omv/ov5640.c | 3 ++- src/omv/ov7690.c | 1 + src/omv/ov7725.c | 1 + src/omv/ov9650.c | 1 + src/omv/sensor.c | 42 ++++++++++++++++++++++++++++++++++++++---- src/omv/sensor.h | 1 + 8 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/omv/ov2640.c b/src/omv/ov2640.c index 6f1ac18e9..a6cddc766 100644 --- a/src/omv/ov2640.c +++ b/src/omv/ov2640.c @@ -854,6 +854,7 @@ int ov2640_init(sensor_t *sensor) SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 1); + SENSOR_HW_FLAGS_SET(sensor, SWNSOR_HW_FLAGS_RGB565_REV, 0); return 0; } diff --git a/src/omv/ov2640_regs.h b/src/omv/ov2640_regs.h index 2aa3a6263..44b973515 100644 --- a/src/omv/ov2640_regs.h +++ b/src/omv/ov2640_regs.h @@ -75,7 +75,7 @@ #define IMAGE_MODE_JPEG_EN 0x10 #define IMAGE_MODE_YUV422 0x00 #define IMAGE_MODE_RAW10 0x04 -#define IMAGE_MODE_RGB565 0x08 +#define IMAGE_MODE_RGB565 0x09 #define IMAGE_MODE_HREF_VSYNC 0x02 #define IMAGE_MODE_LBYTE_FIRST 0x01 #define IMAGE_MODE_GET_FMT(x) ((x)&0xC) diff --git a/src/omv/ov5640.c b/src/omv/ov5640.c index f7551d203..998c8cc3f 100644 --- a/src/omv/ov5640.c +++ b/src/omv/ov5640.c @@ -483,7 +483,7 @@ static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) ret |= cambus_writeb2(&sensor->i2c, sensor->slv_addr, FORMAT_CONTROL_MUX, 0x00); break; case PIXFORMAT_RGB565: - ret |= cambus_writeb2(&sensor->i2c, sensor->slv_addr, FORMAT_CONTROL, 0x61); + ret |= cambus_writeb2(&sensor->i2c, sensor->slv_addr, FORMAT_CONTROL, 0x6F); ret |= cambus_writeb2(&sensor->i2c, sensor->slv_addr, FORMAT_CONTROL_MUX, 0x01); break; case PIXFORMAT_YUV422: @@ -1030,6 +1030,7 @@ int ov5640_init(sensor_t *sensor) SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 1); + SENSOR_HW_FLAGS_SET(sensor, SWNSOR_HW_FLAGS_RGB565_REV, 0); return 0; } diff --git a/src/omv/ov7690.c b/src/omv/ov7690.c index 8e8affdc1..2c5d3b5d0 100644 --- a/src/omv/ov7690.c +++ b/src/omv/ov7690.c @@ -622,6 +622,7 @@ int ov7690_init(sensor_t *sensor) SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 0); + SENSOR_HW_FLAGS_SET(sensor, SWNSOR_HW_FLAGS_RGB565_REV, 1); return 0; } diff --git a/src/omv/ov7725.c b/src/omv/ov7725.c index 6818383aa..c0633f038 100644 --- a/src/omv/ov7725.c +++ b/src/omv/ov7725.c @@ -622,6 +622,7 @@ int ov7725_init(sensor_t *sensor) SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 0); + SENSOR_HW_FLAGS_SET(sensor, SWNSOR_HW_FLAGS_RGB565_REV, 1); return 0; } diff --git a/src/omv/ov9650.c b/src/omv/ov9650.c index 8b11ef29a..3ca783334 100644 --- a/src/omv/ov9650.c +++ b/src/omv/ov9650.c @@ -538,6 +538,7 @@ int ov9650_init(sensor_t *sensor) SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 1); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 0); SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 0); + SENSOR_HW_FLAGS_SET(sensor, SWNSOR_HW_FLAGS_RGB565_REV, 1); return 0; } diff --git a/src/omv/sensor.c b/src/omv/sensor.c index bb1904958..11ce20a5b 100644 --- a/src/omv/sensor.c +++ b/src/omv/sensor.c @@ -1103,6 +1103,29 @@ void *unaligned_memcpy(void *dest, void *src, size_t n) #endif } +// ARM Cortex-M4/M7 Processors can access memory using unaligned 32-bit reads/writes. +void *unaligned_memcpy_rev16(void *dest, void *src, size_t n) +{ + uint32_t *dest32 = (uint32_t *) dest; + uint32_t *src32 = (uint32_t *) src; + +// TODO: Make this faster using only 32-bit aligned reads/writes with data shifting. +#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) || defined(MCU_SERIES_H7) + for (; n > 2; n -= 2) { + *dest32++ = __REV16(*src32++); + } +#endif + + uint16_t *dest16 = (uint16_t *) dest32; + uint16_t *src16 = (uint16_t *) src32; + + for (; n > 0; n -= 1) { + *dest16++ = __REV16(*src16++); + } + + return dest; +} + // Stop allowing new data in on the end of the frame and let snapshot know that the frame has been // received. Note that DCMI_DMAConvCpltUser() is called before DCMI_IT_FRAME is enabled by // DCMI_DMAXferCplt() so this means that the last line of data is *always* transferred before @@ -1207,7 +1230,11 @@ void DCMI_DMAConvCpltUser(uint32_t addr) case PIXFORMAT_RGB565: dst16 += (offset - MAIN_FB()->y) * MAIN_FB()->w; src16 += MAIN_FB()->x; - unaligned_memcpy(dst16, src16, MAIN_FB()->w * sizeof(uint16_t)); + if (SENSOR_HW_FLAGS_GET(&sensor, SWNSOR_HW_FLAGS_RGB565_REV)) { + unaligned_memcpy_rev16(dst16, src16, MAIN_FB()->w); + } else { + unaligned_memcpy(dst16, src16, MAIN_FB()->w * sizeof(uint16_t)); + } break; default: break; @@ -1244,9 +1271,16 @@ void DCMI_DMAConvCpltUser(uint32_t addr) case PIXFORMAT_RGB565: dst16 += offset - MAIN_FB()->y; src16 += MAIN_FB()->x; - for (int i = MAIN_FB()->w, h = MAIN_FB()->h; i; i--) { - *dst16 = *src16++; - dst16 += h; + if (SENSOR_HW_FLAGS_GET(&sensor, SWNSOR_HW_FLAGS_RGB565_REV)) { + for (int i = MAIN_FB()->w, h = MAIN_FB()->h; i; i--) { + *dst16 = __REV16(*src16++); + dst16 += h; + } + } else { + for (int i = MAIN_FB()->w, h = MAIN_FB()->h; i; i--) { + *dst16 = *src16++; + dst16 += h; + } } break; default: diff --git a/src/omv/sensor.h b/src/omv/sensor.h index 08dd3f656..d68872ba9 100644 --- a/src/omv/sensor.h +++ b/src/omv/sensor.h @@ -139,6 +139,7 @@ typedef enum { #define SENSOR_HW_FLAGS_PIXCK (2) // pixel clock edge. #define SENSOR_HW_FLAGS_FSYNC (3) // hardware frame sync. #define SENSOR_HW_FLAGS_JPEGE (4) // hardware JPEG encoder. +#define SWNSOR_HW_FLAGS_RGB565_REV (5) // byte reverse rgb565. #define SENSOR_HW_FLAGS_GET(s, x) ((s)->hw_flags & (1<hw_flags |= (v<hw_flags &= ~(1<