Request I2C maximum bytes increase to 35
-
Sorry to dig this up again. Adafruit has a NeoDriver documentation error which led me to believe 34 would be enough to send the maximum of 10 LEDs, but it seems like it needs one more.
I looked at the RFF code a little. From what I was able to gather, if one doesn't use the maximum array size for M260, it might resend the first byte again at the end of the transaction, and I think maybe the NeoDriver is expecting that. I'm uncertain about that, but in any case the only difference with sending 34 bytes is it's exactly the nominal maximum. It looks like RFF creates an array with the maximum number of elements in any case, and the comments say something about filling the unused elements with the first byte. That makes me think maybe it needs that to work.
EDIT: I looked at the code again and it looks like it sends false to doPad, so I guess it's not padding per se. But I still think the main difference is with less than 34 bytes of data, it's doing something it's not if you try to use the maximum size.
-
@DonStauffer said in Request I2C maximum bytes increase to 35:
EDIT: I looked at the code again and it looks like it sends false to doPad, so I guess it's not padding per se. But I still think the main difference is with less than 34 bytes of data, it's doing something it's not if you try to use the maximum size.
I've reviewed the code (in the 3.6-dev branch) and I don't see it doing anything different if you send less than the maximum size. Please can you explain what it is that you think is wrong with the code when you ask to send fewer than 34 bytes of data.
-
@dc42 My suspicion is that the NeoDriver ignores the last byte because it gets sent with a STOP condition, but I can't get an answer from Adafruit. I did see that the InternalTransfer function in Wire.cpp does that (or something like it) with the last byte. I don't know the rules of I2C well enough to know if that's what it should do. I'm actually not sure whether the STOP condition prevents sending the last byte. But it definitely does something different with the last byte:
**// Send all bytes except the last one.** // Ideally, if there are bytes to read as well as write, we would not send a STOP after sending all the bytes. // Unfortunately, the SAM TWI peripheral doesn't provide any means of reporting when the transmission is complete if we don't send STOP after it. while (bytesSent + 1 < numToWrite) { twi->TWI_THR = *buffer++; if (!WaitByteSent(statusWaitFunc)) { twi->TWI_CR = TWI_CR_STOP; (void)WaitTransferComplete(statusWaitFunc); return bytesSent; } ++bytesSent; } **twi->TWI_THR = *buffer++;** **twi->TWI_CR = TWI_CR_STOP;** if (WaitByteSent(statusWaitFunc)) { ++bytesSent; } (void)WaitTransferComplete(statusWaitFunc); if (bytesSent < numToWrite || numToRead == 0) { return bytesSent; }
-
@dc42 The problem isn't when you send fewer. It's when you try to send all 34 bytes. I get an I2C Transmission Error.
For a while I was getting lots of those randomly and when I tried sending 34 bytes what I got was that the colors came through wrong, but I didn't get the Transmission Error. However, I just installed a pair of pull up resistors on the NeoDriver and suddenly I never get them EXCEPT when I try to send 34 bytes, and when I do, it doesn't mess up the colors; it just ignores the entire transaction. This is consistent and mostly the pull up resistors solved my NeoDriver issues.
So I think I had unreliable transmission before and now the transmission is working well.
-
@dc42 I'm going to go out on a limb:
From how I interpret the code, it seems like after sending the last byte, it may be necessary to wait for a status of TWI_SR_TXRDY before setting the TWI_CR member to TWI_CR_STOP. Possibly if that gets done no increase would be necessary.
If that doesn't make any sense, disregard. I may be misunderstanding.
-
@DonStauffer there is nothing different about how RRF ends a 34-byte transaction compared to a 33-byte transaction. So I can't see how the problem you are having with 34-byte transactions can be the fault of RRF.
Does Adafruit publish the firmware that runs on the NeoDriver?
-
@dc42 I'll check.
-
-
@DonStauffer if you are writing data to the BUF register (register 0x04) then according to https://learn.adafruit.com/adafruit-seesaw-atsamd09-breakout/neopixel the maximum length you can write is is 32 bytes, of which the first 2 bytes are the start address.
-
@dc42 AdaFruit's seesaw NeoDriver page says "Data should be written in blocks of maximum size 30 bytes at a time." So the 30 byte limit refers to the actual color data - 3 bytes per LED x 10 LEDs.
The overhead is: a byte for module base register address (0x0E); a byte for the function register (0x04), and 2 bytes for the offset into the NeoDriver buffer. The module base register address is necessary for the seesaw chip to know what feature of the seesaw chip to use (there are many more besides NeoPixels), and the function register is needed so the chip knows you are sending data to write to the buffer.
That makes a total of 34 bytes in the I2C transaction (not including the I2C address (0x60)) to send a 30-byte block. 32 bytes are passed to the seesaw's NeoPixel BUF function (essentially a "write" function), and provide the information it needs to write the data to the buffer. There is no way to send 30 data bytes to the NeoDriver BUF function with a smaller I2C transaction than 34 bytes. This is borne out by the fact that I can successfully send 27 data bytes only by using an I2C transaction of 31 bytes, using the overhead I described.
(There is an error in AdaFruit's published information: They say 30 data bytes, but the specified offsets for the data is "2-32", which would be 31 bytes. My interpretation is they meant to say "2-31" for the data, which would be 30 bytes. I did ask them if the 31st byte was a trailer, like a null or something, but I didn't get a response)
-
@DonStauffer theI2C device address (which you have called the base address) doesn't count in the 34-byte limit in RRF because it is passed separately to the I2C driver. So RRF currently allows you to send the register address followed by up to 33 data bytes. IOW the B parameter of the M260 command accepts up to 34 values.
-
@dc42 The "module base register address" for the NeoPixel module (0x0E) is different from the I2C address (0x60). It is the first byte of what I2C would consider the data.
The second byte is the "Function Register", which in the case of a write operation is 0x04. The 3rd and 4th data bytes of the I2C transaction payload provide the offset into the NeoDriver buffer, meaning if you give it 0x0003 the data will set colors starting with the 4th LED in the strip.
After those initial 4 bytes, the data is in 3-byte groups, which are the 3 colors for each LED. So there are 4 bytes up front (not including the I2C address, naturally) before the colors begin.
As a result, sending 30 bytes of colors, the maximum AdaFruit recommends, requires a 34 byte I2C transaction payload.
-
@DonStauffer so is it still the case that you only need to use a 34-byte payload in the B parameter?
-
@dc42 The Adafruit documentation is ambiguous because it's internally contradictory by one byte. So I don't know.