blob: fbb631f6312849dcbe95702b39e7397373049b26 [file] [log] [blame]
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2013, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/** Slave address of OMNIVISION chips. */
#define OV_CAPTOR_ADDRESS_1 0x30
#define OV_CAPTOR_ADDRESS_2 0x21
#define OV_CAPTOR_ADDRESS_3 0x3c
#define OV_CAPTOR_ADDRESS_4 0x10
/** terminating list entry for register in configuration file */
#define OV_REG_TERM 0xFF
#define OV_REG_DELAY 0xFFFF
/** terminating list entry for value in configuration file */
#define OV_VAL_TERM 0xFF
//static const Pin pin_ISI_RST= PIN_ISI_RST;
static uint8_t twiSlaveAddr = OV_CAPTOR_ADDRESS_1;
/*----------------------------------------------------------------------------
* Local Functions
*----------------------------------------------------------------------------*/
static void ov_reset(void)
{
volatile uint32_t i;
//PIO_Configure(&pin_ISI_RST, 1);
//PIO_Clear(&pin_ISI_RST);
for(i = 0; i < 6000; i++ );
//PIO_Set(&pin_ISI_RST);
for(i = 0; i<6000; i++ );
}
/**
* \brief Read PID and VER
* \param pTwid TWI interface
* \return VER | (PID<<8)
*/
static uint16_t ov_id8(Twid *pTwid)
{
uint8_t id, ver;
uint8_t status;
// OV_PID
status = ov_read_reg8(pTwid, 0x0A, &id);
if( status != 0 ) return 0;
TRACE_INFO("PID = 0x%X\n\r", id);
// OV_VER
status = ov_read_reg8(pTwid, 0x0B, &ver);
if( status != 0 ) return 0;
TRACE_INFO("VER = 0x%X\n\r", ver);
return((uint16_t)(id <<8) | ver);
}
/**
* \brief Read PID and VER
* \param pTwid TWI interface
* \return VER | (PID<<8)
*/
static uint16_t ov_id16(Twid *pTwid)
{
uint8_t id, ver;
// OV_PID
ov_read_reg16(pTwid, 0x300A, &id);
TRACE_INFO("PID = 0x%X\n\r", id);
// OV_VER
ov_read_reg16(pTwid, 0x300B, &ver);
TRACE_INFO("VER = 0x%X\n\r", ver);
return((uint16_t)(id <<8) | ver);
}
/**
* \brief Read PID and VER
* \param pTwid TWI interface
* \return VER | (PID<<8)
*/
static uint16_t ov_id(Twid *pTwid)
{
uint16_t id;
printf("-I- Try TWI address 0x%x \n\r", twiSlaveAddr);
twiSlaveAddr = OV_CAPTOR_ADDRESS_1;
id = ov_id8(pTwid);
if (id == 0) {
twiSlaveAddr = OV_CAPTOR_ADDRESS_2;
printf("-I- Try TWI address 0x%x \n\r", twiSlaveAddr);
id = ov_id8(pTwid);
if (id == 0) {
twiSlaveAddr = OV_CAPTOR_ADDRESS_3;
printf("-I- Try TWI address 0x%x \n\r", twiSlaveAddr);
id = ov_id16(pTwid);
if (id == 0) {
twiSlaveAddr = OV_CAPTOR_ADDRESS_4;
printf("-I- Try TWI address 0x%x \n\r", twiSlaveAddr);
id = ov_id16(pTwid);
}
}
}
return id;
}
/*----------------------------------------------------------------------------
* Global Functions
*----------------------------------------------------------------------------*/
/**
* \brief Read a value from a register in an OV sensor device.
* \param pTwid TWI interface
* \param reg Register to be read
* \param isize Internal address size in bytes.
* \param pData Data read
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint8_t ov_read_reg8(Twid *pTwid, uint8_t reg, uint8_t *pData)
{
uint8_t status;
status = TWID_Write( pTwid, twiSlaveAddr, 0, 0, &reg, 1, 0);
status |= TWID_Read( pTwid, twiSlaveAddr, 0, 0, pData, 1, 0);
if( status != 0 ) {
TRACE_ERROR("ov_read_reg pb\n\r");
}
return status;
}
/**
* \brief Read a value from a register in an OV sensor device.
* \param pTwid TWI interface
* \param reg Register to be read
* \param pData Data read
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint8_t ov_read_reg16(Twid *pTwid, uint16_t reg, uint8_t *pData)
{
uint8_t status;
uint8_t reg8[2];
reg8[0] = reg>>8;
reg8[1] = reg & 0xff;
status = TWID_Write( pTwid, twiSlaveAddr, 0, 0, reg8, 2, 0);
status |= TWID_Read( pTwid, twiSlaveAddr, 0, 0, pData, 1, 0);
if( status != 0 ) {
TRACE_ERROR("ov_read_reg pb\n\r");
}
return status;
}
/**
* \brief Write a value to a register in an OV sensor device.
* \param pTwid TWI interface
* \param reg Register to be writen
* \param pData Data written
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint8_t ov_write_reg8(Twid *pTwid, uint8_t reg, uint8_t val)
{
uint8_t status;
status = TWID_Write(pTwid, twiSlaveAddr, reg, 1, &val, 1, 0);
if( status != 0 ) {
TRACE_ERROR("ov_write_reg pb\n\r");
}
return status;
}
/**
* \brief Write a value to a register in an OV sensor device.
* \param pTwid TWI interface
* \param reg Register to be writen
* \param pData Data written
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint8_t ov_write_reg16(Twid *pTwid, uint16_t reg, uint8_t val)
{
uint8_t status;
status = TWID_Write(pTwid, twiSlaveAddr, reg, 2, &val, 1, 0);
if( status != 0 ) {
TRACE_ERROR("ov_write_reg pb\n\r");
}
return status;
}
/**
* \brief Initialize a list of OV registers.
* The list of registers is terminated by the pair of values
* \param pTwid TWI interface
* \param pReglist Register list to be written
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint32_t ov_write_regs8(Twid *pTwid, const struct ov_reg* pReglist)
{
uint32_t err;
uint32_t size=0;
const struct ov_reg *pNext = pReglist;
volatile uint32_t delay;
TRACE_DEBUG("ov_write_regs:");
while (!((pNext->reg == OV_REG_TERM) && (pNext->val == OV_VAL_TERM))) {
err = ov_write_reg8(pTwid, pNext->reg, pNext->val);
size++;
for(delay=0;delay<=10000;delay++);
if (err == TWID_ERROR_BUSY){
TRACE_ERROR("ov_write_regs: TWI ERROR\n\r");
return err;
}
//printf("(0x%02x,0x%02x) \n\r", pNext->reg,pNext->val);
pNext++;
}
TRACE_DEBUG_WP("\n\r");
return 0;
}
/**
* \brief Initialize a list of OV registers.
* The list of registers is terminated by the pair of values
* \param pTwid TWI interface
* \param pReglist Register list to be written
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint32_t ov_write_regs16(Twid *pTwid, const struct ov_reg* pReglist)
{
uint32_t err = 0;
uint32_t size = 0;
const struct ov_reg *pNext = pReglist;
volatile uint32_t delay;
TRACE_DEBUG("ov_write_regs:");
while (!((pNext->reg == OV_REG_TERM) && (pNext->val == OV_VAL_TERM))) {
err = ov_write_reg16(pTwid, pNext->reg, pNext->val);
size++;
for(delay = 0;delay <= 10000; delay++);
if (err == TWID_ERROR_BUSY){
TRACE_ERROR("ov_write_regs: TWI ERROR\n\r");
return err;
}
//printf("(0x%02x,0x%02x) \n\r", pNext->reg,pNext->val);
pNext++;
}
TRACE_DEBUG_WP("\n\r");
return 0;
}
void isOV5640_AF_InitDone(Twid *pTwid)
{
uint8_t value = 0;
while(1){
ov_read_reg16(pTwid, 0x3029, &value);
if (value == 0x70) break;
}
}
/**
* \brief AF for OV 5640
* \param pTwid TWI interface
* \return 0 if no error; otherwize TWID_ERROR_BUSY
*/
uint32_t ov_5640_AF_single(Twid *pTwid)
{
uint8_t value;
ov_write_reg16(pTwid, 0x3023, 1);
ov_write_reg16(pTwid, 0x3022, 3);
value =1;
while(1){
ov_read_reg16(pTwid, 0x3023, &value);
if (value == 0) break;
}
return 0;
}
uint32_t ov_5640_AF_continue(Twid *pTwid)
{
uint8_t value;
ov_write_reg16(pTwid, 0x3024, 1);
ov_write_reg16(pTwid, 0x3022, 4);
value =1;
while(1){
ov_read_reg16(pTwid, 0x3023, &value);
if (value == 0) break;
}
return 0;
}
uint32_t ov_5640_AFPause(Twid *pTwid)
{
uint8_t value;
ov_write_reg16(pTwid, 0x3023, 1);
ov_write_reg16(pTwid, 0x3022, 6);
value =1;
while(1){
ov_read_reg16(pTwid, 0x3023, &value);
if (value == 0) break;
}
return 0;
}
uint32_t ov_5640_AFrelease(Twid *pTwid)
{
uint8_t value;
ov_write_reg16(pTwid, 0x3023, 1);
ov_write_reg16(pTwid, 0x3022, 8);
value =1;
while(1){
ov_read_reg16(pTwid, 0x3023, &value);
if (value == 0) break;
}
return 0;
}
/**
* \brief Dump all register
* \param pTwid TWI interface
*/
void ov_DumpRegisters8(Twid *pTwid)
{
uint32_t i;
uint8_t value;
TRACE_INFO_WP("Dump all camera register\n\r");
for(i = 0; i <= 0x5C; i++) {
value = 0;
ov_read_reg8(pTwid, i, &value);
TRACE_INFO_WP("[0x%02x]=0x%02x ", i, value);
if( ((i+1)%5) == 0 ) {
TRACE_INFO_WP("\n\r");
}
}
TRACE_INFO_WP("\n\r");
}
/**
* \brief Dump all register
* \param pTwid TWI interface
*/
void ov_DumpRegisters16(Twid *pTwid)
{
uint32_t i;
uint8_t value;
TRACE_INFO_WP("Dump all camera register\n\r");
for(i = 3000; i <= 0x305C; i++) {
value = 0;
ov_read_reg16(pTwid, i, &value);
TRACE_INFO_WP("[0x%02x]=0x%02x ", i, value);
if( ((i+1)%5) == 0 ) {
TRACE_INFO_WP("\n\r");
}
}
TRACE_INFO_WP("\n\r");
}
/**
* \brief Sequence For correct operation of the sensor
* \param pTwid TWI interface
* \return OV type
*/
uint8_t ov_init(Twid *pTwid)
{
uint16_t id = 0;
uint8_t ovType;
ov_reset();
id = ov_id(pTwid);
switch (id) {
case 0x7740: case 0x7742:
ovType = OV_7740;
break;
case 0x9740: case 0x9742:
ovType = OV_9740;
break;
case 0x2642: case 0x2640:
ovType = OV_2640;
break;
case 0x2643:
ovType = OV_2643;
break;
case 0x5640:
ovType = OV_5640;
break;
default:
ovType = OV_UNKNOWN;
TRACE_ERROR("Can not support product ID %x \n\r", id);
break;
}
return ovType;
}