From f707f8973c8d2fd92050b7f13e1c94884542fc12 Mon Sep 17 00:00:00 2001 From: Ross Owen Date: Fri, 24 Feb 2012 17:15:17 +0000 Subject: [PATCH] Added new iic files --- module_usb_aud_shared/iic/iic.h | 36 +++ module_usb_aud_shared/iic/iic.xc | 454 +++++++++++++++++++++++++++++++ 2 files changed, 490 insertions(+) create mode 100755 module_usb_aud_shared/iic/iic.h create mode 100755 module_usb_aud_shared/iic/iic.xc diff --git a/module_usb_aud_shared/iic/iic.h b/module_usb_aud_shared/iic/iic.h new file mode 100755 index 00000000..8e9ccda0 --- /dev/null +++ b/module_usb_aud_shared/iic/iic.h @@ -0,0 +1,36 @@ +#ifndef IIC_H_ +#define IIC_H_ + +#include + +int iic_initialise(timer t, port p_scl, port p_sda); + +// Write to IIC device +#if defined __XC__ +int iic_writeC(unsigned int address, unsigned int reg, unsigned char data[], unsigned int numBytes, chanend ?c, + port ?p_scl, port ?p_sda); +#elif defined __STDC__ +int iic_writeC(unsigned int address, unsigned int reg, unsigned char data[], unsigned int numBytes, chanend c, + port p_scl, port p_sda); +#endif + +int iic_write(unsigned int address, unsigned int reg, unsigned char data[], unsigned int numBytes, timer t, + port p_scl, port p_sda); + +// Read from IIC device +// It receives numBytes, acking each one and does not ack the final byte +#if defined __XC__ +int iic_readC(unsigned int address, unsigned int reg, unsigned char data[], unsigned int numBytes, chanend ?c, + port ?p_scl, port ?p_sda); +#elif defined __STDC__ +int iic_readC(unsigned int address, unsigned int reg, unsigned char data[], unsigned int numBytes, chanend c, + port p_scl, port p_sda); +#endif + +int iic_read(unsigned int address, unsigned int reg, unsigned char data[], unsigned int numBytes, timer t, port p_scl, port p_sda); + +// iic_phy_wait +// Wait a certain number of cycles +void iic_phy_wait(unsigned delay, timer t); + +#endif /*IIC_H_*/ diff --git a/module_usb_aud_shared/iic/iic.xc b/module_usb_aud_shared/iic/iic.xc new file mode 100755 index 00000000..32547c05 --- /dev/null +++ b/module_usb_aud_shared/iic/iic.xc @@ -0,0 +1,454 @@ +/* + * @ModuleName iic + * @Author Ali Dixon, Corin Rathbone & Ross Owen + * @Date 30/07/2008 + * @Version 1.2 + * @Description IIC bus interface + * + * The copyrights, all other intellectual and industrial + * property rights are retained by XMOS and/or its licensors. + * Terms and conditions covering the use of this code can + * be found in the Xmos End User License Agreement. + * + * Copyright XMOS Ltd 2008 + */ + + +#include +#include +#include "print.h" +#include "iic.h" +#include "freqConst.h" + +#define EXPECT_ACK 0 + +#define IIC_WE 0 +#define IIC_RE 1 + +#define iic_bittime (2000) // ref clock cycles per iic bit + +// times are in units of 10ns +#define iic_scl_high_time (iic_bittime >> 1) +#define iic_scl_low_time (iic_bittime >> 1) +#define iic_bus_free_time iic_bittime +#define iic_start_cond_setup_time iic_bittime +#define iic_start_cond_hold_time iic_bittime +#define iic_write_cycle_time (5000 * XS1_TIMER_MHZ) // 5ms +#define iic_write_ack_poll_time ( 50 * XS1_TIMER_MHZ) // 50us + +//extern port p_i2c_scl; +#define PORT_IIC_SCL p_scl +//extern port p_i2c_sda; +#define PORT_IIC_SDA p_sda + +extern timer i2ctimer; + +#define SCLHIGH() \ + { \ + int onedetect = 0; \ + while (1) { \ + int val; \ + PORT_IIC_SCL :> val; \ + if (val == 1) { \ + onedetect++; \ + if (onedetect > 20) \ + break; \ + } else { \ + onedetect = 0; \ + } \ + } \ + } + +// Wait for the specified amount of time +void iic_phy_wait(unsigned delay, timer t) +{ + unsigned int time; + t :> time; + t when timerafter (time + delay) :> unsigned int tmp; +} + + +// Release the bus +int iic_initialise(timer t, port p_scl, port p_sda) +{ + int returnCode = 0; + unsigned int scl_value; + unsigned int sda_value; + + scl_value = 0; + sda_value = 0; + + while ((scl_value != 1) || (sda_value != 1)) + { + PORT_IIC_SCL :> scl_value; + PORT_IIC_SDA :> sda_value; + } + + iic_phy_wait(10 * iic_bittime, t); + + scl_value = 0; + sda_value = 0; + while ((scl_value != 1) || (sda_value != 1)) + { + PORT_IIC_SCL :> scl_value; + PORT_IIC_SDA :> sda_value; + } + + return returnCode; +} + + +// Generate start condition +void iic_phy_master_start(timer t, port p_scl, port p_sda) +{ + SCLHIGH(); + PORT_IIC_SDA <: 1; + iic_phy_wait(iic_start_cond_setup_time, t); + + PORT_IIC_SDA <: 0; + iic_phy_wait(iic_start_cond_hold_time, t); + + PORT_IIC_SCL <: 0; +} + + +// Generate stop condition +void iic_phy_master_stop(timer t, port p_scl, port p_sda) +{ + PORT_IIC_SDA <: 0; + iic_phy_wait(iic_scl_low_time, t); + SCLHIGH(); + iic_phy_wait(iic_scl_high_time, t); + + PORT_IIC_SDA <: 1; + iic_phy_wait(iic_bus_free_time, t); +} + + +// Send a bit +unsigned int iic_phy_sendBit(unsigned int bit, timer t, port p_scl, port p_sda) +{ + unsigned int time; + + t :> time; + PORT_IIC_SDA <: bit; + + time += iic_scl_low_time; + t when timerafter(time) :> time; + SCLHIGH(); + t :> time; + + time += iic_scl_high_time; + t when timerafter(time) :> time; + PORT_IIC_SCL <: 0; // set clock low + + return 0; +} + + +// Receive a bit +unsigned int iic_phy_receiveBit(timer t, port p_scl, port p_sda) +{ + unsigned int bit; + unsigned int time; + + t :> time; + PORT_IIC_SDA :> int tmp; + + time += iic_scl_low_time; + t when timerafter(time) :> time; + SCLHIGH(); + t :> time; + + PORT_IIC_SDA :> bit; + + time += iic_scl_high_time; + t when timerafter(time) :> time; + PORT_IIC_SCL <: 0; // set clock low + + time += iic_scl_low_time; + t when timerafter(time) :> time; + return bit; +} + + +// Send a byte +int iic_phy_sendByte(unsigned int inByte, unsigned int expectAck, timer t, port p_scl, port p_sda) +{ + unsigned int bitCount; + unsigned int bit; + unsigned int byte; + unsigned int ack; + unsigned int time; + + byte = inByte; + bitCount = 0; + + t :> time; + + while (bitCount < 8) + { + + bit = (byte & 0x80) >> 7; + time += (iic_scl_low_time>>1); + t when timerafter(time) :> time; + + PORT_IIC_SDA <: bit; + + time += (iic_scl_low_time>>1); + t when timerafter(time) :> time; + + SCLHIGH(); + t :> time; + + byte = byte << 1; + bitCount = bitCount + 1; + + time += iic_scl_high_time; + t when timerafter(time) :> time; + PORT_IIC_SCL <: 0; // set clock low + } + + PORT_IIC_SDA :> int tmp; + + ack = iic_phy_receiveBit(t, p_scl, p_sda); + + if (ack != expectAck) + { + return 1; + } + else + { + return 0; + } +} + + +// Receive a byte +unsigned int iic_phy_receiveByte(unsigned int ack, timer t, port p_scl, port p_sda) +{ + unsigned int bitCount; + unsigned int bit; + unsigned int time; + unsigned int byte; + + byte = 0; + bitCount = 0; + + t :> time; + + // set to input + PORT_IIC_SDA :> int tmp; + + while (bitCount < 8) + { + time += iic_scl_low_time; + t when timerafter(time) :> time; + SCLHIGH(); + t :> time; + + PORT_IIC_SDA :> bit; + + byte = (byte << 1) | bit; + bitCount = bitCount + 1; + + time += iic_scl_high_time; + t when timerafter(time) :> time; + PORT_IIC_SCL <: 0; // set clock low + } + + PORT_IIC_SDA :> int tmp; + + iic_phy_sendBit(ack, t, p_scl, p_sda); + + return byte; +} + + +// Poll to determine when write completes +unsigned int iic_checkWriteComplete(unsigned int address, timer t, port p_scl, port p_sda) +{ + unsigned int time; + + t :> time; + + iic_phy_master_start(t, p_scl, p_sda); + do + { + iic_phy_master_stop(t, p_scl, p_sda); + t when timerafter(time + iic_write_ack_poll_time) :> time; + iic_phy_master_start(t, p_scl, p_sda); + } while (iic_phy_sendByte((address << 1) | IIC_WE, EXPECT_ACK, t, p_scl, p_sda)); + + if (iic_phy_sendByte(0, EXPECT_ACK, t, p_scl, p_sda)) + { + } + + if (iic_phy_sendByte(0, EXPECT_ACK, t, p_scl, p_sda)) + { + } + + iic_phy_master_stop(t, p_scl, p_sda); + iic_phy_master_start(t, p_scl, p_sda); + + iic_phy_sendByte((address << 1) | IIC_WE, EXPECT_ACK, t, p_scl, p_sda); + return 0; +} + + +// Write to IIC device +int iic_writeC(unsigned int address, unsigned int reg, char data[], unsigned int numBytes, chanend ?c, + port ?p_scl, port ?p_sda) +{ + + /* If null channel end arg passed in use i2c ports */ + if(isnull(c)) + { + return iic_write(address, reg, data, numBytes, i2ctimer, p_scl, p_sda); + } + else + { + int read; + int retVal; + c <: 1; // isWrite + c <: (address << 1); + c <: reg; + c <: numBytes; + for(int i = 0; i!= numBytes; i++) + { + read = data[i]; + c <: read; + } + + c :> retVal; + return retVal; + } +} + +void iic_wait(timer t, unsigned us) +{ + unsigned time; + t :> time; + time += us * 100; + t when timerafter(time) :> void; +} +#define COPROCESSOR_LOOPS 10 +int iic_write(unsigned int address, unsigned int reg, char data[], unsigned int numBytes, timer t, port p_scl, port p_sda) +{ + unsigned int i = 0; + //printf("Start of iic_write(0x%04x, 0x%04x, 0x%02x, %d)\n", address, reg, data[0], numBytes); + iic_phy_master_start(t, p_scl, p_sda); + + i = COPROCESSOR_LOOPS; + while(i) + { + iic_phy_master_start(t, p_scl, p_sda); + if(0 == iic_phy_sendByte((address << 1) | IIC_WE, EXPECT_ACK, t, p_scl, p_sda)) + break; + iic_wait(t, 600); + i--; + } + if(!i) + { + //printstrln("W1"); + return 1; + } + + if (iic_phy_sendByte((reg), EXPECT_ACK, t, p_scl, p_sda)) + return 3; + + for ( i=0; i read; + data[i] = read; + } + c :> retVal; + return retVal; + } +} + +int iic_read(unsigned int address, unsigned int reg, char data[], unsigned int numBytes, timer t, port p_scl, port p_sda) +{ + unsigned int i; + + iic_phy_master_start(t, p_scl, p_sda); + + i = COPROCESSOR_LOOPS; + while(i) + { + iic_phy_master_start(t, p_scl, p_sda); + if(0 == iic_phy_sendByte((address << 1) | IIC_WE, EXPECT_ACK, t, p_scl, p_sda)) + break; + iic_wait(t, 600); + i--; + } + if(!i) + { + //printstrln("S1"); + return 1; + } + + if (iic_phy_sendByte((reg), EXPECT_ACK, t, p_scl, p_sda)) + { + //printstrln("S2"); + return 1; + } + iic_phy_master_stop(t, p_scl, p_sda); + + i = COPROCESSOR_LOOPS; + while(i) + { + iic_phy_master_start(t, p_scl, p_sda); + if(0 == iic_phy_sendByte((address << 1) | IIC_RE, EXPECT_ACK, t, p_scl, p_sda)) + break; + iic_wait(t, 600); + i--; + } + if(!i) + { + //printstrln("S3"); + return 1; + } + + for (i=0; i