mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
ports/all: Refactor frame buffer line copying code.
This commit is contained in:
parent
27161405b4
commit
345b80358d
@ -14,18 +14,6 @@
|
|||||||
#include "omv_i2c.h"
|
#include "omv_i2c.h"
|
||||||
#include "imlib.h"
|
#include "imlib.h"
|
||||||
|
|
||||||
#define copy_transposed_line(dstp, srcp) \
|
|
||||||
for (int i = MAIN_FB()->u, h = MAIN_FB()->v; i; i--) { \
|
|
||||||
*dstp = *srcp++; \
|
|
||||||
dstp += h; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define copy_transposed_line_rev16(dstp, srcp) \
|
|
||||||
for (int i = MAIN_FB()->u, h = MAIN_FB()->v; i; i--) { \
|
|
||||||
*dstp = __REV16(*srcp++); \
|
|
||||||
dstp += h; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define OV2640_SLV_ADDR (0x60)
|
#define OV2640_SLV_ADDR (0x60)
|
||||||
#define OV5640_SLV_ADDR (0x78)
|
#define OV5640_SLV_ADDR (0x78)
|
||||||
#define OV7725_SLV_ADDR (0x42)
|
#define OV7725_SLV_ADDR (0x42)
|
||||||
@ -484,6 +472,10 @@ int sensor_check_framebuffer_size();
|
|||||||
// Auto-crop frame buffer until it fits in RAM (may switch pixel format to BAYER).
|
// Auto-crop frame buffer until it fits in RAM (may switch pixel format to BAYER).
|
||||||
int sensor_auto_crop_framebuffer();
|
int sensor_auto_crop_framebuffer();
|
||||||
|
|
||||||
|
// Copy a single line buffer to its destination. The copying process is
|
||||||
|
// DMA-accelerated, if available, and falls back to slow software if not.
|
||||||
|
int sensor_copy_line(void *dma, uint8_t *src, uint8_t *dst);
|
||||||
|
|
||||||
// Default snapshot function.
|
// Default snapshot function.
|
||||||
int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags);
|
int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags);
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#include "frogeye2020.h"
|
#include "frogeye2020.h"
|
||||||
#include "gc2145.h"
|
#include "gc2145.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
|
#include "unaligned_memcpy.h"
|
||||||
#include "omv_boardconfig.h"
|
#include "omv_boardconfig.h"
|
||||||
#include "omv_gpio.h"
|
#include "omv_gpio.h"
|
||||||
#include "omv_i2c.h"
|
#include "omv_i2c.h"
|
||||||
@ -1249,6 +1250,85 @@ __weak int sensor_auto_crop_framebuffer() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define copy_transposed_line(dstp, srcp) \
|
||||||
|
for (int i = MAIN_FB()->u, h = MAIN_FB()->v; i; i--) { \
|
||||||
|
*dstp = *srcp++; \
|
||||||
|
dstp += h; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define copy_transposed_line_rev16(dstp, srcp) \
|
||||||
|
for (int i = MAIN_FB()->u, h = MAIN_FB()->v; i; i--) { \
|
||||||
|
*dstp = __REV16(*srcp++); \
|
||||||
|
dstp += h; \
|
||||||
|
}
|
||||||
|
|
||||||
|
__weak int sensor_copy_line(void *dma, uint8_t *src, uint8_t *dst) {
|
||||||
|
uint16_t *src16 = (uint16_t *) src;
|
||||||
|
uint16_t *dst16 = (uint16_t *) dst;
|
||||||
|
#if OMA_ENABLE_DMA_MEMCPY
|
||||||
|
extern int sensor_dma_memcpy(void *dma, void *dst, void *src, int bpp, bool transposed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (sensor.pixformat) {
|
||||||
|
case PIXFORMAT_BAYER:
|
||||||
|
#if OMA_ENABLE_DMA_MEMCPY
|
||||||
|
sensor_dma_memcpy(dma, dst, src, sizeof(uint8_t), sensor.transpose);
|
||||||
|
#else
|
||||||
|
if (!sensor.transpose) {
|
||||||
|
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
||||||
|
} else {
|
||||||
|
copy_transposed_line(dst, src);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case PIXFORMAT_GRAYSCALE:
|
||||||
|
#if OMA_ENABLE_DMA_MEMCPY
|
||||||
|
sensor_dma_memcpy(dma, dst, src, sizeof(uint8_t), sensor.transpose);
|
||||||
|
#else
|
||||||
|
if (sensor.hw_flags.gs_bpp == 1) {
|
||||||
|
// 1BPP GRAYSCALE.
|
||||||
|
if (!sensor.transpose) {
|
||||||
|
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
||||||
|
} else {
|
||||||
|
copy_transposed_line(dst, src);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Extract Y channel from YUV.
|
||||||
|
if (!sensor.transpose) {
|
||||||
|
unaligned_2_to_1_memcpy(dst, src16, MAIN_FB()->u);
|
||||||
|
} else {
|
||||||
|
copy_transposed_line(dst, src16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case PIXFORMAT_RGB565:
|
||||||
|
case PIXFORMAT_YUV422:
|
||||||
|
#if OMA_ENABLE_DMA_MEMCPY
|
||||||
|
sensor_dma_memcpy(dma, dst16, src16, sizeof(uint16_t), sensor.transpose);
|
||||||
|
#else
|
||||||
|
if ((sensor.pixformat == PIXFORMAT_RGB565 && sensor.hw_flags.rgb_swap)
|
||||||
|
|| (sensor.pixformat == PIXFORMAT_YUV422 && sensor.hw_flags.yuv_swap)) {
|
||||||
|
if (!sensor.transpose) {
|
||||||
|
unaligned_memcpy_rev16(dst16, src16, MAIN_FB()->u);
|
||||||
|
} else {
|
||||||
|
copy_transposed_line_rev16(dst16, src16);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!sensor.transpose) {
|
||||||
|
unaligned_memcpy(dst16, src16, MAIN_FB()->u * sizeof(uint16_t));
|
||||||
|
} else {
|
||||||
|
copy_transposed_line(dst16, src16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
__weak int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) {
|
__weak int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -272,68 +272,8 @@ void sensor_line_callback(uint32_t addr) {
|
|||||||
dst += MAIN_FB()->u * bytes_per_pixel * (buffer->offset - MAIN_FB()->y);
|
dst += MAIN_FB()->u * bytes_per_pixel * (buffer->offset - MAIN_FB()->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement per line, per pixel cropping, and image transposing (for image rotation) in
|
// Copy line to frame buffer.
|
||||||
// in software using the CPU to transfer the image from the line buffers to the frame buffer.
|
sensor_copy_line(NULL, src, dst);
|
||||||
uint16_t *src16 = (uint16_t *) src;
|
|
||||||
uint16_t *dst16 = (uint16_t *) dst;
|
|
||||||
|
|
||||||
switch (sensor.pixformat) {
|
|
||||||
case PIXFORMAT_BAYER:
|
|
||||||
#if (OMV_ENABLE_SENSOR_EDMA == 1)
|
|
||||||
edma_memcpy(buffer, dst, src, sizeof(uint8_t), sensor.transpose);
|
|
||||||
#else
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst, src);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case PIXFORMAT_GRAYSCALE:
|
|
||||||
#if (OMV_ENABLE_SENSOR_EDMA == 1)
|
|
||||||
edma_memcpy(buffer, dst, src, sizeof(uint8_t), sensor.transpose);
|
|
||||||
#else
|
|
||||||
if (sensor.hw_flags.gs_bpp == 1) {
|
|
||||||
// 1BPP GRAYSCALE.
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst, src);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Extract Y channel from YUV.
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_2_to_1_memcpy(dst, src16, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst, src16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case PIXFORMAT_RGB565:
|
|
||||||
case PIXFORMAT_YUV422:
|
|
||||||
#if (OMV_ENABLE_SENSOR_EDMA == 1)
|
|
||||||
edma_memcpy(buffer, dst16, src16, sizeof(uint16_t), sensor.transpose);
|
|
||||||
#else
|
|
||||||
if ((sensor.pixformat == PIXFORMAT_RGB565 && sensor.hw_flags.rgb_swap)
|
|
||||||
|| (sensor.pixformat == PIXFORMAT_YUV422 && sensor.hw_flags.yuv_swap)) {
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy_rev16(dst16, src16, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line_rev16(dst16, src16);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy(dst16, src16, MAIN_FB()->u * sizeof(uint16_t));
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst16, src16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++buffer->offset == resolution[sensor.framesize][1]) {
|
if (++buffer->offset == resolution[sensor.framesize][1]) {
|
||||||
|
|||||||
@ -418,16 +418,13 @@ void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
||||||
static void mdma_memcpy(vbuffer_t *buffer, void *dst, void *src, int bpp, bool transposed) {
|
int sensor_dma_memcpy(void *dma, void *dst, void *src, int bpp, bool transposed) {
|
||||||
// We're using two handles to give each channel the maximum amount of time possible to do the line
|
MDMA_HandleTypeDef *handle = dma;
|
||||||
// transfer. In most situations only one channel will be running at a time. However, if SDRAM is
|
|
||||||
// backedup we don't have to disable the channel if it is flushing trailing data to SDRAM.
|
|
||||||
MDMA_HandleTypeDef *handle = (buffer->offset % 2) ? &DCMI_MDMA_Handle1 : &DCMI_MDMA_Handle0;
|
|
||||||
|
|
||||||
// Drop the frame if MDMA is not keeping up as the image will be corrupt.
|
// Drop the frame if MDMA is not keeping up as the image will be corrupt.
|
||||||
if (handle->Instance->CCR & MDMA_CCR_EN) {
|
if (handle->Instance->CCR & MDMA_CCR_EN) {
|
||||||
sensor.drop_frame = true;
|
sensor.drop_frame = true;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If MDMA is still running from a previous transfer HAL_MDMA_Start() will disable that transfer
|
// If MDMA is still running from a previous transfer HAL_MDMA_Start() will disable that transfer
|
||||||
@ -439,6 +436,7 @@ static void mdma_memcpy(vbuffer_t *buffer, void *dst, void *src, int bpp, bool t
|
|||||||
(uint32_t) dst,
|
(uint32_t) dst,
|
||||||
transposed ? bpp : (MAIN_FB()->u * bpp),
|
transposed ? bpp : (MAIN_FB()->u * bpp),
|
||||||
transposed ? MAIN_FB()->u : 1);
|
transposed ? MAIN_FB()->u : 1);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -564,68 +562,14 @@ void DCMI_DMAConvCpltUser(uint32_t addr) {
|
|||||||
dst += bytes_per_pixel * buffer->offset++;
|
dst += bytes_per_pixel * buffer->offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement per line, per pixel cropping, and image transposing (for image rotation) in
|
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
||||||
// in software using the CPU to transfer the image from the line buffers to the frame buffer.
|
// We're using two handles to give each channel the maximum amount of time possible to do the line
|
||||||
uint16_t *src16 = (uint16_t *) src;
|
// transfer. In most situations only one channel will be running at a time. However, if SDRAM is
|
||||||
uint16_t *dst16 = (uint16_t *) dst;
|
// backedup we don't have to disable the channel if it is flushing trailing data to SDRAM.
|
||||||
|
sensor_copy_line((buffer->offset % 2) ? &DCMI_MDMA_Handle1 : &DCMI_MDMA_Handle0, src, dst);
|
||||||
switch (sensor.pixformat) {
|
#else
|
||||||
case PIXFORMAT_BAYER:
|
sensor_copy_line(NULL, src, dst);
|
||||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
#endif
|
||||||
mdma_memcpy(buffer, dst, src, sizeof(uint8_t), sensor.transpose);
|
|
||||||
#else
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst, src);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case PIXFORMAT_GRAYSCALE:
|
|
||||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
|
||||||
mdma_memcpy(buffer, dst, src, sizeof(uint8_t), sensor.transpose);
|
|
||||||
#else
|
|
||||||
if (sensor.hw_flags.gs_bpp == 1) {
|
|
||||||
// 1BPP GRAYSCALE.
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst, src);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Extract Y channel from YUV.
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_2_to_1_memcpy(dst, src16, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst, src16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case PIXFORMAT_RGB565:
|
|
||||||
case PIXFORMAT_YUV422:
|
|
||||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
|
||||||
mdma_memcpy(buffer, dst16, src16, sizeof(uint16_t), sensor.transpose);
|
|
||||||
#else
|
|
||||||
if ((sensor.pixformat == PIXFORMAT_RGB565 && sensor.hw_flags.rgb_swap)
|
|
||||||
|| (sensor.pixformat == PIXFORMAT_YUV422 && sensor.hw_flags.yuv_swap)) {
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy_rev16(dst16, src16, MAIN_FB()->u);
|
|
||||||
} else {
|
|
||||||
copy_transposed_line_rev16(dst16, src16);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!sensor.transpose) {
|
|
||||||
unaligned_memcpy(dst16, src16, MAIN_FB()->u * sizeof(uint16_t));
|
|
||||||
} else {
|
|
||||||
copy_transposed_line(dst16, src16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user