Closed dveazie closed 5 years ago
Yes. It looks odd, but this is how it is described in the datasheet for I2C. It might be possible, that cmd and data can be switched within one transaction, but I never tested this. The other problem is this: Assume I have a long sequence of commands and args. I anyways have to split them into smaller pieces due to the restrictions of the Arduino Wire library. And finally: These commands are transfered only during startup. So there is (almost) no performance impact.
Thank you for the quick reply olikraus. One thing I didn't make clear is that I'm not suggesting that the entire init_seq be sent in 1 transaction. But rather that maybe each command should be sent in 1 transaction.
The init_seq I'm using is u8x8_d_ssd1306_96x16_er_init_seq and the first few commands are:
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x00f), /* multiplex ratio, 0.69 OLED: 0x0f */
U8X8_CA(0x0d3, 0x000), /* display offset, 0.69 OLED */
U8X8_C(0x040), /* set display start line to 0, 0.69 OLED */
As things are now, each byte is sent in its own transaction: U8X8_C(0x0ae) -> [START][0x78][0x00][0xAE][STOP] U8X8_CA(0x0d5, 0x080) -> [START][0x78][0x00][0xD5][STOP][START][0x78][0x00][0x80][STOP] U8X8_CA(0x0a8, 0x00f) -> [START][0x78][0x00][0xA8][STOP][START][0x78][0x00][0x0F][STOP] U8X8_CA(0x0d3, 0x000) -> [START][0x78][0x00][0xD3][STOP][START][0x78][0x00][0x00][STOP] U8X8_C(0x040) -> [START][0x78][0x00][0x40][STOP]
I'm wondering if instead it should be something like: U8X8_C(0x0ae) -> [START][0x78][0x00][0xAE][STOP] U8X8_CA(0x0d5, 0x080) -> [START][0x78][0x00][0xD5][0x80][STOP] U8X8_CA(0x0a8, 0x00f) -> [START][0x78][0x00][0xA8][0x0F][STOP] U8X8_CA(0x0d3, 0x000) -> [START][0x78][0x00][0xD3][0x00][STOP] U8X8_C(0x040) -> [START][0x78][0x00][0x40][STOP]
I'd also like to make it clear that I don't even know yet if what I'm proposing is correct or not. I've got a question into a rep for Solomon Systech and I haven't heard back yet. I also plan on connecting an Aardvark and trying some things out. I'll let you know what I find. Have a great day!
Well, yes, I figured out one way how it works... So I kept it how it is...
I did some tests here
Uno U8G2_SSD1306_128X64_NONAME_F_HW_I2C HW I2C FPS: Clip=17.3 Box=19.5 @=6.6 Pix=8.8 each byte has its own start stop
Uno U8G2_SSD1306_128X64_NONAME_F_HW_I2C HW I2C FPS: Clip=18.0 Box=20.3 @=6.6 Pix=9.0 start/stop for each command
Uno U8G2_SSD1306_128X64_NONAME_F_HW_I2C HW I2C FPS: Clip=18.3 Box=20.8 @=6.7 Pix=9.1 one start/stop for multiple commands
The second measure is the implementation of your last post. It increased performance by about 4%. The third variant only sends one start at the beginning and then sends as much commands as possible.
Actually the whole thing is a little bit risky, because the number of bytes between start and stop is limited in the Arduino environment to 32 bytes, so the third version will only work if the overall number of bytes of the init sequence does not exceed 32 bytes (difficult for some more complex controllers)
The second version seems to be better, but still the number of args must not exceed 31 bytes. The problem might be the grayscale command for some OLEDs...
There will be now two CAD procedures:
u8x8_cad_ssd13xx_i2c classic version
u8x8_cad_ssd13xx_fast_i2c your suggestion from above (4% improvement)
I will apply this to SSD1306 controller for now. This is a list of other controllers, for which the fast procedure needs to be verified first:
SH1106 SH1107 SH1108 SH1122 SSD1309 SSD1317 SSD1325 SSD0323 SSD1326 SSD1327 ST7567 ST7588
closing this...
Trying to use u8x8 with an SSD1306 and I don't think the data is being sent down the I2C bus correctly. During initialization, the first command is "Set Display OFF" which is a command that takes no arguments. I see: START 01111000 0 (Setup Write to [0x3C] + ACK) 00000000 0 (0x00 + ACK) 10101110 0 (0xAE + ACK) STOP
All good so far. The next command is "Set Display Clock Divide Ratio/Oscillator Frequency" which takes an argument. I see: START 01111000 0 (Setup Write to [0x3C] + ACK) 00000000 0 (0x00 + ACK) 11010101 0 (0xD5 + ACK) STOP START 01111000 0 (Setup Write to [0x3C] + ACK) 00000000 0 (0x00 + ACK) 10000000 0 (0x80 + ACK) STOP
Is this correct? Or should it be all in 1 transaction like this: START 01111000 0 (Setup Write to [0x3C] + ACK) 00000000 0 (0x00 + ACK) 11010101 0 (0xD5 + ACK) 10000000 0 (0x80 + ACK) STOP
This happens for all of the commands that take arguments. In the past I used a display that had an ST7036 controller and I thought that all the commands that took arguments were done in 1 transaction. I don't have that project anymore so maybe I'm remembering wrong.