initial commit, working 48k version for tortilla hardware
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
[target.thumbv8m.main-none-eabihf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
# "-C", "debug-assertions",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv8m.main-none-eabihf"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "off"
|
||||
@@ -0,0 +1 @@
|
||||
/target
|
||||
Generated
+712
@@ -0,0 +1,712 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-embedded-io"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed6bb9472871706c9b1f648ca527031e33d647a95706d6ab5659f22ca28d419"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"embedded-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
|
||||
dependencies = [
|
||||
"bare-metal",
|
||||
"bitfield",
|
||||
"critical-section",
|
||||
"embedded-hal 0.2.7",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6"
|
||||
dependencies = [
|
||||
"cortex-m-rt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt-macros"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array 0.14.7",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt"
|
||||
version = "0.3.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad"
|
||||
dependencies = [
|
||||
"defmt 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"defmt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt-macros"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e"
|
||||
dependencies = [
|
||||
"defmt-parser",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt-parser"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defmt-rtt"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93d5a25c99d89c40f5676bec8cefe0614f17f0f40e916f98e345dae941807f9e"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"defmt 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[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-io"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-time"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
|
||||
dependencies = [
|
||||
"num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dab9e9188e97a93276e1fe7b56401b851e2b45a46d045ca658100c1303ada649"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guac"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"defmt 1.0.1",
|
||||
"defmt-rtt",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-io",
|
||||
"heapless 0.9.3",
|
||||
"log-to-defmt",
|
||||
"lpc55-hal",
|
||||
"nb 1.1.0",
|
||||
"panic-halt",
|
||||
"panic-probe",
|
||||
"static_cell",
|
||||
"usb-device",
|
||||
"usbd-uac2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"hash32 0.2.1",
|
||||
"rustc_version 0.4.1",
|
||||
"spin",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32 0.3.1",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4"
|
||||
dependencies = [
|
||||
"hash32 0.3.1",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
dependencies = [
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "log-to-defmt"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9454118d78a9089a15d702fbaf413da2fa23f331b8af6c5eed5784a4369173c6"
|
||||
dependencies = [
|
||||
"defmt 0.3.100",
|
||||
"heapless 0.7.17",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lpc55-hal"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cipher",
|
||||
"cortex-m",
|
||||
"digest",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-time",
|
||||
"generic-array 1.4.1",
|
||||
"lpc55-pac",
|
||||
"nb 1.1.0",
|
||||
"rand_core",
|
||||
"usb-device",
|
||||
"vcell",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lpc55-pac"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a4952baed9d9e7e82a6bbc87333f939b90eb41df3e6c0be5e35d0ec61005f91"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2956e537fc68236d2aa048f55704f231cc93f1c4de42fe1ecb5bd7938061fc4a"
|
||||
dependencies = [
|
||||
"modular-bitfield-impl",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield-impl"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59b43b4fd69e3437618106f7754f34021b831a514f9e1a98ae863cabcd8d8dad"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[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"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[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-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"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 = "panic-halt"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11"
|
||||
|
||||
[[package]]
|
||||
name = "panic-probe"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"defmt 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
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 = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver 1.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "static_cell"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0530892bb4fa575ee0da4b86f86c667132a94b74bb72160f58ee5a4afec74c23"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "usb-device"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6"
|
||||
dependencies = [
|
||||
"defmt 0.3.100",
|
||||
"heapless 0.8.0",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "usbd-uac2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder-embedded-io",
|
||||
"defmt 1.0.1",
|
||||
"embedded-io",
|
||||
"modular-bitfield",
|
||||
"num-traits",
|
||||
"usb-device",
|
||||
]
|
||||
|
||||
[[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 = "volatile-register"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
|
||||
dependencies = [
|
||||
"vcell",
|
||||
]
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "guac"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["ak4490"]
|
||||
ak4490 = []
|
||||
|
||||
[dependencies]
|
||||
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "1.0.1"
|
||||
defmt-rtt = "1.1.0"
|
||||
embedded-hal = "1.0.0"
|
||||
embedded-io = "0.7.1"
|
||||
heapless = "0.9.3"
|
||||
log-to-defmt = "0.1.0"
|
||||
lpc55-hal = { version = "0.5.0", path = "../usbd_uac2/examples/lpc55-hal" }
|
||||
nb = "1.1.0"
|
||||
panic-halt = "1.0.0"
|
||||
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
||||
static_cell = "2.1.1"
|
||||
usb-device = "0.3"
|
||||
usbd-uac2 = { version = "0.1.0", path = "../usbd_uac2", features = ["defmt"]}
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
debug = true
|
||||
codegen-units = 1
|
||||
@@ -0,0 +1,21 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
|
||||
|
||||
/* for use with standard link.x */
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 192K
|
||||
|
||||
/* would be used with proper link.x */
|
||||
/* needs changes to r0 (initialization code) */
|
||||
/* SRAM0 : ORIGIN = 0x20000000, LENGTH = 64K */
|
||||
/* SRAM1 : ORIGIN = 0x20010000, LENGTH = 64K */
|
||||
/* SRAM2 : ORIGIN = 0x20020000, LENGTH = 64K */
|
||||
/* SRAM3 : ORIGIN = 0x20030000, LENGTH = 64K */
|
||||
|
||||
/* CASPER SRAM regions */
|
||||
/* SRAMX0: ORIGIN = 0x1400_0000, LENGTH = 4K /1* to 0x1400_0FFF *1/ */
|
||||
/* SRAMX1: ORIGIN = 0x1400_4000, LENGTH = 4K /1* to 0x1400_4FFF *1/ */
|
||||
|
||||
/* USB1 SRAM regin */
|
||||
/* USB1_SRAM : ORIGIN = 0x40100000, LENGTH = 16K */
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
use cortex_m::prelude::{_embedded_hal_blocking_i2c_Write, _embedded_hal_blocking_i2c_WriteRead};
|
||||
use defmt::warn;
|
||||
|
||||
use crate::hal::prelude::*;
|
||||
use crate::{CodecPins, MCLK_FREQ, SAMPLE_RATE, SampleType};
|
||||
|
||||
const AK4490_I2C_ADDRESS: u8 = 0x10;
|
||||
|
||||
#[repr(u8)]
|
||||
enum RegisterAddress {
|
||||
Control1 = 0x00,
|
||||
Control2 = 0x01,
|
||||
Control3 = 0x02,
|
||||
LeftAtt = 0x03,
|
||||
RightAtt = 0x04,
|
||||
Control4 = 0x05,
|
||||
Control5 = 0x06,
|
||||
Control6 = 0x07,
|
||||
Control7 = 0x08,
|
||||
Control8 = 0x09,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_reg<T>(i2c: &mut T, reg: RegisterAddress, val: u8)
|
||||
where
|
||||
T: _embedded_hal_blocking_i2c_WriteRead + _embedded_hal_blocking_i2c_Write,
|
||||
{
|
||||
i2c.write(AK4490_I2C_ADDRESS, &[reg as u8, val]).ok();
|
||||
}
|
||||
|
||||
pub(crate) fn init_dac<T>(i2c: &mut T, mut pins: CodecPins)
|
||||
where
|
||||
T: _embedded_hal_blocking_i2c_WriteRead + _embedded_hal_blocking_i2c_Write,
|
||||
{
|
||||
// bring out of reset
|
||||
pins.reset.set_high();
|
||||
write_reg(i2c, RegisterAddress::Control1, (1 << 7) | 0x0e | (1 << 0)); // ACKS | I2S-32 | RSTN
|
||||
let dfs = match SAMPLE_RATE {
|
||||
r if r < 54000 => 0,
|
||||
r if r < 108000 => 1,
|
||||
r if r < 216000 => 2,
|
||||
r if r <= 384000 => 4,
|
||||
_ => 5,
|
||||
};
|
||||
// default = 0x22
|
||||
write_reg(i2c, RegisterAddress::Control2, 0x22 | ((dfs & 0x3) << 3));
|
||||
write_reg(i2c, RegisterAddress::Control4, (dfs & 0x4) >> 1);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
pub(crate) struct PllConstants {
|
||||
pub m: u16, // 1-65535
|
||||
pub n: u8, // 1-255
|
||||
pub p: u8, // 1-31
|
||||
pub selp: u8, // 5 bits
|
||||
pub seli: u8, // 6 bits
|
||||
}
|
||||
|
||||
impl PllConstants {
|
||||
pub(crate) const fn new(n: u8, m: u16, p: u8) -> Self {
|
||||
assert!(n != 0, "1 <= N <= 255");
|
||||
assert!(m != 0, "1 <= M <= 65535");
|
||||
assert!(p != 0 && p <= 31, "1 <= P <= 31");
|
||||
|
||||
// Following ripped from lpc55-hal and made const
|
||||
// UM 4.6.6.3.2
|
||||
let selp = {
|
||||
let v = (m >> 2) + 1;
|
||||
if v < 31 { v } else { 31 }
|
||||
} as u8;
|
||||
|
||||
let seli = {
|
||||
let v = match m {
|
||||
m if m >= 8000 => 1,
|
||||
m if m >= 122 => 8000 / m,
|
||||
_ => 2 * (m >> 2) + 3,
|
||||
};
|
||||
|
||||
if v < 63 { v } else { 63 }
|
||||
} as u8;
|
||||
// let seli = min(2*(m >> 2) + 3, 63);
|
||||
Self {
|
||||
n,
|
||||
m,
|
||||
p,
|
||||
selp,
|
||||
seli,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl defmt::Format for PllConstants {
|
||||
fn format(&self, fmt: defmt::Formatter) {
|
||||
let factor = f32::from(self.m) / (f32::from(self.n) * 2.0 * f32::from(self.p));
|
||||
|
||||
defmt::write!(
|
||||
fmt,
|
||||
"m: {} n: {} p: {} selp: {} seli: {} fout: fin * {}",
|
||||
self.m,
|
||||
self.n,
|
||||
self.p,
|
||||
self.selp,
|
||||
self.seli,
|
||||
factor
|
||||
);
|
||||
}
|
||||
}
|
||||
+543
@@ -0,0 +1,543 @@
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate panic_probe;
|
||||
#[defmt::panic_handler]
|
||||
fn panic() -> ! {
|
||||
panic_probe::hard_fault()
|
||||
}
|
||||
|
||||
use core::ptr::null_mut;
|
||||
use core::sync::atomic::{AtomicBool, AtomicI32, AtomicUsize, Ordering};
|
||||
use cortex_m_rt::entry;
|
||||
use defmt;
|
||||
use defmt::debug;
|
||||
use defmt_rtt as _;
|
||||
use hal::Pin;
|
||||
use hal::Syscon;
|
||||
use hal::drivers::{Timer, UsbBus, pins, pins::direction::Output};
|
||||
use hal::prelude::*;
|
||||
use hal::raw as pac;
|
||||
use hal::time::Hertz;
|
||||
use hal::typestates::pin::state::Gpio;
|
||||
use heapless::spsc::Consumer;
|
||||
use lpc55_hal::{self as hal};
|
||||
use pac::interrupt;
|
||||
use static_cell::StaticCell;
|
||||
use usb_device::{
|
||||
bus::{self},
|
||||
device::{StringDescriptors, UsbDeviceBuilder, UsbVidPid},
|
||||
endpoint::IsochronousSynchronizationType,
|
||||
};
|
||||
use usbd_uac2::UsbIsochronousFeedback;
|
||||
use usbd_uac2::{
|
||||
self, AudioClassConfig, RangeEntry, TerminalConfig, UsbAudioClass, UsbAudioClockImpl, UsbSpeed,
|
||||
constants::{FunctionCode, TerminalType},
|
||||
descriptors::{ChannelConfig, ClockType, FormatType1, LockDelay},
|
||||
};
|
||||
|
||||
#[cfg(feature = "ak4490")]
|
||||
mod ak4490;
|
||||
#[cfg(feature = "ak4490")]
|
||||
use ak4490 as dac;
|
||||
mod hw;
|
||||
|
||||
// Fo = M/(N*2*P) * Fin
|
||||
// Fo = 3072/(125*2*8) * 16MHz = 24.576MHz
|
||||
const FIFO_LENGTH: usize = 128; // frames
|
||||
const MCLK_FREQ: u32 = 24576000;
|
||||
const SAMPLE_RATE: u32 = 48000;
|
||||
type SampleType = (i32, i32);
|
||||
|
||||
struct CodecPins {
|
||||
reset: Pin<pins::Pio0_3, Gpio<Output>>,
|
||||
}
|
||||
|
||||
struct ClockSelPins {
|
||||
sel_24m: Pin<pins::Pio0_27, Gpio<Output>>,
|
||||
sel_22m: Pin<pins::Pio0_31, Gpio<Output>>,
|
||||
}
|
||||
|
||||
struct Clock {
|
||||
pins: ClockSelPins,
|
||||
cur_rate: u32,
|
||||
}
|
||||
impl Clock {
|
||||
const RATES: [RangeEntry<u32>; 1] = [RangeEntry::new_fixed(SAMPLE_RATE)];
|
||||
}
|
||||
impl UsbAudioClockImpl for Clock {
|
||||
const CLOCK_TYPE: usbd_uac2::descriptors::ClockType = ClockType::InternalFixed;
|
||||
const SOF_SYNC: bool = false;
|
||||
fn get_sample_rate(&self) -> core::result::Result<u32, usbd_uac2::UsbAudioClassError> {
|
||||
Ok(self.cur_rate)
|
||||
}
|
||||
fn set_sample_rate(
|
||||
&mut self,
|
||||
sample_rate: u32,
|
||||
) -> core::result::Result<(), usbd_uac2::UsbAudioClassError> {
|
||||
if 24_576_000u32.is_multiple_of(sample_rate) {
|
||||
defmt::info!("[clock] 24M clock selected");
|
||||
self.pins.sel_22m.set_low().ok();
|
||||
// hal::wait_at_least(1);
|
||||
self.pins.sel_24m.set_high().ok();
|
||||
} else {
|
||||
defmt::info!("[clock] 24M clock selected");
|
||||
self.pins.sel_24m.set_low().ok();
|
||||
// hal::wait_at_least(1);
|
||||
self.pins.sel_22m.set_high().ok();
|
||||
};
|
||||
self.cur_rate = sample_rate;
|
||||
Ok(())
|
||||
}
|
||||
fn get_rates(
|
||||
&self,
|
||||
) -> core::result::Result<&[usbd_uac2::RangeEntry<u32>], usbd_uac2::UsbAudioClassError> {
|
||||
Ok(&Clock::RATES)
|
||||
}
|
||||
fn get_clock_validity(&self) -> core::result::Result<bool, usbd_uac2::UsbAudioClassError> {
|
||||
Ok(true)
|
||||
}
|
||||
fn alt_setting(
|
||||
&mut self,
|
||||
alt_setting: u8,
|
||||
) -> core::result::Result<(), usbd_uac2::UsbAudioClassError> {
|
||||
match alt_setting {
|
||||
0 => {
|
||||
self.pins.sel_22m.set_low().ok();
|
||||
self.pins.sel_24m.set_low().ok();
|
||||
}
|
||||
1 => {
|
||||
self.set_sample_rate(self.cur_rate).ok();
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct PerfCounters {
|
||||
received_frames: AtomicUsize,
|
||||
played_frames: AtomicUsize,
|
||||
min_fill: AtomicUsize,
|
||||
avg_fill: AtomicUsize,
|
||||
queue_underflows: AtomicUsize,
|
||||
queue_overflows: AtomicUsize,
|
||||
audio_underflows: AtomicUsize,
|
||||
}
|
||||
|
||||
impl PerfCounters {
|
||||
fn reset(&self) {
|
||||
self.received_frames.store(0, Ordering::Relaxed);
|
||||
self.played_frames.store(0, Ordering::Relaxed);
|
||||
self.min_fill.store(FIFO_LENGTH, Ordering::Relaxed);
|
||||
self.avg_fill.store(FIFO_LENGTH / 2, Ordering::Relaxed);
|
||||
self.queue_underflows.store(0, Ordering::Relaxed);
|
||||
self.queue_overflows.store(0, Ordering::Relaxed);
|
||||
self.audio_underflows.store(0, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
impl defmt::Format for PerfCounters {
|
||||
fn format(&self, fmt: defmt::Formatter) {
|
||||
defmt::write!(
|
||||
fmt,
|
||||
"frames: {}/{} min_fill: {} avg fill: {} a_underflows: {} q_underflows: {} q_overflows: {}",
|
||||
self.played_frames.load(Ordering::Relaxed),
|
||||
self.received_frames.load(Ordering::Relaxed),
|
||||
self.min_fill.load(Ordering::Relaxed),
|
||||
self.avg_fill.load(Ordering::Relaxed),
|
||||
self.audio_underflows.load(Ordering::Relaxed),
|
||||
self.queue_underflows.load(Ordering::Relaxed),
|
||||
self.queue_overflows.load(Ordering::Relaxed)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
static FIFO_CONSUMER_STORE: StaticCell<Consumer<SampleType>> = StaticCell::new();
|
||||
static mut FIFO_CONSUMER: *mut Consumer<SampleType> = null_mut();
|
||||
|
||||
static PERF: PerfCounters = PerfCounters {
|
||||
received_frames: AtomicUsize::new(0),
|
||||
played_frames: AtomicUsize::new(0),
|
||||
min_fill: AtomicUsize::new(FIFO_LENGTH),
|
||||
avg_fill: AtomicUsize::new(FIFO_LENGTH / 2),
|
||||
queue_underflows: AtomicUsize::new(0),
|
||||
queue_overflows: AtomicUsize::new(0),
|
||||
audio_underflows: AtomicUsize::new(0),
|
||||
};
|
||||
|
||||
#[interrupt]
|
||||
fn FLEXCOMM7() {
|
||||
let i2s = unsafe { &*pac::I2S7::ptr() };
|
||||
|
||||
if i2s.fifostat.read().txlvl().bits() == 0 {
|
||||
PERF.audio_underflows.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
// refil the buffer to 4 frames / 8 samples
|
||||
let fifo = unsafe { &mut *FIFO_CONSUMER };
|
||||
while i2s.fifostat.read().txlvl().bits() <= 6 {
|
||||
if let Some((l, r)) = fifo.dequeue() {
|
||||
i2s.fifowr.write(|w| unsafe { w.bits(l as u32) });
|
||||
i2s.fifowr.write(|w| unsafe { w.bits(r as u32) });
|
||||
PERF.min_fill.fetch_min(fifo.len(), Ordering::Relaxed);
|
||||
PERF.played_frames.fetch_add(1, Ordering::Relaxed);
|
||||
} else {
|
||||
PERF.queue_underflows.fetch_add(1, Ordering::Relaxed);
|
||||
i2s.fifowr.write(|w| unsafe { w.bits(0) });
|
||||
i2s.fifowr.write(|w| unsafe { w.bits(0) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Audio<'a> {
|
||||
running: AtomicBool,
|
||||
i2s: I2sTx,
|
||||
producer: heapless::spsc::Producer<'a, SampleType>,
|
||||
integrator: AtomicI32,
|
||||
}
|
||||
impl<'a> Audio<'a> {
|
||||
fn start(&self) {
|
||||
self.running.store(true, Ordering::Relaxed);
|
||||
defmt::info!("playback starting, enabling interrupts");
|
||||
self.i2s.i2s.fifointenclr.write(|w| w.txlvl().set_bit());
|
||||
// FIFO threshold trigger enable
|
||||
self.i2s
|
||||
.i2s
|
||||
.fifotrig
|
||||
.modify(|_, w| unsafe { w.txlvl().bits(6).txlvlena().enabled() });
|
||||
// FIFO level interrupt enable
|
||||
self.i2s.i2s.fifointenset.modify(|_, w| w.txlvl().enabled());
|
||||
unsafe { pac::NVIC::unmask(pac::Interrupt::FLEXCOMM7) };
|
||||
}
|
||||
fn stop(&self) {
|
||||
self.running.store(true, Ordering::Relaxed);
|
||||
defmt::info!("playback stopped: {}", PERF);
|
||||
PERF.reset();
|
||||
pac::NVIC::mask(pac::Interrupt::FLEXCOMM7);
|
||||
}
|
||||
}
|
||||
impl<'a, B: bus::UsbBus> UsbAudioClass<'a, B> for Audio<'_> {
|
||||
fn alternate_setting_changed(&mut self, terminal: usb_device::UsbDirection, alt_setting: u8) {
|
||||
match alt_setting {
|
||||
0 => self.stop(),
|
||||
1 => self.start(),
|
||||
_ => defmt::error!("unexpected alt setting {}", alt_setting),
|
||||
}
|
||||
}
|
||||
fn audio_data_rx(
|
||||
&mut self,
|
||||
ep: &usb_device::endpoint::Endpoint<'a, B, usb_device::endpoint::Out>,
|
||||
) {
|
||||
let mut buf = [0; SAMPLE_RATE as usize / 1000 * 64];
|
||||
let len = match ep.read(&mut buf) {
|
||||
Ok(len) => len,
|
||||
Err(e) => {
|
||||
defmt::error!("usb error in rx callback");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let buf = &buf[..len];
|
||||
for sample in buf.chunks_exact(8).map(|b| {
|
||||
PERF.received_frames.fetch_add(1, Ordering::Relaxed);
|
||||
(
|
||||
i32::from_le_bytes(b[..4].try_into().unwrap()),
|
||||
i32::from_le_bytes(b[4..].try_into().unwrap()),
|
||||
)
|
||||
}) {
|
||||
if let Err(e) = self.producer.enqueue(sample) {
|
||||
PERF.queue_overflows.fetch_add(1, Ordering::Relaxed);
|
||||
// defmt::error!("overflowed fifo, len: {}", unsafe {
|
||||
// (*self.producer.get()).len()
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
fn feedback(&mut self) -> Option<UsbIsochronousFeedback> {
|
||||
const TARGET: i32 = FIFO_LENGTH as i32 / 2 - 64;
|
||||
const NOMINAL: i32 = (SAMPLE_RATE as i32 / 1000) << 16;
|
||||
|
||||
let queuelen = self.producer.len();
|
||||
let error = (queuelen as i32 - TARGET).clamp(-32, 32);
|
||||
|
||||
// --- integrator ---
|
||||
let scaled_error = error / 64;
|
||||
|
||||
let new_i = self.integrator.fetch_add(scaled_error, Ordering::Relaxed) + scaled_error;
|
||||
let clamped = new_i.clamp(-131072, 131072);
|
||||
|
||||
// leak + store final value
|
||||
let leaked = clamped - (clamped >> 8);
|
||||
self.integrator.store(leaked, Ordering::Relaxed);
|
||||
|
||||
// reset on large deviation
|
||||
if error.abs() > 96 {
|
||||
self.integrator.store(0, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
// --- gains ---
|
||||
let p = error / 128;
|
||||
let i = leaked / 32768;
|
||||
|
||||
// correction
|
||||
let correction = (-(p + i)).clamp(-32, 32);
|
||||
let v = NOMINAL + (correction << 10);
|
||||
|
||||
// EMA (unchanged, already correct)
|
||||
let ema = PERF.avg_fill.load(Ordering::Relaxed);
|
||||
let new = ((ema * 1023) + queuelen + 512) >> 10;
|
||||
PERF.avg_fill.store(new, Ordering::Relaxed);
|
||||
|
||||
defmt::debug!(
|
||||
"q:{} p:{} i:{} err:{} fb:{}+{}",
|
||||
queuelen,
|
||||
p,
|
||||
i,
|
||||
error,
|
||||
NOMINAL >> 16,
|
||||
correction
|
||||
);
|
||||
|
||||
Some(UsbIsochronousFeedback::new(v as u32))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct I2sTx {
|
||||
pub i2s: pac::I2S7,
|
||||
}
|
||||
|
||||
pub fn init_i2s(mut fc7: pac::FLEXCOMM7, i2s7: pac::I2S7, syscon: &mut Syscon) -> I2sTx {
|
||||
defmt::debug!("init i2s");
|
||||
// Enable BOTH
|
||||
syscon.reset(&mut fc7);
|
||||
syscon.enable_clock(&mut fc7);
|
||||
|
||||
unsafe {
|
||||
pac::IOCON::ptr().as_ref().unwrap().pio0_23.modify(|_, w| {
|
||||
w.func()
|
||||
.alt1() // MCLK
|
||||
.mode()
|
||||
.inactive()
|
||||
.slew()
|
||||
.fast()
|
||||
.invert()
|
||||
.disabled()
|
||||
.digimode()
|
||||
.digital()
|
||||
.od()
|
||||
.normal()
|
||||
});
|
||||
pac::SYSCON::ptr()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.mclkio
|
||||
.modify(|_, w| w.mclkio().input());
|
||||
pac::SYSCON::ptr()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.fcclksel7()
|
||||
.modify(|_, w| w.sel().enum_0x5()); // MCLK
|
||||
};
|
||||
|
||||
// Select I2S TX function
|
||||
fc7.pselid.write(|w| w.persel().i2s_transmit());
|
||||
|
||||
let regs = i2s7;
|
||||
|
||||
// Enable TX FIFO only
|
||||
regs.fifocfg.modify(|_, w| {
|
||||
w.enabletx()
|
||||
.enabled()
|
||||
.enablerx()
|
||||
.disabled()
|
||||
.dmatx()
|
||||
.disabled()
|
||||
.txi2se0()
|
||||
.zero()
|
||||
});
|
||||
|
||||
// Flush
|
||||
regs.fifocfg.modify(|_, w| w.emptytx().set_bit());
|
||||
|
||||
regs.cfg2
|
||||
.modify(|_, w| unsafe { w.position().bits(0).framelen().bits(63) }); // framelen = 64
|
||||
|
||||
let bclk_div = (MCLK_FREQ / SAMPLE_RATE / 64) as u16;
|
||||
regs.div
|
||||
.modify(|_, w| unsafe { w.div().bits(bclk_div - 1) }); // Clock source is MCLK (12.288MHz) / 4 = 3MHz
|
||||
|
||||
// Config
|
||||
regs.cfg1.modify(|_, w| unsafe {
|
||||
w.mstslvcfg()
|
||||
.normal_master()
|
||||
.onechannel()
|
||||
.dual_channel()
|
||||
.datalen()
|
||||
.bits(31)
|
||||
.mainenable()
|
||||
.enabled()
|
||||
.mode()
|
||||
.classic_mode()
|
||||
.datapause()
|
||||
.normal()
|
||||
});
|
||||
|
||||
I2sTx { i2s: regs }
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let hal = hal::new();
|
||||
|
||||
let mut anactrl = hal.anactrl;
|
||||
let mut pmc = hal.pmc;
|
||||
let mut syscon = hal.syscon;
|
||||
|
||||
let mut gpio = hal.gpio.enabled(&mut syscon);
|
||||
let mut iocon = hal.iocon.enabled(&mut syscon);
|
||||
|
||||
debug!("start");
|
||||
|
||||
debug!("iocon");
|
||||
let usb0_vbus_pin = pins::Pio0_22::take()
|
||||
.unwrap()
|
||||
.into_usb0_vbus_pin(&mut iocon);
|
||||
let codec_i2c_pins = (
|
||||
pins::Pio0_16::take().unwrap().into_i2c4_scl_pin(&mut iocon),
|
||||
pins::Pio0_5::take().unwrap().into_i2c4_sda_pin(&mut iocon),
|
||||
);
|
||||
let codec_i2s_pins = (
|
||||
pins::Pio0_21::take().unwrap().into_spi7_sck_pin(&mut iocon),
|
||||
pins::Pio0_20::take().unwrap().into_i2s7_sda_pin(&mut iocon),
|
||||
pins::Pio0_19::take().unwrap().into_i2s7_ws_pin(&mut iocon),
|
||||
pins::Pio0_23::take().unwrap(),
|
||||
);
|
||||
let codec_gpio_pins = CodecPins {
|
||||
reset: pins::Pio0_3::take()
|
||||
.unwrap()
|
||||
.into_gpio_pin(&mut iocon, &mut gpio)
|
||||
.into_output_low(),
|
||||
};
|
||||
let clock_sel_pins = ClockSelPins {
|
||||
sel_24m: pins::Pio0_27::take()
|
||||
.unwrap()
|
||||
.into_gpio_pin(&mut iocon, &mut gpio)
|
||||
.into_output_low(),
|
||||
sel_22m: pins::Pio0_31::take()
|
||||
.unwrap()
|
||||
.into_gpio_pin(&mut iocon, &mut gpio)
|
||||
.into_output_low(),
|
||||
};
|
||||
let leds = (
|
||||
pins::Pio0_13::take()
|
||||
.unwrap()
|
||||
.into_gpio_pin(&mut iocon, &mut gpio)
|
||||
.into_output_low(),
|
||||
pins::Pio0_14::take()
|
||||
.unwrap()
|
||||
.into_gpio_pin(&mut iocon, &mut gpio)
|
||||
.into_output_low(),
|
||||
);
|
||||
|
||||
// iocon.disabled(&mut syscon).release(); // save the environment :)
|
||||
|
||||
debug!("clocks");
|
||||
let clocks = hal::ClockRequirements::default()
|
||||
.system_frequency(96.MHz())
|
||||
.configure(&mut anactrl, &mut pmc, &mut syscon)
|
||||
.unwrap();
|
||||
let mut _delay_timer = Timer::new(
|
||||
hal.ctimer
|
||||
.0
|
||||
.enabled(&mut syscon, clocks.support_1mhz_fro_token().unwrap()),
|
||||
);
|
||||
|
||||
debug!("peripherals");
|
||||
|
||||
let i2c_peripheral = hal
|
||||
.flexcomm
|
||||
.4
|
||||
.enabled_as_i2c(&mut syscon, &clocks.support_flexcomm_token().unwrap());
|
||||
let mut i2c_bus = I2cMaster::new(
|
||||
i2c_peripheral,
|
||||
codec_i2c_pins,
|
||||
Hertz::try_from(400.kHz()).unwrap(),
|
||||
);
|
||||
|
||||
let i2s_peripheral = {
|
||||
let fc7 = hal.flexcomm.7.release();
|
||||
init_i2s(fc7.0, fc7.2, &mut syscon)
|
||||
};
|
||||
|
||||
let usb_peripheral = hal.usbhs.enabled_as_device(
|
||||
&mut anactrl,
|
||||
&mut pmc,
|
||||
&mut syscon,
|
||||
&mut _delay_timer,
|
||||
clocks.support_usbhs_token().unwrap(),
|
||||
);
|
||||
|
||||
let usb_bus = UsbBus::new(usb_peripheral, usb0_vbus_pin);
|
||||
let mut clock = Clock {
|
||||
pins: clock_sel_pins,
|
||||
cur_rate: SAMPLE_RATE,
|
||||
};
|
||||
|
||||
defmt::debug!("codec init");
|
||||
dac::init_dac(&mut i2c_bus, codec_gpio_pins);
|
||||
let queue = cortex_m::singleton!(
|
||||
: heapless::spsc::Queue<SampleType, FIFO_LENGTH>
|
||||
= heapless::spsc::Queue::new()
|
||||
)
|
||||
.unwrap();
|
||||
let (producer, consumer) = queue.split();
|
||||
|
||||
let consumer_ref = FIFO_CONSUMER_STORE.init(consumer);
|
||||
unsafe { FIFO_CONSUMER = consumer_ref as *mut _ };
|
||||
|
||||
let mut audio = Audio {
|
||||
i2s: i2s_peripheral,
|
||||
producer,
|
||||
running: AtomicBool::new(false),
|
||||
integrator: AtomicI32::new(0),
|
||||
};
|
||||
|
||||
let config = AudioClassConfig::new(UsbSpeed::High, FunctionCode::Other, &mut clock, &mut audio)
|
||||
.with_output_config(TerminalConfig::new(
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
FormatType1 {
|
||||
bit_resolution: 32,
|
||||
bytes_per_sample: 4,
|
||||
},
|
||||
TerminalType::ExtLineConnector,
|
||||
ChannelConfig::default_chans(2),
|
||||
IsochronousSynchronizationType::Asynchronous,
|
||||
LockDelay::Undefined(0),
|
||||
None,
|
||||
));
|
||||
|
||||
let mut uac2 = config.build(&usb_bus).unwrap();
|
||||
|
||||
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x1209, 0xcc1d))
|
||||
.composite_with_iads()
|
||||
.strings(&[StringDescriptors::default()
|
||||
.manufacturer("VE7XEN")
|
||||
.product("Guac Tortilla")
|
||||
.serial_number("123456789")])
|
||||
.unwrap()
|
||||
.max_packet_size_0(64)
|
||||
.unwrap()
|
||||
.device_class(0xef)
|
||||
.device_sub_class(0x02)
|
||||
.device_protocol(0x01)
|
||||
.build();
|
||||
|
||||
defmt::info!("main loop");
|
||||
|
||||
loop {
|
||||
usb_dev.poll(&mut [&mut uac2]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user