mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
ports/rp2: Refactor framebuffer API to accept a context.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
parent
a421777d42
commit
5b412cf953
@ -30,7 +30,6 @@
|
|||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "omv_i2c.h"
|
#include "omv_i2c.h"
|
||||||
#include "omv_csi.h"
|
#include "omv_csi.h"
|
||||||
#include "framebuffer.h"
|
|
||||||
|
|
||||||
#include "pico/time.h"
|
#include "pico/time.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
@ -42,9 +41,6 @@
|
|||||||
#include "unaligned_memcpy.h"
|
#include "unaligned_memcpy.h"
|
||||||
#include "dcmi.pio.h"
|
#include "dcmi.pio.h"
|
||||||
|
|
||||||
// Sensor struct.
|
|
||||||
omv_csi_t csi = {};
|
|
||||||
|
|
||||||
static void dma_irq_handler();
|
static void dma_irq_handler();
|
||||||
extern void __fatal_error(const char *msg);
|
extern void __fatal_error(const char *msg);
|
||||||
|
|
||||||
@ -101,8 +97,10 @@ int omv_csi_init() {
|
|||||||
// Reset the csi state
|
// Reset the csi state
|
||||||
memset(&csi, 0, sizeof(omv_csi_t));
|
memset(&csi, 0, sizeof(omv_csi_t));
|
||||||
|
|
||||||
|
// Set default framebuffer
|
||||||
|
csi.fb = framebuffer_get(0);
|
||||||
|
|
||||||
// Set default snapshot function.
|
// Set default snapshot function.
|
||||||
// Some sensors need to call snapshot from init.
|
|
||||||
csi.snapshot = omv_csi_snapshot;
|
csi.snapshot = omv_csi_snapshot;
|
||||||
|
|
||||||
// Configure the csi external clock (XCLK).
|
// Configure the csi external clock (XCLK).
|
||||||
@ -152,7 +150,7 @@ int omv_csi_init() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int omv_csi_abort(bool fifo_flush, bool in_irq) {
|
int omv_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) {
|
||||||
// Disable DMA channel
|
// Disable DMA channel
|
||||||
dma_channel_abort(OMV_CSI_DMA_CHANNEL);
|
dma_channel_abort(OMV_CSI_DMA_CHANNEL);
|
||||||
dma_irqn_set_channel_enabled(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL, false);
|
dma_irqn_set_channel_enabled(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL, false);
|
||||||
@ -161,8 +159,10 @@ int omv_csi_abort(bool fifo_flush, bool in_irq) {
|
|||||||
pio_sm_set_enabled(OMV_CSI_PIO, OMV_CSI_SM, false);
|
pio_sm_set_enabled(OMV_CSI_PIO, OMV_CSI_SM, false);
|
||||||
pio_sm_clear_fifos(OMV_CSI_PIO, OMV_CSI_SM);
|
pio_sm_clear_fifos(OMV_CSI_PIO, OMV_CSI_SM);
|
||||||
|
|
||||||
// Clear bpp flag.
|
if (csi->fb) {
|
||||||
MAIN_FB()->pixfmt = PIXFORMAT_INVALID;
|
// Clear bpp flag.
|
||||||
|
csi->fb->pixfmt = PIXFORMAT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -197,12 +197,14 @@ int omv_csi_set_windowing(int x, int y, int w, int h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dma_irq_handler() {
|
static void dma_irq_handler() {
|
||||||
|
framebuffer_t *fb = csi.fb;
|
||||||
|
|
||||||
if (dma_irqn_get_channel_status(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL)) {
|
if (dma_irqn_get_channel_status(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL)) {
|
||||||
// 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_NO_FLAGS);
|
framebuffer_get_tail(fb, FB_NO_FLAGS);
|
||||||
vbuffer_t *buffer = framebuffer_get_tail(FB_PEEK);
|
vbuffer_t *buffer = framebuffer_get_tail(fb, FB_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);
|
||||||
@ -210,69 +212,71 @@ static void dma_irq_handler() {
|
|||||||
// Unblock the state machine
|
// Unblock the state machine
|
||||||
pio_sm_restart(OMV_CSI_PIO, OMV_CSI_SM);
|
pio_sm_restart(OMV_CSI_PIO, OMV_CSI_SM);
|
||||||
pio_sm_clear_fifos(OMV_CSI_PIO, OMV_CSI_SM);
|
pio_sm_clear_fifos(OMV_CSI_PIO, OMV_CSI_SM);
|
||||||
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (MAIN_FB()->v - 1));
|
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (fb->v - 1));
|
||||||
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (MAIN_FB()->u * MAIN_FB()->bpp) - 1);
|
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (fb->u * fb->bpp) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||||
|
framebuffer_t *fb = csi->fb;
|
||||||
|
|
||||||
// Compress the framebuffer for the IDE preview.
|
// Compress the framebuffer for the IDE preview.
|
||||||
framebuffer_update_jpeg_buffer();
|
framebuffer_update_jpeg_buffer(fb);
|
||||||
|
|
||||||
if (omv_csi_check_framebuffer_size() != 0) {
|
if (omv_csi_check_framebuffer_size() != 0) {
|
||||||
return OMV_CSI_ERROR_FRAMEBUFFER_OVERFLOW;
|
return OMV_CSI_ERROR_FRAMEBUFFER_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the current FB head.
|
// Free the current FB head.
|
||||||
framebuffer_free_current_buffer();
|
framebuffer_free_current_buffer(fb);
|
||||||
|
|
||||||
// Set framebuffer pixel format.
|
// Set framebuffer pixel format.
|
||||||
if (csi->pixformat == PIXFORMAT_INVALID) {
|
if (csi->pixformat == PIXFORMAT_INVALID) {
|
||||||
return OMV_CSI_ERROR_INVALID_PIXFORMAT;
|
return OMV_CSI_ERROR_INVALID_PIXFORMAT;
|
||||||
}
|
}
|
||||||
MAIN_FB()->pixfmt = csi->pixformat;
|
fb->pixfmt = csi->pixformat;
|
||||||
|
|
||||||
vbuffer_t *buffer = framebuffer_get_head(FB_NO_FLAGS);
|
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 (buffer == NULL && !dma_channel_is_busy(OMV_CSI_DMA_CHANNEL)) {
|
||||||
framebuffer_setup_buffers();
|
framebuffer_setup_buffers(fb);
|
||||||
|
|
||||||
buffer = framebuffer_get_tail(FB_PEEK);
|
buffer = framebuffer_get_tail(fb, FB_PEEK);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return OMV_CSI_ERROR_FRAMEBUFFER_ERROR;
|
return OMV_CSI_ERROR_FRAMEBUFFER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the DMA on the first frame, for later frames only the write is changed.
|
// Configure the DMA on the first frame, for later frames only the write is changed.
|
||||||
omv_csi_dma_config(MAIN_FB()->u, MAIN_FB()->v, MAIN_FB()->bpp,
|
omv_csi_dma_config(fb->u, fb->v, fb->bpp,
|
||||||
(void *) buffer->data, (csi->rgb_swap && MAIN_FB()->bpp == 2));
|
(void *) buffer->data,
|
||||||
|
(csi->rgb_swap && fb->bpp == 2));
|
||||||
|
|
||||||
// Re-enable the state machine.
|
// Re-enable the state machine.
|
||||||
pio_sm_clear_fifos(OMV_CSI_PIO, OMV_CSI_SM);
|
pio_sm_clear_fifos(OMV_CSI_PIO, OMV_CSI_SM);
|
||||||
pio_sm_set_enabled(OMV_CSI_PIO, OMV_CSI_SM, true);
|
pio_sm_set_enabled(OMV_CSI_PIO, OMV_CSI_SM, true);
|
||||||
|
|
||||||
// Unblock the state machine
|
// Unblock the state machine
|
||||||
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (MAIN_FB()->v - 1));
|
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (fb->v - 1));
|
||||||
pio_sm_put_blocking(OMV_CSI_PIO, OMV_CSI_SM, (MAIN_FB()->u * MAIN_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.
|
// Wait for the DMA to finish the transfer.
|
||||||
for (mp_uint_t ticks = mp_hal_ticks_ms(); buffer == NULL;) {
|
for (mp_uint_t ticks = mp_hal_ticks_ms(); buffer == NULL;) {
|
||||||
buffer = framebuffer_get_head(FB_NO_FLAGS);
|
buffer = framebuffer_get_head(fb, FB_NO_FLAGS);
|
||||||
if ((mp_hal_ticks_ms() - ticks) > 3000) {
|
if ((mp_hal_ticks_ms() - ticks) > 3000) {
|
||||||
omv_csi_abort(true, false);
|
omv_csi_abort(csi, true, false);
|
||||||
return OMV_CSI_ERROR_CAPTURE_TIMEOUT;
|
return OMV_CSI_ERROR_CAPTURE_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MAIN_FB()->w = MAIN_FB()->u;
|
fb->w = fb->u;
|
||||||
MAIN_FB()->h = MAIN_FB()->v;
|
fb->h = fb->v;
|
||||||
|
|
||||||
// Set the user image.
|
// Set the user image.
|
||||||
framebuffer_init_image(image);
|
framebuffer_init_image(fb, image);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user