diff --git a/Cargo.lock b/Cargo.lock index a176ed7..f3fd143 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,41 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.7", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "aligned-vec" version = "0.6.4" @@ -61,6 +96,27 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[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 = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -96,6 +152,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "basic-toml" version = "0.1.10" @@ -137,6 +205,12 @@ dependencies = [ "syn 2.0.106", ] +[[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.4" @@ -189,6 +263,15 @@ dependencies = [ "uuid", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + [[package]] name = "bt-hci" version = "0.3.2" @@ -199,7 +282,17 @@ dependencies = [ "embedded-io", "embedded-io-async", "futures-intrusive", - "heapless", + "heapless 0.8.0", +] + +[[package]] +name = "buffered-io" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5698b2eda4613b62f3aa3119805df1ca6739e00167a2600b3a234ac49b14803" +dependencies = [ + "embedded-io", + "embedded-io-async", ] [[package]] @@ -275,12 +368,37 @@ dependencies = [ "num-traits", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -327,13 +445,25 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -358,6 +488,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "darling" version = "0.20.11" @@ -438,13 +577,25 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ + "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -491,6 +642,25 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array 0.14.7", + "group", + "hkdf", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embassy-embedded-hal" version = "0.3.2" @@ -582,6 +752,23 @@ 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 0.5.0", + "embedded-io-async", + "embedded-nal-async", + "heapless 0.8.0", + "managed", + "smoltcp", +] + [[package]] name = "embassy-net-driver" version = "0.2.0" @@ -599,7 +786,7 @@ dependencies = [ "embedded-io-async", "futures-sink", "futures-util", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -613,7 +800,7 @@ dependencies = [ "embedded-io-async", "futures-core", "futures-sink", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -665,7 +852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" dependencies = [ "embassy-executor", - "heapless", + "heapless 0.8.0", ] [[package]] @@ -761,6 +948,25 @@ dependencies = [ "embedded-io", ] +[[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", + "embedded-nal", +] + [[package]] name = "embedded-storage" version = "0.3.1" @@ -776,6 +982,48 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "embedded-tls" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6efb76fdd004a4ef787640177237b83449e6c5847765ea50bf15900061fd601" +dependencies = [ + "aes-gcm", + "atomic-polyfill", + "digest", + "embedded-io", + "embedded-io-async", + "generic-array 0.14.7", + "heapless 0.6.1", + "heapless 0.8.0", + "hkdf", + "hmac", + "p256", + "rand_core 0.6.4", + "sha2", + "typenum", +] + +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "enumset" version = "1.1.10" @@ -846,7 +1094,7 @@ dependencies = [ "cfg-if", "esp-config", "esp-println", - "heapless", + "heapless 0.8.0", "semihosting", ] @@ -885,7 +1133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3887eda2917deef3d99e7a5c324f9190714e99055361ad36890dffd0a995b49" dependencies = [ "bitfield 0.19.2", - "bitflags", + "bitflags 2.9.4", "bytemuck", "cfg-if", "critical-section", @@ -1040,6 +1288,18 @@ dependencies = [ "esp-metadata-generated", ] +[[package]] +name = "esp-storage" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f276ad8a3bdc6b47cd92a3e91013f2e42dce9b3fc5023392063387a1ce2ed69a" +dependencies = [ + "critical-section", + "document-features", + "embedded-storage", + "esp-rom-sys", +] + [[package]] name = "esp-synopsys-usb-otg" version = "0.4.2" @@ -1055,9 +1315,9 @@ dependencies = [ [[package]] name = "esp-wifi" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84908f2e95cb99a200cf448abafc416576338be590778a15d9224eee237f3210" +checksum = "69336f3f30938a644077d2a9747e3cd325436dcaf57d9dc8d58f139e02104889" dependencies = [ "allocator-api2", "bt-hci", @@ -1079,6 +1339,7 @@ dependencies = [ "portable-atomic", "portable_atomic_enum", "rand_core 0.9.3", + "smoltcp", "xtensa-lx-rt", ] @@ -1212,6 +1473,16 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "figments" version = "0.0.2" @@ -1361,6 +1632,24 @@ 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" @@ -1369,6 +1658,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1394,6 +1684,16 @@ dependencies = [ "wasip2", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gif" version = "0.13.3" @@ -1404,6 +1704,17 @@ dependencies = [ "weezl", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "half" version = "2.7.1" @@ -1415,6 +1726,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.3.1" @@ -1426,9 +1746,21 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heapless" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +dependencies = [ + "as-slice", + "generic-array 0.14.7", + "hash32 0.1.1", + "stable_deref_trait", +] [[package]] name = "heapless" @@ -1436,7 +1768,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] @@ -1446,6 +1778,36 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + [[package]] name = "ident_case" version = "1.0.1" @@ -1494,13 +1856,14 @@ checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" [[package]] name = "indexmap" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", "hashbrown", "serde", + "serde_core", ] [[package]] @@ -1509,6 +1872,15 @@ version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array 0.14.7", +] + [[package]] name = "instability" version = "0.3.9" @@ -1646,11 +2018,10 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -1669,6 +2040,12 @@ dependencies = [ "imgref", ] +[[package]] +name = "managed" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" + [[package]] name = "maybe-async-cfg" version = "0.2.4" @@ -1799,7 +2176,7 @@ dependencies = [ "arrayvec", "cfg-if", "chrono", - "heapless", + "heapless 0.8.0", "nom", "num-traits", ] @@ -1820,6 +2197,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" +[[package]] +name = "nourl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa07b0722c63805057dec824444fdc814bdfd30d1c782a3a8f63bbcf67c4ed1c" + [[package]] name = "num" version = "0.4.3" @@ -1919,6 +2302,22 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "elliptic-curve", + "primeorder", +] + [[package]] name = "paste" version = "1.0.15" @@ -1949,13 +2348,25 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags", + "bitflags 2.9.4", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.11.1" @@ -2002,12 +2413,21 @@ dependencies = [ ] [[package]] -name = "proc-macro-crate" -version = "3.3.0" +name = "primeorder" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "toml_edit", + "elliptic-curve", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit 0.23.7", ] [[package]] @@ -2068,7 +2488,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ - "bitflags", + "bitflags 2.9.4", "memchr", "unicase", ] @@ -2240,10 +2660,14 @@ dependencies = [ "display-interface", "embassy-embedded-hal 0.5.0", "embassy-executor", + "embassy-net", "embassy-sync 0.7.2", "embassy-time 0.5.0", "embedded-graphics", "embedded-hal-async", + "embedded-storage", + "enum-map", + "enumset", "esp-alloc", "esp-backtrace", "esp-bootloader-esp-idf", @@ -2251,6 +2675,7 @@ dependencies = [ "esp-hal-embassy", "esp-hal-smartled", "esp-println", + "esp-storage", "esp-wifi", "figments", "figments-render", @@ -2261,14 +2686,37 @@ dependencies = [ "mpu6050-dmp", "nalgebra 0.33.2", "nmea", + "reqwless", "rgb", "rmp", "smart-leds", + "smoltcp", "ssd1306", "static_cell", "xtensa-lx-rt", ] +[[package]] +name = "reqwless" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1be74cb817fa6dbda417110f575d9b9ad5488817f1eb65f2f6468fe6d5d663" +dependencies = [ + "base64", + "buffered-io", + "embedded-io", + "embedded-io-async", + "embedded-nal-async", + "embedded-tls", + "heapless 0.8.0", + "hex", + "httparse", + "log", + "nourl", + "rand_chacha", + "rand_core 0.6.4", +] + [[package]] name = "rgb" version = "0.8.52" @@ -2332,8 +2780,6 @@ dependencies = [ [[package]] name = "rmp" version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ "byteorder", "num-traits", @@ -2358,6 +2804,19 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.7", + "subtle", + "zeroize", +] + [[package]] name = "semihosting" version = "0.1.20" @@ -2416,6 +2875,17 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -2485,6 +2955,19 @@ dependencies = [ "rgb", ] +[[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 = "ssd1306" version = "0.10.0" @@ -2542,6 +3025,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -2634,8 +3123,8 @@ checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] @@ -2647,6 +3136,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -2656,7 +3154,28 @@ dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.11", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ "winnow", ] @@ -2684,6 +3203,16 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -2696,7 +3225,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" dependencies = [ - "heapless", + "heapless 0.8.0", "portable-atomic", ] @@ -2916,6 +3445,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + [[package]] name = "zune-core" version = "0.4.12" diff --git a/Cargo.toml b/Cargo.toml index 04e8ffb..13bb4a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,6 +66,8 @@ nalgebra = { version = "0.33.2", default-features = false, features = ["alloc", xtensa-lx-rt = { version = "*", features = ["float-save-restore"] } futures = { version = "0.3.31", default-features = false, features = ["async-await"] } micromath = "2.1.0" +enumset = "1.1.10" +enum-map = "2.7.3" # Telemetry outputs esp-wifi = { version = "0.15.0", optional = true, features = [ diff --git a/assets/blank-icon.pbm b/assets/blank-icon.pbm new file mode 100644 index 0000000..68c7e0c --- /dev/null +++ b/assets/blank-icon.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/assets/demo.pbm b/assets/demo.pbm new file mode 100644 index 0000000..f278951 --- /dev/null +++ b/assets/demo.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +1100000000000000101000000000000010100000000000001010111000000000101010 +0000000000101010000000000011001100101000000000100011100000000010001110 +0000000011101010111000000000101010100000000010101010000000001010101000 +0000000000101000000000000010100000000000001110 \ No newline at end of file diff --git a/assets/gps-off.pbm b/assets/gps-off.pbm index 92839b0..5f2ddee 100644 --- a/assets/gps-off.pbm +++ b/assets/gps-off.pbm @@ -1,7 +1,7 @@ P1 -# Created by GIMP version 3.0.4 PNM plug-in +# Created by GIMP version 3.0.6 PNM plug-in 16 16 -0100001111000010111001000010011101111011110111100011111001111100000111 -0000111000000111100111100000010111111010000000101111010000000010111101 -0000000001111110000000001110011100000001111001111000001110100101110001 -1100011000111011100001100001110100000000000010 \ No newline at end of file +0000000000000000011000000000011001111000000011100011110000011100001111 +1000111000001011110111000001000111111000000100001111000000010000111110 +0000001001111111000000101110011110000001110000111100001110000001110001 +1101100011111001100001110001100000000000000000 \ No newline at end of file diff --git a/assets/gps-on.pbm b/assets/gps-on.pbm index 903e5e2..5bd338d 100644 --- a/assets/gps-on.pbm +++ b/assets/gps-on.pbm @@ -1,7 +1,7 @@ P1 -# Created by GIMP version 3.0.4 PNM plug-in +# Created by GIMP version 3.0.6 PNM plug-in 16 16 -0000001111000000000001111110000000001111111100000001111001111000000111 -0000111000000111000011100000011110011110000000111111110000000011111111 -0000000001111110000000000111111000000000001111000000000000111100000000 -0000011000000000000001100000000000000000000000 \ No newline at end of file +0000000000000000000000000000101000001000000001000001110000011010001111 +1000111000001111110111000001111111111000000111111111000000011111111110 +0000001111111111000000111111111110000001111111111100000011111111100000 +0001111111000000000001110000000000000000000000 \ No newline at end of file diff --git a/assets/gravity-located.pbm b/assets/gravity-located.pbm new file mode 100644 index 0000000..c82044a --- /dev/null +++ b/assets/gravity-located.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0000000000000000000000000000000000000001100000000000000110000000000000 +0110000000000000011000000000000001100000000000111111110000000001111110 +0000000000111100000011100001100001110001110000111000000000111100000011 +1000000000011100011100001110000000001111000000 \ No newline at end of file diff --git a/assets/gravity-missing.pbm b/assets/gravity-missing.pbm new file mode 100644 index 0000000..f7d25a7 --- /dev/null +++ b/assets/gravity-missing.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0000000110000000000001111110000000001110011100000000110000110000000000 +0000110000000000001110000000000001110000000000000110000000000000000000 +0000000000011000000011100001100001110001110000111000000000111100000011 +1000000000011100011100001110000000001111000000 \ No newline at end of file diff --git a/assets/location-off.pbm b/assets/location-off.pbm new file mode 100644 index 0000000..92839b0 --- /dev/null +++ b/assets/location-off.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.4 PNM plug-in +16 16 +0100001111000010111001000010011101111011110111100011111001111100000111 +0000111000000111100111100000010111111010000000101111010000000010111101 +0000000001111110000000001110011100000001111001111000001110100101110001 +1100011000111011100001100001110100000000000010 \ No newline at end of file diff --git a/assets/location-on.pbm b/assets/location-on.pbm new file mode 100644 index 0000000..903e5e2 --- /dev/null +++ b/assets/location-on.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.4 PNM plug-in +16 16 +0000001111000000000001111110000000001111111100000001111001111000000111 +0000111000000111000011100000011110011110000000111111110000000011111111 +0000000001111110000000000111111000000000001111000000000000111100000000 +0000011000000000000001100000000000000000000000 \ No newline at end of file diff --git a/assets/offline.pbm b/assets/offline.pbm new file mode 100644 index 0000000..a828afb --- /dev/null +++ b/assets/offline.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0111000000000000101010000000000011011000000000001010100000000000011100 +0000000000001001100000011000100111000011100010001110011100001000011111 +1000001000001111000000100000111100000010000111111000001000111001110000 +1001110000111000100110000001100010000000000000 \ No newline at end of file diff --git a/assets/online-connecting.pbm b/assets/online-connecting.pbm new file mode 100644 index 0000000..e51f2c1 --- /dev/null +++ b/assets/online-connecting.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0111000000000000101010000000000011011000000000001010100000000000011100 +0000000000001000100000000000100101000000000010001000000000001001010000 +0000001000100010000000100101010100000010001000100000001001010101001000 +1000100010010100100101010100100010001000100101 \ No newline at end of file diff --git a/assets/online-full.pbm b/assets/online-full.pbm new file mode 100644 index 0000000..63cc727 --- /dev/null +++ b/assets/online-full.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0111000000000000101010000000000011011000000000001010100000000000011100 +0000000000001001110000000000100111000000000010011100000000001001110000 +0000001001110111000000100111011100000010011101110000001001110111011100 +1001110111011100100111011101110010011101110111 \ No newline at end of file diff --git a/assets/online-low-quality.pbm b/assets/online-low-quality.pbm new file mode 100644 index 0000000..223659e --- /dev/null +++ b/assets/online-low-quality.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0111000000000000101010000000000011011000000000001010100000000000011100 +0000000000001000100000000000100101000000000010001000000000001001010000 +0000001000100111000000100101011100000010001001110000001001010111011100 +1000100111011100100101011101110010001001110111 \ No newline at end of file diff --git a/assets/online-poor-quality.pbm b/assets/online-poor-quality.pbm new file mode 100644 index 0000000..deb65b9 --- /dev/null +++ b/assets/online-poor-quality.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0111000000000000101010000000000011011000000000001010100000000000011100 +0000000000001000100000000000100101000000000010001000000000001001010000 +0000001000100010000000100101010100000010001000100000001001010101011100 +1000100010011100100101010101110010001000100111 \ No newline at end of file diff --git a/assets/tape.pbm b/assets/tape.pbm new file mode 100644 index 0000000..87335ff --- /dev/null +++ b/assets/tape.pbm @@ -0,0 +1,7 @@ +P1 +# Created by GIMP version 3.0.6 PNM plug-in +16 16 +0000000000000000000000000000000000000000000000001111111111111111100000 +0000000001101000000000010110001111111100011001011111101001100011111111 +0001100000000000000110100111111001011000100000010001111111111111111100 +0000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/src/ego/engine.rs b/src/ego/engine.rs index 6e4dd66..fac515d 100644 --- a/src/ego/engine.rs +++ b/src/ego/engine.rs @@ -5,7 +5,7 @@ use log::*; use core::fmt::Debug; -use crate::{ego::{heading::HeadingEstimator, kalman::Ekf2D, orientation::OrientationEstimator}, events::{Notification, Prediction}, idle::IdleClock, Breaker, CircularBuffer}; +use crate::{Breaker, CircularBuffer, ego::{heading::HeadingEstimator, kalman::Ekf2D, orientation::OrientationEstimator}, events::{Notification, Prediction, SensorSource, SensorState}, idle::IdleClock}; #[derive(PartialEq, Debug, Default, Clone, Copy)] pub enum MotionState { @@ -28,8 +28,10 @@ pub struct BikeStates { reference_fix: Option>, // The first GPS value, which is used to make sense out of the EKF output which is in meters offset from this point // State switches - is_calibrated: Breaker, + has_down: Breaker, + has_forwards: Breaker, motion_state: Breaker, + acquiring_data: Breaker, // FIXME: pub pub has_gps_fix: Breaker, predicted_velocity: Breaker, @@ -55,6 +57,7 @@ impl Debug for BikeStates { impl BikeStates { pub fn insert_gps(&mut self, gps_pos: Vector2) { + self.acquiring_data.set(true); match self.reference_fix { None => { self.reference_fix = Some(gps_pos); @@ -77,6 +80,7 @@ impl BikeStates { } pub fn insert_imu(&mut self, accel: Vector3, gyro: Vector3) { + self.acquiring_data.set(true); self.orientation.insert(accel); if self.orientation.has_down() { @@ -98,19 +102,33 @@ impl BikeStates { self.kf.update_zupt(); } - self.is_calibrated.set(true); + self.has_down.set(true); + + if self.orientation.is_ready() { + self.has_forwards.set(true); + } } } pub async fn commit(&mut self, predictions: &DynamicSender<'static, Prediction>, notifications: &DynPublisher<'static, Notification>) { - if let Some(true) = self.is_calibrated.read_tripped() { - notifications.publish(Notification::SensorOnline(crate::events::SensorSource::IMU)).await + if let Some(true) = self.acquiring_data.read_tripped() { + notifications.publish(Notification::SensorStatus(SensorSource::ForwardsReference, SensorState::AcquiringFix)).await; + notifications.publish(Notification::SensorStatus(SensorSource::GravityReference, SensorState::AcquiringFix)).await; + notifications.publish(Notification::SensorStatus(SensorSource::Location, SensorState::AcquiringFix)).await; + } + + if let Some(true) = self.has_down.read_tripped() { + notifications.publish(Notification::SensorStatus(SensorSource::GravityReference, SensorState::Online)).await + } + + if let Some(true) = self.has_forwards.read_tripped() { + notifications.publish(Notification::SensorStatus(SensorSource::ForwardsReference, SensorState::Online)).await } match self.has_gps_fix.read_tripped() { None => (), - Some(true) => notifications.publish(Notification::SensorOnline(crate::events::SensorSource::GPS)).await, - Some(false) => notifications.publish(Notification::SensorOffline(crate::events::SensorSource::GPS)).await, + Some(true) => notifications.publish(Notification::SensorStatus(SensorSource::Location, SensorState::Online)).await, + Some(false) => notifications.publish(Notification::SensorStatus(SensorSource::Location, SensorState::Degraded)).await, } let est = self.kf.x; @@ -182,7 +200,8 @@ impl Default for BikeStates { last_stamp: Instant::now(), speedo: Default::default(), heading: Default::default(), - is_calibrated: Default::default(), + has_down: Default::default(), + has_forwards: Default::default(), kf: Default::default(), steady_timer: IdleClock::new(Duration::from_secs(3)), last_fix: Default::default(), @@ -191,7 +210,8 @@ impl Default for BikeStates { predicted_location: Default::default(), predicted_velocity: Default::default(), reported_velocity: Default::default(), - wake_requested: Default::default() + wake_requested: Default::default(), + acquiring_data: Default::default() } } } diff --git a/src/events.rs b/src/events.rs index c93badf..d095d4c 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,6 +1,8 @@ use embassy_sync::{blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, channel::Channel, pubsub::PubSubChannel}; use embassy_time::Duration; +use enum_map::Enum; +use enumset::EnumSetType; use nalgebra::{Vector2, Vector3}; use crate::{graphics::display::DisplayControls, ego::engine::MotionState}; @@ -14,6 +16,22 @@ pub enum Scene { Idle, // Default state when waking up from sleep, or entered when accelerometers and GPS both show zero motion for ~30 seconds } +#[derive(Clone, Copy, Default, Debug)] +pub enum SensorState { + #[default] + // There is no connection to the sensor + Offline, + + // Sensor is starting up + AcquiringFix, + + // Sensor is ready and is generating data + Online, + + // Sensor was previously fully functioning but currently is not (eg, gps fix lost) + Degraded, +} + #[derive(Clone, Copy, Debug)] pub enum Measurement { // GPS coordinates @@ -22,8 +40,7 @@ pub enum Measurement { IMU { accel: Vector3, gyro: Vector3 }, // Hardware status updates - SensorOnline(SensorSource), - SensorOffline(SensorSource), + SensorHardwareStatus(SensorSource, SensorState), // Simulation metadata updates SimulationProgress(SensorSource, Duration, f32) @@ -43,12 +60,7 @@ pub enum Notification { SceneChange(Scene), // States of external connections to the world - SensorOnline(SensorSource), - SensorOffline(SensorSource), - - // TODO: Should be emitted by the prediction engine after it doesn't get any sensor data for some time. Perhaps the threads are somehow deadlocked and a reboot is needed if it doesn't recover - SensorsOffline, - + SensorStatus(SensorSource, SensorState), // The prediction engine has decided that the system should be woken up and begin running again WakeUp, // The prediction engine has decided that the system is inactive enough and it should go to low-power sleep @@ -68,10 +80,20 @@ pub enum Telemetry { Prediction(Prediction), } -#[derive(Clone, Copy, Debug)] +#[derive(Debug, EnumSetType, Enum)] pub enum SensorSource { + // Real hardware IMU, - GPS + GPS, + + // Fusion outputs + GravityReference, + ForwardsReference, + Location, + + // Simulated sensors + Demo, + Simulation } #[derive(Debug)] diff --git a/src/graphics/oled_ui.rs b/src/graphics/oled_ui.rs index 542ee2d..7bad59a 100644 --- a/src/graphics/oled_ui.rs +++ b/src/graphics/oled_ui.rs @@ -1,14 +1,15 @@ use core::f32::consts::PI; -use core::fmt::Binary; use alloc::format; +use embedded_graphics::image::ImageRaw; use embedded_graphics::mono_font::ascii::*; use embedded_graphics::mono_font::{MonoTextStyle, MonoTextStyleBuilder}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::Size; +use embedded_graphics::prelude::{DrawTarget, Size}; use embedded_graphics::primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder, StyledDrawable}; use embedded_graphics::text::{Alignment, Text}; use embedded_graphics::{image::Image, prelude::Point, Drawable}; +use enum_map::EnumMap; use figments::liber8tion::trig::sin8; use figments::mappings::embedded_graphics::Matrix2DSpace; use figments::{liber8tion::trig::cos8, mappings::embedded_graphics::EmbeddedGraphicsSampler}; @@ -17,6 +18,7 @@ use nalgebra::Vector2; use micromath::F32Ext; use embedded_graphics::geometry::OriginDimensions; +use crate::events::{SensorSource, SensorState}; use crate::graphics::images; use crate::{ego::engine::MotionState, events::Scene}; @@ -26,8 +28,7 @@ pub struct OledUI { pub motion: MotionState, pub brakelight: bool, pub headlight: bool, - pub gps_online: bool, - pub imu_online: bool, + pub sensor_states: EnumMap, pub velocity: f32, pub location: Vector2, pub sleep: bool, @@ -50,6 +51,90 @@ pub enum Screen { Waking } +struct SensorImage { + source: SensorSource, + on: &'static ImageRaw<'static, BinaryColor>, + off: &'static ImageRaw<'static, BinaryColor>, +} + +struct SensorIcon<'a> { + anchor: embedded_graphics::geometry::Point, + image: &'a SensorImage, + state: SensorState, + frame: usize +} + +impl<'a> SensorIcon<'a> { + pub const fn new(image: &'a SensorImage, state: SensorState, frame: usize, anchor: embedded_graphics::geometry::Point) -> Self { + Self { + anchor, + image, + state, + frame + } + } + + pub fn draw>(&self, target: &mut T) -> Result<(), T::Error> { + match self.state { + SensorState::AcquiringFix => { + if (self.frame / 10) % 2 == 0 { + Image::new(self.image.off, self.anchor).draw(target) + } else { + Ok(()) + } + }, + SensorState::Online => { + Image::new(self.image.on, self.anchor).draw(target) + }, + SensorState::Offline => { + Image::new(self.image.off, self.anchor).draw(target) + }, + SensorState::Degraded => { + if (self.frame / 10) % 2 == 0 { + Image::new(self.image.on, self.anchor).draw(target) + } else { + Ok(()) + } + } + } + } +} + +const SENSOR_IMAGES: &[SensorImage] = &[ + SensorImage { + source: SensorSource::GPS, + on: &images::GPS_ON, off: &images::GPS_OFF, + }, + SensorImage { + source: SensorSource::IMU, + on: &images::IMU_ON, off: &images::IMU_OFF, + }, + SensorImage { + source: SensorSource::GravityReference, + on: &images::GRAVITY_LOCATED, off: &images::GRAVITY_MISSING, + }, + SensorImage { + source: SensorSource::Location, + on: &images::LOCATION_ON, off: &images::LOCATION_OFF, + }, + #[cfg(feature="demo")] + SensorImage { + source: SensorSource::Demo, + on: &images::DEMO, off: &images::DEMO, + }, + #[cfg(feature="simulation")] + SensorImage { + source: SensorSource::Simulation, + on: &images::TAPE, off: &images::TAPE + }, +]; + +const DISPLAY_SIZE: Size = Size::new(128, 64); +const SENSOR_ICON_SIZE: u32 = 16; +const SENSOR_ICON_SPACING: u32 = 2; +const SENSOR_TRAY_SIZE: Size = Size::new(SENSOR_IMAGES.len() as u32 * (SENSOR_ICON_SIZE + SENSOR_ICON_SPACING), SENSOR_ICON_SIZE + SENSOR_ICON_SPACING); +const SPEEDO_TRAY_SIZE: Size = Size::new(DISPLAY_SIZE.width - SENSOR_TRAY_SIZE.width, SENSOR_TRAY_SIZE.height); + impl Screen { pub fn draw_screen<'a, T>(&self, sampler: &mut EmbeddedGraphicsSampler<'a, T>, state: &OledUniforms) where T: Sample<'a, Matrix2DSpace>, T::Output: PixelSink { match self { @@ -74,36 +159,22 @@ impl Screen { Screen::Home => { // Status bar // Sensor indicators - let gps_img = if state.ui.gps_online { - &images::GPS_ON - } else { - &images::GPS_OFF - }; - let imu_img = if state.ui.imu_online { - &images::IMU_ON - } else { - &images::IMU_OFF - }; - Image::new(gps_img, Point::zero()).draw(sampler).unwrap(); - Image::new(imu_img, Point::new((gps_img.size().width + 2) as i32, 0)).draw(sampler).unwrap(); + for (idx, sensor) in SENSOR_IMAGES.iter().enumerate() { + let offset = idx * (16 + 2); + let position = Point::new(offset as i32, 0); + SensorIcon::new(sensor, state.ui.sensor_states[sensor.source], state.frame, position) + .draw(sampler).unwrap(); + } - #[cfg(feature="demo")] - Text::with_alignment("Demo", Point::new(128, 10), TEXT_STYLE, Alignment::Right) - .draw(sampler) - .unwrap(); + let speedo_center = SENSOR_TRAY_SIZE.width + SPEEDO_TRAY_SIZE.width / 2; - #[cfg(feature="simulation")] - Text::with_alignment("Sim", Point::new(128, 10), TEXT_STYLE, Alignment::Right) + // Speed display at the top + Text::with_alignment(&format!("{}", state.ui.velocity), Point::new(speedo_center as i32, 12), SPEED_STYLE, Alignment::Center) .draw(sampler) .unwrap(); // Separates the status bar from the UI - Line::new(Point::new(0, 18), Point::new(128, 18)).draw_styled(&INACTIVE_STYLE, sampler).unwrap(); - - // Speed display at the top - Text::with_alignment(&format!("{}", state.ui.velocity), Point::new(128 / 2, 12), SPEED_STYLE, Alignment::Center) - .draw(sampler) - .unwrap(); + Line::new(Point::new(0, SENSOR_TRAY_SIZE.height as i32), Point::new(128, SENSOR_TRAY_SIZE.height as i32)).draw_styled(&INACTIVE_STYLE, sampler).unwrap(); // The main UI content Image::new(&images::BIKE, Point::new((128 / 2 - images::BIKE.size().width / 2) as i32, 24)).draw(sampler).unwrap(); diff --git a/src/tasks/demo.rs b/src/tasks/demo.rs index d1a4ca0..3821cab 100644 --- a/src/tasks/demo.rs +++ b/src/tasks/demo.rs @@ -1,7 +1,7 @@ use embassy_sync::pubsub::DynPublisher; use embassy_time::Timer; -use crate::events::{Notification, Scene}; +use crate::events::{Notification, Scene, SensorSource, SensorState}; #[embassy_executor::task] @@ -11,10 +11,16 @@ pub async fn demo_task(ui: DynPublisher<'static, Notification>) { ui.publish(Notification::SetBrakelight(true)).await; ui.publish(Notification::SetHeadlight(true)).await; Timer::after_secs(10).await; + ui.publish(Notification::SensorStatus(SensorSource::Demo, SensorState::AcquiringFix)).await; loop { for scene in [Scene::Accelerating, Scene::Ready, Scene::Decelerating, Scene::Ready] { - Timer::after_secs(8).await; - ui.publish(Notification::SceneChange(scene)).await - }; + ui.publish(Notification::SceneChange(scene)).await; + for state in [SensorState::Offline, SensorState::AcquiringFix, SensorState::Degraded, SensorState::Offline] { + for sensor in [SensorSource::ForwardsReference, SensorSource::GPS, SensorSource::GravityReference, SensorSource::IMU, SensorSource::Location] { + ui.publish(Notification::SensorStatus(sensor, state)).await; + } + Timer::after_secs(1).await; + } + } } } \ No newline at end of file diff --git a/src/tasks/motion.rs b/src/tasks/motion.rs index 749c775..54683fc 100644 --- a/src/tasks/motion.rs +++ b/src/tasks/motion.rs @@ -1,7 +1,7 @@ use embassy_sync::{channel::{DynamicReceiver, DynamicSender}, pubsub::DynPublisher}; use log::*; -use crate::{ego::engine::BikeStates, events::{Measurement, Notification, Prediction}}; +use crate::{ego::engine::BikeStates, events::{Measurement, Notification, Prediction, SensorSource, SensorState}}; #[embassy_executor::task] pub async fn motion_task(src: DynamicReceiver<'static, Measurement>, ui_sink: DynPublisher<'static, Notification>, prediction_sink: DynamicSender<'static, Prediction>) { @@ -24,8 +24,10 @@ pub async fn motion_task(src: DynamicReceiver<'static, Measurement>, ui_sink: Dy states.has_gps_fix.set(false); }, // FIXME: This needs harmonized with the automatic data timeout from above, somehow? - Measurement::SensorOnline(source) => warn!("Sensor {source:?} reports online!"), - Measurement::SensorOffline(source) => warn!("Sensor {source:?} reports offline!"), + Measurement::SensorHardwareStatus(source, state) => { + warn!("Sensor {source:?} reports {state:?}!"); + ui_sink.publish(Notification::SensorStatus(source, state)).await; + }, Measurement::SimulationProgress(source, duration, _pct) => debug!("{source:?} simulation time: {}", duration.as_secs()), } } diff --git a/src/tasks/mpu.rs b/src/tasks/mpu.rs index f4ebead..c834dd3 100644 --- a/src/tasks/mpu.rs +++ b/src/tasks/mpu.rs @@ -31,7 +31,6 @@ fn gyro_raw_to_rads(raw: i16) -> f32 { #[esp_hal::ram(rtc_fast, persistent)] static mut MPU_WAS_CALIBRATED: u8 = 0; -//static mut MPU_CALIBRATION: Option<(Accel, Gyro)> = None; #[embassy_executor::task] pub async fn mpu_task(events: DynamicSender<'static, Measurement>, bus: I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Async>>) { @@ -39,6 +38,7 @@ pub async fn mpu_task(events: DynamicSender<'static, Measurement>, bus: I2cDevic let busref = RefCell::new(Some(bus)); backoff.forever().attempt::<_, (), ()>(async || { + events.send(Measurement::SensorHardwareStatus(SensorSource::IMU, crate::events::SensorState::Offline)).await; let mut sensor = backoff.forever().attempt(async || { warn!("Initializing connection to MPU"); match Mpu6050::new(busref.replace(None).unwrap(), Address::default()).await.map_err(|e| { e.i2c }) { @@ -47,6 +47,7 @@ pub async fn mpu_task(events: DynamicSender<'static, Measurement>, bus: I2cDevic Err(()) }, Ok(mut sensor) => { + events.send(Measurement::SensorHardwareStatus(SensorSource::IMU, crate::events::SensorState::AcquiringFix)).await; match backoff.attempt(async || { mpu_init(&mut sensor).await }).await { Err(_) => { busref.replace(Some(sensor.release())); @@ -60,7 +61,7 @@ pub async fn mpu_task(events: DynamicSender<'static, Measurement>, bus: I2cDevic let sensor_ref = &mut sensor; - events.send(Measurement::SensorOnline(SensorSource::IMU)).await; + events.send(Measurement::SensorHardwareStatus(SensorSource::IMU, crate::events::SensorState::Online)).await; //TODO: Need to read in a constant buffer of accelerometer measurements, which we can then use to determine where "forward" points in the body frame when converting from the sensor frame. // From there, we can rotate the body frame into the world frame using gps headings to generate a compass north fn lowpass(prev: f32, current: f32, alpha: f32) -> f32 { diff --git a/src/tasks/oled.rs b/src/tasks/oled.rs index 9c5a062..bd0550c 100644 --- a/src/tasks/oled.rs +++ b/src/tasks/oled.rs @@ -7,7 +7,7 @@ use figments::{mappings::embedded_graphics::Matrix2DSpace, prelude::{Coordinates use figments_render::output::{Brightness, OutputAsync}; use log::*; -use crate::{animation::Animation, backoff::Backoff, events::{Notification, Prediction, SensorSource, Telemetry}, graphics::{display::DisplayControls, oled_ui::{OledUniforms, Screen}}}; +use crate::{animation::Animation, backoff::Backoff, events::{Notification, Prediction, SensorSource, SensorState, Telemetry}, graphics::{display::DisplayControls, oled_ui::{OledUniforms, Screen}}}; #[cfg(feature="oled")] pub type OledUiSurfacePool = BufferedSurfacePool; @@ -84,10 +84,7 @@ impl self.with_uniforms(|state| {state.ui.scene = scene}).await, Telemetry::Notification(Notification::SetBrakelight(b)) => self.with_uniforms(|state| {state.ui.brakelight = b}).await, Telemetry::Notification(Notification::SetHeadlight(b)) => self.with_uniforms(|state| {state.ui.headlight = b}).await, - Telemetry::Notification(Notification::SensorOffline(SensorSource::IMU)) => self.with_uniforms(|state| {state.ui.imu_online = false}).await, - Telemetry::Notification(Notification::SensorOnline(SensorSource::IMU)) => self.with_uniforms(|state| {state.ui.imu_online = true}).await, - Telemetry::Notification(Notification::SensorOffline(SensorSource::GPS)) => self.with_uniforms(|state| {state.ui.gps_online = false}).await, - Telemetry::Notification(Notification::SensorOnline(SensorSource::GPS)) => self.with_uniforms(|state| {state.ui.gps_online = true}).await, + Telemetry::Notification(Notification::SensorStatus(src, sensor_state)) => self.with_uniforms(|state| {state.ui.sensor_states[src] = sensor_state}).await, _ => () } } diff --git a/src/tasks/ui.rs b/src/tasks/ui.rs index a92aa4d..9b8958e 100644 --- a/src/tasks/ui.rs +++ b/src/tasks/ui.rs @@ -6,7 +6,7 @@ use core::fmt::Debug; use futures::join; use log::*; -use crate::{animation::{AnimatedSurface, Animation}, graphics::display::{SegmentSpace, Uniforms}, events::{Notification, Scene, SensorSource, Telemetry}, graphics::shaders::*}; +use crate::{animation::{AnimatedSurface, Animation}, events::{Notification, Scene, SensorSource, SensorState, Telemetry}, graphics::{display::{SegmentSpace, Uniforms}, shaders::*}}; pub struct Ui { // Background layer provides an always-running background for everything to draw on @@ -139,19 +139,13 @@ impl self.flash_notification_color(Rgb::new(0, 255, 0)).await, - Notification::SensorOffline(SensorSource::GPS) => self.flash_notification_color(Rgb::new(255, 0, 0)).await, - Notification::SensorOnline(SensorSource::GPS) => self.flash_notification_color(Rgb::new(0, 255, 255)).await, + Notification::SensorStatus(SensorSource::IMU, SensorState::Online) => self.flash_notification_color(Rgb::new(0, 255, 0)).await, + Notification::SensorStatus(SensorSource::Location, SensorState::Degraded) => self.flash_notification_color(Rgb::new(255, 0, 0)).await, + Notification::SensorStatus(SensorSource::GPS, SensorState::Online) => self.flash_notification_color(Rgb::new(0, 255, 255)).await, // Scene change Notification::SceneChange(scene) => self.apply_scene(scene).await, - Notification::SensorsOffline => { - self.flash_notification_color(Rgb::new(255, 0, 0)).await; - self.flash_notification_color(Rgb::new(0, 255, 0)).await; - self.flash_notification_color(Rgb::new(0, 0, 255)).await; - } - Notification::WakeUp => self.show().await, _ => ()