U8g2: cannot change i2c HW clock speed

Created on 17 Sep 2018  路  11Comments  路  Source: olikraus/u8g2

I'm using U8G2_SSD1306_128X64_NONAME_F_HW_I2C
I can't seem to be able to change the i2c speed outside of the lib itself - which is hardcoded to 400khz in U8x8lib.cpp:
if ( u8x8->display_info->i2c_bus_clock_100kHz >= 4 ) { Wire.setClock(400000L); }
I'm trying to go faster since these OLEDs can do just fine at 1Mhz.

Am I missing anything obvious?
Or could there be some way to either set the i2c speed via the library/constructor itself, or allow it to be set outside the library via arduino's Wire.setClock(...) ?

enhancement

Most helpful comment

added

uint32_t getBusClock(void);
void setBusClock(uint32_t clock_speed);

for I2C and SPI

All 11 comments

Yes, it is hardcoded. You could change the library source in your local Arduino folder.

@olikraus i'm sure I've seen this issue come up before, would it be possible to add a u8g2.setClock(...) method to remove the need for people to mod the library? thinking you have a static var in the lib that holds the default speed for a given display, and the u8g2.setClock method could update that var?

Yes, it is hardcoded. You could change the library source in your local Arduino folder.

@olikraus That's exactly what I did, and the only way I could change the i2c clock speed.
While this works for me, it's not convenient for users who may not find it easy to change that setting.
The intent is to be able to change it through the library, from the sketch, so users of my code (that references your library) do not have to worry about this. Or at least be able to change/override it in the sketch, perhaps after u8g2 has been initialized.

Indeed a u8g2.setClock(...) or something to that effect would be great.

Great library by the way 馃憤

hmmm.... ok, I will think about this...
So your request is to have something like a u8g2.setI2CClockSpeed function to allow manual override of the internal default setting.

@olikraus Yes, or some way to be able to set the clock to something else than the hardcoded 400Khz.
I think it makes the most sense to have it as suggested - through the lib's API - a function seems most appropriate.

I think internally that function should simply call Wire.setClock and let Arduino handle whatever the clock value is, since different processors have different speeds available, so if the user passes in an invalid clock value, then it's not u8g2 lib's fault or responsibility to correct it in any way.

@olikraus yes, from my understanding u8g2 sets the desired clock frequency with each transaction, so i was thinking that instead of hard coding the speed for each display type it could be held in variable, and that variable used to set the speed in each transaction.
then the u8g2 clock method could change the value in that variable allowing the user to override the clock speed where desired, and if not overridden would keep using the current default speed for each screen/display controller type

added

uint32_t getBusClock(void);
void setBusClock(uint32_t clock_speed);

for I2C and SPI

Documentation updated.

Excellent, it works, thanks very much for the effort!

added

uint32_t getBusClock(void);
void setBusClock(uint32_t clock_speed);

for I2C and SPI

Really appreciated! My LCD would garble if the clockspeed was set to default. Wires weren't too long (10cm) and made solid contact.

Setting to: u8g2.setBusClock(600000); before u8g2.begin(); solved it right away! Amazing!!!

_Commenting just for future reference!_

I'm trying to port the low level stuff to the nRF52 because I didn't see someone already doing that.
I am starting with the big banging stuff first, as I didn't use the TWI APIs yet, but I cannot seem to change the bus clock properly:

    u8g2.u8x8.bus_clock = 1000000UL;
    u8x8_SetI2CAddress(u8g2_GetU8x8(&u8g2),0x3c);
    // u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_HW_com_nrf52832, u8g2_nrf_gpio_and_delay_cb);       
    u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8g2_nrf_gpio_and_delay_cb); 


    u8g2.u8x8.bus_clock = 1000000UL;
    u8g2_InitDisplay(&u8g2);

When the code then breaks in the gpio_and_delay_cb

 case U8X8_MSG_DELAY_I2C:
            //NRF_LOG_INFO("Got a U8X8_MSG_DELAY_I2C");
            // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
            // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
            if(arg_int == 1)
            {                
                nrf_delay_us(5);
                //NRF_LOG_INFO("sleep");
            }
            else if (arg_int == 4) 
            {
                //sleep_ns(1250);
                nrf_delay_us(1);
            }
            break;

I can see the arg_int == 4 despite still seems to be u8g2.u8x8.bus_clock = 1000000UL;?

Could that be a bug that the bus_clock is not used in i2c mode?

The thing why I want to set it to 100kHz is because the nRF SDK has no built-in delay_ns function. As said: First goal would be to have a simple "Hello world" then I'll probably switch to TWI anyways.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

13590787364 picture 13590787364  路  3Comments

morosanl picture morosanl  路  3Comments

eimogandolf picture eimogandolf  路  6Comments

benjaminauer picture benjaminauer  路  6Comments

idreamsi picture idreamsi  路  7Comments