Merge #261
261: MQTT settings and telemetry r=ryan-summers a=ryan-summers This PR replaces https://github.com/quartiq/stabilizer/pull/242 This PR addresses #149 by exposing a simple MQTT-based settings interface **TODO**: - [x] Resolve mutable ownership issues in the `MqttInterface` - [x] Expand settings interface to `lockin.rs` - [x] Add all settings (not yet supported by `miniconf`) - [x] ~~Finalize and publish the `miniconf` package~~ Deferred to the future. - [x] Move `MqttInterface`-like behaviors over to `miniconf` - [x] Move smoltcp-nal to a separate crate - [x] Test on hardware - [x] ~~Implement stabilizer telemetry~~: Deferred to future Co-authored-by: Ryan Summers <ryan.summers@vertigo-designs.com> Co-authored-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
commit
bfb416b85b
|
@ -40,17 +40,6 @@ dependencies = [
|
||||||
"embedded-hal",
|
"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]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -96,24 +85,6 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c147d86912d04bef727828fda769a76ca81629a46d8ba311a8d58a26aa91473d"
|
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]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.2"
|
version = "1.4.2"
|
||||||
|
@ -135,23 +106,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
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]]
|
[[package]]
|
||||||
name = "cortex-m"
|
name = "cortex-m"
|
||||||
version = "0.6.7"
|
version = "0.6.7"
|
||||||
|
@ -245,116 +199,23 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "criterion"
|
name = "derive_stringset"
|
||||||
version = "0.3.4"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/quartiq/miniconf.git?branch=develop#97ace3d8268075235cb67a2a8740d200bea1fe30"
|
||||||
checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"proc-macro2",
|
||||||
"cast",
|
"quote",
|
||||||
"clap",
|
"syn",
|
||||||
"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]]
|
[[package]]
|
||||||
name = "dsp"
|
name = "dsp"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"criterion",
|
"easybench",
|
||||||
"generic-array 0.14.4",
|
"generic-array 0.14.4",
|
||||||
"libm",
|
"libm",
|
||||||
|
"miniconf",
|
||||||
"ndarray",
|
"ndarray",
|
||||||
"num",
|
"num",
|
||||||
"rand",
|
"rand",
|
||||||
|
@ -362,10 +223,10 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "easybench"
|
||||||
version = "1.6.1"
|
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 = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
checksum = "355215cf95ddc4db0459d5313c9b146bedd43453305e3f0f1c4e8fde7f8d3884"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-dma"
|
name = "embedded-dma"
|
||||||
|
@ -386,6 +247,17 @@ dependencies = [
|
||||||
"void",
|
"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]]
|
[[package]]
|
||||||
name = "enum-iterator"
|
name = "enum-iterator"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -445,12 +317,6 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "half"
|
|
||||||
version = "1.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hash32"
|
name = "hash32"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -479,15 +345,6 @@ dependencies = [
|
||||||
"stable_deref_trait",
|
"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]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
|
@ -498,45 +355,6 @@ dependencies = [
|
||||||
"hashbrown",
|
"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]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.86"
|
version = "0.2.86"
|
||||||
|
@ -582,18 +400,28 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "miniconf"
|
||||||
version = "2.3.4"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/quartiq/miniconf.git?branch=develop#97ace3d8268075235cb67a2a8740d200bea1fe30"
|
||||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
dependencies = [
|
||||||
|
"derive_stringset",
|
||||||
|
"heapless",
|
||||||
|
"minimq",
|
||||||
|
"serde",
|
||||||
|
"serde-json-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "minimq"
|
||||||
version = "0.6.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
|
checksum = "9c5e626690b6f62e15710cf9815e5ca25ee54084899298c100a14b2504c80a46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"bit_field",
|
||||||
|
"embedded-nal",
|
||||||
|
"enum-iterator",
|
||||||
|
"generic-array 0.14.4",
|
||||||
|
"heapless",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -624,6 +452,12 @@ dependencies = [
|
||||||
"rawpointer",
|
"rawpointer",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "no-std-net"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2178127478ae4ee9be7180bc9c3bffb6354dd7238400db567102f98c413a9f35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -687,22 +521,6 @@ dependencies = [
|
||||||
"autocfg",
|
"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]]
|
[[package]]
|
||||||
name = "panic-halt"
|
name = "panic-halt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -725,34 +543,6 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1"
|
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]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.10"
|
version = "0.2.10"
|
||||||
|
@ -829,55 +619,6 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
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]]
|
[[package]]
|
||||||
name = "rtic-core"
|
name = "rtic-core"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -904,27 +645,6 @@ dependencies = [
|
||||||
"semver",
|
"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]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -952,23 +672,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde-json-core"
|
name = "serde-json-core"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/rust-embedded-community/serde-json-core.git?branch=master#ee06ac91bc43b72450a92198a00d9e5c5b9946d2"
|
||||||
checksum = "89fd6016a00149b485f66da701f76d909210d319040c97b6eff300f6e2ba2153"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heapless",
|
"heapless",
|
||||||
"serde",
|
"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]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.123"
|
version = "1.0.123"
|
||||||
|
@ -980,17 +689,6 @@ dependencies = [
|
||||||
"syn",
|
"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]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -1002,6 +700,17 @@ dependencies = [
|
||||||
"managed",
|
"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]]
|
[[package]]
|
||||||
name = "stabilizer"
|
name = "stabilizer"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -1018,13 +727,13 @@ dependencies = [
|
||||||
"heapless",
|
"heapless",
|
||||||
"log",
|
"log",
|
||||||
"mcp23017",
|
"mcp23017",
|
||||||
|
"miniconf",
|
||||||
"nb 1.0.0",
|
"nb 1.0.0",
|
||||||
"panic-halt",
|
"panic-halt",
|
||||||
"panic-semihosting",
|
"panic-semihosting",
|
||||||
"paste",
|
"paste",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-json-core",
|
"smoltcp-nal",
|
||||||
"smoltcp",
|
|
||||||
"stm32h7xx-hal",
|
"stm32h7xx-hal",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1075,37 +784,12 @@ dependencies = [
|
||||||
"unicode-xid",
|
"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]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -1139,114 +823,8 @@ dependencies = [
|
||||||
"vcell",
|
"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]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.10.2+wasi-snapshot-preview1"
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
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"
|
|
||||||
|
|
16
Cargo.toml
16
Cargo.toml
|
@ -36,7 +36,6 @@ panic-semihosting = { version = "0.5", optional = true }
|
||||||
panic-halt = "0.2"
|
panic-halt = "0.2"
|
||||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||||
heapless = { version = "0.5", features = ["serde"] }
|
heapless = { version = "0.5", features = ["serde"] }
|
||||||
serde-json-core = "0.2"
|
|
||||||
cortex-m-rtic = "0.5.5"
|
cortex-m-rtic = "0.5.5"
|
||||||
embedded-hal = "0.2.4"
|
embedded-hal = "0.2.4"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
|
@ -45,15 +44,20 @@ enum-iterator = "0.6.0"
|
||||||
paste = "1"
|
paste = "1"
|
||||||
dsp = { path = "dsp" }
|
dsp = { path = "dsp" }
|
||||||
ad9959 = { path = "ad9959" }
|
ad9959 = { path = "ad9959" }
|
||||||
|
smoltcp-nal = "0.1.0"
|
||||||
|
miniconf = "0.1"
|
||||||
|
|
||||||
|
[patch.crates-io.miniconf]
|
||||||
|
git = "https://github.com/quartiq/miniconf.git"
|
||||||
|
branch = "develop"
|
||||||
|
|
||||||
|
[patch.crates-io.serde-json-core]
|
||||||
|
git = "https://github.com/rust-embedded-community/serde-json-core.git"
|
||||||
|
branch = "master"
|
||||||
|
|
||||||
[dependencies.mcp23017]
|
[dependencies.mcp23017]
|
||||||
git = "https://github.com/mrd0ll4r/mcp23017.git"
|
git = "https://github.com/mrd0ll4r/mcp23017.git"
|
||||||
|
|
||||||
[dependencies.smoltcp]
|
|
||||||
version = "0.7"
|
|
||||||
features = ["ethernet", "proto-ipv4", "socket-tcp", "proto-ipv6"]
|
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[dependencies.stm32h7xx-hal]
|
[dependencies.stm32h7xx-hal]
|
||||||
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
|
features = ["stm32h743v", "rt", "unproven", "ethernet", "quadspi"]
|
||||||
git = "https://github.com/stm32-rs/stm32h7xx-hal"
|
git = "https://github.com/stm32-rs/stm32h7xx-hal"
|
||||||
|
|
|
@ -80,6 +80,5 @@ See https://github.com/sinara-hw/Stabilizer
|
||||||
|
|
||||||
## Protocol
|
## Protocol
|
||||||
|
|
||||||
Stabilizer can be configured via newline-delimited JSON over TCP.
|
Stabilizer can be configured via MQTT under the topic `stabilizer/settings/<setting>`. Refer to
|
||||||
It listens on port 1235. [stabilizer.py](stabilizer.py) contains a reference
|
[`miniconf`](https://github.com/quartiq/miniconf) for more information about topics.
|
||||||
implementation of the protocol.
|
|
||||||
|
|
|
@ -9,9 +9,10 @@ libm = "0.2.1"
|
||||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||||
generic-array = "0.14"
|
generic-array = "0.14"
|
||||||
num = { version = "0.3.1", default-features = false }
|
num = { version = "0.3.1", default-features = false }
|
||||||
|
miniconf = "0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3"
|
easybench = "1.0"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
ndarray = "0.14"
|
ndarray = "0.14"
|
||||||
|
|
||||||
|
|
|
@ -1,68 +1,80 @@
|
||||||
use core::f32::consts::PI;
|
use core::f32::consts::PI;
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use dsp::{atan2, cossin};
|
||||||
use dsp::{atan2, cossin, iir, iir_int, PLL, RPLL};
|
use dsp::{iir, iir_int};
|
||||||
|
use dsp::{PLL, RPLL};
|
||||||
|
use easybench::bench_env;
|
||||||
|
|
||||||
fn atan2_bench(c: &mut Criterion) {
|
fn atan2_bench() {
|
||||||
let xi = (10 << 16) as i32;
|
let xi = (10 << 16) as i32;
|
||||||
let xf = xi as f32 / i32::MAX as f32;
|
let xf = xi as f32 / i32::MAX as f32;
|
||||||
|
|
||||||
let yi = (-26_328 << 16) as i32;
|
let yi = (-26_328 << 16) as i32;
|
||||||
let yf = yi as f32 / i32::MAX as f32;
|
let yf = yi as f32 / i32::MAX as f32;
|
||||||
|
|
||||||
c.bench_function("atan2(y, x)", |b| {
|
println!(
|
||||||
b.iter(|| atan2(black_box(yi), black_box(xi)))
|
"atan2(yi, xi): {}",
|
||||||
});
|
bench_env((yi, xi), |(yi, xi)| atan2(*yi, *xi))
|
||||||
c.bench_function("y.atan2(x)", |b| {
|
);
|
||||||
b.iter(|| black_box(yf).atan2(black_box(xf)))
|
println!(
|
||||||
});
|
"yf.atan2(xf): {}",
|
||||||
|
bench_env((yf, xf), |(yf, xf)| yf.atan2(*xf))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cossin_bench(c: &mut Criterion) {
|
fn cossin_bench() {
|
||||||
let zi = -0x7304_2531_i32;
|
let zi = -0x7304_2531_i32;
|
||||||
let zf = zi as f32 / i32::MAX as f32 * PI;
|
let zf = zi as f32 / i32::MAX as f32 * PI;
|
||||||
c.bench_function("cossin(zi)", |b| b.iter(|| cossin(black_box(zi))));
|
println!("cossin(zi): {}", bench_env(zi, |zi| cossin(*zi)));
|
||||||
c.bench_function("zf.sin_cos()", |b| b.iter(|| black_box(zf).sin_cos()));
|
println!("zf.sin_cos(): {}", bench_env(zf, |zf| zf.sin_cos()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rpll_bench(c: &mut Criterion) {
|
fn rpll_bench() {
|
||||||
let mut dut = RPLL::new(8);
|
let mut dut = RPLL::new(8);
|
||||||
c.bench_function("RPLL::update(Some(t), 21, 20)", |b| {
|
println!(
|
||||||
b.iter(|| dut.update(black_box(Some(0x241)), 21, 20))
|
"RPLL::update(Some(t), 21, 20): {}",
|
||||||
});
|
bench_env(Some(0x241), |x| dut.update(*x, 21, 20))
|
||||||
c.bench_function("RPLL::update(Some(t), sf, sp)", |b| {
|
);
|
||||||
b.iter(|| {
|
println!(
|
||||||
dut.update(black_box(Some(0x241)), black_box(21), black_box(20))
|
"RPLL::update(Some(t), sf, sp): {}",
|
||||||
})
|
bench_env((Some(0x241), 21, 20), |(x, p, q)| dut.update(*x, *p, *q))
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pll_bench(c: &mut Criterion) {
|
fn pll_bench() {
|
||||||
let mut dut = PLL::default();
|
let mut dut = PLL::default();
|
||||||
c.bench_function("PLL::update(t, 12, 11)", |b| {
|
println!(
|
||||||
b.iter(|| dut.update(black_box(0x1234), 12, 1))
|
"PLL::update(t, 12, 12): {}",
|
||||||
});
|
bench_env(0x241, |x| dut.update(*x, 12, 12))
|
||||||
c.bench_function("PLL::update(t, sf, sp)", |b| {
|
);
|
||||||
b.iter(|| dut.update(black_box(0x241), black_box(21), black_box(20)))
|
println!(
|
||||||
});
|
"PLL::update(t, sf, sp): {}",
|
||||||
|
bench_env((0x241, 21, 20), |(x, p, q)| dut.update(*x, *p, *q))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iir_int_bench(c: &mut Criterion) {
|
fn iir_int_bench() {
|
||||||
let dut = iir_int::IIR::default();
|
let dut = iir_int::IIR::default();
|
||||||
let mut xy = iir_int::Vec5::default();
|
let mut xy = iir_int::Vec5::default();
|
||||||
c.bench_function("int_iir::IIR::update(s, x)", |b| {
|
println!(
|
||||||
b.iter(|| dut.update(&mut xy, black_box(0x2832)))
|
"int_iir::IIR::update(s, x): {}",
|
||||||
});
|
bench_env(0x2832, |x| dut.update(&mut xy, *x))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iir_bench(c: &mut Criterion) {
|
fn iir_bench() {
|
||||||
let dut = iir::IIR::default();
|
let dut = iir::IIR::default();
|
||||||
let mut xy = iir::Vec5::default();
|
let mut xy = iir::Vec5::default();
|
||||||
c.bench_function("int::IIR::update(s, x)", |b| {
|
println!(
|
||||||
b.iter(|| dut.update(&mut xy, black_box(0.32241)))
|
"int::IIR::update(s, x): {}",
|
||||||
});
|
bench_env(0.32241, |x| dut.update(&mut xy, *x))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(trig, atan2_bench, cossin_bench);
|
fn main() {
|
||||||
criterion_group!(pll, rpll_bench, pll_bench);
|
atan2_bench();
|
||||||
criterion_group!(iir, iir_int_bench, iir_bench);
|
cossin_bench();
|
||||||
criterion_main!(trig, pll, iir);
|
rpll_bench();
|
||||||
|
pll_bench();
|
||||||
|
iir_int_bench();
|
||||||
|
iir_bench();
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use miniconf::StringSet;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::{abs, copysign, macc, max, min};
|
use super::{abs, copysign, macc, max, min};
|
||||||
use core::f32;
|
use core::f32;
|
||||||
|
@ -38,7 +39,7 @@ pub type Vec5 = [f32; 5];
|
||||||
/// Therefore it can trivially implement bump-less transfer.
|
/// Therefore it can trivially implement bump-less transfer.
|
||||||
/// * Cascading multiple IIR filters allows stable and robust
|
/// * Cascading multiple IIR filters allows stable and robust
|
||||||
/// implementation of transfer functions beyond bequadratic terms.
|
/// implementation of transfer functions beyond bequadratic terms.
|
||||||
#[derive(Copy, Clone, Default, Deserialize, Serialize)]
|
#[derive(Copy, Clone, Debug, Default, Deserialize, StringSet)]
|
||||||
pub struct IIR {
|
pub struct IIR {
|
||||||
pub ba: Vec5,
|
pub ba: Vec5,
|
||||||
pub y_offset: f32,
|
pub y_offset: f32,
|
||||||
|
|
|
@ -4,33 +4,49 @@
|
||||||
|
|
||||||
use stm32h7xx_hal as hal;
|
use stm32h7xx_hal as hal;
|
||||||
|
|
||||||
#[macro_use]
|
use stabilizer::hardware;
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
use rtic::cyccnt::{Instant, U32Ext};
|
use miniconf::{
|
||||||
|
embedded_nal::{IpAddr, Ipv4Addr},
|
||||||
use heapless::{consts::*, String};
|
minimq, MqttInterface, StringSet,
|
||||||
|
};
|
||||||
use stabilizer::{hardware, server};
|
use serde::Deserialize;
|
||||||
|
|
||||||
use dsp::iir;
|
use dsp::iir;
|
||||||
use hardware::{Adc0Input, Adc1Input, Dac0Output, Dac1Output, AFE0, AFE1};
|
use hardware::{
|
||||||
|
Adc0Input, Adc1Input, AfeGain, CycleCounter, Dac0Output, Dac1Output,
|
||||||
|
NetworkStack, AFE0, AFE1,
|
||||||
|
};
|
||||||
|
|
||||||
const SCALE: f32 = i16::MAX as _;
|
const SCALE: f32 = i16::MAX as _;
|
||||||
|
|
||||||
const TCP_RX_BUFFER_SIZE: usize = 8192;
|
|
||||||
const TCP_TX_BUFFER_SIZE: usize = 8192;
|
|
||||||
|
|
||||||
// The number of cascaded IIR biquads per channel. Select 1 or 2!
|
// The number of cascaded IIR biquads per channel. Select 1 or 2!
|
||||||
const IIR_CASCADE_LENGTH: usize = 1;
|
const IIR_CASCADE_LENGTH: usize = 1;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, StringSet)]
|
||||||
|
pub struct Settings {
|
||||||
|
afe: [AfeGain; 2],
|
||||||
|
iir_ch: [[iir::IIR; IIR_CASCADE_LENGTH]; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
afe: [AfeGain::G1, AfeGain::G1],
|
||||||
|
iir_ch: [[iir::IIR::new(1., -SCALE, SCALE); IIR_CASCADE_LENGTH]; 2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
afes: (AFE0, AFE1),
|
afes: (AFE0, AFE1),
|
||||||
adcs: (Adc0Input, Adc1Input),
|
adcs: (Adc0Input, Adc1Input),
|
||||||
dacs: (Dac0Output, Dac1Output),
|
dacs: (Dac0Output, Dac1Output),
|
||||||
net_interface: hardware::Ethernet,
|
mqtt_interface:
|
||||||
|
MqttInterface<Settings, NetworkStack, minimq::consts::U256>,
|
||||||
|
clock: CycleCounter,
|
||||||
|
|
||||||
// Format: iir_state[ch][cascade-no][coeff]
|
// Format: iir_state[ch][cascade-no][coeff]
|
||||||
#[init([[[0.; 5]; IIR_CASCADE_LENGTH]; 2])]
|
#[init([[[0.; 5]; IIR_CASCADE_LENGTH]; 2])]
|
||||||
|
@ -44,6 +60,21 @@ const APP: () = {
|
||||||
// Configure the microcontroller
|
// Configure the microcontroller
|
||||||
let (mut stabilizer, _pounder) = hardware::setup(c.core, c.device);
|
let (mut stabilizer, _pounder) = hardware::setup(c.core, c.device);
|
||||||
|
|
||||||
|
let mqtt_interface = {
|
||||||
|
let mqtt_client = {
|
||||||
|
let broker = IpAddr::V4(Ipv4Addr::new(10, 34, 16, 1));
|
||||||
|
minimq::MqttClient::new(
|
||||||
|
broker,
|
||||||
|
"stabilizer",
|
||||||
|
stabilizer.net.stack,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
MqttInterface::new(mqtt_client, "stabilizer", Settings::default())
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
// Enable ADC/DAC events
|
// Enable ADC/DAC events
|
||||||
stabilizer.adcs.0.start();
|
stabilizer.adcs.0.start();
|
||||||
stabilizer.adcs.1.start();
|
stabilizer.adcs.1.start();
|
||||||
|
@ -54,10 +85,11 @@ const APP: () = {
|
||||||
stabilizer.adc_dac_timer.start();
|
stabilizer.adc_dac_timer.start();
|
||||||
|
|
||||||
init::LateResources {
|
init::LateResources {
|
||||||
|
mqtt_interface,
|
||||||
afes: stabilizer.afes,
|
afes: stabilizer.afes,
|
||||||
adcs: stabilizer.adcs,
|
adcs: stabilizer.adcs,
|
||||||
dacs: stabilizer.dacs,
|
dacs: stabilizer.dacs,
|
||||||
net_interface: stabilizer.net.interface,
|
clock: stabilizer.cycle_counter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,159 +138,44 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle(resources=[net_interface, iir_state, iir_ch, afes])]
|
#[idle(resources=[mqtt_interface, clock], spawn=[settings_update])]
|
||||||
fn idle(mut c: idle::Context) -> ! {
|
fn idle(mut c: idle::Context) -> ! {
|
||||||
let mut socket_set_entries: [_; 8] = Default::default();
|
let clock = c.resources.clock;
|
||||||
let mut sockets =
|
|
||||||
smoltcp::socket::SocketSet::new(&mut socket_set_entries[..]);
|
|
||||||
|
|
||||||
let mut rx_storage = [0; TCP_RX_BUFFER_SIZE];
|
|
||||||
let mut tx_storage = [0; TCP_TX_BUFFER_SIZE];
|
|
||||||
let tcp_handle = {
|
|
||||||
let tcp_rx_buffer =
|
|
||||||
smoltcp::socket::TcpSocketBuffer::new(&mut rx_storage[..]);
|
|
||||||
let tcp_tx_buffer =
|
|
||||||
smoltcp::socket::TcpSocketBuffer::new(&mut tx_storage[..]);
|
|
||||||
let tcp_socket =
|
|
||||||
smoltcp::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
|
|
||||||
sockets.add(tcp_socket)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut server = server::Server::new();
|
|
||||||
|
|
||||||
let mut time = 0u32;
|
|
||||||
let mut next_ms = Instant::now();
|
|
||||||
|
|
||||||
// TODO: Replace with reference to CPU clock from CCDR.
|
|
||||||
next_ms += 400_000.cycles();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let tick = Instant::now() > next_ms;
|
let sleep = c.resources.mqtt_interface.lock(|interface| {
|
||||||
|
!interface.network_stack().poll(clock.current_ms())
|
||||||
if tick {
|
});
|
||||||
next_ms += 400_000.cycles();
|
|
||||||
time += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
match c
|
||||||
|
.resources
|
||||||
|
.mqtt_interface
|
||||||
|
.lock(|interface| interface.update().unwrap())
|
||||||
{
|
{
|
||||||
let socket =
|
miniconf::Action::Continue => {
|
||||||
&mut *sockets.get::<smoltcp::socket::TcpSocket>(tcp_handle);
|
if sleep {
|
||||||
if socket.state() == smoltcp::socket::TcpState::CloseWait {
|
cortex_m::asm::wfi();
|
||||||
socket.close();
|
}
|
||||||
} else if !(socket.is_open() || socket.is_listening()) {
|
|
||||||
socket
|
|
||||||
.listen(1235)
|
|
||||||
.unwrap_or_else(|e| warn!("TCP listen error: {:?}", e));
|
|
||||||
} else {
|
|
||||||
server.poll(socket, |req| {
|
|
||||||
info!("Got request: {:?}", req);
|
|
||||||
stabilizer::route_request!(req,
|
|
||||||
readable_attributes: [
|
|
||||||
"stabilizer/iir/state": (|| {
|
|
||||||
let state = c.resources.iir_state.lock(|iir_state|
|
|
||||||
server::Status {
|
|
||||||
t: time,
|
|
||||||
x0: iir_state[0][0][0],
|
|
||||||
y0: iir_state[0][0][2],
|
|
||||||
x1: iir_state[1][0][0],
|
|
||||||
y1: iir_state[1][0][2],
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok::<server::Status, ()>(state)
|
|
||||||
}),
|
|
||||||
// "_b" means cascades 2nd IIR
|
|
||||||
"stabilizer/iir_b/state": (|| { let state = c.resources.iir_state.lock(|iir_state|
|
|
||||||
server::Status {
|
|
||||||
t: time,
|
|
||||||
x0: iir_state[0][IIR_CASCADE_LENGTH-1][0],
|
|
||||||
y0: iir_state[0][IIR_CASCADE_LENGTH-1][2],
|
|
||||||
x1: iir_state[1][IIR_CASCADE_LENGTH-1][0],
|
|
||||||
y1: iir_state[1][IIR_CASCADE_LENGTH-1][2],
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok::<server::Status, ()>(state)
|
|
||||||
}),
|
|
||||||
"stabilizer/afe0/gain": (|| c.resources.afes.0.get_gain()),
|
|
||||||
"stabilizer/afe1/gain": (|| c.resources.afes.1.get_gain())
|
|
||||||
],
|
|
||||||
|
|
||||||
modifiable_attributes: [
|
|
||||||
"stabilizer/iir0/state": server::IirRequest, (|req: server::IirRequest| {
|
|
||||||
c.resources.iir_ch.lock(|iir_ch| {
|
|
||||||
if req.channel > 1 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
iir_ch[req.channel as usize][0] = req.iir;
|
|
||||||
|
|
||||||
Ok::<server::IirRequest, ()>(req)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
"stabilizer/iir1/state": server::IirRequest, (|req: server::IirRequest| {
|
|
||||||
c.resources.iir_ch.lock(|iir_ch| {
|
|
||||||
if req.channel > 1 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
iir_ch[req.channel as usize][0] = req.iir;
|
|
||||||
|
|
||||||
Ok::<server::IirRequest, ()>(req)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
"stabilizer/iir_b0/state": server::IirRequest, (|req: server::IirRequest| {
|
|
||||||
c.resources.iir_ch.lock(|iir_ch| {
|
|
||||||
if req.channel > 1 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
iir_ch[req.channel as usize][IIR_CASCADE_LENGTH-1] = req.iir;
|
|
||||||
|
|
||||||
Ok::<server::IirRequest, ()>(req)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
"stabilizer/iir_b1/state": server::IirRequest,(|req: server::IirRequest| {
|
|
||||||
c.resources.iir_ch.lock(|iir_ch| {
|
|
||||||
if req.channel > 1 {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
iir_ch[req.channel as usize][IIR_CASCADE_LENGTH-1] = req.iir;
|
|
||||||
|
|
||||||
Ok::<server::IirRequest, ()>(req)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
"stabilizer/afe0/gain": hardware::AfeGain, (|gain| {
|
|
||||||
c.resources.afes.0.set_gain(gain);
|
|
||||||
Ok::<(), ()>(())
|
|
||||||
}),
|
|
||||||
"stabilizer/afe1/gain": hardware::AfeGain, (|gain| {
|
|
||||||
c.resources.afes.1.set_gain(gain);
|
|
||||||
Ok::<(), ()>(())
|
|
||||||
})
|
|
||||||
]
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
miniconf::Action::CommitSettings => {
|
||||||
|
c.spawn.settings_update().unwrap()
|
||||||
let sleep = match c.resources.net_interface.poll(
|
|
||||||
&mut sockets,
|
|
||||||
smoltcp::time::Instant::from_millis(time as i64),
|
|
||||||
) {
|
|
||||||
Ok(changed) => !changed,
|
|
||||||
Err(smoltcp::Error::Unrecognized) => true,
|
|
||||||
Err(e) => {
|
|
||||||
info!("iface poll error: {:?}", e);
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if sleep {
|
|
||||||
cortex_m::asm::wfi();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[task(priority = 1, resources=[mqtt_interface, afes, iir_ch])]
|
||||||
|
fn settings_update(mut c: settings_update::Context) {
|
||||||
|
let settings = &c.resources.mqtt_interface.settings;
|
||||||
|
|
||||||
|
// Update the IIR channels.
|
||||||
|
c.resources.iir_ch.lock(|iir| *iir = settings.iir_ch);
|
||||||
|
|
||||||
|
// Update AFEs
|
||||||
|
c.resources.afes.0.set_gain(settings.afe[0]);
|
||||||
|
c.resources.afes.1.set_gain(settings.afe[1]);
|
||||||
|
}
|
||||||
|
|
||||||
#[task(binds = ETH, priority = 1)]
|
#[task(binds = ETH, priority = 1)]
|
||||||
fn eth(_: eth::Context) {
|
fn eth(_: eth::Context) {
|
||||||
unsafe { hal::ethernet::interrupt_handler() }
|
unsafe { hal::ethernet::interrupt_handler() }
|
||||||
|
|
|
@ -17,7 +17,6 @@ const APP: () = {
|
||||||
afes: (AFE0, AFE1),
|
afes: (AFE0, AFE1),
|
||||||
adcs: (Adc0Input, Adc1Input),
|
adcs: (Adc0Input, Adc1Input),
|
||||||
dacs: (Dac0Output, Dac1Output),
|
dacs: (Dac0Output, Dac1Output),
|
||||||
net_interface: hardware::Ethernet,
|
|
||||||
|
|
||||||
timestamper: InputStamper,
|
timestamper: InputStamper,
|
||||||
pll: RPLL,
|
pll: RPLL,
|
||||||
|
@ -53,7 +52,6 @@ const APP: () = {
|
||||||
afes: stabilizer.afes,
|
afes: stabilizer.afes,
|
||||||
adcs: stabilizer.adcs,
|
adcs: stabilizer.adcs,
|
||||||
dacs: stabilizer.dacs,
|
dacs: stabilizer.dacs,
|
||||||
net_interface: stabilizer.net.interface,
|
|
||||||
timestamper: stabilizer.timestamper,
|
timestamper: stabilizer.timestamper,
|
||||||
|
|
||||||
pll,
|
pll,
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
use miniconf::StringSet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use enum_iterator::IntoEnumIterator;
|
use enum_iterator::IntoEnumIterator;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, IntoEnumIterator)]
|
#[derive(
|
||||||
|
Copy, Clone, Debug, Serialize, Deserialize, IntoEnumIterator, StringSet,
|
||||||
|
)]
|
||||||
pub enum Gain {
|
pub enum Gain {
|
||||||
G1 = 0b00,
|
G1 = 0b00,
|
||||||
G2 = 0b01,
|
G2 = 0b01,
|
||||||
|
|
|
@ -1,32 +1,36 @@
|
||||||
///! Stabilizer hardware configuration
|
///! Stabilizer hardware configuration
|
||||||
///!
|
///!
|
||||||
///! This file contains all of the hardware-specific configuration of Stabilizer.
|
///! This file contains all of the hardware-specific configuration of Stabilizer.
|
||||||
use smoltcp::{iface::Routes, wire::Ipv4Address};
|
|
||||||
|
|
||||||
use stm32h7xx_hal::{
|
use stm32h7xx_hal::{
|
||||||
self as hal,
|
self as hal,
|
||||||
ethernet::{self, PHY},
|
ethernet::{self, PHY},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use smoltcp_nal::smoltcp;
|
||||||
|
|
||||||
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
adc, afe, dac, design_parameters, digital_input_stamper, eeprom, pounder,
|
adc, afe, cycle_counter::CycleCounter, dac, design_parameters,
|
||||||
timers, DdsOutput, Ethernet, AFE0, AFE1,
|
digital_input_stamper, eeprom, pounder, timers, DdsOutput, NetworkStack,
|
||||||
|
AFE0, AFE1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Network storage definition for the ethernet interface.
|
pub struct NetStorage {
|
||||||
struct NetStorage {
|
pub ip_addrs: [smoltcp::wire::IpCidr; 1],
|
||||||
ip_addrs: [smoltcp::wire::IpCidr; 1],
|
pub sockets: [Option<smoltcp::socket::SocketSetItem<'static>>; 1],
|
||||||
neighbor_cache:
|
pub neighbor_cache:
|
||||||
[Option<(smoltcp::wire::IpAddress, smoltcp::iface::Neighbor)>; 8],
|
[Option<(smoltcp::wire::IpAddress, smoltcp::iface::Neighbor)>; 8],
|
||||||
routes_storage: [Option<(smoltcp::wire::IpCidr, smoltcp::iface::Route)>; 1],
|
pub routes_cache:
|
||||||
|
[Option<(smoltcp::wire::IpCidr, smoltcp::iface::Route)>; 8],
|
||||||
|
pub tx_storage: [u8; 4096],
|
||||||
|
pub rx_storage: [u8; 4096],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The available networking devices on Stabilizer.
|
/// The available networking devices on Stabilizer.
|
||||||
pub struct NetworkDevices {
|
pub struct NetworkDevices {
|
||||||
pub interface: Ethernet,
|
pub stack: NetworkStack,
|
||||||
pub phy: ethernet::phy::LAN8742A<ethernet::EthernetMAC>,
|
pub phy: ethernet::phy::LAN8742A<ethernet::EthernetMAC>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +43,7 @@ pub struct StabilizerDevices {
|
||||||
pub adc_dac_timer: timers::SamplingTimer,
|
pub adc_dac_timer: timers::SamplingTimer,
|
||||||
pub timestamp_timer: timers::TimestampTimer,
|
pub timestamp_timer: timers::TimestampTimer,
|
||||||
pub net: NetworkDevices,
|
pub net: NetworkDevices,
|
||||||
|
pub cycle_counter: CycleCounter,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The available Pounder-specific hardware interfaces.
|
/// The available Pounder-specific hardware interfaces.
|
||||||
|
@ -63,7 +68,11 @@ static mut NET_STORE: NetStorage = NetStorage {
|
||||||
smoltcp::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX,
|
smoltcp::wire::Ipv6Cidr::SOLICITED_NODE_PREFIX,
|
||||||
)],
|
)],
|
||||||
neighbor_cache: [None; 8],
|
neighbor_cache: [None; 8],
|
||||||
routes_storage: [None; 1],
|
routes_cache: [None; 8],
|
||||||
|
sockets: [None; 1],
|
||||||
|
|
||||||
|
tx_storage: [0; 4096],
|
||||||
|
rx_storage: [0; 4096],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Configure the stabilizer hardware for operation.
|
/// Configure the stabilizer hardware for operation.
|
||||||
|
@ -514,8 +523,9 @@ pub fn setup(
|
||||||
24,
|
24,
|
||||||
);
|
);
|
||||||
|
|
||||||
let default_v4_gw = Ipv4Address::new(10, 34, 16, 1);
|
let default_v4_gw = smoltcp::wire::Ipv4Address::new(10, 34, 16, 1);
|
||||||
let mut routes = Routes::new(&mut store.routes_storage[..]);
|
let mut routes =
|
||||||
|
smoltcp::iface::Routes::new(&mut store.routes_cache[..]);
|
||||||
routes.add_default_ipv4_route(default_v4_gw).unwrap();
|
routes.add_default_ipv4_route(default_v4_gw).unwrap();
|
||||||
|
|
||||||
let neighbor_cache =
|
let neighbor_cache =
|
||||||
|
@ -528,8 +538,36 @@ pub fn setup(
|
||||||
.routes(routes)
|
.routes(routes)
|
||||||
.finalize();
|
.finalize();
|
||||||
|
|
||||||
|
let sockets = {
|
||||||
|
// Note(unsafe): Configuration is only called once, so we only access the global
|
||||||
|
// storage a single time.
|
||||||
|
let socket_storage = unsafe { &mut NET_STORE.sockets[..] };
|
||||||
|
let mut sockets = smoltcp::socket::SocketSet::new(socket_storage);
|
||||||
|
|
||||||
|
let tcp_socket = {
|
||||||
|
let rx_buffer = {
|
||||||
|
// Note(unsafe): Configuration is only called once, so we only access the global
|
||||||
|
// storage a single time.
|
||||||
|
let storage = unsafe { &mut NET_STORE.rx_storage[..] };
|
||||||
|
smoltcp::socket::TcpSocketBuffer::new(storage)
|
||||||
|
};
|
||||||
|
|
||||||
|
let tx_buffer = {
|
||||||
|
// Note(unsafe): Configuration is only called once, so we only access the global
|
||||||
|
// storage a single time.
|
||||||
|
let storage = unsafe { &mut NET_STORE.tx_storage[..] };
|
||||||
|
smoltcp::socket::TcpSocketBuffer::new(storage)
|
||||||
|
};
|
||||||
|
|
||||||
|
smoltcp::socket::TcpSocket::new(rx_buffer, tx_buffer)
|
||||||
|
};
|
||||||
|
|
||||||
|
sockets.add(tcp_socket);
|
||||||
|
sockets
|
||||||
|
};
|
||||||
|
|
||||||
NetworkDevices {
|
NetworkDevices {
|
||||||
interface,
|
stack: smoltcp_nal::NetworkStack::new(interface, sockets),
|
||||||
phy: lan8742a,
|
phy: lan8742a,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -795,6 +833,7 @@ pub fn setup(
|
||||||
net: network_devices,
|
net: network_devices,
|
||||||
adc_dac_timer: sampling_timer,
|
adc_dac_timer: sampling_timer,
|
||||||
timestamp_timer,
|
timestamp_timer,
|
||||||
|
cycle_counter: CycleCounter::new(core.DWT, ccdr.clocks.c_ck()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
// info!("Version {} {}", build_info::PKG_VERSION, build_info::GIT_VERSION.unwrap());
|
||||||
|
@ -804,8 +843,5 @@ pub fn setup(
|
||||||
// Enable the instruction cache.
|
// Enable the instruction cache.
|
||||||
core.SCB.enable_icache();
|
core.SCB.enable_icache();
|
||||||
|
|
||||||
// Utilize the cycle counter for RTIC scheduling.
|
|
||||||
core.DWT.enable_cycle_counter();
|
|
||||||
|
|
||||||
(stabilizer, pounder)
|
(stabilizer, pounder)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
use rtic::cyccnt::{Duration, Instant, U32Ext};
|
||||||
|
|
||||||
|
use stm32h7xx_hal::time::Hertz;
|
||||||
|
|
||||||
|
/// A simple clock for counting elapsed milliseconds.
|
||||||
|
pub struct CycleCounter {
|
||||||
|
// The time of the next millisecond in the system.
|
||||||
|
next_tick: Option<Instant>,
|
||||||
|
|
||||||
|
// The number of elapsed milliseconds recorded.
|
||||||
|
ticks: u32,
|
||||||
|
|
||||||
|
// The increment amount of clock cycles for each elapsed millisecond.
|
||||||
|
increment: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CycleCounter {
|
||||||
|
/// Construct the cycle counting clock.
|
||||||
|
///
|
||||||
|
/// # Args
|
||||||
|
/// * `dwt` - The debug watch and trace unit of the CPU core.
|
||||||
|
/// * `cpu_frequency` - The frequency that the cycle counter counts at.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// A clock that can be used for measuring elapsed milliseconds.
|
||||||
|
pub fn new(
|
||||||
|
mut dwt: cortex_m::peripheral::DWT,
|
||||||
|
cpu_frequency: impl Into<Hertz>,
|
||||||
|
) -> Self {
|
||||||
|
dwt.enable_cycle_counter();
|
||||||
|
let increment =
|
||||||
|
((cpu_frequency.into().0 as f32 / 1000.0) as u32).cycles();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
increment,
|
||||||
|
ticks: 0,
|
||||||
|
next_tick: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the current number of milliseconds elapsed in the system.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
/// This function must be called more often than once per 10 seconds to prevent internal
|
||||||
|
/// wrapping of the cycle counter.
|
||||||
|
///
|
||||||
|
/// The internal millisecond accumulator will overflow just shy of every 50 days.
|
||||||
|
///
|
||||||
|
/// This function does not start counting milliseconds until the very first invocation.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// The number of elapsed milliseconds since the system started.
|
||||||
|
pub fn current_ms(&mut self) -> u32 {
|
||||||
|
if self.next_tick.is_none() {
|
||||||
|
self.next_tick = Some(Instant::now() + self.increment);
|
||||||
|
}
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
|
while now > self.next_tick.unwrap() {
|
||||||
|
*self.next_tick.as_mut().unwrap() += self.increment;
|
||||||
|
self.ticks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ticks
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ use panic_halt as _;
|
||||||
mod adc;
|
mod adc;
|
||||||
mod afe;
|
mod afe;
|
||||||
mod configuration;
|
mod configuration;
|
||||||
|
mod cycle_counter;
|
||||||
mod dac;
|
mod dac;
|
||||||
pub mod design_parameters;
|
pub mod design_parameters;
|
||||||
mod digital_input_stamper;
|
mod digital_input_stamper;
|
||||||
|
@ -19,6 +20,7 @@ mod timers;
|
||||||
|
|
||||||
pub use adc::{Adc0Input, Adc1Input};
|
pub use adc::{Adc0Input, Adc1Input};
|
||||||
pub use afe::Gain as AfeGain;
|
pub use afe::Gain as AfeGain;
|
||||||
|
pub use cycle_counter::CycleCounter;
|
||||||
pub use dac::{Dac0Output, Dac1Output};
|
pub use dac::{Dac0Output, Dac1Output};
|
||||||
pub use digital_input_stamper::InputStamper;
|
pub use digital_input_stamper::InputStamper;
|
||||||
pub use pounder::DdsOutput;
|
pub use pounder::DdsOutput;
|
||||||
|
@ -35,8 +37,8 @@ pub type AFE1 = afe::ProgrammableGainAmplifier<
|
||||||
hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>,
|
hal::gpio::gpiod::PD15<hal::gpio::Output<hal::gpio::PushPull>>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
// Type alias for the ethernet interface on Stabilizer.
|
pub type NetworkStack = smoltcp_nal::NetworkStack<
|
||||||
pub type Ethernet = smoltcp::iface::EthernetInterface<
|
'static,
|
||||||
'static,
|
'static,
|
||||||
hal::ethernet::EthernetDMA<'static>,
|
hal::ethernet::EthernetDMA<'static>,
|
||||||
>;
|
>;
|
||||||
|
|
|
@ -5,4 +5,3 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
pub mod hardware;
|
pub mod hardware;
|
||||||
pub mod server;
|
|
||||||
|
|
278
src/server.rs
278
src/server.rs
|
@ -1,278 +0,0 @@
|
||||||
use core::fmt::Write;
|
|
||||||
use heapless::{consts::*, String, Vec};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json_core::{de::from_slice, ser::to_string};
|
|
||||||
use smoltcp as net;
|
|
||||||
|
|
||||||
use dsp::iir;
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! route_request {
|
|
||||||
($request:ident,
|
|
||||||
readable_attributes: [$($read_attribute:tt: $getter:tt),*],
|
|
||||||
modifiable_attributes: [$($write_attribute:tt: $TYPE:ty, $setter:tt),*]) => {
|
|
||||||
match $request.req {
|
|
||||||
server::AccessRequest::Read => {
|
|
||||||
match $request.attribute {
|
|
||||||
$(
|
|
||||||
$read_attribute => {
|
|
||||||
#[allow(clippy::redundant_closure_call)]
|
|
||||||
let value = match $getter() {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(_) => return server::Response::error($request.attribute,
|
|
||||||
"Failed to read attribute"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let encoded_data: String<U256> = match serde_json_core::to_string(&value) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(_) => return server::Response::error($request.attribute,
|
|
||||||
"Failed to encode attribute value"),
|
|
||||||
};
|
|
||||||
|
|
||||||
server::Response::success($request.attribute, &encoded_data)
|
|
||||||
},
|
|
||||||
)*
|
|
||||||
_ => server::Response::error($request.attribute, "Unknown attribute")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
server::AccessRequest::Write => {
|
|
||||||
match $request.attribute {
|
|
||||||
$(
|
|
||||||
$write_attribute => {
|
|
||||||
let new_value = match serde_json_core::from_str::<$TYPE>(&$request.value) {
|
|
||||||
Ok((data, _)) => data,
|
|
||||||
Err(_) => return server::Response::error($request.attribute,
|
|
||||||
"Failed to decode value"),
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure_call)]
|
|
||||||
match $setter(new_value) {
|
|
||||||
Ok(_) => server::Response::success($request.attribute, &$request.value),
|
|
||||||
Err(_) => server::Response::error($request.attribute,
|
|
||||||
"Failed to set attribute"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
_ => server::Response::error($request.attribute, "Unknown attribute")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub enum AccessRequest {
|
|
||||||
Read,
|
|
||||||
Write,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct Request<'a> {
|
|
||||||
pub req: AccessRequest,
|
|
||||||
pub attribute: &'a str,
|
|
||||||
pub value: String<U256>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct IirRequest {
|
|
||||||
pub channel: u8,
|
|
||||||
pub iir: iir::IIR,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct Response {
|
|
||||||
code: i32,
|
|
||||||
attribute: String<U256>,
|
|
||||||
value: String<U256>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Request<'a> {
|
|
||||||
pub fn restore_value(&mut self) {
|
|
||||||
let mut new_value: String<U256> = String::new();
|
|
||||||
for byte in self.value.as_str().chars() {
|
|
||||||
if byte == '\'' {
|
|
||||||
new_value.push('"').unwrap();
|
|
||||||
} else {
|
|
||||||
new_value.push(byte).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.value = new_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Response {
|
|
||||||
/// Remove all double quotation marks from the `value` field of a response.
|
|
||||||
fn sanitize_value(&mut self) {
|
|
||||||
let mut new_value: String<U256> = String::new();
|
|
||||||
for byte in self.value.as_str().chars() {
|
|
||||||
if byte == '"' {
|
|
||||||
new_value.push('\'').unwrap();
|
|
||||||
} else {
|
|
||||||
new_value.push(byte).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.value = new_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remove all double quotation marks from the `value` field of a response and wrap it in single
|
|
||||||
/// quotes.
|
|
||||||
fn wrap_and_sanitize_value(&mut self) {
|
|
||||||
let mut new_value: String<U256> = String::new();
|
|
||||||
new_value.push('\'').unwrap();
|
|
||||||
for byte in self.value.as_str().chars() {
|
|
||||||
if byte == '"' {
|
|
||||||
new_value.push('\'').unwrap();
|
|
||||||
} else {
|
|
||||||
new_value.push(byte).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_value.push('\'').unwrap();
|
|
||||||
|
|
||||||
self.value = new_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a successful reply.
|
|
||||||
///
|
|
||||||
/// Note: `value` will be sanitized to convert all single quotes to double quotes.
|
|
||||||
///
|
|
||||||
/// Args:
|
|
||||||
/// * `attrbute` - The attribute of the success.
|
|
||||||
/// * `value` - The value of the attribute.
|
|
||||||
pub fn success(attribute: &str, value: &str) -> Self {
|
|
||||||
let mut res = Self {
|
|
||||||
code: 200,
|
|
||||||
attribute: String::from(attribute),
|
|
||||||
value: String::from(value),
|
|
||||||
};
|
|
||||||
res.sanitize_value();
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct an error reply.
|
|
||||||
///
|
|
||||||
/// Note: `message` will be sanitized to convert all single quotes to double quotes.
|
|
||||||
///
|
|
||||||
/// Args:
|
|
||||||
/// * `attrbute` - The attribute of the success.
|
|
||||||
/// * `message` - The message denoting the error.
|
|
||||||
pub fn error(attribute: &str, message: &str) -> Self {
|
|
||||||
let mut res = Self {
|
|
||||||
code: 400,
|
|
||||||
attribute: String::from(attribute),
|
|
||||||
value: String::from(message),
|
|
||||||
};
|
|
||||||
res.wrap_and_sanitize_value();
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a custom reply.
|
|
||||||
///
|
|
||||||
/// Note: `message` will be sanitized to convert all single quotes to double quotes.
|
|
||||||
///
|
|
||||||
/// Args:
|
|
||||||
/// * `attrbute` - The attribute of the success.
|
|
||||||
/// * `message` - The message denoting the status.
|
|
||||||
pub fn custom(code: i32, message: &str) -> Self {
|
|
||||||
let mut res = Self {
|
|
||||||
code,
|
|
||||||
attribute: String::from(""),
|
|
||||||
value: String::from(message),
|
|
||||||
};
|
|
||||||
res.wrap_and_sanitize_value();
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct Status {
|
|
||||||
pub t: u32,
|
|
||||||
pub x0: f32,
|
|
||||||
pub y0: f32,
|
|
||||||
pub x1: f32,
|
|
||||||
pub y1: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn json_reply<T: Serialize>(socket: &mut net::socket::TcpSocket, msg: &T) {
|
|
||||||
let mut u: String<U512> = to_string(msg).unwrap();
|
|
||||||
u.push('\n').unwrap();
|
|
||||||
socket.write_str(&u).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Server {
|
|
||||||
data: Vec<u8, U256>,
|
|
||||||
discard: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Server {
|
|
||||||
/// Construct a new server object for managing requests.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
data: Vec::new(),
|
|
||||||
discard: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Poll the server for potential data updates.
|
|
||||||
///
|
|
||||||
/// Args:
|
|
||||||
/// * `socket` - The socket to check contents from.
|
|
||||||
/// * `f` - A closure that can be called if a request has been received on the server.
|
|
||||||
pub fn poll<F>(&mut self, socket: &mut net::socket::TcpSocket, mut f: F)
|
|
||||||
where
|
|
||||||
F: FnMut(&Request) -> Response,
|
|
||||||
{
|
|
||||||
while socket.can_recv() {
|
|
||||||
let found = socket
|
|
||||||
.recv(|buf| {
|
|
||||||
let (len, found) =
|
|
||||||
match buf.iter().position(|&c| c as char == '\n') {
|
|
||||||
Some(end) => (end + 1, true),
|
|
||||||
None => (buf.len(), false),
|
|
||||||
};
|
|
||||||
if self.data.len() + len >= self.data.capacity() {
|
|
||||||
self.discard = true;
|
|
||||||
self.data.clear();
|
|
||||||
} else if !self.discard && len > 0 {
|
|
||||||
self.data.extend_from_slice(&buf[..len]).unwrap();
|
|
||||||
}
|
|
||||||
(len, found)
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if found {
|
|
||||||
if self.discard {
|
|
||||||
self.discard = false;
|
|
||||||
json_reply(
|
|
||||||
socket,
|
|
||||||
&Response::custom(520, "command buffer overflow"),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let r = from_slice::<Request>(
|
|
||||||
&self.data[..self.data.len() - 1],
|
|
||||||
);
|
|
||||||
match r {
|
|
||||||
Ok((mut res, _)) => {
|
|
||||||
// Note that serde_json_core doesn't escape quotations within a string.
|
|
||||||
// To account for this, we manually translate all single quotes to
|
|
||||||
// double quotes. This occurs because we doubly-serialize this field in
|
|
||||||
// some cases.
|
|
||||||
res.restore_value();
|
|
||||||
let response = f(&res);
|
|
||||||
json_reply(socket, &response);
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
warn!("parse error {:?}", err);
|
|
||||||
json_reply(
|
|
||||||
socket,
|
|
||||||
&Response::custom(550, "parse error"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.data.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
112
stabilizer.py
112
stabilizer.py
|
@ -1,112 +0,0 @@
|
||||||
import json
|
|
||||||
import asyncio
|
|
||||||
from collections import OrderedDict as OD
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
class StabilizerError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class StabilizerConfig:
|
|
||||||
async def connect(self, host, port=1235):
|
|
||||||
self.reader, self.writer = await asyncio.open_connection(host, port)
|
|
||||||
|
|
||||||
async def set(self, channel, iir):
|
|
||||||
value = OD([("channel", channel), ("iir", iir.as_dict())])
|
|
||||||
request = {
|
|
||||||
"req": "Write",
|
|
||||||
"attribute": "stabilizer/iir{}/state".format(channel),
|
|
||||||
"value": json.dumps(value, separators=[',', ':']).replace('"', "'"),
|
|
||||||
}
|
|
||||||
s = json.dumps(request, separators=[',', ':'])
|
|
||||||
assert "\n" not in s
|
|
||||||
logger.debug("send %s", s)
|
|
||||||
self.writer.write(s.encode("ascii") + b"\n")
|
|
||||||
r = (await self.reader.readline()).decode()
|
|
||||||
logger.debug("recv %s", r)
|
|
||||||
ret = json.loads(r, object_pairs_hook=OD)
|
|
||||||
if ret["code"] != 200:
|
|
||||||
raise StabilizerError(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class IIR:
|
|
||||||
t_update = 2e-6
|
|
||||||
full_scale = float((1 << 15) - 1)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.ba = np.zeros(5, np.float32)
|
|
||||||
self.y_offset = 0.
|
|
||||||
self.y_min = -self.full_scale - 1
|
|
||||||
self.y_max = self.full_scale
|
|
||||||
|
|
||||||
def as_dict(self):
|
|
||||||
iir = OD()
|
|
||||||
iir["ba"] = [float(_) for _ in self.ba]
|
|
||||||
iir["y_offset"] = self.y_offset
|
|
||||||
iir["y_min"] = self.y_min
|
|
||||||
iir["y_max"] = self.y_max
|
|
||||||
return iir
|
|
||||||
|
|
||||||
def configure_pi(self, kp, ki, g=0.):
|
|
||||||
ki = np.copysign(ki, kp)*self.t_update*2
|
|
||||||
g = np.copysign(g, kp)
|
|
||||||
eps = np.finfo(np.float32).eps
|
|
||||||
if abs(ki) < eps:
|
|
||||||
a1, b0, b1 = 0., kp, 0.
|
|
||||||
else:
|
|
||||||
if abs(g) < eps:
|
|
||||||
c = 1.
|
|
||||||
else:
|
|
||||||
c = 1./(1. + ki/g)
|
|
||||||
a1 = 2*c - 1.
|
|
||||||
b0 = ki*c + kp
|
|
||||||
b1 = ki*c - a1*kp
|
|
||||||
if abs(b0 + b1) < eps:
|
|
||||||
raise ValueError("low integrator gain and/or gain limit")
|
|
||||||
self.ba[0] = b0
|
|
||||||
self.ba[1] = b1
|
|
||||||
self.ba[2] = 0.
|
|
||||||
self.ba[3] = a1
|
|
||||||
self.ba[4] = 0.
|
|
||||||
|
|
||||||
def set_x_offset(self, o):
|
|
||||||
b = self.ba[:3].sum()*self.full_scale
|
|
||||||
self.y_offset = b*o
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import argparse
|
|
||||||
p = argparse.ArgumentParser()
|
|
||||||
p.add_argument("-s", "--stabilizer", default="10.0.16.99")
|
|
||||||
p.add_argument("-c", "--channel", default=0, type=int,
|
|
||||||
help="Stabilizer channel to configure")
|
|
||||||
p.add_argument("-o", "--offset", default=0., type=float,
|
|
||||||
help="input offset, in units of full scale")
|
|
||||||
p.add_argument("-p", "--proportional-gain", default=1., type=float,
|
|
||||||
help="Proportional gain, in units of 1")
|
|
||||||
p.add_argument("-i", "--integral-gain", default=0., type=float,
|
|
||||||
help="Integral gain, in units of Hz, "
|
|
||||||
"sign taken from proportional-gain")
|
|
||||||
|
|
||||||
args = p.parse_args()
|
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
# loop.set_debug(True)
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
i = IIR()
|
|
||||||
i.configure_pi(args.proportional_gain, args.integral_gain)
|
|
||||||
i.set_x_offset(args.offset)
|
|
||||||
s = StabilizerConfig()
|
|
||||||
await s.connect(args.stabilizer)
|
|
||||||
assert args.channel in range(2)
|
|
||||||
r = await s.set(args.channel, i)
|
|
||||||
|
|
||||||
loop.run_until_complete(main())
|
|
Loading…
Reference in New Issue