i2c.c
来自「TVP5150 视频解码芯片驱动包含I2C模拟 VDSP环境」· C语言 代码 · 共 395 行
C
395 行
#include "I2C.h"
/*------------------------------------------------------------------------------
// I2C Peripheral Function Prototypes
//------------------------------------------------------------------------------
void Init(void); // Initialize I2C port
void Start(void); // Sends I2C Start Trasfer
void Stop(void); // Sends I2C Stop Trasfer
bool Write(unsigned char data_out); // Writes data over the I2C bus
bool Read(unsigned char *data_in, bool send_ack);// Reads data from the I2C bus
void SetSCLK(bool state); // Set SCLK to <state>
void SetSDATA(bool state); // Set SDATA to <state>
bool GetSDATA(); // Get SDATA state
*/
//------------------------------------------------------------------------------
// I2C Peripheral Variables
//------------------------------------------------------------------------------
unsigned int Delay = 0x00000000;
unsigned char IdentAddr = 0x0;
//------------------------------------------------------------------------------
// I2C Functions - Master
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Routine: Init
// Inputs: none
// Outputs: none
// Purpose: Initialize I2C for the ADu812C
//------------------------------------------------------------------------------
void INL Init(void)
{
*pFIO_DIR |= SCLK; // Set SCLK as output and SDATA as input/high
*pFIO_POLAR &= ~SDATA; // Enable Active Hight
*pFIO_EDGE &= ~SDATA; // Enable Level Sensitivity
*pFIO_INEN |= SDATA; // Enable SDATA Input Buffer
SetSDATA(1); // Set SDATA as input/high
SetSCLK(1); // Set SCLK high
}
//------------------------------------------------------------------------------
// Routine: Start
// Inputs: none
// Outputs: none
// Purpose: Sends I2C Start Trasfer - "S"
//------------------------------------------------------------------------------
void INL Start(void)
{
// 11182003 - Following line has been added! (Fixed thanks to Andrew Seddon).
// Shouldn't Stop() be setting SCLK high?
SetSCLK(1); // Set SCLK high
SetSDATA(0); // Set SDATA output/low
SetSCLK(0); // Set SCLK low
}
//------------------------------------------------------------------------------
// Routine: Stop
// Inputs: none
// Outputs: none
// Purpose: Sends I2C Stop Trasfer - "P"
//------------------------------------------------------------------------------
void INL Stop(void)
{
SetSDATA(0); // Set SDATA output/low
SetSCLK(1); // Set SCLK high
SetSDATA(1); // Set SDATA as input/high
}
//------------------------------------------------------------------------------
// Routine: Write
// Inputs: data_out
// Outputs: bool
// Purpose: Writes data over the I2C bus and return status.
//------------------------------------------------------------------------------
bool INL Write(unsigned char data_out)
{
unsigned char index;
// An I2C output byte is bits 7-0 (MSB to LSB). Shift one bit at a time to
// the SDATA output, and then clock the data to the I2C Slave device.
// Send 8 bits out the port
for(index = 0; index < 8; index++)
{
// Output the data bit to the device
SetSDATA(((data_out & 0x80) ? 1 : 0));
data_out <<= 1; // Shift the byte by one bit
SetSCLK(1); // Set SCLK high
SetSCLK(0); // Set SCLK low
}
SetSDATA(1); // Set SDATA input/high
SetSCLK(1); // Set SCLK high
if (!GetSDATA())
{
SetSCLK(0); // Set SCLK low
return true; // ACK from slave
} else
{
SetSCLK(0); // Set SCLK low
return false; // NACK from slave
}
}
//------------------------------------------------------------------------------
// Routine: Read
// Inputs: *data_in, send_ack (if true send the ACK signal else send NACK)
// Outputs: bool
// Purpose: Reads data from the I2C bus and return it in data_in.
// Returns status.
//------------------------------------------------------------------------------
bool INL Read(unsigned char *data_in, bool send_ack)
{
unsigned char index;
*data_in = 0x00;
SetSDATA(1); // Set SDATA input/high
SetSCLK(0); // Set SCLK low
// Get 8 bits from the device
for(index = 0; index < 8; index++)
{
*data_in <<= 1; // Shift the data right 1 bit
SetSCLK(1); // Set SCLK high
// 11182003 - Line moved...
// SetSCLK(0); // Set SCLK low
*data_in |= GetSDATA(); // Read the data bit
// 11182003 - to here! (Fixed thanks to Andrew Seddon).
SetSCLK(0); // Set SCLK low
}
if (send_ack)
SetSDATA(0); // Set data pin to output/low to ACK the read
else
SetSDATA(1); // Set data pin to input/high to NACK the read
SetSCLK(1); // Set SCLK high
SetSCLK(0); // Set SCLK low
SetSDATA(0); // Set SDATA output/low
SetSDATA(1); // Set SDATA input/high
return true;
}
//------------------------------------------------------------------------------
// Routine: SetSDATA
// Inputs: state
// Outputs: none
// Purpose: Set the I2C port SDATA pin to <state>.
//------------------------------------------------------------------------------
void INL SetSDATA(bool state)
{
unsigned int i, d;
if (state)
{
*pFIO_DIR &= ~SDATA; // Set SDATA as input/high.
} else
{
*pFIO_DIR |= SDATA; // Set SDATA as output.
*pFIO_FLAG_D &= ~SDATA; // Set SDATA low.
}
// Delay
for (i = 0; i < Delay; i++) { asm("nop;"); }
}
//------------------------------------------------------------------------------
// Routine: SetSCLK
// Inputs: state
// Outputs: none
// Purpose: Set the I2C port SCLK pin to <state>.
//------------------------------------------------------------------------------
void INL SetSCLK(bool state)
{
unsigned int i, d;
if (state)
{
*pFIO_FLAG_D |= SCLK; // Set SCLK high.
} else
{
*pFIO_FLAG_D &= ~SCLK; // Set SCLK low.
}
// Delay
for (i = 0; i < Delay; i++) { asm("nop;"); }
}
//------------------------------------------------------------------------------
// Routine: GetSDATA
// Inputs: none
// Outputs: bool
// Purpose: Get the I2C port SDATA pin state.
//------------------------------------------------------------------------------
bool INL GetSDATA()
{
return ((*pFIO_FLAG_D & SDATA) ? 1 : 0);
}
//------------------------------------------------------------------------------
// Procedure: I2C_Init
// Inputs: identaddr
// Outputs: bool
// Description: Initialize I2C and setup Slave Ident Addr. then check the ident
// for response and returns true if ok.
//------------------------------------------------------------------------------
bool I2C_Init(unsigned char identaddr)
{
bool ret;
// Calculate Delay NEED FIX!!!
Delay = ((*pPLL_CTL & 0x7e00) >> 9)*15;
//Delay = 0x1000;
if ((*pPLL_CTL & 0x0001) == 0x0001)
Delay /= 2;
IdentAddr = identaddr;
Init(); // Initialize I2C port
Start(); // Check Slave Ident Addr
ret = Write(IdentAddr);
Stop();
return ret; // Return true if Ident Addr. Ok
}
//------------------------------------------------------------------------------
// Procedure: I2C_Write
// Inputs: data out, address
// Outputs: bool
// Description: Writes a byte to the given address and return status.
//------------------------------------------------------------------------------
extern bool I2C_Write(unsigned char data_out, unsigned char address)
{
Start(); // Send start signal
if (!Write(IdentAddr)) // Send identifier I2C address
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
if (!Write(address)) // Send address to device
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
if (!Write(data_out)) // Send byte to device
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
Stop(); // Send I2C Stop Transfer
// DelayTVP5150();
return true;
}
//------------------------------------------------------------------------------
// Procedure: I2C_Read
// Inputs: *data_in, address
// Outputs: bool
// Description: Reads a byte from the given address and return status.
//------------------------------------------------------------------------------
bool I2C_Read(unsigned char *data_in, unsigned char address)
{
Start(); // Send start signal
if (!Write(IdentAddr)) // Send identifer I2C address
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
if (!Write(address)) // Send address to device
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
Start(); // Send I2C Start Transer
if (!Write(IdentAddr+1)) // Send identifer I2C address
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
if (!Read(data_in, false)) // Read byte
{
Stop(); // Send I2C Stop Transfer
return false;
}
DelayTVP5150();
Stop(); // Send I2C Stop Transfer
return true;
}
void INL DelayTVP5150()
{
asm("p0.l=0x57C0;");
asm("p0.h=0x1;");
asm("lsetup(_delay_begin,_delay_end) lc0=p0;");
asm("_delay_begin:");
asm("_delay_end:");
asm("nop;");
}
//------------------------------------------------------------------------------
// Procedure: TVP5150_Reset
// Inputs: bReset
// Outputs: bool
// Description: Reset TVP5150,bReset = 1 is reset =0 is cancel
// returns true if ok.
//Reset address is 0x05h
//------------------------------------------------------------------------------
bool TVP5150_Reset(bool bReset)
{
bool Status;
I2C_Init(0xB8);//0xBA for high I2CSEL
if(bReset){
Status = I2C_Write(0x01,0x05);
return Status;
}
else return true;
}
//------------------------------------------------------------------------------
// Procedure: TVP5150_Cnfg
// Inputs: SourceMode:
// 0:from A Channel input the Composite analog Video signal
// 1:from B Channel input the Composite analog Video signal
// 2:from A and B Channel input luma and chroma signal
// else: nothing
// OutputMode:
// 0:output ITU-R.BT601 PAL-N signal 625
// 1:output ITU-R.BT601 PAL-M signal 625
// 2:output ITU-R.BT601 NTSC signal 525
// 3:output ITU-R.BT601 SECAM signal 625
// 4:output ITU-R.BT656 NTSC signal 525
// 5:output ITU-R.BT656 PAL signal 625
// other:not support
// Outputs: bool
// 0=ok,1=error
// Description:
// Set TVP5150 signal input channel and output signal format.
// and set other correlative register
//------------------------------------------------------------------------------
bool TVP5150_Cnfg(int SourceMode, int OutputMode)
{
bool Status;
//unsigned char temp;
switch(SourceMode){
case 0:
Status = I2C_Write(0x0,0x0);
break;
case 1:
Status = I2C_Write(0x02,0x0);
break;
case 2:
Status = I2C_Write(0x01,0x0);
break;
default:
}
switch(OutputMode){
case 0: // 601 PAL-N
Status = I2C_Write(0x0f,0x03);
Status = I2C_Write(0xf4,0x04);
Status = I2C_Write(0x40,0x0d);
break;
case 1://601 PAL-M
Status = I2C_Write(0x0f,0x03);
Status = I2C_Write(0x0f,0x04);
Status = I2C_Write(0x40,0x0d);
break;
case 2://601 NTSC
Status = I2C_Write(0x0f,0x03);
Status = I2C_Write(0xec,0x04);
Status = I2C_Write(0x40,0x0d);
break;
case 3://601 SECAM
Status = I2C_Write(0x0f,0x03);
Status = I2C_Write(0xdc,0x04);
Status = I2C_Write(0x40,0x0d);
break;
case 4://656 NTSC
Status = I2C_Write(0x29,0x03);
Status = I2C_Write(0xec,0x04);
Status = I2C_Write(0x47,0x0d);
Status = I2C_Write(0x40,0x07);//insert ancilly header
break;
case 5://656 PAL
Status = I2C_Write(0x7f,0x03);
// Status = I2C_Write(0xc0,0x04);
Status = I2C_Write(0x40,0x07);//insert ancilly header
Status = I2C_Write(0x47,0x0d);
Status = I2C_Write(0x0,0x0f);
break;
default:
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?