/* ---------------------------------------------------------------------------- | |
* 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, ®, 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; | |
} |