diff --git a/src/omv/common/sensor.h b/src/omv/common/sensor.h index 3c9873479..d279b720b 100644 --- a/src/omv/common/sensor.h +++ b/src/omv/common/sensor.h @@ -454,6 +454,9 @@ bool sensor_get_auto_rotation(); // Set the number of virtual frame buffers. int sensor_set_framebuffers(int count); +// Drop the next frame to match the current frame rate. +void sensor_throttle_framerate(); + // Set special digital effects (SDE). int sensor_set_special_effect(sde_t sde); diff --git a/src/omv/common/sensor_utils.c b/src/omv/common/sensor_utils.c index 9cb61273f..37f918c7e 100644 --- a/src/omv/common/sensor_utils.c +++ b/src/omv/common/sensor_utils.c @@ -666,6 +666,25 @@ __weak int sensor_set_framerate(int framerate) { return 0; } +__weak void sensor_throttle_framerate() { + if (!sensor.first_line) { + sensor.first_line = true; + uint32_t tick = mp_hal_ticks_ms(); + uint32_t framerate_ms = IM_DIV(1000, sensor.framerate); + + if (sensor.last_frame_ms_valid && ((tick - sensor.last_frame_ms) < framerate_ms)) { + // Drop the current frame to match the requested frame rate. Note that if the frame + // is marked to be dropped, it should not be copied to SRAM/SDRAM to save CPU time. + sensor.drop_frame = true; + } else if (sensor.last_frame_ms_valid) { + sensor.last_frame_ms += framerate_ms; + } else { + sensor.last_frame_ms = tick; + sensor.last_frame_ms_valid = true; + } + } +} + __weak bool sensor_get_cropped() { if (sensor.framesize != FRAMESIZE_INVALID) { return (MAIN_FB()->x != 0) // should be zero if not cropped. @@ -676,7 +695,6 @@ __weak bool sensor_get_cropped() { return false; } - __weak uint32_t sensor_get_src_bpp() { switch (sensor.pixformat) { case PIXFORMAT_GRAYSCALE: @@ -1231,6 +1249,10 @@ __weak int sensor_auto_crop_framebuffer() { return 0; } +__weak int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) { + return -1; +} + const char *sensor_strerror(int error) { static const char *sensor_errors[] = { "No error.", @@ -1265,8 +1287,4 @@ const char *sensor_strerror(int error) { return sensor_errors[error]; } } - -__weak int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) { - return -1; -} #endif //MICROPY_PY_SENSOR diff --git a/src/omv/ports/mimxrt/sensor.c b/src/omv/ports/mimxrt/sensor.c index c33f549c7..e043a774d 100644 --- a/src/omv/ports/mimxrt/sensor.c +++ b/src/omv/ports/mimxrt/sensor.c @@ -188,23 +188,8 @@ void sensor_sof_callback() { } void sensor_line_callback(uint32_t addr) { - if (!sensor.first_line) { - sensor.first_line = true; - uint32_t tick = mp_hal_ticks_ms(); - uint32_t framerate_ms = IM_DIV(1000, sensor.framerate); - - // Drops frames to match the frame rate requested by the user. The frame is NOT copied to - // SRAM/SDRAM when dropping to save CPU cycles/energy that would be wasted. - // If framerate is zero then this does nothing... - if (sensor.last_frame_ms_valid && ((tick - sensor.last_frame_ms) < framerate_ms)) { - sensor.drop_frame = true; - } else if (sensor.last_frame_ms_valid) { - sensor.last_frame_ms += framerate_ms; - } else { - sensor.last_frame_ms = tick; - sensor.last_frame_ms_valid = true; - } - } + // Throttle frames to match the current frame rate. + sensor_throttle_framerate(); // Get current framebuffer. vbuffer_t *buffer = framebuffer_get_tail(FB_PEEK); diff --git a/src/omv/ports/stm32/sensor.c b/src/omv/ports/stm32/sensor.c index 0c6851bb2..b2df2b335 100644 --- a/src/omv/ports/stm32/sensor.c +++ b/src/omv/ports/stm32/sensor.c @@ -442,27 +442,11 @@ static void mdma_memcpy(vbuffer_t *buffer, void *dst, void *src, int bpp, bool t } #endif -// This function is called back after each line transfer is complete, -// with a pointer to the line buffer that was used. At this point the -// DMA transfers the next line to the other half of the line buffer. +// This function is called back after each line transfer is complete, with a pointer to the +// buffer that was used. At this point the DMA transfers the next line to the next buffer. void DCMI_DMAConvCpltUser(uint32_t addr) { - if (!sensor.first_line) { - sensor.first_line = true; - uint32_t tick = HAL_GetTick(); - uint32_t framerate_ms = IM_DIV(1000, sensor.framerate); - - // Drops frames to match the frame rate requested by the user. The frame is NOT copied to - // SRAM/SDRAM when dropping to save CPU cycles/energy that would be wasted. - // If framerate is zero then this does nothing... - if (sensor.last_frame_ms_valid && ((tick - sensor.last_frame_ms) < framerate_ms)) { - sensor.drop_frame = true; - } else if (sensor.last_frame_ms_valid) { - sensor.last_frame_ms += framerate_ms; - } else { - sensor.last_frame_ms = tick; - sensor.last_frame_ms_valid = true; - } - } + // Throttle frames to match the current frame rate. + sensor_throttle_framerate(); if (sensor.drop_frame) { // If we're dropping a frame in full offload mode it's safe to disable this interrupt saving