Waveshare 3.49 and mipi_spi

this is a odd sized display with 640x172 format, and tried to use the mipi drivers for it but got this error:

Failed config

display.mipi_spi: [source /config/esphome/esphome-web-c0c120.yaml:1981]
platform: mipi_spi
id: main_display
model: AXS15231
data_rate: 80MHz
cs_pin: 9
reset_pin: 21
rotation: 90
update_interval: never
dimensions:
height: 640

Dimensions and offsets must be divisible by 8.
width: 172

pages:
- id: idle_page

not sure if this is a issue with mipi_spi or if it just won’t support odd sized displays that doesn’t divide by 8? qspi works though.

What happens if you lie and tell it that it’s 176?

Also, use code tags for you yaml, they make your posts much easier to read.

no that would be a workaround not a fix, then i might as well stay on qspi

and yes i didn’t put the logs in code block because it was just that, logs, not code. (the logs is just quoting a code block)

it worked with 176 but of course my gfx gets cropped and my OCD is going nuts well knowing it’s 172

spi:
  id: display_qspi
  type: quad
  clk_pin: 10
  data_pins: [11, 12, 13, 14]

display:
  - platform: mipi_spi
    id: main_display
    model: AXS15231
    data_rate: 80MHz
    cs_pin: 9
    reset_pin: 21
    rotation: ${rotate_display}
    update_interval: never
    dimensions:
        height: 640
        width: 176

Probably a good idea to log an issue on Github then.

So looking into this, the problem is that the AXS15231 requires partial writes to be on 8 pixel boundaries, so it has a draw_rounding preset of 8. If you are using LVGL you might be able to set draw_rounding to 4 in the display config but 8 in the LVGL config (I have not tested that.)

If you’re using the native drawing functions you should stick with 176 and just avoid drawing in the off-screen area.

yeah im using native drawing, a shame that is the workaround when it worked with qspi, but i will try to adapt to it, just have to make seperate dimensions for display and drawing routines :slight_smile: thanks for looking into it :+1:

i use same drawing logic for many displays and though i could fix it with a offset to this display, but that complains too about not being devideable by 8 :frowning:

display:
  - platform: mipi_spi
    id: main_display
    model: AXS15231
    data_rate: 80MHz
    cs_pin: 9
    reset_pin: 21
    rotation: ${rotate_display}
    update_interval: never
    dimensions:
        height: ${imagewidth}
        width: 176
        offset_width: 4

problem is that it starts drawring at 0,0, where to avoid cropping it should start at 0,4 and only way i can do that without affecting other displays using same drawing yaml is to make a new substitution like “draw_offset” and set it to 4 for this display., 0 for all others displays and calculate that in all the drawing i do…

if you have a better suggestion i would be happy to hear it :slight_smile:

You can set draw_rounding to 4 which will allow the dimensions and offsets to be divisible by 4. You will probably also need to set auto_clear_enabled to ensure full screen updates because previous tests with the AXS15231 showed it will not do partial updates except on 8 pixel boundaries.

draw_rounding: 4 doesn’t seem to change anything, still get compile error:
Dimensions and offsets must be divisible by 8.
no matter if i use original size and no offset:

display:
  - platform: mipi_spi
    id: main_display
    model: AXS15231
    data_rate: 80MHz
    cs_pin: 9
    reset_pin: 21
    rotation: ${rotate_display}
    draw_rounding: 4
    auto_clear_enabled: true
    dimensions:
        height: 640
        width: 172
#        offset_width: 4
    update_interval: never

or 176 with offset 4

display:
  - platform: mipi_spi
    id: main_display
    model: AXS15231
    data_rate: 80MHz
    cs_pin: 9
    reset_pin: 21
    rotation: ${rotate_display}
    draw_rounding: 4
    auto_clear_enabled: true
    dimensions:
        height: 640
        width: 176
        offset_width: 4
    update_interval: never

:man_shrugging:

Does it work using the old driver and an offset of 4?

it works as it should with qspi and no offset, if thats what you mean?

display:
  - platform: qspi_dbi
    id: main_display
    model: AXS15231
    data_rate: 80MHz
    cs_pin: 9
    reset_pin: 21
    rotation: ${rotate_display}
    update_interval: never
    dimensions:
        height: 640
        width: 172

if i set width to 176 and offset 4, then i just get 4 lines of garbage but it does compile

So that’s the problem, an offset of 4 isn’t going to work because that display controller requires writes to be on 8 pixel boundaries.

when is qspi planned to be removed?, a shame since that works :frowning:

There’s no specific date, but you just said it didn’t work (4 lines of garbage.)

no with qspi it works perfect with the real dimesion settings and no offset, all is good. it’s when i add offset and use 176 instead of 172 i get the extra line of garbage as expected. only testet that since you asked how offset worked with original driver, it’s not needed with qspi.

problem is if qspi is being removed and it isn’t working with mipi

So why do you want to specify an offset? With width of 176 and an offset of 0 (the default) it will just crop at the end. Not ideal, but should work.

But the other option is to use the custom model - adapt for your pin config etc.

display:
  - platform: mipi_spi
    model: custom
    color_order: RGB
    bus_mode: QUAD
    init_sequence:
        - [0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5]
        - [0xC1, 0x33]
        - [0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
    rotation: 0
    draw_rounding: 4
    dimensions:
      height: 480
      width: 172
    cs_pin: 45 # as required.
    data_rate: 40MHz

Interestingly, testing this on a JC3248W535 it works fine. The original AXS15231 board that was tested required draw_rounding of 8, but maybe that is not fundamental to the chip, just that particular board.

The mipi_spi driver also needs tweaking so that setting draw_rounding overrides the default for the dimensions check but the custom model will get you going for now.

no with width of 176 and default offset (0) it crops the top, so i would have to adjust all my display pages and calculations for this display only.

i tried your example:

display:
  - platform: mipi_spi
    id: main_display
    model: custom
    bus_mode: QUAD
    cs_pin: 9
    reset_pin: 21
    init_sequence:
        - [0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5]
        - [0xC1, 0x33]
        - [0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
    rotation: 90
    draw_rounding: 4
    update_interval: never
    dimensions:
        height: 640
        width: 172

and not sure if it’s the init codes but get this:

i have no clue regarding init codes, but when looking at xiaozhi-es32’s code for same display : xiaozhi-esp32/main/boards/waveshare-s3-touch-lcd-3.49/waveshare-s3-touch-lcd-3.49.cc at 1d1f9ff1ff82692cd36df72ddd376c62f41d633c · 78/xiaozhi-esp32 · GitHub
the only init codes i see is these:

static const axs15231b_lcd_init_cmd_t lcd_init_cmds[] = {
    {0x11, (uint8_t []){0x00}, 0, 100},
    {0x29, (uint8_t []){0x00}, 0, 100},
};

but when trying to use same in esphome:

display:
  - platform: mipi_spi
    id: main_display
    model: custom
    bus_mode: QUAD
    cs_pin: 9
    reset_pin: 21
    rotation: ${rotate_display}
    init_sequence:
      - [0x11]
      - delay 100ms
      - [0x29]
      - delay 100ms
    update_interval: never

i get same 4 set of bars on top and below as with your example :man_shrugging:

The init sequence is fine, it’s the same as what you have been using with the axs15231 model. Try without rotation first up, and use show_test_card: true with an update interval other than never.

What version of ESPHome are you using?