+138
src/badge_display/mod.rs
+138
src/badge_display/mod.rs
···
1
+
pub mod display_image;
2
+
3
+
use core::sync::atomic::{AtomicBool, AtomicU32, AtomicU8};
4
+
use display_image::get_current_image;
5
+
use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice;
6
+
use embassy_rp::gpio;
7
+
use embassy_rp::gpio::Input;
8
+
use embassy_time::{Delay, Duration, Timer};
9
+
use embedded_graphics::{
10
+
image::Image,
11
+
mono_font::{ascii::*, MonoTextStyle},
12
+
pixelcolor::BinaryColor,
13
+
prelude::*,
14
+
primitives::{PrimitiveStyle, Rectangle},
15
+
};
16
+
use embedded_text::{
17
+
alignment::HorizontalAlignment,
18
+
style::{HeightMode, TextBoxStyleBuilder},
19
+
TextBox,
20
+
};
21
+
use gpio::Output;
22
+
use heapless::String;
23
+
use tinybmp::Bmp;
24
+
use uc8151::asynch::Uc8151;
25
+
use uc8151::LUT;
26
+
use uc8151::WIDTH;
27
+
use {defmt_rtt as _, panic_probe as _};
28
+
29
+
use crate::Spi0Bus;
30
+
31
+
pub static CURRENT_IMAGE: AtomicU8 = AtomicU8::new(0);
32
+
pub static CHANGE_IMAGE: AtomicBool = AtomicBool::new(true);
33
+
34
+
static WIFI_COUNT: AtomicU32 = AtomicU32::new(0);
35
+
36
+
#[embassy_executor::task]
37
+
pub async fn run_the_display(
38
+
spi_bus: &'static Spi0Bus,
39
+
cs: Output<'static>,
40
+
dc: Output<'static>,
41
+
busy: Input<'static>,
42
+
reset: Output<'static>,
43
+
) {
44
+
let spi_dev = SpiDevice::new(&spi_bus, cs);
45
+
46
+
let mut display = Uc8151::new(spi_dev, dc, busy, reset, Delay);
47
+
48
+
display.reset().await;
49
+
50
+
// Initialise display. Using the default LUT speed setting
51
+
let _ = display.setup(LUT::Fast).await;
52
+
53
+
// Note we're setting the Text color to `Off`. The driver is set up to treat Off as Black so that BMPs work as expected.
54
+
let character_style = MonoTextStyle::new(&FONT_9X18_BOLD, BinaryColor::Off);
55
+
let textbox_style = TextBoxStyleBuilder::new()
56
+
.height_mode(HeightMode::FitToText)
57
+
.alignment(HorizontalAlignment::Left)
58
+
.paragraph_spacing(6)
59
+
.build();
60
+
61
+
// Bounding box for our text. Fill it with the opposite color so we can read the text.
62
+
let name_and_detail_bounds = Rectangle::new(Point::new(0, 40), Size::new(WIDTH - 75, 0));
63
+
name_and_detail_bounds
64
+
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
65
+
.draw(&mut display)
66
+
.unwrap();
67
+
68
+
// Create the text box and apply styling options.
69
+
70
+
let text = "Bailey Townsend\nSoftware Dev";
71
+
// \nWritten in rust\nRunning on a pico w";
72
+
let name_and_detail_box =
73
+
TextBox::with_textbox_style(text, name_and_detail_bounds, character_style, textbox_style);
74
+
75
+
// Draw the text box.
76
+
name_and_detail_box.draw(&mut display).unwrap();
77
+
78
+
let _ = display.update().await;
79
+
80
+
let delay: Duration = Duration::from_secs(30);
81
+
let mut text: String<16> = String::<16>::new();
82
+
83
+
loop {
84
+
let count = WIFI_COUNT.load(core::sync::atomic::Ordering::Relaxed);
85
+
// let _ = core::fmt::write(&mut text, format_args!("Count: {}", count));
86
+
// let count_bounds = Rectangle::new(Point::new(0, 0), Size::new(WIDTH, 24));
87
+
// count_bounds
88
+
// .into_styled(
89
+
// PrimitiveStyleBuilder::default()
90
+
// .stroke_color(BinaryColor::Off)
91
+
// .fill_color(BinaryColor::On)
92
+
// .stroke_width(1)
93
+
// .build(),
94
+
// )
95
+
// .draw(&mut display)
96
+
// .unwrap();
97
+
98
+
// Text::new(text.as_str(), Point::new(8, 16), character_style)
99
+
// .draw(&mut display)
100
+
// .unwrap();
101
+
102
+
// // // Draw the text box.
103
+
// let result = display
104
+
// .partial_update(count_bounds.try_into().unwrap())
105
+
// .await;
106
+
// match result {
107
+
// Ok(_) => {}
108
+
// Err(_) => {
109
+
// info!("Error updating display");
110
+
// }
111
+
// }
112
+
// text.clear();
113
+
// let _ = display.clear(Rgb565::WHITE.into());
114
+
// let _ = display.update().await;
115
+
WIFI_COUNT.store(count + 1, core::sync::atomic::Ordering::Relaxed);
116
+
117
+
if CHANGE_IMAGE.load(core::sync::atomic::Ordering::Relaxed) {
118
+
let current_image = get_current_image();
119
+
let tga: Bmp<BinaryColor> = Bmp::from_slice(¤t_image.image()).unwrap();
120
+
let image = Image::new(&tga, current_image.image_location());
121
+
//clear image location by writing a white rectangle over previous image location
122
+
let clear_bounds = Rectangle::new(
123
+
current_image.previous().image_location(),
124
+
Size::new(157, 101),
125
+
);
126
+
clear_bounds
127
+
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
128
+
.draw(&mut display)
129
+
.unwrap();
130
+
131
+
let _ = image.draw(&mut display);
132
+
let _ = display.update().await;
133
+
CHANGE_IMAGE.store(false, core::sync::atomic::Ordering::Relaxed);
134
+
}
135
+
136
+
Timer::after(Duration::from_millis(500)).await;
137
+
}
138
+
}
+3
-4
src/image_handler.rs
src/badge_display/display_image.rs
+3
-4
src/image_handler.rs
src/badge_display/display_image.rs
···
2
2
3
3
use embedded_graphics::prelude::Point;
4
4
5
-
pub static CURRENT_IMAGE: AtomicU8 = AtomicU8::new(0);
6
-
pub static CHANGE_IMAGE: AtomicBool = AtomicBool::new(true);
5
+
use super::CURRENT_IMAGE;
7
6
8
7
static NUMBER_OF_IMAGES: u8 = 2;
9
-
static FERRIS_IMG: &[u8; 15722] = include_bytes!("../images/ferris_w_a_knife.bmp");
10
-
static REPO_IMG: &[u8; 11262] = include_bytes!("../images/repo.bmp");
8
+
static FERRIS_IMG: &[u8; 15722] = include_bytes!("../../images/ferris_w_a_knife.bmp");
9
+
static REPO_IMG: &[u8; 11262] = include_bytes!("../../images/repo.bmp");
11
10
12
11
pub enum DisplayImage {
13
12
Ferris = 0,
+3
-115
src/main.rs
+3
-115
src/main.rs
···
4
4
5
5
#![no_std]
6
6
#![no_main]
7
-
use core::sync::atomic::AtomicU32;
7
+
use badge_display::display_image::DisplayImage;
8
+
use badge_display::{run_the_display, CHANGE_IMAGE, CURRENT_IMAGE};
8
9
use defmt::info;
9
-
use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice;
10
10
use embassy_executor::Spawner;
11
11
use embassy_rp::gpio;
12
12
use embassy_rp::gpio::Input;
···
29
29
TextBox,
30
30
};
31
31
use gpio::{Level, Output, Pull};
32
-
use heapless::String;
33
-
use image_handler::{get_current_image, DisplayImage, CHANGE_IMAGE, CURRENT_IMAGE};
34
32
use static_cell::StaticCell;
35
-
use tinybmp::Bmp;
36
-
use uc8151::asynch::Uc8151;
37
-
use uc8151::LUT;
38
-
use uc8151::WIDTH;
39
33
use {defmt_rtt as _, panic_probe as _};
40
34
35
+
mod badge_display;
41
36
mod cyw43_driver;
42
-
mod image_handler;
43
37
44
38
type Spi0Bus = Mutex<NoopRawMutex, Spi<'static, SPI0, spi::Async>>;
45
-
46
-
static WIFI_COUNT: AtomicU32 = AtomicU32::new(0);
47
39
48
40
#[embassy_executor::main]
49
41
async fn main(spawner: Spawner) {
···
111
103
Timer::after(Duration::from_millis(100)).await;
112
104
}
113
105
}
114
-
115
-
#[embassy_executor::task]
116
-
async fn run_the_display(
117
-
spi_bus: &'static Spi0Bus,
118
-
cs: Output<'static>,
119
-
dc: Output<'static>,
120
-
busy: Input<'static>,
121
-
reset: Output<'static>,
122
-
) {
123
-
let spi_dev = SpiDevice::new(&spi_bus, cs);
124
-
125
-
let mut display = Uc8151::new(spi_dev, dc, busy, reset, Delay);
126
-
127
-
display.reset().await;
128
-
129
-
// Initialise display. Using the default LUT speed setting
130
-
let _ = display.setup(LUT::Fast).await;
131
-
132
-
// Note we're setting the Text color to `Off`. The driver is set up to treat Off as Black so that BMPs work as expected.
133
-
let character_style = MonoTextStyle::new(&FONT_9X18_BOLD, BinaryColor::Off);
134
-
let textbox_style = TextBoxStyleBuilder::new()
135
-
.height_mode(HeightMode::FitToText)
136
-
.alignment(HorizontalAlignment::Left)
137
-
.paragraph_spacing(6)
138
-
.build();
139
-
140
-
// Bounding box for our text. Fill it with the opposite color so we can read the text.
141
-
let name_and_detail_bounds = Rectangle::new(Point::new(0, 40), Size::new(WIDTH - 75, 0));
142
-
name_and_detail_bounds
143
-
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
144
-
.draw(&mut display)
145
-
.unwrap();
146
-
147
-
// Create the text box and apply styling options.
148
-
149
-
let text = "Bailey Townsend\nSoftware Dev";
150
-
// \nWritten in rust\nRunning on a pico w";
151
-
let name_and_detail_box =
152
-
TextBox::with_textbox_style(text, name_and_detail_bounds, character_style, textbox_style);
153
-
154
-
// Draw the text box.
155
-
name_and_detail_box.draw(&mut display).unwrap();
156
-
157
-
let _ = display.update().await;
158
-
159
-
let delay: Duration = Duration::from_secs(30);
160
-
let mut text: String<16> = String::<16>::new();
161
-
162
-
loop {
163
-
let count = WIFI_COUNT.load(core::sync::atomic::Ordering::Relaxed);
164
-
// let _ = core::fmt::write(&mut text, format_args!("Count: {}", count));
165
-
// let count_bounds = Rectangle::new(Point::new(0, 0), Size::new(WIDTH, 24));
166
-
// count_bounds
167
-
// .into_styled(
168
-
// PrimitiveStyleBuilder::default()
169
-
// .stroke_color(BinaryColor::Off)
170
-
// .fill_color(BinaryColor::On)
171
-
// .stroke_width(1)
172
-
// .build(),
173
-
// )
174
-
// .draw(&mut display)
175
-
// .unwrap();
176
-
177
-
// Text::new(text.as_str(), Point::new(8, 16), character_style)
178
-
// .draw(&mut display)
179
-
// .unwrap();
180
-
181
-
// // // Draw the text box.
182
-
// let result = display
183
-
// .partial_update(count_bounds.try_into().unwrap())
184
-
// .await;
185
-
// match result {
186
-
// Ok(_) => {}
187
-
// Err(_) => {
188
-
// info!("Error updating display");
189
-
// }
190
-
// }
191
-
// text.clear();
192
-
// let _ = display.clear(Rgb565::WHITE.into());
193
-
// let _ = display.update().await;
194
-
WIFI_COUNT.store(count + 1, core::sync::atomic::Ordering::Relaxed);
195
-
196
-
if CHANGE_IMAGE.load(core::sync::atomic::Ordering::Relaxed) {
197
-
let current_image = get_current_image();
198
-
let tga: Bmp<BinaryColor> = Bmp::from_slice(¤t_image.image()).unwrap();
199
-
let image = Image::new(&tga, current_image.image_location());
200
-
//clear image location by writing a white rectangle over previous image location
201
-
let clear_bounds = Rectangle::new(
202
-
current_image.previous().image_location(),
203
-
Size::new(157, 91),
204
-
);
205
-
clear_bounds
206
-
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
207
-
.draw(&mut display)
208
-
.unwrap();
209
-
210
-
let _ = image.draw(&mut display);
211
-
let _ = display.update().await;
212
-
CHANGE_IMAGE.store(false, core::sync::atomic::Ordering::Relaxed);
213
-
}
214
-
215
-
Timer::after(Duration::from_millis(500)).await;
216
-
}
217
-
}