iic.cpp
来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C++ 代码 · 共 1,063 行 · 第 1/2 页
CPP
1,063 行
{0x0a,0x9d},
{0x0b,0x02},
{0x0c,0x04},
{0x0d,0x00},
{0x0e,0x20},
{0x0f,0x02},
{0x1b,0x40},
{0x1c,0x40},
//page5
{0xec,0x05},
{0x1f,0x00},
{0x08,0x59},
{0x0a,0x71},
{0x1e,0x00}, // 23 at 20frame
//page6
{0xec,0x06},
{0x00,0x3e},
{0x01,0xa6},
{0x02,0x40},
{0x03,0xcb},
{0x04,0x09},
{0x05,0xdb},
{0x06,0x40},
{0x07,0xf2},
{0x08,0x09},
{0x09,0xdb},
{0x0a,0x40},
{0x0b,0xf2},
//page7
{0xec,0x07},
{0x11,0xfe},
{0x23,0x07},
{0x08,0xff},
{0x09,0x6c},
{0x87,0x00},
{0x21,0xff},
{0x22,0x70},
{0x31,0x05},
{0x38,0x01},
{0x39,0x01},
{0x3a,0xf0},
{0x26,0x04},
{0x27,0x10},
{0x2a,0x10},
{0x2b,0x10},
{0x49,0x02},
{0x59,0x80},
{0x5A,0x04},
{0x5B,0x06},
{0x5C,0x06},
{0x5D,0x06},
{0x5E,0x04},
{0x5F,0x04},
//page0
{0xec,0x00},
{0x0a,0x01},
{0x13,0x20},
{0x14,0x20},
{0x15,0x20},
{0x16,0x20},
{0x17,0x30},
{0x18,0x30},
{0x19,0x20},
{0x1a,0x20},
{0x1b,0x20},
{0x1c,0x20},
{0x1d,0x20},
{0x1e,0x30},
{0x1f,0x30},
{0x20,0x20},
{0x71,0x11},
{0x72,0xaa}, //aa at 20.0Mhz // a2 at 19.2Mhz
{0x61,0xb0},
{0x66,0x01},
{0x6c,0x50},
{0x7c,0x00},
{0x0D,0x24},
{0x7e,0x04},
{0x64,0xf0},
{0x86,0x01},
{0x87,0x00},
{0x76,0x80},
{0x77,0x90},
{0x78,0x6c},
{0x34,0x0d},
{0x35,0x0a},
{0x36,0x05},
{0x37,0x05},
{0x38,0x06},
{0x39,0x08},
{0x3A,0x0a},
{0x3B,0x0a},
{0x3C,0x18},
{0x3D,0xE0},
{0x3E,0x10},
{0x40,0x1d},
{0x41,0x4f},
{0x42,0x24},
{0x43,0x3c},
{0x44,0x34},
{0x45,0x2e},
{0x48,0xb0},
{0x49,0xc0},
{0x4A,0x58},
{0x4B,0x50},
{0x4C,0xe0},
{0x4D,0xc0},
{0x4E,0x30},
{0x4F,0x20},
{0x50,0xb0},
{0x51,0xc0},
{0x52,0x50},
{0x53,0x60},
{0x54,0xe0},
{0x55,0xc0},
{0x56,0x20},
{0x57,0x10},
{0x58,0xa0},
{0x59,0xc0},
{0x5A,0x60},
{0x5B,0x58},
{0x5C,0xe0},
{0x5D,0xc0},
{0x5E,0x45},
{0x5F,0x10},
{0x79,0x00},
{0x7a,0xfe},
{0xe0,0x0f},
{0xe5,0x48},
{0xe3,0x58},
{0x73,0x11},
{0xa4,0x30},
{0xa5,0x30},
{0x7f,0x30},
{0xbb,0x01},
// TotalH : 0858(035a) = 0656(0290) + 0202(00ca)
// TotalV : 0559(022f) = 0508(01fc) + 0051(0033) + [04(04)]
{0xec,0x00},
{0x02,0x00},
{0x03,0x6b},
// gamma : dc8
{0xec,0x01},
{0x24,0x08},
{0x25,0x10},
{0x26,0x40},
{0x27,0x80},
{0x28,0x2C},
{0x29,0xD6},
{0x2A,0x0C},
{0x2B,0xFF},
{0x2C,0x00},
{0x2D,0x5F},
{0xB0,0x08},
{0xB1,0x10},
{0xB2,0x40},
{0xB3,0x80},
{0xB4,0x2C},
{0xB5,0xD6},
{0xB6,0x0C},
{0xB7,0xFF},
{0xB8,0x00},
{0xB9,0x5F},
{0xec,0x00},
{0x77,0xc0}, // color gain
{0x6c,0x30}, // ae target
{0x76,0x7a}, // brightness
{0x78,0x78}, // agc max
{0x73,0x00}, // frame
{0x42,0x26},
{0x43,0x3a},
{0x4a,0x30},
{0xec,0x01},
{0x15,0xfa}, // color matrix
{0x16,0xfd},
{0x20,0xd0}, //high-light color suppress reference
{0x22,0x2f}, //high-light color suppress gain
{0x6d,0x0e}, //yc group delay
{0xec,0x02},
{0x2c,0x82}, // adlc
{0x27,0x37},
{0xec,0x02},
{0x14,0x01},
{0x15,0xcf},
{0xec,0x03},
{0x08,0x01},
{0x09,0xcf},
{0xec,0x00},
{0xec,0x00},
{0x0c,0x6a},
{0x73,0x41},
// added by junon
{0xec,0x01},
{0x10,0x26}, // 0x21-ITU-R656(CbYCrY), 0x25-ITU-R601(CbYCrY), 0x26-ITU-R601(YCrYCb)
#endif
};
extern void Camera_Initialize(void);
extern volatile S3C24A0_IOPORT_REG *s24A0IOP;
extern volatile S3C24A0_IICBUS_REG *s24A0IIC;
extern volatile S3C24A0_INTR_REG *s24A0INT;
extern volatile S3C24A0_CLKPWR_REG *s24A0PWR;
void Camera_Initialize(void);
void Delay(int time);
void SetCAMClockDivider(int divn);
void CAM_WriteBlock(void);
void Wr_CamIIC(U32 slvAddr, U32 addr, U8 data);
void Rd_CamIIC(U32 slvAddr, U32 addr, U8 *data);
void Run_IicPoll(void);
void IicPoll(void);
static HANDLE IIC_InterruptEvent = NULL;
void Camera_Initialize(void)
{
UINT Irq = 0;
if (IIC_InterruptEvent == NULL)
{
// allocate the interrupt event for IIC
IIC_InterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
if (NULL == IIC_InterruptEvent)
{
RETAILMSG(RETAIL_ON,(TEXT("IIC interrupt event Error1\r\n")));
}
// Obtain sysintr values from the OAL for the camera interrupt.
//
Irq = IRQ_IIC;
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(UINT32), &gIntrIIC, sizeof(UINT32), NULL))
{
RETAILMSG(RETAIL_ON, (TEXT("ERROR: Failed to request the iic sysintr.\r\n")));
gIntrIIC = SYSINTR_UNDEFINED;
}
// initialize the interrupt to the event
if (!InterruptInitialize (gIntrIIC, IIC_InterruptEvent, NULL, 0))
{
RETAILMSG(RETAIL_ON,(TEXT("IIC interrupt event Error2\r\n")));
}
}
RETAILMSG(RETAIL_ON,(TEXT("Use IIC for initialization\r\n")));
// Use IIC for initialization
CAM_WriteBlock();
}
void SetCAMClockDivider(int divn) // divn is even number 0~15
{
s24A0PWR->CLKDIVN = (s24A0PWR->CLKDIVN & ~(0xf00)) | ((divn & 0xf)<<8); // CAMCLK is divided..
}
void CamIIC_open(void)
{
//Enable ACK, Prescaler IICCLK=PCLK/512, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
s24A0IIC->IICCON = (1<<7) | (1<<6) | (1<<5) | ~(1<<4) | (0x3);
RETAILMSG(RETAIL_ON, (TEXT("---------------------- s24A0IIC->IICSTAT 0x%x\r\n"), s24A0IIC->IICSTAT));
s24A0IIC->IICSTAT &= ~(1<<4); //disable serial output before setting IICADD
s24A0IIC->IICADD = 0x10; //24A0 slave address = [7:1]
s24A0IIC->IICSTAT = 0x10; //IIC bus data output enable(Rx/Tx)
s24A0IIC->SDADLY = (1<<2)|(3); // SDAOUT has 5clock cycle delay
RETAILMSG(RETAIL_ON, (TEXT("IICCON = 0x%x IICSTAT = 0x%x IICADD = 0x%x IICDS = 0x%x\r\n"), s24A0IIC->IICCON, s24A0IIC->IICSTAT, s24A0IIC->IICADD, s24A0IIC->IICDS));
}
void CAM_WriteBlock(void)
{
static U8 rdata[256];
int err = 0;
int i;
CamIIC_open();
// RETAILMSG(RETAIL_ON, (TEXT("IICCON = 0x%x IICSTAT = 0x%x IICADD = 0x%x IICDS = 0x%x\r\n"), s24A0IIC->IICCON, s24A0IIC->IICSTAT, s24A0IIC->IICADD, s24A0IIC->IICDS));
// RETAILMSG(RETAIL_ON,(_T("Inside CAM_WriteBlock(), size = %d\r\n"), sizeof(S5X532_YCbCr8bit_TV)/2));
// for(i=0; i<(sizeof(S5X532_YCbCr8bit_TV)/2); i++)
// {
//RETAILMSG(RETAIL_ON,(TEXT("num:%d\r\n"),i));
// Wr_CamIIC(SlaveID, S5X532_YCbCr8bit_TV[i][0], S5X532_YCbCr8bit_TV[i][1]);
// Sleep(1);
// }
for(i=0; i<(sizeof(_OV9650_Init)/2); i=i+2)
{
Wr_CamIIC(SlaveID, _OV9650_Init[i], _OV9650_Init[i+1]);
Sleep(1);
}
for(i=0; i<(sizeof(_OV9650_Init_CIF)/2); i=i+2)
{
Wr_CamIIC(SlaveID, _OV9650_Init_CIF[i], _OV9650_Init_CIF[i+1]);
Sleep(1);
}
#if 0
//-------------------------------------------------------------------
// Routines for IIC Read/Write test start
for(i=1; i<10; i++)
{
//RETAILMSG(RETAIL_ON,(TEXT("num:%d "),i));
if (S5X532_YCbCr8bit_TV[i][0] != 0xec)
Wr_CamIIC(SlaveID, S5X532_YCbCr8bit_TV[i][0], S5X532_YCbCr8bit_TV[i][1]);
else
Rd_CamIIC(SlaveID, S5X532_YCbCr8bit_TV[i][0], &rdata[i]);
Sleep(1);
}
for(i=1; i<10; i++)
{
if (S5X532_YCbCr8bit_TV[i][0] != 0xec)
RETAILMSG(RETAIL_ON,(_T("Page : 0x%x\r\n"), S5X532_YCbCr8bit_TV[i][1]));
else
{
RETAILMSG(RETAIL_ON,(_T("Addr: 0x%x, W: 0x%x, R: 0x%x\r\n"), S5X532_YCbCr8bit_TV[i][0], S5X532_YCbCr8bit_TV[i][1], rdata[i]));
if (S5X532_YCbCr8bit_TV[i][1] != rdata[i]) err++;
}
}
if (err) RETAILMSG(RETAIL_ON,(_T("IIC Wr/Rd Error !!!! %d\r\n"), i));
else RETAILMSG(RETAIL_ON,(_T("IIC Wr/Rd Success !!!!\r\n")));
// Routines for IIC Read/Write test end
//-------------------------------------------------------------------
#endif
RETAILMSG(RETAIL_ON,(TEXT("Block TX Ended...\r\n")));
}
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
s24A0IIC->IICDS = slvAddr; //0x5a
// After this time, timing is critical, because IIC start.
s24A0IIC->IICSTAT = 0xf0; //Start Master TX Condition
s24A0IIC->IICCON = 0xef; //Clearing the pending bit isn't needed because the pending bit has been cleared.
// RETAILMSG(RETAIL_ON,(_T("Inside Wr_CamIIC(), before while, _iicDataCount = %d\r\n"), _iicDataCount));
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
s24A0IIC->IICDS = slvAddr; //0x42: OV7620 Slave ID
// After this time, timing is critical, because IIC start.
s24A0IIC->IICSTAT = 0xf0; //Start Master TX Condition
s24A0IIC->IICCON = 0xef; //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;
s24A0IIC->IICDS = slvAddr;
s24A0IIC->IICSTAT = 0xb0; //Master Rx,Start
s24A0IIC->IICCON = 0xef; //Resumes IIC operation.
while(_iicDataCount!=-1)
Run_IicPoll();
*data = _iicData[1];
}
void Run_IicPoll(void)
{
DWORD waitStatus;
// RETAILMSG(RETAIL_ON, (TEXT("In Run_IicPoll, waiting for IIC_InterruptEvent\r\n")));
// When using Interrupt mode
waitStatus = WaitForSingleObject(IIC_InterruptEvent, INFINITE);
// When using polling mode
// if(s24A0IIC->IICCON & 0x10) //Tx/Rx Interrupt Enable
// RETAILMSG(RETAIL_ON, (TEXT("In Run_IicPoll, IIC_InterruptEvent wait over\r\n")));
IicPoll();
}
void IicPoll(void)
{
// RETAILMSG(RETAIL_ON,(TEXT("IicPoll --> IIC Interrupt occur\r\n")));
switch(_iicMode)
{
case RDDATA:
if((_iicDataCount--)==0)
{
_iicData[_iicPt++] = s24A0IIC->IICDS;
s24A0IIC->IICSTAT = 0x90; //Stop MasRx condition
s24A0IIC->IICCON = 0xef; //Resumes IIC operation.
Delay(10); //Wait until stop condtion is in effect., Too long time...
//The pending bit will not be set after issuing stop condition.
break;
}
_iicData[_iicPt++] = s24A0IIC->IICDS; //The last data has to be read with no ack.
if((_iicDataCount)==0)
s24A0IIC->IICCON = 0x6f; //Resumes IIC operation with NOACK in case of OV7620 Cameara
else
s24A0IIC->IICCON = 0xef; //Resumes IIC operation with ACK
break;
case WRDATA:
if((_iicDataCount--)==0)
{
s24A0IIC->IICSTAT = 0xd0; //stop MasTx condition
s24A0IIC->IICCON = 0xef; //resumes IIC operation.
Delay(10); // we should adjust this time.
//The pending bit will not be set after issuing stop condition.
break;
}
s24A0IIC->IICDS = _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(RETAIL_ON,(TEXT("BB"))); // we should adjust this time.
s24A0IIC->IICCON = 0xef; //resumes IIC operation.
break;
case SETRDADDR:
if((_iicDataCount--)==0)
{
s24A0IIC->IICSTAT = 0xd0; //stop MasTx condition
s24A0IIC->IICCON = 0xef; //resumes IIC operation.
Delay(1); //wait until stop condtion is in effect.
break; //IIC operation is stopped because of IICCON[4]
}
s24A0IIC->IICDS = _iicData[_iicPt++];
Delay(10);
//for(i=0;i<1000;i++); //for setup time until rising edge of IICSCL
//RETAILMSG(RETAIL_ON,(TEXT("RD"))); // we should adjust this time.
s24A0IIC->IICCON = 0xef; //resumes IIC operation.
break;
default:
break;
}
InterruptDone(gIntrIIC);
}
void Delay(int time)
{
volatile int i;
for(;time>0;time--)
for(i=0;i<100;i++);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?