📄 soft_i2c.c
字号:
/*******************************************************************
*
* Copyright C 2006 by Amlogic, Inc. All Rights Reserved.
*
* Description: soft_i2c.c
*
* Author: Amlogic Software
* Created: 11/1/2007
*
*******************************************************************/
#include "includes.h"
#include "ioapi.h"
#include "Drivers/i2c/soft_i2c.h"
soft_i2c_para_t soft_i2c_para = {
SOFT_I2C_MAGIC, // unsigned magic;
"/dev/soft_i2c", //char *device_name
0xa0, //unsigned char device_id;
0xff, //unsigned char id_mask;
0, //unsigned char i2c_flag
512, //unsigned max_addr;
70, //100, //unsigned delay; //i2x speed is about 80khz
0x012000A0, //unsigned scl_en_reg; //FEC_D_0 is muxed to scl
0x20000000, //unsigned scl_en_mask;
0x012000A4, //unsigned scl_output_reg;
0x20000000, //unsigned scl_output_mask;
0x012000A8, //unsigned scl_input_reg;
0x20000000, //unsigned scl_input_mask;
0x012000A0, //unsigned sda_en_reg; //FEC_D_1 is muxed to sda
0x10000000, //unsigned sda_en_mask;
0x012000A4, //unsigned sda_output_reg;
0x10000000, //unsigned sda_output_mask;
0x012000A8, //unsigned sda_input_reg;
0x10000000, //unsigned sda_input_mask;
};
#define set_scl_output (*(volatile unsigned *)soft_i2c_para.scl_en_reg &= ~soft_i2c_para.scl_en_mask)
#define set_scl_outputlevel(data) {if(data){*(volatile unsigned *)soft_i2c_para.scl_output_reg |= soft_i2c_para.scl_output_mask;}else{*(volatile unsigned *)soft_i2c_para.scl_output_reg &= ~soft_i2c_para.scl_output_mask;}}
#define set_scl_input (*(volatile unsigned *)soft_i2c_para.scl_en_reg |= soft_i2c_para.scl_en_mask)
#define get_scl_input_level ((*(volatile unsigned *)soft_i2c_para.scl_input_reg & soft_i2c_para.scl_input_mask)?1:0)
#define set_sda_output (*(volatile unsigned *)soft_i2c_para.sda_en_reg &= ~soft_i2c_para.sda_en_mask)
#define set_sda_outputlevel(data) {if(data){*(volatile unsigned *)soft_i2c_para.sda_output_reg |= soft_i2c_para.sda_output_mask;}else{*(volatile unsigned *)soft_i2c_para.sda_output_reg &= ~soft_i2c_para.sda_output_mask;}}
#define set_sda_input (*(volatile unsigned *)soft_i2c_para.sda_en_reg |= soft_i2c_para.sda_en_mask)
#define get_sda_input_level ((*(volatile unsigned *)soft_i2c_para.sda_input_reg & soft_i2c_para.sda_input_mask)?1:0)
#define I2C_RETRY_TIME 3
#define I2C_PAGE_SIZE 8
//#define I2C_PAGE_MOD 7
static OS_EVENT *swi2c_mutex;
static void soft_i2c_Delay(unsigned int delay_count)
{
if(delay_count)
while(delay_count--);
}
static void soft_i2c_Start(void)
{
/* A HIGH to LOW transition on the SDA line while SCL is
* HIGH indicates a START condition.
*/
set_sda_outputlevel(0);
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay << 2) ;
set_scl_outputlevel(0);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay << 1) ;
return ;
}
static void soft_i2c_ReStart(void)
{
/* A HIGH to LOW transition on the SDA line while SCL is
* HIGH indicates a START condition.
*/
set_scl_outputlevel(0); //talk->set_sda(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay << 1) ;
set_sda_outputlevel(1); //talk->set_sda(TRUE);
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay << 1) ;
set_scl_input;
// while(get_scl_input_level == 0);
for(int i = 0; i < soft_i2c_para.delay * 16;i++){
if(get_scl_input_level){
break;
}
} /* wait for slc is free */
soft_i2c_Delay(soft_i2c_para.delay ) ;
// set_scl_outputlevel(1); //talk->set_scl(TRUE);
// set_scl_output;
// soft_i2c_Delay(soft_i2c_para.delay << 1) ;
set_sda_outputlevel(0); //talk->set_sda(FALSE);
soft_i2c_Delay(soft_i2c_para.delay << 1) ;
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay << 1) ;
return ;
}
static void soft_i2c_Stop(void)
{
/* A LOW to HIGH transition on the SDA line while SCL is
* HIGH defines a STOP condition.
*/
set_sda_outputlevel(0); //talk->set_sda(FALSE);
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay << 5 ) ;
set_scl_input;
// while(get_scl_input_level == 0);
for(int i = 0; i < soft_i2c_para.delay * 16;i++){
if(get_scl_input_level){
break;
}
} /* wait for slc is free */
soft_i2c_Delay(soft_i2c_para.delay ) ;
// set_scl_outputlevel(1); //talk->set_scl(TRUE);
// set_scl_output;
// soft_i2c_Delay(soft_i2c_para.delay << 1);
set_sda_outputlevel(1); //talk->set_sda(TRUE);
soft_i2c_Delay(soft_i2c_para.delay ) ;
set_scl_input;
set_sda_input;
return ;
}
static int soft_i2c_TestAck(void)
{
int i, ret = 0;
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay << 1 );
set_sda_input; //i = talk->get_sda();
soft_i2c_Delay(soft_i2c_para.delay );
set_scl_input;
// while(get_scl_input_level == 0);
for(i = 0; i < soft_i2c_para.delay * 16; i++){
if(get_scl_input_level){
break;
}
} /* wait for slc is free */
soft_i2c_Delay(soft_i2c_para.delay ) ;
// soft_i2c_Delay(soft_i2c_para.delay << 1 ) ;
// set_scl_outputlevel(1); //talk->set_scl(TRUE);
// set_scl_output;
// soft_i2c_Delay(soft_i2c_para.delay << 1);
for(i = 0; i < soft_i2c_para.delay * 16;i++){
if(!get_sda_input_level){
ret = 1;
break;
}
} /* wait for ack */
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay * 6);
return ret;
}
static void soft_i2c_Ack(void)
{
set_sda_outputlevel(0); //talk->set_sda(FALSE);
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay ) ;
set_scl_input;
// while(get_scl_input_level == 0);
for(int i = 0; i < soft_i2c_para.delay * 16;i++){
if(get_scl_input_level){
break;
}
} /* wait for slc is free */
soft_i2c_Delay(soft_i2c_para.delay ) ;
// set_scl_outputlevel(1); //talk->set_scl(TRUE);
// soft_i2c_Delay(soft_i2c_para.delay << 1) ;
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay * 6) ;
return ;
}
static void soft_i2c_NoAck(void)
{
set_sda_outputlevel(1); //talk->set_sda(TRUE);
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay ) ;
set_scl_input;
// while(get_scl_input_level == 0);
for(int i = 0; i < soft_i2c_para.delay * 16;i++){
if(get_scl_input_level){
break;
}
} /* wait for slc is free */
soft_i2c_Delay(soft_i2c_para.delay ) ;
// set_scl_outputlevel(1); //talk->set_scl(TRUE);
// soft_i2c_Delay(soft_i2c_para.delay << 1) ;
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay * 6) ;
return ;
}
static unsigned char soft_i2c_Read8Bit(void)
{
unsigned char rbyte = 0;
int i;
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay ) ;
set_sda_input; //i = talk->get_sda();
soft_i2c_Delay(soft_i2c_para.delay ) ;
for (i = 0; i < 8; i++)
{
set_scl_input;
// while(get_scl_input_level == 0);
for(int ii = 0; ii < soft_i2c_para.delay * 16; ii++){
if(get_scl_input_level){
break;
}
} /* wait for slc is free */
soft_i2c_Delay(soft_i2c_para.delay ) ;
// set_scl_outputlevel(1); //talk->set_scl(TRUE);
// set_scl_output;
// soft_i2c_Delay(soft_i2c_para.delay << 1);
rbyte = (rbyte<<1) | ((unsigned char)(get_sda_input_level));
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay << 1);
}
set_sda_outputlevel(0);
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay) ;
return rbyte;
}
static unsigned char soft_i2c_Write8Bit(unsigned char input)
{
int i;
// set_scl_outputlevel(0); //talk->set_scl(TRUE);
// soft_i2c_Delay(soft_i2c_para.delay ) ;
for(i = 0x80; i > 0; i >>= 1) {
set_scl_outputlevel(0); //talk->set_scl(FALSE);
set_scl_output;
soft_i2c_Delay(soft_i2c_para.delay ) ;
if(input & i)
{
set_sda_outputlevel(1);
}
else
{
set_sda_outputlevel(0);
}
// if(i == 0x80)
set_sda_output;
soft_i2c_Delay(soft_i2c_para.delay << 1);
set_scl_input;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -