Basic I2C Driver help [SOLVED]
What am I doing wrong here?
I am trying to write "test" to my eeprom.
But it looks like it isn't all being written. All I get back when I read the address it "t".
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Post Edited (Bobb Fwed) : 8/3/2009 10:46:59 PM GMT
I am trying to write "test" to my eeprom.
But it looks like it isn't all being written. All I get back when I read the address it "t".
CON
_CLKMODE = XTAL1' + PLL4X
_XINFREQ = 5_000_000 ' 5MHz Crystal
start_table = $3FFF
OBJ
DEBUG : "FullDuplexSerial"
i2c : "Basic_I2C_Driver"
VAR
BYTE val[noparse][[/noparse]32]
PUB Main | i, v
DEBUG.start(31, 30, 0, 57600)
waitcnt(clkfreq + cnt)
DEBUG.tx($0D)
i2c.Initialize(i2c#BootPin)
bytefill(@val, 0, 32)
bytemove(@val, string("test"), 32)
write_table
REPEAT i FROM 0 TO 32
v := read_table(start_table + i)
IF (v == 0)
quit
DEBUG.tx(v)
DEBUG.tx($0D)
PUB write_table | time
IF i2c.WritePage(i2c#BootPin, i2c#EEPROM, start_table, @val, 32)
abort
time := cnt
repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, start_table)
if cnt - time > clkfreq / 10
abort
PUB read_table (addr) : ret_val
IF i2c.ReadPage(i2c#BootPin, i2c#EEPROM, addr, @val, 1)
abort
return val
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Post Edited (Bobb Fwed) : 8/3/2009 10:46:59 PM GMT

Comments
To show you that it works with the internal EEPROM I enabled a section of my demo right a string to the EERPROM and then read it back. The mechanism I use may be helpful, i.e., you don't have to read back one character at a time.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Thanks.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Obex item /464/ contains maybe the smallest and correct SPIN I2C driver for boot EEPROMS. Although, it is not the fastest! Supplied with a plethora of SPIN I2C drivers, I am still waiting for a stand alone I2C driver in PASM to appear somewhere. This delay is·a good excuse for me not to update the I2C protocol based driver·of the FPU on OBEX.
Cheers,
Istvan
(P.S.: I mean, that the basic I2C driver task is maybe NOT SOLVED yet.)
Post Edited (cessnapilot) : 8/4/2009 8:34:52 AM GMT
Different part, I'm using an MCP3221, but I'm a total I2C newbie and the examples in the obex all assumed that I knew more than I did - I couldn't get any of them to work, even one that was supposed to be written specifically for the MCP3xxx series parts.
But just last night I finally got it working perfectly, thanks to Jon's example code attached to this thread. His code was just short and simple enough to make sense with the part documentation.
Thanks, Jon!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 SCL = 28 SDA = 29 read = 1 write = 0 OBJ out : "Parallax serial terminal" var long ack, temperature, data, send_data pub init ack := temperature := data := 0 out.start(115200) 'start the PST waitcnt(clkfreq * 3 + cnt) out.str(string("TMP100 program v 0.1")) repeat 2 out.newline main pub main | fract, whole, number send_data := address | write starti2c ack := send_i2c(send_data) 'send the address byte and indicate if a read/write follows. Ack = 1 when device exists on the i2c bus send_data := 0 if ack out.str(@devgood) out.newline 'send pointer reg byte telling it to set the pointer to the temperature conv reg 'starti2c ack := send_i2c(pointer[noparse][[/noparse]0]) 'ack should be low from dev if all is good ack := !ack if ack out.str(@devgood) send_data := address | read stopi2c starti2c 'then it needs a start condition again ack := send_i2c(send_data) 'then an address byte with the read bit set !ack if ack 'now read in data data := read_i2c(2,0) 'read_i2c(bytes to read, ack bit to send) stopi2c temperature := data out.char("$") out.hex(temperature,4) out.newline out.char("%") out.bin(temperature,32) waitcnt(clkfreq * 5 + cnt) {fract >>= 4 out.dec(whole) out.char(".") number := lookdown(fract : %0000, %1000, %0100, %1100, %0010, %1010, %0110, %1110, %0001, %1001, %0101, %1101, %0011, %1011, %1111) fract := lookup(number : 0, 5, 25, 75, 125, 625, 375, 875, 0625, 5625, 3125, 7825, 1875, 6875, 9375) out.dec(fract) out.str(@c) } pri starti2c dira[noparse][[/noparse]scl..sda] := %11 outa[noparse][[/noparse]scl..sda] := %11 waitcnt(1200 + cnt) !outa[noparse][[/noparse]sda] waitcnt(1200 +cnt) !outa[noparse][[/noparse]scl] waitcnt(1200 +cnt) dira[noparse][[/noparse]scl..sda]~ pri stopi2c dira[noparse][[/noparse]scl..sda] := %11 outa[noparse][[/noparse]scl..sda] := %00 waitcnt(1200 + cnt) !outa[noparse][[/noparse]scl] waitcnt(1200 +cnt) !outa[noparse][[/noparse]sda] waitcnt(1200 +cnt) dira[noparse][[/noparse]scl..sda]~ pri send_i2c(_data):getack | sftw,a sftw := _data >< 8 dira[noparse][[/noparse]scl..sda]~~ repeat a from 0 to 7 outa[noparse][[/noparse]sda] := sftw outa[noparse][[/noparse]scl]~~ sftw >>= 1 !outa[noparse][[/noparse]scl] waitcnt(1200 +cnt) dira[noparse][[/noparse]sda]~ outa[noparse][[/noparse]scl]~~ getack := ina[noparse][[/noparse]sda] outa[noparse][[/noparse]scl]~ dira[noparse][[/noparse]scl..sda]~~ return getack pri read_i2c(bytes,_ackbit): recv | dataget, b 'read_i2c(bits to read, ack bit to send) dira[noparse][[/noparse]sda]~ repeat bytes repeat 8 outa[noparse][[/noparse]scl]~~ 'SCL high recv |= ina[noparse][[/noparse]sda] 'OR in sda to recv outa[noparse][[/noparse]scl]~ 'lock in recv by bringing SCL low recv <<= 1 waitcnt(80 +cnt) dataget := %10 dataget := dataget | _ackbit'set the desired ackbit dira[noparse][[/noparse]scl..sda]~~ 'make sda output the ack bit outa[noparse][[/noparse]scl..sda] := dataget outa[noparse][[/noparse]scl]~ dira[noparse][[/noparse]sda]~ dira[noparse][[/noparse]scl..sda]~~ 'both outputs again outa[noparse][[/noparse]scl..sda]~ 'leave databus low return recv DAT 'sensor 0 sensor 1 sensor 2 sensor 3 address byte %10010000, %10010010, %10010100, %10010110 'indicate a write opp follows 'Temp Config Temp LOW Temp HIGH Pointer byte %00000000, %00000001, %00000010, %00000011 'write to the appropriate reg '9bit 10bit 11bit 12bit Resolution byte %00000000, %00100000, %01000000, %01100000 'temperature resolution *MUST be "OR"d with config_reg '1 fault 2 faults 4 faults 6 faults Fault byte %00000000, %00001000, %00010000, %00011000 'defines an alert when Temp High/Low is exceeded c byte " Celcius",0 devgood byte "Device 0 found!, getting temp data...",0i believe the code i wrote (for the 8th time) is legit and follows the timing diagrams well (for SPIN) i would like to make a PASM version but i'm not willing to make one thats going to communicate wrong with a device.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Quicker answers in the #propeller chat channel on freenode.net. Don't know squat about IRC? Download Pigin! So easy a caveman could do it...
http://folding.stanford.edu/ - Donating some CPU/GPU downtime just might lead to a cure for cancer! My team stats.