diff --git a/common/omv_csi.c b/common/omv_csi.c index 92eed9178..c8ec0fa57 100644 --- a/common/omv_csi.c +++ b/common/omv_csi.c @@ -60,6 +60,7 @@ #include "frogeye2020.h" #include "gc2145.h" #include "genx320.h" +#include "softcsi.h" #include "framebuffer.h" #include "unaligned_memcpy.h" @@ -370,7 +371,12 @@ int omv_csi_probe_init(uint32_t bus_id, uint32_t bus_speed) { csi.reset_pol = OMV_CSI_ACTIVE_LOW; #endif } else { + #if (OMV_SOFTCSI_ENABLE == 1) + csi.slv_addr = SOFTCSI_SLV_ADDR; + csi.chip_id = SOFTCSI_ID; + #else return OMV_CSI_ERROR_ISC_UNDETECTED; + #endif } } } @@ -547,6 +553,12 @@ int omv_csi_probe_init(uint32_t bus_id, uint32_t bus_speed) { break; #endif // (OMV_FROGEYE2020_ENABLE == 1) + #if (OMV_SOFTCSI_ENABLE == 1) + case SOFTCSI_ID: + init_ret = softcsi_init(&csi); + break; + #endif // (OMV_SOFTCSI_ENABLE == 1) + default: return OMV_CSI_ERROR_ISC_UNSUPPORTED; break; diff --git a/common/omv_csi.h b/common/omv_csi.h index b4759b742..08f6a84df 100644 --- a/common/omv_csi.h +++ b/common/omv_csi.h @@ -49,6 +49,7 @@ #define FROGEYE2020_SLV_ADDR (0x6E) #define PAG7920_SLV_ADDR (0x80) #define PAG7936_SLV_ADDR (0x80) +#define SOFTCSI_SLV_ADDR (0x7f) // Chip ID Registers #define OV5640_CHIP_ID (0x300A) @@ -92,6 +93,7 @@ #define PAG7936_ID (0x7936) #define PAJ6100_ID (0x6100) #define FROGEYE2020_ID (0x2020) +#define SOFTCSI_ID (0x50F7) #define OMV_CSI_TIMEOUT_MS (3000) diff --git a/drivers/drivers.mk b/drivers/drivers.mk index 51093b419..f3c7953bd 100644 --- a/drivers/drivers.mk +++ b/drivers/drivers.mk @@ -204,6 +204,7 @@ DRIVER_SRC_C += $(addprefix sensors/, \ pag7920.c \ pag7936.c \ paj6100.c \ + softcsi.c \ ) CFLAGS += -I$(TOP_DIR)/drivers/sensors diff --git a/drivers/sensors/softcsi.c b/drivers/sensors/softcsi.c new file mode 100644 index 000000000..7d5f74396 --- /dev/null +++ b/drivers/sensors/softcsi.c @@ -0,0 +1,137 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright (C) 2025 OpenMV, LLC. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Virtual image sensor. + */ +#include "omv_boardconfig.h" +#if (OMV_SOFTCSI_ENABLE == 1) + +#include +#include "omv_csi.h" +#include "vospi.h" +#include "py/mphal.h" +#include "omv_common.h" +#include "omv_gpio.h" +#include "omv_i2c.h" +#include "framebuffer.h" + +static int reset(omv_csi_t *csi) { + return 0; +} + +static int set_pixformat(omv_csi_t *csi, pixformat_t pixformat) { + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_GRAYSCALE: + return 0; + default: + return -1; + } +} + +static int set_framesize(omv_csi_t *csi, omv_csi_framesize_t framesize) { + return 0; +} + +static int snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { + if (!image) { + return 0; + } + + framebuffer_update_jpeg_buffer(); + + if (MAIN_FB()->n_buffers != 1) { + framebuffer_set_buffers(1); + } + + if (csi->pixformat == PIXFORMAT_INVALID) { + return OMV_CSI_ERROR_INVALID_PIXFORMAT; + } + + if (csi->framesize == OMV_CSI_FRAMESIZE_INVALID) { + return OMV_CSI_ERROR_INVALID_FRAMESIZE; + } + + if (omv_csi_check_framebuffer_size(csi) == -1) { + return OMV_CSI_ERROR_FRAMEBUFFER_OVERFLOW; + } + + framebuffer_free_current_buffer(); + vbuffer_t *buffer = framebuffer_get_tail(FB_NO_FLAGS); + + if (!buffer) { + return OMV_CSI_ERROR_FRAMEBUFFER_ERROR; + } + + MAIN_FB()->w = MAIN_FB()->u; + MAIN_FB()->h = MAIN_FB()->v; + MAIN_FB()->pixfmt = csi->pixformat; + + framebuffer_init_image(image); + + static uint32_t step = 0; + uint32_t offset = (step / 4); + + for (size_t y = 0; y < image->h; y++) { + for (size_t x = 0; x < image->w; x++) { + switch (csi->pixformat) { + case PIXFORMAT_GRAYSCALE: { + // Checkerboard: periodic every 16 pixels, scrolls horizontally + uint8_t value = ((((x + offset) / 16) + (y / 16)) % 2) ? 0xFF : 0x00; + IMAGE_PUT_GRAYSCALE_PIXEL(image, x, y, value); + break; + } + case PIXFORMAT_RGB565: { + // Make red/blue periodic with smooth wrap using modulo + uint8_t r = (((x + offset) % image->w) * 31) / (image->w - 1); + uint8_t g = (y * 63) / (image->h - 1); + uint8_t b = (((((x + offset) % image->w) ^ y) * 31) / (image->w + image->h - 2)); + uint16_t pixel = COLOR_R5_G6_B5_TO_RGB565(r, g, b); + IMAGE_PUT_RGB565_PIXEL(image, x, y, pixel); + break; + } + default: + break; + } + } + } + + step++; + return 0; +} + +int softcsi_init(omv_csi_t *csi) { + csi->reset = reset; + csi->snapshot = snapshot; + csi->set_pixformat = set_pixformat; + csi->set_framesize = set_framesize; + + csi->vsync_pol = 1; + csi->hsync_pol = 0; + csi->pixck_pol = 0; + csi->frame_sync = 0; + csi->mono_bpp = 1; + + return 0; +} +#endif // (OMV_SOFTCSI_ENABLE == 1) diff --git a/drivers/sensors/softcsi.h b/drivers/sensors/softcsi.h new file mode 100644 index 000000000..bfb557a10 --- /dev/null +++ b/drivers/sensors/softcsi.h @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright (C) 2025 OpenMV, LLC. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Virtual image sensor. + */ +#ifndef __SOFTCSI_H__ +#define __SOFTCSI_H__ +#define OMV_SOFTCSI_CLK_FREQ (24000000) +int softcsi_init(omv_csi_t *csi); +#endif // __SOFTCSI_H__