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 "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 OV5640_SLV_ADDR (0x78)
|
||||
#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).
|
||||
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.
|
||||
int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags);
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "frogeye2020.h"
|
||||
#include "gc2145.h"
|
||||
#include "framebuffer.h"
|
||||
#include "unaligned_memcpy.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include "omv_gpio.h"
|
||||
#include "omv_i2c.h"
|
||||
@ -1249,6 +1250,85 @@ __weak int sensor_auto_crop_framebuffer() {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Implement per line, per pixel cropping, and image transposing (for image rotation) in
|
||||
// in software using the CPU to transfer the image from the line buffers to the frame buffer.
|
||||
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;
|
||||
}
|
||||
// Copy line to frame buffer.
|
||||
sensor_copy_line(NULL, src, dst);
|
||||
}
|
||||
|
||||
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)
|
||||
static void mdma_memcpy(vbuffer_t *buffer, 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
|
||||
// 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;
|
||||
int sensor_dma_memcpy(void *dma, void *dst, void *src, int bpp, bool transposed) {
|
||||
MDMA_HandleTypeDef *handle = dma;
|
||||
|
||||
// Drop the frame if MDMA is not keeping up as the image will be corrupt.
|
||||
if (handle->Instance->CCR & MDMA_CCR_EN) {
|
||||
sensor.drop_frame = true;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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,
|
||||
transposed ? bpp : (MAIN_FB()->u * bpp),
|
||||
transposed ? MAIN_FB()->u : 1);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -564,68 +562,14 @@ void DCMI_DMAConvCpltUser(uint32_t addr) {
|
||||
dst += bytes_per_pixel * buffer->offset++;
|
||||
}
|
||||
|
||||
// Implement per line, per pixel cropping, and image transposing (for image rotation) in
|
||||
// in software using the CPU to transfer the image from the line buffers to the frame buffer.
|
||||
uint16_t *src16 = (uint16_t *) src;
|
||||
uint16_t *dst16 = (uint16_t *) dst;
|
||||
|
||||
switch (sensor.pixformat) {
|
||||
case PIXFORMAT_BAYER:
|
||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
||||
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)
|
||||
// We're using two handles to give each channel the maximum amount of time possible to do the line
|
||||
// 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.
|
||||
sensor_copy_line((buffer->offset % 2) ? &DCMI_MDMA_Handle1 : &DCMI_MDMA_Handle0, src, dst);
|
||||
#else
|
||||
sensor_copy_line(NULL, src, dst);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(OMV_MDMA_CHANNEL_DCMI_0)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user