diff --git a/Cargo.lock b/Cargo.lock index 50c4090..deb7eae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,6 +437,7 @@ dependencies = [ "embedded-hal 1.0.0", "heapless", "micromath", + "portable-atomic", "qingke", "qingke-rt", ] @@ -512,6 +513,9 @@ name = "portable-atomic" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +dependencies = [ + "critical-section", +] [[package]] name = "proc-macro-error" diff --git a/Cargo.toml b/Cargo.toml index 0075a12..95e021b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ embassy-futures = "0.1.1" heapless = "0.8.0" critical-section = "1.2.0" micromath = "2.1.0" +portable-atomic = { version = "1.10.0", features = ["critical-section"] } [profile.release] strip = false @@ -36,4 +37,4 @@ opt-level = "z" strip = false lto = false debug = true -opt-level = 1 +opt-level = 1 \ No newline at end of file diff --git a/client/Cargo.lock b/client/Cargo.lock new file mode 100644 index 0000000..6a21d62 --- /dev/null +++ b/client/Cargo.lock @@ -0,0 +1,1146 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "built" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cc" +version = "1.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "client" +version = "0.1.0" +dependencies = [ + "image", + "serialport", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "image" +version = "0.25.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "io-kit-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" +dependencies = [ + "core-foundation-sys", + "mach2", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libudev" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b324152da65df7bb95acfcaab55e3097ceaab02fb19b228a9eb74d55f135e0" +dependencies = [ + "libc", + "libudev-sys", +] + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[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", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serialport" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ecfc4858c2266c7695d8b8460bbd612fa81bd2e250f5f0dd16195e4b4f8b3d8" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "core-foundation", + "core-foundation-sys", + "io-kit-sys", + "libudev", + "mach2", + "nix", + "scopeguard", + "unescaper", + "winapi", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unescaper" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815" +dependencies = [ + "thiserror", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winnow" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +dependencies = [ + "zune-core", +] diff --git a/client/Cargo.toml b/client/Cargo.toml new file mode 100644 index 0000000..9db3411 --- /dev/null +++ b/client/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "client" +version = "0.1.0" +edition = "2021" + +[dependencies] +image = "0.25.5" +serialport = "4.7.0" diff --git a/client/src/main.rs b/client/src/main.rs new file mode 100644 index 0000000..50aa166 --- /dev/null +++ b/client/src/main.rs @@ -0,0 +1,88 @@ +use image::ImageReader; +use std::env; +use std::fs::{self, DirEntry}; +use std::path::{Path, PathBuf}; +use std::thread::sleep; +use std::time::Duration; + +#[repr(u8)] +#[derive(Eq, PartialEq, Debug)] +enum Command { + Info = 0, + Frame = 1, + Brightness = 2, + Invalid = 255, +} + +fn find_images(path: PathBuf) -> Vec { + let mut res = Vec::new(); + for f in path.read_dir().unwrap() { + if let Ok(entry) = f { + if entry.file_name().as_encoded_bytes().ends_with(b".png") { + res.push(entry); + } + } + } + res +} + +fn main() { + let mut args = env::args(); + + let mut port = serialport::new(args.nth(1).unwrap(), 1_000_000) + .open() + .unwrap(); + let frames = find_images("frames/".into()); + let src_fps = 50; + + port.write(&[Command::Info as u8, 0, 0]).unwrap(); + port.set_timeout(Duration::from_secs(1)).unwrap(); + + let (width, height, tgt_fps, mut cur_frame) = { + let mut info = [0u8; 14]; + port.read_exact(&mut info).unwrap(); + let width = u16::from_be_bytes(info[0..2].try_into().unwrap()); + let height = u16::from_be_bytes(info[2..4].try_into().unwrap()); + let tgt_fps = u16::from_be_bytes(info[4..6].try_into().unwrap()); + let cur_frame = u64::from_be_bytes(info[6..14].try_into().unwrap()); + (width, height, tgt_fps, cur_frame) + }; + + let src_frametime = 1. / src_fps as f64; + let dst_frametime = 1. / tgt_fps as f64; + let frames_per_frame = (tgt_fps / src_fps) as u64; + + let frame_pkt_size = width * height + 8; + + let bright = 0; + port.write(&[Command::Brightness as u8]).unwrap(); + port.write(&1u16.to_be_bytes()).unwrap(); + port.write(&[bright]).unwrap(); + { + let mut buf = [0u8; 1]; + port.read_exact(&mut buf).unwrap(); + } + + loop { + for frame in &frames { + let next_frame = cur_frame + frames_per_frame; + let img = ImageReader::open(frame.path()).unwrap().decode().unwrap(); + let gs = img.as_luma8().unwrap(); + println!( + "writing frame bytes {} for display at {}, cur_frame: {}", + gs.len(), + next_frame, cur_frame + ); + port.write(&[Command::Frame as u8]).unwrap(); + port.write(&frame_pkt_size.to_be_bytes()).unwrap(); + port.write(&next_frame.to_be_bytes()).unwrap(); + port.write(&gs).unwrap(); + cur_frame = { + let mut buf = [0; 8]; + port.read_exact(&mut buf).unwrap(); + u64::from_be_bytes(buf) + }; + sleep(Duration::from_secs_f64(src_frametime)); + } + } +} diff --git a/src/main.rs b/src/main.rs index fb08fbf..9520fe5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,14 +23,19 @@ use hal::timer::simple_pwm::{PwmPin, SimplePwm}; use hal::{peripherals, usbd}; use heapless::{binary_heap::Min, BinaryHeap}; use micromath::F32Ext; +use portable_atomic::AtomicU64; bind_interrupts!(struct Irqs { USB_LP_CAN1_RX0 => usbd::InterruptHandler; }); const FPS: usize = 120; +const WIDTH: usize = 16; +const HEIGHT: usize = 16; const EMPTY_FRAME: Frame = Frame::empty(); -static FRAME_QUEUE: Mutex>> = + +static CUR_FRAME: AtomicU64 = AtomicU64::new(0); +static MBI_QUEUE: Mutex>> = Mutex::new(RefCell::new(BinaryHeap::new())); /// Unfortunately embedded_hal doesn't support atomic writes to multiple bytes, which is required for this implementation, so we must take a platform register :( @@ -41,7 +46,8 @@ struct MBI5043 { port: Gpio, } -#[repr(u32)] +// Should be an enum containing the data itself, for auto generic +#[repr(u8)] enum DataType { Data = 1, Global = 3, @@ -132,14 +138,181 @@ impl<'a, SDI: Pin, DCLK: Pin, LE: Pin> MBI5043 { pub trait MBI { fn send_pixels u16>(&self, pixels: &[u8], transform: T); + fn set_gain(&self, gain: u8); } impl MBI for MBI5043 { fn send_pixels u16>(&self, pixels: &[u8], transform: T) { for pixel in pixels { - self.send_word::<1>(&transform(*pixel)); + self.send_word::<{ DataType::Data as u8 }>(&transform(*pixel)); + } + // dummy word to latch the output registers + self.send_word::<{ DataType::Global as u8 }>(&0x0000); + } + // TODO: Need to store rest of the config and restore it here + fn set_gain(&self, gain: u8) { + let config = (gain as u16) << 4; + self.send_word::<15>(&config); + self.send_word::<11>(&config); + } +} + +#[derive(Debug)] +enum ProtocolState { + WaitCmd, + WaitLengthLsb, + WaitLengthMsb, + WaitData, +} + +#[repr(u8)] +#[derive(Eq, PartialEq, Debug)] +enum Command { + Info = 0, + Frame = 1, + Brightness = 2, + Invalid = 255, +} + +impl From for Command { + fn from(value: u8) -> Self { + match value { + 0 => Command::Info, + 1 => Command::Frame, + 2 => Command::Brightness, + _ => Command::Invalid, + } + } +} + +struct Protocol<'d, T: usbd::Instance + 'd> { + class: &'d mut CdcAcmClass<'d, usbd::Driver<'d, T>>, + state: ProtocolState, + cmd: Command, + to_read: u16, + cur_pos: usize, + buf: [u8; 1024], +} + +impl<'d, T: usbd::Instance + 'd> Protocol<'d, T> { + fn new(class: &'d mut CdcAcmClass<'d, usbd::Driver<'d, T>>) -> Self { + Self { + class, + state: ProtocolState::WaitCmd, + cmd: Command::Info, + to_read: 0, + cur_pos: 0, + buf: [0; 1024], + } + } + fn transition(&mut self, new_state: ProtocolState) { + // println!("transition {:?} -> {:?}", self.state, new_state); + self.state = new_state + } + async fn receive(&mut self) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = self.class.read_packet(&mut buf).await?; + let mut data = &buf[..n]; + while !data.is_empty() { + match self.state { + ProtocolState::WaitCmd => { + let cmd: Command = data[0].into(); + if cmd != Command::Invalid { + self.cmd = cmd; + self.transition(ProtocolState::WaitLengthMsb); + } + } + ProtocolState::WaitLengthMsb => { + self.to_read = (data[0] as u16) << 8; + self.transition(ProtocolState::WaitLengthLsb); + } + ProtocolState::WaitLengthLsb => { + self.cur_pos = 0; + self.to_read |= data[0] as u16; + // println!("expecting {} bytes", self.to_read); + if self.to_read != 0 { + self.transition(ProtocolState::WaitData); + } else { + self.handle().await; + self.transition(ProtocolState::WaitCmd); + } + } + ProtocolState::WaitData => { + if self.to_read != 0 { + self.buf[self.cur_pos] = data[0]; + self.cur_pos += 1; + self.to_read -= 1; + } + if self.to_read == 0 { + self.handle().await; + self.transition(ProtocolState::WaitCmd); + } + } + } + data = &data[1..]; + } + } + } + async fn send_frame_no(&mut self) { + let frame_be = CUR_FRAME + .load(core::sync::atomic::Ordering::Relaxed) + .to_be_bytes(); + self.class.write_packet(&frame_be).await.unwrap(); + } + + async fn handle(&mut self) { + // println!("handling cmd: {:?}", self.cmd); + match self.cmd { + Command::Info => self.handle_info().await, + Command::Frame => self.handle_frame().await, + Command::Brightness => self.handle_brightness().await, + Command::Invalid => unimplemented!(), + } + } + + // response: + // u16 width + // u16 height + // u16 fps + // u64 cur_frame + async fn handle_info(&mut self) { + let width_be = (WIDTH as u16).to_be_bytes(); + let height_be = (HEIGHT as u16).to_be_bytes(); + let fps_be = (FPS as u16).to_be_bytes(); + self.class.write_packet(&width_be).await.unwrap(); + self.class.write_packet(&height_be).await.unwrap(); + self.class.write_packet(&fps_be).await.unwrap(); + self.send_frame_no().await; + } + + // data: + // u64 when + // u8[WIDTH * HEIGHT] pixels + // response: + // u64 cur_frame + async fn handle_frame(&mut self) { + let cmd = MbiCommand::frame_from_packet(self.buf.as_slice()); + critical_section::with(|cs| MBI_QUEUE.borrow_ref_mut(cs).push(cmd)); + self.send_frame_no().await; + } + + // data: + // u8 gain - 6 bits, 12.5 - 200% + // response: + // u8 - 255 if ok, 0 if not + async fn handle_brightness(&mut self) { + let gain = self.buf[0]; + if gain & 0b11000000 != 0 { + self.class.write_packet(&[0u8]).await.unwrap(); + } else { + critical_section::with(|cs| { + MBI_QUEUE + .borrow_ref_mut(cs) + .push(MbiCommand::from_brightness(gain)) + }).unwrap(); + self.class.write_packet(&[255u8]).await.unwrap(); } - self.send_word::<3>(&0x0000); } } @@ -193,14 +366,16 @@ async fn usb(usb: peripherals::USBD, irq: Irqs, dp: peripherals::PA12, dm: perip let usb_fut = usb.run(); let echo_fut = async { + let mut protocol = Protocol::new(&mut class); loop { - class.wait_connection().await; - receive(&mut class).await; + protocol.class.wait_connection().await; + protocol.receive().await.unwrap(); } }; join(usb_fut, echo_fut).await; } +#[derive(Debug)] struct Disconnected {} impl From for Disconnected { @@ -212,41 +387,66 @@ impl From for Disconnected { } } -async fn receive<'d, T: usbd::Instance + 'd>( - class: &mut CdcAcmClass<'d, usbd::Driver<'d, T>>, -) -> Result<(), Disconnected> { - let mut buf = [0; 64]; - loop { - let n = class.read_packet(&mut buf).await?; - let data = &buf[..n]; - class.write_packet(data).await?; - let mut frame = Frame::empty(); - frame.when = 512; - let mut i = 0; - for b in data { - for j in 0..8 { - if b & (1 << j) != 0 { - frame.pixels[i * 8 + j] = 128 - }; - } - i += 1 +#[derive(Debug)] +struct MbiCommand { + when: u64, + inner: MbiCommandInner, +} + +impl MbiCommand { + fn frame_from_packet(packet: &[u8]) -> MbiCommand { + Self { + when: u64::from_be_bytes(packet[0..8].try_into().unwrap()), + inner: Frame::from(&packet[8..]).into(), + } + } + fn from_brightness(gain: u8) -> MbiCommand { + Self { + when: 0, + inner: MbiCommandInner::Brightness(gain), } - println!("queueing new frame"); - critical_section::with(|cs| FRAME_QUEUE.borrow_ref_mut(cs).push(frame)); } } -#[derive(Ord, Eq)] +impl PartialOrd for MbiCommand { + fn partial_cmp(&self, other: &Self) -> Option { + self.when.partial_cmp(&other.when) + } +} + +impl PartialEq for MbiCommand { + fn eq(&self, other: &Self) -> bool { + self.when.eq(&other.when) + } +} +impl Eq for MbiCommand {} +impl Ord for MbiCommand { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.when.cmp(&other.when) + } +} + +#[derive(Debug)] +enum MbiCommandInner { + Frame(Frame), + Brightness(u8), +} + +impl From for MbiCommandInner { + fn from(value: Frame) -> Self { + MbiCommandInner::Frame(value) + } +} + +#[derive(Clone, Debug)] struct Frame { - when: u64, - pixels: [u8; 256], + pixels: [u8; WIDTH as usize * HEIGHT as usize], } impl Frame { const fn empty() -> Self { Self { - when: 0, - pixels: [0; 256], + pixels: [0; WIDTH as usize * HEIGHT as usize], } } } @@ -257,15 +457,15 @@ impl Default for Frame { } } -impl PartialEq for Frame { - fn eq(&self, other: &Self) -> bool { - self.when.eq(&other.when) - } -} - -impl PartialOrd for Frame { - fn partial_cmp(&self, other: &Self) -> Option { - self.when.partial_cmp(&other.when) +impl From<&[u8]> for Frame { + fn from(value: &[u8]) -> Self { + let mut pixels = [0; WIDTH as usize * HEIGHT as usize]; + for i in 0..pixels.len() { + let y = i / WIDTH as usize; + let x = WIDTH as usize - (i % WIDTH as usize) - 1; + pixels[y * WIDTH as usize + x] = value[i]; + } + Frame { pixels } } } @@ -303,14 +503,14 @@ impl Lightbar { } } async fn mbi_send_frame(&self, f: &Frame) { - for row in 0..16 { + for row in 0..HEIGHT as usize { pac::GPIOB.outdr().write_value(Outdr(0)); - self.mbi - .send_pixels(&f.pixels[row * 16..(row + 1) * 16], |val| { - self.gamma_lut.correct(val) - }); + self.mbi.send_pixels( + &f.pixels[row * WIDTH as usize..(row + 1) * WIDTH as usize], + |val| self.gamma_lut.correct(val), + ); pac::GPIOB.outdr().write_value(Outdr(1 << row)); - Timer::after_micros(1_000_000 / FPS as u64 / 17).await; + Timer::after_micros(1_000_000 / FPS as u64 / (HEIGHT as u64 + 1)).await; } } async fn display_task(&self) { @@ -322,21 +522,33 @@ impl Lightbar { .cfghr() .write_value(gpio::regs::Cfghr(0x33333333)); - let mut frame: u64 = 0; + let mut cmd: Option = None; let mut draw_frame: Frame = EMPTY_FRAME; let mut ticker = Ticker::every(Duration::from_micros(1_000_000 / FPS as u64)); + // TODO: move to interrupt driven loop { + let frame = CUR_FRAME.fetch_add(1, core::sync::atomic::Ordering::Relaxed); critical_section::with(|cs| { - let mut frames = FRAME_QUEUE.borrow_ref_mut(cs); - if frames.peek().is_some_and(|f| frame >= f.when) { - draw_frame = frames.pop().unwrap(); - println!("got new frame for {} @ {}", draw_frame.when, frame); + let mut commands = MBI_QUEUE.borrow_ref_mut(cs); + + if commands.peek().is_some_and(|v| frame >= v.when) { + cmd = commands.pop(); + } else { + cmd = None } }); - self.mbi_send_frame(&draw_frame).await; - frame += 1; - ticker.next().await + if let Some(cmd) = &cmd { + match &cmd.inner { + MbiCommandInner::Brightness(gain) => self.mbi.set_gain(*gain), + MbiCommandInner::Frame(f) => { + draw_frame = f.clone(); + } + } + } else { + self.mbi_send_frame(&draw_frame).await; + ticker.next().await + } } } } @@ -373,14 +585,9 @@ async fn main(spawner: Spawner) -> ! { ); let ch = hal::timer::Channel::Ch1; - let max_duty = pwm.get_max_duty(); pwm.set_duty(ch, 9); pwm.enable(ch); - // println!("exti: {:x}", pac::EXTI.intenr().read().0); - // pac::EXTI.intenr().modify(|w| w.set_mr(18, true)); - // println!("exti: {:x}", pac::EXTI.intenr().read().0); - let app: Lightbar = Lightbar::new(spi_mosi.degrade(), spi_sck.degrade(), le.degrade(), 2.8); spawner.spawn(usb(p.USBD, Irqs, p.PA12, p.PA11)).unwrap(); @@ -388,23 +595,6 @@ async fn main(spawner: Spawner) -> ! { .spawn(blink(p.PC14.degrade(), p.PC15.degrade())) .unwrap(); - // spawner - // .spawn(mbi_writer( - // spi_mosi.degrade(), - // spi_sck.degrade(), - // le.degrade(), - // )) - // .unwrap(); - - // spawner.spawn(busy()).unwrap(); - - critical_section::with(|cs| { - FRAME_QUEUE.borrow_ref_mut(cs).push(Frame { - when: 60, - pixels: [128; 256], - }) - }); - loop { app.display_task().await } @@ -412,8 +602,9 @@ async fn main(spawner: Spawner) -> ! { #[inline(never)] #[panic_handler] -fn panic(info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop { + println!("{:?}", _info); core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); } }