i2c-gpio.c

/*******************************************************************************
 *
 *  DESCRIPTION
 *    This file defines routines for i2c master with gpio, port from linux kernel
 *
 ******************************************************************************/

#include <pio.h>

#include "sensor.h"

#define TS_SCL_PIO_MASK         (0x01UL << SENSOR_I2C_SCL_PIO)
#define TS_SDA_PIO_MASK         (0x01UL << SENSOR_I2C_SDA_PIO)

#define CS_H()  PioSet(SENSOR_I2C_SCL_PIO, TRUE)
#define CS_L()  PioSet(SENSOR_I2C_SCL_PIO, FALSE)
#define SDA_OUT() PioSetDir(SENSOR_I2C_SDA_PIO, TRUE)
#define SDA_IN() PioSetDir(SENSOR_I2C_SDA_PIO, FALSE)
#define SDA_READ() PioGet(SENSOR_I2C_SDA_PIO)   
#define SDA_H()  PioSet(SENSOR_I2C_SDA_PIO, TRUE)
#define SDA_L()  PioSet(SENSOR_I2C_SDA_PIO, FALSE)
#define SCK_H()  PioSet(SENSOR_I2C_SCL_PIO, TRUE)
#define SCK_L()  PioSet(SENSOR_I2C_SCL_PIO, FALSE)
#define udelay(x) TimeDelayUSec(x)

/*
 * DELAY_TIME is quarter clock cycle of i2c SCL.
 * As far as i known, no delay is needed in CSR101x_A05
 */
#ifdef DELAY_TIME
#define DELAY(x)   udelay(x)
#else
#define DELAY(x)   do{ }while(0)
#endif

static void I2cStart(void)
{
    /* assert: scl, sda are high */
    DELAY(DELAY_TIME);
 SDA_L();    
 DELAY(DELAY_TIME<<1);
 SCK_L();  
 DELAY(DELAY_TIME);

    return;
}

static void I2cRestart(void)
{
    /* assert: scl is low */
    SDA_H();
    DELAY(DELAY_TIME);
    SCK_H();
    DELAY(DELAY_TIME<<1);
 SDA_L();    
 DELAY(DELAY_TIME<<1);
 SCK_L();  
 DELAY(DELAY_TIME);

    return;
}

static void I2cStop(void)
{
     /* assert: scl is low */
    SDA_L();
 DELAY(DELAY_TIME);
 SCK_H();   
 DELAY(DELAY_TIME<<1);
    SDA_H();
    DELAY(DELAY_TIME<<1);

    return;
}

static int I2cOutByte(uint8 c)
{
    bool ack;
    int16 i;
    uint8 sb;
   
    SDA_OUT();
    for(i=7; i>=0; i--)
    {
        sb = (c >> i) & 1;
        if(sb) SDA_H();
        else SDA_L();
        DELAY(DELAY_TIME);
        SCK_H();
        DELAY(DELAY_TIME<<1);
        SCK_L();
        DELAY(DELAY_TIME);
    }

    SDA_H();
    DELAY(DELAY_TIME);
    SDA_IN();
    SCK_H();
    DELAY(DELAY_TIME<<1);
    ack = !SDA_READ();

    SCK_L();
    DELAY(DELAY_TIME);
    SDA_OUT();

    return ack;
}

static int I2cInByte(void)
{
    int16 i;
    uint8 indata = 0;
   
    /* assert: scl is low */
    SDA_H();
    SDA_IN();
    DELAY(DELAY_TIME);
    for (i = 0; i < 8; i++) {
        SCK_H();
        DELAY(DELAY_TIME);

        indata *= 2;
        if (SDA_READ()) indata |= 0x01;
        DELAY(DELAY_TIME);

        SCK_L();
        if(i == 7) DELAY(DELAY_TIME);
        else DELAY(DELAY_TIME<<1);
    }
    SDA_OUT();

    return indata;
}

static int I2cAckNak(uint16 is_ack)
{
    /* assert: sda is high */
    if (is_ack) SDA_L(); /* send ack */
    else SDA_H();
   
    DELAY(DELAY_TIME);
    SCK_H();
    DELAY(DELAY_TIME<<1);
    SCK_L();
    DELAY(DELAY_TIME);
   
    return 0;
}

bool TSCWrite(uint8 addr, uint16 reg, uint16 *buf, uint16 size)
{
    bool acktemp;
    uint16 i;
   
    I2cStart();
    
    acktemp = I2cOutByte(addr);
    if(!acktemp) return acktemp;
    acktemp = I2cOutByte(reg&0xff);
    if(!acktemp) return acktemp;
    acktemp = I2cOutByte(reg>>8);
    if(!acktemp) return acktemp;
     
    for(i=0;i<size;i++)
    {
        acktemp = I2cOutByte(buf[i]&0xff);
        acktemp = I2cOutByte(buf[i]>>8);
    }
    I2cStop();
   
    return acktemp;
}

bool TSCRead(uint8 addr, uint16 reg, uint16 *buf, uint16 size)
{
      bool acktemp;
      uint16 i=0;

      I2cStart();
      acktemp = I2cOutByte(addr);
      if(!acktemp) return acktemp;
      acktemp = I2cOutByte(reg&0xff);
      if(!acktemp) return acktemp;
      acktemp = I2cOutByte(reg>>8);
      if(!acktemp) return acktemp;
    
      I2cRestart();
      acktemp = I2cOutByte(addr + 1);
      if(!acktemp) return acktemp;

      for(i=0;i<size;i++)
      {
          buf[i] = I2cInByte();
          I2cAckNak(TRUE);
          buf[i] |= (I2cInByte())<<8;
          I2cAckNak(TRUE);
      }
   
      I2cStop();

      return acktemp;
}

bool Read_N_Bytes(uint8 dev_addr, uint8 l_data, uint8 h_data, uint8 *buffer, uint16 n)
{
    bool acktemp;   
    uint16 i;

    I2cStart();
    acktemp = I2cOutByte(dev_addr);   
    acktemp = I2cOutByte(l_data);
    acktemp = I2cOutByte(h_data);
   
    I2cRestart();
    acktemp = I2cOutByte(dev_addr + 1);
   
    for(i=0; i<n; i++)
    {
        buffer[i] = I2cInByte();           
        I2cAckNak(TRUE);
    }
   
    I2cStop();
   
    return acktemp;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值