# Driver for IT8951 E-Paper display
The driver uses the embedded_hal traits as hardware abstraction layer.
This driver can be used with the embedded graphics trait, currently only supporing Gray4 (16bit grayscale).
## Details
- IT8951 has a image load engine which can convert pixel data before storing it in the local frame buffer.
- It is possible to read and write the memory directly without using the image load engine
- **Important** Data must be always aligned to 16bit words!
- The crates uses the alloc feature to allocate memory on the heap:
- Firmware and LUT version string read from the controller
- Staging buffers to write pixel to the controller. The buffers are allocated as needed, but only one buffer at a time and with up to `Config::max_buffer_size`, which is 1kByte per default.
## Supported devices
It should support all waveshare devices using the IT8951 controller over SPI.
These e-ink screens are known to be working
* [7.8 inch, 1872×1404 pixels, 4-bit grayscale](https://www.waveshare.com/wiki/7.8inch_e-Paper_HAT)
* [10.3 inch, 1872×1404 pixels, 4-bit grayscale](https://www.waveshare.com/wiki/10.3inch_e-Paper_HAT) **Important** This screen needs to be initialized with origin of `TopRight` to be working correctly
## Performance Considerations
Always prefer the embedded_graphics `fill_solid` and `fill_contiguous` functions over `draw_iter`.
`draw_iter` writes every single pixel to the display, which has a significant overhead.
### Improve Drawing Speed e.g. for Fonts
If you embedded_graphics UI uses a lot of `draw_iter` calls, e.g. for font rendering, please consider using the textbox locally.
A suitable crate is [embedded-graphics-framebuf](https://crates.io/crates/embedded-graphics-framebuf).
An example can be found in the `test_eink` example.
The idea is to create a local framebuffer to render into, with only the required dimensions e.g. 100x20px on an 1000x800px display.
The local framebuffer can be written sparsely using `draw_iter`.
Afterwards the full local framebuffer is written to the display using `fill_contiguous`.
On an 200x30px sized Text as used in the example the speed-up is roughly 10x.
### Allocation details
The general approach of this crate is to dynamically allocate buffers with the smallest possible size.
Meaning the required heap is minimized, but new allocations & releases may happen more often.
We are currently discussing approaches without alloc. If you have any opinion on this please get in touch.
## TODOs
- Support Gray2 and Gray8 with embedded-graphics
- Support display engine fill area
- Support display engine 1 bit per pixel mode
- Support static buffer allocations
## Changelog
### 0.5.1
- Reset pin is optional
- VCOM during init is optional
### 0.5.0
- Add optional defmt support
- Add display origin support (fixes mirroring on certain devices)
- Allow setting memory buffer address
### 0.4.2
- add display rotation support
- Exponential backoff for `wait_while_busy`
### 0.4.1
- fix divide by zero in fill_solid for zero sized area
- fill_solid correctly skip limit areas to the display bounds
### 0.4.0
- **Public API** `new` expects a `Config` parameter to set timeout and buffer size. Default is implemented with timeouts of 15s and buffer size is 1024 Bytes.
- Buffer data type changed from u16 to u8
- **Public API**: `load_image_area`, `load_image`, and `memory_burst_write` functions are now using u8 as buffer type
- Memory usage is reduced by half (1kByte max. instead of 2kByte)
- **Behavior** Calling `init` no longer clears the eink display. Instead call `reset` directly.