Merge branch 'master' into feature/mqtt-convert
This commit is contained in:
commit
65a0831e2d
|
@ -40,6 +40,17 @@ dependencies = [
|
|||
"embedded-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
|
@ -85,6 +96,24 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c147d86912d04bef727828fda769a76ca81629a46d8ba311a8d58a26aa91473d"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.2"
|
||||
|
@ -106,6 +135,23 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.6.7"
|
||||
|
@ -199,33 +245,127 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_stringset"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/quartiq/miniconf.git?branch=rs/issue-21/terminal-array-elements#b93924e81ad860efd9dcda8df2ea901a579958e2"
|
||||
name = "criterion"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"atty",
|
||||
"cast",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"csv",
|
||||
"itertools 0.10.0",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"const_fn",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"csv-core",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dsp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"easybench",
|
||||
"criterion",
|
||||
"generic-array 0.14.4",
|
||||
"libm",
|
||||
"miniconf",
|
||||
"ndarray",
|
||||
"num",
|
||||
"rand",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "easybench"
|
||||
version = "1.1.0"
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "355215cf95ddc4db0459d5313c9b146bedd43453305e3f0f1c4e8fde7f8d3884"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-dma"
|
||||
|
@ -246,17 +386,6 @@ dependencies = [
|
|||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-nal"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae46eb1b02de5a76d9d0ea21d657ff5b0ad2cc47f3a7723608227b1dd1b3eb18"
|
||||
dependencies = [
|
||||
"heapless",
|
||||
"nb 1.0.0",
|
||||
"no-std-net",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator"
|
||||
version = "0.6.0"
|
||||
|
@ -316,6 +445,12 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.1.1"
|
||||
|
@ -344,6 +479,15 @@ dependencies = [
|
|||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.6.1"
|
||||
|
@ -354,6 +498,45 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.86"
|
||||
|
@ -399,28 +582,18 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniconf"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/quartiq/miniconf.git?branch=rs/issue-21/terminal-array-elements#b93924e81ad860efd9dcda8df2ea901a579958e2"
|
||||
dependencies = [
|
||||
"derive_stringset",
|
||||
"heapless",
|
||||
"minimq",
|
||||
"serde",
|
||||
"serde-json-core",
|
||||
]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "minimq"
|
||||
version = "0.2.0"
|
||||
name = "memoffset"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c5e626690b6f62e15710cf9815e5ca25ee54084899298c100a14b2504c80a46"
|
||||
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"embedded-nal",
|
||||
"enum-iterator",
|
||||
"generic-array 0.14.4",
|
||||
"heapless",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -452,10 +625,17 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "no-std-net"
|
||||
version = "0.4.0"
|
||||
name = "num"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2178127478ae4ee9be7180bc9c3bffb6354dd7238400db567102f98c413a9f35"
|
||||
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
|
@ -476,6 +656,28 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
||||
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.14"
|
||||
|
@ -485,6 +687,22 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "panic-halt"
|
||||
version = "0.2.0"
|
||||
|
@ -507,6 +725,34 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
|
@ -583,6 +829,55 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
||||
|
||||
[[package]]
|
||||
name = "rtic-core"
|
||||
version = "0.3.1"
|
||||
|
@ -609,6 +904,27 @@ dependencies = [
|
|||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
|
@ -643,6 +959,16 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_cbor"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
|
||||
dependencies = [
|
||||
"half",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.123"
|
||||
|
@ -654,6 +980,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smoltcp"
|
||||
version = "0.7.0"
|
||||
|
@ -665,17 +1002,6 @@ dependencies = [
|
|||
"managed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smoltcp-nal"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4e5aeb4818706fd74c35917692008d29a5314483c8180300a582253718ce57a"
|
||||
dependencies = [
|
||||
"embedded-nal",
|
||||
"heapless",
|
||||
"smoltcp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stabilizer"
|
||||
version = "0.4.1"
|
||||
|
@ -692,13 +1018,13 @@ dependencies = [
|
|||
"heapless",
|
||||
"log",
|
||||
"mcp23017",
|
||||
"miniconf",
|
||||
"nb 1.0.0",
|
||||
"panic-halt",
|
||||
"panic-semihosting",
|
||||
"paste",
|
||||
"serde",
|
||||
"smoltcp-nal",
|
||||
"serde-json-core",
|
||||
"smoltcp",
|
||||
"stm32h7xx-hal",
|
||||
]
|
||||
|
||||
|
@ -749,12 +1075,37 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2ada8616fad06a2d0c455adc530de4ef57605a8120cc65da9653e0e9623ca74"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
|
@ -788,8 +1139,114 @@ dependencies = [
|
|||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
|
|
@ -8,10 +8,10 @@ edition = "2018"
|
|||
libm = "0.2.1"
|
||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||
generic-array = "0.14"
|
||||
miniconf = "0.1"
|
||||
num = { version = "0.3.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
easybench = "1.0"
|
||||
criterion = "0.3"
|
||||
rand = "0.8"
|
||||
ndarray = "0.14"
|
||||
|
||||
|
|
|
@ -1,80 +1,68 @@
|
|||
use core::f32::consts::PI;
|
||||
use dsp::{atan2, cossin};
|
||||
use dsp::{iir, iir_int};
|
||||
use dsp::{pll::PLL, rpll::RPLL};
|
||||
use easybench::bench_env;
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use dsp::{atan2, cossin, iir, iir_int, PLL, RPLL};
|
||||
|
||||
fn atan2_bench() {
|
||||
fn atan2_bench(c: &mut Criterion) {
|
||||
let xi = (10 << 16) as i32;
|
||||
let xf = xi as f32 / i32::MAX as f32;
|
||||
|
||||
let yi = (-26_328 << 16) as i32;
|
||||
let yf = yi as f32 / i32::MAX as f32;
|
||||
|
||||
println!(
|
||||
"atan2(yi, xi): {}",
|
||||
bench_env((yi, xi), |(yi, xi)| atan2(*yi, *xi))
|
||||
);
|
||||
println!(
|
||||
"yf.atan2(xf): {}",
|
||||
bench_env((yf, xf), |(yf, xf)| yf.atan2(*xf))
|
||||
);
|
||||
c.bench_function("atan2(y, x)", |b| {
|
||||
b.iter(|| atan2(black_box(yi), black_box(xi)))
|
||||
});
|
||||
c.bench_function("y.atan2(x)", |b| {
|
||||
b.iter(|| black_box(yf).atan2(black_box(xf)))
|
||||
});
|
||||
}
|
||||
|
||||
fn cossin_bench() {
|
||||
fn cossin_bench(c: &mut Criterion) {
|
||||
let zi = -0x7304_2531_i32;
|
||||
let zf = zi as f32 / i32::MAX as f32 * PI;
|
||||
println!("cossin(zi): {}", bench_env(zi, |zi| cossin(*zi)));
|
||||
println!("zf.sin_cos(): {}", bench_env(zf, |zf| zf.sin_cos()));
|
||||
c.bench_function("cossin(zi)", |b| b.iter(|| cossin(black_box(zi))));
|
||||
c.bench_function("zf.sin_cos()", |b| b.iter(|| black_box(zf).sin_cos()));
|
||||
}
|
||||
|
||||
fn rpll_bench() {
|
||||
fn rpll_bench(c: &mut Criterion) {
|
||||
let mut dut = RPLL::new(8);
|
||||
println!(
|
||||
"RPLL::update(Some(t), 21, 20): {}",
|
||||
bench_env(Some(0x241), |x| dut.update(*x, 21, 20))
|
||||
);
|
||||
println!(
|
||||
"RPLL::update(Some(t), sf, sp): {}",
|
||||
bench_env((Some(0x241), 21, 20), |(x, p, q)| dut.update(*x, *p, *q))
|
||||
);
|
||||
c.bench_function("RPLL::update(Some(t), 21, 20)", |b| {
|
||||
b.iter(|| dut.update(black_box(Some(0x241)), 21, 20))
|
||||
});
|
||||
c.bench_function("RPLL::update(Some(t), sf, sp)", |b| {
|
||||
b.iter(|| {
|
||||
dut.update(black_box(Some(0x241)), black_box(21), black_box(20))
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn pll_bench() {
|
||||
fn pll_bench(c: &mut Criterion) {
|
||||
let mut dut = PLL::default();
|
||||
println!(
|
||||
"PLL::update(t, 12, 12): {}",
|
||||
bench_env(0x241, |x| dut.update(*x, 12, 12))
|
||||
);
|
||||
println!(
|
||||
"PLL::update(t, sf, sp): {}",
|
||||
bench_env((0x241, 21, 20), |(x, p, q)| dut.update(*x, *p, *q))
|
||||
);
|
||||
c.bench_function("PLL::update(t, 12, 11)", |b| {
|
||||
b.iter(|| dut.update(black_box(0x1234), 12, 1))
|
||||
});
|
||||
c.bench_function("PLL::update(t, sf, sp)", |b| {
|
||||
b.iter(|| dut.update(black_box(0x241), black_box(21), black_box(20)))
|
||||
});
|
||||
}
|
||||
|
||||
fn iir_int_bench() {
|
||||
fn iir_int_bench(c: &mut Criterion) {
|
||||
let dut = iir_int::IIR::default();
|
||||
let mut xy = iir_int::Vec5::default();
|
||||
println!(
|
||||
"int_iir::IIR::update(s, x): {}",
|
||||
bench_env(0x2832, |x| dut.update(&mut xy, *x))
|
||||
);
|
||||
c.bench_function("int_iir::IIR::update(s, x)", |b| {
|
||||
b.iter(|| dut.update(&mut xy, black_box(0x2832)))
|
||||
});
|
||||
}
|
||||
|
||||
fn iir_bench() {
|
||||
fn iir_bench(c: &mut Criterion) {
|
||||
let dut = iir::IIR::default();
|
||||
let mut xy = iir::Vec5::default();
|
||||
println!(
|
||||
"int::IIR::update(s, x): {}",
|
||||
bench_env(0.32241, |x| dut.update(&mut xy, *x))
|
||||
);
|
||||
c.bench_function("int::IIR::update(s, x)", |b| {
|
||||
b.iter(|| dut.update(&mut xy, black_box(0.32241)))
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
atan2_bench();
|
||||
cossin_bench();
|
||||
rpll_bench();
|
||||
pll_bench();
|
||||
iir_int_bench();
|
||||
iir_bench();
|
||||
}
|
||||
criterion_group!(trig, atan2_bench, cossin_bench);
|
||||
criterion_group!(pll, rpll_bench, pll_bench);
|
||||
criterion_group!(iir, iir_int_bench, iir_bench);
|
||||
criterion_main!(trig, pll, iir);
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
use core::ops::Mul;
|
||||
pub use num::Complex;
|
||||
|
||||
use super::{atan2, cossin};
|
||||
|
||||
#[derive(Copy, Clone, Default, PartialEq, Debug)]
|
||||
pub struct Complex<T>(pub T, pub T);
|
||||
|
||||
impl<T: Copy> Complex<T> {
|
||||
pub fn map<F>(&self, func: F) -> Self
|
||||
where
|
||||
F: Fn(T) -> T,
|
||||
{
|
||||
Complex(func(self.0), func(self.1))
|
||||
}
|
||||
/// Complex extension trait offering DSP (fast, good accuracy) functionality.
|
||||
pub trait ComplexExt<T, U> {
|
||||
fn from_angle(angle: T) -> Self;
|
||||
fn abs_sqr(&self) -> U;
|
||||
fn log2(&self) -> T;
|
||||
fn arg(&self) -> T;
|
||||
}
|
||||
|
||||
impl Complex<i32> {
|
||||
impl ComplexExt<i32, u32> for Complex<i32> {
|
||||
/// Return a Complex on the unit circle given an angle.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use dsp::Complex;
|
||||
/// use dsp::{Complex, ComplexExt};
|
||||
/// Complex::<i32>::from_angle(0);
|
||||
/// Complex::<i32>::from_angle(1 << 30); // pi/2
|
||||
/// Complex::<i32>::from_angle(-1 << 30); // -pi/2
|
||||
/// ```
|
||||
pub fn from_angle(angle: i32) -> Self {
|
||||
fn from_angle(angle: i32) -> Self {
|
||||
let (c, s) = cossin(angle);
|
||||
Self(c, s)
|
||||
Self { re: c, im: s }
|
||||
}
|
||||
|
||||
/// Return the absolute square (the squared magnitude).
|
||||
|
@ -39,13 +35,13 @@ impl Complex<i32> {
|
|||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use dsp::Complex;
|
||||
/// assert_eq!(Complex(i32::MIN, 0).abs_sqr(), 1 << 31);
|
||||
/// assert_eq!(Complex(i32::MAX, i32::MAX).abs_sqr(), u32::MAX - 3);
|
||||
/// use dsp::{Complex, ComplexExt};
|
||||
/// assert_eq!(Complex::new(i32::MIN, 0).abs_sqr(), 1 << 31);
|
||||
/// assert_eq!(Complex::new(i32::MAX, i32::MAX).abs_sqr(), u32::MAX - 3);
|
||||
/// ```
|
||||
pub fn abs_sqr(&self) -> u32 {
|
||||
(((self.0 as i64) * (self.0 as i64)
|
||||
+ (self.1 as i64) * (self.1 as i64))
|
||||
fn abs_sqr(&self) -> u32 {
|
||||
(((self.re as i64) * (self.re as i64)
|
||||
+ (self.im as i64) * (self.im as i64))
|
||||
>> 31) as u32
|
||||
}
|
||||
|
||||
|
@ -59,15 +55,15 @@ impl Complex<i32> {
|
|||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use dsp::Complex;
|
||||
/// assert_eq!(Complex(i32::MAX, i32::MAX).log2(), -1);
|
||||
/// assert_eq!(Complex(i32::MAX, 0).log2(), -2);
|
||||
/// assert_eq!(Complex(1, 0).log2(), -63);
|
||||
/// assert_eq!(Complex(0, 0).log2(), -64);
|
||||
/// use dsp::{Complex, ComplexExt};
|
||||
/// assert_eq!(Complex::new(i32::MAX, i32::MAX).log2(), -1);
|
||||
/// assert_eq!(Complex::new(i32::MAX, 0).log2(), -2);
|
||||
/// assert_eq!(Complex::new(1, 0).log2(), -63);
|
||||
/// assert_eq!(Complex::new(0, 0).log2(), -64);
|
||||
/// ```
|
||||
pub fn log2(&self) -> i32 {
|
||||
let a = (self.0 as i64) * (self.0 as i64)
|
||||
+ (self.1 as i64) * (self.1 as i64);
|
||||
fn log2(&self) -> i32 {
|
||||
let a = (self.re as i64) * (self.re as i64)
|
||||
+ (self.im as i64) * (self.im as i64);
|
||||
-(a.leading_zeros() as i32)
|
||||
}
|
||||
|
||||
|
@ -78,52 +74,51 @@ impl Complex<i32> {
|
|||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use dsp::Complex;
|
||||
/// assert_eq!(Complex(1, 0).arg(), 0);
|
||||
/// assert_eq!(Complex(-i32::MAX, 1).arg(), i32::MAX);
|
||||
/// assert_eq!(Complex(-i32::MAX, -1).arg(), -i32::MAX);
|
||||
/// assert_eq!(Complex(0, -1).arg(), -i32::MAX >> 1);
|
||||
/// assert_eq!(Complex(0, 1).arg(), (i32::MAX >> 1) + 1);
|
||||
/// assert_eq!(Complex(1, 1).arg(), (i32::MAX >> 2) + 1);
|
||||
/// use dsp::{Complex, ComplexExt};
|
||||
/// assert_eq!(Complex::new(1, 0).arg(), 0);
|
||||
/// assert_eq!(Complex::new(-i32::MAX, 1).arg(), i32::MAX);
|
||||
/// assert_eq!(Complex::new(-i32::MAX, -1).arg(), -i32::MAX);
|
||||
/// assert_eq!(Complex::new(0, -1).arg(), -i32::MAX >> 1);
|
||||
/// assert_eq!(Complex::new(0, 1).arg(), (i32::MAX >> 1) + 1);
|
||||
/// assert_eq!(Complex::new(1, 1).arg(), (i32::MAX >> 2) + 1);
|
||||
/// ```
|
||||
pub fn arg(&self) -> i32 {
|
||||
atan2(self.1, self.0)
|
||||
fn arg(&self) -> i32 {
|
||||
atan2(self.im, self.re)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Complex<i32> {
|
||||
type Output = Self;
|
||||
/// Full scale fixed point multiplication.
|
||||
pub trait MulScaled<T> {
|
||||
fn mul_scaled(self, other: T) -> Self;
|
||||
}
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
let a = self.0 as i64;
|
||||
let b = self.1 as i64;
|
||||
let c = other.0 as i64;
|
||||
let d = other.1 as i64;
|
||||
Complex(
|
||||
((a * c - b * d + (1 << 31)) >> 32) as i32,
|
||||
((b * c + a * d + (1 << 31)) >> 32) as i32,
|
||||
)
|
||||
impl MulScaled<Complex<i32>> for Complex<i32> {
|
||||
fn mul_scaled(self, other: Self) -> Self {
|
||||
let a = self.re as i64;
|
||||
let b = self.im as i64;
|
||||
let c = other.re as i64;
|
||||
let d = other.im as i64;
|
||||
Complex {
|
||||
re: ((a * c - b * d + (1 << 30)) >> 31) as i32,
|
||||
im: ((b * c + a * d + (1 << 30)) >> 31) as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i32> for Complex<i32> {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: i32) -> Self {
|
||||
Complex(
|
||||
((other as i64 * self.0 as i64 + (1 << 31)) >> 32) as i32,
|
||||
((other as i64 * self.1 as i64 + (1 << 31)) >> 32) as i32,
|
||||
)
|
||||
impl MulScaled<i32> for Complex<i32> {
|
||||
fn mul_scaled(self, other: i32) -> Self {
|
||||
Complex {
|
||||
re: ((other as i64 * self.re as i64 + (1 << 30)) >> 31) as i32,
|
||||
im: ((other as i64 * self.im as i64 + (1 << 30)) >> 31) as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i16> for Complex<i32> {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: i16) -> Self {
|
||||
Complex(
|
||||
(other as i32 * (self.0 >> 16) + (1 << 15)) >> 16,
|
||||
(other as i32 * (self.1 >> 16) + (1 << 15)) >> 16,
|
||||
)
|
||||
impl MulScaled<i16> for Complex<i32> {
|
||||
fn mul_scaled(self, other: i16) -> Self {
|
||||
Complex {
|
||||
re: (other as i32 * (self.re >> 16) + (1 << 14)) >> 15,
|
||||
im: (other as i32 * (self.im >> 16) + (1 << 14)) >> 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@ pub fn cossin(phase: i32) -> (i32, i32) {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::Complex;
|
||||
use core::f64::consts::PI;
|
||||
|
||||
#[test]
|
||||
|
@ -82,11 +81,11 @@ mod tests {
|
|||
// Constant amplitude error due to LUT data range.
|
||||
const AMPLITUDE: f64 = ((1i64 << 31) - (1i64 << 15)) as _;
|
||||
const MAX_PHASE: f64 = (1i64 << 32) as _;
|
||||
let mut rms_err = Complex(0f64, 0f64);
|
||||
let mut sum_err = Complex(0f64, 0f64);
|
||||
let mut max_err = Complex(0f64, 0f64);
|
||||
let mut sum = Complex(0f64, 0f64);
|
||||
let mut demod = Complex(0f64, 0f64);
|
||||
let mut rms_err = (0f64, 0f64);
|
||||
let mut sum_err = (0f64, 0f64);
|
||||
let mut max_err = (0f64, 0f64);
|
||||
let mut sum = (0f64, 0f64);
|
||||
let mut demod = (0f64, 0f64);
|
||||
|
||||
// use std::{fs::File, io::{BufWriter, prelude::*}, path::Path};
|
||||
// let mut file = BufWriter::new(File::create(Path::new("data.bin")).unwrap());
|
||||
|
|
107
dsp/src/lib.rs
107
dsp/src/lib.rs
|
@ -1,101 +1,28 @@
|
|||
#![cfg_attr(not(test), no_std)]
|
||||
#![cfg_attr(feature = "nightly", feature(asm, core_intrinsics))]
|
||||
|
||||
use core::ops::{Add, Mul, Neg};
|
||||
|
||||
fn abs<T>(x: T) -> T
|
||||
where
|
||||
T: PartialOrd + Default + Neg<Output = T>,
|
||||
{
|
||||
if x >= T::default() {
|
||||
x
|
||||
} else {
|
||||
-x
|
||||
}
|
||||
}
|
||||
|
||||
// These are implemented here because core::f32 doesn't have them (yet).
|
||||
// They are naive and don't handle inf/nan.
|
||||
// `compiler-intrinsics`/llvm should have better (robust, universal, and
|
||||
// faster) implementations.
|
||||
|
||||
fn copysign<T>(x: T, y: T) -> T
|
||||
where
|
||||
T: PartialOrd + Default + Neg<Output = T>,
|
||||
{
|
||||
if (x >= T::default() && y >= T::default())
|
||||
|| (x <= T::default() && y <= T::default())
|
||||
{
|
||||
x
|
||||
} else {
|
||||
-x
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
fn max<T>(x: T, y: T) -> T
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
if x > y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
fn min<T>(x: T, y: T) -> T
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
if x < y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
fn max(x: f32, y: f32) -> f32 {
|
||||
core::intrinsics::maxnumf32(x, y)
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
fn min(x: f32, y: f32) -> f32 {
|
||||
core::intrinsics::minnumf32(x, y)
|
||||
}
|
||||
|
||||
// Multiply-accumulate vectors `x` and `a`.
|
||||
//
|
||||
// A.k.a. dot product.
|
||||
// Rust/LLVM optimize this nicely.
|
||||
fn macc<T>(y0: T, x: &[T], a: &[T]) -> T
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + Copy,
|
||||
{
|
||||
x.iter()
|
||||
.zip(a)
|
||||
.map(|(x, a)| *x * *a)
|
||||
.fold(y0, |y, xa| y + xa)
|
||||
}
|
||||
|
||||
pub mod accu;
|
||||
mod tools;
|
||||
pub use tools::*;
|
||||
mod atan2;
|
||||
pub use atan2::*;
|
||||
mod accu;
|
||||
pub use accu::*;
|
||||
mod complex;
|
||||
pub use complex::*;
|
||||
mod cossin;
|
||||
pub use cossin::*;
|
||||
pub mod iir;
|
||||
pub mod iir_int;
|
||||
pub mod lockin;
|
||||
pub mod lowpass;
|
||||
pub mod pll;
|
||||
pub mod rpll;
|
||||
pub mod unwrap;
|
||||
|
||||
pub use accu::Accu;
|
||||
pub use atan2::atan2;
|
||||
pub use complex::Complex;
|
||||
pub use cossin::cossin;
|
||||
mod lockin;
|
||||
pub use lockin::*;
|
||||
mod lowpass;
|
||||
pub use lowpass::*;
|
||||
mod pll;
|
||||
pub use pll::*;
|
||||
mod rpll;
|
||||
pub use rpll::*;
|
||||
mod unwrap;
|
||||
pub use unwrap::*;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod testing;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{lowpass::Lowpass, Complex};
|
||||
use super::{Complex, ComplexExt, Lowpass, MulScaled};
|
||||
use generic_array::typenum::U2;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
|
@ -8,19 +8,15 @@ pub struct Lockin {
|
|||
|
||||
impl Lockin {
|
||||
/// Update the lockin with a sample taken at a given phase.
|
||||
/// The lowpass has a gain of `1 << k`.
|
||||
pub fn update(&mut self, sample: i16, phase: i32, k: u8) -> Complex<i32> {
|
||||
// Get the LO signal for demodulation.
|
||||
let lo = Complex::from_angle(phase);
|
||||
|
||||
// Mix with the LO signal
|
||||
let mix = lo * sample;
|
||||
pub fn update(&mut self, sample: i32, phase: i32, k: u8) -> Complex<i32> {
|
||||
// Get the LO signal for demodulation and mix the sample;
|
||||
let mix = Complex::from_angle(phase).mul_scaled(sample);
|
||||
|
||||
// Filter with the IIR lowpass,
|
||||
// return IQ (in-phase and quadrature) data.
|
||||
Complex(
|
||||
self.state[0].update(mix.0, k),
|
||||
self.state[1].update(mix.1, k),
|
||||
)
|
||||
Complex {
|
||||
re: self.state[0].update(mix.re, k),
|
||||
im: self.state[1].update(mix.im, k),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,19 +14,20 @@ impl<N: ArrayLength<i32>> Lowpass<N> {
|
|||
/// Update the filter with a new sample.
|
||||
///
|
||||
/// # Args
|
||||
/// * `x`: Input data, needs `k` bits headroom.
|
||||
/// * `k`: Log2 time constant, 0..31.
|
||||
/// * `x`: Input data. Needs 1 bit headroom but will saturate cleanly beyond that.
|
||||
/// * `k`: Log2 time constant, 1..=31.
|
||||
///
|
||||
/// # Return
|
||||
/// Filtered output y, with gain of `1 << k`.
|
||||
/// Filtered output y.
|
||||
pub fn update(&mut self, x: i32, k: u8) -> i32 {
|
||||
debug_assert!(k & 31 == k);
|
||||
debug_assert!((k - 1) & 31 == k - 1);
|
||||
// This is an unrolled and optimized first-order IIR loop
|
||||
// that works for all possible time constants.
|
||||
// Note DF-II and the zeros at Nyquist.
|
||||
let mut x = x << k;
|
||||
// Note T-DF-I and the zeros at Nyquist.
|
||||
let mut x = x;
|
||||
for y in self.y.iter_mut() {
|
||||
let dy = (x - *y + (1 << (k - 1))) >> k;
|
||||
let dy = x.saturating_sub(*y).saturating_add(1 << (k - 1)) >> k;
|
||||
*y += dy;
|
||||
x = *y - (dy >> 1);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ pub fn complex_isclose(
|
|||
rtol: f32,
|
||||
atol: f32,
|
||||
) -> bool {
|
||||
isclosef(a.0, b.0, rtol, atol) && isclosef(a.1, b.1, rtol, atol)
|
||||
isclosef(a.re, b.re, rtol, atol) && isclosef(a.im, b.im, rtol, atol)
|
||||
}
|
||||
|
||||
pub fn complex_allclose(
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
use core::ops::{Add, Mul, Neg};
|
||||
|
||||
pub fn abs<T>(x: T) -> T
|
||||
where
|
||||
T: PartialOrd + Default + Neg<Output = T>,
|
||||
{
|
||||
if x >= T::default() {
|
||||
x
|
||||
} else {
|
||||
-x
|
||||
}
|
||||
}
|
||||
|
||||
// These are implemented here because core::f32 doesn't have them (yet).
|
||||
// They are naive and don't handle inf/nan.
|
||||
// `compiler-intrinsics`/llvm should have better (robust, universal, and
|
||||
// faster) implementations.
|
||||
|
||||
pub fn copysign<T>(x: T, y: T) -> T
|
||||
where
|
||||
T: PartialOrd + Default + Neg<Output = T>,
|
||||
{
|
||||
if (x >= T::default() && y >= T::default())
|
||||
|| (x <= T::default() && y <= T::default())
|
||||
{
|
||||
x
|
||||
} else {
|
||||
-x
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
pub fn max<T>(x: T, y: T) -> T
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
if x > y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
pub fn min<T>(x: T, y: T) -> T
|
||||
where
|
||||
T: PartialOrd,
|
||||
{
|
||||
if x < y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
pub fn max(x: f32, y: f32) -> f32 {
|
||||
core::intrinsics::maxnumf32(x, y)
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
pub fn min(x: f32, y: f32) -> f32 {
|
||||
core::intrinsics::minnumf32(x, y)
|
||||
}
|
||||
|
||||
// Multiply-accumulate vectors `x` and `a`.
|
||||
//
|
||||
// A.k.a. dot product.
|
||||
// Rust/LLVM optimize this nicely.
|
||||
pub fn macc<T>(y0: T, x: &[T], a: &[T]) -> T
|
||||
where
|
||||
T: Add<Output = T> + Mul<Output = T> + Copy,
|
||||
{
|
||||
x.iter()
|
||||
.zip(a)
|
||||
.map(|(x, a)| *x * *a)
|
||||
.fold(y0, |y, xa| y + xa)
|
||||
}
|
||||
|
||||
/// Combine high and low i32 into a single downscaled i32, saturating the type.
|
||||
pub fn saturating_scale(lo: i32, hi: i32, shift: u32) -> i32 {
|
||||
debug_assert!(shift & 31 == shift);
|
||||
|
||||
let shift_hi = 31 - shift;
|
||||
debug_assert!(shift_hi & 31 == shift_hi);
|
||||
|
||||
let over = hi >> shift;
|
||||
if over < -1 {
|
||||
i32::MIN
|
||||
} else if over > 0 {
|
||||
i32::MAX
|
||||
} else {
|
||||
(lo >> shift) + (hi << shift_hi)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ use stm32h7xx_hal as hal;
|
|||
|
||||
use stabilizer::{hardware, hardware::design_parameters};
|
||||
|
||||
use dsp::{lockin::Lockin, rpll::RPLL, Accu};
|
||||
use dsp::{Accu, Complex, ComplexExt, Lockin, RPLL};
|
||||
use hardware::{
|
||||
Adc0Input, Adc1Input, Dac0Output, Dac1Output, InputStamper, AFE0, AFE1,
|
||||
};
|
||||
|
@ -110,22 +110,33 @@ const APP: () = {
|
|||
let sample_phase =
|
||||
phase_offset.wrapping_add(pll_phase.wrapping_mul(harmonic));
|
||||
|
||||
let output = adc_samples[0]
|
||||
let output: Complex<i32> = adc_samples[0]
|
||||
.iter()
|
||||
// Zip in the LO phase.
|
||||
.zip(Accu::new(sample_phase, sample_frequency))
|
||||
// Convert to signed, MSB align the ADC sample.
|
||||
// Convert to signed, MSB align the ADC sample, update the Lockin (demodulate, filter)
|
||||
.map(|(&sample, phase)| {
|
||||
lockin.update(sample as i16, phase, time_constant)
|
||||
let s = (sample as i16 as i32) << 16;
|
||||
lockin.update(s, phase, time_constant)
|
||||
})
|
||||
// Decimate
|
||||
.last()
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
* 2; // Full scale assuming the 2f component is gone.
|
||||
|
||||
let conf = "frequency_discriminator";
|
||||
#[allow(dead_code)]
|
||||
enum Conf {
|
||||
PowerPhase,
|
||||
FrequencyDiscriminator,
|
||||
Quadrature,
|
||||
}
|
||||
|
||||
let conf = Conf::FrequencyDiscriminator; // TODO: expose
|
||||
let output = match conf {
|
||||
// Convert from IQ to power and phase.
|
||||
"power_phase" => [(output.log2() << 24) as _, output.arg()],
|
||||
"frequency_discriminator" => [pll_frequency as _, output.arg()],
|
||||
_ => [output.0, output.1],
|
||||
Conf::PowerPhase => [(output.log2() << 24) as _, output.arg()],
|
||||
Conf::FrequencyDiscriminator => [pll_frequency as _, output.arg()],
|
||||
Conf::Quadrature => [output.re, output.im],
|
||||
};
|
||||
|
||||
// Convert to DAC data.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use dsp::{lockin::Lockin, Accu};
|
||||
use dsp::{Accu, Complex, ComplexExt, Lockin};
|
||||
use hardware::{Adc1Input, Dac0Output, Dac1Output, AFE0, AFE1};
|
||||
use stabilizer::{hardware, hardware::design_parameters};
|
||||
|
||||
|
@ -95,17 +95,19 @@ const APP: () = {
|
|||
let sample_phase = phase_offset
|
||||
.wrapping_add((pll_phase as i32).wrapping_mul(harmonic));
|
||||
|
||||
let output = adc_samples
|
||||
let output: Complex<i32> = adc_samples
|
||||
.iter()
|
||||
// Zip in the LO phase.
|
||||
.zip(Accu::new(sample_phase, sample_frequency))
|
||||
// Convert to signed, MSB align the ADC sample, update the Lockin (demodulate, filter)
|
||||
.map(|(&sample, phase)| {
|
||||
lockin.update(sample as i16, phase, time_constant)
|
||||
let s = (sample as i16 as i32) << 16;
|
||||
lockin.update(s, phase, time_constant)
|
||||
})
|
||||
// Decimate
|
||||
.last()
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
* 2; // Full scale assuming the 2f component is gone.
|
||||
|
||||
for value in dac_samples[1].iter_mut() {
|
||||
*value = (output.arg() >> 16) as u16 ^ 0x8000;
|
||||
|
|
Loading…
Reference in New Issue