Yes the i2cslave supports write though I dont remember whether I used it, the particular app I used the i2cslave didn't use write so even if I tested it I wouldn't have done much. But the issues I had with hippys wasn't with that it was the master device wanted 8bit addresses and there were a couple of extra states on the i2c bus.
The thing to remember is the address is shared between read and write so if you write the address pointer increments, same with read and if you dont supply the address at the start of write/read they affect each other.
Tim, I will be able to resume hardware testing tomorrow. In the mean time, I get the issue with the state machine, but I was wondering what issue you had regarding 8bit addresses?
I mean the memory address not the i2c device adddress. If I remember correctly hippys code emulated a ram in cog memory. I needed 2 things, 1 the master device would only use a 8bit register to set the memory address so it couldn't address more than 256bytes. The other was since I was reading sensors and allowing the master to read I wanted to read from hub memory which was writen by code on the prop.
Tim, today I tried the readLocation16 from the modified Basic_i2C_driver, I extracted from your fsensor zip. I soon realized while reading the word data that the lower 8 bits and upper 8 bits were reversed. Looking at the Prop Manual, spin function WORD on page 230, I see that a word's lower 8 bits reside in the first byte and upper 8 bits reside in the second byte. Following this convention my problem seems to be sorted out, I am consistently reading and writing to my slave prop running i2cslave_info.spin.
I wrote the following set of routines, using Mike Green's I2c conventions, which can be pasted into the Basic_i2C_driver object and used for accessing the i2c slave. Note that when specifying the i2cslave_info array pointer, the size must be in a power of 2 (2, 4 8, .. 256):
PUB writeSlaveArray(SCL, device_address, register, dataPtr, count) : ackbit
'' Write out a block of i2c data bytes. Device select code is device_address. Device starting
'' address (0 to i2c slave size-1, in bytes) is register. Write data address is at dataPtr.
'' Number of bytes is count. Maximum count is 256 bytes.
'' Return zero if no errors or the acknowledge bits if an error occurred. If
'' more than 31 bytes are transmitted, the sign bit is "sticky" and is the
'' logical "or" of the acknowledge bits of any bytes past the 31st.
start(SCL)
ackbit := write(SCL,device_address | Xmit)
ackbit := (ackbit << 1) | write(SCL,register)
repeat count ' Now send the data
ackbit := ackbit << 1 | ackbit & $80000000 ' "Sticky" sign bit
ackbit |= Write(SCL, byte[dataPtr++])
stop (SCL)
PUB writeSlaveByte(SCL, device_address, register, value)
'' Write out a single byte of i2c data. Device select code is device_address. Device
'' starting address (0 to i2c slave array size-1, in bytes) is register. This returns true
'' if an error occurred.
if writeSlaveArray(SCL, device_address, register, @value, 1)
return true
return false
PUB writeSlaveWord(SCL, device_address, register, value)
'' Write out a single word of i2c data. Device select code is device_address. Device
'' starting address (0 to i2c slave array size-1, in bytes) is register. This returns true
'' if an error occurred.
if writeSlaveArray(SCL, device_address, register, @value, 2)
return true
return false
PUB writeSlaveLong(SCL, device_address, register, value)
'' Write out a single long of i2c data. Device select code is device_address. Device
'' starting address (0 to i2c slave array size-1, in bytes) is register. This returns true
'' if an error occurred.
if writeSlaveArray(SCL, device_address, register, @value, 4)
return true
return false
PUB readSlaveArray(SCL, device_address, register, dataPtr, count) : ackbit
'' Read in a block of i2c data bytes. Device select code is device_address. Device starting
'' address (0 to i2c slave array size-1, in bytes) is register. Read data is stored at
'' dataPtr. Number of bytes is count.
'' Return zero if no errors or the acknowledge bits if an error occurred.
start(SCL)
ackbit := write(SCL,device_address | Xmit)
ackbit := (ackbit << 1) | write(SCL,register)
start(SCL)
ackbit := (ackbit << 1) | write(SCL,device_address | Recv)
repeat count - 1
byte[dataPtr++] := Read(SCL, ACK)
byte[dataPtr++] := Read(SCL, NAK)
Stop(SCL)
return ackbit
PUB readSlaveByte(SCL, device_address, register) : value
'' Read in a single byte of i2c data. Device select code is device_address. Device
'' starting address (0 to i2c slave array size-1, in bytes) is register. This returns
'' true if an error occurred.
if readSlaveArray(SCL, device_address, register, @value, 1)
return -1
PUB readSlaveWord(SCL, device_address, register) : value
'' Read in a single word of i2c data. Device select code is device_address. Device
'' starting address (0 to i2c slave array size-1, in bytes) is register. This returns
'' true if an error occurred.
if readSlaveArray(SCL, device_address, register, @value, 2)
return -1
PUB readSlaveLong(SCL, device_address, register) : value
'' Read in a single long of i2c data. Device select code is device_address. Device
'' starting address (0 to i2c slave array size-1, in bytes) is register. This returns
'' true if an error occurred.
'' Note that you can't distinguish between a return value of -1 and true error.
if readSlaveArray(SCL, device_address, register, @value, 4)
return -1
I have been consistently reading and writing long data with this code. I assume reading and writing byte data will work. Also, I have not tried reading or writing the entire array.
Let me know if you see any mistakes.
By the way, I studied Hippy's AiChip_I2cSlave_Slave_006.spin object code. What was not clear from the instructions, in the object, or from the posts I had read, is to access the hub ram with the master object you need to add 1024 to your register address. Which is the switch that bypass' the cog ram. Also, hub ram size should be specified in powers of 2. So after implementing the Tim Moore's fixes to the jump table, in the AiChip_I2cSlave_Slave_006 object, I am now reading and writing, to and from, hub ram on my slave prop from a separate master prop using the AiChip_I2cSlave_Master_ProtoBoard_006 object.
I have tested Timmoore's version (altered to use 2 byte address) with an I2C eerpom reader program on a maple. Tim's i2cslave on the propeller works with the maple I2C @100KHz, but hangs if I run the maple's I2C at 400KHz. Has anyone had success with the i2cslave at 400KHz?
(The maple program will successfully write/read a real I2C EEPROM at both 100KHz and 400KHz.)
I have tested Timmoore's version (altered to use 2 byte address) with an I2C eerpom reader program on a maple. Tim's i2cslave on the propeller works with the maple I2C @100KHz, but hangs if I run the maple's I2C at 400KHz. Has anyone had success with the i2cslave at 400KHz?
(The maple program will successfully write/read a real I2C EEPROM at both 100KHz and 400KHz.)
Can you easily test other speeds ? ie is it nearly ok, or a long way short ?
( it's a good idea to check something you want to ship at +10% or so anyway )
Comments
The thing to remember is the address is shared between read and write so if you write the address pointer increments, same with read and if you dont supply the address at the start of write/read they affect each other.
I wrote the following set of routines, using Mike Green's I2c conventions, which can be pasted into the Basic_i2C_driver object and used for accessing the i2c slave. Note that when specifying the i2cslave_info array pointer, the size must be in a power of 2 (2, 4 8, .. 256):
I have been consistently reading and writing long data with this code. I assume reading and writing byte data will work. Also, I have not tried reading or writing the entire array.
Let me know if you see any mistakes.
By the way, I studied Hippy's AiChip_I2cSlave_Slave_006.spin object code. What was not clear from the instructions, in the object, or from the posts I had read, is to access the hub ram with the master object you need to add 1024 to your register address. Which is the switch that bypass' the cog ram. Also, hub ram size should be specified in powers of 2. So after implementing the Tim Moore's fixes to the jump table, in the AiChip_I2cSlave_Slave_006 object, I am now reading and writing, to and from, hub ram on my slave prop from a separate master prop using the AiChip_I2cSlave_Master_ProtoBoard_006 object.
Thanks, Tim for all your help!
(The maple program will successfully write/read a real I2C EEPROM at both 100KHz and 400KHz.)
Can you easily test other speeds ? ie is it nearly ok, or a long way short ?
( it's a good idea to check something you want to ship at +10% or so anyway )