Merge pull request #562 from kwagyeman/kwabena/ov2640_final

OV2640 fixes.
This commit is contained in:
Ibrahim Abd Elkader 2019-08-20 02:41:53 +02:00 committed by GitHub
commit 64aea12015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 133 additions and 76 deletions

View File

@ -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)) {

View File

@ -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();

View File

@ -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));

View File

@ -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)},

View File

@ -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)

View File

@ -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;