Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 31c6eb0821 | |||
| 82230299a4 | |||
| 939120b08e | |||
| 92e1475c93 | |||
| 9288c2b28d | |||
| db7a2bc36b | |||
| 389df16c0c | |||
| 5b72765928 | |||
| e31be21b78 | |||
| 7cee5eb4c5 | |||
| 3604a9405b | |||
| 33291108bd | |||
| 6e02c6b46e | |||
| 8babea285f | |||
| 35ae384a43 | |||
| 1b09b4e235 | |||
| 54afb64ae8 | |||
| 2fe5e93d4b | |||
| 7a5866dc4c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
data.csv
|
||||||
|
|||||||
327
Cargo.lock
generated
327
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler2"
|
name = "adler2"
|
||||||
@@ -20,6 +20,15 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -32,6 +41,18 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.19.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
@@ -44,18 +65,47 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
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 = "chrono"
|
||||||
|
version = "0.4.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118"
|
||||||
|
dependencies = [
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.4.2"
|
version = "1.4.2"
|
||||||
@@ -74,6 +124,12 @@ dependencies = [
|
|||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.34"
|
version = "1.0.34"
|
||||||
@@ -109,6 +165,30 @@ dependencies = [
|
|||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.65"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.9"
|
version = "0.24.9"
|
||||||
@@ -122,12 +202,67 @@ dependencies = [
|
|||||||
"png",
|
"png",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-kit-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"mach2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.159"
|
version = "0.2.159"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libudev"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78b324152da65df7bb95acfcaab55e3097ceaab02fb19b228a9eb74d55f135e0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"libudev-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libudev-sys"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach2"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "macroquad"
|
name = "macroquad"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@@ -186,6 +321,17 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -213,13 +359,19 @@ dependencies = [
|
|||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.14"
|
version = "0.17.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
|
checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"fdeflate",
|
"fdeflate",
|
||||||
"flate2",
|
"flate2",
|
||||||
@@ -245,7 +397,9 @@ dependencies = [
|
|||||||
name = "quad"
|
name = "quad"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
"macroquad",
|
"macroquad",
|
||||||
|
"serialport",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -263,6 +417,42 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serialport"
|
||||||
|
version = "4.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ba776acc8c373b9175829206229366273225436845c04f9c20aab8099960e2e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"cfg-if",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"io-kit-sys",
|
||||||
|
"libudev",
|
||||||
|
"mach2",
|
||||||
|
"nix",
|
||||||
|
"scopeguard",
|
||||||
|
"unescaper",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@@ -289,12 +479,41 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
version = "0.15.2"
|
version = "0.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unescaper"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c878a167baa8afd137494101a688ef8c67125089ff2249284bd2b5f9bfedb815"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
@@ -307,6 +526,51 @@ version = "0.9.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.108"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.108"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.108"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.108"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -329,6 +593,65 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.62.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-link",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.60.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.59.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-strings"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.35"
|
||||||
|
|||||||
@@ -4,4 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
chrono = "0.4.43"
|
||||||
macroquad = "0.4.13"
|
macroquad = "0.4.13"
|
||||||
|
serialport = "4.5.1"
|
||||||
|
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -1,3 +1,12 @@
|
|||||||
Finally, an easy way to do graphics with rust.
|
Finally, an easy way to do graphics with rust.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Keybinds
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
| - | - |
|
||||||
|
| F1 | Pause/Play the graph |
|
||||||
|
| F2 | Dump the current data to a csv and graph it with gnuplot |
|
||||||
|
| F3 | Show/Hide Debug info |
|
||||||
|
| F4 | Show/Hide Cursor Location |
|
||||||
|
|||||||
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 33 KiB |
510
src/main.rs
510
src/main.rs
@@ -1,43 +1,69 @@
|
|||||||
|
#![feature(random)]
|
||||||
use core::f32;
|
use core::f32;
|
||||||
|
use std::{
|
||||||
|
fs::{read_dir, OpenOptions},
|
||||||
|
io::Write,
|
||||||
|
path::PathBuf,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
sync::mpsc::{self, Receiver, Sender},
|
||||||
|
thread::{self, JoinHandle},
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
|
use chrono::{Datelike, Local, Timelike};
|
||||||
use macroquad::prelude::*;
|
use macroquad::prelude::*;
|
||||||
|
|
||||||
const DOT_RADIUS: f32 = 1.0;
|
const THICKNESS: f32 = 2.0;
|
||||||
|
const TAIL_LEN: usize = 100;
|
||||||
|
const BAUD_RATE: u32 = 57600;
|
||||||
|
static mut PORT: Option<String> = None;
|
||||||
|
|
||||||
struct Dot {
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
struct Point {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
|
time_since_last: f32,
|
||||||
}
|
}
|
||||||
|
impl Point {
|
||||||
impl Dot {
|
fn new(x: f32, y: f32, delta: f32) -> Self {
|
||||||
fn new(x: f32, y: f32) -> Self {
|
Self {
|
||||||
Self {x,y}
|
x,
|
||||||
}
|
y,
|
||||||
fn draw(&self) {
|
time_since_last: delta,
|
||||||
draw_circle(self.x, self.y,DOT_RADIUS, GREEN);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DebugWindow {
|
struct DebugWindow<'a> {
|
||||||
text: Vec<String>,
|
text: Vec<String>,
|
||||||
text_margin: f32,
|
text_margin: f32,
|
||||||
|
font: Option<&'a Font>,
|
||||||
}
|
}
|
||||||
impl DebugWindow {
|
impl<'a> DebugWindow<'a> {
|
||||||
fn new() -> Self {
|
fn new(font: Option<&'a Font>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
text: Vec::new(),
|
text: Vec::new(),
|
||||||
text_margin: 20.0,
|
text_margin: 20.0,
|
||||||
|
font,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn add_line(&mut self, line: String) {
|
fn add_line(&mut self, line: String) {
|
||||||
self.text.push(line);
|
self.text.push(line);
|
||||||
}
|
}
|
||||||
|
fn get_params(&self) -> TextParams {
|
||||||
|
let params = TextParams {
|
||||||
|
color: WHITE,
|
||||||
|
font: self.font,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
params
|
||||||
|
}
|
||||||
fn draw(&self) {
|
fn draw(&self) {
|
||||||
let params = TextParams { color: WHITE, ..Default::default()} ;
|
let params = self.get_params();
|
||||||
|
|
||||||
self.text.iter().enumerate().for_each(|(index, text)| {
|
self.text.iter().enumerate().for_each(|(index, text)| {
|
||||||
let x = self.text_margin;
|
let x = self.text_margin;
|
||||||
let y = self.text_margin+20.*(index as f32 + 1.);
|
let y = self.text_margin + 20. * (index as f32 + 1.);
|
||||||
|
|
||||||
// let measurement = measure_text(text, None, params.font_size, params.font_scale);
|
// let measurement = measure_text(text, None, params.font_size, params.font_scale);
|
||||||
// draw_rectangle(x,y,measurement.width,-measurement.height, Color { r: 1., g: 1., b: 1., a: 0.25 });
|
// draw_rectangle(x,y,measurement.width,-measurement.height, Color { r: 1., g: 1., b: 1., a: 0.25 });
|
||||||
@@ -46,69 +72,384 @@ impl DebugWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Axis {
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Graph
|
||||||
|
/// Holds 1 contiguous line. Can be graphed on 1 or 2 axis.
|
||||||
|
struct Graph<'a> {
|
||||||
|
font: Option<&'a Font>,
|
||||||
|
points: [Point; TAIL_LEN],
|
||||||
|
head: usize,
|
||||||
|
axises: Axis,
|
||||||
|
/// What the tail treats as 0
|
||||||
|
head_tracker: f32,
|
||||||
|
/// The graph's local origin
|
||||||
|
x_origin: f32,
|
||||||
|
/// The graph's local origin
|
||||||
|
y_origin: f32,
|
||||||
|
/// How fast X scrolls when using a since axis tail
|
||||||
|
px_per_s: f32,
|
||||||
|
}
|
||||||
|
impl<'a> Graph<'a> {
|
||||||
|
fn recalculate_origin(&mut self) {
|
||||||
|
let (x_offset, y_offset) = match self.axises {
|
||||||
|
Axis::One => (0., screen_height() / 2.),
|
||||||
|
Axis::Two => (screen_width() / 2., screen_height() / 2.),
|
||||||
|
};
|
||||||
|
self.x_origin = x_offset;
|
||||||
|
self.y_origin = y_offset;
|
||||||
|
}
|
||||||
|
fn new(axises: Axis, font: Option<&'a Font>) -> Self {
|
||||||
|
let (x_offset, y_offset) = match axises {
|
||||||
|
Axis::One => (0., screen_height() / 2.),
|
||||||
|
Axis::Two => (screen_width() / 2., screen_height() / 2.),
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
font,
|
||||||
|
// start all the dots off screen
|
||||||
|
points: [Point::new(-1., -1., 0.); TAIL_LEN],
|
||||||
|
head: 0,
|
||||||
|
axises,
|
||||||
|
x_origin: x_offset,
|
||||||
|
y_origin: y_offset,
|
||||||
|
px_per_s: 800.,
|
||||||
|
head_tracker: 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn draw_time(&self) {
|
||||||
|
match self.axises {
|
||||||
|
Axis::Two => {}
|
||||||
|
Axis::One => {
|
||||||
|
let ms_per_px = self.px_per_s / 1000.;
|
||||||
|
// how many ms per segment
|
||||||
|
let segment_len_ms = 100.;
|
||||||
|
let px_offset = ms_per_px * segment_len_ms;
|
||||||
|
let segments = screen_width() / px_offset;
|
||||||
|
|
||||||
|
let mut params = TextParams::default();
|
||||||
|
params.font = self.font;
|
||||||
|
params.font_size = 20;
|
||||||
|
params.color = DARKGRAY;
|
||||||
|
|
||||||
|
let y2 = screen_height();
|
||||||
|
for i in 0..=segments as i32 {
|
||||||
|
let x = i as f32 * px_offset;
|
||||||
|
draw_line(x, 0., x, y2, 2., DARKGRAY);
|
||||||
|
|
||||||
|
draw_text_ex(
|
||||||
|
&format!("{}ms", segment_len_ms * i as f32),
|
||||||
|
x,
|
||||||
|
y2 / 2.,
|
||||||
|
params.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn draw_axises(&self) {
|
||||||
|
// Horzontal line
|
||||||
|
// (0, y_origin) -> (max, y_origin)
|
||||||
|
draw_line(
|
||||||
|
0.,
|
||||||
|
self.y_origin,
|
||||||
|
screen_width(),
|
||||||
|
self.y_origin,
|
||||||
|
1.,
|
||||||
|
DARKGRAY,
|
||||||
|
);
|
||||||
|
// Vertical line
|
||||||
|
// (x_origin, 0) -> (x_origin, max)
|
||||||
|
draw_line(
|
||||||
|
self.x_origin,
|
||||||
|
0.,
|
||||||
|
self.x_origin,
|
||||||
|
screen_height(),
|
||||||
|
1.,
|
||||||
|
DARKGRAY,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn place_next(&mut self, delta_time: f32, x: f32, y: f32) {
|
||||||
|
match self.axises {
|
||||||
|
Axis::One => {
|
||||||
|
// x will scroll while y gets displaced
|
||||||
|
if self.head_tracker >= screen_width() {
|
||||||
|
self.head_tracker = 0.;
|
||||||
|
} else {
|
||||||
|
self.head_tracker = self.head_tracker + (delta_time * self.px_per_s)
|
||||||
|
}
|
||||||
|
self.push(Point::new(self.head_tracker, self.y_origin - y, delta_time));
|
||||||
|
}
|
||||||
|
Axis::Two => {
|
||||||
|
// both x and y will get displaced
|
||||||
|
self.push(Point::new(self.x_origin + x, self.y_origin - y, delta_time))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn push(&mut self, dot: Point) {
|
||||||
|
if self.head >= self.points.len() - 1 {
|
||||||
|
self.head = 0
|
||||||
|
} else {
|
||||||
|
self.head += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
self.points[self.head] = dot;
|
||||||
|
}
|
||||||
|
fn draw(&self) {
|
||||||
|
self.points
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(index, point)| {
|
||||||
|
// dots fade
|
||||||
|
let virtual_index = if index > self.head {
|
||||||
|
index - self.head
|
||||||
|
} else {
|
||||||
|
index + (self.points.len() - self.head)
|
||||||
|
};
|
||||||
|
let faded = virtual_index as f32 / self.points.len() as f32;
|
||||||
|
let faded_inverse = 1. - faded;
|
||||||
|
let color = Color {
|
||||||
|
r: faded_inverse,
|
||||||
|
g: faded,
|
||||||
|
b: 0.2,
|
||||||
|
a: faded + 0.1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let prev = self.previous(index);
|
||||||
|
|
||||||
|
if point.x == 0. || point.y == 0. || prev.x == -1. || prev.y == -1. {
|
||||||
|
// Don't have lines that cross the whole screen while using 1D graph
|
||||||
|
// draw_circle(point.x, point.y,THICKNESS, color);
|
||||||
|
} else if self.head == index {
|
||||||
|
// Draw the head differently
|
||||||
|
draw_circle(point.x, point.y, THICKNESS * 2., color);
|
||||||
|
draw_line(point.x, point.y, prev.x, prev.y, THICKNESS, color);
|
||||||
|
} else if prev == self.points[self.head] {
|
||||||
|
// Prevent the tail from connecting to the head
|
||||||
|
draw_circle(point.x, point.y, THICKNESS, color);
|
||||||
|
} else {
|
||||||
|
draw_line(point.x, point.y, prev.x, prev.y, THICKNESS, color);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn previous(&self, index: usize) -> Point {
|
||||||
|
let prev = if index > 0 {
|
||||||
|
index - 1
|
||||||
|
} else {
|
||||||
|
self.points.len() - 1
|
||||||
|
};
|
||||||
|
self.points[prev]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_font() -> Option<Font> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let fonts_path = "C:\\Windows\\Fonts";
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let fonts_path = "/usr/share/fonts/";
|
||||||
|
|
||||||
|
if let Ok(dir) = read_dir(fonts_path) {
|
||||||
|
let selection = dir
|
||||||
|
.filter_map(|f| f.ok())
|
||||||
|
.map(|f| (f.file_name(), f.path()))
|
||||||
|
.map(|(a, b)| (a.into_string(), b))
|
||||||
|
.filter(|(a, _)| a.is_ok())
|
||||||
|
.map(|(a, b)| (a.unwrap(), b))
|
||||||
|
// Arial is a good windows default, Adwaita is a good Linux default
|
||||||
|
.filter(|(a, _)| a.contains("Arial") | a.contains("Adwaita"))
|
||||||
|
.map(|(_, b)| b)
|
||||||
|
.collect::<Vec<PathBuf>>();
|
||||||
|
if selection.len() > 0 {
|
||||||
|
if let Ok(dir) = read_dir(&selection[0]) {
|
||||||
|
let ttfs = dir
|
||||||
|
.filter_map(|f| f.ok())
|
||||||
|
.map(|f| (f.file_name(), f.path()))
|
||||||
|
.map(|(a, b)| (a.into_string(), b))
|
||||||
|
.filter(|(a, _)| a.is_ok())
|
||||||
|
.map(|(a, b)| (a.unwrap(), b))
|
||||||
|
.filter(|(a, _)| a.contains("Regular"))
|
||||||
|
.filter(|(a, _)| a.contains("Mono"))
|
||||||
|
.filter(|(a, _)| a.contains("ttf"))
|
||||||
|
.map(|(_, b)| b)
|
||||||
|
.collect::<Vec<PathBuf>>();
|
||||||
|
|
||||||
|
if ttfs.len() > 0 {
|
||||||
|
let selection = ttfs[0].to_str().expect("Bad path");
|
||||||
|
let ttf = load_ttf_font(selection)
|
||||||
|
.await
|
||||||
|
.expect("Cannot load ttf {selection}");
|
||||||
|
println!("Loaded {:?}", ttfs[0]);
|
||||||
|
return Some(ttf);
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"So sutable fonts found in the sub dir \"{:?}\"",
|
||||||
|
selection[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("No fonts found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
#[macroquad::main("Graph")]
|
#[macroquad::main("Graph")]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// Dot params
|
let font = get_font().await;
|
||||||
let y_offset = screen_height() / 2.0;
|
|
||||||
let mut x_offset = screen_width();
|
// Dot params
|
||||||
let mut trail: Vec<Dot> = Vec::new();
|
let mut graph = Graph::new(Axis::One, font.as_ref());
|
||||||
|
|
||||||
// Selection box
|
|
||||||
let mut inital_x_pos = 0.;
|
|
||||||
let mut inital_y_pos = 0.;
|
|
||||||
|
|
||||||
// Tooling
|
// Tooling
|
||||||
let mut show_debug = false;
|
let mut show_debug = false;
|
||||||
let mut px_per_s: f32 = 100.;
|
let mut plot_delta_time = 0.;
|
||||||
|
let mut pause = false;
|
||||||
|
|
||||||
|
// Serial
|
||||||
|
let (rx, _handle) = get_serial_port_or_demo();
|
||||||
loop {
|
loop {
|
||||||
|
let mut debug = DebugWindow::new(font.as_ref());
|
||||||
|
let params = debug.get_params();
|
||||||
|
let (mouse_x, mouse_y) = mouse_position();
|
||||||
|
let (_, my) = mouse_wheel();
|
||||||
|
graph.px_per_s += 10. * my;
|
||||||
|
|
||||||
clear_background(BLACK);
|
clear_background(BLACK);
|
||||||
|
|
||||||
let delta_time = get_frame_time();
|
graph.recalculate_origin();
|
||||||
|
graph.draw_axises();
|
||||||
|
graph.draw_time();
|
||||||
|
|
||||||
if x_offset >= screen_width() {
|
let frame_delta_time = get_frame_time();
|
||||||
// wrap once you've hit the end of the line
|
// keep track of the time since last plot
|
||||||
x_offset = 0.;
|
plot_delta_time += frame_delta_time;
|
||||||
trail.clear();
|
|
||||||
} else {
|
match rx.try_recv() {
|
||||||
x_offset = x_offset + (delta_time * px_per_s);
|
Ok(x) => {
|
||||||
|
if !pause {
|
||||||
|
graph.place_next(plot_delta_time, 0., x as f32);
|
||||||
|
plot_delta_time = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(x) => match x {
|
||||||
|
mpsc::TryRecvError::Empty => {}
|
||||||
|
mpsc::TryRecvError::Disconnected => {
|
||||||
|
eprintln!("Sender hung-up.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = 0.+x_offset;
|
graph.draw();
|
||||||
let y = 0.+y_offset;
|
|
||||||
|
|
||||||
let dot = Dot::new(x,y);
|
if is_key_pressed(KeyCode::F1) {
|
||||||
trail.push(dot);
|
pause = !pause;
|
||||||
trail.iter().for_each(|d| d.draw());
|
}
|
||||||
|
if is_key_pressed(KeyCode::F2) {
|
||||||
|
// Dump data to csv
|
||||||
|
if let Ok(mut file) = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.append(false)
|
||||||
|
.truncate(true)
|
||||||
|
.create(true)
|
||||||
|
.open("data.csv")
|
||||||
|
{
|
||||||
|
let mut x = 0.;
|
||||||
|
for p in &graph.points {
|
||||||
|
x += p.time_since_last;
|
||||||
|
let _ = file.write_all(format!("{x},{}\n", p.y - graph.y_origin).as_bytes());
|
||||||
|
}
|
||||||
|
let _ = file.flush();
|
||||||
|
|
||||||
if is_key_pressed(KeyCode::D) {
|
let now = Local::now();
|
||||||
|
let date_string = format!(
|
||||||
|
"{}-{}-{}-{}-{}-{}-{}",
|
||||||
|
now.year(),
|
||||||
|
now.month(),
|
||||||
|
now.day(),
|
||||||
|
now.hour(),
|
||||||
|
now.minute(),
|
||||||
|
now.second(),
|
||||||
|
now.timestamp_subsec_millis()
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Ok(out_file) = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.append(false)
|
||||||
|
.truncate(true)
|
||||||
|
.create(true)
|
||||||
|
.open(format!("dump-{date_string}.png"))
|
||||||
|
{
|
||||||
|
let _ = Command::new("gnuplot")
|
||||||
|
.stdin(file)
|
||||||
|
.arg("template.gnuplot")
|
||||||
|
.stdout(out_file)
|
||||||
|
.spawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_key_pressed(KeyCode::F3) {
|
||||||
show_debug = !show_debug;
|
show_debug = !show_debug;
|
||||||
}
|
}
|
||||||
if is_key_pressed(KeyCode::Up) {
|
|
||||||
px_per_s += 5.;
|
|
||||||
}
|
|
||||||
if is_key_pressed(KeyCode::Down) {
|
|
||||||
px_per_s -= 5.;
|
|
||||||
}
|
|
||||||
// selection box
|
|
||||||
if is_mouse_button_pressed(MouseButton::Left) {
|
|
||||||
(inital_x_pos, inital_y_pos) = mouse_position();
|
|
||||||
}
|
|
||||||
if is_mouse_button_down(MouseButton::Left) {
|
|
||||||
|
|
||||||
let (x, y) = mouse_position();
|
if !pause {
|
||||||
let width = x - inital_x_pos;
|
// Cursor information
|
||||||
let height = y - inital_y_pos;
|
let text = &format!("x{mouse_x}, y{}", -(mouse_y - graph.y_origin));
|
||||||
|
let size = measure_text(text, params.font, params.font_size, params.font_scale);
|
||||||
draw_rectangle(inital_x_pos, inital_y_pos, width, height, Color { r: 0.2, g: 0.1, b: 1., a: 0.3 });
|
draw_rectangle(
|
||||||
|
mouse_x,
|
||||||
|
mouse_y + (size.offset_y / 4.),
|
||||||
|
size.width,
|
||||||
|
-(size.height),
|
||||||
|
DARKGRAY,
|
||||||
|
);
|
||||||
|
draw_text_ex(text, mouse_x, mouse_y, params.clone());
|
||||||
}
|
}
|
||||||
// toggle debug box
|
|
||||||
|
if pause {
|
||||||
|
for i in graph.points {
|
||||||
|
let distance = 15.;
|
||||||
|
if (i.x - mouse_x).abs() < distance && (i.y - mouse_y).abs() < distance {
|
||||||
|
let size = 10.;
|
||||||
|
draw_rectangle(i.x - size / 2., i.y - size / 2., size, size, YELLOW);
|
||||||
|
|
||||||
|
let text = &format!("x{}, y{}", i.x, i.y);
|
||||||
|
let size = measure_text(text, params.font, params.font_size, params.font_scale);
|
||||||
|
draw_rectangle(
|
||||||
|
i.x,
|
||||||
|
i.y + (size.offset_y / 4.),
|
||||||
|
size.width,
|
||||||
|
-(size.height),
|
||||||
|
DARKGRAY,
|
||||||
|
);
|
||||||
|
draw_text_ex(text, i.x, i.y, params.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if show_debug {
|
if show_debug {
|
||||||
let mut debug = DebugWindow::new();
|
// Debug textbox
|
||||||
debug.add_line(format!("FPS {}, Latency {:.2}ms", get_fps(), delta_time * 1000.0));
|
debug.add_line(format!(
|
||||||
debug.add_line(format!("px/s {}", px_per_s));
|
"FPS {:04}, Frametime {:05.2}ms",
|
||||||
debug.add_line(format!("Dots {}", trail.len()));
|
get_fps(),
|
||||||
|
frame_delta_time * 1000.0
|
||||||
|
));
|
||||||
|
debug.add_line(format!(
|
||||||
|
"Tail Length {TAIL_LEN}, px/s {:.2}",
|
||||||
|
graph.px_per_s
|
||||||
|
));
|
||||||
debug.add_line(format!("Cursor Pos {:?}", mouse_position()));
|
debug.add_line(format!("Cursor Pos {:?}", mouse_position()));
|
||||||
|
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
if let Some(port_name) = unsafe { PORT.clone() } {
|
||||||
|
debug.add_line(format!("Serial Port {port_name}, Baud Rate {BAUD_RATE}"));
|
||||||
|
}
|
||||||
|
|
||||||
debug.draw();
|
debug.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,3 +457,58 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type INT = i32;
|
||||||
|
|
||||||
|
fn get_serial_port_or_demo() -> (Receiver<INT>, JoinHandle<()>) {
|
||||||
|
let (tx, rx): (Sender<INT>, Receiver<INT>) = mpsc::channel();
|
||||||
|
|
||||||
|
let handle = match serialport::available_ports() {
|
||||||
|
Ok(ok) => {
|
||||||
|
let x = ok
|
||||||
|
.iter()
|
||||||
|
.filter(|x| x.port_name.contains("ACM"))
|
||||||
|
.take(1)
|
||||||
|
.collect::<Vec<&serialport::SerialPortInfo>>();
|
||||||
|
if x.len() > 0 {
|
||||||
|
let port = x[0];
|
||||||
|
unsafe {
|
||||||
|
PORT = Some(port.port_name.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut x = serialport::new(port.port_name.clone(), BAUD_RATE)
|
||||||
|
.timeout(Duration::from_millis(10))
|
||||||
|
.open()
|
||||||
|
.expect("Failed to open port");
|
||||||
|
|
||||||
|
let handle = thread::spawn(move || loop {
|
||||||
|
let mut serial_buf: Vec<u8> = vec![0; 8];
|
||||||
|
if let Ok(x) = x.read(serial_buf.as_mut_slice()) {
|
||||||
|
for i in &serial_buf[..x - 1] {
|
||||||
|
// this data may need to be cleansed
|
||||||
|
let _err = tx.send(i.clone() as INT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
handle
|
||||||
|
} else {
|
||||||
|
dummy_port(tx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_err) => dummy_port(tx),
|
||||||
|
};
|
||||||
|
|
||||||
|
(rx, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dummy_port(tx: Sender<INT>) -> JoinHandle<()> {
|
||||||
|
let handle = thread::spawn(move || loop {
|
||||||
|
let a: u8 = std::random::random(..);
|
||||||
|
// center around y origin
|
||||||
|
let a: INT = a as INT - ((u8::MAX / 2) as INT);
|
||||||
|
|
||||||
|
let _err = tx.send(a);
|
||||||
|
thread::sleep(Duration::from_millis(10))
|
||||||
|
});
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
|||||||
17
template.gnuplot
Normal file
17
template.gnuplot
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
datafile = 'data.csv'
|
||||||
|
set datafile separator ','
|
||||||
|
|
||||||
|
set title 'Data Dump'
|
||||||
|
set key autotitle columnhead
|
||||||
|
set xlabel "Time (ms)"
|
||||||
|
set ylabel "Value"
|
||||||
|
|
||||||
|
set style line 1 linewidth 2 linecolor 1 pointtype 7 pointsize 1.5
|
||||||
|
|
||||||
|
set autoscale
|
||||||
|
set grid
|
||||||
|
|
||||||
|
set term png size 1280, 720
|
||||||
|
plot datafile using 1:2 with linespoints linestyle 1
|
||||||
|
# plot datafile using 1:2 with linespoints linestyle 1, datafile using 1:3, etc...
|
||||||
|
replot
|
||||||
Reference in New Issue
Block a user