X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=firmware%2Fapps%2Fi2c%2Fi2c.c;h=6e1dfdea058437b79d83b98749146d0f2bde1a17;hp=6ee1623b041826219441a9cb4e0709c92bb22062;hb=027937b9bed208a4a79b7e9d89a7326747b52a9e;hpb=ae09939eb8c62c83f244527e7916cee5f9145e6c diff --git a/firmware/apps/i2c/i2c.c b/firmware/apps/i2c/i2c.c index 6ee1623..6e1dfde 100644 --- a/firmware/apps/i2c/i2c.c +++ b/firmware/apps/i2c/i2c.c @@ -11,28 +11,59 @@ #include "platform.h" #include "command.h" +#include "i2c.h" -#include -#include -#include - +#ifndef _GNU_ASSEMBLER_ +#include +#endif //Pins and I/O #include -#define SDA TDI -#define SCL TDO + +//! Handles an i2c command. +void i2c_handle_fn( uint8_t const app, + uint8_t const verb, + uint32_t const len); + +// define the i2c app's app_t +app_t const i2c_app = { + + /* app number */ + I2C_APP, + + /* handle fn */ + i2c_handle_fn, + + /* name */ + "I2C", + + /* desc */ + "\tThe I2C app implements the i2c bus protocol thus\n" + "\tturning your GoodFET into a USB-to-i2c adapter.\n" +}; #define I2CDELAY(x) delay(x<<4) //2xx only, need 1xx compat code -#define CLRSDA P5OUT&=~SDA -#define SETSDA P5OUT|=SDA -#define CLRSCL P5OUT&=~SCL -#define SETSCL P5OUT|=SCL +#define SDA TDI +#define SCL TDO + +#define SDAINPUT SPIDIR&=~SDA +#define SDAOUTPUT SPIDIR|=SDA +#define SCLINPUT SPIDIR&=~SCL +#define SCLOUTPUT SPIDIR|=SCL + +#define PULLON SPIREN|=(SDA|SCL) +#define PULLOFF SPIREN&=~(SDA|SCL) -#define READSDA (P5IN&SDA?1:0) -#define SETBOTH P5OUT|=(SDA|SCL) +#define CLRSDA SPIOUT&=~SDA +#define SETSDA SPIOUT|=SDA +#define CLRSCL SPIOUT&=~SCL +#define SETSCL SPIOUT|=SCL + +#define READSDA (SPIIN&SDA?1:0) +#define SETBOTH SPIOUT|=(SDA|SCL) #define I2C_DATA_HI() SETSDA #define I2C_DATA_LO() CLRSDA @@ -42,24 +73,36 @@ //#warning "Using internal resistors. Won't work on 161x devices." -//! Inits bitbanging port, must be called before using the functions below -void I2C_Init() +// Take control of the bus +void I2C_Take() { - - //Clear SDA and SCL. - //Direction, not value, is used to set the value. - //(Pull-up or 0.) - - P5DIR|=(SDA|SCL); - P5REN|=SDA|SCL; - - I2C_CLOCK_HI(); I2C_DATA_HI(); + SCLOUTPUT; + SDAOUTPUT; +} +void I2C_Release() +{ + SDAINPUT; + SCLINPUT; +} + +//! Inits bitbanging port, must be called before using the functions below +void I2C_Init() +{ + I2C_Take(); + //PULLON; I2CDELAY(1); } +// XXX This is never called... +void I2C_Exit() +{ + I2C_Release(); + PULLOFF; +} + //! Write an I2C bit. void I2C_WriteBit( unsigned char c ) { @@ -73,39 +116,64 @@ void I2C_WriteBit( unsigned char c ) I2C_CLOCK_LO(); I2CDELAY(1); - - if(c>0) - I2C_DATA_LO(); - - I2CDELAY(1); } //! Read an I2C bit. unsigned char I2C_ReadBit() { - I2C_DATA_HI(); - + SDAINPUT; I2C_CLOCK_HI(); - I2CDELAY(1); unsigned char c = READSDA; + if(c) + I2C_DATA_HI(); + else + I2C_DATA_LO(); + SDAOUTPUT; + I2CDELAY(1); I2C_CLOCK_LO(); I2CDELAY(1); return c; } +unsigned char I2C_ReadBit_Wait() +{ + SDAINPUT; + I2C_CLOCK_HI(); + + unsigned int i = 0; + unsigned char c = READSDA; + + while(c>0 && i<=35) + { + I2CDELAY(1); + c = READSDA; + i++; + } + + if(c) + I2C_DATA_HI(); + else + I2C_DATA_LO(); + + SDAOUTPUT; + I2CDELAY(1); + I2C_CLOCK_LO(); + I2CDELAY(1); + + return c?0:1; // return true on ACK (0) +} //! Send a START Condition void I2C_Start() { - // set both to high at the same time - SETBOTH; - I2CDELAY(1); + I2C_Take(); // XXX Should probably check to see if someone else is using the bus before we do this + I2CDELAY(3); I2C_DATA_LO(); - I2CDELAY(1); + I2CDELAY(3); I2C_CLOCK_LO(); I2CDELAY(1); @@ -114,11 +182,15 @@ void I2C_Start() //! Send a STOP Condition void I2C_Stop() { + I2C_DATA_LO(); + I2CDELAY(3); + I2C_CLOCK_HI(); - I2CDELAY(1); + I2CDELAY(3); I2C_DATA_HI(); I2CDELAY(1); + I2C_Release(); } //! write a byte to the I2C slave device @@ -130,7 +202,7 @@ unsigned char I2C_Write( unsigned char c ) c<<=1; } - return I2C_ReadBit(); + return I2C_ReadBit_Wait(); } @@ -155,45 +227,68 @@ unsigned char I2C_Read( unsigned char ack ) return res; } - -//! Handles a monitor command. -void i2chandle(unsigned char app, - unsigned char verb, - unsigned char len){ - unsigned char i; - switch(verb){ - - case PEEK: - break; - case POKE: - break; - - case READ: - if(len>0) //optional parameter of length - len=cmddata[0]; - if(!len) //default value of 1 - len=1; - for(i=0;i 0) //optional parameter of length + l=cmddata[0]; + if(!l) //default value of 1 + l=1; + I2C_Start(); + for(i=0; i < l; i++) + cmddata[i]=I2C_Read(i