Open MatzElectronics opened 6 years ago
Who is working on the docs for these blocks?
@mrodriguez-parallax - Can you test these blocks and report back?
We need docs and testing on this issue please.
See unpub node 1673 for draft block ref content
These blocks don't work yet. Here is a list of changes that can be made to the C code the blocks emit to get single byte exchanges to work. I will take a look at multi-byte next (soon I hope).
In the C code the i2c controller receive block emits, remove & from i2cInBuf in i2c_in call.
When an I2C block causes an i2c_init call to be added to the code, it needs to put the SCL value in the first argument and the SDA value in the second.
In the C code the i2c controller send block emits, the i2cInBuf needs to be populated before the call to i2c_out, not after. It would probably be better to name it i2cBuf, or have separate i2cIn/Out buffers.
@AndyLindsay @zfi here are the changes recommended above: https://github.com/parallaxinc/BlocklyProp-cdn/pull/83
I retested the MMA7455 accelerator for some basic I2C communication and also did some multi-byte addressing and waiting for busy with the the 24LC512. Both generated working C code.
i2c eeprom 24LC512 string across 128 byte boundary i2c eeprom 24LC512 int i2c MMA7455 z-axis
The only gotcha or surprise so far was that I had to use the "Other" board type to get access to P28 and P29 for the Propeller's EEPROM bus. I'm guessing the rationale was to prevent a user from modifying their own EEPROM program. Since it would take some concerted effort to modify the EEPROM, it's probably safe to allow I2C access to the P28 and P29 lines on the FLiP and Activity Board. The ones to remove would be P26 and P27 on the FLiP and Activity Board since since LED and D/A circuits could interfere. Especially on the Activity Board, P26 and P27 are behind RC filters and output buffers. Unidirectional, so no SDA, and RC + slew won't be good for SCL either.
Although the result of a store to and retrieve from EEPROM operation comes out right, the order the bytes are transmitted and received in is the reverse of what the block says. The i2c send block transmits bytes LSB first when it is set to MSB first. Likewise, the i2c receive block receives bytes LSB first when it is set to MSB first.
Also, when a send or receive block is set to LSB first, it makes the 4th argument in the i2c_write/read call negative. Instead, it should make the 6th argument negative when it is set to MSB first.
I think this can be resolved in 2 steps:
Example: Send with the default LSB first setting
item = [01020304] hexadecimal
i2c controller send [4] bytes of data [item] [LSB first] to register [32768] length [2] bytes at device address [1010000 binary] SDA [29] SCL [28]
// ------ Libraries and Definitions ------
#include "simpletools.h"
// ------ Global Variables and Objects ------
int item;
i2c *i2c29;
unsigned char i2cBuf[4] = {0, 0, 0, 0};
// ------ Main Program ------
int main() {
i2c29 = i2c_newbus(28, 29, 0);
item = (0x01020304);
i2cBuf[3] = (item >> 24) & 255;
i2cBuf[2] = (item >> 16) & 255;
i2cBuf[1] = (item >> 8) & 255;
i2cBuf[0] = (item) & 255;
i2c_out(i2c29, 0b1010000 & 0x7F, 32768, 2, i2cBuf, 4);
}
Example: Send with the alternate MSB first setting
item = [01020304] hexadecimal
i2c controller send [4] bytes of data [item] [MSB first] to register [32768] length [2] bytes at device address [1010000 binary] SDA [29] SCL [28]
// ------ Libraries and Definitions ------
#include "simpletools.h"
// ------ Global Variables and Objects ------
int item;
i2c *i2c29;
unsigned char i2cBuf[4] = {0, 0, 0, 0};
// ------ Main Program ------
int main() {
i2c29 = i2c_newbus(28, 29, 0);
item = (0x01020304);
i2cBuf[3] = (item >> 24) & 255;
i2cBuf[2] = (item >> 16) & 255;
i2cBuf[1] = (item >> 8) & 255;
i2cBuf[0] = (item) & 255;
i2c_out(i2c29, 0b1010000 & 0x7F, 32768, 2, i2cBuf, -4); // <- Note 4 changed to -4
}
Example: Receive with the default LSB first setting
i2c controller receive [4] bytes [LSB] first from register [32768] length [2] bytes at device address 1010000 binary as [Decimal] store in [item2] SDA [29] SCL [28]
// ------ Libraries and Definitions ------
#include "simpletools.h"
// ------ Global Variables and Objects ------
int item2;
i2c *i2c29;
unsigned char i2cBuf[4] = {0, 0, 0, 0};
// ------ Main Program ------
int main() {
i2c29 = i2c_newbus(28, 29, 0);
i2c_in(i2c29, 0b1010000 & 0x7F, 32768, 2, i2cBuf, 4);
item2 = ((i2cBuf[3] << 24) | (i2cBuf[2] << 16) | (i2cBuf[1] << 8) | i2cBuf[0]);
}
Example: Receive with the alternate MSB first setting
i2c controller receive [4] bytes [MSB] first from register [32768] length [2] bytes at device address 1010000 binary as [Decimal] store in [item2] SDA [29] SCL [28]
// ------ Libraries and Definitions ------
#include "simpletools.h"
// ------ Global Variables and Objects ------
int item2;
i2c *i2c29;
unsigned char i2cBuf[4] = {0, 0, 0, 0};
// ------ Main Program ------
int main() {
i2c29 = i2c_newbus(28, 29, 0);
i2c_in(i2c29, 0b1010000 & 0x7F, 32768, 2, i2cBuf, -4); // <- Note 4 changed to -4
item2 = ((i2cBuf[3] << 24) | (i2cBuf[2] << 16) | (i2cBuf[1] << 8) | i2cBuf[0]);
}
If you start with an i2c controller send block that looks like this:
i2c controller send [4] bytes of data [item] [LSB first] to register [32768] length [2] bytes at device address [1010000 binary] SDA [29] SCL [28]
... it kind of looks like the register address will be transmitted LSB first and the device address is 2 bytes long. Here is one way that might bake it clearer:
i2c controller send Data [4 bytes] [LSB] first [item] Register [2 bytes] address 32768 Bus SCL 28 SDA 29 Device address 1010000 binary
Conversely, the i2c receive command to get that data back from an EEPROM is currently
i2c controller receive [4] bytes [LSB] first from register [32768] length [2] bytes at device address 1010000 binary as [Decimal] store in [item2] SDA [29] SCL [28]
It might be more clear as something like:
i2c controller receive Data [4 bytes] [LSB] first [item] Register [2 bytes] address 32768 Bus SCL 28 SDA 29 Device address 1010000 binary
One final thought for now, it might be better to only have the MSB/LSB option appear when more than one byte of data is sent/received.
I was able to incorporate nearly all of @AndyLindsay 's suggestions, so these blocks should now be ready for a comprehensive re-test.
I didn't see any issues in the retest.
Thanks, @PropGit for pointing out that we no longer have access to P28 and P29. Those should not be off limits.
My tests this morning were no good because I used old blocks that I had saved instead of dragging out new ones. True, the code those blocks generated was correct, but it looks like the blocks have been modified too. It's going to need to be retested.
@AndyLindsay - Sure!
These are done, but require testing