Get most basics working
- Control (at least) 1 neopixel - Add basic blinky panic handler - Support N-key rollover - Test GPIO pins
This commit is contained in:
119
Cargo.lock
generated
119
Cargo.lock
generated
@ -97,6 +97,12 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@ -234,7 +240,7 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-cortex-m"
|
name = "embassy-cortex-m"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-polyfill 1.0.1",
|
"atomic-polyfill 1.0.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -249,7 +255,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-embedded-hal"
|
name = "embassy-embedded-hal"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-sync",
|
"embassy-sync",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
@ -257,13 +263,13 @@ dependencies = [
|
|||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
"embedded-storage",
|
"embedded-storage",
|
||||||
"embedded-storage-async",
|
"embedded-storage-async",
|
||||||
"nb 1.0.0",
|
"nb 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-executor"
|
name = "embassy-executor"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-polyfill 1.0.1",
|
"atomic-polyfill 1.0.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -278,7 +284,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-futures"
|
name = "embassy-futures"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
@ -286,7 +292,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-hal-common"
|
name = "embassy-hal-common"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
@ -294,7 +300,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-macros"
|
name = "embassy-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -305,12 +311,12 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-net-driver"
|
name = "embassy-net-driver"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-net-driver-channel"
|
name = "embassy-net-driver-channel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-net-driver",
|
"embassy-net-driver",
|
||||||
@ -320,7 +326,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-rp"
|
name = "embassy-rp"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-polyfill 1.0.1",
|
"atomic-polyfill 1.0.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -343,7 +349,7 @@ dependencies = [
|
|||||||
"embedded-storage",
|
"embedded-storage",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"nb 1.0.0",
|
"nb 1.1.0",
|
||||||
"paste",
|
"paste",
|
||||||
"pio",
|
"pio",
|
||||||
"pio-proc",
|
"pio-proc",
|
||||||
@ -354,7 +360,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-sync"
|
name = "embassy-sync"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
@ -367,7 +373,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-time"
|
name = "embassy-time"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-polyfill 1.0.1",
|
"atomic-polyfill 1.0.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@ -382,7 +388,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-usb"
|
name = "embassy-usb"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-net-driver-channel",
|
"embassy-net-driver-channel",
|
||||||
@ -396,12 +402,12 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-usb-driver"
|
name = "embassy-usb-driver"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-usb-logger"
|
name = "embassy-usb-logger"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy.git#bf013be9ba51c50ff6ad16b38dede08387b4e117"
|
source = "git+https://github.com/embassy-rs/embassy.git#055597063f2d3f1156a9f8076c601dd300d85542"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-sync",
|
"embassy-sync",
|
||||||
@ -444,7 +450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7e0760ec0a3bf76859d5e33f39542af103f157d5b2ecfb00ace56dd461472e3a"
|
checksum = "7e0760ec0a3bf76859d5e33f39542af103f157d5b2ecfb00ace56dd461472e3a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-hal 1.0.0-alpha.9",
|
"embedded-hal 1.0.0-alpha.9",
|
||||||
"nb 1.0.0",
|
"nb 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -461,9 +467,9 @@ checksum = "156d7a2fdd98ebbf9ae579cbceca3058cff946e13f8e17b90e3511db0508c723"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-storage-async"
|
name = "embedded-storage-async"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ff04af74e47e9bb4315bd7aa2b01f3d1b05f33c03a6c4e9c3b20e9ce9cd8d79"
|
checksum = "052997a894670d0cde873faa7405bc98e2fd29f569d2acd568561bc1c396b35a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embedded-storage",
|
"embedded-storage",
|
||||||
]
|
]
|
||||||
@ -659,7 +665,9 @@ dependencies = [
|
|||||||
"embedded-io",
|
"embedded-io",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"panic-halt",
|
"pio",
|
||||||
|
"pio-proc",
|
||||||
|
"smart-leds",
|
||||||
"static_cell",
|
"static_cell",
|
||||||
"usb-device",
|
"usb-device",
|
||||||
"usbd-hid",
|
"usbd-hid",
|
||||||
@ -699,9 +707,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.140"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@ -734,14 +742,14 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nb 1.0.0",
|
"nb 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nb"
|
name = "nb"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "new_debug_unreachable"
|
name = "new_debug_unreachable"
|
||||||
@ -784,12 +792,6 @@ version = "1.17.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "panic-halt"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -815,9 +817,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.11"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "petgraph"
|
||||||
@ -985,6 +987,15 @@ version = "0.6.28"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rgb"
|
||||||
|
version = "0.8.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rp2040-pac2"
|
name = "rp2040-pac2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -1014,9 +1025,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.11"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
@ -1047,9 +1058,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.152"
|
version = "1.0.154"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
@ -1063,6 +1074,24 @@ version = "1.10.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smart-leds"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38dd45fa275f70b4110eac5f5182611ad384f88bb22b68b9a9c3cafd7015290b"
|
||||||
|
dependencies = [
|
||||||
|
"smart-leds-trait",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smart-leds-trait"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebf6d833fa93f16a1c1874e62c2aebe8567e5bdd436d59bf543ed258b6f7a8e3"
|
||||||
|
dependencies = [
|
||||||
|
"rgb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@ -1099,9 +1128,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "string_cache"
|
name = "string_cache"
|
||||||
version = "0.8.6"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d69e88b23f23030bf4d0e9ca7b07434f70e1c1f4d3ca7e93ce958b373654d9f"
|
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -1149,18 +1178,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.38"
|
version = "1.0.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.38"
|
version = "1.0.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1178,9 +1207,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.6"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
|
|||||||
@ -8,7 +8,7 @@ edition = "2021"
|
|||||||
cortex-m = "0.7.6"
|
cortex-m = "0.7.6"
|
||||||
cortex-m-rt = "0.7"
|
cortex-m-rt = "0.7"
|
||||||
embedded-hal ="0.2.5"
|
embedded-hal ="0.2.5"
|
||||||
panic-halt= "0.2.0"
|
#panic-halt= "0.2.0"
|
||||||
usb-device = "*"
|
usb-device = "*"
|
||||||
usbd-hid = "0.6.1"
|
usbd-hid = "0.6.1"
|
||||||
static_cell = "1.0.0"
|
static_cell = "1.0.0"
|
||||||
@ -25,3 +25,10 @@ embassy-usb-driver = { git = "https://github.com/embassy-rs/embassy.git", featur
|
|||||||
|
|
||||||
embassy-rp = { git = "https://github.com/embassy-rs/embassy.git", features = ["log", "nightly", "unstable-traits", "unstable-pac", "time-driver", "pio", "critical-section-impl"] }
|
embassy-rp = { git = "https://github.com/embassy-rs/embassy.git", features = ["log", "nightly", "unstable-traits", "unstable-pac", "time-driver", "pio", "critical-section-impl"] }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
pio = "0.2.1"
|
||||||
|
pio-proc = "0.2.1"
|
||||||
|
smart-leds = "0.3.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["n-key-rollover"]
|
||||||
|
n-key-rollover=[]
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use embassy_rp::gpio::{AnyPin, Input, Pin, Pull};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
use log::info;
|
||||||
|
|
||||||
pub const ROWS: usize = 3;
|
pub const ROWS: usize = 3;
|
||||||
pub const COLS: usize = 5;
|
pub const COLS: usize = 5;
|
||||||
@ -62,6 +64,18 @@ pub enum Button {
|
|||||||
Key { keycode: u8 },
|
Key { keycode: u8 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task(pool_size = 20)]
|
||||||
|
pub async fn monitor_switch(pin: AnyPin) -> ! {
|
||||||
|
let pin_nr = pin.pin();
|
||||||
|
let mut pin = Input::new(pin, Pull::Up);
|
||||||
|
loop {
|
||||||
|
pin.wait_for_low().await;
|
||||||
|
info!("pin {pin_nr} low");
|
||||||
|
pin.wait_for_high().await;
|
||||||
|
info!("pin {pin_nr} high");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl Button {
|
impl Button {
|
||||||
pub const fn key(keycode: u8) -> Self {
|
pub const fn key(keycode: u8) -> Self {
|
||||||
@ -120,7 +134,12 @@ impl Button {
|
|||||||
pub const KEY_RALT: Button = Button::key(0xE6);
|
pub const KEY_RALT: Button = Button::key(0xE6);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn letter_to_key(c: char) -> Option<Button> {
|
/// Random functions for testing
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn letter_to_key(c: char) -> Option<Button> {
|
||||||
if !c.is_ascii() {
|
if !c.is_ascii() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -165,9 +184,9 @@ pub fn letter_to_key(c: char) -> Option<Button> {
|
|||||||
log::info!("char {c:?} -> {key:?}");
|
log::info!("char {c:?} -> {key:?}");
|
||||||
|
|
||||||
Some(key)
|
Some(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_type(s: &str) {
|
pub async fn type_string(s: &str) {
|
||||||
log::info!("typing {s:?}");
|
log::info!("typing {s:?}");
|
||||||
|
|
||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
@ -186,4 +205,34 @@ pub async fn test_type(s: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Press all keys at once
|
||||||
|
pub async fn rollover<const N: usize>(letters: [char; N]) {
|
||||||
|
log::info!("pressing all letters in {letters:?}");
|
||||||
|
|
||||||
|
let keys = letters.map(letter_to_key);
|
||||||
|
|
||||||
|
for key in &keys {
|
||||||
|
for col in 0..COLS {
|
||||||
|
for row in 0..ROWS {
|
||||||
|
if Some(&TEST_KEYMAP[row][col]) == key.as_ref() {
|
||||||
|
MATRIX[row][col].press();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer::after(Duration::from_millis(200)).await;
|
||||||
|
|
||||||
|
for key in &keys {
|
||||||
|
for col in 0..COLS {
|
||||||
|
for row in 0..ROWS {
|
||||||
|
if Some(&TEST_KEYMAP[row][col]) == key.as_ref() {
|
||||||
|
MATRIX[row][col].release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
src/main.rs
59
src/main.rs
@ -11,16 +11,23 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
extern crate cortex_m_rt;
|
extern crate cortex_m_rt;
|
||||||
extern crate panic_halt;
|
//extern crate panic_halt;
|
||||||
|
|
||||||
mod board;
|
mod board;
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
mod neopixel;
|
||||||
|
mod panic_handler;
|
||||||
mod usb;
|
mod usb;
|
||||||
|
mod ws2812;
|
||||||
|
|
||||||
use board::Board;
|
use board::Board;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_rp::gpio::{Level, Output};
|
use embassy_rp::{
|
||||||
|
gpio::{Level, Output, Pin},
|
||||||
|
pio::PioPeripheral,
|
||||||
|
};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
use ws2812::Rgb;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
@ -54,12 +61,21 @@ async fn main(spawner: Spawner) {
|
|||||||
neopixel_power: p.PIN_16,
|
neopixel_power: p.PIN_16,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut led = Output::new(board.d13, Level::High);
|
//let mut led = Output::new(board.d13, Level::Low);
|
||||||
|
let _neopixel_power = Output::new(board.neopixel_power, Level::High);
|
||||||
|
|
||||||
|
let (_, sm, ..) = p.PIO0.split();
|
||||||
|
let mut neopixel = ws2812::Ws2812::new(sm, p.DMA_CH0, board.neopixel.degrade());
|
||||||
|
//let mut neopixel = ws2812::Ws2812::new(sm, p.DMA_CH0, board.d5.degrade());
|
||||||
|
|
||||||
|
neopixel.write(&[Rgb::new(0xb7, 0x31, 0x2c)]).await;
|
||||||
|
|
||||||
let mut builder = usb::builder(p.USB);
|
let mut builder = usb::builder(p.USB);
|
||||||
|
|
||||||
usb::logger::setup(&mut builder).await;
|
usb::logger::setup(&mut builder).await;
|
||||||
|
|
||||||
|
neopixel.write(&[Rgb::new(0xf0, 0xd0, 0x20)]).await;
|
||||||
|
|
||||||
log::error!("log_level: error");
|
log::error!("log_level: error");
|
||||||
log::warn!("log_level: warn");
|
log::warn!("log_level: warn");
|
||||||
log::info!("log_level: info");
|
log::info!("log_level: info");
|
||||||
@ -72,12 +88,41 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
spawner.must_spawn(usb::run(usb));
|
spawner.must_spawn(usb::run(usb));
|
||||||
|
|
||||||
Timer::after(Duration::from_millis(1000)).await;
|
Timer::after(Duration::from_millis(3000)).await;
|
||||||
|
|
||||||
crate::keyboard::test_type("Hello there!\n").await;
|
spawner.must_spawn(keyboard::monitor_switch(board.a0.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.a1.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.a2.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.a3.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d2.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d3.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d4.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d7.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d9.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d10.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d11.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d12.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d24.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.d25.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.scl.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.sda.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.mosi.degrade()));
|
||||||
|
spawner.must_spawn(keyboard::monitor_switch(board.miso.degrade()));
|
||||||
|
|
||||||
|
//keyboard::test::type_string("Hello there!\n").await;
|
||||||
|
//keyboard::test::rollover(['h', 'e', 'l', 'o', 't', 'r', 'a', 'b', 'c', 'd', 'i']).await;
|
||||||
loop {
|
loop {
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
//neopixel
|
||||||
led.toggle();
|
// .write(&[
|
||||||
|
// Rgb::new(0xAA, 0xFF, 0x00),
|
||||||
|
// Rgb::new(0xAA, 0xFF, 0x00),
|
||||||
|
// Rgb::new(0xAA, 0xFF, 0x00),
|
||||||
|
// Rgb::new(0xAA, 0xFF, 0x00),
|
||||||
|
// Rgb::new(0xAA, 0xFF, 0x00),
|
||||||
|
// Rgb::new(0xAA, 0xFF, 0x00),
|
||||||
|
// ])
|
||||||
|
// .await;
|
||||||
|
//Timer::after(Duration::from_millis(10)).await;
|
||||||
|
Timer::after(Duration::from_secs(10)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/neopixel.pio
Normal file
11
src/neopixel.pio
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.program ws2812
|
||||||
|
.side_set 1
|
||||||
|
.wrap_target
|
||||||
|
bitloop:
|
||||||
|
out x 1 side 0 [6]; Drive low. Side-set still takes place before instruction stalls.
|
||||||
|
jmp !x do_zero side 1 [3]; Branch on the bit we shifted out previous delay. Drive high.
|
||||||
|
do_one:
|
||||||
|
jmp bitloop side 1 [4]; Continue driving high, for a one (long pulse)
|
||||||
|
do_zero:
|
||||||
|
nop side 0 [4]; Or drive low, for a zero (short pulse)
|
||||||
|
.wrap
|
||||||
122
src/neopixel.rs
Normal file
122
src/neopixel.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
use embassy_rp::{
|
||||||
|
gpio::{AnyPin, Drive, SlewRate},
|
||||||
|
peripherals::{DMA_CH0, PIO0},
|
||||||
|
pio::{FifoJoin, PioPeripheral, PioStateMachine, ShiftDirection},
|
||||||
|
pio_instr_util,
|
||||||
|
relocate::RelocatedProgram,
|
||||||
|
PeripheralRef,
|
||||||
|
};
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn test(pio: PIO0, pin: AnyPin, dma: DMA_CH0) {
|
||||||
|
let (_common, mut sm, ..) = pio.split();
|
||||||
|
let mut dma = PeripheralRef::new(dma);
|
||||||
|
|
||||||
|
let pio_program = pio_proc::pio_file!("src/neopixel.pio");
|
||||||
|
|
||||||
|
let relocated = RelocatedProgram::new(&pio_program.program);
|
||||||
|
sm.write_instr(relocated.origin() as usize, relocated.code());
|
||||||
|
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
|
||||||
|
|
||||||
|
let pin = sm.make_pio_pin(pin);
|
||||||
|
sm.set_set_pins(&[&pin]);
|
||||||
|
sm.set_sideset_base_pin(&pin);
|
||||||
|
sm.set_sideset_count(1);
|
||||||
|
|
||||||
|
// Clock config
|
||||||
|
// TODO CLOCK_FREQ should come from embassy_rp
|
||||||
|
const CLOCK_FREQ: u32 = 125_000_000;
|
||||||
|
const WS2812_FREQ: u32 = 800_000;
|
||||||
|
const CYCLES_PER_BIT: u32 = 16;
|
||||||
|
|
||||||
|
let bit_freq = WS2812_FREQ * CYCLES_PER_BIT;
|
||||||
|
let mut int = CLOCK_FREQ / bit_freq;
|
||||||
|
let rem = CLOCK_FREQ - (int * bit_freq);
|
||||||
|
let frac = (rem * 256) / bit_freq;
|
||||||
|
// 65536.0 is represented as 0 in the pio's clock divider
|
||||||
|
if int == 65536 {
|
||||||
|
int = 0;
|
||||||
|
}
|
||||||
|
sm.set_clkdiv((int << 8) | frac);
|
||||||
|
let pio::Wrap { source, target } = relocated.wrap();
|
||||||
|
sm.set_wrap(source, target);
|
||||||
|
|
||||||
|
sm.set_autopull(true);
|
||||||
|
sm.set_fifo_join(FifoJoin::TxOnly);
|
||||||
|
sm.set_pull_threshold(8); // 24?
|
||||||
|
sm.set_out_shift_dir(ShiftDirection::Left);
|
||||||
|
|
||||||
|
sm.set_enable(true);
|
||||||
|
|
||||||
|
log::info!("wrap: {:?}", sm.get_wrap());
|
||||||
|
log::info!("addr: {:?}", sm.get_addr());
|
||||||
|
log::info!("sideset_base: {:?}", sm.get_sideset_base());
|
||||||
|
log::info!("sideset_count: {:?}", sm.get_sideset_count());
|
||||||
|
log::info!("in_base: {:?}", sm.get_in_base());
|
||||||
|
log::info!("jmp_pin: {:?}", sm.get_jmp_pin());
|
||||||
|
log::info!("set_range: {:?}", sm.get_set_range());
|
||||||
|
log::info!("out_range: {:?}", sm.get_out_range());
|
||||||
|
log::info!("pull_threshold: {:?}", sm.get_pull_threshold());
|
||||||
|
log::info!("push_threshold: {:?}", sm.get_push_threshold());
|
||||||
|
|
||||||
|
//sm = rp2pio.StateMachine(
|
||||||
|
// assembled,
|
||||||
|
// frequency=12_800_000, # to get appropriate sub-bit times in PIO program
|
||||||
|
// first_sideset_pin=NEOPIXEL,
|
||||||
|
// auto_pull=True,
|
||||||
|
// out_shift_right=False,
|
||||||
|
// pull_threshold=8,
|
||||||
|
//)
|
||||||
|
|
||||||
|
loop {
|
||||||
|
log::info!("sending dma");
|
||||||
|
|
||||||
|
sm.dma_push(dma.reborrow(), &[0x0a, 0x00, 0x00]).await;
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
sm.dma_push(dma.reborrow(), &[0x00, 0x0a, 0x00]).await;
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
sm.dma_push(dma.reborrow(), &[0x00, 0x00, 0x0a]).await;
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
|
||||||
|
//sm0.set_enable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn test_blink(pio: PIO0, pin: AnyPin) {
|
||||||
|
log::info!("test blink hehe");
|
||||||
|
let (_, mut sm, ..) = pio.split();
|
||||||
|
// Setup sm2
|
||||||
|
|
||||||
|
// blink
|
||||||
|
let prg = pio_proc::pio_file!("src/blink.pio");
|
||||||
|
|
||||||
|
let relocated = RelocatedProgram::new(&prg.program);
|
||||||
|
let out_pin = sm.make_pio_pin(pin);
|
||||||
|
let pio_pins = [&out_pin];
|
||||||
|
sm.set_set_pins(&pio_pins);
|
||||||
|
sm.set_set_range(25, 1);
|
||||||
|
|
||||||
|
sm.write_instr(relocated.origin() as usize, relocated.code());
|
||||||
|
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
|
||||||
|
// sm.set_clkdiv((65535 << 8) + 255 as u32);
|
||||||
|
// sm.set_clkdiv(0);
|
||||||
|
|
||||||
|
let pio::Wrap { source, target } = relocated.wrap();
|
||||||
|
sm.set_wrap(source, target);
|
||||||
|
|
||||||
|
// sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32);
|
||||||
|
sm.set_enable(true);
|
||||||
|
// sm.wait_push().await as i32;
|
||||||
|
// sm.push_tx(1);
|
||||||
|
sm.wait_push(125_000_000).await;
|
||||||
|
log::info!("started");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
sm.wait_irq(3).await;
|
||||||
|
log::info!("did it!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
8
src/neopixel2.pio
Normal file
8
src/neopixel2.pio
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.program ws2812
|
||||||
|
.origin 0
|
||||||
|
.wrap_target
|
||||||
|
out x 1
|
||||||
|
set pins,1 [1]
|
||||||
|
mov pins,x [1]
|
||||||
|
set pins,0
|
||||||
|
.wrap
|
||||||
28
src/panic_handler.rs
Normal file
28
src/panic_handler.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
|
use embassy_executor::Executor;
|
||||||
|
use embassy_rp::gpio::{AnyPin, Level, Output, Pin};
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use static_cell::StaticCell;
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic_blink(_info: &PanicInfo) -> ! {
|
||||||
|
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
||||||
|
|
||||||
|
// SAFETY: we panicked, so no other code will be running.
|
||||||
|
let p = unsafe { embassy_rp::Peripherals::steal() };
|
||||||
|
|
||||||
|
EXECUTOR.init(Executor::new()).run(|spawner| {
|
||||||
|
spawner.spawn(blink(p.PIN_11.degrade())).ok();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn blink(led: AnyPin) {
|
||||||
|
let mut led = Output::new(led, Level::High);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
|
led.toggle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,7 +25,7 @@ pub fn builder(usb: USB) -> Builder<'static, Driver<'static, USB>> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create embassy-usb Config
|
// Create embassy-usb Config
|
||||||
let mut config = Config::new(0xc0de, 0xcafe);
|
let mut config = Config::new(0xb00b, 0x1355);
|
||||||
config.manufacturer = Some("Tux");
|
config.manufacturer = Some("Tux");
|
||||||
config.product = Some("Tangentbord1");
|
config.product = Some("Tangentbord1");
|
||||||
config.serial_number = Some("42069");
|
config.serial_number = Some("42069");
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
pub mod report;
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_rp::{peripherals::USB, usb::Driver};
|
use embassy_rp::{peripherals::USB, usb::Driver};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
@ -8,9 +10,12 @@ use embassy_usb::{
|
|||||||
};
|
};
|
||||||
use embassy_usb_driver::EndpointError;
|
use embassy_usb_driver::EndpointError;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use usbd_hid::descriptor::{KeyboardReport, MouseReport, SerializedDescriptor};
|
use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
|
||||||
|
|
||||||
use crate::keyboard::{Button, COLS, MATRIX, ROWS, TEST_KEYMAP};
|
use crate::{
|
||||||
|
keyboard::{Button, COLS, MATRIX, ROWS, TEST_KEYMAP},
|
||||||
|
usb::keyboard::report::{KeyboardReport, EMPTY_KEYBOARD_REPORT},
|
||||||
|
};
|
||||||
|
|
||||||
use super::MAX_PACKET_SIZE;
|
use super::MAX_PACKET_SIZE;
|
||||||
|
|
||||||
@ -84,44 +89,50 @@ async fn task(stream: HidStream, handler: &'static Handler) {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn keyboard_test(mut stream: HidStream, handler: &'static Handler) -> Result<(), Error> {
|
async fn keyboard_test(mut stream: HidStream, _handler: &'static Handler) -> Result<(), Error> {
|
||||||
stream.ready().await;
|
stream.ready().await;
|
||||||
loop {
|
loop {
|
||||||
Timer::after(Duration::from_millis(2)).await;
|
Timer::after(Duration::from_millis(2)).await;
|
||||||
|
|
||||||
let keymap = &TEST_KEYMAP;
|
let keymap = &TEST_KEYMAP;
|
||||||
|
|
||||||
let mut keycodes = [0u8; 6];
|
let mut report = EMPTY_KEYBOARD_REPORT;
|
||||||
|
#[cfg(not(feature = "n-key-rollover"))]
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
||||||
|
#[allow(unused_labels)]
|
||||||
'keyscan: for col in 0..COLS {
|
'keyscan: for col in 0..COLS {
|
||||||
for row in 0..ROWS {
|
for row in 0..ROWS {
|
||||||
if !MATRIX[row][col].is_pressed() {
|
if !MATRIX[row][col].is_pressed() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Button::Key { keycode } = &keymap[row][col];
|
let &Button::Key { keycode } = &keymap[row][col];
|
||||||
// else { continue; };
|
// else { continue; };
|
||||||
|
|
||||||
keycodes[i] = *keycode;
|
#[cfg(feature = "n-key-rollover")]
|
||||||
|
report.set_key(keycode);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "n-key-rollover"))]
|
||||||
|
{
|
||||||
|
report.keycodes[i] = keycode;
|
||||||
i += 1;
|
i += 1;
|
||||||
if i >= keycodes.len() {
|
if i >= report.keycodes.len() {
|
||||||
break 'keyscan;
|
break 'keyscan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if keycodes.iter().any(|&b| b != 0) {
|
|
||||||
log::info!("keycodes: {keycodes:?}");
|
|
||||||
}
|
}
|
||||||
stream
|
|
||||||
.write_serialize(&KeyboardReport {
|
if report.keycodes != EMPTY_KEYBOARD_REPORT.keycodes {
|
||||||
modifier: 0,
|
log::debug!("keys: {:x?}", report.keycodes);
|
||||||
reserved: 0,
|
}
|
||||||
leds: 0,
|
|
||||||
keycodes,
|
#[cfg(feature = "n-key-rollover")]
|
||||||
})
|
stream.write(&report.serialized()).await?;
|
||||||
.await?;
|
|
||||||
|
#[cfg(not(feature = "n-key-rollover"))]
|
||||||
|
stream.write_serialize(&report).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
104
src/usb/keyboard/report.rs
Normal file
104
src/usb/keyboard/report.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
/// KeyboardReport describes a report and its companion descriptor that can be
|
||||||
|
/// used to send keyboard button presses to a host and receive the status of the
|
||||||
|
/// keyboard LEDs.
|
||||||
|
///
|
||||||
|
/// Unlike usbd_hids KeyboardReport, this one supports N-key rollover.
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
#[cfg(feature = "n-key-rollover")]
|
||||||
|
pub struct KeyboardReport {
|
||||||
|
pub modifier: u8,
|
||||||
|
|
||||||
|
/// Bitmap representing all keycodes from 0 to 104
|
||||||
|
pub keycodes: [u8; 13],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "n-key-rollover"))]
|
||||||
|
pub use usbd_hid::descriptor::KeyboardReport;
|
||||||
|
|
||||||
|
#[cfg(feature = "n-key-rollover")]
|
||||||
|
pub const EMPTY_KEYBOARD_REPORT: KeyboardReport = KeyboardReport {
|
||||||
|
modifier: 0,
|
||||||
|
keycodes: [0; 13],
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "n-key-rollover"))]
|
||||||
|
pub const EMPTY_KEYBOARD_REPORT: KeyboardReport = KeyboardReport {
|
||||||
|
modifier: 0,
|
||||||
|
leds: 0,
|
||||||
|
reserved: 0,
|
||||||
|
keycodes: [0; 6],
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "n-key-rollover")]
|
||||||
|
impl KeyboardReport {
|
||||||
|
pub fn set_key(&mut self, keycode: u8) {
|
||||||
|
log::info!("setting keycode: {keycode}");
|
||||||
|
let byte = keycode >> 3;
|
||||||
|
let bit = keycode & 0b111;
|
||||||
|
let mask = 1 << bit;
|
||||||
|
|
||||||
|
if let Some(k) = self.keycodes.get_mut(byte as usize) {
|
||||||
|
*k |= mask;
|
||||||
|
} else {
|
||||||
|
log::warn!("Tried to set out-of-range keycode: {keycode:x}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialized(&self) -> [u8; 14] {
|
||||||
|
let [a, b, c, d, e, f, g, h, i, j, k, l, m] = self.keycodes;
|
||||||
|
[self.modifier, a, b, c, d, e, f, g, h, i, j, k, l, m]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitmasks for the `modifier` field
|
||||||
|
pub const MOD_LCTRL: u8 = 0x01;
|
||||||
|
pub const MOD_LSHIFT: u8 = 0x02;
|
||||||
|
pub const MOD_LALT: u8 = 0x04;
|
||||||
|
pub const MOD_LSUPER: u8 = 0x08;
|
||||||
|
pub const MOD_RCTRL: u8 = 0x10;
|
||||||
|
pub const MOD_RSHIFT: u8 = 0x20;
|
||||||
|
pub const MOD_RALT: u8 = 0x40;
|
||||||
|
pub const MOD_RSUPER: u8 = 0x80;
|
||||||
|
|
||||||
|
#[cfg(feature = "n-key-rollover")]
|
||||||
|
impl usbd_hid::descriptor::SerializedDescriptor for KeyboardReport {
|
||||||
|
fn desc() -> &'static [u8] {
|
||||||
|
// Manually define the descriptor since I can't figure out how to get
|
||||||
|
// gen_hid_descriptor to generate the correct one.
|
||||||
|
&[
|
||||||
|
0x05, 0x01, // usage page 1 (generic desktop)
|
||||||
|
0x09, 0x06, // usage (keyboard)
|
||||||
|
0xa1, 0x01, // collection (application)
|
||||||
|
//
|
||||||
|
0x05, 0x07, // usage page 7 (keyboard/keypad)
|
||||||
|
0x19, 0xe0, // local usage minimum
|
||||||
|
0x29, 0xe7, // local usage maximum
|
||||||
|
0x15, 0x00, // local minimum
|
||||||
|
0x25, 0x01, // local maximum
|
||||||
|
0x75, 0x01, // report size (1 bit)
|
||||||
|
0x95, 0x08, // report count (8)
|
||||||
|
0x81, 0x02, // input (variable)
|
||||||
|
//
|
||||||
|
0x19, 0x00, // local usage minimum
|
||||||
|
0x29, 0x67, // local usage maximum
|
||||||
|
0x95, 0x68, // report count
|
||||||
|
0x81, 0x02, // input (variable)
|
||||||
|
//
|
||||||
|
0x05, 0x08, // usage page 8 (led page)
|
||||||
|
0x19, 0x01, // local usage minimum
|
||||||
|
0x29, 0x05, // local usage maximum
|
||||||
|
0x15, 0x00, // logical min
|
||||||
|
0x25, 0x01, // logical max
|
||||||
|
0x75, 0x01, // report size
|
||||||
|
0x95, 0x05, // report count
|
||||||
|
0x91, 0x02, // output (variable)
|
||||||
|
//
|
||||||
|
0x75, 0x03, // report size
|
||||||
|
0x95, 0x01, // report count
|
||||||
|
0x91, 0x01, // output (constant)
|
||||||
|
0xc0, // end collection
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
126
src/ws2812.rs
Normal file
126
src/ws2812.rs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
use core::fmt::{self, Debug};
|
||||||
|
use core::mem::transmute;
|
||||||
|
|
||||||
|
use embassy_rp::dma::{self, AnyChannel};
|
||||||
|
use embassy_rp::pio::{
|
||||||
|
FifoJoin, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance,
|
||||||
|
};
|
||||||
|
use embassy_rp::pio_instr_util;
|
||||||
|
use embassy_rp::relocate::RelocatedProgram;
|
||||||
|
use embassy_rp::{gpio, PeripheralRef};
|
||||||
|
|
||||||
|
pub struct Ws2812<P: PioInstance, S: SmInstance> {
|
||||||
|
sm: PioStateMachineInstance<P, S>,
|
||||||
|
dma: PeripheralRef<'static, AnyChannel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An Rgb value that can be safely transmuted to u32 for use with Ws2812.
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Rgb(u32);
|
||||||
|
|
||||||
|
impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
|
||||||
|
pub fn new(
|
||||||
|
mut sm: PioStateMachineInstance<P, S>,
|
||||||
|
dma: impl dma::Channel,
|
||||||
|
pin: gpio::AnyPin,
|
||||||
|
) -> Self {
|
||||||
|
// prepare the PIO program
|
||||||
|
let side_set = pio::SideSet::new(false, 1, false);
|
||||||
|
let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set);
|
||||||
|
|
||||||
|
const T1: u8 = 2; // start bit
|
||||||
|
const T2: u8 = 5; // data bit
|
||||||
|
const T3: u8 = 3; // stop bit
|
||||||
|
const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32;
|
||||||
|
|
||||||
|
let mut wrap_target = a.label();
|
||||||
|
let mut wrap_source = a.label();
|
||||||
|
let mut do_zero = a.label();
|
||||||
|
a.set_with_side_set(pio::SetDestination::PINDIRS, 1, 0);
|
||||||
|
a.bind(&mut wrap_target);
|
||||||
|
// Do stop bit
|
||||||
|
a.out_with_delay_and_side_set(pio::OutDestination::X, 1, T3 - 1, 0);
|
||||||
|
// Do start bit
|
||||||
|
a.jmp_with_delay_and_side_set(pio::JmpCondition::XIsZero, &mut do_zero, T1 - 1, 1);
|
||||||
|
// Do data bit = 1
|
||||||
|
a.jmp_with_delay_and_side_set(pio::JmpCondition::Always, &mut wrap_target, T2 - 1, 1);
|
||||||
|
a.bind(&mut do_zero);
|
||||||
|
// Do data bit = 0
|
||||||
|
a.nop_with_delay_and_side_set(T2 - 1, 0);
|
||||||
|
a.bind(&mut wrap_source);
|
||||||
|
|
||||||
|
let prg = a.assemble_with_wrap(wrap_source, wrap_target);
|
||||||
|
|
||||||
|
let relocated = RelocatedProgram::new(&prg);
|
||||||
|
sm.write_instr(relocated.origin() as usize, relocated.code());
|
||||||
|
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
|
||||||
|
|
||||||
|
// Pin config
|
||||||
|
let out_pin = sm.make_pio_pin(pin);
|
||||||
|
sm.set_set_pins(&[&out_pin]);
|
||||||
|
sm.set_sideset_base_pin(&out_pin);
|
||||||
|
sm.set_sideset_count(1);
|
||||||
|
|
||||||
|
// Clock config
|
||||||
|
// TODO CLOCK_FREQ should come from embassy_rp
|
||||||
|
const CLOCK_FREQ: u32 = 125_000_000;
|
||||||
|
const WS2812_FREQ: u32 = 800_000;
|
||||||
|
|
||||||
|
let bit_freq = WS2812_FREQ * CYCLES_PER_BIT;
|
||||||
|
let mut int = CLOCK_FREQ / bit_freq;
|
||||||
|
let rem = CLOCK_FREQ - (int * bit_freq);
|
||||||
|
let frac = (rem * 256) / bit_freq;
|
||||||
|
// 65536.0 is represented as 0 in the pio's clock divider
|
||||||
|
if int == 65536 {
|
||||||
|
int = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm.set_clkdiv((int << 8) | frac);
|
||||||
|
let pio::Wrap { source, target } = relocated.wrap();
|
||||||
|
sm.set_wrap(source, target);
|
||||||
|
|
||||||
|
// FIFO config
|
||||||
|
sm.set_autopull(true);
|
||||||
|
sm.set_fifo_join(FifoJoin::TxOnly);
|
||||||
|
sm.set_pull_threshold(24);
|
||||||
|
sm.set_out_shift_dir(ShiftDirection::Left);
|
||||||
|
|
||||||
|
sm.set_enable(true);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
sm,
|
||||||
|
dma: PeripheralRef::new(dma.degrade()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write(&mut self, colors: &[Rgb]) {
|
||||||
|
let colors = rgbs_to_u32s(colors);
|
||||||
|
self.sm.dma_push(self.dma.reborrow(), colors).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn rgbs_to_u32s(rgbs: &[Rgb]) -> &[u32] {
|
||||||
|
// SAFETY: Rgb contains only a u32, and is #[repr(transparent)]
|
||||||
|
unsafe { transmute(rgbs) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rgb {
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn new(r: u8, g: u8, b: u8) -> Self {
|
||||||
|
Self(u32::from_be_bytes([g, r, b, 0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub const fn components(&self) -> (u8, u8, u8) {
|
||||||
|
let [g, r, b, _] = self.0.to_be_bytes();
|
||||||
|
(r, g, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Rgb {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let (r, g, b) = self.components();
|
||||||
|
f.debug_tuple("Rgb").field(&r).field(&g).field(&b).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user