alpha
Login
or
Join now
arthomnix.dev
/
eepy
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
initial embedded-graphics support
author
arthomnix
date
1 year ago
(Jan 9, 2025, 9:00 PM UTC)
commit
f51b485e
f51b485eb08150d2a364a7f7b995e4e4e226204f
parent
6038940c
6038940c30b16d694622ad30309ffef1c1c061c0
+125
-91
6 changed files
Expand all
Collapse all
Unified
Split
Cargo.toml
fw16-epd-main
Cargo.toml
src
main.rs
fw16-epd-program-interface
Cargo.toml
src
eg.rs
lib.rs
+2
-1
Cargo.toml
Reviewed
···
22
22
mcp9808 = "0.4"
23
23
usb-device = "0.3"
24
24
usbd-serial = "0.2"
25
25
-
crc32fast = { version = "1.4", default-features = false }
25
25
+
crc32fast = { version = "1.4", default-features = false }
26
26
+
embedded-graphics = { version = "0.8.1", features = ["defmt"] }
+3
-2
fw16-epd-main/Cargo.toml
Reviewed
···
5
5
6
6
[dependencies]
7
7
fw16-epd-bsp = { path = "../fw16-epd-bsp" }
8
8
-
fw16-epd-program-interface = { path = "../fw16-epd-program-interface" }
8
8
+
fw16-epd-program-interface = { path = "../fw16-epd-program-interface", features = ["embedded-graphics"] }
9
9
tp370pgh01 = { path = "../tp370pgh01", features = ["rp2040"] }
10
10
cortex-m.workspace = true
11
11
cortex-m-rt.workspace = true
···
19
19
mcp9808.workspace = true
20
20
usb-device.workspace = true
21
21
usbd-serial.workspace = true
22
22
-
crc32fast.workspace = true
22
22
+
crc32fast.workspace = true
23
23
+
embedded-graphics.workspace = true
+40
-86
fw16-epd-main/src/main.rs
Reviewed
···
11
11
use core::cell::{RefCell, RefMut};
12
12
use critical_section::Mutex;
13
13
use defmt::{debug, error, info, trace};
14
14
+
use embedded_graphics::pixelcolor::BinaryColor;
15
15
+
use embedded_graphics::prelude::*;
16
16
+
use embedded_graphics::primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder};
14
17
use embedded_hal::digital::PinState;
15
18
use embedded_hal::i2c::I2c;
16
19
use embedded_hal_bus::i2c::RefCellDevice;
···
30
33
use fw16_epd_bsp::hal::multicore::{Multicore, Stack};
31
34
use fw16_epd_bsp::pac::I2C0;
32
35
use fw16_epd_bsp::pac::interrupt;
36
36
+
use fw16_epd_program_interface::eg::EpdDrawTarget;
37
37
+
use fw16_epd_program_interface::ProgramFunctionTable;
33
38
use tp370pgh01::rp2040::{Rp2040PervasiveSpiDelays, IoPin};
34
34
-
use tp370pgh01::Tp370pgh01;
39
39
+
use tp370pgh01::{Tp370pgh01, IMAGE_BYTES};
35
40
use crate::programs::Programs;
36
41
37
42
static CORE1_STACK: Stack<8192> = Stack::new();
···
47
52
static mut GLOBAL_USB_DEVICE: Option<UsbDevice<hal::usb::UsbBus>> = None;
48
53
static mut GLOBAL_USB_BUS: Option<UsbBusAllocator<hal::usb::UsbBus>> = None;
49
54
static mut GLOBAL_USB_SERIAL: Option<SerialPort<hal::usb::UsbBus>> = None;
55
55
+
56
56
+
extern "C" fn write_image(image: &[u8; IMAGE_BYTES]) {
57
57
+
critical_section::with(|cs| IMAGE_BUFFER.borrow_ref_mut(cs).copy_from_slice(image));
58
58
+
}
59
59
+
60
60
+
extern "C" fn refresh() {
61
61
+
DO_REFRESH.store(true, Ordering::Relaxed);
62
62
+
FAST_REFRESH.store(false, Ordering::Relaxed);
63
63
+
cortex_m::asm::sev();
64
64
+
}
65
65
+
66
66
+
extern "C" fn refresh_fast() {
67
67
+
DO_REFRESH.store(true, Ordering::Relaxed);
68
68
+
FAST_REFRESH.store(true, Ordering::Relaxed);
69
69
+
cortex_m::asm::sev();
70
70
+
}
50
71
51
72
#[entry]
52
73
fn main() -> ! {
···
169
190
}
170
191
}
171
192
172
172
-
fn plot(data: &mut RefMut<[u8; 12480]>, x: u16, y: u16) {
173
173
-
let bit_index = (y as usize) * 240 + (x as usize);
174
174
-
let i = bit_index / 8;
175
175
-
let j = 1 << (bit_index % 8);
176
176
-
177
177
-
let val = &mut data[i];
178
178
-
*val |= j;
179
179
-
}
180
180
-
181
181
-
fn plot_line_low(data: &mut RefMut<[u8; 12480]>, x0: i16, y0: i16, x1: i16, y1: i16) {
182
182
-
let dx = x1 - x0;
183
183
-
let mut dy = y1 - y0;
184
184
-
let mut yi = 1;
185
185
-
if dy < 0 {
186
186
-
yi = -1;
187
187
-
dy = -dy;
188
188
-
}
189
189
-
let mut d = (2 * dy) - dx;
190
190
-
let mut y = y0;
191
191
-
192
192
-
for x in x0..=x1 {
193
193
-
plot(data, x as u16, y as u16);
194
194
-
if d > 0 {
195
195
-
y += yi;
196
196
-
d += 2 * (dy - dx);
197
197
-
} else {
198
198
-
d += 2 * dy;
199
199
-
}
200
200
-
}
201
201
-
}
202
202
-
203
203
-
fn plot_line_high(data: &mut RefMut<[u8; 12480]>, x0: i16, y0: i16, x1: i16, y1: i16) {
204
204
-
let mut dx = x1 - x0;
205
205
-
let dy = y1 - y0;
206
206
-
let mut xi = 1;
207
207
-
if dx < 0 {
208
208
-
xi = -1;
209
209
-
dx = -dx;
210
210
-
}
211
211
-
let mut d = (2 * dx) - dy;
212
212
-
let mut x = x0;
213
213
-
214
214
-
for y in y0..=y1 {
215
215
-
plot(data, x as u16, y as u16);
216
216
-
if d > 0 {
217
217
-
x += xi;
218
218
-
d += 2 * (dx - dy);
219
219
-
} else {
220
220
-
d += 2 * dx;
221
221
-
}
222
222
-
}
223
223
-
}
224
224
-
225
225
-
fn plot_line(data: &mut RefMut<[u8; 12480]>, x0: u16, y0: u16, x1: u16, y1: u16) {
226
226
-
if y1.abs_diff(y0) < x1.abs_diff(x0) {
227
227
-
if x0 > x1 {
228
228
-
plot_line_low(data, x1 as i16, y1 as i16, x0 as i16, y0 as i16);
229
229
-
} else {
230
230
-
plot_line_low(data, x0 as i16, y0 as i16, x1 as i16, y1 as i16);
231
231
-
}
232
232
-
} else {
233
233
-
if y0 > y1 {
234
234
-
plot_line_high(data, x1 as i16, y1 as i16, x0 as i16, y0 as i16);
235
235
-
} else {
236
236
-
plot_line_high(data, x0 as i16, y0 as i16, x1 as i16, y1 as i16);
237
237
-
}
238
238
-
}
239
239
-
}
240
240
-
241
193
#[interrupt]
242
194
fn USBCTRL_IRQ() {
243
195
static mut INDEX: usize = 0;
···
271
223
fn IO_IRQ_BANK0() {
272
224
static mut TOUCH_INT_PIN: Option<EpdTouchInt> = None;
273
225
static mut I2C: Option<I2C<I2C0, (I2CSda, I2CScl)>> = None;
274
274
-
static mut PREV_POS: (u16, u16) = (0, 0);
226
226
+
static mut PREV_POS: Point = Point::new(0, 0);
227
227
+
static mut DRAW_TARGET: EpdDrawTarget = EpdDrawTarget::new(ProgramFunctionTable {
228
228
+
write_image,
229
229
+
refresh,
230
230
+
refresh_fast,
231
231
+
});
275
232
276
233
trace!("IO_IRQ_BANK0");
277
234
···
299
256
if int.interrupt_status(EdgeLow) {
300
257
let mut buf = [0u8; 9];
301
258
i2c.write_read(0x38u8, &[0x00], &mut buf).unwrap();
302
302
-
let x = (((buf[3] & 0x0f) as u16) << 8) | buf[4] as u16;
303
303
-
let y = (((buf[5] & 0x0f) as u16) << 8) | buf[6] as u16;
259
259
+
let x = (((buf[3] & 0x0f) as i32) << 8) | buf[4] as i32;
260
260
+
let y = (((buf[5] & 0x0f) as i32) << 8) | buf[6] as i32;
261
261
+
debug!("touch event at ({}, {})", x, y);
262
262
+
let pos = Point::new(x, y);
304
263
305
264
let state = buf[3] >> 6;
306
265
307
266
if state == 1 && y > 400 {
308
308
-
critical_section::with(|cs| {
309
309
-
IMAGE_BUFFER.borrow_ref_mut(cs).copy_from_slice(&[0; (240 * 416) / 8]);
310
310
-
});
311
311
-
FAST_REFRESH.store(false, Ordering::Relaxed);
312
312
-
DO_REFRESH.store(true, Ordering::Relaxed);
267
267
+
DRAW_TARGET.clear(BinaryColor::Off).unwrap();
268
268
+
DRAW_TARGET.refresh();
313
269
} else if state == 1 && y < 20 {
314
270
hal::rom_data::reset_to_usb_boot(0, 0);
315
271
} else {
316
272
if state == 1 || state == 2 {
317
317
-
let (x0, y0) = *PREV_POS;
318
318
-
let (x1, y1) = (x, y);
319
319
-
critical_section::with(|cs| {
320
320
-
plot_line(&mut IMAGE_BUFFER.borrow_ref_mut(cs), x0, y0, x1, y1);
321
321
-
});
273
273
+
Line::new(PREV_POS.clone(), pos)
274
274
+
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 5))
275
275
+
.draw(DRAW_TARGET)
276
276
+
.unwrap();
277
277
+
DRAW_TARGET.refresh_fast();
322
278
}
323
323
-
FAST_REFRESH.store(true, Ordering::Relaxed);
324
324
-
DO_REFRESH.store(true, Ordering::Relaxed);
325
279
326
280
if state == 0 || state == 2 {
327
327
-
*PREV_POS = (x, y);
281
281
+
*PREV_POS = Point::new(x, y);
328
282
}
329
283
}
330
284
int.clear_interrupt(EdgeLow);
+2
-1
fw16-epd-program-interface/Cargo.toml
Reviewed
···
4
4
edition = "2021"
5
5
6
6
[dependencies]
7
7
-
tp370pgh01 = { path = "../tp370pgh01" }
7
7
+
tp370pgh01 = { path = "../tp370pgh01" }
8
8
+
embedded-graphics = { workspace = true, optional = true }
+71
fw16-epd-program-interface/src/eg.rs
Reviewed
···
1
1
+
use core::convert::Infallible;
2
2
+
use embedded_graphics::prelude::*;
3
3
+
use embedded_graphics::geometry::Dimensions;
4
4
+
use embedded_graphics::Pixel;
5
5
+
use embedded_graphics::pixelcolor::BinaryColor;
6
6
+
use embedded_graphics::primitives::Rectangle;
7
7
+
use tp370pgh01::{DIM_X, DIM_Y, IMAGE_BYTES};
8
8
+
use crate::ProgramFunctionTable;
9
9
+
10
10
+
pub struct EpdDrawTarget {
11
11
+
functions: ProgramFunctionTable,
12
12
+
buf: [u8; IMAGE_BYTES],
13
13
+
}
14
14
+
15
15
+
impl Dimensions for EpdDrawTarget {
16
16
+
fn bounding_box(&self) -> Rectangle {
17
17
+
Rectangle::new(Point::new(0, 0), Size::new(DIM_X as u32, DIM_Y as u32))
18
18
+
}
19
19
+
}
20
20
+
21
21
+
impl DrawTarget for EpdDrawTarget {
22
22
+
type Color = BinaryColor;
23
23
+
type Error = Infallible;
24
24
+
25
25
+
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
26
26
+
where
27
27
+
I: IntoIterator<Item = Pixel<Self::Color>>,
28
28
+
{
29
29
+
for Pixel(point @ Point { x, y }, colour) in pixels {
30
30
+
if !self.bounding_box().contains(point) {
31
31
+
continue;
32
32
+
}
33
33
+
34
34
+
let bit_index = (y as usize) * 240 + (x as usize);
35
35
+
let i = bit_index >> 3;
36
36
+
let j = 1 << (bit_index & 0x07);
37
37
+
38
38
+
match colour {
39
39
+
BinaryColor::Off => self.buf[i] &= !j,
40
40
+
BinaryColor::On => self.buf[i] |= j,
41
41
+
}
42
42
+
}
43
43
+
44
44
+
Ok(())
45
45
+
}
46
46
+
47
47
+
fn clear(&mut self, colour: Self::Color) -> Result<(), Self::Error> {
48
48
+
match colour {
49
49
+
BinaryColor::Off => self.buf.copy_from_slice(&[0; IMAGE_BYTES]),
50
50
+
BinaryColor::On => self.buf.copy_from_slice(&[u8::MAX; IMAGE_BYTES]),
51
51
+
}
52
52
+
53
53
+
Ok(())
54
54
+
}
55
55
+
}
56
56
+
57
57
+
impl EpdDrawTarget {
58
58
+
pub const fn new(functions: ProgramFunctionTable) -> Self {
59
59
+
Self { functions, buf: [0; IMAGE_BYTES] }
60
60
+
}
61
61
+
62
62
+
pub fn refresh(&self) {
63
63
+
(self.functions.write_image)(&self.buf);
64
64
+
(self.functions.refresh)();
65
65
+
}
66
66
+
67
67
+
pub fn refresh_fast(&self) {
68
68
+
(self.functions.write_image)(&self.buf);
69
69
+
(self.functions.refresh_fast)();
70
70
+
}
71
71
+
}
+7
-1
fw16-epd-program-interface/src/lib.rs
Reviewed
···
1
1
#![no_std]
2
2
3
3
+
#[cfg(feature = "embedded-graphics")]
4
4
+
pub mod eg;
5
5
+
3
6
pub use tp370pgh01::IMAGE_BYTES;
4
7
5
8
#[repr(C)]
9
9
+
#[derive(Copy, Clone)]
6
10
pub struct ProgramFunctionTable {
7
7
-
write_epd_image: extern "C" fn(&[u8; IMAGE_BYTES]),
11
11
+
pub write_image: extern "C" fn(&[u8; IMAGE_BYTES]),
12
12
+
pub refresh: extern "C" fn(),
13
13
+
pub refresh_fast: extern "C" fn(),
8
14
}