mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #562 from kwagyeman/kwabena/ov2640_final
OV2640 fixes.
This commit is contained in:
commit
64aea12015
@ -6,9 +6,9 @@
|
||||
* Framebuffer stuff.
|
||||
*
|
||||
*/
|
||||
#include "imlib.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#include "mpprint.h"
|
||||
#include "framebuffer.h"
|
||||
#include "omv_boardconfig.h"
|
||||
|
||||
extern char _fb_base;
|
||||
framebuffer_t *fb_framebuffer = (framebuffer_t *) &_fb_base;
|
||||
@ -16,6 +16,45 @@ framebuffer_t *fb_framebuffer = (framebuffer_t *) &_fb_base;
|
||||
extern char _jpeg_buf;
|
||||
jpegbuffer_t *jpeg_fb_framebuffer = (jpegbuffer_t *) &_jpeg_buf;
|
||||
|
||||
int encode_for_ide_new_size(image_t *img)
|
||||
{
|
||||
return (((img->bpp * 8) + 5) / 6) + 2;
|
||||
}
|
||||
|
||||
void encode_for_ide(uint8_t *ptr, image_t *img)
|
||||
{
|
||||
*ptr++ = 0xFE;
|
||||
|
||||
for(int i = 0, j = (img->bpp / 3) * 3; i < j; i += 3) {
|
||||
int x = 0;
|
||||
x |= img->data[i + 0] << 0;
|
||||
x |= img->data[i + 1] << 8;
|
||||
x |= img->data[i + 2] << 16;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 18) & 0x3F);
|
||||
}
|
||||
|
||||
if((img->bpp % 3) == 2) { // 2 bytes -> 16-bits -> 24-bits sent
|
||||
int x = 0;
|
||||
x |= img->data[img->bpp - 2] << 0;
|
||||
x |= img->data[img->bpp - 1] << 8;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
|
||||
}
|
||||
|
||||
if((img->bpp % 3) == 1) { // 1 byte -> 8-bits -> 16-bits sent
|
||||
int x = 0;
|
||||
x |= img->data[img->bpp - 1] << 0;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
}
|
||||
|
||||
*ptr++ = 0xFE;
|
||||
}
|
||||
|
||||
uint32_t fb_buffer_size()
|
||||
{
|
||||
switch (MAIN_FB()->bpp) {
|
||||
@ -42,11 +81,13 @@ void fb_update_jpeg_buffer()
|
||||
static int overflow_count = 0;
|
||||
|
||||
if ((MAIN_FB()->bpp > 3) && JPEG_FB()->enabled) {
|
||||
bool does_not_fit = false;
|
||||
// Lock FB
|
||||
if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) {
|
||||
if((OMV_JPEG_BUF_SIZE-64) < MAIN_FB()->bpp) {
|
||||
// image won't fit. so don't copy.
|
||||
JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0;
|
||||
does_not_fit = true;
|
||||
} else {
|
||||
memcpy(JPEG_FB()->pixels, MAIN_FB()->pixels, MAIN_FB()->bpp);
|
||||
JPEG_FB()->w = MAIN_FB()->w; JPEG_FB()->h = MAIN_FB()->h; JPEG_FB()->size = MAIN_FB()->bpp;
|
||||
@ -55,6 +96,15 @@ void fb_update_jpeg_buffer()
|
||||
// Unlock the framebuffer mutex
|
||||
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV);
|
||||
}
|
||||
if (does_not_fit) {
|
||||
image_t out = { .w=MAIN_FB()->w, .h=MAIN_FB()->h, .bpp=MAIN_FB()->bpp, .data=MAIN_FB()->pixels };
|
||||
int new_size = encode_for_ide_new_size(&out);
|
||||
fb_alloc_mark();
|
||||
uint8_t *temp = fb_alloc(new_size);
|
||||
encode_for_ide(temp, &out);
|
||||
(MP_PYTHON_PRINTER)->print_strn((MP_PYTHON_PRINTER)->data, (const char *) temp, new_size);
|
||||
fb_alloc_free_till_mark();
|
||||
}
|
||||
} else if ((MAIN_FB()->bpp >= 0) && JPEG_FB()->enabled) {
|
||||
// Lock FB
|
||||
if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) {
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#ifndef __FRAMEBUFFER_H__
|
||||
#define __FRAMEBUFFER_H__
|
||||
#include <stdint.h>
|
||||
#include "imlib.h"
|
||||
#include "mutex.h"
|
||||
|
||||
typedef struct framebuffer {
|
||||
@ -44,6 +45,10 @@ extern jpegbuffer_t *jpeg_fb_framebuffer;
|
||||
// Use this macro to get a pointer to the free SRAM area located after the framebuffer.
|
||||
#define JPEG_FB_PIXELS() (JPEG_FB()->pixels + JPEG_FB()->size)
|
||||
|
||||
// Encode jpeg data for transmission over a text channel.
|
||||
int encode_for_ide_new_size(image_t *img);
|
||||
void encode_for_ide(uint8_t *ptr, image_t *img);
|
||||
|
||||
// Returns the main frame buffer size, factoring in pixel formats.
|
||||
uint32_t fb_buffer_size();
|
||||
|
||||
|
||||
@ -219,7 +219,7 @@ static const uint8_t default_regs[][2] = {
|
||||
// {COM1, 0x06 | 0x80},
|
||||
// {HSTART, 0x11},
|
||||
// {HSTOP, 0x43},
|
||||
// {VSTART, 0x00},
|
||||
// {VSTART, 0x01}, // 0x01 fixes issue with garbage pixels in the image...
|
||||
// {VSTOP, 0x97},
|
||||
// {REG32, 0x09},
|
||||
// {BANK_SEL, BANK_SEL_DSP},
|
||||
@ -237,7 +237,7 @@ static const uint8_t svga_regs[][2] = {
|
||||
{COM1, 0x0A | 0x80},
|
||||
{HSTART, 0x11},
|
||||
{HSTOP, 0x43},
|
||||
{VSTART, 0x00},
|
||||
{VSTART, 0x01}, // 0x01 fixes issue with garbage pixels in the image...
|
||||
{VSTOP, 0x97},
|
||||
{REG32, 0x09},
|
||||
{BANK_SEL, BANK_SEL_DSP},
|
||||
@ -305,8 +305,6 @@ static const uint8_t jpeg_regs[][2] = {
|
||||
{R_BYPASS, R_BYPASS_DSP_EN},
|
||||
{IMAGE_MODE, IMAGE_MODE_JPEG_EN},
|
||||
{0xd7, 0x03},
|
||||
{0xe1, 0x77},
|
||||
{QS, 0x0c},
|
||||
{RESET, 0x00},
|
||||
{R_BYPASS, R_BYPASS_DSP_EN},
|
||||
{0, 0},
|
||||
@ -432,6 +430,10 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
uint16_t w = resolution[framesize][0];
|
||||
uint16_t h = resolution[framesize][1];
|
||||
|
||||
if ((w % 4) || (h % 4)) { // w/h must be divisble by 4
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Looks really bad.
|
||||
/* if ((w <= CIF_WIDTH) && (h <= CIF_HEIGHT)) {
|
||||
regs = cif_regs;
|
||||
@ -452,13 +454,15 @@ static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
ret |= cambus_writeb(sensor->slv_addr, regs[i][0], regs[i][1]);
|
||||
}
|
||||
|
||||
uint16_t div = IM_MIN(IM_MIN(sensor_w / w, sensor_h / h), 8);
|
||||
uint64_t tmp_div = IM_MIN(sensor_w / w, sensor_h / h);
|
||||
uint16_t log_div = IM_MIN(IM_LOG2(tmp_div) - 1, 3);
|
||||
uint16_t div = 1 << log_div;
|
||||
uint16_t w_mul = w * div;
|
||||
uint16_t h_mul = h * div;
|
||||
uint16_t x_off = (sensor_w - w_mul) / 2;
|
||||
uint16_t y_off = (sensor_h - h_mul) / 2;
|
||||
|
||||
ret |= cambus_writeb(sensor->slv_addr, CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(div - 1) | CTRLI_H_DIV_SET(div - 1));
|
||||
ret |= cambus_writeb(sensor->slv_addr, CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(log_div) | CTRLI_H_DIV_SET(log_div));
|
||||
ret |= cambus_writeb(sensor->slv_addr, HSIZE, HSIZE_SET(w_mul));
|
||||
ret |= cambus_writeb(sensor->slv_addr, VSIZE, VSIZE_SET(h_mul));
|
||||
ret |= cambus_writeb(sensor->slv_addr, XOFFL, XOFFL_SET(x_off));
|
||||
|
||||
@ -1276,41 +1276,11 @@ static mp_obj_t py_image_compress_for_ide(uint n_args, const mp_obj_t *args, mp_
|
||||
uint8_t *buffer = fb_alloc_all(&size);
|
||||
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .data=buffer };
|
||||
PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!");
|
||||
PY_ASSERT_TRUE_MSG(((((out.bpp * 8) + 5) / 6) + 2) <= image_size(arg_img), "Can't compress in place!");
|
||||
uint8_t *ptr = arg_img->data;
|
||||
int new_size = encode_for_ide_new_size(&out);
|
||||
PY_ASSERT_TRUE_MSG(new_size <= image_size(arg_img), "Can't compress in place!");
|
||||
encode_for_ide(arg_img->data, &out);
|
||||
|
||||
*ptr++ = 0xFE;
|
||||
|
||||
for(int i = 0, j = (out.bpp / 3) * 3; i < j; i += 3) {
|
||||
int x = 0;
|
||||
x |= out.data[i + 0] << 0;
|
||||
x |= out.data[i + 1] << 8;
|
||||
x |= out.data[i + 2] << 16;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 18) & 0x3F);
|
||||
}
|
||||
|
||||
if((out.bpp % 3) == 2) { // 2 bytes -> 16-bits -> 24-bits sent
|
||||
int x = 0;
|
||||
x |= out.data[out.bpp - 2] << 0;
|
||||
x |= out.data[out.bpp - 1] << 8;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
|
||||
}
|
||||
|
||||
if((out.bpp % 3) == 1) { // 1 byte -> 8-bits -> 16-bits sent
|
||||
int x = 0;
|
||||
x |= out.data[out.bpp - 1] << 0;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
}
|
||||
|
||||
*ptr++ = 0xFE;
|
||||
|
||||
out.bpp = (((out.bpp * 8) + 5) / 6) + 2;
|
||||
out.bpp = new_size;
|
||||
arg_img->bpp = out.bpp;
|
||||
fb_alloc_free_till_mark();
|
||||
|
||||
@ -1353,41 +1323,11 @@ static mp_obj_t py_image_compressed_for_ide(uint n_args, const mp_obj_t *args, m
|
||||
uint8_t *buffer = fb_alloc_all(&size);
|
||||
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .data=buffer };
|
||||
PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!");
|
||||
uint8_t *temp = xalloc((((out.bpp * 8) + 5) / 6) + 2);
|
||||
uint8_t *ptr = temp;
|
||||
int new_size = encode_for_ide_new_size(&out);
|
||||
uint8_t *temp = xalloc(new_size);
|
||||
encode_for_ide(temp, &out);
|
||||
|
||||
*ptr++ = 0xFE;
|
||||
|
||||
for(int i = 0, j = (out.bpp / 3) * 3; i < j; i += 3) {
|
||||
int x = 0;
|
||||
x |= out.data[i + 0] << 0;
|
||||
x |= out.data[i + 1] << 8;
|
||||
x |= out.data[i + 2] << 16;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 12) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 18) & 0x3F);
|
||||
}
|
||||
|
||||
if((out.bpp % 3) == 2) { // 2 bytes -> 16-bits -> 24-bits sent
|
||||
int x = 0;
|
||||
x |= out.data[out.bpp - 2] << 0;
|
||||
x |= out.data[out.bpp - 1] << 8;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 12) & 0x0F);
|
||||
}
|
||||
|
||||
if((out.bpp % 3) == 1) { // 1 byte -> 8-bits -> 16-bits sent
|
||||
int x = 0;
|
||||
x |= out.data[out.bpp - 1] << 0;
|
||||
*ptr++ = 0x80 | ((x >> 0) & 0x3F);
|
||||
*ptr++ = 0x80 | ((x >> 6) & 0x03);
|
||||
}
|
||||
|
||||
*ptr++ = 0xFE;
|
||||
|
||||
out.bpp = (((out.bpp * 8) + 5) / 6) + 2;
|
||||
out.bpp = new_size;
|
||||
out.data = temp;
|
||||
fb_alloc_free_till_mark();
|
||||
|
||||
@ -1395,6 +1335,42 @@ static mp_obj_t py_image_compressed_for_ide(uint n_args, const mp_obj_t *args, m
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_compressed_for_ide_obj, 1, py_image_compressed_for_ide);
|
||||
|
||||
static mp_obj_t py_image_jpeg_encode_for_ide(mp_obj_t img_obj)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(img_obj);
|
||||
PY_ASSERT_TRUE_MSG(arg_img->bpp >= IMAGE_BPP_JPEG, "Image format is not supported!");
|
||||
PY_ASSERT_TRUE_MSG(MAIN_FB()->pixels == arg_img->data, "Can't compress in place!");
|
||||
|
||||
int new_size = encode_for_ide_new_size(arg_img);
|
||||
fb_alloc_mark();
|
||||
uint8_t *temp = fb_alloc(new_size);
|
||||
encode_for_ide(temp, arg_img);
|
||||
|
||||
MAIN_FB()->bpp = 0;
|
||||
PY_ASSERT_TRUE_MSG(new_size <= fb_avail(), "The new image won't fit in the main frame buffer!");
|
||||
MAIN_FB()->bpp = new_size;
|
||||
arg_img->bpp = new_size;
|
||||
|
||||
memcpy(arg_img->data, temp, new_size);
|
||||
fb_alloc_free_till_mark();
|
||||
|
||||
return img_obj;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_jpeg_encode_for_ide_obj, py_image_jpeg_encode_for_ide);
|
||||
|
||||
static mp_obj_t py_image_jpeg_encoded_for_ide(mp_obj_t img_obj)
|
||||
{
|
||||
image_t *arg_img = py_image_cobj(img_obj);
|
||||
PY_ASSERT_TRUE_MSG(arg_img->bpp >= IMAGE_BPP_JPEG, "Image format is not supported!");
|
||||
|
||||
int new_size = encode_for_ide_new_size(arg_img);
|
||||
uint8_t *temp = xalloc(new_size);
|
||||
encode_for_ide(temp, arg_img);
|
||||
|
||||
return py_image(arg_img->w, arg_img->h, new_size, temp);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_jpeg_encoded_for_ide_obj, py_image_jpeg_encoded_for_ide);
|
||||
|
||||
static mp_obj_t py_image_copy_int(uint n_args, const mp_obj_t *args, mp_map_t *kw_args, bool mode)
|
||||
{
|
||||
// mode == false -> copy behavior
|
||||
@ -6320,6 +6296,8 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_compress_for_ide), MP_ROM_PTR(&py_image_compress_for_ide_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_compressed), MP_ROM_PTR(&py_image_compressed_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_compressed_for_ide), MP_ROM_PTR(&py_image_compressed_for_ide_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_jpeg_encode_for_ide), MP_ROM_PTR(&py_image_jpeg_encode_for_ide_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_jpeg_encoded_for_ide),MP_ROM_PTR(&py_image_jpeg_encoded_for_ide_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&py_image_copy_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_crop), MP_ROM_PTR(&py_image_crop_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_scale), MP_ROM_PTR(&py_image_crop_obj)},
|
||||
|
||||
@ -446,6 +446,12 @@ Q(compressed)
|
||||
Q(compressed_for_ide)
|
||||
// duplicate Q(quality)
|
||||
|
||||
// Encode for IDE (in place)
|
||||
Q(jpeg_encode_for_ide)
|
||||
|
||||
// Encoded for IDE (out of place)
|
||||
Q(jpeg_encoded_for_ide)
|
||||
|
||||
// Copy
|
||||
// duplicate Q(copy)
|
||||
Q(crop)
|
||||
|
||||
@ -50,6 +50,20 @@ int printf(const char *fmt, ...)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NORETURN void nlr_jump(void *val)
|
||||
{
|
||||
__fatal_error();
|
||||
}
|
||||
|
||||
void *mp_obj_new_exception_msg(const void *exc_type, const char *msg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const void *mp_type_MemoryError = NULL;
|
||||
|
||||
const void *mp_sys_stdout_print = NULL;
|
||||
|
||||
static uint8_t frame_index = 0;
|
||||
static uint8_t format_index = 0;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user