ST7735 Display Driver
A no_std Rust driver library for the ST7735 TFT LCD display controller
Features
- no_std support: Can be used in embedded systems
- Type-safe color formats: Compile-time guarantees for 12-bit, 16-bit, and 18-bit color modes
- Flexible range specification: Supports Rust's standard range syntax
- Zero-cost abstractions: Type safety without runtime overhead
- Comprehensive testing: Validates behavior of each command and color format
Supported Color Formats
| Format | Bit Layout | Bytes/Pixel | Description |
|---|---|---|---|
| 12-bit | RGB 4:4:4 | 1.5 (3 bytes for 2 pixels) | Low memory usage |
| 16-bit | RGB 5:6:5 | 2 | Most common, well-balanced |
| 18-bit | RGB 6:6:6 | 3 | Highest quality |
Installation
Add this to your Cargo.toml:
[]
= "0.1.3"
Usage Examples
The examples/ directory contains runnable sample code demonstrating various features of this library.
Basic Initialization
examples/basic_initialization.rs
Demonstrates the basic initialization sequence for the display.
Example output:
Slpout command byte: 0x11
Slpout post delay: Some(120ms)
Colmod command byte: 0x3A
Colmod parameter bytes: [5]
Dispon command byte: 0x29
Dispon post delay: Some(100ms)
Basic initialization example completed successfully!
Drawing a Rectangle
Shows how to specify a rectangular area and fill it with a color.
Example output:
=== Caset (Column Address Set) ===
Command byte: 0x2A
Parameter bytes: [0, 0, 0, 9]
Post delay: None
=== Raset (Row Address Set) ===
Command byte: 0x2B
Parameter bytes: [0, 0, 0, 9]
Post delay: None
=== Ramwr (Memory Write) ===
Command byte: 0x2C
Parameter bytes count: 200 bytes
First 20 bytes: [F8, 00, F8, 00, F8, 00, F8, 00, F8, 00, F8, 00, F8, 00, F8, 00, F8, 00, F8, 00]
Post delay: None
Drawing rectangle example completed successfully!
Using Custom Colors
Demonstrates how to use predefined colors and create custom colors.
Example output:
=== Predefined Colors ===
RED: R=31, G=0, B=0
GREEN: R=0, G=63, B=0
BLUE: R=0, G=0, B=31
WHITE: R=31, G=63, B=31
BLACK: R=0, G=0, B=0
=== Custom Color ===
CUSTOM: R=20, G=40, B=15
Custom colors example completed successfully!
Different Color Formats
examples/different_color_formats.rs
Shows the differences between 12-bit, 16-bit, and 18-bit color formats.
Example output:
=== 12-bit Color Format (RGB 4:4:4) ===
RED: R=15, G=0, B=0 (max: 15)
GREEN: R=0, G=15, B=0 (max: 15)
BLUE: R=0, G=0, B=15 (max: 15)
=== 16-bit Color Format (RGB 5:6:5) ===
RED: R=31, G=0, B=0 (R,B max: 31, G max: 63)
GREEN: R=0, G=63, B=0 (R,B max: 31, G max: 63)
BLUE: R=0, G=0, B=31 (R,B max: 31, G max: 63)
=== 18-bit Color Format (RGB 6:6:6) ===
RED: R=63, G=0, B=0 (max: 63)
GREEN: R=0, G=63, B=0 (max: 63)
BLUE: R=0, G=0, B=63 (max: 63)
Different color formats example completed successfully!
Drawing with Functions
examples/draw_rect_function.rs
Demonstrates how to use draw_rect with a function to create dynamic pixel patterns based on coordinates.
Example output:
=== draw_rect Function Example ===
1. Gradient Pattern (2x2):
Generated 8 bytes
Bytes: [00, 00, 08, 41, 08, 41, 10, 82]
2. Checkerboard Pattern (4x4):
Generated 32 bytes for 16 pixels
3. Horizontal Gradient (8x1):
Generated 16 bytes
4. Circular Pattern (10x10):
Generated 200 bytes for 100 pixels
=== Key Benefits ===
✓ No memory allocation for pixel data
✓ Pixels computed on-demand as bytes are consumed
✓ Efficient for large displays or complex patterns
✓ Function composition enables flexible pixel generation
Architecture
Type Safety
This library leverages Rust's type system to guarantee color format correctness at compile time:
// Types are determined at compile time
let pixel16 = RED;
let pixel18 = RED;
// Cannot mix different types (compile error)
// let mixed = if condition { pixel16 } else { pixel18 };
Zero-Cost Abstractions
By using PhantomData, type information exists only at compile time with no runtime memory overhead.
Efficient Memory Usage
Both fill_rect() and draw_rect() generate pixel data using iterators without allocating large buffers:
fill_rect(): Fills a rectangular area with a single colordraw_rect(): Generates pixels dynamically using a function that takes (x, y) coordinates
This approach is particularly efficient for large displays or complex patterns.
Hardware Connection
ST7735 displays are typically connected via SPI interface:
| Pin | Description |
|---|---|
| VCC | Power supply (3.3V or 5V) |
| GND | Ground |
| SCL | SPI clock |
| SDA | SPI data (MOSI) |
| RES | Reset |
| DC(A0) | Data/Command select |
| CS | Chip select |
| BL | Backlight (optional) |
Display Control Commands
Memory Access Control (MADCTL)
The Madctl command controls the display orientation and color order:
use ;
// Portrait mode (0° rotation)
let madctl = Madctl ;
// Landscape mode (90° rotation)
let madctl = Madctl ;
Available rotation configurations:
- 0°: Portrait mode (default)
- 90°: Landscape mode (clockwise)
- 180°: Portrait mode (upside down)
- 270°: Landscape mode (counter-clockwise)
SPI Communication Pattern
The typical pattern for sending commands is:
- Set CS pin LOW.
- Set DC pin LOW (command mode)
- Send command byte via SPI
- Set DC pin HIGH (data mode)
- Send parameter bytes via SPI
- Set CS pin HIGH.
- Wait for required delay (if any)
Example pseudo-code:
// Send command
cs.set_low;
dc.set_low;
spi.write.unwrap;
cs.set_high;
// Send parameters
cs.set_low;
dc.set_high;
for byte in command.parm_bytes
cs.set_high;
// Wait if needed
delay;
Testing
Run the test suite:
The library includes comprehensive tests for:
- Command byte generation
- Parameter byte generation
- Color format conversions
- Range handling
- Pixel data generation
License
See LICENSE file for details.
Contributing
Contributions are welcome! Before submitting a pull request, please ensure:
- Code is formatted (
cargo fmt) - All tests pass (
cargo test) - New features include tests
References
Author
Shisei Hanai ruimo.uno@gmail.com