Skip to content

Commit

Permalink
Merge pull request #70 from martinschaer/spi-st7789-rpi-zero-w
Browse files Browse the repository at this point in the history
Add spi st7789 rpi zero w example
  • Loading branch information
almindor authored Aug 17, 2023
2 parents 4856fd9 + 724f413 commit 0dac848
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 0 deletions.
2 changes: 2 additions & 0 deletions mipidsi/examples/spi-st7789-rpi-zero-w/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.arm-unknown-linux-musleabihf]
linker = "arm-linux-musleabihf-gcc"
2 changes: 2 additions & 0 deletions mipidsi/examples/spi-st7789-rpi-zero-w/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
12 changes: 12 additions & 0 deletions mipidsi/examples/spi-st7789-rpi-zero-w/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "spi-st7789-rpi-zero-w"
version = "0.1.0"
edition = "2021"

[dependencies]
display-interface-spi = "0.4.1"
embedded-graphics = "0.8.0"
mipidsi = "0.7.1"
rppal = { version = "0.14.1", features = ["hal"] }

[workspace]
50 changes: 50 additions & 0 deletions mipidsi/examples/spi-st7789-rpi-zero-w/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# SPI ST7789 on a Raspberry Pi Zero W Example

This example demonstrates how to use the [Display HAT Mini by Pomoroni](https://shop.pimoroni.com/products/display-hat-mini?variant=39496084717651) on a Raspberry Pi Zero W.

The example shows a scrolling text and a pulsing RGB LED.

Buttons:

- A: change LED color
- B: exit
- X: move text up
- Y: move text down

## Pre-requisite

**Enable SPI** by any of this options:

- `sudo raspi-config`
- `sudo raspi-config nonint do_spi 0`
- manually adding `dtparam=spi=on` to /boot/config.txt
- the graphical Raspberry Pi Configuration UI

[More info about SPI](https://docs.golemparts.com/rppal/0.14.1/rppal/spi/index.html#spi0)

## Build, strip, copy, and run

### Mac OS

Pre-requisite: musl-cross (Homebrew users: `brew install FiloSottile/musl-cross/musl-cross --without-x86_64 --with-arm-hf`)

```bash
# build for rpi zero w
cargo build --release --target=arm-unknown-linux-musleabihf
# look at the size of the bin file
ls -lh target/arm-unknown-linux-musleabihf/release/spi-st7789-rpi-zero-w
# strip it
arm-linux-musleabihf-strip target/arm-unknown-linux-musleabihf/release/spi-st7789-rpi-zero-w
# look at it now ;)
ls -lh target/arm-unknown-linux-musleabihf/release/spi-st7789-rpi-zero-w
# copy over ssh
scp target/arm-unknown-linux-musleabihf/release/spi-st7789-rpi-zero-w [email protected]:~/
# ssh into the rpi to run it
ssh [email protected]
# run it
./spi-st7789-rpi-zero-w
```

### Linux

Not tested. Follow this article [Raspberry Pi Zero Raspbian/Rust Primer](https://dev.to/jeikabu/raspberry-pi-zero-raspbian-rust-primer-3aj6).
158 changes: 158 additions & 0 deletions mipidsi/examples/spi-st7789-rpi-zero-w/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
# SPI ST7789 on a Raspberry Pi Zero W Example
This example demonstrates how to use the [Display HAT Mini by Pomoroni](https://shop.pimoroni.com/products/display-hat-mini?variant=39496084717651)
on a Raspberry Pi Zero W.
The example shows a scrolling text and a pulsing RGB LED.
Buttons:
- A: change LED color
- B: exit
- X: move text up
- Y: move text down
Read the README.md for more information.
*/

use display_interface_spi::SPIInterfaceNoCS;
use embedded_graphics::{
mono_font::{ascii::FONT_10X20, MonoTextStyle},
pixelcolor::Rgb565,
prelude::*,
text::Text,
};
use mipidsi::Builder;
use rppal::gpio::{Gpio, OutputPin};
use rppal::hal::Delay;
use rppal::spi::{Bus, Mode, SlaveSelect, Spi};
use std::process::ExitCode;

// Pins

const SPI_DC: u8 = 9;
const BACKLIGHT: u8 = 13;

const BUTTON_A: u8 = 5;
const BUTTON_B: u8 = 6;
const BUTTON_X: u8 = 16;
const BUTTON_Y: u8 = 24;

const LED_R: u8 = 17;
const LED_G: u8 = 27;
const LED_B: u8 = 22;

// Display
const W: i32 = 320;
const H: i32 = 240;

fn main() -> ExitCode {
// GPIO
let gpio = Gpio::new().unwrap();
let dc = gpio.get(SPI_DC).unwrap().into_output();
let mut backlight = gpio.get(BACKLIGHT).unwrap().into_output();

// LEDs
let mut led_r = gpio.get(LED_R).unwrap().into_output();
let mut led_g = gpio.get(LED_G).unwrap().into_output();
let mut led_b = gpio.get(LED_B).unwrap().into_output();

// Buttons
let button_a = gpio.get(BUTTON_A).unwrap().into_input_pullup();
let button_b = gpio.get(BUTTON_B).unwrap().into_input_pullup();
let button_x = gpio.get(BUTTON_X).unwrap().into_input_pullup();
let button_y = gpio.get(BUTTON_Y).unwrap().into_input_pullup();

// SPI Display
let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss1, 60_000_000_u32, Mode::Mode0).unwrap();
let di = SPIInterfaceNoCS::new(spi, dc);
let mut delay = Delay::new();
let mut display = Builder::st7789(di)
// width and height are switched on purpose because of the orientation
.with_display_size(H as u16, W as u16)
// this orientation applies for the Display HAT Mini by Pimoroni
.with_orientation(mipidsi::Orientation::LandscapeInverted(true))
.with_invert_colors(mipidsi::ColorInversion::Inverted)
.init(&mut delay, None::<OutputPin>)
.unwrap();

// Text
let char_w = 10;
let char_h = 20;
let text_style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
let text = "Hello World ^_^;";
let mut text_x = W;
let mut text_y = H / 2;

// Alternating color
let colors = [Rgb565::RED, Rgb565::GREEN, Rgb565::BLUE];

// Clear the display initially
display.clear(colors[0]).unwrap();

// Turn on backlight
backlight.set_high();

// Set LEDs to PWM mode
led_r.set_pwm_frequency(50., 1.).unwrap();
led_g.set_pwm_frequency(50., 1.).unwrap();
led_b.set_pwm_frequency(50., 1.).unwrap();

let start = std::time::Instant::now();
let mut last = std::time::Instant::now();
let mut led_flags = 0b000;
let mut counter = 0;
loop {
let elapsed = last.elapsed().as_secs_f64();
if elapsed < 0.125 {
continue;
}
last = std::time::Instant::now();
counter += 1;

// X: move text up
if button_x.is_low() {
text_y -= char_h;
}
// Y: move text down
if button_y.is_low() {
text_y += char_h;
}
// A: change led color
if button_a.is_low() {
led_flags = (led_flags + 1) % 8;
}
// B: exit
if button_b.is_low() {
break;
}

// Fill the display with alternating colors every 8 frames
display.clear(colors[(counter / 8) % colors.len()]).unwrap();

// Draw text
let right = Text::new(text, Point::new(text_x, text_y), text_style)
.draw(&mut display)
.unwrap();
text_x = if right.x <= 0 { W } else { text_x - char_w };

// Led
let y = ((start.elapsed().as_secs_f64().sin() + 1.) * 50.).round() / 100.;
led_r
.set_pwm_frequency(50., if led_flags & 0b100 != 0 { y } else { 1. })
.unwrap();
led_g
.set_pwm_frequency(50., if led_flags & 0b010 != 0 { y } else { 1. })
.unwrap();
led_b
.set_pwm_frequency(50., if led_flags & 0b001 != 0 { y } else { 1. })
.unwrap();
}

// Turn off backlight and clear the display
backlight.set_low();
display.clear(Rgb565::BLACK).unwrap();

ExitCode::SUCCESS
}

0 comments on commit 0dac848

Please sign in to comment.