📄 iic.cpp
字号:
#define SET_SIOD_READ() rGPECON1=(rGPECON1&0x3FFFFFFF)
#define SET_SIOD_WRITE() rGPECON1=(rGPECON1&0x3FFFFFFF)|0x40000000
#define SET_SIOC_READ() rGPECON1=(rGPECON1&0xCFFFFFFF)
#define SET_SIOC_WRITE() rGPECON1=(rGPECON1&0xCFFFFFFF)|0x10000000
static __inline void set_gpio_ctrl(unsigned int gpio)
{
rGPECON1 &= ~(3<<((gpio&0xf)*2));
if(gpio&GPIO_MODE_OUT)
rGPECON1 |= 1<<((gpio&0xf)*2);
if(gpio&GPIO_PULLUP_DIS)
rGPEUP1 |= 1<<(gpio&0xf);
else
rGPEUP1 &= ~(1<<(gpio&0xf));
}
/*********** start of OV7620 ********************/
/* refer to 25p of OV7620 datasheet */
#define OV7620_SCCB_ID 0x60//0x42 /* CS[2:0] = 000 */ //hzh, use variable
#define OV7620_MAX_CLK 24000000 // 24MHz
#define OV7620_PRODUCT_ID 0x7FA2
#define OV7620_SCCB_DELAY 100
#define OV7620_SCCB_DELAY2 100
#define SIO_C (GPIO_E14)
#define SIO_D (GPIO_E15)
#define MAKE_HIGH(_x) write_gpio_bit_set(_x)
#define MAKE_LOW(_x) write_gpio_bit_clear(_x)
#define BIT_READ(_x) read_gpio_bit(_x)
#define CFG_READ(_x) set_gpio_ctrl(_x | GPIO_PULLUP_DIS | GPIO_MODE_IN)
#define CFG_WRITE(_x) set_gpio_ctrl(_x | GPIO_PULLUP_DIS | GPIO_MODE_OUT)
/* 2-wire SCCB */
void __inline ov7620_sccb_start(void)
{
MAKE_HIGH(SIO_C);
MAKE_HIGH(SIO_D);
WAIT_STAB;
MAKE_LOW(SIO_D);
WAIT_STAB;
MAKE_LOW(SIO_C);
WAIT_STAB;
}
/* 2-wire SCCB */
void __inline ov7620_sccb_end(void)
{
MAKE_LOW(SIO_D);
WAIT_STAB;
MAKE_HIGH(SIO_C);
WAIT_STAB;
MAKE_HIGH(SIO_D);
WAIT_STAB;
}
void __inline ov7620_sccb_write_bit(unsigned char bit)
{
if (bit)
MAKE_HIGH(SIO_D);
else
MAKE_LOW(SIO_D);
WAIT_STAB;
MAKE_HIGH(SIO_C);
WAIT_CYL;
MAKE_LOW(SIO_C);
WAIT_STAB;
}
int __inline ov7620_sccb_read_bit(void)
{
int tmp = 0;
MAKE_HIGH(SIO_C);
WAIT_CYL;
tmp = BIT_READ(SIO_D);
MAKE_LOW(SIO_C);
WAIT_STAB;
return tmp;
}
void __inline ov7620_sccb_writechar(unsigned char data)
{
int i = 0;
/* data */
for (i = 0; i < 8; i++ ) {
ov7620_sccb_write_bit(data & 0x80);
data <<= 1;
}
/* 9th bit - Don't care */
ov7620_sccb_write_bit(1);
}
void __inline ov7620_sccb_readchar(unsigned char *val)
{
int i;
int tmp = 0;
CFG_READ(SIO_D);
for (i = 7; i >= 0; i--)
tmp |= ov7620_sccb_read_bit() << i;
CFG_WRITE(SIO_D);
/* 9th bit - N.A. */
ov7620_sccb_write_bit(1);
*val = tmp & 0xff;
}
/* 3-phase write */
static void ov7620_sccb_sendbyte(unsigned char subaddr, unsigned char data)
{
// down(&dev.bus_lock);
ov7620_sccb_start();
ov7620_sccb_writechar(OV7620_SCCB_ID);
ov7620_sccb_writechar(subaddr);
ov7620_sccb_writechar(data);
ov7620_sccb_end();
mdelay(1);
// up(&dev.bus_lock);
}
/* 2-phase read */
static unsigned char ov7620_sccb_receivebyte(unsigned char subaddr)
{
unsigned char value;
// down(&dev.bus_lock);
/* 2-phase write */
ov7620_sccb_start();
ov7620_sccb_writechar(OV7620_SCCB_ID);
ov7620_sccb_writechar(subaddr);
ov7620_sccb_end();
/* 2-phase read */
ov7620_sccb_start();
ov7620_sccb_writechar(OV7620_SCCB_ID | 0x01);
ov7620_sccb_readchar(&value);
ov7620_sccb_end();
//msWait(7);
mdelay(7);
// up(&dev.bus_lock);
return value;
}
void ReadCameraProductID(void)
{
U8 id ;
id = 0 ;
//s2440CLKPW->rCLKCON |= 0x80000;
s2440IOP->rGPGCON &= 0xFCFFFFFF ;
s2440IOP->rGPGCON |= (1<<24) ;
s2440IOP->rGPGUP |= (1<<12) ;
s2440IOP->rGPGDAT &= ~(1<<12) ;
//s2440IOP->rGPECON &= ~(0xF<<28); //GPE15:IICSDA , GPE14:IICSCL
//s2440IOP->rGPECON |= (0xa<<28); //GPE15:IICSDA , GPE14:IICSCL
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
//s2440IIC->rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
// s2440IIC->rIICADD = 0x10; //2440 slave address = [7:1]. this is avialable when 240 is slave.
// s2440IIC->rIICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
// s2440IIC->rIICLC = (1<<2)|(3); // Filter enable, 15 clocks SDA output delay added into 2440
CFG_WRITE(SIO_C);
CFG_WRITE(SIO_D);
mdelay(10);
id = ov7620_sccb_receivebyte(10);
RETAILMSG(1,(TEXT("ID=0x%x\r\n"),id));
//Rd_CamIIC(SlaveID,10,&id) ;
// RETAILMSG(1,(TEXT("------------------\r\n")));
// RETAILMSG(1,(TEXT("Product ID = 0x%x\r\n"), id));
}
void Camera_Initialize(void)
{
/*
if (IIC_InterruptEvent == NULL)
{
// allocate the interrupt event for IIC
IIC_InterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == IIC_InterruptEvent) {
RETAILMSG(1,(TEXT("IIC interrupt event Error1\r\n")));
}
// initialize the card insertion interrupt event
if (!InterruptInitialize (SYSINTR_IIC, IIC_InterruptEvent, NULL, 0)) {
RETAILMSG(1,(TEXT("IIC interrupt event Error2\r\n")));
}
}
*/
RETAILMSG(1,(TEXT("Use IIC for initialization\r\n")));
/*
CFG_WRITE(SIO_C);
CFG_WRITE(SIO_D);
mdelay(10);
s2440IOP->rGPGCON &= 0xFCFFFFFF ;
s2440IOP->rGPGCON |= (1<<24) ;
s2440IOP->rGPGUP |= (1<<12) ;
s2440IOP->rGPGDAT &= ~(1<<12) ;
*/
ReadCameraProductID();
ReadCameraProductID();
ReadCameraProductID();
ReadCameraProductID();
ReadCameraProductID();
// Use IIC for initialization
CAM_WriteBlock();
}
void SetCAMClockDivider(int divn) // divn is even number 0~15
{
volatile CLKPWRreg *s2440PWR = (CLKPWRreg *)CLKPWR_BASE;
s2440PWR->rCAMDIVN = (s2440PWR->rCAMDIVN & ~(0xf))|(0x10)|(divn); // CAMCLK is divided..
// RETAILMSG(1,(TEXT("s2440PWR->rCLKCON:0x%x\r\n"),s2440PWR->rCLKCON));
}
void CAM_WriteBlock(void)
{
/*
unsigned int i, save_E, save_PE;
static U8 rdata[256];
int err = 0;
s2440CLKPW->rCLKCON |= 0x80000;
save_E = s2440IOP->rGPECON;
save_PE = s2440IOP->rGPEUP;
//s2440IOP->rGPEUP &= ~0xc000; //Pull-up disable
//s2440IOP->rGPEUP |= 0xc000; //Pull-up disable
s2440IOP->rGPECON &= ~(0xF<<28); //GPE15:IICSDA , GPE14:IICSCL
s2440IOP->rGPECON |= (0xa<<28); //GPE15:IICSDA , GPE14:IICSCL
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
s2440IIC->rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
s2440IIC->rIICADD = 0x10; //2440 slave address = [7:1]. this is avialable when 240 is slave.
s2440IIC->rIICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
s2440IIC->rIICLC = (1<<2)|(3); // Filter enable, 15 clocks SDA output delay added into 2440
for(i=0; i<(sizeof(S5X532_YCbCr8bit_TV)/2); i++){
//RETAILMSG(1,(TEXT("num:%d\r\n"),i));
Wr_CamIIC(SlaveID, S5X532_YCbCr8bit_TV[i][0], S5X532_YCbCr8bit_TV[i][1]);
Sleep(1);
}
RETAILMSG(1,(TEXT("Block TX Ended...\r\n")));
s2440IOP->rGPEUP = save_PE;
s2440IOP->rGPECON = save_E;
*/
int i;
for (i = 0; i < OV9650_REGS; i++) {
if (ov9650_reg[i].subaddr == CHIP_DELAY)
Delay(ov9650_reg[i].value);
//mdelay(ov9650_reg[i].value);
else
ov7620_sccb_sendbyte(ov9650_reg[i].subaddr & 0xff
, ov9650_reg[i].value & 0xff);
}
}
void Wr_CamIIC(U32 slvAddr, U32 addr, U8 data)
{
_iicMode = WRDATA;
_iicPt = 0;
_iicData[0] = (U8)addr;
_iicData[1] = data;
_iicDataCount = 2;
// write slave address
s2440IIC->rIICDS = slvAddr; //0x42: OV7620 Slave ID
// After this time, timing is critical, because IIC start.
s2440IIC->rIICSTAT = 0xf0; //Start Master TX Condition
s2440IIC->rIICCON = 0xAf; //Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1)
Run_IicPoll();
}
void Rd_CamIIC(U32 slvAddr,U32 addr,U8 *data){ /*IIC Slave Addr Write + IIC Reg Addr Write */ _iicMode = SETRDADDR; _iicPt = 0; _iicData[0] = (U8)addr; _iicDataCount = 1;
// write slave address
s2440IIC->rIICDS = (slvAddr<<1)&0; //0x42: OV7620 Slave ID
// After this time, timing is critical, because IIC start.
s2440IIC->rIICSTAT = 0xf0; //Start Master TX Condition
s2440IIC->rIICCON = 0xAf; //Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1)
Run_IicPoll();
_iicMode = RDDATA;
_iicPt = 0;
_iicDataCount = 1;
s2440IIC->rIICDS = (slvAddr<<1)&1;
s2440IIC->rIICSTAT = 0xb0; //Master Rx,Start
s2440IIC->rIICCON = 0xAf; //Resumes IIC operation.
while(_iicDataCount!=-1)
Run_IicPoll();
*data = _iicData[1];
RETAILMSG(1,(TEXT("Data0:0x%x\r\n"),_iicData[0]));
RETAILMSG(1,(TEXT("Data1:0x%x\r\n"),_iicData[1]));
}
void Run_IicPoll(void)
{
DWORD waitStatus;
// When using Interrupt mode
//waitStatus = WaitForSingleObject(IIC_InterruptEvent, INFINITE);
// When using polling mode
if(s2440IIC->rIICCON & 0x10) //Tx/Rx Interrupt Enable
IicPoll();
}
void IicPoll(void)
{
volatile U32 i;
//RETAILMSG(1,(TEXT("IIC Interrupt occur\r\n")));
switch(_iicMode)
{
case RDDATA:
if((_iicDataCount--)==0)
{
_iicData[_iicPt++] = s2440IIC->rIICDS;
s2440IIC->rIICSTAT = 0x90; //Stop MasRx condition
s2440IIC->rIICCON = 0xAf; //Resumes IIC operation.
Delay(20); //Wait until stop condtion is in effect., Too long time...
//The pending bit will not be set after issuing stop condition.
break;
}
_iicData[_iicPt++] = s2440IIC->rIICDS; //The last data has to be read with no ack.
if((_iicDataCount)==0)
s2440IIC->rIICCON = 0x2f; //Resumes IIC operation with NOACK in case of OV7620 Cameara
else
s2440IIC->rIICCON = 0xAf; //Resumes IIC operation with ACK
break;
case WRDATA:
if((_iicDataCount--)==0)
{
s2440IIC->rIICSTAT = 0xd0; //stop MasTx condition
s2440IIC->rIICCON = 0xAf; //resumes IIC operation.
Delay(10); // we should adjust this time.
//The pending bit will not be set after issuing stop condition.
break;
}
s2440IIC->rIICDS = _iicData[_iicPt++]; //_iicData[0] has dummy.
//for setup time until rising edge of IICSCL. we have to adjust this time.
Delay(10);
//for(i=0;i<1000;i++);
// IICDS has to be written before clearing the IIC interrupt pending bit
//RETAILMSG(1,(TEXT("BB"))); // we should adjust this time.
s2440IIC->rIICCON = 0xAf; //resumes IIC operation.
break;
case SETRDADDR:
if((_iicDataCount--)==0)
{
s2440IIC->rIICSTAT = 0xd0; //stop MasTx condition
s2440IIC->rIICCON = 0xAf; //resumes IIC operation.
Delay(1); //wait until stop condtion is in effect.
break; //IIC operation is stopped because of IICCON[4]
}
s2440IIC->rIICDS = _iicData[_iicPt++];
Delay(20);
//for(i=0;i<1000;i++); //for setup time until rising edge of IICSCL
//RETAILMSG(1,(TEXT("RD"))); // we should adjust this time.
s2440IIC->rIICCON = 0xAf; //resumes IIC operation.
break;
default:
break;
}
InterruptDone(SYSINTR_IIC);
}
void Delay(int time)
{
/*
volatile int i;
for(;time>0;time--)
for(i=0;i<100;i++);
*/
volatile int i, j = 0;
volatile static int loop = S2440FCLK/100000;
for(;time > 0;time--)
for(i=0;i < loop; i++) { j++; }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -