commit 00cd459f341de00051fa9e5f9b2734ba17ac31c0 Author: Keenan Tims Date: Sat Jan 4 02:51:38 2025 -0800 initial commit: poc working diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..bb8213a --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,4 @@ +[build] +target = "riscv32imc-unknown-none-elf" +[target.riscv32imc-unknown-none-elf] +runner = "wlink -v flash --enable-sdi-print --watch-serial --erase" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..656bbf8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ch32-hal"] + path = ch32-hal + url = https://github.com/ch32-rs/ch32-hal diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..50c4090 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,796 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ch32-hal" +version = "0.1.0" +dependencies = [ + "ch32-metapac", + "critical-section", + "embassy-futures", + "embassy-hal-internal", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embassy-usb-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "futures", + "nb 1.1.0", + "proc-macro2", + "qingke", + "qingke-rt", + "quote", + "rand_core", + "sdio-host", +] + +[[package]] +name = "ch32-metapac" +version = "0.1.0" +source = "git+https://github.com/ch32-rs/ch32-metapac?rev=b1cbc7a98e43af3fd3170821654784e2c01cb26b#b1cbc7a98e43af3fd3170821654784e2c01cb26b" +dependencies = [ + "riscv 0.11.1", + "vcell", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.94", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.94", +] + +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-executor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64f84599b0f4296b92a4b6ac2109bc02340094bda47b9766c5f9ec6a318ebf8" +dependencies = [ + "critical-section", + "document-features", + "embassy-executor-macros", + "embassy-time-driver", + "embassy-time-queue-driver", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3577b1e9446f61381179a330fc5324b01d511624c55f25e3c66c9e3c626dbecf" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.94", +] + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" + +[[package]] +name = "embassy-hal-internal" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef3bac31ec146321248a169e9c7b5799f1e0b3829c7a9b324cb4600a7438f59" +dependencies = [ + "num-traits", +] + +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-net-driver-channel" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4818c32afec43e3cae234f324bad9a976c9aa7501022d26ff60a4017a1a006b7" +dependencies = [ + "embassy-futures", + "embassy-net-driver", + "embassy-sync", +] + +[[package]] +name = "embassy-sync" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3899a6e39fa3f54bf8aaf00979f9f9c0145a522f7244810533abbb748be6ce82" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-sink", + "futures-util", + "heapless", +] + +[[package]] +name = "embassy-time" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "158080d48f824fad101d7b2fae2d83ac39e3f7a6fa01811034f7ab8ffc6e7309" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embassy-time-queue-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-util", + "heapless", +] + +[[package]] +name = "embassy-time-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c214077aaa9206958b16411c157961fb7990d4ea628120a78d1a5a28aed24" +dependencies = [ + "document-features", +] + +[[package]] +name = "embassy-time-queue-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1177859559ebf42cd24ae7ba8fe6ee707489b01d0bf471f8827b7b12dcb0bc0" + +[[package]] +name = "embassy-usb" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d0b882133fa684b9d4652351cd7aac5afe8a2c2bf4a7da59f442ff61087cda2" +dependencies = [ + "embassy-futures", + "embassy-net-driver-channel", + "embassy-sync", + "embassy-usb-driver", + "heapless", + "ssmarshal", + "usbd-hid", +] + +[[package]] +name = "embassy-usb-driver" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc247028eae04174b6635104a35b1ed336aabef4654f5e87a8f32327d231970" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.94", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "lightbar" +version = "0.1.0" +dependencies = [ + "ch32-hal", + "critical-section", + "embassy-executor", + "embassy-futures", + "embassy-time", + "embassy-time-driver", + "embassy-usb", + "embedded-hal 1.0.0", + "heapless", + "micromath", + "qingke", + "qingke-rt", +] + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "micromath" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "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 = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qingke" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0230c5310b68c08a3cf8b59fbeec3e9d8e352bc6500f62cbaf9c677f42c8dfc" +dependencies = [ + "bit_field", + "critical-section", + "riscv 0.12.1", +] + +[[package]] +name = "qingke-rt" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b955c60adac70c6d40205b1dbe9f57e1151d06aa842069cdbaef7bc07ad283fd" +dependencies = [ + "qingke", + "qingke-rt-macros", +] + +[[package]] +name = "qingke-rt-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ed46d18953ea5765ab26a07d1f092dffac2da1b4830c4397e02c3cec08501" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "riscv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", +] + +[[package]] +name = "riscv" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.94", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "sdio-host" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" + +[[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 2.0.94", +] + +[[package]] +name = "ssmarshal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" +dependencies = [ + "encode_unicode", + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless", + "portable-atomic", +] + +[[package]] +name = "usbd-hid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f291ab53d428685cc780f08a2eb9d5d6ff58622db2b36e239a4f715f1e184c" +dependencies = [ + "serde", + "ssmarshal", + "usb-device", + "usbd-hid-macros", +] + +[[package]] +name = "usbd-hid-descriptors" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee54712c5d778d2fb2da43b1ce5a7b5060886ef7b09891baeb4bf36910a3ed" +dependencies = [ + "bitfield", +] + +[[package]] +name = "usbd-hid-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb573c76e7884035ac5e1ab4a81234c187a82b6100140af0ab45757650ccda38" +dependencies = [ + "byteorder", + "hashbrown", + "log", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", + "usbd-hid-descriptors", +] + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "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 2.0.94", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0075a12 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "lightbar" +version = "0.1.0" +edition = "2021" + +[dependencies] +ch32-hal = { path = "ch32-hal", features = [ + "ch32v203c8t6", + "embassy", + "memory-x", + "rt", + "highcode", +], no-default-features = true } +embassy-executor = { version = "0.6.3", features = [ + "integrated-timers", + "arch-spin", + "executor-thread", +] } +qingke-rt = "*" +qingke = { version = "0.5.0" } +embedded-hal = "1.0.0" +embassy-time = { version = "0.3.2", features = ["tick-hz-10_000"] } +embassy-time-driver = "0.1.0" +embassy-usb = "0.3.0" +embassy-futures = "0.1.1" +heapless = "0.8.0" +critical-section = "1.2.0" +micromath = "2.1.0" + +[profile.release] +strip = false +lto = true +opt-level = "z" + +[profile.dev] +strip = false +lto = false +debug = true +opt-level = 1 diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..9ed9568 --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=-Tlink.x"); +} diff --git a/ch32-hal b/ch32-hal new file mode 160000 index 0000000..3ccf0c8 --- /dev/null +++ b/ch32-hal @@ -0,0 +1 @@ +Subproject commit 3ccf0c87ed952b2d8bef7b9e6193e5059a00101c diff --git a/openocd/debug.cfg b/openocd/debug.cfg new file mode 100644 index 0000000..3bcd192 --- /dev/null +++ b/openocd/debug.cfg @@ -0,0 +1,18 @@ +#interface wlink +adapter driver wlinke +adapter speed 6000 +transport select sdi + +wlink_set_address 0x00000000 +set _CHIPNAME wch_riscv +sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 + +set _TARGETNAME $_CHIPNAME.cpu + +# target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1 +set _FLASHNAME $_CHIPNAME.flash + +# flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 + +echo "Ready for Remote Connections" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..fb08fbf --- /dev/null +++ b/src/main.rs @@ -0,0 +1,419 @@ +#![no_std] +#![no_main] + +use ch32_hal::{self as hal, bind_interrupts}; +use core::borrow::{Borrow, BorrowMut}; +use core::cell::{Cell, RefCell}; +use core::panic::PanicInfo; +use critical_section::Mutex; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_time::{Duration, Ticker, Timer}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use hal::gpio::{AnyPin, Level, Output, Pin}; +use hal::pac; +use hal::pac::gpio::regs::Outdr; +use hal::pac::gpio::{self, Gpio}; +use hal::println; +use hal::time::Hertz; +use hal::timer::low_level::CountingMode; +use hal::timer::simple_pwm::{PwmPin, SimplePwm}; +use hal::{peripherals, usbd}; +use heapless::{binary_heap::Min, BinaryHeap}; +use micromath::F32Ext; + +bind_interrupts!(struct Irqs { + USB_LP_CAN1_RX0 => usbd::InterruptHandler; +}); + +const FPS: usize = 120; +const EMPTY_FRAME: Frame = Frame::empty(); +static FRAME_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 :( +struct MBI5043 { + sdi: SDI, + dclk: DCLK, + le: LE, + port: Gpio, +} + +#[repr(u32)] +enum DataType { + Data = 1, + Global = 3, + ReadConfig = 5, + WriteConfig = 11, + EnableWriteConfig = 15, +} + +pub trait PinBit { + fn bit(&self) -> u32; +} + +impl PinBit for T { + fn bit(&self) -> u32 { + 1 << self.pin() + } +} + +impl<'a, SDI: Pin, DCLK: Pin, LE: Pin> MBI5043 { + pub fn new(sdi: SDI, dclk: DCLK, le: LE) -> Self { + assert_eq!(sdi.port(), dclk.port()); + assert_eq!(sdi.port(), le.port()); + + let port = pac::GPIO(sdi.port() as usize); + Self::set_port_mode(&sdi); + Self::set_port_mode(&dclk); + Self::set_port_mode(&le); + Self { + port, + sdi, + dclk, + le, + } + } + fn set_port_mode(pin: &T) { + if pin.pin() < 8 { + let reg = pac::GPIO(pin.port() as usize).cfglr(); + // low bits + reg.modify(|w| { + w.set_mode(pin.pin() as usize, gpio::vals::Mode::OUTPUT_50MHZ); + w.set_cnf( + pin.pin() as usize, + gpio::vals::Cnf::ANALOG_IN__PUSH_PULL_OUT, + ); + }); + } else { + // high bits + let reg = pac::GPIO(pin.port() as usize).cfghr(); + reg.modify(|r| { + r.set_mode(pin.pin() as usize, gpio::vals::Mode::OUTPUT_50MHZ); + r.set_cnf( + pin.pin() as usize, + gpio::vals::Cnf::ANALOG_IN__PUSH_PULL_OUT, + ); + }); + } + } + fn clk_data_le_mask(&self) -> u32 { + self.dclk.bit() | self.sdi.bit() | self.le.bit() + } + fn set_all(&self) { + self.port.outdr().modify(|p| { + p.set_odr(self.dclk.pin() as usize, true); + p.set_odr(self.sdi.pin() as usize, true); + p.set_odr(self.le.pin() as usize, true) + }); + } + fn send_word(&self, val: &u16) { + for i in (0..16).rev() { + // clk low & new data + self.port.outdr().modify(|w| { + w.set_odr(self.dclk.pin() as usize, false); + w.set_odr(self.sdi.pin() as usize, val & (1 << i) != 0); + w.set_odr(self.le.pin() as usize, i < LE_LEN); + }); + + // rising clock + self.port + .outdr() + .modify(|w| w.set_odr(self.dclk.pin() as usize, true)); + } + // clear all bits + self.port + .outdr() + .modify(|w| w.0 &= !self.clk_data_le_mask()); + } +} + +pub trait MBI { + fn send_pixels u16>(&self, pixels: &[u8], transform: T); +} + +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::<3>(&0x0000); + } +} + +#[embassy_executor::task] +async fn blink(pin1: AnyPin, pin2: AnyPin) { + let mut leds = [ + Output::new(pin1, Level::Low, Default::default()), + Output::new(pin2, Level::Low, Default::default()), + ]; + let mut ticker = Ticker::every(Duration::from_millis(250)); + // println!("blinker running"); + let mut i = 0; + loop { + for idx in 0..leds.len() { + leds[idx].set_level(((1 << idx) & i != 0).into()); + } + i += 1; + ticker.next().await + } +} + +// #[embassy_executor::task] +// async fn busy() { +// loop { +// pac::GPIOC.outdr().modify(|w| w.set_odr(13, !w.odr(13))); +// } +// } + +#[embassy_executor::task] +async fn usb(usb: peripherals::USBD, irq: Irqs, dp: peripherals::PA12, dm: peripherals::PA11) { + let usb_driver = usbd::Driver::new(usb, irq, dp, dm); + let usb_config = embassy_usb::Config::new(0xc0de, 0xcafe); + + let mut config_desc = [0; 256]; + let mut bos_desc = [0; 256]; + let mut control_buf = [0; 7]; + + let mut state = State::new(); + let mut builder = Builder::new( + usb_driver, + usb_config, + &mut config_desc, + &mut bos_desc, + &mut [], + &mut control_buf, + ); + + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + let mut usb = builder.build(); + + let usb_fut = usb.run(); + + let echo_fut = async { + loop { + class.wait_connection().await; + receive(&mut class).await; + } + }; + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => 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 + } + println!("queueing new frame"); + critical_section::with(|cs| FRAME_QUEUE.borrow_ref_mut(cs).push(frame)); + } +} + +#[derive(Ord, Eq)] +struct Frame { + when: u64, + pixels: [u8; 256], +} + +impl Frame { + const fn empty() -> Self { + Self { + when: 0, + pixels: [0; 256], + } + } +} + +impl Default for Frame { + fn default() -> Self { + Self::empty() + } +} + +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) + } +} + +struct GammaLut { + gamma: f32, + max: u16, + lut: [u16; 256], +} + +impl GammaLut { + fn new(gamma: f32, max: u16) -> Self { + let mut lut = [0u16; 256]; + let f32_max = max as f32; + for i in 0..256 { + let f_val = (i as f32 / 255.).powf(gamma) * f32_max + 0.5; + lut[i] = f_val as u16; + } + Self { gamma, max, lut } + } + fn correct(&self, val: u8) -> u16 { + self.lut[val as usize] + } +} + +struct Lightbar { + gamma_lut: GammaLut, + mbi: MBI5043, +} + +impl Lightbar { + fn new(sdi: AnyPin, sck: AnyPin, le: AnyPin, gamma: f32) -> Self { + Self { + mbi: MBI5043::new(sdi, sck, le), + gamma_lut: GammaLut::new(gamma, u16::MAX), + } + } + async fn mbi_send_frame(&self, f: &Frame) { + for row in 0..16 { + pac::GPIOB.outdr().write_value(Outdr(0)); + self.mbi + .send_pixels(&f.pixels[row * 16..(row + 1) * 16], |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; + } + } + async fn display_task(&self) { + // configure GPIOB as output + pac::GPIOB + .cfglr() + .write_value(gpio::regs::Cfglr(0x33333333)); + pac::GPIOB + .cfghr() + .write_value(gpio::regs::Cfghr(0x33333333)); + + let mut frame: u64 = 0; + let mut draw_frame: Frame = EMPTY_FRAME; + + let mut ticker = Ticker::every(Duration::from_micros(1_000_000 / FPS as u64)); + loop { + 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); + } + }); + self.mbi_send_frame(&draw_frame).await; + frame += 1; + ticker.next().await + } + } +} + +#[embassy_executor::task] +async fn display_task(app: &'static Lightbar) { + app.display_task().await +} + +#[embassy_executor::main(entry = "qingke_rt::entry")] +// #[qingke_rt::entry] +async fn main(spawner: Spawner) -> ! { + hal::debug::SDIPrint::enable(); + let mut config = hal::Config::default(); + config.rcc = hal::rcc::Config::SYSCLK_FREQ_144MHZ_HSE; + + let p = hal::init(config); + Output::new(p.PC13.degrade(), Level::High, Default::default()); + + let spi_sck = p.PA5; + let spi_mosi = p.PA7; + let le = p.PA4; + let gclk = p.PA8; + + let ch1 = PwmPin::new_ch1::<0>(gclk); + let mut pwm = SimplePwm::new( + p.TIM1, + Some(ch1), + None, + None, + None, + Hertz::mhz(8), + CountingMode::default(), + ); + 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(); + 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 + } +} + +#[inline(never)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop { + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } +}