Configuring SSD1306 shield with 64x32 pixel display.

I recently bought this display that is 64x32 pixels and uses the SSD1306 driver. When running the LVGL Basic Sample with the Zephyr ssd1306_128x64 shield, the display works, but shows only the bottom center of what would show up on the 128x64 display. Zephyr does not have a ssd1306_64x32 shield unfortunately, so I have tried changing the width and height in the devicetree like from 128->64 and from 64 ->32 like this:
nrf52dk_nrf52832.overlay:
/ {
	chosen {
		zephyr,display = &ssd1306_ssd1306_128x64;
	};
};

&arduino_i2c {
	status = "okay";

	ssd1306_ssd1306_128x64: ssd1306@3c {
		compatible = "solomon,ssd1306fb";
		reg = 0x3c;
		width = 64;
		height = 32;
		segment-offset = 0;
		page-offset = 0;
		display-offset = 0;
		multiplex-ratio = 63;
		segment-remap;
		com-invdir;
		prechargep = <x22;
	};
};
but this results in the display freezing on whatever was showing before the flash. Any ideas on what I could modify to use a 64x32 display?
  • I have found a temporary solution. In zephyr/drivers/display/ssd1306.c, change these lines:

    static int ssd1306_write_default(const struct device *dev, const uint16_t x, const uint16_t y,
    				 const struct display_buffer_descriptor *desc, const void *buf,
    				 const size_t buf_len)
    {
    	uint8_t cmd_buf[] = {
    		SSD1306_SET_MEM_ADDRESSING_MODE,
    		SSD1306_ADDRESSING_MODE,
    		SSD1306_SET_COLUMN_ADDRESS,
    		x,
    		(x + desc->width - 1),
    		SSD1306_SET_PAGE_ADDRESS,
    		y/8,
    		((y + desc->height)/8 - 1)
    	};

    to this:

    static int ssd1306_write_default(const struct device *dev, const uint16_t y,
    				 const struct display_buffer_descriptor *desc, const void *buf,
    				 const size_t buf_len)
    {
    	uint8_t cmd_buf[] = {
    		SSD1306_SET_MEM_ADDRESSING_MODE,
    		SSD1306_ADDRESSING_MODE,
    		SSD1306_SET_COLUMN_ADDRESS,
    		SSD1306_SET_LOWER_COL_ADDRESS,
    		SSD1306_SET_HIGHER_COL_ADDRESS,
    		SSD1306_SET_PAGE_ADDRESS,
    		y/8,
    		((y + desc->height)/8 - 1)
    	};

    Where

    SSD1306_SET_LOWER_COL_ADDRESS = 0x20
    SSD1306_SET_HIGHER_COL_ADDRESS = 0x5f

    Also, the multiplex ratio in the device tree configuration should be set to height-1, so 31.

    I am not sure where I am supposed to be able to set the "x" value in the ssd1306_write_default() function. This would allow me to configure the display without needing to modify the zephyr source files.

  • Hi,

    Can you debug the application and set a breakpoint in ssd1306_write_default() to see where it is being called from? I tried this with the default sample, but the breakpoint was never hit.

    Have you made any other modifications to the libraries or sources?

    Best regards,
    Jørgen

  • HI Jørgen,

    Attached is the project folder. I am building with the nrf52dk_nrf52832 board. The breakpoint gets hit and there are multiple functions that are called before it.

    Also it turns out that my temporary "solution" only works for the text labels set in main(). Anything added afterwards shows up broken on the screen (similar to what it looked before the temp fix)

    Project folder:

    3302.lvgl.zip

    In the attached solution I modified some lines in the ssd1306_write_default to be able to change the "x" value dynamically with "segment offset" in the devicetree.

     

Related