mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Update sensor code
* Add OV2640 PID * Add DCMI polarities to sensor struct * Set DCMI polarities in sensors init functions * Update OV9650 to set DCMI polarities
This commit is contained in:
parent
c5ee4bc08a
commit
1e14eacaa2
15
src/ov9650.c
15
src/ov9650.c
@ -15,7 +15,7 @@
|
||||
|
||||
#define NUM_BR_LEVELS 7
|
||||
|
||||
static uint8_t default_regs[][2] = {
|
||||
static const uint8_t default_regs[][2] = {
|
||||
/* See Implementation Guide */
|
||||
{REG_COM2, 0x01}, /* Output drive x2 */
|
||||
{REG_COM5, 0x00}, /* System clock */
|
||||
@ -146,7 +146,7 @@ static uint8_t default_regs[][2] = {
|
||||
{0x00, 0x00}
|
||||
};
|
||||
|
||||
static uint8_t rgb565_regs[][2] = {
|
||||
static const uint8_t rgb565_regs[][2] = {
|
||||
/* See Implementation Guide */
|
||||
{REG_COM3, 0x04}, /* Vario Pixels */
|
||||
{REG_COM4, 0x80}, /* Vario Pixels */
|
||||
@ -170,7 +170,7 @@ static uint8_t rgb565_regs[][2] = {
|
||||
{0x00, 0x00}
|
||||
};
|
||||
|
||||
static uint8_t yuv422_regs[][2] = {
|
||||
static const uint8_t yuv422_regs[][2] = {
|
||||
/* See Implementation Guide */
|
||||
{REG_COM3, 0x04}, /* Vario Pixels */
|
||||
{REG_COM4, 0x80}, /* Vario Pixels */
|
||||
@ -197,7 +197,7 @@ static uint8_t yuv422_regs[][2] = {
|
||||
static int reset()
|
||||
{
|
||||
int i=0;
|
||||
uint8_t (*regs)[2]=default_regs;
|
||||
const uint8_t (*regs)[2]=default_regs;
|
||||
|
||||
/* Reset all registers */
|
||||
SCCB_Write(REG_COM7, 0x80);
|
||||
@ -217,7 +217,7 @@ static int reset()
|
||||
static int set_pixformat(enum sensor_pixformat pixformat)
|
||||
{
|
||||
int i=0;
|
||||
uint8_t (*regs)[2];
|
||||
const uint8_t (*regs)[2];
|
||||
uint8_t com7=0; /* framesize/RGB */
|
||||
|
||||
/* read pixel format reg */
|
||||
@ -344,6 +344,11 @@ static int set_gainceiling(enum sensor_gainceiling gainceiling)
|
||||
|
||||
int ov9650_init(struct sensor_dev *sensor)
|
||||
{
|
||||
/* set HSYNC/VSYNC/PCLK polarity */
|
||||
sensor->vsync_pol = DCMI_VSPolarity_High;
|
||||
sensor->hsync_pol = DCMI_HSPolarity_Low;
|
||||
sensor->pixck_pol = DCMI_PCKPolarity_Rising;
|
||||
|
||||
/* set function pointers */
|
||||
sensor->reset = reset;
|
||||
sensor->set_pixformat = set_pixformat;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#ifndef __OV9650_H__
|
||||
#define __OV9650_H__
|
||||
#include <stdint.h>
|
||||
#include "sensor.h"
|
||||
int ov9650_init(struct sensor_dev *sensor);
|
||||
#endif /* __OV9650_H__ */
|
||||
|
||||
115
src/sensor.c
115
src/sensor.c
@ -9,6 +9,7 @@
|
||||
#include <stm32f4xx_dcmi.h>
|
||||
#include "sccb.h"
|
||||
#include "ov9650.h"
|
||||
#include "ov2640.h"
|
||||
#include "systick.h"
|
||||
#include "sensor.h"
|
||||
#include "framebuffer.h"
|
||||
@ -20,12 +21,33 @@
|
||||
#define REG_MIDL 0x1D
|
||||
|
||||
#define OV9650_PID 0x96
|
||||
#define OV2640_PID 0x26
|
||||
#define BREAK() __asm__ volatile ("BKPT")
|
||||
#define DCMI_DR_ADDRESS (DCMI_BASE + 0x28)
|
||||
|
||||
struct sensor_dev sensor;
|
||||
static volatile int frame_ready = 0;
|
||||
|
||||
const int res_width[] = {
|
||||
88, /* QQCIF */
|
||||
160, /* QQVGA */
|
||||
176, /* QCIF */
|
||||
320, /* QVGA */
|
||||
352, /* CIF */
|
||||
640, /* VGA */
|
||||
1280, /* SXGA */
|
||||
};
|
||||
|
||||
const int res_height[]= {
|
||||
72, /* QQCIF */
|
||||
120, /* QQVGA */
|
||||
144, /* QCIF */
|
||||
240, /* QVGA */
|
||||
288, /* CIF */
|
||||
480, /* VGA */
|
||||
1024, /* SXGA */
|
||||
};
|
||||
|
||||
/* IRQ Handlers */
|
||||
void DCMI_IRQHandler(void)
|
||||
{
|
||||
@ -199,11 +221,11 @@ static int dcmi_config()
|
||||
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
|
||||
|
||||
/* Active VS/HS clocks*/
|
||||
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
|
||||
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
|
||||
DCMI_InitStructure.DCMI_VSPolarity = sensor.vsync_pol;
|
||||
DCMI_InitStructure.DCMI_HSPolarity = sensor.hsync_pol;
|
||||
|
||||
/* Sample data on rising edge of PCK */
|
||||
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
|
||||
DCMI_InitStructure.DCMI_PCKPolarity = sensor.pixck_pol;
|
||||
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
|
||||
|
||||
/* Capture 8 bits on every pixel clock */
|
||||
@ -311,35 +333,28 @@ int sensor_init()
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
|
||||
|
||||
/* RESET/PWDN GPIO configuration */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||
|
||||
/* RESET */
|
||||
/* Configure the RESET GPIO pin */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
|
||||
/* PWDN */
|
||||
/* Configure the PWDN GPIO pin */
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* power down */
|
||||
/* Do a power cycle */
|
||||
GPIO_SetBits(GPIOB, GPIO_Pin_5);
|
||||
systick_sleep(100);
|
||||
|
||||
/* power up */
|
||||
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
|
||||
systick_sleep(100);
|
||||
|
||||
/* reset sensor */
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(100);
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(1000);
|
||||
|
||||
/* Initialize SCCB interface */
|
||||
/* Initialize the SCCB interface */
|
||||
SCCB_Init();
|
||||
systick_sleep(10);
|
||||
|
||||
@ -347,57 +362,82 @@ int sensor_init()
|
||||
extclk_config(24000000);
|
||||
systick_sleep(10);
|
||||
|
||||
/* Configure the DCMI interface */
|
||||
dcmi_config();
|
||||
/* Some sensors have different reset polarities, and we can't know which sensor
|
||||
is connected before initializing SCCB and reading the PID register, which in
|
||||
turn requires pulling the sensor out of the reset state. So we try to read a
|
||||
register with both polarities to determine line state. */
|
||||
|
||||
sensor.reset_pol = ACTIVE_LOW;
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(10);
|
||||
|
||||
/* clear sesnor struct */
|
||||
/* Check if we can read PID */
|
||||
if (SCCB_Read(REG_PID) == 255) {
|
||||
/* Sensor is held in reset, so reset is active high */
|
||||
sensor.reset_pol = ACTIVE_HIGH;
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(10);
|
||||
}
|
||||
|
||||
/* Reset the sesnor state */
|
||||
bzero(&sensor, sizeof(struct sensor_dev));
|
||||
|
||||
/* read sensor id */
|
||||
/* Read the sensor information */
|
||||
sensor.id.MIDH = SCCB_Read(REG_MIDH);
|
||||
sensor.id.MIDL = SCCB_Read(REG_MIDL);
|
||||
sensor.id.PID = SCCB_Read(REG_PID);
|
||||
sensor.id.VER = SCCB_Read(REG_VER);
|
||||
|
||||
/* call the sensor init function */
|
||||
/* Call the sensor-specific init function */
|
||||
switch (sensor.id.PID) {
|
||||
case OV9650_PID:
|
||||
ov9650_init(&sensor);
|
||||
break;
|
||||
case OV2640_PID:
|
||||
ov2640_init(&sensor);
|
||||
break;
|
||||
default:
|
||||
/* sensor not supported */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure the DCMI interface. This should be called
|
||||
after ovxxx_init to set VSYNC/HSYNC/PCLK polarities */
|
||||
dcmi_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sensor_reset()
|
||||
{
|
||||
/* reset sesnor state */
|
||||
/* Reset the sesnor state */
|
||||
sensor.pixformat=0xFF;
|
||||
sensor.framesize=0xFF;
|
||||
sensor.framerate=0xFF;
|
||||
sensor.gainceiling=0xFF;
|
||||
|
||||
/* reset the sensor */
|
||||
/* Hard reset the sensor */
|
||||
switch (sensor.reset_pol) {
|
||||
case ACTIVE_HIGH:
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(10);
|
||||
break;
|
||||
case ACTIVE_LOW:
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(10);
|
||||
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(10);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call sensor-specific reset function */
|
||||
sensor.reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sensor_hard_reset()
|
||||
{
|
||||
/* reset sensor */
|
||||
GPIO_SetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(100);
|
||||
|
||||
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
|
||||
systick_sleep(1000);
|
||||
|
||||
sensor_reset(sensor);
|
||||
}
|
||||
|
||||
int sensor_read_reg(uint8_t reg)
|
||||
{
|
||||
return SCCB_Read(reg);
|
||||
@ -494,15 +534,15 @@ int sensor_set_framesize(enum sensor_framesize framesize)
|
||||
/* set framebuffer dimensions */
|
||||
switch (framesize) {
|
||||
case FRAMESIZE_QQCIF:
|
||||
fb->w = 88;
|
||||
fb->w = 88;
|
||||
fb->h = 72;
|
||||
break;
|
||||
case FRAMESIZE_QQVGA:
|
||||
fb->w = 160;
|
||||
fb->w = 160;
|
||||
fb->h = 120;
|
||||
break;
|
||||
case FRAMESIZE_QCIF:
|
||||
fb->w = 176;
|
||||
fb->w = 176;
|
||||
fb->h = 144;
|
||||
break;
|
||||
default:
|
||||
@ -513,6 +553,7 @@ int sensor_set_framesize(enum sensor_framesize framesize)
|
||||
dma_config(fb->pixels, fb->w * fb->h * 2);
|
||||
|
||||
#if 0
|
||||
/* This enables croping use it to test bigger frames */
|
||||
DCMI_CROPCmd(DISABLE);
|
||||
DCMI_CROPInitTypeDef DCMI_CROPInitStructure= {
|
||||
.DCMI_HorizontalOffsetCount = 0,
|
||||
|
||||
@ -69,6 +69,9 @@ enum reset_polarity {
|
||||
ACTIVE_HIGH
|
||||
};
|
||||
|
||||
extern const int res_width[];
|
||||
extern const int res_height[];
|
||||
|
||||
struct sensor_dev {
|
||||
struct sensor_id id;
|
||||
uint16_t vsync_pol;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user