MTK2502平台GPIO模拟I2C实现
#include "kal_release.h"
#include "pxs_custom.h"
#include "drv_comm.h"
#include "us_timer.h"
#include "dcl.h"
extern const char gpio_ms_i2c_clk_pin;
extern const char gpio_ms_i2c_data_pin;
#define MS_SCL gpio_ms_i2c_clk_pin
#define MS_SDA gpio_ms_i2c_data_pin
/******************************************************
I2C header (slaver address|W/R) macro define
*******************************************************/
#define MS_SLAVEADDR_W ((0x33 << 1) + 0) //0x0001 0110 0x18*2
#define MS_SLAVEADDR_R ((0x33 << 1) + 1) //0x0001 0111 0x19
/******************************************************
GPIO macro define for software I2C
*******************************************************/
#define MS_CLK_PIN_GPIO_MODE GPIO_ModeSetup(MS_SCL,0)
#define MS_DATA_PIN_GPIO_MODE GPIO_ModeSetup(MS_SDA,0)
#define MS_I2C_CLK_OUTPUT GPIO_InitIO(OUTPUT,MS_SCL)
#define MS_I2C_DATA_OUTPUT GPIO_InitIO(OUTPUT,MS_SDA)
#define MS_I2C_DATA_INPUT GPIO_InitIO(INPUT,MS_SDA)
#define MS_I2C_CLK_HIGH GPIO_WriteIO(1,MS_SCL)
#define MS_I2C_CLK_LOW GPIO_WriteIO(0,MS_SCL)
#define MS_I2C_DATA_HIGH GPIO_WriteIO(1,MS_SDA)
#define MS_I2C_DATA_LOW GPIO_WriteIO(0,MS_SDA)
#define MS_I2C_GET_BIT GPIO_ReadIO(MS_SDA)
void I2C_DELAY(kal_uint32 delay)
{
kal_uint32 tick, duration;
tick = drv_get_current_time();
do{
duration = drv_get_duration_ms(tick);
}while(duration < delay);
}
void PAH_i2c_udelay(kal_uint32 delay)
{
kal_uint32 ust = 0; //ust_get_current_time
kal_uint32 count = 0;
kal_uint32 break_count = 0;
ust = ust_get_current_time();
do{
if(ust_get_current_time() != ust)
count++;
else
break_count++;
}while((count < delay) && (break_count < 0xFFFFFF));
}
void PAH_i2c_start(void)
{
MS_CLK_PIN_GPIO_MODE;
MS_I2C_CLK_OUTPUT;
MS_DATA_PIN_GPIO_MODE;
MS_I2C_DATA_OUTPUT;
MS_I2C_DATA_HIGH;
MS_I2C_CLK_HIGH;
PAH_i2c_udelay(40); //20
MS_I2C_DATA_LOW;
PAH_i2c_udelay(20); //10
MS_I2C_CLK_LOW;
PAH_i2c_udelay(20); //10
}
void PAH_i2c_stop(void)
{
MS_I2C_CLK_OUTPUT;
MS_I2C_DATA_OUTPUT;
PAH_i2c_udelay(20); //10
MS_I2C_CLK_HIGH;
PAH_i2c_udelay(20); //10
MS_I2C_DATA_HIGH;
}
void PAH_i2c_one_clk(void)
{
PAH_i2c_udelay(10); //5
MS_I2C_CLK_HIGH;
PAH_i2c_udelay(20); //10
MS_I2C_CLK_LOW;
PAH_i2c_udelay(10); //5
}
kal_uint8 pah_ReadByteAck(void)
{
kal_int8 i;
kal_uint8 data;
MS_I2C_DATA_INPUT;
data = 0;
for (i=7; i>=0; i--)
{
if (MS_I2C_GET_BIT)
{
data |= (0x01<<i);
}
PAH_i2c_one_clk();
}
MS_I2C_DATA_OUTPUT;
MS_I2C_DATA_LOW;
PAH_i2c_one_clk();
return data;
}
kal_uint8 pah_ReadByteNAck(void)
{
kal_int8 i;
kal_uint8 data;
MS_I2C_DATA_INPUT;
data = 0;
for (i=7; i>=0; i--)
{
if (MS_I2C_GET_BIT)
{
data |= (0x01<<i);
}
PAH_i2c_one_clk();
}
MS_I2C_DATA_OUTPUT;
MS_I2C_DATA_HIGH;
PAH_i2c_one_clk();
return data;
}
void pah_SendByte(kal_uint8 sData)
{
kal_int8 i;
for (i=7; i>=0; i--)
{
if ((sData>>i)&0x01)
{
MS_I2C_DATA_HIGH;
}
else
{
MS_I2C_DATA_LOW;
}
PAH_i2c_one_clk();
}
}
kal_bool pah_ChkAck(void)
{
MS_I2C_DATA_INPUT;
PAH_i2c_udelay(10); //5
MS_I2C_CLK_HIGH;
PAH_i2c_udelay(10); //5
if(MS_I2C_GET_BIT) //Non-ack
{
PAH_i2c_udelay(10); //5
MS_I2C_CLK_LOW;
PAH_i2c_udelay(10); //5
MS_I2C_DATA_OUTPUT;
MS_I2C_DATA_LOW;
return KAL_FALSE;
}
else //Ack
{
PAH_i2c_udelay(10); //5
MS_I2C_CLK_LOW;
PAH_i2c_udelay(10); //5
MS_I2C_DATA_OUTPUT;
MS_I2C_DATA_LOW;
return KAL_TRUE;
}
}
void pah_Restart(void)
{
MS_I2C_CLK_OUTPUT;
MS_I2C_DATA_OUTPUT;
PAH_i2c_udelay(40);
MS_I2C_DATA_HIGH;
PAH_i2c_udelay(20); //10
MS_I2C_CLK_HIGH;
PAH_i2c_udelay(40);
MS_I2C_DATA_LOW;
PAH_i2c_udelay(20); //10
MS_I2C_CLK_LOW;
PAH_i2c_udelay(20); //10
}
void PAH8001ei_DelayMS(kal_uint16 delay)
{
kal_uint16 i=0;
for(i=0; i<delay; i++)
{
PAH_i2c_udelay(1000);
}
}
/*
* 读寄存器
*/
kal_bool pah8001ei_reg_read( kal_uint8 RegAddr,kal_uint8* Data)
{
PAH_i2c_start(); //start bit
pah_SendByte(MS_SLAVEADDR_W); //slave address|write bit
if(KAL_FALSE == pah_ChkAck()) //check Ack bit
{
//TO_DO: display ack check fail when send write id
//ms_dbg_print(MOD_AUX, "ack fail when send wid in readbytes");
//ms_dbg_print_ps("ack fail when send wid in readbytes\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
pah_SendByte(RegAddr); //send RegAddr
if(KAL_FALSE == pah_ChkAck()) //check Ack bit
{
//TO_DO: display ack check fail when send RegAddr
//ms_dbg_print(MOD_AUX, "ack fail when send Reg in readbytes");
//ms_dbg_print_ps("ack fail when send Reg in readbytes\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
pah_Restart(); //restart bit
pah_SendByte(MS_SLAVEADDR_R); //slave address|read bit
if(KAL_FALSE == pah_ChkAck())
{
//TO_DO: display ack check fail when send read id
//ms_dbg_print(MOD_AUX, "ack fail when send rid in readbytes");
//ms_dbg_print_ps("ack fail when send rid in readbytes\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
*Data = pah_ReadByteNAck();
PAH_i2c_stop(); //stop bit
//TO_DO: add debug code to display the data received
return KAL_TRUE;
}
/*
* 连续读寄存器
*/
kal_bool PAH8001ei_ConReadBytes(kal_uint8* Data, kal_uint8 RegAddr, kal_uint16 Length)
{
kal_uint8* Data_ptr;
kal_uint16 i;
Data_ptr = Data;
PAH_i2c_start(); //start bit
pah_SendByte(MS_SLAVEADDR_W); //slave address|write bit
if(KAL_FALSE == pah_ChkAck()) //check Ack bit
{
//TO_DO: display ack check fail when send write id
//ms_dbg_print(MOD_AUX, "ack fail when send wid in conread");
//ms_dbg_print_ps("ack fail when send wid in conread\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
pah_SendByte(RegAddr); //send RegAddr
if(KAL_FALSE == pah_ChkAck()) //check Ack bit
{
//TO_DO: display ack check fail when send RegAddr
//ms_dbg_print(MOD_AUX, "ack fail when send Reg in conread");
//ms_dbg_print_ps("ack fail when send Reg in conread\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
pah_Restart(); //restart bit
pah_SendByte(MS_SLAVEADDR_R); //slave address|read bit
if(KAL_FALSE == pah_ChkAck())
{
//TO_DO: display ack check fail when send read id
//ms_dbg_print(MOD_AUX, "ack fail when send rid in conread");
//ms_dbg_print_ps("ack fail when send rid in conread\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
for(i=Length; i>1; i--)
{
*Data_ptr = pah_ReadByteAck(); //read byte with ack
Data_ptr++;
}
*Data_ptr = pah_ReadByteNAck(); //read byte with non-ack to stop reading
PAH_i2c_stop(); //stop bit
//TO_DO: add debug code to display the data received
return KAL_TRUE;
}
/*
* 写寄存器
*/
kal_bool pah8001ei_reg_write(kal_uint8 RegAddr, kal_uint8 Data)
{
PAH_i2c_start(); //start bit
pah_SendByte(MS_SLAVEADDR_W); //slave address|write bit
if(KAL_FALSE == pah_ChkAck()) //check Ack bit
{
//TO_DO: display check ack fail when send write id
//ms_dbg_print(MOD_AUX, "ack fail when send wid in writebytes");
//ms_dbg_print_ps("ack fail when send wid in writebytes\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
pah_SendByte(RegAddr); //send RegAddr
if(KAL_FALSE == pah_ChkAck()) //check Ack bit
{
//TO_DO: display check ack fail when send RegAddr
//ms_dbg_print(MOD_AUX, "ack fail when send Reg in wirtebytes");
//ms_dbg_print_ps("ack fail when send Reg in wirtebytes\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
pah_SendByte(Data); //send parameter
if(KAL_FALSE == pah_ChkAck())
{
//TO_DO: display check ack fail when send data
//ms_dbg_print(MOD_AUX, "ack fail when send para in writebytes");
//ms_dbg_print_ps("ack fail when send para in writebytes\n\r");
PAH_i2c_stop();
return KAL_FALSE;
}
PAH_i2c_stop(); //stop bit
return KAL_TRUE;
}
/*
* 写一个寄存器
*/
void writeRegister(kal_uint8 reg_addr, kal_uint8 value)
{
kal_bool ret = KAL_FALSE;
ret = pah8001ei_reg_write(reg_addr, value);
if(ret == KAL_FALSE) {
kal_prompt_trace(MOD_MMI, "[LXZ]writeRegister error reg_addr = %x, value = %x", reg_addr, value);
}
}
/*
* 读一个寄存器
*/
kal_uint8 readRegister(kal_uint8 reg_addr)
{
kal_uint8 temp = 0;
kal_bool ret = KAL_FALSE;
ret = pah8001ei_reg_read(reg_addr, &temp);
if (ret == KAL_FALSE) {
kal_prompt_trace(MOD_MMI, "[LXZ]readRegister error reg_addr = %x value = %x", reg_addr, temp);
}
return temp;
}
/*
* 读多寄存器
*/
void readRegisterCont(kal_uint8 reg_addr, kal_uint8 *buffer, kal_uint8 length)
{
kal_bool ret = KAL_FALSE;
ret = PAH8001ei_ConReadBytes(buffer, reg_addr, length);
if (ret == KAL_FALSE) {
kal_prompt_trace(MOD_MMI, "[LXZ]readRegisterCont error reg_addr = %x", reg_addr);
}
}