Inkplate 10 hardware interfaces for Rust implementation

Customer:

I’m planning a project with an Inkplate 10 and need to understand the hardware interfaces to implement them in Rust. I want to program the ESP32 in Rust rather than MicroPython or C++, so I’ll need to implement the communication protocols myself.

What’s the command set for SD card communication? I see it uses SPI. Also, what’s the interface to the E-Paper display? It looks like a mix of I2C and GPIO pins - does the ESP32 communicate with IO expanders over I2C, which then set pins connected to the display?

Originally submitted via email support on 23 December 2025. Migrated to the forum for community visibility.

Soldered Support:

The SD card supports communication via the SPI protocol. The Inkplate library uses the SdFat library to initialize and communicate with the SD card - you can check its source code for details. There’s also a Rust library that could do what you’re trying to accomplish.

The Inkplate 10 panel communicates with an 8-bit bit-banged parallel protocol. All data lines are connected directly to the ESP32, while some control pins are connected via the GPIO expander. To understand the full implementation, analyze the schematic.

Since this is a significant undertaking, I’d recommend studying the code available in the repository. Note that this version currently only supports the newer Inkplate 10 model with a purple PCB and the PCAL GPIO expander. Feel free to ask if you have more questions.

Customer:

I have a few follow-up questions:

  1. What does the ARDUINO_ESP32_DEV build flag represent? It appears in the old version but not in the cleaned-up code.

  2. In several places, internalIO.pinMode(addr, OUTPUT) is followed by internalIO.digitalWrite(addr, LOW), notably in void EPDDriver::gpioInit(). However, in void IOExpander::pinModeInternal(uint8_t _pin, uint8_t _mode), if mode is OUTPUT, the code sets the pin state to LOW. This would imply the call to internalIO.digitalWrite(addr, LOW) is unnecessary, unless I’m missing something.

  3. In void EPDDriver::gpioInit(), on the third line there’s a call to internalIO.digitalWrite(9, LOW);, which according to the schematic appears to be GPIO_0_MOSFET. Later, there’s internalIO.pinMode(9, OUTPUT); internalIO.digitalWrite(9, LOW);. If GPIO_0_MOSFET is set to output and set to low, can the later initialization be skipped?

  4. There’s mention of initializing unused pins in IO expander 1 (internalIO) using addresses 14 and 15, and later addresses 10, 11, and 12. While 14 and 15 are indeed unused, there seems to be an off-by-one error: the pin with address 10 (P1_2, pin 12 on the schematic) links to SD_ENABLE. So the now-unused pins (which were previously touchpad pins) are 11 to 15, and all can be configured as OUTPUT LOW.

Soldered Support:

Great questions, and thanks for the thorough analysis!

  1. The ARDUINO_ESP32_DEV build flag is used to detect the older version of the Inkplate 6 device, where the older MCP expander was used. In the rewrite, support for older e-radionica Inkplate devices isn’t yet implemented.

2 & 3. You’re absolutely right on both points. There are redundant code snippets in places that were used while debugging. I’m the one refactoring the library, so I know there are unfinished or not-yet-cleaned-up parts in the code since we’re currently adding support for an upcoming Inkplate device and the whole refactoring has been put on hold. If you find similar redundant or confusing code sections, please report them back - it will help the refactoring process.

  1. Your analysis about the off-by-one error and the unused pins 11 to 15 that can be configured as OUTPUT LOW is correct.

Thank you for taking on this significant undertaking. I’m confident your Rust implementation could later serve as a template to build support for all Inkplate models.