Skip to content

[bug] ESP32SPI sends garbage data to display on 9-bit SPI #754

@Eggrror404

Description

@Eggrror404

Currently, the ESP32SPI databus cannot properly communicate with a display through 9-bit SPI, not even initialize it.

Since the ESP32 SPI driver sends data byte by byte, any message that does not make up a multiple of bytes gets padded with "random bits" as the official docs says. So in the flush function, pushing any amount of bits (consists of 9-bit commands) may include garbage data at the end to make up a full byte, breaking the communication.

If the amount of bits pushed is limited to multiple of 8, with some other additional changes (because flushing now may not leave the buffer empty), the communication would work and the display could display something.

my current changes
void Arduino_ESP32SPI::beginWrite()
{
  // _data_buf_bit_idx = 0;
  // _buffer[0] = 0;
  ...
}

void Arduino_ESP32SPI::writeRepeat(uint16_t p, uint32_t len)
{
  ...
  if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
  {
    for (uint32_t i = 0; i < len; i++) {
      write16(p);
    }
    return; // TEMPORARY FIX
  ...
}

void Arduino_ESP32SPI::flush_data_buf()
{
  if (_data_buf_bit_idx % 8 != 0) return;
  uint16_t bytes = _data_buf_bit_idx / 8; // total bytes to flush, NOT including leftovers

  // uint32_t len = (_data_buf_bit_idx + 31) / 32;
  uint32_t len = (bytes + 3) / 4;
  for (uint32_t i = 0; i < len; i++)
  {
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5
    _spi->dev->data_buf[i].val = _buffer32[i];
#else
    _spi->dev->data_buf[i] = _buffer32[i];
#endif
  }
  POLL(bytes * 8 - 1);

  uint16_t leftover_bits = _data_buf_bit_idx - bytes * 8;
  _buffer[0] = _buffer[bytes];
  _data_buf_bit_idx = leftover_bits;
  // _data_buf_bit_idx = 0;
}

The better solution, I think, is padding flushes with no-op commands (9 zeros i believe) until the data is a multiple of bytes. At maximum, only 7 commands would be padded. This doesn't leave part of existing commands in the buffer after flushing, and the assumption that the buffer would be empty after flushing wouldn't be broken as well.

I'd love to create a PR for that if wanted, since I'm working with this 3-wire SPI display module myself already.

Thanks for the amazing library, and wish you a nice 2026 :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions