ports/rp2: Use the new framebuffer API.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
iabdalkader 2025-07-21 15:04:06 +02:00
parent 63ac8e7c64
commit e91878bd7e
3 changed files with 31 additions and 34 deletions

View File

@ -51,8 +51,10 @@ static void dma_irq_handler() {
// Clear the interrupt request. // Clear the interrupt request.
dma_irqn_acknowledge_channel(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL); dma_irqn_acknowledge_channel(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL);
framebuffer_get_tail(fb, FB_NO_FLAGS); // Release the current buffer and acquire a new one.
vbuffer_t *buffer = framebuffer_get_tail(fb, FB_PEEK); framebuffer_release(fb, FB_FLAG_FREE | FB_FLAG_CHECK_LAST);
vbuffer_t *buffer = framebuffer_acquire(fb, FB_FLAG_FREE | FB_FLAG_PEEK);
if (buffer != NULL) { if (buffer != NULL) {
// Set next buffer and retrigger the DMA channel. // Set next buffer and retrigger the DMA channel.
dma_channel_set_write_addr(OMV_CSI_DMA_CHANNEL, buffer->data, true); dma_channel_set_write_addr(OMV_CSI_DMA_CHANNEL, buffer->data, true);
@ -66,6 +68,10 @@ static void dma_irq_handler() {
} }
} }
static bool rp2_csi_is_active(omv_csi_t *csi) {
return dma_channel_is_busy(OMV_CSI_DMA_CHANNEL);
}
static int rp2_csi_config(omv_csi_t *csi, omv_csi_config_t config) { static int rp2_csi_config(omv_csi_t *csi, omv_csi_config_t config) {
if (config == OMV_CSI_CONFIG_INIT) { if (config == OMV_CSI_CONFIG_INIT) {
// PIXCLK // PIXCLK
@ -153,37 +159,14 @@ int omv_csi_set_windowing(omv_csi_t *csi, int x, int y, int w, int h) {
} }
static int rp2_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) { static int rp2_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
vbuffer_t *buffer = NULL;
framebuffer_t *fb = csi->fb; framebuffer_t *fb = csi->fb;
// Compress the framebuffer for the IDE preview.
if (flags & OMV_CSI_CAPTURE_FLAGS_UPDATE) {
image_t tmp;
framebuffer_init_image(fb, &tmp);
framebuffer_update_jpeg_buffer(&tmp);
}
if (omv_csi_check_framebuffer_size(csi) != 0) {
return OMV_CSI_ERROR_FRAMEBUFFER_OVERFLOW;
}
// Free the current FB head.
framebuffer_free_current_buffer(fb);
// Set framebuffer pixel format.
if (csi->pixformat == PIXFORMAT_INVALID) {
return OMV_CSI_ERROR_INVALID_PIXFORMAT;
}
fb->pixfmt = csi->pixformat;
vbuffer_t *buffer = framebuffer_get_head(fb, FB_NO_FLAGS);
// If there's no ready buffer in the fifo, and the DMA is Not currently // If there's no ready buffer in the fifo, and the DMA is Not currently
// transferring a new buffer, reconfigure and restart the DMA transfer. // transferring a new buffer, reconfigure and restart the DMA transfer.
if (buffer == NULL && !dma_channel_is_busy(OMV_CSI_DMA_CHANNEL)) { if (!rp2_csi_is_active(csi) && !framebuffer_readable(fb)) {
framebuffer_setup_buffers(fb); // Acquire a buffer from the free queue.
if (!(buffer = framebuffer_acquire(fb, FB_FLAG_FREE | FB_FLAG_PEEK))) {
buffer = framebuffer_get_tail(fb, FB_PEEK);
if (buffer == NULL) {
return OMV_CSI_ERROR_FRAMEBUFFER_ERROR; return OMV_CSI_ERROR_FRAMEBUFFER_ERROR;
} }
@ -216,17 +199,30 @@ static int rp2_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (fb->u * fb->bpp) - 1); pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (fb->u * fb->bpp) - 1);
} }
// Wait for the DMA to finish the transfer. // One shot DMA transfers must be invalidated.
for (mp_uint_t ticks = mp_hal_ticks_ms(); buffer == NULL;) { framebuffer_flags_t fb_flags = FB_FLAG_USED | FB_FLAG_PEEK | FB_FLAG_INVALIDATE;
buffer = framebuffer_get_head(fb, FB_NO_FLAGS);
if ((mp_hal_ticks_ms() - ticks) > 3000) { // Wait for a frame to be ready.
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_event_handle_nowait()) {
if ((buffer = framebuffer_acquire(fb, fb_flags))) {
break;
}
if (flags & OMV_CSI_CAPTURE_FLAGS_NBLOCK) {
return OMV_CSI_ERROR_WOULD_BLOCK;
}
if ((mp_hal_ticks_ms() - start) > OMV_CSI_TIMEOUT_MS) {
omv_csi_abort(csi, true, false); omv_csi_abort(csi, true, false);
return OMV_CSI_ERROR_CAPTURE_TIMEOUT; return OMV_CSI_ERROR_CAPTURE_TIMEOUT;
} }
} }
// Set the framebuffer width/height.
fb->w = fb->u; fb->w = fb->u;
fb->h = fb->v; fb->h = fb->v;
// Set the framebuffer pixel format.
fb->pixfmt = csi->pixformat;
// Set the user image. // Set the user image.
framebuffer_init_image(fb, image); framebuffer_init_image(fb, image);

View File

@ -122,6 +122,7 @@ target_sources(${MICROPY_TARGET} PRIVATE
${TOP_DIR}/common/umm_malloc.c ${TOP_DIR}/common/umm_malloc.c
${TOP_DIR}/common/dma_alloc.c ${TOP_DIR}/common/dma_alloc.c
${TOP_DIR}/common/unaligned_memcpy.c ${TOP_DIR}/common/unaligned_memcpy.c
${TOP_DIR}/common/queue.c
${TOP_DIR}/drivers/sensors/ov2640.c ${TOP_DIR}/drivers/sensors/ov2640.c
${TOP_DIR}/drivers/sensors/ov5640.c ${TOP_DIR}/drivers/sensors/ov5640.c

View File

@ -28,7 +28,7 @@ export CXX=
# Note this overrides USER_C_MODULES. # Note this overrides USER_C_MODULES.
MPY_MKARGS += BOARD=$(TARGET) BUILD=$(BUILD)/rp2 USER_C_MODULES="" \ MPY_MKARGS += BOARD=$(TARGET) BUILD=$(BUILD)/rp2 USER_C_MODULES="" \
OMV_CMAKE=$(TOP_DIR)/$(OMV_DIR)/ports/$(PORT)/omv_portconfig.cmake OMV_CMAKE=$(TOP_DIR)/ports/$(PORT)/omv_portconfig.cmake
################################################### ###################################################
all: $(OPENMV) all: $(OPENMV)