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