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;
-}