Skip to content

Commit 2b81a39

Browse files
authored
Merge pull request #153 from Quicr/mipidsi
Use mipidsi
2 parents fc035f6 + 6768d20 commit 2b81a39

File tree

3 files changed

+73
-201
lines changed

3 files changed

+73
-201
lines changed

ui-stm32/Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,26 @@ defmt = "1.0.1"
1919
defmt-rtt = "1.0.0"
2020

2121
embassy-executor = { version = "0.8.0", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
22-
embassy-futures = { version = "0.1.1", features = ["defmt"] }
2322
embassy-stm32 = { version = "0.3.0", features = ["defmt", "stm32f405rg", "memory-x", "time-driver-tim1", "exti", "chrono"] }
2423
embassy-time = { version = "0.5.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
2524
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
2625
embassy-sync = { version = "0.7.1", features = ["defmt"] }
27-
num_enum = { version = "0.7.4", default-features = false }
28-
hex = { version = "0.4.3", default-features = false }
2926
heapless = { version = "0.9.1", features = ["defmt"] }
3027
embedded-io-async = "0.6.1"
3128
embedded-io = { version = "0.6.1", default-features = false }
32-
ili9341 = "0.6.0"
33-
display-interface = "0.5.0"
34-
embedded-graphics-core = { version = "0.4.0", default-features = false }
35-
bitmap-font = "0.3.0"
3629
embedded-graphics = "0.8.1"
3730
embedded-hal = { version = "1.0.0", default-features = false }
31+
mipidsi = "0.9.0"
32+
embassy-embedded-hal = "0.5.0"
33+
static_cell = "2.1.1"
3834

3935
[profile.release]
4036
debug = 2
4137

4238
[profile.dev]
4339
debug = 2
4440
opt-level = "s"
41+
42+
# Tell `cargo machete` that these packages are needed
43+
[package.metadata.cargo-machete]
44+
ignored = ["cortex-m-rt"]

ui-stm32/src/board/ev12.rs

Lines changed: 33 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,44 @@
11
use super::{Button, Eeprom, Keyboard, NetTx, StatusLed};
2-
use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
2+
use core::cell::RefCell;
3+
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
34
use embassy_stm32::{
45
bind_interrupts,
56
exti::ExtiInput,
67
gpio::{Input, Level, Output, Pull, Speed},
78
i2c::{mode::Master, I2c},
89
mode::{Async, Blocking},
910
peripherals,
10-
spi::{Spi, Word},
11+
spi::Spi,
1112
usart::{self, UartRx, UartTx},
1213
};
14+
use embassy_sync::blocking_mutex::{raw::NoopRawMutex, NoopMutex};
1315
use embassy_time::Delay;
1416
use embedded_graphics::{pixelcolor::Rgb565, prelude::*};
15-
use ili9341::{Ili9341, Orientation};
17+
use mipidsi::{
18+
interface::SpiInterface,
19+
models::ILI9341Rgb565,
20+
options::{ColorOrder, Orientation},
21+
Builder, Display,
22+
};
23+
use static_cell::StaticCell;
1624
use ui_app::{Led, Outputs};
1725

18-
struct DisplayData {
19-
// These fields are not used, but we need to keep them alive so that the chip select output is
20-
// held low and the backlight output is held high.
21-
_chip_select: Output<'static>,
22-
_backlight: Output<'static>,
23-
24-
data_command: Output<'static>,
25-
spi: Spi<'static, Blocking>,
26-
}
27-
28-
impl DisplayData {
29-
fn new(
30-
mut backlight: Output<'static>,
31-
mut chip_select: Output<'static>,
32-
data_command: Output<'static>,
33-
spi: Spi<'static, Blocking>,
34-
) -> Self {
35-
backlight.set_high();
36-
chip_select.set_low();
37-
38-
Self {
39-
_backlight: backlight,
40-
_chip_select: chip_select,
41-
data_command,
42-
spi,
43-
}
44-
}
45-
46-
fn write(&mut self, data: DataFormat<'_>) -> Result<(), DisplayError> {
47-
use DataFormat::*;
48-
match data {
49-
U8(slice) => self.write_slice(slice),
50-
U16(slice) => self.write_slice(slice),
51-
U16BE(slice) => self.write_slice(slice),
52-
U16LE(slice) => self.write_slice(slice),
53-
U8Iter(iter) => self.write_iter(iter),
54-
U16BEIter(iter) => self.write_iter(iter),
55-
U16LEIter(iter) => self.write_iter(iter),
56-
_ => unreachable!(),
57-
}
58-
}
59-
60-
fn write_slice<W: Word>(&mut self, data: &[W]) -> Result<(), DisplayError> {
61-
self.spi.blocking_write(data).unwrap();
62-
Ok(())
63-
}
64-
65-
fn write_iter<W: Word>(
66-
&mut self,
67-
iter: &mut dyn Iterator<Item = W>,
68-
) -> Result<(), DisplayError> {
69-
// 1kb of render buffer
70-
const CHUNK_SIZE: usize = 512;
71-
72-
// XXX(RLB) Very C-style iteration, could probably write this in a way that would optimize
73-
// better.
74-
let mut data = [W::default(); CHUNK_SIZE];
75-
let mut n = 0;
76-
for (i, x) in iter.enumerate() {
77-
data[i % CHUNK_SIZE] = x;
78-
n += 1;
79-
80-
if n > 0 && n % CHUNK_SIZE == 0 {
81-
self.spi.blocking_write(&data).unwrap();
82-
n = 0;
83-
}
84-
}
85-
86-
self.spi.blocking_write(&data[..n]).unwrap();
87-
Ok(())
88-
}
89-
}
90-
91-
impl WriteOnlyDataCommand for DisplayData {
92-
fn send_commands(&mut self, cmd: DataFormat<'_>) -> Result<(), DisplayError> {
93-
self.data_command.set_low();
94-
self.write(cmd)
95-
}
96-
97-
fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> {
98-
self.data_command.set_high();
99-
self.write(buf)
100-
}
101-
}
26+
type DisplaySpiDevice = SpiDevice<'static, NoopRawMutex, Spi<'static, Blocking>, Output<'static>>;
27+
type DisplaySpiInterface = SpiInterface<'static, DisplaySpiDevice, Output<'static>>;
10228

10329
pub struct Board {
10430
status_led: StatusLed,
105-
screen: Ili9341<DisplayData, Output<'static>>,
31+
screen: Display<DisplaySpiInterface, ILI9341Rgb565, Output<'static>>,
10632
net_tx: NetTx<UartTx<'static, Async>>,
10733
i2c: I2c<'static, Blocking, Master>,
10834
pub button_a: Option<Button>,
10935
pub button_b: Option<Button>,
11036
pub keyboard: Option<Keyboard>,
11137
pub net_rx: Option<UartRx<'static, Async>>,
38+
39+
// This field isn't used, but is held to keep the pin low instead of floating
40+
#[allow(dead_code)]
41+
backlight: Output<'static>,
11242
}
11343

11444
bind_interrupts!(struct Irqs {
@@ -179,6 +109,9 @@ impl Board {
179109
let keyboard = Keyboard::new(cols, rows);
180110

181111
// Screen
112+
static SPI_BUS: StaticCell<NoopMutex<RefCell<Spi<'static, Blocking>>>> = StaticCell::new();
113+
let display_buffer = cortex_m::singleton!(: [u8; 512] = [0; 512]).unwrap();
114+
182115
let chip_select = Output::new(p.PB8, Level::Low, Speed::Low);
183116
let data_command = Output::new(p.PB9, Level::Low, Speed::Low);
184117
let reset = Output::new(p.PC13, Level::Low, Speed::Low);
@@ -193,15 +126,17 @@ impl Board {
193126
config
194127
};
195128
let spi = Spi::new_blocking_txonly(p.SPI1, p.PA5, p.PA7, config);
196-
197-
let screen = Ili9341::new(
198-
DisplayData::new(backlight, chip_select, data_command, spi),
199-
reset,
200-
&mut Delay,
201-
Orientation::Portrait,
202-
ili9341::DisplaySize240x320,
203-
)
204-
.unwrap();
129+
let spi_bus = NoopMutex::new(RefCell::new(spi));
130+
let spi_bus = SPI_BUS.init(spi_bus);
131+
let spi_dev = SpiDevice::new(spi_bus, chip_select);
132+
let spi_if = SpiInterface::new(spi_dev, data_command, display_buffer);
133+
134+
let screen = Builder::new(ILI9341Rgb565, spi_if)
135+
.reset_pin(reset)
136+
.orientation(Orientation::new().flip_horizontal())
137+
.color_order(ColorOrder::Bgr)
138+
.init(&mut Delay)
139+
.unwrap();
205140

206141
// NET UART
207142
let net_uart = {
@@ -230,6 +165,7 @@ impl Board {
230165
button_b: Some(button_b),
231166
keyboard: Some(keyboard),
232167
net_rx: Some(net_rx),
168+
backlight,
233169
}
234170
}
235171
}

ui-stm32/src/board/ev13.rs

Lines changed: 33 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,44 @@
11
use super::{Button, Eeprom, Keyboard, NetTx, StatusLed};
2-
use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand};
2+
use core::cell::RefCell;
3+
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
34
use embassy_stm32::{
45
bind_interrupts,
56
exti::ExtiInput,
67
gpio::{Input, Level, Output, Pull, Speed},
78
i2c::{mode::Master, I2c},
89
mode::{Async, Blocking},
910
peripherals,
10-
spi::{Spi, Word},
11+
spi::Spi,
1112
usart::{self, UartRx, UartTx},
1213
};
14+
use embassy_sync::blocking_mutex::{raw::NoopRawMutex, NoopMutex};
1315
use embassy_time::Delay;
1416
use embedded_graphics::{pixelcolor::Rgb565, prelude::*};
15-
use ili9341::{Ili9341, Orientation};
17+
use mipidsi::{
18+
interface::SpiInterface,
19+
models::ILI9341Rgb565,
20+
options::{ColorOrder, Orientation},
21+
Builder, Display,
22+
};
23+
use static_cell::StaticCell;
1624
use ui_app::{Led, Outputs};
1725

18-
struct DisplayData {
19-
// These fields are not used, but we need to keep them alive so that the chip select output is
20-
// held low and the backlight output is held high.
21-
_chip_select: Output<'static>,
22-
_backlight: Output<'static>,
23-
24-
data_command: Output<'static>,
25-
spi: Spi<'static, Blocking>,
26-
}
27-
28-
impl DisplayData {
29-
fn new(
30-
mut backlight: Output<'static>,
31-
mut chip_select: Output<'static>,
32-
data_command: Output<'static>,
33-
spi: Spi<'static, Blocking>,
34-
) -> Self {
35-
backlight.set_high();
36-
chip_select.set_low();
37-
38-
Self {
39-
_backlight: backlight,
40-
_chip_select: chip_select,
41-
data_command,
42-
spi,
43-
}
44-
}
45-
46-
fn write(&mut self, data: DataFormat<'_>) -> Result<(), DisplayError> {
47-
use DataFormat::*;
48-
match data {
49-
U8(slice) => self.write_slice(slice),
50-
U16(slice) => self.write_slice(slice),
51-
U16BE(slice) => self.write_slice(slice),
52-
U16LE(slice) => self.write_slice(slice),
53-
U8Iter(iter) => self.write_iter(iter),
54-
U16BEIter(iter) => self.write_iter(iter),
55-
U16LEIter(iter) => self.write_iter(iter),
56-
_ => unreachable!(),
57-
}
58-
}
59-
60-
fn write_slice<W: Word>(&mut self, data: &[W]) -> Result<(), DisplayError> {
61-
self.spi.blocking_write(data).unwrap();
62-
Ok(())
63-
}
64-
65-
fn write_iter<W: Word>(
66-
&mut self,
67-
iter: &mut dyn Iterator<Item = W>,
68-
) -> Result<(), DisplayError> {
69-
// 1kb of render buffer
70-
const CHUNK_SIZE: usize = 512;
71-
72-
// XXX(RLB) Very C-style iteration, could probably write this in a way that would optimize
73-
// better.
74-
let mut data = [W::default(); CHUNK_SIZE];
75-
let mut n = 0;
76-
for (i, x) in iter.enumerate() {
77-
data[i % CHUNK_SIZE] = x;
78-
n += 1;
79-
80-
if n > 0 && n % CHUNK_SIZE == 0 {
81-
self.spi.blocking_write(&data).unwrap();
82-
n = 0;
83-
}
84-
}
85-
86-
self.spi.blocking_write(&data[..n]).unwrap();
87-
Ok(())
88-
}
89-
}
90-
91-
impl WriteOnlyDataCommand for DisplayData {
92-
fn send_commands(&mut self, cmd: DataFormat<'_>) -> Result<(), DisplayError> {
93-
self.data_command.set_low();
94-
self.write(cmd)
95-
}
96-
97-
fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> {
98-
self.data_command.set_high();
99-
self.write(buf)
100-
}
101-
}
26+
type DisplaySpiDevice = SpiDevice<'static, NoopRawMutex, Spi<'static, Blocking>, Output<'static>>;
27+
type DisplaySpiInterface = SpiInterface<'static, DisplaySpiDevice, Output<'static>>;
10228

10329
pub struct Board {
10430
status_led: StatusLed,
105-
screen: Ili9341<DisplayData, Output<'static>>,
31+
screen: Display<DisplaySpiInterface, ILI9341Rgb565, Output<'static>>,
10632
net_tx: NetTx<UartTx<'static, Async>>,
10733
i2c: I2c<'static, Blocking, Master>,
10834
pub button_a: Option<Button>,
10935
pub button_b: Option<Button>,
11036
pub keyboard: Option<Keyboard>,
11137
pub net_rx: Option<UartRx<'static, Async>>,
38+
39+
// This field isn't used, but is held to keep the pin low instead of floating
40+
#[allow(dead_code)]
41+
backlight: Output<'static>,
11242
}
11343

11444
bind_interrupts!(struct Irqs {
@@ -179,6 +109,9 @@ impl Board {
179109
let keyboard = Keyboard::new(cols, rows);
180110

181111
// Screen
112+
static SPI_BUS: StaticCell<NoopMutex<RefCell<Spi<'static, Blocking>>>> = StaticCell::new();
113+
let display_buffer = cortex_m::singleton!(: [u8; 512] = [0; 512]).unwrap();
114+
182115
let chip_select = Output::new(p.PB8, Level::Low, Speed::Low);
183116
let data_command = Output::new(p.PB9, Level::Low, Speed::Low);
184117
let reset = Output::new(p.PC13, Level::Low, Speed::Low);
@@ -193,15 +126,17 @@ impl Board {
193126
config
194127
};
195128
let spi = Spi::new_blocking_txonly(p.SPI1, p.PA5, p.PA7, config);
196-
197-
let screen = Ili9341::new(
198-
DisplayData::new(backlight, chip_select, data_command, spi),
199-
reset,
200-
&mut Delay,
201-
Orientation::Portrait,
202-
ili9341::DisplaySize240x320,
203-
)
204-
.unwrap();
129+
let spi_bus = NoopMutex::new(RefCell::new(spi));
130+
let spi_bus = SPI_BUS.init(spi_bus);
131+
let spi_dev = SpiDevice::new(spi_bus, chip_select);
132+
let spi_if = SpiInterface::new(spi_dev, data_command, display_buffer);
133+
134+
let screen = Builder::new(ILI9341Rgb565, spi_if)
135+
.reset_pin(reset)
136+
.orientation(Orientation::new().flip_horizontal())
137+
.color_order(ColorOrder::Bgr)
138+
.init(&mut Delay)
139+
.unwrap();
205140

206141
// NET UART
207142
let net_uart = {
@@ -230,6 +165,7 @@ impl Board {
230165
button_b: Some(button_b),
231166
keyboard: Some(keyboard),
232167
net_rx: Some(net_rx),
168+
backlight,
233169
}
234170
}
235171
}

0 commit comments

Comments
 (0)