⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 soft_i2c.c

📁 软件模拟i2c
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************
 *
 *  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 + -