From f78ae2192de82239171b62eab19fa69c571ebd92 Mon Sep 17 00:00:00 2001 From: asmig Date: Mon, 18 Feb 2013 02:55:02 +0000 Subject: [PATCH] I2C master app and client. Impressively ugly. Might work occasionally. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1503 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- client/GoodFETI2C.py | 32 ++++++++ client/goodfet.i2ceeprom | 75 +++++++++++++++++++ firmware/apps/i2c/i2c.c | 156 +++++++++++++++++++++++---------------- 3 files changed, 198 insertions(+), 65 deletions(-) create mode 100644 client/GoodFETI2C.py create mode 100755 client/goodfet.i2ceeprom diff --git a/client/GoodFETI2C.py b/client/GoodFETI2C.py new file mode 100644 index 0000000..614be83 --- /dev/null +++ b/client/GoodFETI2C.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# GoodFET I2C and I2Ceeprom Client Library +# +# Pre-alpha. You've been warned! + +#import sys, time, string, cStringIO, struct, glob, serial, os + +from GoodFET import GoodFET + +class GoodFETI2C(GoodFET): + def I2Csetup(self): + """Move the FET into the I2C application.""" + self.writecmd(0x02,0x10) + + def I2Cstart(self): + """Produce Start condition on I2C bus""" + self.writecmd(0x02,0x20) + def I2Cstop(self): + """Produce Stop condition on I2C bus""" + self.writecmd(0x02,0x21) + def I2Cread(self,count=1): + """Read data from I2C.""" + self.writecmd(0x02,0x00,1,[count]) + def I2Cwritebytes(self,data): + """Write multiple bytes to I2C.""" + self.writecmd(0x02,0x01,len(data),data) + def I2Cwritebyte(self,val): + """Write a single byte to I2C.""" + self.I2Cwritebytes([val]) + def I2Ctrans(self,readcount,data): + """Use PEEK to do a multi-start transaction""" + return self.writecmd(0x02,0x02,len(data)+1,[readcount]+data) diff --git a/client/goodfet.i2ceeprom b/client/goodfet.i2ceeprom new file mode 100755 index 0000000..10f0326 --- /dev/null +++ b/client/goodfet.i2ceeprom @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +#GoodFET I2C eeprom Client + +import re +import sys +import binascii +import array +from GoodFETI2C import GoodFETI2C +#from intelhex import IntelHex + +if(len(sys.argv)==1): + print "Usage: %s verb [objects]\n" % sys.argv[0] + print "%s dump 0x$target $filename.bin [0x$start [0x$length]]" % sys.argv[0] + print "%s read 0x$target [0x$start [0x$length]]" % sys.argv[0] + print "%s write 0x$target 0x$adr 0x$val [0x...]" % sys.argv[0] + sys.exit() + +#Initialize FET and set baud rate +client=GoodFETI2C() +#client.verbose=True +client.serInit() +client.I2Csetup() + +control_chars = ''.join(map(chr, range(0,32) + range(127,256))) +control_char_re = re.compile('[%s]' % re.escape(control_chars)) + +def dotnpc(s): + """Replace non-printing-characters with dots""" + return control_char_re.sub('.', s) + +def xxd(data): + for offset in range(0, len(data), 16): + line = data[offset:offset+16] + hex = binascii.hexlify(line) + print "%07x: %4s %4s %4s %4s %4s %4s %4s %4s %s" %tuple([offset] + [hex[s:s+4] for s in range(0,32,4)] + [dotnpc(line)]) + +if(sys.argv[1]=="dump"): + devadr = int(sys.argv[2],16) + f = sys.argv[3] + start=0x00 + count=0x100 + if(len(sys.argv)>4): + start=int(sys.argv[4],16) + if(len(sys.argv)>5): + count=int(sys.argv[5],16) + + print "Dumping %i bytes from device 0x%02x starting at 0x%02x to file: %s." % (count,devadr,start,f) + file = open(f, mode='wb') + data=client.I2Ctrans(count, [devadr, start]) + print "Dumped %i bytes."%len(data) + file.write(data) + file.close() + +if(sys.argv[1]=="read"): + devadr = int(sys.argv[2],16) + start=0x00 + if(len(sys.argv)>3): + start=int(sys.argv[3],16) + count=1 + if(len(sys.argv)>4): + count=int(sys.argv[4],16) + print "Reading %i bytes from device 0x%02x starting at 0x%02x." % (count,devadr,start) + data=client.I2Ctrans(count, [devadr, start]) + if(data): + xxd(data) + else: + print "No data received" + +if(sys.argv[1]=="write"): + if(len(sys.argv)>2): + data=[int(x,16) for x in sys.argv[2:]] + for i,byte in enumerate(data): + print "0x%02x: 0x%02x" % (i,byte) + client.I2Cwritebytes(data) diff --git a/firmware/apps/i2c/i2c.c b/firmware/apps/i2c/i2c.c index e58b266..1018c5f 100644 --- a/firmware/apps/i2c/i2c.c +++ b/firmware/apps/i2c/i2c.c @@ -13,10 +13,9 @@ #include "command.h" #include "i2c.h" -#include +#ifndef _GNU_ASSEMBLER_ #include -#include - +#endif //Pins and I/O #include @@ -47,37 +46,24 @@ app_t const i2c_app = { //2xx only, need 1xx compat code -#if (board == tilaunchpad) -// P3.1 SDA -// P3.3 SCL -#define SDA (1<<1) -#define SCL (1<<3) - -#define CLRSDA P3OUT&=~SDA -#define SETSDA P3OUT|=SDA -#define CLRSCL P3OUT&=~SCL -#define SETSCL P3OUT|=SCL - -#define READSDA (P3IN&SDA?1:0) -#define SDAINPUT P3DIR&=~SDA -#define SDAOUTPUT P3DIR|=SDA -#define SCLINPUT P3DIR&=~SCL -#define SCLOUTPUT P3DIR|=SCL -#define SETBOTH P3OUT|=(SDA|SCL) - -#else - #define SDA TDI #define SCL TDO -#define CLRSDA P5OUT&=~SDA -#define SETSDA P5OUT|=SDA -#define CLRSCL P5OUT&=~SCL -#define SETSCL P5OUT|=SCL +#define SDAINPUT SPIDIR&=~SDA +#define SDAOUTPUT SPIDIR|=SDA +#define SCLINPUT SPIDIR&=~SCL +#define SCLOUTPUT SPIDIR|=SCL -#define READSDA (P5IN&SDA?1:0) -#define SETBOTH P5OUT|=(SDA|SCL) -#endif +#define PULLON SPIREN|=(SDA|SCL) +#define PULLOFF SPIREN&=~(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 @@ -93,30 +79,24 @@ void I2C_Init() //Clear SDA and SCL. //Direction, not value, is used to set the value. - //(Pull-up or 0.) -#if (platform == tilaunchpad) - SDAOUTPUT; SCLOUTPUT; -#else - P5DIR|=(SDA|SCL); -#endif - //P5REN|=SDA|SCL; - + SDAOUTPUT; I2C_CLOCK_HI(); I2C_DATA_HI(); + //PULLON; I2CDELAY(1); } -#if (platform == tilaunchpad) +// This is never called... void I2C_Exit() { SDAINPUT; SCLINPUT; + PULLOFF; } -#endif //! Write an I2C bit. void I2C_WriteBit( unsigned char c ) @@ -132,40 +112,68 @@ void I2C_WriteBit( unsigned char c ) I2C_CLOCK_LO(); I2CDELAY(1); - if(c>0) - I2C_DATA_LO(); - - I2CDELAY(1); + /*if(c>0) + *I2C_DATA_LO(); + * + *I2CDELAY(1); + */ } //! Read an I2C bit. unsigned char I2C_ReadBit() { - I2C_DATA_HI(); - - I2C_CLOCK_HI(); SDAINPUT; - I2CDELAY(1); + I2C_CLOCK_HI(); unsigned char c = READSDA; + if(c) + I2C_DATA_HI(); + else + I2C_DATA_LO(); - I2C_CLOCK_LO(); - I2CDELAY(1); SDAOUTPUT; + I2CDELAY(1); + I2C_CLOCK_LO(); 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(); + + return c; +} //! Send a START Condition void I2C_Start() { // set both to high at the same time SETBOTH; - I2CDELAY(1); + I2CDELAY(3); I2C_DATA_LO(); - I2CDELAY(1); + I2CDELAY(3); I2C_CLOCK_LO(); I2CDELAY(1); @@ -174,8 +182,11 @@ 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); @@ -190,7 +201,7 @@ unsigned char I2C_Write( unsigned char c ) c<<=1; } - return I2C_ReadBit(); + return I2C_ReadBit_Wait(); } @@ -215,7 +226,6 @@ unsigned char I2C_Read( unsigned char ack ) return res; } - //! Handles an i2c command. void i2c_handle_fn( uint8_t const app, uint8_t const verb, @@ -225,28 +235,44 @@ void i2c_handle_fn( uint8_t const app, unsigned long l; switch(verb) { - - case PEEK: - break; - case POKE: - break; - case READ: l = len; if(l > 0) //optional parameter of length l=cmddata[0]; if(!l) //default value of 1 l=1; - for(i = 0; i < l; i++) - cmddata[i]=I2C_Read(1); //Always acknowledge + I2C_Start(); + for(i=0; i < l; i++) + cmddata[i]=I2C_Read(i