mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
common: Add the framebuffer instance to csi struct.
This commit is contained in:
parent
3d90961c21
commit
f468c12f74
124
common/omv_csi.c
124
common/omv_csi.c
@ -128,6 +128,8 @@ uint16_t resolution[][2] = {
|
|||||||
{2592, 1944}, /* WQXGA2 */
|
{2592, 1944}, /* WQXGA2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
omv_csi_t csi = {0};
|
||||||
|
|
||||||
__weak void omv_csi_init0() {
|
__weak void omv_csi_init0() {
|
||||||
// Reset the csi state
|
// Reset the csi state
|
||||||
memset(&csi, 0, sizeof(omv_csi_t));
|
memset(&csi, 0, sizeof(omv_csi_t));
|
||||||
@ -198,13 +200,13 @@ __weak int omv_csi_reset() {
|
|||||||
omv_i2c_enable(&csi.i2c_bus, true);
|
omv_i2c_enable(&csi.i2c_bus, true);
|
||||||
|
|
||||||
// Call csi-specific reset function
|
// Call csi-specific reset function
|
||||||
if (csi.reset != NULL
|
if (csi.reset != NULL &&
|
||||||
&& csi.reset(&csi) != 0) {
|
csi.reset(&csi) != 0) {
|
||||||
return OMV_CSI_ERROR_CTL_FAILED;
|
return OMV_CSI_ERROR_CTL_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset framebuffers
|
// Reset framebuffers
|
||||||
framebuffer_flush_buffers(true);
|
framebuffer_flush_buffers(csi.fb, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -671,11 +673,11 @@ __weak int omv_csi_set_pixformat(pixformat_t pixformat) {
|
|||||||
// Some sensor drivers automatically switch to BAYER to reduce the frame size if it does not fit in RAM.
|
// Some sensor drivers automatically switch to BAYER to reduce the frame size if it does not fit in RAM.
|
||||||
// If the current format is BAYER (1BPP), and the target format is color and (2BPP), and the frame does not
|
// If the current format is BAYER (1BPP), and the target format is color and (2BPP), and the frame does not
|
||||||
// fit in RAM it will just be switched back again to BAYER, so we keep the current format unchanged.
|
// fit in RAM it will just be switched back again to BAYER, so we keep the current format unchanged.
|
||||||
uint32_t size = framebuffer_get_buffer_size();
|
uint32_t size = framebuffer_get_buffer_size(csi.fb);
|
||||||
if ((csi.pixformat == PIXFORMAT_BAYER) &&
|
if ((csi.pixformat == PIXFORMAT_BAYER) &&
|
||||||
((pixformat == PIXFORMAT_RGB565) || (pixformat == PIXFORMAT_YUV422)) &&
|
((pixformat == PIXFORMAT_RGB565) || (pixformat == PIXFORMAT_YUV422)) &&
|
||||||
(MAIN_FB()->u * MAIN_FB()->v * 2 > size) &&
|
(csi.fb->u * csi.fb->v * 2 > size) &&
|
||||||
(MAIN_FB()->u * MAIN_FB()->v * 1 <= size)) {
|
(csi.fb->u * csi.fb->v * 1 <= size)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,7 +691,7 @@ __weak int omv_csi_set_pixformat(pixformat_t pixformat) {
|
|||||||
omv_csi_abort(true, false);
|
omv_csi_abort(true, false);
|
||||||
|
|
||||||
// Flush previous frame.
|
// Flush previous frame.
|
||||||
framebuffer_update_jpeg_buffer();
|
framebuffer_update_jpeg_buffer(csi.fb);
|
||||||
|
|
||||||
// Check if the control is supported.
|
// Check if the control is supported.
|
||||||
if (csi.set_pixformat == NULL) {
|
if (csi.set_pixformat == NULL) {
|
||||||
@ -709,7 +711,7 @@ __weak int omv_csi_set_pixformat(pixformat_t pixformat) {
|
|||||||
csi.pixformat = pixformat;
|
csi.pixformat = pixformat;
|
||||||
|
|
||||||
// Reset pixel format to skip the first frame.
|
// Reset pixel format to skip the first frame.
|
||||||
MAIN_FB()->pixfmt = PIXFORMAT_INVALID;
|
csi.fb->pixfmt = PIXFORMAT_INVALID;
|
||||||
|
|
||||||
// Auto-adjust the number of frame buffers.
|
// Auto-adjust the number of frame buffers.
|
||||||
omv_csi_set_framebuffers(-1);
|
omv_csi_set_framebuffers(-1);
|
||||||
@ -728,7 +730,7 @@ __weak int omv_csi_set_framesize(omv_csi_framesize_t framesize) {
|
|||||||
omv_csi_abort(true, false);
|
omv_csi_abort(true, false);
|
||||||
|
|
||||||
// Flush previous frame.
|
// Flush previous frame.
|
||||||
framebuffer_update_jpeg_buffer();
|
framebuffer_update_jpeg_buffer(csi.fb);
|
||||||
|
|
||||||
// Call the sensor specific function
|
// Call the sensor specific function
|
||||||
if (csi.set_framesize == NULL) {
|
if (csi.set_framesize == NULL) {
|
||||||
@ -747,16 +749,16 @@ __weak int omv_csi_set_framesize(omv_csi_framesize_t framesize) {
|
|||||||
csi.framesize = framesize;
|
csi.framesize = framesize;
|
||||||
|
|
||||||
// Set x and y offsets.
|
// Set x and y offsets.
|
||||||
MAIN_FB()->x = 0;
|
csi.fb->x = 0;
|
||||||
MAIN_FB()->y = 0;
|
csi.fb->y = 0;
|
||||||
// Set width and height.
|
// Set width and height.
|
||||||
MAIN_FB()->w = resolution[framesize][0];
|
csi.fb->w = resolution[framesize][0];
|
||||||
MAIN_FB()->h = resolution[framesize][1];
|
csi.fb->h = resolution[framesize][1];
|
||||||
// Set backup width and height.
|
// Set backup width and height.
|
||||||
MAIN_FB()->u = resolution[framesize][0];
|
csi.fb->u = resolution[framesize][0];
|
||||||
MAIN_FB()->v = resolution[framesize][1];
|
csi.fb->v = resolution[framesize][1];
|
||||||
// Reset pixel format to skip the first frame.
|
// Reset pixel format to skip the first frame.
|
||||||
MAIN_FB()->pixfmt = PIXFORMAT_INVALID;
|
csi.fb->pixfmt = PIXFORMAT_INVALID;
|
||||||
|
|
||||||
// Auto-adjust the number of frame buffers.
|
// Auto-adjust the number of frame buffers.
|
||||||
omv_csi_set_framebuffers(-1);
|
omv_csi_set_framebuffers(-1);
|
||||||
@ -776,8 +778,8 @@ __weak int omv_csi_set_framerate(int framerate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the csi implements framerate control use it.
|
// If the csi implements framerate control use it.
|
||||||
if (csi.set_framerate != NULL
|
if (csi.set_framerate != NULL &&
|
||||||
&& csi.set_framerate(&csi, framerate) != 0) {
|
csi.set_framerate(&csi, framerate) != 0) {
|
||||||
return OMV_CSI_ERROR_CTL_FAILED;
|
return OMV_CSI_ERROR_CTL_FAILED;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise use software framerate control.
|
// Otherwise use software framerate control.
|
||||||
@ -807,10 +809,10 @@ __weak void omv_csi_throttle_framerate() {
|
|||||||
|
|
||||||
__weak bool omv_csi_get_cropped() {
|
__weak bool omv_csi_get_cropped() {
|
||||||
if (csi.framesize != OMV_CSI_FRAMESIZE_INVALID) {
|
if (csi.framesize != OMV_CSI_FRAMESIZE_INVALID) {
|
||||||
return (MAIN_FB()->x != 0) ||
|
return (csi.fb->x != 0) ||
|
||||||
(MAIN_FB()->y != 0) ||
|
(csi.fb->y != 0) ||
|
||||||
(MAIN_FB()->u != resolution[csi.framesize][0]) ||
|
(csi.fb->u != resolution[csi.framesize][0]) ||
|
||||||
(MAIN_FB()->v != resolution[csi.framesize][1]);
|
(csi.fb->v != resolution[csi.framesize][1]);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -848,8 +850,8 @@ __weak uint32_t omv_csi_get_dst_bpp() {
|
|||||||
|
|
||||||
__weak int omv_csi_set_windowing(int x, int y, int w, int h) {
|
__weak int omv_csi_set_windowing(int x, int y, int w, int h) {
|
||||||
// Check if the value has changed.
|
// Check if the value has changed.
|
||||||
if ((MAIN_FB()->x == x) && (MAIN_FB()->y == y) &&
|
if ((csi.fb->x == x) && (csi.fb->y == y) &&
|
||||||
(MAIN_FB()->u == w) && (MAIN_FB()->v == h)) {
|
(csi.fb->u == w) && (csi.fb->v == h)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,19 +863,19 @@ __weak int omv_csi_set_windowing(int x, int y, int w, int h) {
|
|||||||
omv_csi_abort(true, false);
|
omv_csi_abort(true, false);
|
||||||
|
|
||||||
// Flush previous frame.
|
// Flush previous frame.
|
||||||
framebuffer_update_jpeg_buffer();
|
framebuffer_update_jpeg_buffer(csi.fb);
|
||||||
|
|
||||||
// Set x and y offsets.
|
// Set x and y offsets.
|
||||||
MAIN_FB()->x = x;
|
csi.fb->x = x;
|
||||||
MAIN_FB()->y = y;
|
csi.fb->y = y;
|
||||||
// Set width and height.
|
// Set width and height.
|
||||||
MAIN_FB()->w = w;
|
csi.fb->w = w;
|
||||||
MAIN_FB()->h = h;
|
csi.fb->h = h;
|
||||||
// Set backup width and height.
|
// Set backup width and height.
|
||||||
MAIN_FB()->u = w;
|
csi.fb->u = w;
|
||||||
MAIN_FB()->v = h;
|
csi.fb->v = h;
|
||||||
// Reset pixel format to skip the first frame.
|
// Reset pixel format to skip the first frame.
|
||||||
MAIN_FB()->pixfmt = PIXFORMAT_INVALID;
|
csi.fb->pixfmt = PIXFORMAT_INVALID;
|
||||||
|
|
||||||
// Auto-adjust the number of frame buffers.
|
// Auto-adjust the number of frame buffers.
|
||||||
omv_csi_set_framebuffers(-1);
|
omv_csi_set_framebuffers(-1);
|
||||||
@ -1205,7 +1207,7 @@ __weak int omv_csi_set_framebuffers(int count) {
|
|||||||
omv_csi_abort(true, false);
|
omv_csi_abort(true, false);
|
||||||
|
|
||||||
// Flush previous frame.
|
// Flush previous frame.
|
||||||
framebuffer_update_jpeg_buffer();
|
framebuffer_update_jpeg_buffer(csi.fb);
|
||||||
|
|
||||||
if (csi.pixformat == PIXFORMAT_INVALID) {
|
if (csi.pixformat == PIXFORMAT_INVALID) {
|
||||||
return OMV_CSI_ERROR_INVALID_PIXFORMAT;
|
return OMV_CSI_ERROR_INVALID_PIXFORMAT;
|
||||||
@ -1217,12 +1219,12 @@ __weak int omv_csi_set_framebuffers(int count) {
|
|||||||
|
|
||||||
#if OMV_CSI_HW_CROP_ENABLE
|
#if OMV_CSI_HW_CROP_ENABLE
|
||||||
// If hardware cropping is supported, use window size.
|
// If hardware cropping is supported, use window size.
|
||||||
MAIN_FB()->frame_size = MAIN_FB()->u * MAIN_FB()->v * 2;
|
csi.fb->frame_size = csi.fb->u * csi.fb->v * 2;
|
||||||
#else
|
#else
|
||||||
// Otherwise, use the real frame size.
|
// Otherwise, use the real frame size.
|
||||||
MAIN_FB()->frame_size = resolution[csi.framesize][0] * resolution[csi.framesize][1] * 2;
|
csi.fb->frame_size = resolution[csi.framesize][0] * resolution[csi.framesize][1] * 2;
|
||||||
#endif
|
#endif
|
||||||
return framebuffer_set_buffers(count);
|
return framebuffer_set_buffers(csi.fb, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak int omv_csi_set_special_effect(omv_csi_sde_t sde) {
|
__weak int omv_csi_set_special_effect(omv_csi_sde_t sde) {
|
||||||
@ -1302,21 +1304,21 @@ __weak const uint16_t *omv_csi_get_color_palette() {
|
|||||||
|
|
||||||
__weak int omv_csi_check_framebuffer_size() {
|
__weak int omv_csi_check_framebuffer_size() {
|
||||||
uint32_t bpp = omv_csi_get_dst_bpp();
|
uint32_t bpp = omv_csi_get_dst_bpp();
|
||||||
uint32_t size = framebuffer_get_buffer_size();
|
uint32_t size = framebuffer_get_buffer_size(csi.fb);
|
||||||
return (((MAIN_FB()->u * MAIN_FB()->v * bpp) <= size) ? 0 : -1);
|
return (((csi.fb->u * csi.fb->v * bpp) <= size) ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak int omv_csi_auto_crop_framebuffer() {
|
__weak int omv_csi_auto_crop_framebuffer() {
|
||||||
uint32_t bpp = omv_csi_get_dst_bpp();
|
uint32_t bpp = omv_csi_get_dst_bpp();
|
||||||
uint32_t size = framebuffer_get_buffer_size();
|
uint32_t size = framebuffer_get_buffer_size(csi.fb);
|
||||||
|
|
||||||
// If the pixformat is NULL/JPEG there we can't do anything to check if it fits before hand.
|
// If the pixformat is NULL/JPEG there we can't do anything to check if it fits before hand.
|
||||||
if (!bpp) {
|
if (!bpp) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAIN_FB() fits, we are done.
|
// csi.fb fits, we are done.
|
||||||
if ((MAIN_FB()->u * MAIN_FB()->v * bpp) <= size) {
|
if ((csi.fb->u * csi.fb->v * bpp) <= size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1325,14 +1327,14 @@ __weak int omv_csi_auto_crop_framebuffer() {
|
|||||||
omv_csi_set_pixformat(PIXFORMAT_BAYER);
|
omv_csi_set_pixformat(PIXFORMAT_BAYER);
|
||||||
bpp = 1;
|
bpp = 1;
|
||||||
|
|
||||||
// MAIN_FB() fits, we are done (bpp is 1).
|
// csi.fb fits, we are done (bpp is 1).
|
||||||
if ((MAIN_FB()->u * MAIN_FB()->v) <= size) {
|
if ((csi.fb->u * csi.fb->v) <= size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int window_w = MAIN_FB()->u;
|
int window_w = csi.fb->u;
|
||||||
int window_h = MAIN_FB()->v;
|
int window_h = csi.fb->v;
|
||||||
|
|
||||||
// We need to shrink the frame buffer. We can do this by cropping. So, we will subtract columns
|
// We need to shrink the frame buffer. We can do this by cropping. So, we will subtract columns
|
||||||
// and rows from the frame buffer until it fits within the frame buffer.
|
// and rows from the frame buffer until it fits within the frame buffer.
|
||||||
@ -1373,20 +1375,20 @@ __weak int omv_csi_auto_crop_framebuffer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crop the frame buffer while keeping the aspect ratio and keeping the width/height even.
|
// Crop the frame buffer while keeping the aspect ratio and keeping the width/height even.
|
||||||
while (((MAIN_FB()->u * MAIN_FB()->v * bpp) > size) || (MAIN_FB()->u % 2) || (MAIN_FB()->v % 2)) {
|
while (((csi.fb->u * csi.fb->v * bpp) > size) || (csi.fb->u % 2) || (csi.fb->v % 2)) {
|
||||||
MAIN_FB()->u -= u_sub;
|
csi.fb->u -= u_sub;
|
||||||
MAIN_FB()->v -= v_sub;
|
csi.fb->v -= v_sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Center the new window using the previous offset and keep the offset even.
|
// Center the new window using the previous offset and keep the offset even.
|
||||||
MAIN_FB()->x += (window_w - MAIN_FB()->u) / 2;
|
csi.fb->x += (window_w - csi.fb->u) / 2;
|
||||||
MAIN_FB()->y += (window_h - MAIN_FB()->v) / 2;
|
csi.fb->y += (window_h - csi.fb->v) / 2;
|
||||||
|
|
||||||
if (MAIN_FB()->x % 2) {
|
if (csi.fb->x % 2) {
|
||||||
MAIN_FB()->x -= 1;
|
csi.fb->x -= 1;
|
||||||
}
|
}
|
||||||
if (MAIN_FB()->y % 2) {
|
if (csi.fb->y % 2) {
|
||||||
MAIN_FB()->y -= 1;
|
csi.fb->y -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-adjust the number of frame buffers.
|
// Auto-adjust the number of frame buffers.
|
||||||
@ -1395,13 +1397,13 @@ __weak int omv_csi_auto_crop_framebuffer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define copy_transposed_line(dstp, srcp) \
|
#define copy_transposed_line(dstp, srcp) \
|
||||||
for (int i = MAIN_FB()->u, h = MAIN_FB()->v; i; i--) { \
|
for (int i = csi.fb->u, h = csi.fb->v; i; i--) { \
|
||||||
*dstp = *srcp++; \
|
*dstp = *srcp++; \
|
||||||
dstp += h; \
|
dstp += h; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define copy_transposed_line_rev16(dstp, srcp) \
|
#define copy_transposed_line_rev16(dstp, srcp) \
|
||||||
for (int i = MAIN_FB()->u, h = MAIN_FB()->v; i; i--) { \
|
for (int i = csi.fb->u, h = csi.fb->v; i; i--) { \
|
||||||
*dstp = __REV16(*srcp++); \
|
*dstp = __REV16(*srcp++); \
|
||||||
dstp += h; \
|
dstp += h; \
|
||||||
}
|
}
|
||||||
@ -1421,7 +1423,7 @@ __weak int omv_csi_copy_line(void *dma, uint8_t *src, uint8_t *dst) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!csi.transpose) {
|
if (!csi.transpose) {
|
||||||
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
unaligned_memcpy(dst, src, csi.fb->u);
|
||||||
} else {
|
} else {
|
||||||
copy_transposed_line(dst, src);
|
copy_transposed_line(dst, src);
|
||||||
}
|
}
|
||||||
@ -1435,14 +1437,14 @@ __weak int omv_csi_copy_line(void *dma, uint8_t *src, uint8_t *dst) {
|
|||||||
if (csi.mono_bpp == 1) {
|
if (csi.mono_bpp == 1) {
|
||||||
// 1BPP GRAYSCALE.
|
// 1BPP GRAYSCALE.
|
||||||
if (!csi.transpose) {
|
if (!csi.transpose) {
|
||||||
unaligned_memcpy(dst, src, MAIN_FB()->u);
|
unaligned_memcpy(dst, src, csi.fb->u);
|
||||||
} else {
|
} else {
|
||||||
copy_transposed_line(dst, src);
|
copy_transposed_line(dst, src);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Extract Y channel from YUV.
|
// Extract Y channel from YUV.
|
||||||
if (!csi.transpose) {
|
if (!csi.transpose) {
|
||||||
unaligned_2_to_1_memcpy(dst, src16, MAIN_FB()->u);
|
unaligned_2_to_1_memcpy(dst, src16, csi.fb->u);
|
||||||
} else {
|
} else {
|
||||||
copy_transposed_line(dst, src16);
|
copy_transposed_line(dst, src16);
|
||||||
}
|
}
|
||||||
@ -1460,14 +1462,14 @@ __weak int omv_csi_copy_line(void *dma, uint8_t *src, uint8_t *dst) {
|
|||||||
} else if ((csi.pixformat == PIXFORMAT_RGB565 && csi.rgb_swap) ||
|
} else if ((csi.pixformat == PIXFORMAT_RGB565 && csi.rgb_swap) ||
|
||||||
(csi.pixformat == PIXFORMAT_YUV422 && csi.yuv_swap)) {
|
(csi.pixformat == PIXFORMAT_YUV422 && csi.yuv_swap)) {
|
||||||
if (!csi.transpose) {
|
if (!csi.transpose) {
|
||||||
unaligned_memcpy_rev16(dst16, src16, MAIN_FB()->u);
|
unaligned_memcpy_rev16(dst16, src16, csi.fb->u);
|
||||||
} else {
|
} else {
|
||||||
copy_transposed_line_rev16(dst16, src16);
|
copy_transposed_line_rev16(dst16, src16);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!csi.transpose) {
|
if (!csi.transpose) {
|
||||||
unaligned_memcpy(dst16, src16, MAIN_FB()->u * sizeof(uint16_t));
|
unaligned_memcpy(dst16, src16, csi.fb->u * sizeof(uint16_t));
|
||||||
} else {
|
} else {
|
||||||
copy_transposed_line(dst16, src16);
|
copy_transposed_line(dst16, src16);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "omv_i2c.h"
|
#include "omv_i2c.h"
|
||||||
#include "imlib.h"
|
#include "imlib.h"
|
||||||
|
#include "framebuffer.h"
|
||||||
|
|
||||||
#define OV2640_SLV_ADDR (0x60)
|
#define OV2640_SLV_ADDR (0x60)
|
||||||
#define OV5640_SLV_ADDR (0x78)
|
#define OV5640_SLV_ADDR (0x78)
|
||||||
@ -320,6 +321,8 @@ typedef struct _omv_csi {
|
|||||||
|
|
||||||
omv_i2c_t i2c_bus; // SCCB/I2C bus.
|
omv_i2c_t i2c_bus; // SCCB/I2C bus.
|
||||||
|
|
||||||
|
framebuffer_t *fb; // Frame buffer pointer
|
||||||
|
|
||||||
#ifdef OMV_CSI_PORT_BITS
|
#ifdef OMV_CSI_PORT_BITS
|
||||||
// Additional port-specific members like device base pointer,
|
// Additional port-specific members like device base pointer,
|
||||||
// dma handles, more I/Os etc... are included directly here,
|
// dma handles, more I/Os etc... are included directly here,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user