From 6841142729c8a9c5f6590a9a820a9d5f6f9c4a9a Mon Sep 17 00:00:00 2001 From: Kat Inskip Date: Sat, 18 Oct 2025 02:15:49 -0700 Subject: [PATCH] feat: less just, lol --- .cargo/config.toml | 5 +- .envrc | 1 + .sops.yaml | 8 ++ Cargo.lock | 296 +++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 12 +- flake.nix | 32 ++--- justfile | 8 -- rust-toolchain.toml | 2 +- secrets.yaml | 29 +++++ src/main.rs | 212 +++++++++++++++++++++++++++---- 10 files changed, 549 insertions(+), 56 deletions(-) create mode 100644 .sops.yaml delete mode 100644 justfile create mode 100644 secrets.yaml diff --git a/.cargo/config.toml b/.cargo/config.toml index fb52d86..94fe7d6 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -11,5 +11,8 @@ rustflags = [ target = "riscv32imc-unknown-none-elf" +[env] +ESP_LOG="INFO" + [unstable] -build-std = ["core"] +build-std = ["alloc", "core"] diff --git a/.envrc b/.envrc index 3550a30..01590f9 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ use flake +export $(sops -d --output-type dotenv secrets.yaml | xargs) diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..18465e9 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,8 @@ +keys: +- &kat CD8CE78CB0B3BDD4 # https://inskip.me/pubkey.asc +creation_rules: +- path_regex: secrets.yaml + shamir_threshold: 1 + key_groups: + - pgp: + - *kat diff --git a/Cargo.lock b/Cargo.lock index 008e920..d5e2a8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c583acf993cf4245c4acb0a2cc2ab1f9cc097de73411bb6d3647ff6af2b1013d" +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + [[package]] name = "autocfg" version = "1.4.0" @@ -46,6 +52,12 @@ dependencies = [ "syn 2.0.102", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.0" @@ -197,6 +209,36 @@ dependencies = [ "nb 1.1.0", ] +[[package]] +name = "embassy-executor" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" +dependencies = [ + "critical-section", + "document-features", + "embassy-executor-macros", + "embassy-executor-timer-queue", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "embassy-executor-timer-queue" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" + [[package]] name = "embassy-futures" version = "0.1.2" @@ -212,6 +254,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "embassy-net" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0558a231a47e7d4a06a28b5278c92e860f1200f24821d2f365a2f40fe3f3c7b2" +dependencies = [ + "document-features", + "embassy-net-driver", + "embassy-sync 0.7.2", + "embassy-time", + "embedded-io-async 0.6.1", + "embedded-nal-async", + "heapless 0.8.0", + "managed", + "smoltcp", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + [[package]] name = "embassy-sync" version = "0.6.2" @@ -240,6 +305,41 @@ dependencies = [ "heapless 0.8.0", ] +[[package]] +name = "embassy-time" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-core", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-utils" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e2ee86063bd028a420a5fb5898c18c87a8898026da1d4c852af2c443d0a454" +dependencies = [ + "embassy-executor-timer-queue", + "heapless 0.8.0", +] + [[package]] name = "embedded-can" version = "0.4.1" @@ -358,6 +458,25 @@ dependencies = [ "syn 2.0.102", ] +[[package]] +name = "embedded-nal" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56a28be191a992f28f178ec338a0bf02f63d7803244add736d026a471e6ed77" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-nal-async" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76959917cd2b86f40a98c28dd5624eddd1fa69d746241c8257eac428d83cb211" +dependencies = [ + "embedded-io-async 0.6.1", + "embedded-nal", +] + [[package]] name = "embedded-storage" version = "0.3.1" @@ -373,6 +492,17 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "embedded-text" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cf5c72c52db2f7dbe4a9c1ed81cd21301e8d66311b194fa41c04fb4f71843ba" +dependencies = [ + "az", + "embedded-graphics", + "object-chain", +] + [[package]] name = "enumset" version = "1.1.6" @@ -467,7 +597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f75242d788e67fc7ce51308019c0ff5d5103f989721577bb566b02710ef1ba79" dependencies = [ "bitfield", - "bitflags", + "bitflags 2.9.0", "bytemuck", "cfg-if", "critical-section", @@ -532,6 +662,21 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b18b1787dd3adea642fb529dd83fe558a08ace365bbaede4643a8959992900f4" +[[package]] +name = "esp-phy" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62199c3e50eefcf53b8f3c690946582a124f7137b45bd1b14eb4b90a3fec2dd7" +dependencies = [ + "cfg-if", + "document-features", + "esp-config", + "esp-hal", + "esp-metadata-generated", + "esp-sync", + "esp-wifi-sys", +] + [[package]] name = "esp-println" version = "0.16.0" @@ -545,6 +690,45 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "esp-radio" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83744f57d19a7190a538ad42025da7f53940c3aca71cbcd92275095d671e254" +dependencies = [ + "allocator-api2", + "cfg-if", + "document-features", + "embassy-net-driver", + "embedded-io 0.6.1", + "embedded-io 0.7.1", + "embedded-io-async 0.6.1", + "embedded-io-async 0.7.0", + "enumset", + "esp-alloc", + "esp-config", + "esp-hal", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-phy", + "esp-radio-rtos-driver", + "esp-sync", + "esp-wifi-sys", + "heapless 0.9.1", + "instability", + "num-derive", + "num-traits", + "portable-atomic", + "portable_atomic_enum", + "smoltcp", +] + +[[package]] +name = "esp-radio-rtos-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab031e544f6bc086c2d7aba89276e6a47ce6bb5614ae3c88a1c12a4ab4f8f25c" + [[package]] name = "esp-riscv-rt" version = "0.13.0" @@ -567,6 +751,26 @@ dependencies = [ "esp-metadata-generated", ] +[[package]] +name = "esp-rtos" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01dbf6e54315b6e05da3ad828c7da1ba98f541eb8b0c5d5d260b8eb3b64a8cd" +dependencies = [ + "cfg-if", + "document-features", + "embassy-executor", + "embassy-sync 0.7.2", + "embassy-time-driver", + "embassy-time-queue-utils", + "esp-config", + "esp-hal", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-sync", + "portable-atomic", +] + [[package]] name = "esp-sync" version = "0.1.0" @@ -582,6 +786,15 @@ dependencies = [ "xtensa-lx", ] +[[package]] +name = "esp-wifi-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b6544f6f0cb86169d1f93ba2101a8d50358a040c5043676ed86b793e09b12c" +dependencies = [ + "anyhow", +] + [[package]] name = "esp32" version = "0.39.0" @@ -714,9 +927,9 @@ checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -863,20 +1076,33 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + [[package]] name = "meepy" version = "0.1.0" dependencies = [ "display-interface-spi", + "embassy-executor", + "embassy-net", + "embassy-time", "embedded-graphics", "embedded-hal-bus", "embedded-layout", + "embedded-text", "esp-alloc", "esp-backtrace", "esp-bootloader-esp-idf", "esp-hal", "esp-println", + "esp-radio", + "esp-rtos", "ili9341", + "static_cell", ] [[package]] @@ -906,6 +1132,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -915,6 +1152,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object-chain" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41af26158b0f5530f7b79955006c2727cd23d0d8e7c3109dc316db0a919784dd" + [[package]] name = "paste" version = "1.0.15" @@ -948,6 +1191,27 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "portable_atomic_enum" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d48f60c43e0120bb2bb48589a16d4bed2f4b911be41e299f2d0fc0e0e20885" +dependencies = [ + "portable-atomic", + "portable_atomic_enum_macros", +] + +[[package]] +name = "portable_atomic_enum_macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33fa6ec7f2047f572d49317cca19c87195de99c6e5b6ee492da701cfe02b053" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -1113,6 +1377,19 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "smoltcp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "cfg-if", + "heapless 0.8.0", + "managed", +] + [[package]] name = "somni-expr" version = "0.2.0" @@ -1134,6 +1411,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_cell" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23" +dependencies = [ + "portable-atomic", +] + [[package]] name = "strsim" version = "0.11.1" @@ -1238,9 +1524,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ufmt-write" diff --git a/Cargo.toml b/Cargo.toml index 8495761..8c225b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,13 @@ license = "MIT" [dependencies] display-interface-spi = "0.5.0" +embassy-executor = "0.9.1" +embassy-net = { version = "0.7.1", features = ["tcp", "udp", "dhcpv4", "medium-ethernet"] } +embassy-time = "0.5.0" embedded-graphics = "0.8.1" embedded-hal-bus = "0.3.0" embedded-layout = "0.4.2" +embedded-text = "0.7.3" esp-alloc = { version = "0.9.0", features = ["esp32c3"] } esp-backtrace = { version = "0.18.0", features = [ "esp32c3", @@ -17,9 +21,9 @@ esp-backtrace = { version = "0.18.0", features = [ "println", ]} esp-bootloader-esp-idf = { version = "0.3.0", features = ["esp32c3"]} -esp-hal = { version = "1.0.0-rc.1",features = [ - "esp32c3", - "unstable", -] } +esp-hal = { version = "1.0.0-rc.1", features = ["esp32c3", "unstable"] } esp-println = { version = "0.16.0", features = ["esp32c3", "log-04"] } +esp-radio = { version = "0.16.0", features = ["smoltcp", "wifi", "esp32c3", "unstable"] } +esp-rtos = { version = "0.1.1", features = ["esp32c3", "embassy"] } ili9341 = "0.6.0" +static_cell = "2.1.1" diff --git a/flake.nix b/flake.nix index d587b7b..fff2aea 100644 --- a/flake.nix +++ b/flake.nix @@ -7,35 +7,36 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; }; outputs = { nixpkgs, flake-utils, esp-rs-nix, ... }@inputs: let + arch = "riscv32imc-unknown-none-elf"; mkPkgs = system: (import nixpkgs) { inherit system; - rust.rustcTarget = "riscv32imc-unknown-none-elf"; + rust.rustcTarget = arch; }; eachSystemOutputs = flake-utils.lib.eachDefaultSystem (system: let pkgs = mkPkgs system; + lib = pkgs.lib; inherit (esp-rs-nix.packages.${system}) esp-rs; + inherit (lib.meta) getExe; + buildy = pkgs.writeShellScriptBin "build" '' + set -euox pipefail + PACKAGE_NAME="$(${getExe pkgs.toml-cli} get -r Cargo.toml package.name)" + EXE="''${PROJECT_DIR}/target/${arch}/release/''${PACKAGE_NAME}" + cargo build --release && + sudo espflash flash ''${EXE} + ''; esp-shell = pkgs.mkShell rec { name = "esp-shell"; buildInputs = [ - esp-rs - pkgs.rustup + esp-rs + buildy + pkgs.rustup pkgs.espflash - pkgs.pkg-config - pkgs.stdenv.cc - #pkgs.rust-analyzer - #pkgs.bacon - #pkgs.systemdMinimal - #pkgs.lunarvim - #pkgs.inotify-tools - #pkgs.picocom - #pkgs.vscode-fhs + pkgs.pkg-config + pkgs.stdenv.cc pkgs.libusb1 pkgs.python3 - # Workspace command runners - pkgs.just pkgs.mprocs - # This is for parameterising the justfile pkgs.toml-cli pkgs.moreutils pkgs.gdb @@ -44,6 +45,7 @@ LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath buildInputs}"; shellHook = '' + export PROJECT_DIR="$(pwd)"; # custom bashrc stuff export PS1_PREFIX="(esp-rs)" . ~/.bashrc diff --git a/justfile b/justfile deleted file mode 100644 index 7991b7f..0000000 --- a/justfile +++ /dev/null @@ -1,8 +0,0 @@ -arch := "riscv32imc-unknown-none-elf" -pakidg := shell('toml get -r Cargo.toml package.name') -exe := justfile_directory() / "target" / arch / "release" / pakidg - -build: - #!/usr/bin/env bash - cargo build --release && \ - sudo espflash flash {{exe}} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e6c6255..98b588e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] channel = "stable" -components = ["rust-src"] +components = ["rust-src", "clippy", "rust-analyzer"] targets = ["riscv32imc-unknown-none-elf"] diff --git a/secrets.yaml b/secrets.yaml new file mode 100644 index 0000000..ad8f5e4 --- /dev/null +++ b/secrets.yaml @@ -0,0 +1,29 @@ +WIFI_SSID: ENC[AES256_GCM,data:4mQfGSI=,iv:q8ljooV+fN/g2oBL7J6M5CkQ/h/pYnagdsVJ+PLF+hA=,tag:3eGz3yh0UX0mWL1H+aFGpA==,type:str] +WIFI_PASSWORD: ENC[AES256_GCM,data:MUZ0olPXKE4=,iv:AOIfYGGhLvcTVb+7HOY/2hQT8AzAQq358xDd5pIRSO8=,tag:ZyCEhEitqwGweZ0hEAeG0Q==,type:str] +sops: + shamir_threshold: 1 + lastmodified: "2025-10-18T08:32:27Z" + mac: ENC[AES256_GCM,data:rm46Or9iyN2mNy6id0oNDLf+y0zXiLUCZB8wRxh0zItQyTAnAWiE/ccVmKu/AKQASDdimEwlxn2JWXZQZuulFVGBrSRzPkr2mxkIpCLT2ybMbghropTnSWANw55YcXblNl4QptW3r2ZioM5jD93ADqGsZxm++0zanqCIlZU8HWA=,iv:UnrDnYBKD2ZA9FWcASn0TaJNDqTN/WNAgbi8KVxwgvw=,tag:UuSALcsVmYWKCFzZdkukOQ==,type:str] + pgp: + - created_at: "2025-10-18T08:31:23Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA82M54yws73UAQ//YR/4g37rZEgCnuaeZSvtmIDouSCLooSnKjWS4ixIC0iq + M85LmrFFTSiA4v7n/JwCTU+sWpL8WLMu/kR6oKDj/avTpwQ2XExWRd2XcLPCRKsw + aKK4EQ01l4po95wp6FCB3ipFNQMwOfcUqJdoEu5QGaVwKNQaK4uTtGVeQ3bZvltN + qGIRa8o2UxlHiYcbE7qhZkppCDmT+eMQoe0Ze+az71WgZIFaEfE4J4juDcaachjn + IbV7ZfgXKVERSQulDyrC8tGTIAOW0gL1nqWOiF3x6mOb/1XCUb2Hv/VaC7DockQb + JQlHDOUvdHUHFg03Isjn1ygHUnViyUOk1W+jIIjggYQwHJERafXnmC8WAOkdMEGn + DirCGkLjwvQQ9JGnmZx3OwK+moYas21M4OwtYS2RMgwpCT0kMckH1oQPArIeAw+a + OT4lUl128TAIzFEMjZvrVuUjdwnTHaOq95cY+jC8d1T/kV2yGiHqGF6ywx8KEtps + ZCBCwkzp+BcuIaE1nrWDm0HXyBrbgTepEMY8O3NKeB7pXhtBmlzNCOFcs4ujyzys + WtFi2K6ELEDyqAiC5p7p5plbxQxDoBse/xXAYuRG4iAyq0UlnN4ocUdEufTuds3V + rxn15LPs117ULtevW12/7X13OCcC1lTTH4Y0Bry1SJuWeqy3AUCkfuqA7Z79wxLS + XgHbLfkE01arAUEZxcGjk2h+lSdTXEgdDZ+6WsCaLu9ibWathJ01lxj4EDvDWX7f + h6e1xJ0vgonZD1aFRf475QtX5KUlmtv5k2bKu1t1gLir3x7NwU3gudugosVlrLM= + =fzG1 + -----END PGP MESSAGE----- + fp: CD8CE78CB0B3BDD4 + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/src/main.rs b/src/main.rs index ac7214c..a63e400 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,30 @@ #![no_std] #![no_main] +extern crate alloc; + use { + core::ptr::addr_of_mut, display_interface_spi::{SPIInterface, *}, embedded_graphics::{ - mono_font::{ascii::FONT_8X13, MonoFont, MonoTextStyle}, + mono_font::{ascii::{FONT_8X13, FONT_6X10}, MonoFont, MonoTextStyle}, pixelcolor::{Rgb565, Bgr565, RgbColor}, prelude::*, - primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle, Triangle}, + primitives::{Styled, Line, PrimitiveStyle, PrimitiveStyleBuilder, Rectangle, Triangle}, text::{Alignment, Text}, }, + embedded_text::{ + TextBox, + style::{ + TextBoxStyleBuilder, + HeightMode, + }, + alignment::HorizontalAlignment as TextHorizontalAlignment, + }, + embedded_layout::{ + layout::linear::LinearLayout, + prelude::*, + }, embedded_hal_bus::spi::{ExclusiveDevice, NoDelay}, esp_backtrace as _, esp_hal::{ @@ -29,8 +44,13 @@ use { }, esp_println::println, ili9341::{DisplaySize240x320, Ili9341, Orientation}, + embassy_executor::Spawner, + embassy_time::{Duration, Timer}, }; +const SSID: &str = env!("WIFI_SSID"); +const PASSWORD: &str = env!("WIFI_PASSWORD"); + esp_bootloader_esp_idf::esp_app_desc!(); type TFTSpiDevice<'spi> = ExclusiveDevice, Output<'spi>, NoDelay>; @@ -111,8 +131,21 @@ impl<'a> Dimensions for DrawFlipper<'a, '_> { } } +#[derive(Clone,Copy)] +enum StyleVariant { + Header, + Regular +} impl<'spi> TFT<'spi> { + const H_BG: Bgr565 = Bgr565::CSS_DARK_SLATE_GRAY; + const H_S: Bgr565 = Bgr565::CYAN; + const H_FG: Bgr565 = Bgr565::WHITE; + + const R_BG: Bgr565 = Bgr565::CSS_DARK_SLATE_GRAY; + const R_S: Bgr565 = Bgr565::BLUE; + const R_FG: Bgr565 = Bgr565::WHITE; + pub fn new( spi2: SPI2<'spi>, sclk: impl OutputPin + 'spi, @@ -163,43 +196,178 @@ impl<'spi> TFT<'spi> { .unwrap(); } - pub fn containing_recty(&mut self, x: i32, y: i32, w: u32, h: u32) { + pub fn containing_recty(&mut self, x: i32, y: i32, w: u32, h: u32, style: StyleVariant) -> Styled> { + let bg = match style { + StyleVariant::Header => Self::H_BG, + StyleVariant::Regular => Self::R_BG, + }; + let s = match style { + StyleVariant::Header => Self::H_S, + StyleVariant::Regular => Self::R_S, + }; + let style = PrimitiveStyleBuilder::new() + .fill_color(bg) + .stroke_color(s) + .stroke_width(1) + .build(); Rectangle::new(Point::new(x, y), Size::new(w, h)) - .into_styled(PrimitiveStyle::with_stroke(Bgr565::CYAN, 1)) - .draw(&mut self.draw_target()) - .unwrap(); + .clone() + .into_styled(style) } - pub fn container(&mut self, margin: i32, y: i32, h: u32) { + pub fn container(&mut self, margin: i32, y: i32, h: u32, style: StyleVariant) -> Styled> { let width = self.display.bounding_box().size.width; - self.containing_recty(margin, y, width - margin as u32, h); + self.containing_recty(margin, y, width - margin as u32, h, style) } pub fn println(&mut self, text: &str, x: i32, y: i32) { - let style = MonoTextStyle::new(&FONT_8X13, Bgr565::WHITE); + let style = MonoTextStyle::new(&FONT_6X10, Bgr565::WHITE); Text::with_alignment(text, Point::new(x, y), style, Alignment::Center) .draw(&mut self.draw_target()) .unwrap(); } } -#[main] -fn main() -> ! { +macro_rules! mk_static { + ($t:ty,$val:expr) => {{ + static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new(); + #[deny(unused_attributes)] + let x = STATIC_CELL.uninit().write(($val)); + x + }}; +} +/* +#[embassy_executor::task] +async fn connection(mut controller: WifiController<'static>) { + println!("start connection task"); + println!("Device capabilities: {:?}", controller.capabilities()); + loop { + if esp_wifi::wifi::wifi_state() == WifiState::StaConnected { + // wait until we're no longer connected + controller.wait_for_event(WifiEvent::StaDisconnected).await; + Timer::after(Duration::from_millis(5000)).await + } + if !matches!(controller.is_started(), Ok(true)) { + let client_config = Configuration::Client(ClientConfiguration { + ssid: SSID.into(), + password: PASSWORD.into(), + ..Default::default() + }); + controller.set_configuration(&client_config).unwrap(); + println!("Starting wifi"); + controller.start_async().await.unwrap(); + println!("Wifi started!"); + } + println!("About to connect..."); + + match controller.connect_async().await { + Ok(_) => println!("Wifi connected!"), + Err(e) => { + println!("Failed to connect to wifi: {e:?}"); + Timer::after(Duration::from_millis(5000)).await + } + } + } +} + +#[embassy_executor::task] +async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) { + runner.run().await +}*/ + + +fn init_heap() { + const HEAP_SIZE: usize = 64 * 1024; + static mut HEAP: core::mem::MaybeUninit<[u8; HEAP_SIZE]> = core::mem::MaybeUninit::uninit(); + + unsafe { + esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new( + addr_of_mut!(HEAP) as *mut u8, + HEAP_SIZE, + esp_alloc::MemoryCapability::Internal.into(), + )); + } +} + +struct Controller<'tft> { + pub tft: TFT<'tft>, +} + +impl Controller<'_> { + async fn init(peripherals: Peripherals) -> Self { + let tft = Self::init_screen(peripherals).await; + let controller = Self { + tft, + }; + controller + } + + async fn init_screen<'tft>(peripherals: Peripherals) -> TFT<'tft> { + let dc = peripherals.GPIO9; + let mosi = peripherals.GPIO6; + let sclk = peripherals.GPIO4; + let miso = peripherals.GPIO5; + let cs = peripherals.GPIO7; + let rst = peripherals.GPIO0; + + let mut tft = TFT::new(peripherals.SPI2, sclk, miso, mosi, cs, rst, dc); + let _ = tft.draw_target().clear(Bgr565::BLACK); + tft + } +} + +#[esp_rtos::main] +async fn main(spawner: Spawner) { + init_heap(); + #[cfg(feature = "log")] + { + // The default log level can be specified here. + // You can see the esp-println documentation: https://docs.rs/esp-println + esp_println::logger::init_logger(log::LevelFilter::Info); + } + let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals: Peripherals = init(config); - esp_alloc::heap_allocator!(size: 72*1024); +/* let timer1 = TimerGroup::new(peripherals.TIMG1); + let rng = Rng::new(); + let esp_wifi_ctrl = &*mk_static!( + EspWifiController<'static>, + init(timer1.timer0, rng).unwrap() + ); + let (controller, interfaces) = esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).unwrap(); + let wifi_interface = interfaces.sta; + let seed = rng.random(); + let wifi_config = Config::dhcpv4(Default::default()); + let (stack, runner) = embassy_net::new( + wifi_interface, + wifi_config, + mk_static!(StackResources<8>, StackResources::<8>::new()), + seed, + );*/ - let dc = peripherals.GPIO9; - let mosi = peripherals.GPIO6; // sdo -> MOSI - let sclk = peripherals.GPIO4; - let miso = peripherals.GPIO5; // sdi -> MISO - let cs = peripherals.GPIO7; - let rst = peripherals.GPIO0; + let mut controller = Controller::init(peripherals).await; - let mut tft = TFT::new(peripherals.SPI2, sclk, miso, mosi, cs, rst, dc); - tft.draw_target().clear(Bgr565::BLACK); - tft.container(2, 2, 16); - tft.println("nya~! -w-", 100, 40); + let display_area = controller.tft.display.bounding_box(); + let text_style = MonoTextStyle::new(&FONT_6X10, Bgr565::WHITE); + let margin = 2; + let display_width = display_area.size.width; + let display_height = display_area.size.height; + + LinearLayout::vertical( + Chain::new( + LinearLayout::horizontal( + Chain::new( + Text::new("Initializing~!", Point::new(margin, margin), text_style) + ).append( + controller.tft.container(margin, -10, 20, StyleVariant::Header) + ) + ) + ) + ).with_alignment(horizontal::Center) + .arrange() + .align_to(&display_area, horizontal::Center, vertical::Center) + .draw(&mut controller.tft.draw_target()) + .unwrap(); loop { // your business logic