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:
iabdalkader 2014-02-21 23:16:47 +02:00
parent c5ee4bc08a
commit 1e14eacaa2
4 changed files with 91 additions and 43 deletions

View File

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

View File

@ -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__ */

View File

@ -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,55 +362,80 @@ 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 */
sensor.reset(); switch (sensor.reset_pol) {
return 0; case ACTIVE_HIGH:
}
void sensor_hard_reset()
{
/* reset sensor */
GPIO_SetBits(GPIOA, GPIO_Pin_10); GPIO_SetBits(GPIOA, GPIO_Pin_10);
systick_sleep(100); systick_sleep(10);
GPIO_ResetBits(GPIOA, GPIO_Pin_10); GPIO_ResetBits(GPIOA, GPIO_Pin_10);
systick_sleep(1000); systick_sleep(10);
break;
case ACTIVE_LOW:
GPIO_ResetBits(GPIOA, GPIO_Pin_10);
systick_sleep(10);
sensor_reset(sensor); GPIO_SetBits(GPIOA, GPIO_Pin_10);
systick_sleep(10);
break;
}
/* Call sensor-specific reset function */
sensor.reset();
return 0;
} }
int sensor_read_reg(uint8_t reg) int sensor_read_reg(uint8_t reg)
@ -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,

View File

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