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