Fixed linker script to load haar cascade into CCM

Fixed issue with SCCB delay and optimization
Recompiled all libraries with optimization enabled (-O2)
Some more tweaks to the Sensor's registers
Added function to load CCM data into .ccm section in runtime
This commit is contained in:
iabdalkader 2013-12-02 22:17:45 +02:00
parent b3de021627
commit 5a259bbcf1
12 changed files with 218 additions and 112 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -10,15 +10,15 @@ OBJDUMP = arm-none-eabi-objdump
#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS = -O2
else
CFLAGS = -O0 -ggdb
else
CFLAGS = -O2 -ggdb
endif
#Compiler Flags
CFLAGS += -Wall -mlittle-endian -mthumb -mthumb-interwork -nostartfiles -mcpu=cortex-m4
CFLAGS += -fsingle-precision-constant -Wdouble-promotion -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -I. -I../include/CMSIS -I../include/StdPeriph -I../include/USB_OTG -DSTM32F40_41xxx -DUSE_USB_OTG_FS
CFLAGS += -fsingle-precision-constant -Wdouble-promotion -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -I. -I../include/CMSIS -I../include/StdPeriph -I../include/USB_OTG -DSTM32F40_41xxx -DUSE_USB_OTG_FS -DARM_MATH_CM4 -D__FPU_PRESENT
#Linker Flags
LDFLAGS = -mcpu=cortex-m4 -mthumb -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16
@ -29,14 +29,14 @@ BIN = "openmv"
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
#Libraries
LIB = -lc -lm -lstdperiph -lusbgeneric -lusbdevcore -lusbcore
LIB = -lc -lm -lstdperiph -ldsp -lusbgeneric -lusbdevcore -lusbcore
all:: $(BIN)
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) $(LIB) -o $(BIN).elf
$(OBJCOPY) -Oihex -j .text -j .data $(BIN).elf $(BIN).hex
$(OBJCOPY) -Obinary -j .text -j .data $(BIN).elf $(BIN).bin
$(OBJCOPY) -Obinary $(BIN).elf $(BIN).bin
$(OBJDUMP) -d $(BIN).elf > $(BIN).dis
stats: $(BIN).elf

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,8 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <arm_math.h>
#include <stm32f4xx.h>
#include <core_cm4.h>
#include <core_cm4_simd.h>
#include "array.h"
#include "imlib.h"
#include "cascade.h"
@ -302,8 +301,8 @@ static int runCascadeClassifier(struct cascade* cascade, struct point pt, int st
{
int i, j;
int p_offset;
uint32_t mean;
uint32_t std;
int32_t mean;
int32_t std;
int w_index = 0;
int r_index = 0;
@ -338,9 +337,7 @@ static int runCascadeClassifier(struct cascade* cascade, struct point pt, int st
+ cascade->sum.data[cascade->sum.width * win_h + win_w + p_offset];
std = sqrtf(sumsq * cascade->window.width * cascade->window.height - mean * mean);
// if (std < 10) {
// return -1;
// }
for (i=start_stage; i<cascade->n_stages; i++) {
stage_sum = 0;
for (j=0; j<stages_array[i]; j++, tree_index++, w_index+=3, r_index+=12) {
@ -349,7 +346,7 @@ static int runCascadeClassifier(struct cascade* cascade, struct point pt, int st
}
/* If the sum is below the stage threshold, no faces are detected */
if (stage_sum < 0.9*stages_thresh_array[i]) {
if (stage_sum < 0.25*stages_thresh_array[i]) {
return -i;
}
}
@ -393,6 +390,89 @@ static void ScaleImageInvoker(struct cascade *cascade, float factor, int sum_row
}
}
struct rectangle *rectangle_clone(struct rectangle *rect)
{
struct rectangle *rectangle;
rectangle = malloc(sizeof(struct rectangle));
memcpy(rectangle, rect, sizeof(struct rectangle));
return rectangle;
}
void rectangle_add(struct rectangle *rect0, struct rectangle *rect1)
{
rect0->x += rect1->x;
rect0->y += rect1->y;
rect0->w += rect1->w;
rect0->h += rect1->h;
}
void rectangle_div(struct rectangle *rect0, int c)
{
rect0->x /= c;
rect0->y /= c;
rect0->w /= c;
rect0->h /= c;
}
void rectangle_merge(struct rectangle *rect0, struct rectangle *rect1)
{
rect0->x = (rect0->x < rect1->x)? rect0->x:rect1->x;
rect0->y = (rect0->y < rect1->y)? rect0->y:rect1->y;
rect0->w = (rect0->w > rect1->w)? rect0->w:rect1->w;
rect0->h = (rect0->h > rect1->h)? rect0->h:rect1->h;
}
int rectangle_intersects(struct rectangle *rect0, struct rectangle *rect1)
{
return ((rect0->x < (rect1->x+rect1->w)) &&
(rect0->y < (rect1->y+rect1->h)) &&
((rect0->x+rect0->w) > rect1->x) &&
((rect0->y+rect0->h) > rect1->y));
}
struct array *imlib_merge_detections(struct array *rectangles)
{
int j;
struct array *objects;
struct array *overlap;
struct rectangle *rect1, *rect2;
array_alloc(&objects, free);
array_alloc(&overlap, free);
/* merge overlaping detections */
while (array_length(rectangles)) {
/* check for overlaping detections */
rect1 = (struct rectangle *) array_at(rectangles, 0);
for (j=1; j<array_length(rectangles); j++) {
rect2 = (struct rectangle *) array_at(rectangles, j);
if (rectangle_intersects(rect1, rect2)) {
array_push_back(overlap, rectangle_clone(rect2));
array_erase(rectangles, j--);
}
}
/* add the overlaping detections */
int count = array_length(overlap)+1;
while (array_length(overlap)) {
rect2 = (struct rectangle *) array_at(overlap, 0);
rectangle_add(rect1, rect2);
array_erase(overlap, 0);
}
/* average the overlaping detections */
rectangle_div(rect1, count);
array_push_back(objects, rectangle_clone(rect1));
array_erase(rectangles, 0);
}
array_free(overlap);
array_free(rectangles);
return objects;
}
struct array *imlib_detect_objects(struct cascade *cascade, struct frame_buffer *fb)
{
/* scaling factor */
@ -457,12 +537,9 @@ struct array *imlib_detect_objects(struct cascade *cascade, struct frame_buffer
ScaleImageInvoker(cascade, factor, sum.height, sum.width, objects);
}
// if (minNeighbors != 0 && array_length(objects)) {
// groupRectangles(objects, minNeighbors, GROUP_EPS);
// }
free(sum.data);
objects = imlib_merge_detections(objects);
return objects;
}

View File

@ -18,14 +18,11 @@
static volatile int frame_ready = 0;
static uint8_t ov9650_init_regs[][2] = {
{REG_BLUE, 0x80},
{REG_RED, 0x80},
/* See Implementation Guide */
{REG_COM2, 0x01}, /* Output drive x2 */
{REG_COM5, 0x00}, /* System clock */
{REG_CLKRC, 0x81}, /* Clock control 30 FPS*/
{REG_MVFP, 0x00}, /* Mirror/VFlip */
{REG_MVFP, 0x10}, /* Mirror/VFlip */
/* Default QQVGA-RGB565 */
{REG_COM7, 0x14}, /* QVGA/RGB565 */
@ -42,7 +39,7 @@ static uint8_t ov9650_init_regs[][2] = {
{REG_ADVFL, 0x00}, /* Dummy Pixel Insert LSB */
/* See Implementation Guide Section 3.4.1.2 */
{REG_COM8, 0xA3}, /* Enable Fast Mode AEC/Enable Banding Filter/AGC/AWB/AEC */
{REG_COM8, 0xA7}, /* Enable Fast Mode AEC/Enable Banding Filter/AGC/AWB/AEC */
{0x60, 0x8C}, /* Normal AWB, 0x0C for Advanced AWB */
{REG_AEW, 0x74}, /* AGC/AEC Threshold Upper Limit */
{REG_AEB, 0x68}, /* AGC/AEC Threshold Lower Limit */
@ -53,10 +50,11 @@ static uint8_t ov9650_init_regs[][2] = {
// {REG_GRCOM, 0x3F}, /* Analog BLC/External Regulator */
/* See OV9650 Implementation Guide */
{REG_COM11, 0x01}, /* Automatic/Manual Banding Filter */
{REG_MBD, 0x1a}, /* Manual banding filter LSB */
{REG_COM11, 0x01}, /* Night Mode-Automatic/Manual Banding Filter */
{REG_MBD, 0x1a}, /* MBD[7:0] Manual banding filter LSB */
{REG_HV, 0x14}, /* HV[0] Manual banding filter MSB */
{REG_COM12, 0x04}, /* HREF options/ UV average */
{REG_COM9, 0x58}, /* Gain ceiling [6:4]/Over-Exposure */
{REG_COM9, 0x40}, /* Gain ceiling [6:4]/Over-Exposure */
{REG_COM16, 0x02}, /* Color matrix coeff double option */
{REG_COM13, 0x10}, /* Gamma/Colour Matrix/UV delay */
{REG_COM23, 0x00}, /* Disable Color bar/Analog Color Gain */
@ -64,8 +62,10 @@ static uint8_t ov9650_init_regs[][2] = {
{REG_COM10, 0x00}, /* Slave mode, HREF vs HSYNC, signals negate */
{REG_EDGE, 0xa6}, /* Edge enhancement treshhold and factor */
{REG_COM6, 0x43}, /* HREF & ADBLC options */
{REG_COM22, 0x00}, /* Edge enhancement/Denoising */
{REG_COM22, 0x20}, /* Edge enhancement/Denoising */
{REG_COM21, 0x00}, /* COM21[3] Digital Zoom */
/* When AEC is not used */
// {REG_AECH, 0x00}, /* Exposure Value MSB */
// {REG_AECHM, 0x00}, /* Exposure Value LSB */
@ -116,25 +116,25 @@ static uint8_t ov9650_init_regs[][2] = {
{0x8a, 0xe6},
/* Reserved Registers, see OV965x App Note */
{0x16, 0x06},
{0x34, 0xbf},
{0x16, 0x07},
{0x34, 180},
//{0xa8, 0x80},/* this doesn't work with QQCIF/QCIF */
{0x96, 0x04},
{0x8e, 0x00},
{0x8b, 0x06},
{0x35, 0x91},
{0x94, 0x88},
{0x95, 0x88},
{0xa9, 0xb8},
{0xaa, 0x92},
{0xab, 0x0a},
/*
{0x5c, 0x96},
{0x5d, 0x96},
{0x5e, 0x10},
{0x59, 0xeb},
{0x5a, 0x9c},
{0x5b, 0x55},
*/
/* NULL reg */
{0x00, 0x00}
};
@ -148,7 +148,7 @@ static uint8_t ov9650_rgb565_regs[][2] = {
/* See Implementation Guide Section 3.4.1.2 */
{REG_OFON, 0x43}, /* Power down register */
{REG_ACOM38, 0x12}, /* reserved */
{REG_ADC, 0x00}, /* reserved */
{REG_ADC, 0xFF}, /* reserved */
{REG_RSVD35, 0x81}, /* reserved */
/* YUV fmt /Special Effects Controls */
@ -252,7 +252,7 @@ void DMA2_Stream1_IRQHandler(void)
void delay(uint32_t ntime)
{
uint32_t x;
volatile uint32_t x;
while (ntime) {
for (x=0; x<10000; x--);
ntime--;

View File

@ -9,13 +9,13 @@ enum ov9650_pixformat {
};
enum ov9650_framesize {
FRAMESIZE_SXGA, /* 1280x1024 */
FRAMESIZE_VGA, /* 640x480 */
FRAMESIZE_CIF, /* 352x288 */
FRAMESIZE_QVGA, /* 320x240 */
FRAMESIZE_QCIF, /* 176x144 */
FRAMESIZE_QQCIF, /* 88x72 */
FRAMESIZE_QQVGA,/* 160x120 */
FRAMESIZE_QQCIF /* 88x72 */
FRAMESIZE_QCIF, /* 176x144 */
FRAMESIZE_QVGA, /* 320x240 */
FRAMESIZE_CIF, /* 352x288 */
FRAMESIZE_VGA, /* 640x480 */
FRAMESIZE_SXGA, /* 1280x1024 */
};
enum ov9650_framerate {
@ -34,6 +34,7 @@ enum ov9650_command {
CMD_SET_FRAMERATE,
CMD_SET_FRAMESIZE,
CMD_FACE_DETECTION,
CMD_WRITE_REG,
};
enum cmd_result {

View File

@ -23,7 +23,7 @@
static void delay(void)
{
uint32_t d = 10;
volatile uint32_t d = 10;
while(d--) {
}
}

View File

@ -45,7 +45,7 @@ MEMORY
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
ccm (w!rx) : ORIGIN = 0x10000000, LENGTH = 64K
CCM (w!rx) : ORIGIN = 0x10000000, LENGTH = 64K
}
/* Define output sections */
@ -116,6 +116,7 @@ SECTIONS
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
@ -123,10 +124,18 @@ SECTIONS
_edata = .; /* define a global symbol at data end */
} >RAM
.ccm : /*define section*/
/* This section will load the .ccm data into FLASH,
a C function in .init section copies the .ccm data
from FLASH to CCM memory in runtime. */
_eidata = (_sidata + SIZEOF(.data) + SIZEOF(.jcr));
.ccm : AT ( _sidata + SIZEOF(.data) + SIZEOF(.jcr))
{
. = ALIGN(4);
_sccm = .;
*(.ccm)
}>ccm
. = ALIGN(4);
_eccm = .;
}>CCM
/* Uninitialized data section */
. = ALIGN(4);

View File

@ -13,6 +13,7 @@
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include "ov9650.h"
#include "ov9650_regs.h"
#define USB_VID (0x0483) /* vendor id */
#define USB_PID (0x5740) /* product id */
#define EP_IN (0x81) /* IN endpoint */
@ -91,50 +92,32 @@ long get_time_ms()
return timeval.tv_sec * 1000 + (long) (timeval.tv_usec * 0.001f);
}
SDL_Surface *flip_surface(SDL_Surface *surface)
int write_image(char *path, struct frame_buffer *image)
{
int x,rx,y,ry;
//Pointer to the soon to be flipped surface
SDL_Surface *flipped = NULL;
int i;
FILE *fp = fopen(path, "w");
if (fp == NULL) {
printf("Unable to open file %s\n", path);
return -1;
}
/* write header */
fprintf(fp, "P5\n%d %d\n%d\n", image->width, image->height, 255);
/* write pixels */
for (i = 0; i < (image->width * image->height); i++) {
fprintf(fp, "%c", image->pixels[i]);
}
fclose(fp);
return 0;
}
//If the image is color keyed
if (surface->flags & SDL_SRCCOLORKEY) {
flipped = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h,
surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, 0);
} else {
flipped = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h,
surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, 0);
}
//If the surface must be locked
if (SDL_MUSTLOCK(surface)) {
//Lock the surface
SDL_LockSurface( surface );
}
//Go through columns
for (x=0, rx=flipped->w-1; x<flipped->w; x++, rx--) {
//Go through rows
for (y=0, ry=flipped->h-1; y<flipped->h; y++, ry--) {
//Get pixel
Uint32 pixel = ((Uint32*)surface->pixels)[( y * surface->w ) + x];
((Uint32*)flipped->pixels)[( ry * surface->w ) + x] =pixel;
}
}
//Unlock surface
if(SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
//Copy color key
if (surface->flags & SDL_SRCCOLORKEY) {
SDL_SetColorKey(flipped, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey);
}
SDL_BlitSurface(flipped, NULL, surface, NULL);
SDL_FreeSurface(flipped);
return 0;
void write_reg(reg, val)
{
uint8_t cmd_buf[3];
cmd_buf[0] = CMD_WRITE_REG;
cmd_buf[1] = reg;
cmd_buf[2] = val;
bulk_xfr(EP_OUT, cmd_buf, 3);
}
int main (int argc, char **argv)
@ -249,13 +232,17 @@ int main (int argc, char **argv)
/*install signal handlers*/
sigaction(SIGINT, &act, NULL);
libusb_set_debug(NULL, DEBUG_LEVEL); /*set debugging level*/
/*set debugging level*/
libusb_set_debug(NULL, DEBUG_LEVEL);
if ((dev = libusb_open_device_with_vid_pid(NULL, USB_VID, USB_PID)) == NULL){
fprintf(stderr, "Device could not be found.\n");
exit(1);
}
/* reset device */
libusb_reset_device(dev);
/* claim interace zero */
if (libusb_claim_interface(dev, 0) != 0) {
fprintf(stderr, "Failed to claim interface\n");
@ -300,8 +287,6 @@ int main (int argc, char **argv)
exit(1);
}
libusb_reset_device(dev);
/* set pixelformat */
cmd_buf[0] = CMD_SET_PIXFORMAT;
cmd_buf[1] = ov9650.pixformat;
@ -317,6 +302,11 @@ int main (int argc, char **argv)
cmd_buf[1] = ov9650.framerate;
bulk_xfr(EP_OUT, cmd_buf, 2);
cmd_buf[0] = CMD_WRITE_REG;
cmd_buf[1] = REG_COM9;
cmd_buf[2] = 0x50;
bulk_xfr(EP_OUT, cmd_buf, 3);
sleep(1);
SDL_Event event;
@ -367,30 +357,59 @@ int main (int argc, char **argv)
pixels[3]=0;
}
flip_surface(surface);
SDL_BlitSurface(surface, NULL, screen, NULL);
++frames;
t_elapsed = get_time_ms() - t_start;
t_total += t_elapsed;
char text_buf[64];
//printf("FPS %d\n", ((1000 /(t_total/frames))));
static uint8_t v=0;
char buf[9]={0};
for (i=0; i<8; i++) {
buf[i]=(((v<<i)&0x80)>>7)+48;
}
// write_reg(REG_GAIN, v);
// sprintf(text_buf, "REG %d %s", v, buf);
sprintf(text_buf, "FPS %.2f", 1000/(float)(t_total / frames));
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
exit(0);
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_0:
v=0;
break;
case SDLK_KP_PLUS:
v++;
break;
case SDLK_KP_MINUS:
v--;
break;
case SDLK_s:
printf("snapshot...\n");
write_image("snapshot.pgm", fb);
break;
case SDLK_ESCAPE:
exit(0);
default:
break;
}
break;
}
SDL_Color fg = {255, 0, 0, 0};
SDL_Surface *text = TTF_RenderText_Solid(font, text_buf, fg);
SDL_Rect rect = {0, 0, 0, 0};
SDL_BlitSurface(text, NULL, screen, &rect);
SDL_BlitSurface(text, NULL, surface, &rect);
SDL_BlitSurface(surface, NULL, screen, NULL);
SDL_FreeSurface(text);
/*flush*/
SDL_UpdateRect(screen, 0, 0, fb->width, fb->height);
SDL_PollEvent(&event);
if (event.type == SDL_QUIT) {
exit(0);
}
}
return 0;
}