diff --git a/Cargo.lock b/Cargo.lock index bb828ca..d871276 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -365,7 +365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ "annotate-snippets", - "bitflags 2.8.0", + "bitflags 2.9.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -420,9 +420,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" dependencies = [ "serde 1.0.218", ] @@ -485,7 +485,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cairo-sys-rs", "glib 0.18.5", "libc", @@ -693,6 +693,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + [[package]] name = "const-oid" version = "0.9.6" @@ -1057,6 +1063,18 @@ dependencies = [ "serde 1.0.218", ] +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + [[package]] name = "embedded-dma" version = "0.2.0" @@ -1797,7 +1815,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "futures-channel", "futures-core", "futures-executor", @@ -1820,7 +1838,7 @@ version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707b819af8059ee5395a2de9f2317d87a53dbad8846a2f089f0bb44703f37686" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "futures-channel", "futures-core", "futures-executor", @@ -2819,7 +2837,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65f3a4b81b2a2d8c7f300643676202debd1b7c929dbf5c9bb89402ea11d19810" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cc", "convert_case", "cookie-factory", @@ -2870,6 +2888,12 @@ dependencies = [ "fixed", ] +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3118,7 +3142,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "libc", ] @@ -3262,7 +3286,7 @@ version = "0.10.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "cfg-if", "foreign-types", "libc", @@ -3539,7 +3563,9 @@ dependencies = [ name = "pico-st7789" version = "0.1.0" dependencies = [ + "bitflags 2.9.0", "cortex-m-rt", + "embedded-alloc", "embedded-hal 1.0.0", "fugit", "panic-halt", @@ -3607,7 +3633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08e645ba5c45109106d56610b3ee60eb13a6f2beb8b74f8dc8186cf261788dda" dependencies = [ "anyhow", - "bitflags 2.8.0", + "bitflags 2.9.0", "libc", "libspa", "libspa-sys", @@ -3804,7 +3830,7 @@ checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.8.0", + "bitflags 2.9.0", "lazy_static", "num-traits", "rand 0.8.5", @@ -4043,7 +4069,7 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -4131,6 +4157,18 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "rlsf" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "svgbobdoc", +] + [[package]] name = "rp-pico" version = "0.9.0" @@ -4262,7 +4300,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -4350,7 +4388,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation", "core-foundation-sys", "libc", @@ -4721,7 +4759,7 @@ checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.8.0", + "bitflags 2.9.0", "byteorder", "bytes", "crc", @@ -4763,7 +4801,7 @@ checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.8.0", + "bitflags 2.9.0", "byteorder", "crc", "dotenvy", @@ -4844,6 +4882,19 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64 0.9.3", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + [[package]] name = "syn" version = "1.0.109" @@ -5985,7 +6036,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] diff --git a/pico-st7789/Cargo.toml b/pico-st7789/Cargo.toml index 6d8012e..ff98242 100644 --- a/pico-st7789/Cargo.toml +++ b/pico-st7789/Cargo.toml @@ -4,7 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] +bitflags = "2.9.0" cortex-m-rt = "0.7.3" +embedded-alloc = "0.6.0" embedded-hal = "1.0.0" fugit = "0.3.7" panic-halt = "1.0.0" diff --git a/pico-st7789/src/canvas.rs b/pico-st7789/src/canvas.rs new file mode 100644 index 0000000..cb2d05b --- /dev/null +++ b/pico-st7789/src/canvas.rs @@ -0,0 +1,125 @@ +// a a a +// f b +// f b +// f b +// g g g +// e c +// e c +// e c +// d d d + +use alloc::collections::btree_map::BTreeMap; + +/* +*/ + +pub struct RGB { pub r: u8, pub g: u8, pub b: u8 } + +pub trait Canvas { + fn set_pixel(&mut self, x: usize, y: usize, color: &RGB); + + fn square(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: &RGB) { + for x in x1..x2+1 { + self.set_pixel(x, y1, color); + } + for x in x1..x2+1 { + self.set_pixel(x, y2, color); + } + for y in y1..y2+1 { + self.set_pixel(x1, y, color); + } + for y in y1..y2+1 { + self.set_pixel(x2, y, color); + } + } +} + +/* +pub const DIGIT_WIDTH: usize = 5; +pub const DIGIT_HEIGHT: usize = 9; + +pub const ZERO_SEVEN_SEGMENT: [bool; 7] = [true, true, true, true, true, true, false]; + +pub const ONE_SEVEN_SEGMENT: [bool; 7] = [false, true, true, false, false, false, false]; + +pub const TWO_SEVEN_SEGMENT: [bool; 7] = [true, true, false, true, true, false, true]; + +pub const THREE_SEVEN_SEGMENT: [bool; 7] = [true, true, true, true, false, false, true]; + +pub const FOUR_SEVEN_SEGMENT: [bool; 7] = [false, true, true, false, false, true, true]; + +pub const FIVE_SEVEN_SEGMENT: [bool; 7] = [true, false, true, true, false, true, true]; + +pub const SIX_SEVEN_SEGMENT: [bool; 7] = [true, false, true, true, true, true, true]; + +pub const SEVEN_SEVEN_SEGMENT: [bool; 7] = [true, true, true, false, false, false, false]; + +pub const EIGHT_SEVEN_SEGMENT: [bool; 7] = [true, true, true, true, true, true, true]; + +pub const NINE_SEVEN_SEGMENT: [bool; 7] = [true, true, true, false, false, true, true]; + +pub const SEVEN_SEGMENT_FONT: [[bool; 7]; 10] = [ + ZERO_SEVEN_SEGMENT, + ONE_SEVEN_SEGMENT, + TWO_SEVEN_SEGMENT, + THREE_SEVEN_SEGMENT, + FOUR_SEVEN_SEGMENT, + FIVE_SEVEN_SEGMENT, + SIX_SEVEN_SEGMENT, + SEVEN_SEVEN_SEGMENT, + EIGHT_SEVEN_SEGMENT, + NINE_SEVEN_SEGMENT, +]; + +pub fn write_pixel(framebuf: &mut [u8], width: usize, x: usize, y: usize, color: (u8, u8, u8)) { + framebuf[(y * width + x) * 3 + 0] = color.0 << 2; + framebuf[(y * width + x) * 3 + 1] = color.1 << 2; + framebuf[(y * width + x) * 3 + 2] = color.2 << 2; +} + +pub fn draw_seven_segment( + digit: u8, + frame: &mut [u8], + width: usize, + x: usize, + y: usize, + color: (u8, u8, u8), +) { + let segments = SEVEN_SEGMENT_FONT[digit as usize]; + if segments[0] { + write_pixel(frame, width, x + 1, y, color); + write_pixel(frame, width, x + 2, y, color); + write_pixel(frame, width, x + 3, y, color); + } + if segments[1] { + write_pixel(frame, width, x + 4, y + 1, color); + write_pixel(frame, width, x + 4, y + 2, color); + write_pixel(frame, width, x + 4, y + 3, color); + } + if segments[2] { + write_pixel(frame, width, x + 4, y + 5, color); + write_pixel(frame, width, x + 4, y + 6, color); + write_pixel(frame, width, x + 4, y + 7, color); + } + if segments[3] { + write_pixel(frame, width, x + 1, y + 8, color); + write_pixel(frame, width, x + 2, y + 8, color); + write_pixel(frame, width, x + 3, y + 8, color); + } + if segments[4] { + write_pixel(frame, width, x, y + 5, color); + write_pixel(frame, width, x, y + 6, color); + write_pixel(frame, width, x, y + 7, color); + } + if segments[5] { + write_pixel(frame, width, x, y + 1, color); + write_pixel(frame, width, x, y + 2, color); + write_pixel(frame, width, x, y + 3, color); + } + if segments[6] { + write_pixel(frame, width, x + 1, y + 4, color); + write_pixel(frame, width, x + 2, y + 4, color); + write_pixel(frame, width, x + 3, y + 4, color); + } +} +*/ diff --git a/pico-st7789/src/font/mod.rs b/pico-st7789/src/font/mod.rs new file mode 100644 index 0000000..126176d --- /dev/null +++ b/pico-st7789/src/font/mod.rs @@ -0,0 +1,13 @@ +use crate::canvas::{Canvas, RGB}; + +mod sixteen_segment; +pub use sixteen_segment::SixteenSegmentFont; + +pub trait Font<A> { + fn glyph(&self, c: char) -> &A; +} + +pub trait Glyph { + fn draw(&self, canvas: &mut impl Canvas, x: usize, y: usize, color: &RGB); +} + diff --git a/pico-st7789/src/font/sixteen_segment.rs b/pico-st7789/src/font/sixteen_segment.rs new file mode 100644 index 0000000..fe021ff --- /dev/null +++ b/pico-st7789/src/font/sixteen_segment.rs @@ -0,0 +1,517 @@ +use alloc::collections::btree_map::BTreeMap; +use bitflags::bitflags; + +use crate::canvas::{Canvas, RGB}; + +use super::{Font, Glyph}; + +// Sixteen Segments +// https://www.partsnotincluded.com/segmented-led-display-ascii-library/ +// +// a1 a2 +// f h i jb +// f i j b +// f hij b +// g1 g2 +// e klm c +// e k l m c +// ek l mc +// d1 d2 + +bitflags! { + pub struct SixteenSegmentGlyph: u32 { + const NONE = 0; + const A1 = 0x0001; + const A2 = 0x0001 << 1; + const B = 0x0001 << 2; + const C = 0x0001 << 3; + const D1 = 0x0001 << 4; + const D2 = 0x0001 << 5; + const E = 0x0001 << 6; + const F = 0x0001 << 7; + const G1 = 0x0001 << 8; + const G2 = 0x0001 << 9; + const H = 0x0001 << 10; + const I = 0x0001 << 11; + const J = 0x0001 << 12; + const K = 0x0001 << 13; + const L = 0x0001 << 14; + const M = 0x0001 << 15; + const DOT = 0x0001 << 16; + } +} + +pub struct SixteenSegmentFont(BTreeMap<char, SixteenSegmentGlyph>); + +impl SixteenSegmentFont { + pub fn new() -> Self { + let mut font = BTreeMap::new(); + font.insert(' ', SixteenSegmentGlyph::NONE); + font.insert( + '!', + SixteenSegmentGlyph::B | SixteenSegmentGlyph::C | SixteenSegmentGlyph::DOT, + ); + font.insert('"', SixteenSegmentGlyph::B | SixteenSegmentGlyph::I); + font.insert( + '0', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::J + | SixteenSegmentGlyph::K, + ); + font.insert( + '1', + SixteenSegmentGlyph::B | SixteenSegmentGlyph::C | SixteenSegmentGlyph::J, + ); + font.insert( + '2', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + '3', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::G2, + ); + font.insert( + '4', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + '5', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::M, + ); + font.insert( + '6', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + '7', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C, + ); + font.insert( + '8', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + '9', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'A', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'B', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::G2 + | SixteenSegmentGlyph::I + | SixteenSegmentGlyph::L, + ); + font.insert( + 'C', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F, + ); + font.insert( + 'D', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::I + | SixteenSegmentGlyph::L, + ); + font.insert( + 'E', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1, + ); + font.insert( + 'F', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1, + ); + font.insert( + 'G', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'H', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'I', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::I + | SixteenSegmentGlyph::L, + ); + font.insert( + 'J', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E, + ); + font.insert( + 'K', + SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::J + | SixteenSegmentGlyph::M, + ); + font.insert( + 'L', + SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F, + ); + font.insert( + 'M', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::H + | SixteenSegmentGlyph::J, + ); + font.insert( + 'N', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::H + | SixteenSegmentGlyph::M, + ); + font.insert( + 'O', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F, + ); + font.insert( + 'P', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'Q', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::M, + ); + font.insert( + 'R', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::B + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2 + | SixteenSegmentGlyph::M, + ); + font.insert( + 'S', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'T', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::I + | SixteenSegmentGlyph::L, + ); + font.insert( + 'U', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F, + ); + font.insert( + 'V', + SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::J + | SixteenSegmentGlyph::K, + ); + font.insert( + 'W', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::E + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::K + | SixteenSegmentGlyph::M, + ); + font.insert( + 'X', + SixteenSegmentGlyph::H + | SixteenSegmentGlyph::J + | SixteenSegmentGlyph::K + | SixteenSegmentGlyph::M, + ); + font.insert( + 'Y', + SixteenSegmentGlyph::B + | SixteenSegmentGlyph::C + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::F + | SixteenSegmentGlyph::G1 + | SixteenSegmentGlyph::G2, + ); + font.insert( + 'Z', + SixteenSegmentGlyph::A1 + | SixteenSegmentGlyph::A2 + | SixteenSegmentGlyph::D1 + | SixteenSegmentGlyph::D2 + | SixteenSegmentGlyph::J + | SixteenSegmentGlyph::K, + ); + Self(font) + } +} + +impl Font<SixteenSegmentGlyph> for SixteenSegmentFont { + fn glyph(&self, c: char) -> &SixteenSegmentGlyph { + self.0.get(&c).unwrap() + } +} + +impl Glyph for SixteenSegmentGlyph { + fn draw(&self, canvas: &mut impl Canvas, x: usize, y: usize, color: &RGB) { + if self.contains(SixteenSegmentGlyph::A1) { + canvas.set_pixel(x + 1, y, color); + canvas.set_pixel(x + 2, y, color); + canvas.set_pixel(x + 3, y, color); + } + if self.contains(SixteenSegmentGlyph::A2) { + canvas.set_pixel(x + 5, y, color); + canvas.set_pixel(x + 6, y, color); + canvas.set_pixel(x + 7, y, color); + } + if self.contains(SixteenSegmentGlyph::B) { + canvas.set_pixel(x + 8, y + 1, color); + canvas.set_pixel(x + 8, y + 2, color); + canvas.set_pixel(x + 8, y + 3, color); + canvas.set_pixel(x + 8, y + 4, color); + canvas.set_pixel(x + 8, y + 5, color); + } + if self.contains(SixteenSegmentGlyph::C) { + canvas.set_pixel(x + 8, y + 7, color); + canvas.set_pixel(x + 8, y + 8, color); + canvas.set_pixel(x + 8, y + 9, color); + canvas.set_pixel(x + 8, y + 10, color); + canvas.set_pixel(x + 8, y + 11, color); + } + + if self.contains(SixteenSegmentGlyph::D1) { + canvas.set_pixel(x + 1, y + 12, color); + canvas.set_pixel(x + 2, y + 12, color); + canvas.set_pixel(x + 3, y + 12, color); + } + if self.contains(SixteenSegmentGlyph::D2) { + canvas.set_pixel(x + 5, y + 12, color); + canvas.set_pixel(x + 6, y + 12, color); + canvas.set_pixel(x + 7, y + 12, color); + } + + if self.contains(SixteenSegmentGlyph::E) { + canvas.set_pixel(x, y + 7, color); + canvas.set_pixel(x, y + 8, color); + canvas.set_pixel(x, y + 9, color); + canvas.set_pixel(x, y + 10, color); + canvas.set_pixel(x, y + 11, color); + } + if self.contains(SixteenSegmentGlyph::F) { + canvas.set_pixel(x, y + 1, color); + canvas.set_pixel(x, y + 2, color); + canvas.set_pixel(x, y + 3, color); + canvas.set_pixel(x, y + 4, color); + canvas.set_pixel(x, y + 5, color); + } + + if self.contains(SixteenSegmentGlyph::G1) { + canvas.set_pixel(x + 1, y + 6, color); + canvas.set_pixel(x + 2, y + 6, color); + canvas.set_pixel(x + 3, y + 6, color); + } + if self.contains(SixteenSegmentGlyph::G2) { + canvas.set_pixel(x + 5, y + 6, color); + canvas.set_pixel(x + 6, y + 6, color); + canvas.set_pixel(x + 7, y + 6, color); + } + + if self.contains(SixteenSegmentGlyph::H) { + canvas.set_pixel(x + 1, y + 1, color); + canvas.set_pixel(x + 1, y + 2, color); + canvas.set_pixel(x + 2, y + 3, color); + canvas.set_pixel(x + 3, y + 4, color); + canvas.set_pixel(x + 3, y + 5, color); + } + if self.contains(SixteenSegmentGlyph::I) { + canvas.set_pixel(x + 4, y + 1, color); + canvas.set_pixel(x + 4, y + 2, color); + canvas.set_pixel(x + 4, y + 3, color); + canvas.set_pixel(x + 4, y + 4, color); + canvas.set_pixel(x + 4, y + 5, color); + } + if self.contains(SixteenSegmentGlyph::J) { + canvas.set_pixel(x + 7, y + 1, color); + canvas.set_pixel(x + 7, y + 2, color); + canvas.set_pixel(x + 6, y + 3, color); + canvas.set_pixel(x + 5, y + 4, color); + canvas.set_pixel(x + 5, y + 5, color); + } + if self.contains(SixteenSegmentGlyph::K) { + canvas.set_pixel(x + 3, y + 7, color); + canvas.set_pixel(x + 3, y + 8, color); + canvas.set_pixel(x + 2, y + 9, color); + canvas.set_pixel(x + 1, y + 10, color); + canvas.set_pixel(x + 1, y + 11, color); + } + if self.contains(SixteenSegmentGlyph::L) { + canvas.set_pixel(x + 4, y + 7, color); + canvas.set_pixel(x + 4, y + 8, color); + canvas.set_pixel(x + 4, y + 9, color); + canvas.set_pixel(x + 4, y + 10, color); + canvas.set_pixel(x + 4, y + 11, color); + } + if self.contains(SixteenSegmentGlyph::M) { + canvas.set_pixel(x + 5, y + 7, color); + canvas.set_pixel(x + 5, y + 8, color); + canvas.set_pixel(x + 6, y + 9, color); + canvas.set_pixel(x + 7, y + 10, color); + canvas.set_pixel(x + 7, y + 11, color); + } + } +} + diff --git a/pico-st7789/src/main.rs b/pico-st7789/src/main.rs index cdb6130..e404ba7 100644 --- a/pico-st7789/src/main.rs +++ b/pico-st7789/src/main.rs @@ -1,23 +1,26 @@ #![no_main] #![no_std] -use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiBus}; +extern crate alloc; + +use embedded_alloc::LlffHeap as Heap; +use embedded_hal::{delay::DelayNs, digital::OutputPin}; use fugit::RateExtU32; use panic_halt as _; use rp_pico::{ entry, - hal::{ - clocks::init_clocks_and_plls, - gpio::{FunctionSio, Pin, PinId, PullDown, SioOutput}, - spi::{Enabled, Spi, SpiDevice, ValidSpiPinout}, - Clock, Sio, Timer, Watchdog, - }, + hal::{clocks::init_clocks_and_plls, spi::Spi, Clock, Sio, Timer, Watchdog}, pac, Pins, }; +mod canvas; +use canvas::{Canvas, RGB}; + +mod font; +use font::{Font, Glyph, SixteenSegmentFont}; + mod st7789; use st7789::{ST7789Display, SETUP_PROGRAM}; -pub use st7789::Step; const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // MHz, https://forums.raspberrypi.com/viewtopic.php?t=356764 @@ -25,15 +28,44 @@ const ROWS: usize = 320; const COLUMNS: usize = 170; const FRAMEBUF: usize = ROWS * COLUMNS * 3; -/* -struct Frame { - columns: usize, - buf: [u8; FRAMEBUF], +#[global_allocator] +static HEAP: Heap = Heap::empty(); + +static mut BUF: [u8; 163200] = [0; 163200]; + +pub struct FrameBuf { + pub buf: &'static mut [u8; 163200], + pub width: usize, +} + +impl FrameBuf { + pub fn new() -> Self { + Self { + buf: unsafe { &mut BUF }, + width: 170, + } + } +} + +impl Canvas for FrameBuf { + fn set_pixel(&mut self, x: usize, y: usize, color: &RGB) { + self.buf[(y * self.width + x) * 3 + 0] = color.r << 2; + self.buf[(y * self.width + x) * 3 + 1] = color.g << 2; + self.buf[(y * self.width + x) * 3 + 2] = color.b << 2; + } } -*/ #[entry] unsafe fn main() -> ! { + { + use core::mem::MaybeUninit; + const HEAP_SIZE: usize = 1024; + static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; + unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } + } + + let font_sixteen = SixteenSegmentFont::new(); + // rp_pico::pac::Peripherals is a reference to physical hardware defined on the Pico. let mut peripherals = pac::Peripherals::take().unwrap(); @@ -92,8 +124,8 @@ unsafe fn main() -> ! { &mut peripherals.RESETS, // The SPI system uses the peripheral clock clocks.peripheral_clock.freq(), - // Transmit data at a rate of 1Mbit. - 1_u32.MHz(), + // Transmit data at a rate of 32Mbit. + 32_u32.MHz(), // Run with SPI Mode 1. This means that the clock line should start high and that data will // be sampled starting at the first falling edge. embedded_hal::spi::MODE_3, @@ -110,31 +142,158 @@ unsafe fn main() -> ! { timer.delay_ms(1000); - let mut frame: [u8; FRAMEBUF] = [0; FRAMEBUF]; + /* + let mut framebuf = [0; FRAMEBUF]; + let mut canvas = Canvas::new(&mut framebuf, COLUMNS); + */ + let mut canvas = FrameBuf::new(); + let white = RGB { r: 63, g: 63, b: 63 }; - let mut strength = 0; loop { - led.set_high(); + /* + draw_seven_segment(0, &mut frame, 0, 0, (255, 255, 255)); + draw_seven_segment(1, &mut frame, 7, 0, (255, 255, 255)); + draw_seven_segment(2, &mut frame, 14, 0, (255, 255, 255)); + draw_seven_segment(3, &mut frame, 21, 0, (255, 255, 255)); + draw_seven_segment(4, &mut frame, 28, 0, (255, 255, 255)); + draw_seven_segment(5, &mut frame, 35, 0, (255, 255, 255)); + draw_seven_segment(6, &mut frame, 42, 0, (255, 255, 255)); + draw_seven_segment(7, &mut frame, 49, 0, (255, 255, 255)); + draw_seven_segment(8, &mut frame, 56, 0, (255, 255, 255)); + draw_seven_segment(9, &mut frame, 63, 0, (255, 255, 255)); + */ + + font_sixteen + .glyph(' ') + .draw(&mut canvas, 0, 0, &white); + font_sixteen + .glyph('0') + .draw(&mut canvas, 11, 0, &white); + font_sixteen + .glyph('1') + .draw(&mut canvas, 22, 0, &white); + font_sixteen + .glyph('2') + .draw(&mut canvas, 33, 0, &white); + font_sixteen + .glyph('3') + .draw(&mut canvas, 44, 0, &white); + font_sixteen + .glyph('4') + .draw(&mut canvas, 55, 0, &white); + font_sixteen + .glyph('5') + .draw(&mut canvas, 66, 0, &white); + font_sixteen + .glyph('6') + .draw(&mut canvas, 77, 0, &white); + font_sixteen + .glyph('7') + .draw(&mut canvas, 88, 0, &white); + font_sixteen + .glyph('8') + .draw(&mut canvas, 99, 0, &white); + font_sixteen + .glyph('9') + .draw(&mut canvas, 110, 0, &white); + + font_sixteen + .glyph('A') + .draw(&mut canvas, 0, 20, &white); + font_sixteen + .glyph('B') + .draw(&mut canvas, 11, 20, &white); + font_sixteen + .glyph('C') + .draw(&mut canvas, 22, 20, &white); + font_sixteen + .glyph('D') + .draw(&mut canvas, 33, 20, &white); + font_sixteen + .glyph('E') + .draw(&mut canvas, 44, 20, &white); + font_sixteen + .glyph('F') + .draw(&mut canvas, 55, 20, &white); + font_sixteen + .glyph('G') + .draw(&mut canvas, 66, 20, &white); + font_sixteen + .glyph('H') + .draw(&mut canvas, 77, 20, &white); + font_sixteen + .glyph('I') + .draw(&mut canvas, 88, 20, &white); + font_sixteen + .glyph('J') + .draw(&mut canvas, 99, 20, &white); + font_sixteen + .glyph('K') + .draw(&mut canvas, 110, 20, &white); + font_sixteen + .glyph('L') + .draw(&mut canvas, 121, 20, &white); + font_sixteen + .glyph('M') + .draw(&mut canvas, 132, 20, &white); + font_sixteen + .glyph('N') + .draw(&mut canvas, 143, 20, &white); + font_sixteen + .glyph('O') + .draw(&mut canvas, 154, 20, &white); + + font_sixteen + .glyph('P') + .draw(&mut canvas, 0, 40, &white); + font_sixteen + .glyph('Q') + .draw(&mut canvas, 11, 40, &white); + font_sixteen + .glyph('R') + .draw(&mut canvas, 22, 40, &white); + font_sixteen + .glyph('S') + .draw(&mut canvas, 33, 40, &white); + font_sixteen + .glyph('T') + .draw(&mut canvas, 44, 40, &white); + font_sixteen + .glyph('U') + .draw(&mut canvas, 55, 40, &white); + font_sixteen + .glyph('V') + .draw(&mut canvas, 66, 40, &white); + font_sixteen + .glyph('W') + .draw(&mut canvas, 77, 40, &white); + font_sixteen + .glyph('X') + .draw(&mut canvas, 88, 40, &white); + font_sixteen + .glyph('Y') + .draw(&mut canvas, 99, 40, &white); + font_sixteen + .glyph('Z') + .draw(&mut canvas, 110, 40, &white); + + canvas.square(10, 70, 160, 310, &white); + { let display = display.acquire(); - display.send_buf(&frame); + let _ = led.set_high(); + timer.delay_ms(100); + display.send_buf(canvas.buf); + let _ = led.set_low(); } - + /* for x in 80..90 { for y in 155..165 { - write_pixel(&mut frame, x, y, (0, 0, 63)); + draw_pixel(&mut frame, x, y, (0, 0, 63)); } } - - timer.delay_ms(10); - led.set_low(); + */ timer.delay_ms(1000); } } - -fn write_pixel(framebuf: &mut [u8], x: usize, y: usize, color: (u8, u8, u8)) { - framebuf[(y * COLUMNS + x) * 3 + 0] = color.0 << 2; - framebuf[(y * COLUMNS + x) * 3 + 1] = color.1 << 2; - framebuf[(y * COLUMNS + x) * 3 + 2] = color.2 << 2; -}