diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..83b30326b2e76dbe32701c8de4367434ebc9edd5
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "rust-analyzer.checkOnSave.allTargets": false,
+}
\ No newline at end of file
diff --git a/embassy-net-badgelink/Cargo.toml b/embassy-net-badgelink/Cargo.toml
index ab412ce829b90de476fe877eccc9537777467671..998f909b71dba823605f9cd79aa227d8b05f93ec 100644
--- a/embassy-net-badgelink/Cargo.toml
+++ b/embassy-net-badgelink/Cargo.toml
@@ -5,15 +5,15 @@ edition = "2021"
 authors = ["zdmx <hi@zdmx.me>"]
 
 [dependencies]
-embassy-time = "0.1.1"
+embassy-time = "0.1.2"
 embassy-sync = "0.2.0"
 embassy-futures = "0.1.0"
 embassy-net-driver-channel = "0.1.0"
 
 embedded-hal = "0.2.7"
-embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.10" }
+embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.11" }
 embedded-hal-async = "0.2.0-alpha.1"
 serial-line-ip = "0.5.0"
 heapless = "0.7.16"
-esp32s3-hal = { version = "0.10.0", features = ["embedded-hal-async", "async"] }
+esp32s3-hal = { version = "0.11.0", features = ["embedded-hal-async", "async"] }
 esp-println = { version = "0.5.0", features = ["esp32s3"] }
diff --git a/embassy-net-badgelink/src/lib.rs b/embassy-net-badgelink/src/lib.rs
index 3a409921be1ee27e88748dfcc8240ef433bee4dc..d0e9b3c90b8808a720a9364b620f339e9d8ecf39 100644
--- a/embassy-net-badgelink/src/lib.rs
+++ b/embassy-net-badgelink/src/lib.rs
@@ -8,7 +8,6 @@ use embedded_hal_async::serial::Write;
 use esp32s3_hal::uart::Instance;
 use esp32s3_hal::Uart;
 use esp_println::println;
-use heapless::Vec;
 use serial_line_ip::{Decoder, Encoder};
 
 const MTU: usize = 1500;
diff --git a/.cargo/config.toml b/flow3-rs-rt/.cargo/config.toml
similarity index 100%
rename from .cargo/config.toml
rename to flow3-rs-rt/.cargo/config.toml
diff --git a/flow3-rs-rt/Cargo.lock b/flow3-rs-rt/Cargo.lock
new file mode 100644
index 0000000000000000000000000000000000000000..e9099e71b58ef3af32b4ccb9dedbccbb108382b1
--- /dev/null
+++ b/flow3-rs-rt/Cargo.lock
@@ -0,0 +1,1435 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ad7147"
+version = "0.1.0"
+dependencies = [
+ "byte-slice-cast 1.2.2",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "heapless",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c6f84b74db2535ebae81eede2f39b947dcbf01d093ae5f791e5dd414a1bf289"
+
+[[package]]
+name = "as-slice"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
+dependencies = [
+ "generic-array 0.12.4",
+ "generic-array 0.13.3",
+ "generic-array 0.14.7",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "as-slice"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516"
+dependencies = [
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "atomic-polyfill"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "atomic-polyfill"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "atomic-pool"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58c5fc22e05ec2884db458bf307dc7b278c9428888d2b6e6fad9c0ae7804f5f6"
+dependencies = [
+ "as-slice 0.1.5",
+ "as-slice 0.2.1",
+ "atomic-polyfill 1.0.3",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "az"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
+
+[[package]]
+name = "bare-metal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
+
+[[package]]
+name = "basic-toml"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitfield"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+
+[[package]]
+name = "bmi270"
+version = "0.1.0"
+dependencies = [
+ "embedded-hal 0.2.7",
+ "fixedvec",
+]
+
+[[package]]
+name = "byte-slice-cast"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3"
+
+[[package]]
+name = "byte-slice-cast"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
+
+[[package]]
+name = "bytemuck"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "core-isa-parser"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23ec98e54b735872e54b2335c2e5a5c7fa7d9c3bfd45500f75280f84089a0083"
+dependencies = [
+ "anyhow",
+ "enum-as-inner",
+ "regex",
+ "strum 0.24.1",
+ "strum_macros 0.24.3",
+]
+
+[[package]]
+name = "critical-section"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
+
+[[package]]
+name = "darling"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
+dependencies = [
+ "darling_core 0.13.4",
+ "darling_macro 0.13.4",
+]
+
+[[package]]
+name = "darling"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
+dependencies = [
+ "darling_core 0.20.3",
+ "darling_macro 0.20.3",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
+dependencies = [
+ "darling_core 0.13.4",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
+dependencies = [
+ "darling_core 0.20.3",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "display-interface"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7517c040926d7b02b111884aa089177db80878533127f7c1b480d852c5fb4112"
+
+[[package]]
+name = "display-interface"
+version = "0.5.0-alpha.1"
+dependencies = [
+ "async-trait",
+ "embedded-dma",
+]
+
+[[package]]
+name = "display-interface-spi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "489378ad054862146fbd1f09f51d585ccbe4bd1e2feadcda2a13ac33f840e1a5"
+dependencies = [
+ "byte-slice-cast 0.3.5",
+ "display-interface 0.4.1",
+ "embedded-hal 0.2.7",
+]
+
+[[package]]
+name = "embassy-executor"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acebf176f4622fd87c7200b568ee32d5b435e3a4d58e39355ce0837b45139eca"
+dependencies = [
+ "atomic-polyfill 1.0.3",
+ "critical-section",
+ "embassy-macros",
+ "embassy-time",
+ "futures-util",
+ "static_cell",
+]
+
+[[package]]
+name = "embassy-futures"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e5367165d347c039360f784812f493b001583ab6a3dd8622f4ce9c30374ec3"
+
+[[package]]
+name = "embassy-macros"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf2e5e33cc670fcdf208c0fdf8ee93493681658562fb1c50ba8ceb09591e0ff"
+dependencies = [
+ "darling 0.13.4",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "embassy-net"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d812646c1c50452d77293e05bf2eca13c23803447cdf9bbbcf820588f4c9879"
+dependencies = [
+ "as-slice 0.2.1",
+ "atomic-polyfill 1.0.3",
+ "atomic-pool",
+ "embassy-net-driver",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-io",
+ "embedded-nal-async",
+ "futures",
+ "generic-array 0.14.7",
+ "heapless",
+ "managed",
+ "smoltcp",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "embassy-net-badgelink"
+version = "0.1.0"
+dependencies = [
+ "embassy-futures",
+ "embassy-net-driver-channel",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "esp-println",
+ "esp32s3-hal",
+ "heapless",
+ "serial-line-ip",
+]
+
+[[package]]
+name = "embassy-net-driver"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6a4985a5dab4cb55d09703bfdd7d74f58c12c6e889fd3cbb40ea40462a976e"
+
+[[package]]
+name = "embassy-net-driver-channel"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be7993940e31beda742ce0341fde6d64f93ec28926612bdc8ca4f1bf7d2fbcc0"
+dependencies = [
+ "embassy-futures",
+ "embassy-net-driver",
+ "embassy-sync",
+]
+
+[[package]]
+name = "embassy-sync"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0dad296a6f70bfdc32ef52442a31f98c28e1608893c1cecc9b6f419bab005a0"
+dependencies = [
+ "cfg-if",
+ "critical-section",
+ "embedded-io",
+ "futures-util",
+ "heapless",
+]
+
+[[package]]
+name = "embassy-time"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a0461fa8de2cf03c4363a38f439a5d7e4cc16cd41947b51663ff4b2f155b902"
+dependencies = [
+ "atomic-polyfill 1.0.3",
+ "cfg-if",
+ "critical-section",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "futures-util",
+ "heapless",
+]
+
+[[package]]
+name = "embedded-can"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438"
+dependencies = [
+ "nb 1.1.0",
+]
+
+[[package]]
+name = "embedded-dma"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446"
+dependencies = [
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "embedded-graphics"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0"
+dependencies = [
+ "az",
+ "byteorder",
+ "embedded-graphics-core",
+ "float-cmp",
+ "micromath",
+]
+
+[[package]]
+name = "embedded-graphics-core"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044"
+dependencies = [
+ "az",
+ "byteorder",
+]
+
+[[package]]
+name = "embedded-graphics-framebuf"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22354420f68727fa24d1e2741dae1e9a041065e80fb63b35a8d19c647a85be76"
+dependencies = [
+ "embedded-dma",
+ "embedded-graphics",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
+dependencies = [
+ "nb 0.1.3",
+ "void",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "1.0.0-alpha.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7724ebabcadfeb15920571dd727bc8ccde8586e52f2890bdb8182fdf42c3ff2"
+
+[[package]]
+name = "embedded-hal-async"
+version = "0.2.0-alpha.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "918285ec7b18edb024d4adc64f6f16cdc7c4d72eadfc85c3313d1e0ff40e0229"
+dependencies = [
+ "embedded-hal 1.0.0-alpha.11",
+]
+
+[[package]]
+name = "embedded-hal-bus"
+version = "0.1.0-alpha.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b36407d17c7b9de899bf9ff24d497d7bb02e52f2385045632f5e6b50187e954"
+dependencies = [
+ "critical-section",
+ "embedded-hal 1.0.0-alpha.11",
+]
+
+[[package]]
+name = "embedded-hal-nb"
+version = "1.0.0-alpha.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a09e4c3f8a54e60803405e1cc17e36c963ab32e654f8d6bb49d48cd8116360d7"
+dependencies = [
+ "embedded-hal 1.0.0-alpha.11",
+ "nb 1.1.0",
+]
+
+[[package]]
+name = "embedded-io"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
+
+[[package]]
+name = "embedded-nal"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db9efecb57ab54fa918730f2874d7d37647169c50fa1357fecb81abee840b113"
+dependencies = [
+ "heapless",
+ "nb 1.1.0",
+ "no-std-net 0.5.0",
+]
+
+[[package]]
+name = "embedded-nal-async"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27ce84f518ca912777ec143db235f4d615e3bf8d4e46d507d6ef12daf5b1df98"
+dependencies = [
+ "embedded-io",
+ "embedded-nal",
+ "heapless",
+ "no-std-net 0.6.0",
+]
+
+[[package]]
+name = "enum-as-inner"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "esp-backtrace"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b151ef7db21143b1a3b7a378c16d97ae13d0a5e3cb9682ed1f11bba821cce42d"
+dependencies = [
+ "esp-println",
+]
+
+[[package]]
+name = "esp-hal-common"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9bb3220d63ba0ec4e9b1846edd47e8da3a884c6557b3ba7398494c56a93de35"
+dependencies = [
+ "basic-toml",
+ "bitfield",
+ "bitflags 2.4.0",
+ "cfg-if",
+ "critical-section",
+ "embassy-futures",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-can",
+ "embedded-dma",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "embedded-hal-nb",
+ "esp-hal-procmacros",
+ "esp-synopsys-usb-otg",
+ "esp32s3",
+ "fugit",
+ "lock_api",
+ "log",
+ "nb 1.1.0",
+ "paste",
+ "serde",
+ "strum 0.25.0",
+ "usb-device",
+ "void",
+ "xtensa-lx",
+ "xtensa-lx-rt",
+]
+
+[[package]]
+name = "esp-hal-procmacros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "042d5a1ef0e01d6de045972779e4aced3a10e6170169a5cb2de7bef31802e28a"
+dependencies = [
+ "darling 0.20.3",
+ "proc-macro-crate",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "esp-hal-smartled"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd1c4e28c17b0b6f7aac56a5e27c71b5e5ece3e81b49fbcfa81be2ccb9cc2f82"
+dependencies = [
+ "esp-hal-common",
+ "fugit",
+ "smart-leds-trait",
+]
+
+[[package]]
+name = "esp-println"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af6a511d37dba5fb8f01bf5485bc619a1a1959e1aaf666a7597df8fe615a0816"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "esp-synopsys-usb-otg"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc6734e87e7b86858f7884649deae6bf634d1e6f5b2d078e457cf4d72c541ec"
+dependencies = [
+ "critical-section",
+ "embedded-hal 0.2.7",
+ "usb-device",
+ "vcell",
+]
+
+[[package]]
+name = "esp32s3"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e482df6923df18ccd05ab80b54be5af32497f112f5b60ee05dc9d57562e68c"
+dependencies = [
+ "critical-section",
+ "vcell",
+ "xtensa-lx",
+]
+
+[[package]]
+name = "esp32s3-hal"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd8d75d35f3286a1e1126758527b0d8ef1d98f6a137b77fed066800f74bc9c9"
+dependencies = [
+ "bare-metal",
+ "embassy-time",
+ "embedded-hal 0.2.7",
+ "embedded-hal-async",
+ "esp-hal-common",
+]
+
+[[package]]
+name = "fixedvec"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b395ef2adf62bdeefcd1b59ad0dd2225c6c333ec79656ea79ac5285c46d051ea"
+
+[[package]]
+name = "float-cmp"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "flow3-rs"
+version = "0.1.0"
+dependencies = [
+ "ad7147",
+ "bmi270",
+ "byte-slice-cast 1.2.2",
+ "display-interface 0.5.0-alpha.1",
+ "embassy-executor",
+ "embassy-futures",
+ "embassy-net",
+ "embassy-net-badgelink",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-dma",
+ "embedded-graphics",
+ "embedded-graphics-framebuf",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "embedded-hal-bus",
+ "esp-backtrace",
+ "esp-hal-smartled",
+ "esp-println",
+ "esp32s3-hal",
+ "gc9a01",
+ "heapless",
+ "port-expander",
+ "shared-bus",
+ "smart-leds",
+ "smoltcp",
+ "static_cell",
+ "tinybmp",
+]
+
+[[package]]
+name = "flow3-rs-rt"
+version = "0.1.0"
+dependencies = [
+ "embassy-executor",
+ "embassy-sync",
+ "embassy-time",
+ "esp-println",
+ "esp32s3-hal",
+ "flow3-rs",
+ "lazy_static",
+ "shared-bus",
+ "static_cell",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "fugit"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
+dependencies = [
+ "gcd",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+
+[[package]]
+name = "futures-io"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+
+[[package]]
+name = "futures-task"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+
+[[package]]
+name = "futures-util"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+dependencies = [
+ "futures-core",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "gc9a01"
+version = "0.1.0"
+dependencies = [
+ "display-interface 0.5.0-alpha.1",
+ "display-interface-spi",
+ "embedded-dma",
+ "embedded-graphics-core",
+ "embedded-hal 0.2.7",
+]
+
+[[package]]
+name = "gcd"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+
+[[package]]
+name = "heapless"
+version = "0.7.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
+dependencies = [
+ "atomic-polyfill 0.1.11",
+ "hash32",
+ "rustc_version",
+ "spin 0.9.8",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "indexmap"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+
+[[package]]
+name = "managed"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "micromath"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55"
+
+[[package]]
+name = "minijinja"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "359c4820413be7706e93999171652e140578384f85faac14cb22d350bd0fbabf"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "mutex-trait"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4bb1638d419e12f8b1c43d9e639abd0d1424285bdea2f76aa231e233c63cd3a"
+
+[[package]]
+name = "nb"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
+dependencies = [
+ "nb 1.1.0",
+]
+
+[[package]]
+name = "nb"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
+
+[[package]]
+name = "no-std-net"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bcece43b12349917e096cddfa66107277f123e6c96a5aea78711dc601a47152"
+
+[[package]]
+name = "no-std-net"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
+
+[[package]]
+name = "num-traits"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "paste"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "port-expander"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3facaed79c04a8116d7d83d5e0be5e449986428716e8d089e426366b7a20282e"
+dependencies = [
+ "embedded-hal 0.2.7",
+ "shared-bus",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
+dependencies = [
+ "once_cell",
+ "toml_edit",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r0"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
+
+[[package]]
+name = "regex"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
+
+[[package]]
+name = "rgb"
+version = "0.8.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+
+[[package]]
+name = "serde"
+version = "1.0.183"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.183"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "serial-line-ip"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08a0b86bcdab6b15029ff7e37ae8acdadbf5d48e070ec5a067aa5c31e306f958"
+
+[[package]]
+name = "shared-bus"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bb5650c146f3186332c5da30ff542f7d1ff0c2410346cd861f34fa836dc0d84"
+dependencies = [
+ "embedded-hal 0.2.7",
+ "nb 1.1.0",
+ "spin 0.9.8",
+ "xtensa-lx",
+]
+
+[[package]]
+name = "smart-leds"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38dd45fa275f70b4110eac5f5182611ad384f88bb22b68b9a9c3cafd7015290b"
+dependencies = [
+ "smart-leds-trait",
+]
+
+[[package]]
+name = "smart-leds-trait"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3"
+dependencies = [
+ "rgb",
+]
+
+[[package]]
+name = "smoltcp"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d2e3a36ac8fea7b94e666dfa3871063d6e0a5c9d5d4fec9a1a6b7b6760f0229"
+dependencies = [
+ "bitflags 1.3.2",
+ "byteorder",
+ "cfg-if",
+ "heapless",
+ "managed",
+]
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "static_cell"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49cd323fc21eb534f903ee78d781d622099f9716c5b408ed23bcf39f8f1651c0"
+dependencies = [
+ "atomic-polyfill 1.0.3",
+]
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+
+[[package]]
+name = "strum"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
+dependencies = [
+ "strum_macros 0.25.2",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.25.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tinybmp"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "197cc000e382175ff15abd9c54c694ef80ef20cb07e7f956c71e3ea97fc8dc60"
+dependencies = [
+ "embedded-graphics",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
+
+[[package]]
+name = "toml_edit"
+version = "0.19.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+
+[[package]]
+name = "usb-device"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508"
+
+[[package]]
+name = "vcell"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+
+[[package]]
+name = "winnow"
+version = "0.5.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83817bbecf72c73bad717ee86820ebf286203d2e04c3951f3cd538869c897364"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "xtensa-lx"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9490addc0a1edd86e571a9ed8063f33d8224f981e61bbf72279671ed0cb4bb7c"
+dependencies = [
+ "bare-metal",
+ "mutex-trait",
+ "spin 0.9.8",
+]
+
+[[package]]
+name = "xtensa-lx-rt"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f68fea36eb8e2d5ff4c99d367527f4a56e484b16c5e84abf4195988bd845a3fc"
+dependencies = [
+ "bare-metal",
+ "core-isa-parser",
+ "minijinja",
+ "r0",
+ "xtensa-lx-rt-proc-macros",
+]
+
+[[package]]
+name = "xtensa-lx-rt-proc-macros"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3283815e334d3e5d21868dc3c7140720b2a784238289b1127b67908c89404b79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
diff --git a/flow3-rs-rt/Cargo.toml b/flow3-rs-rt/Cargo.toml
index b8c16fe4f95f22317968a2dc19d742104febf857..9ed15f041dfb01beaa0ae8561e1a91a697cc015f 100644
--- a/flow3-rs-rt/Cargo.toml
+++ b/flow3-rs-rt/Cargo.toml
@@ -7,8 +7,11 @@ edition = "2021"
 
 [dependencies]
 embassy-executor = { version = "0.2.0", features = ["nightly", "arch-xtensa", "executor-thread", "integrated-timers"] }
-hal = { package = "esp32s3-hal", version = "0.10.0", features = ["embassy", "async", "embassy-time", "embassy-time-systick"] }
-embassy-time = { version = "=0.1.1", features = ["nightly", "unstable-traits"] }
+hal = { package = "esp32s3-hal", version = "0.11.0", features = ["embassy", "async", "embassy-time", "embassy-time-systick"] }
+embassy-time = { version = "=0.1.2", features = ["nightly", "unstable-traits"] }
 static_cell = "1.2.0"
 shared-bus = { version = "0.3.0", features = ["xtensa"] }
-flow3-rs = { path = "../" }
\ No newline at end of file
+flow3-rs = { path = "../flow3-rs" }
+lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
+esp-println = { version = "0.5.0", features = ["esp32s3"] }
+embassy-sync = "0.2.0"
diff --git a/rust-toolchain.toml b/flow3-rs-rt/rust-toolchain.toml
similarity index 100%
rename from rust-toolchain.toml
rename to flow3-rs-rt/rust-toolchain.toml
diff --git a/flow3-rs-rt/src/flow3r.rs b/flow3-rs-rt/src/flow3r.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4d7efe2eb96f866ee0199705fc382f01df5ef9bc
--- /dev/null
+++ b/flow3-rs-rt/src/flow3r.rs
@@ -0,0 +1,191 @@
+use hal::{
+    clock::{ClockControl, Clocks},
+    cpu_control::CpuControl,
+    embassy,
+    gdma::Gdma,
+    i2c::I2C,
+    ledc::LEDC,
+    peripherals::{Peripherals, I2C0},
+    prelude::*,
+    pulse_control::ClockSource,
+    systimer::SystemTimer,
+    timer::TimerGroup,
+    PulseControl, Rtc, Spi, Uart, IO, uart::{self, TxRxPins}, Rng,
+};
+use static_cell::StaticCell;
+
+use flow3_rs::{
+    badgelink::BadgeLink,
+    captouch::{Captouch, CaptouchRunner},
+    display::Display,
+    imu::ImuHandler,
+    input::{Inputs, InputRunner},
+    leds::init_leds,
+    Flow3r,
+};
+
+static CLOCKS: StaticCell<Clocks> = StaticCell::new();
+
+pub async fn init_flow3r() -> (Flow3r, InputRunner, CaptouchRunner)  {
+    let peripherals = Peripherals::take();
+    let mut system = peripherals.SYSTEM.split();
+    let clocks = CLOCKS.init(ClockControl::boot_defaults(system.clock_control).freeze());
+
+    let mut rtc = Rtc::new(peripherals.RTC_CNTL);
+    let timer_group0 = TimerGroup::new(
+        peripherals.TIMG0,
+        &clocks,
+        &mut system.peripheral_clock_control,
+    );
+    let mut wdt0 = timer_group0.wdt;
+    let timer_group1 = TimerGroup::new(
+        peripherals.TIMG1,
+        &clocks,
+        &mut system.peripheral_clock_control,
+    );
+    let mut wdt1 = timer_group1.wdt;
+
+    // Disable watchdog timers
+    rtc.swd.disable();
+    rtc.rwdt.disable();
+    wdt0.disable();
+    wdt1.disable();
+
+    embassy::init(&clocks, SystemTimer::new(peripherals.SYSTIMER));
+
+    // Async requires the GPIO interrupt to wake futures
+    hal::interrupt::enable(
+        hal::peripherals::Interrupt::GPIO,
+        hal::interrupt::Priority::Priority1,
+    )
+    .unwrap();
+
+    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
+    let pulse = PulseControl::new(
+        peripherals.RMT,
+        &mut system.peripheral_clock_control,
+        ClockSource::APB,
+        0,
+        0,
+        0,
+    )
+    .unwrap();
+
+    // Init I2C
+
+    let sda = io.pins.gpio2;
+    let scl = io.pins.gpio1;
+
+    let i2c = I2C::new(
+        peripherals.I2C0,
+        sda,
+        scl,
+        100u32.kHz(),
+        &mut system.peripheral_clock_control,
+        &clocks,
+    );
+
+    // Create shared I2C Bus
+
+    let i2c_busmanager = shared_bus::new_xtensa!(I2C<'static, I2C0> = i2c).unwrap();
+
+    // Init SPI + DMA
+
+    let sck = io.pins.gpio41;
+    let mosi = io.pins.gpio42;
+    let spi = Spi::new_no_cs_no_miso(
+        peripherals.SPI2,
+        sck,
+        mosi,
+        80u32.MHz(),
+        hal::spi::SpiMode::Mode0,
+        &mut system.peripheral_clock_control,
+        &clocks,
+    );
+
+    let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control);
+    let dma_channel = dma.channel0;
+
+    // Init Display backlight control
+
+    let ledc = LEDC::new(
+        peripherals.LEDC,
+        clocks,
+        &mut system.peripheral_clock_control,
+    );
+
+    // Init display early to clear pixel mash from screen
+
+    let mut display = Display::new(
+        spi,
+        dma_channel,
+        ledc,
+        io.pins.gpio46,
+        io.pins.gpio38,
+        io.pins.gpio40,
+    )
+    .await;
+    display.clear().await.unwrap();
+
+    // Init uart
+
+    let uart0_config = uart::config::Config {
+        baudrate: 9600, //115200,
+        data_bits: uart::config::DataBits::DataBits8,
+        parity: uart::config::Parity::ParityNone,
+        stop_bits: uart::config::StopBits::STOP1
+    };
+    let uart0_pins = TxRxPins::new_tx_rx(io.pins.gpio7.into_push_pull_output(), io.pins.gpio6.into_floating_input());
+    let mut uart0 = Uart::new_with_config(peripherals.UART1, Some(uart0_config), Some(uart0_pins), &clocks, &mut system.peripheral_clock_control);
+    uart0.set_rx_fifo_full_threshold(64 as u16);
+
+    hal::interrupt::enable(
+        hal::peripherals::Interrupt::UART1,
+        hal::interrupt::Priority::Priority2,
+    )
+    .unwrap();
+
+    let uart1_config = uart::config::Config {
+        baudrate: 9600, //115200,
+        data_bits: uart::config::DataBits::DataBits8,
+        parity: uart::config::Parity::ParityNone,
+        stop_bits: uart::config::StopBits::STOP1
+    };
+    let uart1_pins = TxRxPins::new_tx_rx(io.pins.gpio5.into_push_pull_output(), io.pins.gpio4.into_floating_input());
+    let mut uart1 = Uart::new_with_config(peripherals.UART2, Some(uart1_config),Some(uart1_pins), &clocks, &mut system.peripheral_clock_control);
+    uart1.set_rx_fifo_full_threshold(64 as u16);
+
+    hal::interrupt::enable(
+        hal::peripherals::Interrupt::UART2,
+        hal::interrupt::Priority::Priority2,
+    )
+    .unwrap();
+
+    let rng = Rng::new(peripherals.RNG);
+
+    // Init Flow3r components
+
+    let badgelink = BadgeLink::new(i2c_busmanager.acquire_i2c());
+    let imu = ImuHandler::new(i2c_busmanager.acquire_i2c());
+    let inputs = Inputs;
+    let captouch = Captouch;
+    let leds = init_leds(pulse.channel0, io.pins.gpio14);
+
+    let input_runner = InputRunner::new(
+        i2c_busmanager.acquire_i2c(),
+        io.pins.gpio8,
+        io.pins.gpio0,
+        io.pins.gpio3,
+    );
+
+    let captouch_runner = CaptouchRunner::new(
+        i2c_busmanager.acquire_i2c(),
+        i2c_busmanager.acquire_i2c(),
+        io.pins.gpio16,
+        io.pins.gpio15,
+    );
+
+    let flow3r = Flow3r::new(Some(badgelink), Some(captouch), Some(display), Some(imu), Some(inputs), Some(leds), Some(uart0), Some(uart1), Some(rng));
+
+    (flow3r, input_runner, captouch_runner)
+}
\ No newline at end of file
diff --git a/flow3-rs-rt/src/lib.rs b/flow3-rs-rt/src/lib.rs
index c05c5b6fefd173747e8cbc28ff1471d667f3ec59..dba5d27ef1656503f40a2947abbc916a2061f404 100644
--- a/flow3-rs-rt/src/lib.rs
+++ b/flow3-rs-rt/src/lib.rs
@@ -2,4 +2,9 @@
 #![feature(type_alias_impl_trait)]
 
 mod runtime;
-pub use runtime::start_runtime;
\ No newline at end of file
+mod flow3r;
+pub use runtime::start_runtime;
+pub use runtime::EXECUTOR;
+pub use flow3r::init_flow3r;
+pub use runtime::captouch_task;
+pub use runtime::input_task;
\ No newline at end of file
diff --git a/flow3-rs-rt/src/runtime.rs b/flow3-rs-rt/src/runtime.rs
index 1550de8d0ebefcf8d0464dcb2ef5813207f9b84d..8849ab7f93feecf1a07bdf3318191701c9f50aea 100644
--- a/flow3-rs-rt/src/runtime.rs
+++ b/flow3-rs-rt/src/runtime.rs
@@ -1,229 +1,48 @@
 use embassy_executor::{Executor, Spawner, SpawnToken};
-use embassy_time::{Duration, Timer};
-use hal::{
-    clock::{ClockControl, Clocks},
-    cpu_control::CpuControl,
-    embassy,
-    gdma::Gdma,
-    i2c::I2C,
-    ledc::LEDC,
-    peripherals::{Peripherals, I2C0},
-    prelude::*,
-    pulse_control::ClockSource,
-    systimer::SystemTimer,
-    timer::TimerGroup,
-    PulseControl, Rng, Rtc, Spi, Uart, IO, uart::{self, TxRxPins},
-};
+use esp_println::println;
 use static_cell::StaticCell;
 
-use flow3_rs::{
-    badgelink::BadgeLink,
-    captouch::{captouch_controller, CaptouchHandler},
-    display::Display,
-    imu::ImuHandler,
-    input::{input_controller, InputHandler},
-    leds::init_leds,
-    Flow3r,
-};
+use flow3_rs::{Flow3r, input::InputRunner, captouch::CaptouchRunner};
 
-const READ_BUF_SIZE: usize = 64;
+use crate::flow3r::init_flow3r;
 
-static RNG: StaticCell<Rng> = StaticCell::new();
-static EXECUTOR: StaticCell<Executor> = StaticCell::new();
-//static APP_CORE_EXECUTOR: StaticCell<Executor> = StaticCell::new();
-static CLOCKS: StaticCell<Clocks> = StaticCell::new();
+pub static EXECUTOR: StaticCell<Executor> = StaticCell::new();
 
-pub fn start_runtime(main_function: fn(Flow3r) -> SpawnToken<*mut fn()>) -> ! {
+pub fn start_runtime<S>(main: fn(Flow3r) -> SpawnToken<S>) -> ! 
+{
+    println!("starting runtime");
+    let main: fn(Flow3r) -> SpawnToken<*mut ()> = unsafe { core::mem::transmute(main) };
     let executor = EXECUTOR.init(Executor::new());
     executor.run(|spawner| {
-        spawner.spawn(init_runtime(main_function)).ok();
+        spawner.spawn(init_runtime(main)).unwrap();
     });
 }
 
-#[embassy_executor::task]
-async fn start_app_core(mut cpu_control: CpuControl) -> ! {
-    let mut app_core_function = || {
-        /*let executor = APP_CORE_EXECUTOR.init(Executor::new());
-        executor.run(|spawner| {
-            spawner.spawn(display_refresh()).ok();
-        })*/
-    };
-    let _guard = cpu_control.start_app_core(&mut app_core_function).unwrap();
-    loop {
-        Timer::after(Duration::from_secs(100)).await;
-    }
-}
 
 #[embassy_executor::task]
-async fn init_runtime(main_function: fn(Flow3r) -> SpawnToken<*mut fn()>) {
-    let peripherals = Peripherals::take();
-    let mut system = peripherals.SYSTEM.split();
-    let clocks = CLOCKS.init(ClockControl::boot_defaults(system.clock_control).freeze());
-
-    let mut rtc = Rtc::new(peripherals.RTC_CNTL);
-    let timer_group0 = TimerGroup::new(
-        peripherals.TIMG0,
-        &clocks,
-        &mut system.peripheral_clock_control,
-    );
-    let mut wdt0 = timer_group0.wdt;
-    let timer_group1 = TimerGroup::new(
-        peripherals.TIMG1,
-        &clocks,
-        &mut system.peripheral_clock_control,
-    );
-    let mut wdt1 = timer_group1.wdt;
-
-    // Disable watchdog timers
-    rtc.swd.disable();
-    rtc.rwdt.disable();
-    wdt0.disable();
-    wdt1.disable();
-
-    embassy::init(&clocks, SystemTimer::new(peripherals.SYSTIMER));
-
-    let _cpu_control = CpuControl::new(system.cpu_control);
-
-    // Async requires the GPIO interrupt to wake futures
-    hal::interrupt::enable(
-        hal::peripherals::Interrupt::GPIO,
-        hal::interrupt::Priority::Priority1,
-    )
-    .unwrap();
-
-    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
-    let pulse = PulseControl::new(
-        peripherals.RMT,
-        &mut system.peripheral_clock_control,
-        ClockSource::APB,
-        0,
-        0,
-        0,
-    )
-    .unwrap();
-
-    // Init I2C
-
-    let sda = io.pins.gpio2;
-    let scl = io.pins.gpio1;
-
-    let i2c = I2C::new(
-        peripherals.I2C0,
-        sda,
-        scl,
-        100u32.kHz(),
-        &mut system.peripheral_clock_control,
-        &clocks,
-    );
-
-    // Create shared I2C Bus
-
-    let i2c_busmanager = shared_bus::new_xtensa!(I2C<'static, I2C0> = i2c).unwrap();
-
-    // Init SPI + DMA
-
-    let sck = io.pins.gpio41;
-    let mosi = io.pins.gpio42;
-    let spi = Spi::new_no_cs_no_miso(
-        peripherals.SPI2,
-        sck,
-        mosi,
-        80u32.MHz(),
-        hal::spi::SpiMode::Mode0,
-        &mut system.peripheral_clock_control,
-        &clocks,
-    );
-
-    let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control);
-    let dma_channel = dma.channel0;
-
-    // Init Display backlight control
-
-    let ledc = LEDC::new(
-        peripherals.LEDC,
-        clocks,
-        &mut system.peripheral_clock_control,
-    );
+async fn init_runtime(main: fn(Flow3r) -> SpawnToken<*mut ()>) {
 
-    // Init display early to clear pixel mash from screen
-
-    let mut display = Display::new(
-        spi,
-        dma_channel,
-        ledc,
-        io.pins.gpio46,
-        io.pins.gpio38,
-        io.pins.gpio40,
-    )
-    .await;
-    display.clear().await.unwrap();
-
-    // Init uart
-
-    let uart0_config = uart::config::Config {
-        baudrate: 9600, //115200,
-        data_bits: uart::config::DataBits::DataBits8,
-        parity: uart::config::Parity::ParityNone,
-        stop_bits: uart::config::StopBits::STOP1
-    };
-    let uart0_pins = TxRxPins::new_tx_rx(io.pins.gpio7.into_push_pull_output(), io.pins.gpio6.into_floating_input());
-    let mut uart0 = Uart::new_with_config(peripherals.UART1, Some(uart0_config), Some(uart0_pins), &clocks, &mut system.peripheral_clock_control);
-    uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
-
-    hal::interrupt::enable(
-        hal::peripherals::Interrupt::UART1,
-        hal::interrupt::Priority::Priority2,
-    )
-    .unwrap();
-
-    let uart1_config = uart::config::Config {
-        baudrate: 9600, //115200,
-        data_bits: uart::config::DataBits::DataBits8,
-        parity: uart::config::Parity::ParityNone,
-        stop_bits: uart::config::StopBits::STOP1
-    };
-    let uart1_pins = TxRxPins::new_tx_rx(io.pins.gpio5.into_push_pull_output(), io.pins.gpio4.into_floating_input());
-    let mut uart1 = Uart::new_with_config(peripherals.UART2, Some(uart1_config),Some(uart1_pins), &clocks, &mut system.peripheral_clock_control);
-    uart1.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
-
-    hal::interrupt::enable(
-        hal::peripherals::Interrupt::UART2,
-        hal::interrupt::Priority::Priority2,
-    )
-    .unwrap();
-
-    let rng = RNG.init(Rng::new(peripherals.RNG));
-
-    // Init Flow3r components
-
-    let badgelink = BadgeLink::new(i2c_busmanager.acquire_i2c());
-    let imu = ImuHandler::new(i2c_busmanager.acquire_i2c());
-    let inputs = InputHandler;
-    let captouch = CaptouchHandler;
-    let leds = init_leds(pulse.channel0, io.pins.gpio14);
-
-    let flow3r = Flow3r::new(badgelink, captouch, display, imu, inputs, leds, uart0, uart1, rng);
+    let (flow3r, input_runner, captouch_runner) = init_flow3r().await;
 
     // Spawn background tasks
-
     let spawner = Spawner::for_current_executor().await;
     spawner
-        .spawn(input_controller(
-            i2c_busmanager.acquire_i2c(),
-            io.pins.gpio8,
-            io.pins.gpio0,
-            io.pins.gpio3,
-        ))
-        .ok();
+        .spawn(input_task(input_runner))
+        .unwrap();
     spawner
-        .spawn(captouch_controller(
-            i2c_busmanager.acquire_i2c(),
-            i2c_busmanager.acquire_i2c(),
-            io.pins.gpio16,
-            io.pins.gpio15,
-        ))
-        .ok();
+        .spawn(captouch_task(captouch_runner))
+        .unwrap();
 
     // Hand over to main task
-    spawner.spawn::<*mut fn()>(main_function(flow3r)).ok();
+    spawner.spawn(main(flow3r)).unwrap();
+}
+
+#[embassy_executor::task]
+pub async fn input_task(runner: InputRunner) -> ! {
+    runner.run().await
+}
+
+#[embassy_executor::task]
+pub async fn captouch_task(runner: CaptouchRunner) -> ! {
+    runner.run().await
 }
\ No newline at end of file
diff --git a/flow3-rs-template/.cargo/config.toml b/flow3-rs-template/.cargo/config.toml
new file mode 100644
index 0000000000000000000000000000000000000000..292a084c5761876f8aae9bfe037775753cc38bf9
--- /dev/null
+++ b/flow3-rs-template/.cargo/config.toml
@@ -0,0 +1,13 @@
+[target.xtensa-esp32s3-none-elf]
+runner = "espflash flash --monitor"
+
+[build]
+rustflags = [
+  "-C", "link-arg=-Tlinkall.x",
+  "-C", "link-arg=-nostartfiles",
+]
+
+target = "xtensa-esp32s3-none-elf"
+
+[unstable]
+build-std = ["core"]
diff --git a/Cargo.lock b/flow3-rs-template/Cargo.lock
similarity index 95%
rename from Cargo.lock
rename to flow3-rs-template/Cargo.lock
index d1062911f52e141d008b643622c41bb883cb4b0c..5cd3350a729e5a662da6f0832a58b21e8526d062 100644
--- a/Cargo.lock
+++ b/flow3-rs-template/Cargo.lock
@@ -14,18 +14,18 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "1.0.2"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.72"
+version = "1.0.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
+checksum = "8c6f84b74db2535ebae81eede2f39b947dcbf01d093ae5f791e5dd414a1bf289"
 
 [[package]]
 name = "as-slice"
@@ -50,9 +50,9 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.72"
+version = "0.1.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
+checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -124,9 +124,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.3.3"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
+checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
 
 [[package]]
 name = "bmi270"
@@ -181,9 +181,9 @@ dependencies = [
 
 [[package]]
 name = "critical-section"
-version = "1.1.1"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
+checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
 
 [[package]]
 name = "darling"
@@ -417,9 +417,9 @@ dependencies = [
 
 [[package]]
 name = "embedded-graphics"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd2a8e0250a7e1212828166b01eed0219e488ebb2599f44624a29c9bd249f397"
+checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0"
 dependencies = [
  "az",
  "byteorder",
@@ -556,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "05d4498ddbbbf9a21e64f9269d2b4dd4059c34863ff54c702fb99e435f967767"
 dependencies = [
  "basic-toml",
- "bitflags 2.3.3",
+ "bitflags 2.4.0",
  "cfg-if",
  "critical-section",
  "embassy-futures",
@@ -709,9 +709,12 @@ name = "flow3-rs-rt"
 version = "0.1.0"
 dependencies = [
  "embassy-executor",
+ "embassy-sync",
  "embassy-time",
+ "esp-println",
  "esp32s3-hal",
  "flow3-rs",
+ "lazy_static",
  "shared-bus",
  "static_cell",
 ]
@@ -873,7 +876,7 @@ dependencies = [
  "atomic-polyfill 0.1.11",
  "hash32",
  "rustc_version",
- "spin",
+ "spin 0.9.8",
  "stable_deref_trait",
 ]
 
@@ -899,6 +902,15 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
+
 [[package]]
 name = "lock_api"
 version = "0.4.10"
@@ -998,9 +1010,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.10"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
+checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
 
 [[package]]
 name = "pin-utils"
@@ -1078,9 +1090,9 @@ checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
 
 [[package]]
 name = "regex"
-version = "1.9.1"
+version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
+checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1090,9 +1102,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.3.4"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
+checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1143,18 +1155,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
 
 [[package]]
 name = "serde"
-version = "1.0.181"
+version = "1.0.183"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890"
+checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.181"
+version = "1.0.183"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed"
+checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1175,7 +1187,7 @@ checksum = "8bb5650c146f3186332c5da30ff542f7d1ff0c2410346cd861f34fa836dc0d84"
 dependencies = [
  "embedded-hal 0.2.7",
  "nb 1.1.0",
- "spin",
+ "spin 0.9.8",
  "xtensa-lx",
 ]
 
@@ -1210,6 +1222,12 @@ dependencies = [
  "managed",
 ]
 
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
 [[package]]
 name = "spin"
 version = "0.9.8"
@@ -1381,9 +1399,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 
 [[package]]
 name = "winnow"
-version = "0.5.3"
+version = "0.5.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807"
+checksum = "83817bbecf72c73bad717ee86820ebf286203d2e04c3951f3cd538869c897364"
 dependencies = [
  "memchr",
 ]
@@ -1396,7 +1414,7 @@ checksum = "9490addc0a1edd86e571a9ed8063f33d8224f981e61bbf72279671ed0cb4bb7c"
 dependencies = [
  "bare-metal",
  "mutex-trait",
- "spin",
+ "spin 0.9.8",
 ]
 
 [[package]]
diff --git a/template/Cargo.toml b/flow3-rs-template/Cargo.toml
similarity index 89%
rename from template/Cargo.toml
rename to flow3-rs-template/Cargo.toml
index d6a7ab6dd3cf4adba87b0def0fddfa4cbd7202f6..882ef5778e7dbf8bf463145a85dc7c1770bcefe3 100644
--- a/template/Cargo.toml
+++ b/flow3-rs-template/Cargo.toml
@@ -20,16 +20,16 @@ embedded-dma = "0.2.0"
 embedded-graphics = "0.8.0"
 embedded-graphics-framebuf = "0.5.0"
 embedded-hal = "0.2.7"
-embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
+embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
 embedded-hal-async = "0.2.0-alpha.1"
 embedded-hal-bus = "0.1.0-alpha.2"
 esp-backtrace = { version = "0.7.0", features = ["esp32s3", "panic-handler", "exception-handler", "print-uart"] }
 esp-println = { version = "0.5.0", features = ["esp32s3"] }
-hal = { package = "esp32s3-hal", version = "0.10.0", features = ["embassy", "async", "embassy-time", "embassy-time-systick"] }
+hal = { package = "esp32s3-hal", version = "0.155.0", features = ["embassy", "async", "embassy-time", "embassy-time-systick"] }
 heapless = "0.7.16"
 smart-leds = "0.3.0"
 smoltcp = { version = "0.10.0", default-features = false }
 static_cell = "1.2.0"
 tinybmp = "0.5.0"
-flow3-rs = { path = "../" }
+flow3-rs = { path = "../flow3-rs" }
 flow3-rs-rt = { path = "../flow3-rs-rt" }
\ No newline at end of file
diff --git a/flow3-rs-template/rust-toolchain.toml b/flow3-rs-template/rust-toolchain.toml
new file mode 100644
index 0000000000000000000000000000000000000000..a2f5ab508d236f9d696f88ceafe84e1c6b51e9a9
--- /dev/null
+++ b/flow3-rs-template/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "esp"
diff --git a/template/src/demo_tasks.rs b/flow3-rs-template/src/demo_tasks.rs
similarity index 96%
rename from template/src/demo_tasks.rs
rename to flow3-rs-template/src/demo_tasks.rs
index 575f96ace646ac636e7c7776de44a01542c090ba..6cea41bda8b0ded42213e5de81393fb77ad3a696 100644
--- a/template/src/demo_tasks.rs
+++ b/flow3-rs-template/src/demo_tasks.rs
@@ -1,4 +1,3 @@
-use flow3_rs::{captouch::CaptouchHandler, display::Display, imu::ImuHandler, badgelink::{BadgeLink, badgenet::{BadgenetUartLeft, BadgenetUartRight, start_badgenet_left, start_badgenet_right}}};
 use embassy_executor::Spawner;
 use embassy_futures::select::{select, select3, Either, Either3};
 use embassy_net::{udp::{UdpSocket, PacketMetadata}, Ipv6Address, Stack, StaticConfigV6, Config, Ipv6Cidr};
@@ -21,26 +20,31 @@ use tinybmp::Bmp;
 
 use smart_leds::SmartLedsWrite;
 
-use flow3_rs::input::InputHandler;
+use flow3_rs::{display::Display, imu::ImuHandler, badgelink::{BadgeLink, badgenet::{BadgenetUartLeft, BadgenetUartRight, start_badgenet_left, start_badgenet_right}}, input::Inputs, captouch::Captouch};
 
 #[embassy_executor::task]
 pub async fn leds_fade(mut leds: flow3_rs::leds::Leds) -> ! {
     let mut b = (30, false);
 
+    println!("led task running");
+
     loop {
+        println!("led loop entry");
         leds.write(smart_leds::brightness(
             smart_leds::gamma([smart_leds::colors::VIOLET; 40].into_iter()),
             b.0,
         ))
         .expect("failed to set leds");
 
+        println!("led loop");
+
         Timer::after(Duration::from_millis(30)).await;
         b = flow3_rs::leds::brightness_fade_in_out(b, 30, 0);
     }
 }
 
 pub async fn display_demo(display: &mut flow3_rs::display::Display) {
-    let input = InputHandler;
+    let input = Inputs;
     let mut inputs = input.split();
 
     display.set_backlight(100).unwrap();
@@ -115,7 +119,7 @@ pub async fn draw_start_screen(display: &mut Display) {
 }
 
 pub async fn imu_demo(display: &mut Display, imu: &mut ImuHandler) {
-    let input = InputHandler;
+    let input = Inputs;
     let mut inputs = input.split();
 
     let circle = Circle::with_center(display.bounding_box().center(), 20);
@@ -155,10 +159,10 @@ pub async fn imu_demo(display: &mut Display, imu: &mut ImuHandler) {
 }
 
 pub async fn captouch_demo(display: &mut Display) {
-    let input = InputHandler;
+    let input = Inputs;
     let mut inputs = input.split();
 
-    let captouch = CaptouchHandler;
+    let captouch = Captouch;
     let top = captouch.top_petals();
     let bot = captouch.bottom_petals();
 
diff --git a/flow3-rs-template/src/main.rs b/flow3-rs-template/src/main.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a91cdf1c4979f031e8657ebd18c95877a2dbd83b
--- /dev/null
+++ b/flow3-rs-template/src/main.rs
@@ -0,0 +1,52 @@
+#![no_std]
+#![no_main]
+#![feature(type_alias_impl_trait)]
+#![feature(async_fn_in_trait)]
+
+mod demo_tasks;
+mod ui;
+
+use demo_tasks::draw_start_screen;
+use embassy_executor::{Spawner, Executor};
+use embassy_time::{Duration, Timer};
+
+use esp_backtrace as _;
+use esp_println::println;
+use flow3_rs_rt::{init_flow3r, input_task, captouch_task};
+use hal::prelude::*;
+
+use crate::ui::main_menu::main_menu;
+
+#[entry]
+fn runtime() -> ! {
+    let executor = flow3_rs_rt::EXECUTOR.init(Executor::new());
+    executor.run(|spawner| {
+        spawner.spawn(main()).unwrap();
+    });
+}
+
+#[embassy_executor::task]
+async fn main() -> ! {
+    let (mut flow3r, input_runner, captouch_runner) = init_flow3r().await;
+
+    // Spawn background tasks
+    let spawner = Spawner::for_current_executor().await;
+    spawner
+        .spawn(input_task(input_runner))
+        .unwrap();
+    spawner
+        .spawn(captouch_task(captouch_runner))
+        .unwrap();
+
+    println!("started main");
+    // draw_start_screen(&mut flow3r.take_display()).await;
+
+    let spawner = Spawner::for_current_executor().await;
+    spawner.spawn(demo_tasks::leds_fade(flow3r.take_leds())).unwrap();
+
+    println!("started led task");
+
+    Timer::after(Duration::from_secs(2)).await;
+
+    main_menu(flow3r).await
+}
diff --git a/template/src/ui/main_menu.rs b/flow3-rs-template/src/ui/main_menu.rs
similarity index 93%
rename from template/src/ui/main_menu.rs
rename to flow3-rs-template/src/ui/main_menu.rs
index 6890b74147da428889476b0d193e6062d65188da..3957be5110401fc7583a27212e44df642b686d22 100644
--- a/template/src/ui/main_menu.rs
+++ b/flow3-rs-template/src/ui/main_menu.rs
@@ -7,12 +7,14 @@ use embedded_graphics::{
     text::Text,
 };
 
-use flow3_rs::{display::Display, input::InputHandler, imu::ImuHandler};
+use flow3_rs::{display::Display, imu::ImuHandler, Flow3r};
 
 use crate::demo_tasks::{display_demo, imu_demo, captouch_demo};
 
-pub async fn main_menu(mut display: Display, inputs: InputHandler, mut imu: ImuHandler) -> ! {
-    let mut inputs = inputs.split();
+pub async fn main_menu(mut flow3r: Flow3r) -> ! {
+    let mut inputs = flow3r.take_inputs().split();
+    let mut display = flow3r.take_display();
+    let mut imu = flow3r.take_imu();
 
     let apps = ["input_test", "imu_test", "captouch_test"];
     let mut selected = 0usize;
diff --git a/template/src/ui/mod.rs b/flow3-rs-template/src/ui/mod.rs
similarity index 100%
rename from template/src/ui/mod.rs
rename to flow3-rs-template/src/ui/mod.rs
diff --git a/flow3-rs/.cargo/config.toml b/flow3-rs/.cargo/config.toml
new file mode 100644
index 0000000000000000000000000000000000000000..292a084c5761876f8aae9bfe037775753cc38bf9
--- /dev/null
+++ b/flow3-rs/.cargo/config.toml
@@ -0,0 +1,13 @@
+[target.xtensa-esp32s3-none-elf]
+runner = "espflash flash --monitor"
+
+[build]
+rustflags = [
+  "-C", "link-arg=-Tlinkall.x",
+  "-C", "link-arg=-nostartfiles",
+]
+
+target = "xtensa-esp32s3-none-elf"
+
+[unstable]
+build-std = ["core"]
diff --git a/flow3-rs/Cargo.lock b/flow3-rs/Cargo.lock
new file mode 100644
index 0000000000000000000000000000000000000000..5f71d30d523e4b5d5267330b869a27fa1b14f423
--- /dev/null
+++ b/flow3-rs/Cargo.lock
@@ -0,0 +1,1405 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ad7147"
+version = "0.1.0"
+dependencies = [
+ "byte-slice-cast 1.2.2",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "heapless",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
+
+[[package]]
+name = "as-slice"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
+dependencies = [
+ "generic-array 0.12.4",
+ "generic-array 0.13.3",
+ "generic-array 0.14.7",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "as-slice"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516"
+dependencies = [
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "atomic-polyfill"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "atomic-polyfill"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "atomic-pool"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58c5fc22e05ec2884db458bf307dc7b278c9428888d2b6e6fad9c0ae7804f5f6"
+dependencies = [
+ "as-slice 0.1.5",
+ "as-slice 0.2.1",
+ "atomic-polyfill 1.0.3",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "az"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
+
+[[package]]
+name = "bare-metal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
+
+[[package]]
+name = "basic-toml"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bitfield"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
+
+[[package]]
+name = "bmi270"
+version = "0.1.0"
+dependencies = [
+ "embedded-hal 0.2.7",
+ "fixedvec",
+]
+
+[[package]]
+name = "byte-slice-cast"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3"
+
+[[package]]
+name = "byte-slice-cast"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
+
+[[package]]
+name = "bytemuck"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "core-isa-parser"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23ec98e54b735872e54b2335c2e5a5c7fa7d9c3bfd45500f75280f84089a0083"
+dependencies = [
+ "anyhow",
+ "enum-as-inner",
+ "regex",
+ "strum 0.24.1",
+ "strum_macros 0.24.3",
+]
+
+[[package]]
+name = "critical-section"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
+
+[[package]]
+name = "darling"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
+dependencies = [
+ "darling_core 0.13.4",
+ "darling_macro 0.13.4",
+]
+
+[[package]]
+name = "darling"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
+dependencies = [
+ "darling_core 0.20.3",
+ "darling_macro 0.20.3",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
+dependencies = [
+ "darling_core 0.13.4",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
+dependencies = [
+ "darling_core 0.20.3",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "display-interface"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7517c040926d7b02b111884aa089177db80878533127f7c1b480d852c5fb4112"
+
+[[package]]
+name = "display-interface"
+version = "0.5.0-alpha.1"
+dependencies = [
+ "async-trait",
+ "embedded-dma",
+]
+
+[[package]]
+name = "display-interface-spi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "489378ad054862146fbd1f09f51d585ccbe4bd1e2feadcda2a13ac33f840e1a5"
+dependencies = [
+ "byte-slice-cast 0.3.5",
+ "display-interface 0.4.1",
+ "embedded-hal 0.2.7",
+]
+
+[[package]]
+name = "embassy-executor"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acebf176f4622fd87c7200b568ee32d5b435e3a4d58e39355ce0837b45139eca"
+dependencies = [
+ "atomic-polyfill 1.0.3",
+ "critical-section",
+ "embassy-macros",
+ "embassy-time",
+ "futures-util",
+ "static_cell",
+]
+
+[[package]]
+name = "embassy-futures"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e5367165d347c039360f784812f493b001583ab6a3dd8622f4ce9c30374ec3"
+
+[[package]]
+name = "embassy-macros"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf2e5e33cc670fcdf208c0fdf8ee93493681658562fb1c50ba8ceb09591e0ff"
+dependencies = [
+ "darling 0.13.4",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "embassy-net"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d812646c1c50452d77293e05bf2eca13c23803447cdf9bbbcf820588f4c9879"
+dependencies = [
+ "as-slice 0.2.1",
+ "atomic-polyfill 1.0.3",
+ "atomic-pool",
+ "embassy-net-driver",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-io",
+ "embedded-nal-async",
+ "futures",
+ "generic-array 0.14.7",
+ "heapless",
+ "managed",
+ "smoltcp",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "embassy-net-badgelink"
+version = "0.1.0"
+dependencies = [
+ "embassy-futures",
+ "embassy-net-driver-channel",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "esp-println",
+ "esp32s3-hal",
+ "heapless",
+ "serial-line-ip",
+]
+
+[[package]]
+name = "embassy-net-driver"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6a4985a5dab4cb55d09703bfdd7d74f58c12c6e889fd3cbb40ea40462a976e"
+
+[[package]]
+name = "embassy-net-driver-channel"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be7993940e31beda742ce0341fde6d64f93ec28926612bdc8ca4f1bf7d2fbcc0"
+dependencies = [
+ "embassy-futures",
+ "embassy-net-driver",
+ "embassy-sync",
+]
+
+[[package]]
+name = "embassy-sync"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0dad296a6f70bfdc32ef52442a31f98c28e1608893c1cecc9b6f419bab005a0"
+dependencies = [
+ "cfg-if",
+ "critical-section",
+ "embedded-io",
+ "futures-util",
+ "heapless",
+]
+
+[[package]]
+name = "embassy-time"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a0461fa8de2cf03c4363a38f439a5d7e4cc16cd41947b51663ff4b2f155b902"
+dependencies = [
+ "atomic-polyfill 1.0.3",
+ "cfg-if",
+ "critical-section",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "futures-util",
+ "heapless",
+]
+
+[[package]]
+name = "embedded-can"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438"
+dependencies = [
+ "nb 1.1.0",
+]
+
+[[package]]
+name = "embedded-dma"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446"
+dependencies = [
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "embedded-graphics"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd2a8e0250a7e1212828166b01eed0219e488ebb2599f44624a29c9bd249f397"
+dependencies = [
+ "az",
+ "byteorder",
+ "embedded-graphics-core",
+ "float-cmp",
+ "micromath",
+]
+
+[[package]]
+name = "embedded-graphics-core"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044"
+dependencies = [
+ "az",
+ "byteorder",
+]
+
+[[package]]
+name = "embedded-graphics-framebuf"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22354420f68727fa24d1e2741dae1e9a041065e80fb63b35a8d19c647a85be76"
+dependencies = [
+ "embedded-dma",
+ "embedded-graphics",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
+dependencies = [
+ "nb 0.1.3",
+ "void",
+]
+
+[[package]]
+name = "embedded-hal"
+version = "1.0.0-alpha.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7724ebabcadfeb15920571dd727bc8ccde8586e52f2890bdb8182fdf42c3ff2"
+
+[[package]]
+name = "embedded-hal-async"
+version = "0.2.0-alpha.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "918285ec7b18edb024d4adc64f6f16cdc7c4d72eadfc85c3313d1e0ff40e0229"
+dependencies = [
+ "embedded-hal 1.0.0-alpha.11",
+]
+
+[[package]]
+name = "embedded-hal-bus"
+version = "0.1.0-alpha.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b36407d17c7b9de899bf9ff24d497d7bb02e52f2385045632f5e6b50187e954"
+dependencies = [
+ "critical-section",
+ "embedded-hal 1.0.0-alpha.11",
+]
+
+[[package]]
+name = "embedded-hal-nb"
+version = "1.0.0-alpha.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a09e4c3f8a54e60803405e1cc17e36c963ab32e654f8d6bb49d48cd8116360d7"
+dependencies = [
+ "embedded-hal 1.0.0-alpha.11",
+ "nb 1.1.0",
+]
+
+[[package]]
+name = "embedded-io"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
+
+[[package]]
+name = "embedded-nal"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db9efecb57ab54fa918730f2874d7d37647169c50fa1357fecb81abee840b113"
+dependencies = [
+ "heapless",
+ "nb 1.1.0",
+ "no-std-net 0.5.0",
+]
+
+[[package]]
+name = "embedded-nal-async"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27ce84f518ca912777ec143db235f4d615e3bf8d4e46d507d6ef12daf5b1df98"
+dependencies = [
+ "embedded-io",
+ "embedded-nal",
+ "heapless",
+ "no-std-net 0.6.0",
+]
+
+[[package]]
+name = "enum-as-inner"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "esp-backtrace"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b151ef7db21143b1a3b7a378c16d97ae13d0a5e3cb9682ed1f11bba821cce42d"
+dependencies = [
+ "esp-println",
+]
+
+[[package]]
+name = "esp-hal-common"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9bb3220d63ba0ec4e9b1846edd47e8da3a884c6557b3ba7398494c56a93de35"
+dependencies = [
+ "basic-toml",
+ "bitfield",
+ "bitflags 2.3.3",
+ "cfg-if",
+ "critical-section",
+ "embassy-futures",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-can",
+ "embedded-dma",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "embedded-hal-nb",
+ "esp-hal-procmacros",
+ "esp-synopsys-usb-otg",
+ "esp32s3",
+ "fugit",
+ "lock_api",
+ "log",
+ "nb 1.1.0",
+ "paste",
+ "serde",
+ "strum 0.25.0",
+ "usb-device",
+ "void",
+ "xtensa-lx",
+ "xtensa-lx-rt",
+]
+
+[[package]]
+name = "esp-hal-procmacros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "042d5a1ef0e01d6de045972779e4aced3a10e6170169a5cb2de7bef31802e28a"
+dependencies = [
+ "darling 0.20.3",
+ "proc-macro-crate",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "esp-hal-smartled"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd1c4e28c17b0b6f7aac56a5e27c71b5e5ece3e81b49fbcfa81be2ccb9cc2f82"
+dependencies = [
+ "esp-hal-common",
+ "fugit",
+ "smart-leds-trait",
+]
+
+[[package]]
+name = "esp-println"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af6a511d37dba5fb8f01bf5485bc619a1a1959e1aaf666a7597df8fe615a0816"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "esp-synopsys-usb-otg"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc6734e87e7b86858f7884649deae6bf634d1e6f5b2d078e457cf4d72c541ec"
+dependencies = [
+ "critical-section",
+ "embedded-hal 0.2.7",
+ "usb-device",
+ "vcell",
+]
+
+[[package]]
+name = "esp32s3"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e482df6923df18ccd05ab80b54be5af32497f112f5b60ee05dc9d57562e68c"
+dependencies = [
+ "critical-section",
+ "vcell",
+ "xtensa-lx",
+]
+
+[[package]]
+name = "esp32s3-hal"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cd8d75d35f3286a1e1126758527b0d8ef1d98f6a137b77fed066800f74bc9c9"
+dependencies = [
+ "bare-metal",
+ "embassy-time",
+ "embedded-hal 0.2.7",
+ "embedded-hal-async",
+ "esp-hal-common",
+]
+
+[[package]]
+name = "fixedvec"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b395ef2adf62bdeefcd1b59ad0dd2225c6c333ec79656ea79ac5285c46d051ea"
+
+[[package]]
+name = "float-cmp"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "flow3-rs"
+version = "0.1.0"
+dependencies = [
+ "ad7147",
+ "bmi270",
+ "byte-slice-cast 1.2.2",
+ "display-interface 0.5.0-alpha.1",
+ "embassy-executor",
+ "embassy-futures",
+ "embassy-net",
+ "embassy-net-badgelink",
+ "embassy-sync",
+ "embassy-time",
+ "embedded-dma",
+ "embedded-graphics",
+ "embedded-graphics-framebuf",
+ "embedded-hal 0.2.7",
+ "embedded-hal 1.0.0-alpha.11",
+ "embedded-hal-async",
+ "embedded-hal-bus",
+ "esp-backtrace",
+ "esp-hal-smartled",
+ "esp-println",
+ "esp32s3-hal",
+ "gc9a01",
+ "heapless",
+ "port-expander",
+ "shared-bus",
+ "smart-leds",
+ "smoltcp",
+ "static_cell",
+ "tinybmp",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "fugit"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
+dependencies = [
+ "gcd",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+
+[[package]]
+name = "futures-io"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+
+[[package]]
+name = "futures-task"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+
+[[package]]
+name = "futures-util"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+dependencies = [
+ "futures-core",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "gc9a01"
+version = "0.1.0"
+dependencies = [
+ "display-interface 0.5.0-alpha.1",
+ "display-interface-spi",
+ "embedded-dma",
+ "embedded-graphics-core",
+ "embedded-hal 0.2.7",
+]
+
+[[package]]
+name = "gcd"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+
+[[package]]
+name = "heapless"
+version = "0.7.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
+dependencies = [
+ "atomic-polyfill 0.1.11",
+ "hash32",
+ "rustc_version",
+ "spin",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "indexmap"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+
+[[package]]
+name = "managed"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "micromath"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39617bc909d64b068dcffd0e3e31679195b5576d0c83fadc52690268cc2b2b55"
+
+[[package]]
+name = "minijinja"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "359c4820413be7706e93999171652e140578384f85faac14cb22d350bd0fbabf"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "mutex-trait"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4bb1638d419e12f8b1c43d9e639abd0d1424285bdea2f76aa231e233c63cd3a"
+
+[[package]]
+name = "nb"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
+dependencies = [
+ "nb 1.1.0",
+]
+
+[[package]]
+name = "nb"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
+
+[[package]]
+name = "no-std-net"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bcece43b12349917e096cddfa66107277f123e6c96a5aea78711dc601a47152"
+
+[[package]]
+name = "no-std-net"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
+
+[[package]]
+name = "num-traits"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "paste"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "port-expander"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3facaed79c04a8116d7d83d5e0be5e449986428716e8d089e426366b7a20282e"
+dependencies = [
+ "embedded-hal 0.2.7",
+ "shared-bus",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
+dependencies = [
+ "once_cell",
+ "toml_edit",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r0"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
+
+[[package]]
+name = "regex"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
+
+[[package]]
+name = "rgb"
+version = "0.8.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
+
+[[package]]
+name = "serde"
+version = "1.0.183"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.183"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "serial-line-ip"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08a0b86bcdab6b15029ff7e37ae8acdadbf5d48e070ec5a067aa5c31e306f958"
+
+[[package]]
+name = "shared-bus"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bb5650c146f3186332c5da30ff542f7d1ff0c2410346cd861f34fa836dc0d84"
+dependencies = [
+ "embedded-hal 0.2.7",
+ "nb 1.1.0",
+ "spin",
+ "xtensa-lx",
+]
+
+[[package]]
+name = "smart-leds"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38dd45fa275f70b4110eac5f5182611ad384f88bb22b68b9a9c3cafd7015290b"
+dependencies = [
+ "smart-leds-trait",
+]
+
+[[package]]
+name = "smart-leds-trait"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3"
+dependencies = [
+ "rgb",
+]
+
+[[package]]
+name = "smoltcp"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d2e3a36ac8fea7b94e666dfa3871063d6e0a5c9d5d4fec9a1a6b7b6760f0229"
+dependencies = [
+ "bitflags 1.3.2",
+ "byteorder",
+ "cfg-if",
+ "heapless",
+ "managed",
+]
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "static_cell"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49cd323fc21eb534f903ee78d781d622099f9716c5b408ed23bcf39f8f1651c0"
+dependencies = [
+ "atomic-polyfill 1.0.3",
+]
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+
+[[package]]
+name = "strum"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
+dependencies = [
+ "strum_macros 0.25.2",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.25.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.28",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tinybmp"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "197cc000e382175ff15abd9c54c694ef80ef20cb07e7f956c71e3ea97fc8dc60"
+dependencies = [
+ "embedded-graphics",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
+
+[[package]]
+name = "toml_edit"
+version = "0.19.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+
+[[package]]
+name = "usb-device"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508"
+
+[[package]]
+name = "vcell"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+
+[[package]]
+name = "winnow"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "xtensa-lx"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9490addc0a1edd86e571a9ed8063f33d8224f981e61bbf72279671ed0cb4bb7c"
+dependencies = [
+ "bare-metal",
+ "mutex-trait",
+ "spin",
+]
+
+[[package]]
+name = "xtensa-lx-rt"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f68fea36eb8e2d5ff4c99d367527f4a56e484b16c5e84abf4195988bd845a3fc"
+dependencies = [
+ "bare-metal",
+ "core-isa-parser",
+ "minijinja",
+ "r0",
+ "xtensa-lx-rt-proc-macros",
+]
+
+[[package]]
+name = "xtensa-lx-rt-proc-macros"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3283815e334d3e5d21868dc3c7140720b2a784238289b1127b67908c89404b79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
diff --git a/Cargo.toml b/flow3-rs/Cargo.toml
similarity index 65%
rename from Cargo.toml
rename to flow3-rs/Cargo.toml
index c1f7f4cd14f86547c718250c6ef701805b5cf786..5f0191f8b20a27d9d1b5f93e1f3cf9a16e48a3f8 100644
--- a/Cargo.toml
+++ b/flow3-rs/Cargo.toml
@@ -5,41 +5,32 @@ edition = "2021"
 authors = ["zdmx <hi@zdmx.me>"]
 
 [dependencies]
-ad7147 = { path = "./vendor/ad7147" }
-bmi270 = { path = "./vendor/bmi270" }
+ad7147 = { path = "../vendor/ad7147" }
+bmi270 = { path = "../vendor/bmi270" }
 byte-slice-cast = { version = "1.2.2", default-features = false }
-display-interface = { path = "./vendor/display-interface", features = ["nightly", "async", "dma"] }
+display-interface = { path = "../vendor/display-interface", features = ["nightly", "async", "dma"] }
 embassy-executor = { version = "0.2.0", features = ["nightly", "arch-xtensa", "executor-thread", "integrated-timers"] }
 embassy-futures = "0.1.0"
 embassy-net = { version = "0.1.0", features = ["medium-ethernet", "udp", "proto-ipv6", "nightly", "unstable-traits"] }
-embassy-net-badgelink = { path = "./embassy-net-badgelink" }
+embassy-net-badgelink = { path = "../embassy-net-badgelink" }
 embassy-sync = "0.2.0"
-embassy-time = { version = "=0.1.1", features = ["nightly", "unstable-traits"] }
+embassy-time = { version = "=0.1.2", features = ["nightly", "unstable-traits"] }
 embedded-dma = "0.2.0"
 embedded-graphics = "0.8.0"
 embedded-graphics-framebuf = "0.5.0"
 embedded-hal = "0.2.7"
-embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
+embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
 embedded-hal-async = "0.2.0-alpha.1"
 embedded-hal-bus = "0.1.0-alpha.2"
 esp-backtrace = { version = "0.7.0", features = ["esp32s3", "panic-handler", "exception-handler", "print-uart"] }
-esp-hal-smartled = { version = "0.3.0", features = ["esp32s3"] }
+esp-hal-smartled = { version = "0.4.0", features = ["esp32s3"] }
 esp-println = { version = "0.5.0", features = ["esp32s3"] }
-gc9a01 = { path = "./vendor/gc9a01" }
-hal = { package = "esp32s3-hal", version = "0.10.0", features = ["embassy", "async", "embassy-time", "embassy-time-systick"] }
+gc9a01 = { path = "../vendor/gc9a01" }
+hal = { package = "esp32s3-hal", version = "0.11.0", features = ["embassy", "async", "embassy-time", "embassy-time-systick"] }
 heapless = "0.7.16"
 port-expander = "0.4.0"
 shared-bus = { version = "0.3.0", features = ["xtensa"] }
 smart-leds = "0.3.0"
 smoltcp = { version = "0.10.0", default-features = false }
 static_cell = "1.2.0"
-tinybmp = "0.5.0"
-
-[workspace]
-members = [
-    "vendor/ad7147",
-    "vendor/bmi270",
-    "embassy-net-badgelink",
-    "flow3-rs-rt",
-    "template"
-]
\ No newline at end of file
+tinybmp = "0.5.0"
\ No newline at end of file
diff --git a/flow3-rs/README.md b/flow3-rs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a5eceed34993124f1d023f89128159efe71c8a3b
--- /dev/null
+++ b/flow3-rs/README.md
@@ -0,0 +1,6 @@
+## flow3-rs crate
+
+This crate contains the main Board Support for the Flow3r.
+It is in many parts built on async, so it needs an async runtime, however it should be runtime-independent by itself.
+`flow3-rs-rt` provides an embassy-based runtime for use with this bsp-crate.
+For most use-cases, you should use `flow3-rs` with the `flow3-rs-rt`.
\ No newline at end of file
diff --git a/flow3-rs/rust-toolchain.toml b/flow3-rs/rust-toolchain.toml
new file mode 100644
index 0000000000000000000000000000000000000000..a2f5ab508d236f9d696f88ceafe84e1c6b51e9a9
--- /dev/null
+++ b/flow3-rs/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "esp"
diff --git a/src/badgelink/badgenet.rs b/flow3-rs/src/badgelink/badgenet.rs
similarity index 100%
rename from src/badgelink/badgenet.rs
rename to flow3-rs/src/badgelink/badgenet.rs
diff --git a/src/badgelink/mod.rs b/flow3-rs/src/badgelink/mod.rs
similarity index 100%
rename from src/badgelink/mod.rs
rename to flow3-rs/src/badgelink/mod.rs
diff --git a/src/captouch.rs b/flow3-rs/src/captouch.rs
similarity index 91%
rename from src/captouch.rs
rename to flow3-rs/src/captouch.rs
index 108ff1636fb09737c987a89ad611b40003b2c900..c590eef99d44e98a1a8ce0c1af065392f0ea5fd1 100644
--- a/src/captouch.rs
+++ b/flow3-rs/src/captouch.rs
@@ -31,88 +31,9 @@ static PETALS: Mutex<CriticalSectionRawMutex, [Flow3rPetal; 10]> = Mutex::new([
     Flow3rPetal::new(Flow3rCaptouchController::BOTTOM),
 ]);
 
+pub struct Captouch;
 
-#[derive(Debug, Clone, Copy)]
-enum Flow3rPetal {
-    TOP {
-        ccw: Flow3rPetalPart,
-        base: Flow3rPetalPart,
-        cw: Flow3rPetalPart,
-    },
-    BOTTOM {
-        base: Flow3rPetalPart,
-        tip: Flow3rPetalPart,
-    },
-}
-
-impl Flow3rPetal {
-    const fn new(pos: Flow3rCaptouchController) -> Flow3rPetal {
-        match pos {
-            Flow3rCaptouchController::TOP => Self::TOP {
-                ccw: Flow3rPetalPart {
-                    pressed: false,
-                    raw: 0,
-                },
-                base: Flow3rPetalPart {
-                    pressed: false,
-                    raw: 0,
-                },
-                cw: Flow3rPetalPart {
-                    pressed: false,
-                    raw: 0,
-                },
-            },
-            Flow3rCaptouchController::BOTTOM => Self::BOTTOM {
-                base: Flow3rPetalPart {
-                    pressed: false,
-                    raw: 0,
-                },
-                tip: Flow3rPetalPart {
-                    pressed: false,
-                    raw: 0,
-                },
-            },
-        }
-    }
-
-    pub fn pressed(&self) -> bool {
-        match self {
-            Flow3rPetal::TOP {
-                ccw,
-                base,
-                cw,
-            } => ccw.pressed | base.pressed | cw.pressed,
-            Flow3rPetal::BOTTOM { base, tip } => base.pressed | tip.pressed,
-        }
-    }
-
-    pub fn position(&self) -> i32 {
-        match self {
-            Flow3rPetal::TOP {
-                ccw,
-                base,
-                cw,
-            } => (ccw.raw as i32 + cw.raw as i32) / 2 - base.raw as i32,
-            Flow3rPetal::BOTTOM {base, tip } => base.raw as i32 + tip.raw as i32 / 2,
-        }
-    }
-}
-
-#[derive(Debug, Default, Clone, Copy)]
-struct Flow3rPetalPart {
-    pressed: bool,
-    raw: u16,
-}
-
-#[derive(Debug, Clone, Copy)]
-enum Flow3rCaptouchController {
-    BOTTOM,
-    TOP,
-}
-
-pub struct CaptouchHandler;
-
-impl CaptouchHandler {
+impl Captouch {
     pub fn top_petals(&self) -> TopPetals {
         TopPetals {
             petal0: Petal::new(0),
@@ -170,6 +91,53 @@ pub struct BottomPetals {
     pub petal9: Petal,
 }
 
+pub struct CaptouchRunner {
+    i2c_bot: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
+    i2c_top: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
+    cap_bot_int: Gpio16<Unknown>,
+    cap_top_int: Gpio15<Unknown>,
+}
+
+impl CaptouchRunner {
+    pub fn new(
+        i2c_bot: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
+        i2c_top: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
+        cap_bot_int: Gpio16<Unknown>,
+        cap_top_int: Gpio15<Unknown>, 
+    ) -> Self {
+        Self { i2c_bot, i2c_top, cap_bot_int, cap_top_int }
+    }
+
+    pub async fn run(
+        self
+    ) -> ! {
+        let mut cap_bot_int = self.cap_bot_int.into_pull_up_input();
+        let mut cap_top_int = self.cap_top_int.into_pull_up_input();
+        let (mut ad7147_bot, mut ad7147_top) = init_captouch(self.i2c_bot, self.i2c_top).unwrap();
+
+        let device_id = ad7147_bot.read_device_id().unwrap();
+        println!("captouch bot device id: {:016b}", device_id);
+        let device_id = ad7147_top.read_device_id().unwrap();
+        println!("captouch top device id: {:016b}", device_id);
+        println!("initialized captouch");
+        loop {
+            match select(cap_bot_int.wait_for_low(), cap_top_int.wait_for_low()).await {
+                Either::First(_) => {
+                    let _ = ad7147_bot.read_interrupt_registers().unwrap();
+                    let measurements_bot = ad7147_bot.read_all_stages().unwrap();
+                    // println!("pad 0: {}, {}, {}, {}", measurements_bot[0], measurements_bot[1], interrupts[1] & (1 << 0) != 0, interrupts[1] & (1 << 1) != 0);
+                    update_petals_bot(measurements_bot).await;
+                }
+                Either::Second(_) => {
+                    let _ = ad7147_top.read_interrupt_registers().unwrap();
+                    let measurements_top = ad7147_top.read_all_stages().unwrap();
+                    update_petals_top(measurements_top).await;
+                }
+            }
+        }
+    }
+}
+
 fn init_captouch(
     i2c_bot: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
     i2c_top: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
@@ -418,37 +386,82 @@ fn init_captouch(
     ))
 }
 
-#[embassy_executor::task]
-pub async fn captouch_controller(
-    i2c_bot: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
-    i2c_top: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
-    cap_bot_int: Gpio16<Unknown>,
-    cap_top_int: Gpio15<Unknown>,
-) -> ! {
-    let mut cap_bot_int = cap_bot_int.into_pull_up_input();
-    let mut cap_top_int = cap_top_int.into_pull_up_input();
-    let (mut ad7147_bot, mut ad7147_top) = init_captouch(i2c_bot, i2c_top).unwrap();
+#[derive(Debug, Clone, Copy)]
+enum Flow3rPetal {
+    TOP {
+        ccw: Flow3rPetalPart,
+        base: Flow3rPetalPart,
+        cw: Flow3rPetalPart,
+    },
+    BOTTOM {
+        base: Flow3rPetalPart,
+        tip: Flow3rPetalPart,
+    },
+}
 
-    let device_id = ad7147_bot.read_device_id().unwrap();
-    println!("captouch bot device id: {:016b}", device_id);
-    let device_id = ad7147_top.read_device_id().unwrap();
-    println!("captouch top device id: {:016b}", device_id);
-    println!("initialized captouch");
-    loop {
-        match select(cap_bot_int.wait_for_low(), cap_top_int.wait_for_low()).await {
-            Either::First(_) => {
-                let _ = ad7147_bot.read_interrupt_registers().unwrap();
-                let measurements_bot = ad7147_bot.read_all_stages().unwrap();
-                // println!("pad 0: {}, {}, {}, {}", measurements_bot[0], measurements_bot[1], interrupts[1] & (1 << 0) != 0, interrupts[1] & (1 << 1) != 0);
-                update_petals_bot(measurements_bot).await;
-            }
-            Either::Second(_) => {
-                let _ = ad7147_top.read_interrupt_registers().unwrap();
-                let measurements_top = ad7147_top.read_all_stages().unwrap();
-                update_petals_top(measurements_top).await;
-            }
+impl Flow3rPetal {
+    const fn new(pos: Flow3rCaptouchController) -> Flow3rPetal {
+        match pos {
+            Flow3rCaptouchController::TOP => Self::TOP {
+                ccw: Flow3rPetalPart {
+                    pressed: false,
+                    raw: 0,
+                },
+                base: Flow3rPetalPart {
+                    pressed: false,
+                    raw: 0,
+                },
+                cw: Flow3rPetalPart {
+                    pressed: false,
+                    raw: 0,
+                },
+            },
+            Flow3rCaptouchController::BOTTOM => Self::BOTTOM {
+                base: Flow3rPetalPart {
+                    pressed: false,
+                    raw: 0,
+                },
+                tip: Flow3rPetalPart {
+                    pressed: false,
+                    raw: 0,
+                },
+            },
+        }
+    }
+
+    pub fn pressed(&self) -> bool {
+        match self {
+            Flow3rPetal::TOP {
+                ccw,
+                base,
+                cw,
+            } => ccw.pressed | base.pressed | cw.pressed,
+            Flow3rPetal::BOTTOM { base, tip } => base.pressed | tip.pressed,
         }
     }
+
+    pub fn position(&self) -> i32 {
+        match self {
+            Flow3rPetal::TOP {
+                ccw,
+                base,
+                cw,
+            } => (ccw.raw as i32 + cw.raw as i32) / 2 - base.raw as i32,
+            Flow3rPetal::BOTTOM {base, tip } => base.raw as i32 + tip.raw as i32 / 2,
+        }
+    }
+}
+
+#[derive(Debug, Default, Clone, Copy)]
+struct Flow3rPetalPart {
+    pressed: bool,
+    raw: u16,
+}
+
+#[derive(Debug, Clone, Copy)]
+enum Flow3rCaptouchController {
+    BOTTOM,
+    TOP,
 }
 
 #[derive(Debug, Copy, Clone)]
diff --git a/src/display/backlight.rs b/flow3-rs/src/display/backlight.rs
similarity index 100%
rename from src/display/backlight.rs
rename to flow3-rs/src/display/backlight.rs
diff --git a/src/display/display_driver.rs b/flow3-rs/src/display/display_driver.rs
similarity index 100%
rename from src/display/display_driver.rs
rename to flow3-rs/src/display/display_driver.rs
diff --git a/src/display/display_interface.rs b/flow3-rs/src/display/display_interface.rs
similarity index 100%
rename from src/display/display_interface.rs
rename to flow3-rs/src/display/display_interface.rs
diff --git a/src/display/framebuffer.rs b/flow3-rs/src/display/framebuffer.rs
similarity index 100%
rename from src/display/framebuffer.rs
rename to flow3-rs/src/display/framebuffer.rs
diff --git a/src/display/mod.rs b/flow3-rs/src/display/mod.rs
similarity index 100%
rename from src/display/mod.rs
rename to flow3-rs/src/display/mod.rs
diff --git a/src/imu.rs b/flow3-rs/src/imu.rs
similarity index 100%
rename from src/imu.rs
rename to flow3-rs/src/imu.rs
diff --git a/src/input.rs b/flow3-rs/src/input.rs
similarity index 55%
rename from src/input.rs
rename to flow3-rs/src/input.rs
index 88553c48fc916ef804857cf4d2dbfd61ccfe7c2c..a9277f63f922729c98e4f3be4660cf61baacb0f0 100644
--- a/src/input.rs
+++ b/flow3-rs/src/input.rs
@@ -18,9 +18,9 @@ static INPUTS_CHANNEL: PubSubChannel<CriticalSectionRawMutex, Flow3rInputEvent,
 pub type InputEventListener =
     Subscriber<'static, CriticalSectionRawMutex, Flow3rInputEvent, 32, 32, 32>;
 
-pub struct InputHandler;
+pub struct Inputs;
 
-impl InputHandler {
+impl Inputs {
     pub fn get_event_listener(
         &mut self,
     ) -> Result<InputEventListener, embassy_sync::pubsub::Error> {
@@ -39,6 +39,93 @@ impl InputHandler {
     }
 }
 
+pub struct InputRunner {
+    i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
+    i2c_int: Gpio8<Unknown>,
+    sw1_button: Gpio0<Unknown>,
+    sw2_button: Gpio3<Unknown>,
+}
+
+impl InputRunner {
+    pub fn new(
+        i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
+        i2c_int: Gpio8<Unknown>,
+        sw1_button: Gpio0<Unknown>,
+        sw2_button: Gpio3<Unknown>,
+    ) -> Self {
+        Self { i2c, i2c_int, sw1_button, sw2_button }
+    }
+
+    pub async fn run(self) -> ! {
+        let mut i2c_int = self.i2c_int.into_pull_up_input();
+        let mut sw1_button = self.sw1_button.into_pull_up_input();
+        let mut sw2_button = self.sw2_button.into_pull_up_input();
+    
+        let mut pe2 = port_expander::Max7321::new(self.i2c, true, true, false, true);
+    
+        let pe2_io = pe2.split();
+        let mut sw1_r = pe2_io.p0;
+        sw1_r.set_high().unwrap();
+        let mut sw1_l = pe2_io.p7;
+        sw1_l.set_high().unwrap();
+        let mut sw2_r = pe2_io.p5;
+        sw2_r.set_high().unwrap();
+        let mut sw2_l = pe2_io.p4;
+        sw2_l.set_high().unwrap();
+    
+        let _lcd_rst = pe2_io.p3;
+    
+        let inputs_publisher = INPUTS_CHANNEL.immediate_publisher();
+    
+        loop {
+            match select3(
+                i2c_int.wait_for_low(),
+                sw1_button.wait_for_any_edge(),
+                sw2_button.wait_for_any_edge(),
+            )
+            .await
+            {
+                Either3::First(_) => {
+                    let values =
+                        port_expander::read_multiple([&sw1_l, &sw1_r, &sw2_l, &sw2_r]).unwrap();
+                    if !values[0] {
+                        inputs_publisher.publish_immediate(Flow3rInputEvent {
+                            input: FlowerInputEventSource::SW1Left,
+                            etype: Flow3rInputEventType::Press,
+                        });
+                    }
+                    if !values[1] {
+                        inputs_publisher.publish_immediate(Flow3rInputEvent {
+                            input: FlowerInputEventSource::SW1Right,
+                            etype: Flow3rInputEventType::Press,
+                        });
+                    }
+                    if !values[2] {
+                        inputs_publisher.publish_immediate(Flow3rInputEvent {
+                            input: FlowerInputEventSource::SW2Left,
+                            etype: Flow3rInputEventType::Press,
+                        });
+                    }
+                    if !values[3] {
+                        inputs_publisher.publish_immediate(Flow3rInputEvent {
+                            input: FlowerInputEventSource::SW2Right,
+                            etype: Flow3rInputEventType::Press,
+                        });
+                    }
+                }
+                Either3::Second(_) => inputs_publisher.publish_immediate(Flow3rInputEvent {
+                    input: FlowerInputEventSource::SW1Press,
+                    etype: Flow3rInputEventType::Press,
+                }),
+                Either3::Third(_) => inputs_publisher.publish_immediate(Flow3rInputEvent {
+                    input: FlowerInputEventSource::SW2Press,
+                    etype: Flow3rInputEventType::Press,
+                }),
+            }
+        }
+    }
+}
+
 async fn wait_for_event(
     input: FlowerInputEventSource,
     etype: Flow3rInputEventType,
@@ -111,81 +198,6 @@ pub enum Flow3rInputEventType {
     Release,
 }
 
-#[embassy_executor::task]
-pub async fn input_controller(
-    i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>,
-    i2c_int: Gpio8<Unknown>,
-    sw1_button: Gpio0<Unknown>,
-    sw2_button: Gpio3<Unknown>,
-) {
-    let mut i2c_int = i2c_int.into_pull_up_input();
-    let mut sw1_button = sw1_button.into_pull_up_input();
-    let mut sw2_button = sw2_button.into_pull_up_input();
-
-    let mut pe2 = port_expander::Max7321::new(i2c, true, true, false, true);
-
-    let pe2_io = pe2.split();
-    let mut sw1_r = pe2_io.p0;
-    sw1_r.set_high().unwrap();
-    let mut sw1_l = pe2_io.p7;
-    sw1_l.set_high().unwrap();
-    let mut sw2_r = pe2_io.p5;
-    sw2_r.set_high().unwrap();
-    let mut sw2_l = pe2_io.p4;
-    sw2_l.set_high().unwrap();
-
-    let _lcd_rst = pe2_io.p3;
-
-    let inputs_publisher = INPUTS_CHANNEL.immediate_publisher();
-
-    loop {
-        match select3(
-            i2c_int.wait_for_low(),
-            sw1_button.wait_for_any_edge(),
-            sw2_button.wait_for_any_edge(),
-        )
-        .await
-        {
-            Either3::First(_) => {
-                let values =
-                    port_expander::read_multiple([&sw1_l, &sw1_r, &sw2_l, &sw2_r]).unwrap();
-                if !values[0] {
-                    inputs_publisher.publish_immediate(Flow3rInputEvent {
-                        input: FlowerInputEventSource::SW1Left,
-                        etype: Flow3rInputEventType::Press,
-                    });
-                }
-                if !values[1] {
-                    inputs_publisher.publish_immediate(Flow3rInputEvent {
-                        input: FlowerInputEventSource::SW1Right,
-                        etype: Flow3rInputEventType::Press,
-                    });
-                }
-                if !values[2] {
-                    inputs_publisher.publish_immediate(Flow3rInputEvent {
-                        input: FlowerInputEventSource::SW2Left,
-                        etype: Flow3rInputEventType::Press,
-                    });
-                }
-                if !values[3] {
-                    inputs_publisher.publish_immediate(Flow3rInputEvent {
-                        input: FlowerInputEventSource::SW2Right,
-                        etype: Flow3rInputEventType::Press,
-                    });
-                }
-            }
-            Either3::Second(_) => inputs_publisher.publish_immediate(Flow3rInputEvent {
-                input: FlowerInputEventSource::SW1Press,
-                etype: Flow3rInputEventType::Press,
-            }),
-            Either3::Third(_) => inputs_publisher.publish_immediate(Flow3rInputEvent {
-                input: FlowerInputEventSource::SW2Press,
-                etype: Flow3rInputEventType::Press,
-            }),
-        }
-    }
-}
-
 #[embassy_executor::task]
 async fn input_logger() -> ! {
     let mut inputs_subscriber = INPUTS_CHANNEL.subscriber().unwrap();
diff --git a/src/leds.rs b/flow3-rs/src/leds.rs
similarity index 100%
rename from src/leds.rs
rename to flow3-rs/src/leds.rs
diff --git a/flow3-rs/src/lib.rs b/flow3-rs/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..cc307ce0648977bd4329c22239f902e31d7f9d64
--- /dev/null
+++ b/flow3-rs/src/lib.rs
@@ -0,0 +1,96 @@
+#![no_std]
+#![feature(type_alias_impl_trait, async_fn_in_trait)]
+
+use hal::Rng;
+
+use self::badgelink::BadgeLink;
+use self::badgelink::badgenet::{BadgenetUartLeft, BadgenetUartRight};
+use self::captouch::Captouch;
+use self::display::Display;
+use self::imu::ImuHandler;
+use self::input::Inputs;
+use self::leds::Leds;
+
+pub mod badgelink;
+pub mod captouch;
+pub mod display;
+pub mod imu;
+pub mod input;
+pub mod leds;
+pub mod sdcard;
+
+unsafe impl Sync for Flow3r {}
+
+pub struct Flow3r {
+    badgelink: Option<BadgeLink>,
+    captouch: Option<Captouch>,
+    display: Option<Display>,
+    imu: Option<ImuHandler>,
+    inputs: Option<Inputs>,
+    leds: Option<Leds>,
+    uart0: Option<BadgenetUartLeft>,
+    uart1: Option<BadgenetUartRight>,
+    rng: Option<Rng<'static>>,
+}
+
+impl Flow3r {
+    pub fn new(
+        badgelink: Option<BadgeLink>,
+        captouch: Option<Captouch>,
+        display: Option<Display>,
+        imu: Option<ImuHandler>,
+        inputs: Option<Inputs>,
+        leds: Option<Leds>,
+        uart0: Option<BadgenetUartLeft>,
+        uart1: Option<BadgenetUartRight>,
+        rng: Option<Rng<'static>>,
+    ) -> Self {
+        Self {
+            badgelink,
+            captouch,
+            display,
+            imu,
+            inputs,
+            leds,
+            uart0,
+            uart1,
+            rng,
+        }
+    }
+
+    pub fn take_badgelink(&mut self) -> BadgeLink {
+        self.badgelink.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_captouch(&mut self) -> Captouch {
+        self.captouch.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_display(&mut self) -> Display {
+        self.display.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_inputs(&mut self) -> Inputs {
+        self.inputs.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_imu(&mut self) -> ImuHandler {
+        self.imu.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_leds(&mut self) -> Leds {
+        self.leds.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_uart_left(&mut self) -> BadgenetUartLeft {
+        self.uart0.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_uart_right(&mut self) -> BadgenetUartRight {
+        self.uart1.take().expect("can only take badgelink once!")
+    }
+
+    pub fn take_rng(&mut self) -> Rng {
+        self.rng.take().expect("can only take badgelink once!")
+    }
+}
\ No newline at end of file
diff --git a/src/sdcard.rs b/flow3-rs/src/sdcard.rs
similarity index 100%
rename from src/sdcard.rs
rename to flow3-rs/src/sdcard.rs
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100644
index aec3ee5799506448b1b50f63c6131fbd3525d95b..0000000000000000000000000000000000000000
--- a/src/lib.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-#![no_std]
-#![feature(type_alias_impl_trait, async_fn_in_trait)]
-
-use hal::Rng;
-
-use self::badgelink::BadgeLink;
-use self::badgelink::badgenet::{BadgenetUartLeft, BadgenetUartRight};
-use self::captouch::CaptouchHandler;
-use self::display::Display;
-use self::imu::ImuHandler;
-use self::input::InputHandler;
-use self::leds::Leds;
-
-pub mod badgelink;
-pub mod captouch;
-pub mod display;
-pub mod imu;
-pub mod input;
-pub mod leds;
-pub mod sdcard;
-
-pub struct Flow3r {
-    pub badgelink: BadgeLink,
-    pub captouch: CaptouchHandler,
-    pub display: Display,
-    pub imu: ImuHandler,
-    pub inputs: InputHandler,
-    pub leds: Leds,
-    pub uart0: BadgenetUartLeft,
-    pub uart1: BadgenetUartRight,
-    pub rng: &'static mut Rng<'static>,
-}
-
-impl Flow3r {
-    pub fn new(
-        badgelink: BadgeLink,
-        captouch: CaptouchHandler,
-        display: Display,
-        imu: ImuHandler,
-        inputs: InputHandler,
-        leds: Leds,
-        uart0: BadgenetUartLeft,
-        uart1: BadgenetUartRight,
-        rng: &'static mut Rng<'static>,
-    ) -> Self {
-        Self {
-            badgelink,
-            captouch,
-            display,
-            imu,
-            inputs,
-            leds,
-            uart0,
-            uart1,
-            rng
-        }
-    }
-}
diff --git a/template/src/main.rs b/template/src/main.rs
deleted file mode 100644
index d027f27f94c11ff6e67d62b1f55c46a012e9eb6f..0000000000000000000000000000000000000000
--- a/template/src/main.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-#![no_std]
-#![no_main]
-#![feature(type_alias_impl_trait)]
-#![feature(async_fn_in_trait)]
-
-mod demo_tasks;
-mod ui;
-
-use demo_tasks::{draw_start_screen, badgelink_demo};
-use embassy_executor::Spawner;
-use embassy_time::{Duration, Timer};
-
-use esp_backtrace as _;
-use hal::prelude::*;
-
-use flow3_rs::Flow3r;
-use flow3_rs_rt::start_runtime;
-
-use crate::ui::main_menu::main_menu;
-
-#[entry]
-fn runtime() -> ! {
-    start_runtime(main)
-}
-
-#[embassy_executor::task]
-async fn main(mut flow3r: Flow3r) -> ! {
-    draw_start_screen(&mut flow3r.display).await;
-
-    let spawner = Spawner::for_current_executor().await;
-    spawner.spawn(demo_tasks::leds_fade(flow3r.leds)).ok();
-
-    Timer::after(Duration::from_secs(2)).await;
-
-    main_menu(flow3r.display, flow3r.inputs, flow3r.imu).await
-}
diff --git a/vendor/README.md b/vendor/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f82b6a8ba6d3f6b4f961e93a2c008b5832439208
--- /dev/null
+++ b/vendor/README.md
@@ -0,0 +1 @@
+This directory contains some crates.io dependencies with custom patches for flow3-rs that have not yet (or will not be) upstreamed.
\ No newline at end of file
diff --git a/vendor/ad7147/Cargo.toml b/vendor/ad7147/Cargo.toml
index 29bbf6e2e5cb676b5ce9dc78d82d990a25e60455..f0b001c42765ca11b63255b9dea2b4fd4c3559d1 100644
--- a/vendor/ad7147/Cargo.toml
+++ b/vendor/ad7147/Cargo.toml
@@ -8,6 +8,6 @@ authors = ["zdmx <hi@zdmx.me>"]
 
 [dependencies]
 byte-slice-cast = { version = "1.2.2", default-features = false }
-embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" }
+embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
 embedded-hal = "0.2.7"
 heapless = "0.7.16"