initial commit, fw
commit
dfe4a17296
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
firmware.bin
|
|
@ -0,0 +1,754 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "az"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4"
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
|
||||
dependencies = [
|
||||
"rustc_version 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cross"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dtlogic",
|
||||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"longan-nano",
|
||||
"panic-halt",
|
||||
"riscv 0.7.0",
|
||||
"riscv-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtlogic"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"embedded-graphics",
|
||||
"embedded-graphics-simulator",
|
||||
"profont",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-dma"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c8c02e4347a0267ca60813c952017f4c5948c232474c6010a381a337f1bda4"
|
||||
dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "750082c65094fbcc4baf9ba31583ce9a8bb7f52cadfb96f6164b1bc7f922f32b"
|
||||
dependencies = [
|
||||
"az",
|
||||
"byteorder",
|
||||
"embedded-graphics-core",
|
||||
"float-cmp",
|
||||
"micromath",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics-core"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8b1239db5f3eeb7e33e35bd10bd014e7b2537b17e071f726a09351431337cfa"
|
||||
dependencies = [
|
||||
"az",
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics-simulator"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b889c087f6ddfba35047f9f0dfbd662aa05597110c937e5dbde641735d97fb1"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"embedded-graphics",
|
||||
"image",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gd32vf103-pac"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffd430737a49edbd1c0241b58cabe79a7ac7ebe208f67dc838c1c981eb60e83"
|
||||
dependencies = [
|
||||
"bare-metal 0.2.5",
|
||||
"riscv 0.6.0",
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gd32vf103xx-hal"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bdffb2f55a16c7916b5df9c02b1dab0dc1c8545237491821a7fd98c61378e4a"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"embedded-dma",
|
||||
"embedded-hal",
|
||||
"gd32vf103-pac",
|
||||
"nb 0.1.3",
|
||||
"riscv 0.6.0",
|
||||
"vcell",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.23.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"gif",
|
||||
"jpeg-decoder",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"png",
|
||||
"scoped_threadpool",
|
||||
"tiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||
dependencies = [
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
|
||||
|
||||
[[package]]
|
||||
name = "longan-nano"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccee9f0becbcd65041ab8c52f048f9783f1c7872122670e3253c4affc2520dd5"
|
||||
dependencies = [
|
||||
"embedded-hal",
|
||||
"gd32vf103xx-hal",
|
||||
"nb 1.0.0",
|
||||
"riscv 0.6.0",
|
||||
"st7735-lcd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "micromath"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc4010833aea396656c2f91ee704d51a6f1329ec2ab56ffd00bfd56f7481ea94"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic-halt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.16.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"deflate",
|
||||
"miniz_oxide 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profont"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eec6ccbe5cbbbdb18822a3e5b36a5e42bc9a3df0874ae0cfbf7abef285e9c2e0"
|
||||
dependencies = [
|
||||
"embedded-graphics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r0"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7a31eed1591dcbc95d92ad7161908e72f4677f8fabf2a32ca49b4237cbf211"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
dependencies = [
|
||||
"rand_core 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "riscv"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2f0b705d428e9d0f78e2bb73093887ee58a83c9688de3faedbb4c0631c4618e"
|
||||
dependencies = [
|
||||
"bare-metal 0.2.5",
|
||||
"bit_field",
|
||||
"riscv-target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba"
|
||||
dependencies = [
|
||||
"bare-metal 1.0.0",
|
||||
"bit_field",
|
||||
"riscv-target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-rt"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab9f28dc850356196a36078c51c9dc7b46014a29a8fde35d5f81c99e489d0e00"
|
||||
dependencies = [
|
||||
"r0",
|
||||
"riscv 0.7.0",
|
||||
"riscv-rt-macros",
|
||||
"riscv-target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-rt-macros"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3525f8341898dec060782087b7a15969e1cfe52818afacc47709265c19a23d53"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-target"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver 1.0.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7"
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "st7735-lcd"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5488ad3219621c70d6521c275cd82be7605c22791da9abb0135c7493846030f"
|
||||
dependencies = [
|
||||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"nb 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
|
||||
dependencies = [
|
||||
"jpeg-decoder",
|
||||
"miniz_oxide 0.4.4",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "vcell"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
|
|
@ -0,0 +1,5 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"cross",
|
||||
"dtlogic",
|
||||
]
|
|
@ -0,0 +1,3 @@
|
|||
cd cross
|
||||
cargo build --release
|
||||
llvm-objcopy -O binary ../target/riscv32imac-unknown-none-elf/release/cross ../firmware.bin
|
|
@ -0,0 +1,9 @@
|
|||
[target.riscv32imac-unknown-none-elf]
|
||||
runner = 'riscv64-unknown-elf-gdb -x openocd.gdb'
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tmemory-c8.x",
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "riscv32imac-unknown-none-elf"
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "cross"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[[bin]]
|
||||
name = "cross"
|
||||
bench = false
|
||||
doctest = false
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
longan-nano = { version = "0.3", features = [ "lcd" ] }
|
||||
riscv-rt = "0.8"
|
||||
panic-halt = "0.2"
|
||||
embedded-graphics = "0.7"
|
||||
dtlogic = { path = "../dtlogic" }
|
||||
embedded-hal = "0.2"
|
||||
riscv = "0"
|
|
@ -0,0 +1,152 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use panic_halt as _;
|
||||
|
||||
use longan_nano::hal::{
|
||||
pac,
|
||||
pac::ECLIC,
|
||||
prelude::*,
|
||||
gpio,
|
||||
timer::{Timer, Event},
|
||||
eclic::{EclicExt, LevelPriorityBits, TriggerType, Level, Priority},
|
||||
};
|
||||
use longan_nano::{lcd, lcd_pins};
|
||||
use riscv_rt::entry;
|
||||
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
||||
|
||||
use dtlogic::{
|
||||
ui,
|
||||
input,
|
||||
};
|
||||
|
||||
static mut G_R: Option<gpio::gpioc::PC13<gpio::Output<gpio::PushPull>>> = None;
|
||||
static mut G_TIMER1: Option<Timer<pac::TIMER1>> = None;
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// Configure clocks
|
||||
let mut rcu = dp
|
||||
.RCU
|
||||
.configure()
|
||||
.ext_hf_clock(8.mhz())
|
||||
.sysclk(108.mhz())
|
||||
.freeze();
|
||||
let mut afio = dp.AFIO.constrain(&mut rcu);
|
||||
|
||||
// Configure GPIO.
|
||||
let gpioa = dp.GPIOA.split(&mut rcu);
|
||||
let gpiob = dp.GPIOB.split(&mut rcu);
|
||||
let gpioc = dp.GPIOC.split(&mut rcu);
|
||||
|
||||
// Blink.
|
||||
let (mut r, mut g, mut b) = (
|
||||
gpioc.pc13.into_push_pull_output(),
|
||||
gpioa.pa1.into_push_pull_output(),
|
||||
gpioa.pa2.into_push_pull_output(),
|
||||
);
|
||||
r.set_high().unwrap();
|
||||
g.set_high().unwrap();
|
||||
b.set_high().unwrap();
|
||||
|
||||
// Set up LCD.
|
||||
let lcd_pins = lcd_pins!(gpioa, gpiob);
|
||||
let mut lcd = lcd::configure(dp.SPI0, lcd_pins, &mut afio, &mut rcu);
|
||||
|
||||
// Configure interrupts and timer.
|
||||
ECLIC::reset();
|
||||
ECLIC::set_threshold_level(Level::L0);
|
||||
ECLIC::set_level_priority_bits(LevelPriorityBits::L3P1);
|
||||
ECLIC::setup(pac::Interrupt::TIMER1, TriggerType::Level, Level::L0, Priority::P0);
|
||||
unsafe { ECLIC::unmask(pac::Interrupt::TIMER1) };
|
||||
|
||||
let mut timer = Timer::timer1(dp.TIMER1, 1.khz(), &mut rcu);
|
||||
timer.listen(Event::Update);
|
||||
|
||||
unsafe {
|
||||
G_R = Some(r);
|
||||
G_TIMER1 = Some(timer);
|
||||
}
|
||||
|
||||
unsafe { riscv::interrupt::enable() };
|
||||
|
||||
// Run application code..
|
||||
|
||||
let debug = false;
|
||||
|
||||
let buttons = [
|
||||
gpioa.pa3.into_pull_up_input().downgrade(),
|
||||
gpioa.pa4.into_pull_up_input().downgrade(),
|
||||
gpiob.pb10.into_pull_up_input().downgrade(),
|
||||
gpiob.pb11.into_pull_up_input().downgrade(),
|
||||
];
|
||||
|
||||
let mut state_ts = ui::TimeSelect::new();
|
||||
let mut state_running = ui::Running::new();
|
||||
let mut s: &mut dyn ui::State<_> = &mut state_ts;
|
||||
s.enter(ui::Transition::TimeSelect);
|
||||
|
||||
let mut ctx = ui::Context{
|
||||
buttons: input::Buttons::new(),
|
||||
ticks: 0,
|
||||
};
|
||||
|
||||
loop {
|
||||
let mut states = [false; 4];
|
||||
for (i, button) in buttons.iter().enumerate() {
|
||||
if let Ok(v) = button.is_low() {
|
||||
states[i] = v;
|
||||
}
|
||||
}
|
||||
if debug {
|
||||
if states[0] {
|
||||
g.set_low().unwrap();
|
||||
} else {
|
||||
g.set_high().unwrap();
|
||||
}
|
||||
if states[3] {
|
||||
b.set_low().unwrap();
|
||||
} else {
|
||||
b.set_high().unwrap();
|
||||
}
|
||||
}
|
||||
ctx.ticks = ticks();
|
||||
ctx.buttons.update(ctx.ticks, states);
|
||||
let next = s.tick(&ctx);
|
||||
s.draw(&mut lcd).unwrap();
|
||||
match next {
|
||||
ui::Transition::Keep => (),
|
||||
ui::Transition::Running { .. } => {
|
||||
s = &mut state_running;
|
||||
s.enter(next);
|
||||
},
|
||||
ui::Transition::TimeSelect => {
|
||||
s = &mut state_ts;
|
||||
s.enter(next);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut TICKS: u32 = 0;
|
||||
|
||||
fn ticks() -> u32 {
|
||||
let mut res: u32 = 0;
|
||||
riscv::interrupt::free(|_| {
|
||||
res = unsafe { TICKS };
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
fn TIMER1() {
|
||||
unsafe {
|
||||
if let Some(timer) = &mut G_TIMER1 {
|
||||
timer.clear_update_interrupt_flag();
|
||||
}
|
||||
TICKS += 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "dtlogic"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
profont = "0.5"
|
||||
embedded-graphics = "0.7"
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
embedded-graphics-simulator = { version = "0.3", default-features = false }
|
|
@ -0,0 +1,148 @@
|
|||
#[derive(Clone)]
|
||||
pub struct Buttons {
|
||||
state: [Option<u32>; 4],
|
||||
}
|
||||
|
||||
impl Buttons {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
state: [None; 4],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ts: u32, state: [bool; 4]) {
|
||||
for (&s, v) in state.iter().zip(self.state.iter_mut()) {
|
||||
if let Some(pressed) = v {
|
||||
// Ignore recent changes (ie., debounce).
|
||||
if ts - *pressed < 10 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !s {
|
||||
*v = None;
|
||||
}
|
||||
} else {
|
||||
if s {
|
||||
*v = Some(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn watch(&self) -> ButtonWatcher {
|
||||
let mut pending = [false; 4];
|
||||
for (i, v) in self.state.iter().enumerate() {
|
||||
if v.is_some() {
|
||||
pending[i] = true;
|
||||
}
|
||||
}
|
||||
ButtonWatcher {
|
||||
state: self.state.clone(),
|
||||
pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ButtonWatcher {
|
||||
state: [Option<u32>; 4],
|
||||
pending: [bool; 4],
|
||||
}
|
||||
|
||||
impl ButtonWatcher {
|
||||
pub fn update(&mut self, buttons: &Buttons) {
|
||||
for (i, (v, o)) in self.state.iter_mut().zip(buttons.state.iter()).enumerate() {
|
||||
|
||||
match (&v, o) {
|
||||
(Some(a), Some(b)) => {
|
||||
// Button continues to be pressed, or new press.
|
||||
if a == b {
|
||||
// Do nothing.
|
||||
} else {
|
||||
// New press, set pending and update.
|
||||
self.pending[i] = true;
|
||||
*v = Some(*b);
|
||||
}
|
||||
},
|
||||
(Some(_), None) => {
|
||||
// Button released.
|
||||
*v = None;
|
||||
},
|
||||
(None, Some(b)) => {
|
||||
// Button newly pressed.
|
||||
self.pending[i] = true;
|
||||
*v = Some(*b);
|
||||
},
|
||||
(None, None) => {
|
||||
// Do nothing.
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn events<'a>(&'a mut self) -> ButtonWatcherPending<'a> {
|
||||
ButtonWatcherPending {
|
||||
w: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ButtonWatcherPending<'a> {
|
||||
w: &'a mut ButtonWatcher,
|
||||
}
|
||||
|
||||
impl<'a> core::iter::Iterator for ButtonWatcherPending<'a> {
|
||||
type Item = usize;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
for (i, p) in self.w.pending.iter_mut().enumerate() {
|
||||
if *p {
|
||||
*p = false;
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::input::Buttons;
|
||||
#[test]
|
||||
fn buttons_debounce() {
|
||||
let mut b = Buttons::new();
|
||||
b.update(100, [false, false, false, false]);
|
||||
assert_eq!(b.state, [None, None, None, None]);
|
||||
b.update(110, [true, false, true, false]);
|
||||
assert_eq!(b.state, [Some(110), None, Some(110), None]);
|
||||
b.update(110, [false, true, true, false]);
|
||||
assert_eq!(b.state, [Some(110), Some(110), Some(110), None]);
|
||||
b.update(112, [false, false, true, true]);
|
||||
assert_eq!(b.state, [Some(110), Some(110), Some(110), Some(112)]);
|
||||
b.update(120, [false, false, false, false]);
|
||||
assert_eq!(b.state, [None, None, None, Some(112)]);
|
||||
b.update(122, [false, false, false, true]);
|
||||
assert_eq!(b.state, [None, None, None, Some(112)]);
|
||||
b.update(182, [false, false, false, true]);
|
||||
assert_eq!(b.state, [None, None, None, Some(112)]);
|
||||
}
|
||||
#[test]
|
||||
fn buttons_watcher() {
|
||||
let mut b = Buttons::new();
|
||||
let mut w = b.watch();
|
||||
assert_eq!(w.events().collect::<Vec<_>>(), vec![]);
|
||||
|
||||
b.update(100, [true, false, false, false]);
|
||||
w.update(&b);
|
||||
assert_eq!(w.events().collect::<Vec<_>>(), vec![0]);
|
||||
|
||||
b.update(120, [false, true, false, false]);
|
||||
w.update(&b);
|
||||
b.update(140, [false, false, true, false]);
|
||||
w.update(&b);
|
||||
assert_eq!(w.events().collect::<Vec<_>>(), vec![1, 2]);
|
||||
assert_eq!(w.events().collect::<Vec<_>>(), vec![]);
|
||||
b.update(150, [false, false, true, false]);
|
||||
w.update(&b);
|
||||
assert_eq!(w.events().collect::<Vec<_>>(), vec![]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#![feature(trait_alias)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
pub mod input;
|
||||
pub mod ui;
|
|
@ -0,0 +1,357 @@
|
|||
use core::fmt::Write;
|
||||
|
||||
use embedded_graphics::{
|
||||
pixelcolor::{RgbColor, PixelColor},
|
||||
draw_target::DrawTarget,
|
||||
prelude::{Point, Size, Primitive, Drawable},
|
||||
primitives::{Rectangle, PrimitiveStyle},
|
||||
mono_font::MonoTextStyleBuilder,
|
||||
text::{Text, Baseline},
|
||||
};
|
||||
|
||||
use profont::{
|
||||
PROFONT_7_POINT,
|
||||
PROFONT_18_POINT,
|
||||
PROFONT_24_POINT,
|
||||
};
|
||||
|
||||
use crate::input;
|
||||
|
||||
pub trait ColorSpace = RgbColor + PixelColor;
|
||||
|
||||
pub struct Context {
|
||||
pub buttons: input::Buttons,
|
||||
pub ticks: u32,
|
||||
}
|
||||
|
||||
pub enum Transition {
|
||||
Keep,
|
||||
Running {
|
||||
start: u32,
|
||||
msec: u32,
|
||||
},
|
||||
TimeSelect,
|
||||
}
|
||||
|
||||
pub trait State<D: DrawTarget<Color: ColorSpace>> {
|
||||
fn enter(&mut self, tr: Transition);
|
||||
fn tick(&mut self, ctx: &Context) -> Transition;
|
||||
fn draw(&mut self, target: &mut D) -> Result<(), <D as DrawTarget>::Error>;
|
||||
fn size(&mut self, target: &mut D) -> (u32, u32)
|
||||
{
|
||||
let bb = target.bounding_box();
|
||||
(bb.size.width, bb.size.height)
|
||||
}
|
||||
fn clear(&mut self, target: &mut D, color: D::Color) -> Result<(), <D as DrawTarget>::Error>
|
||||
{
|
||||
let (width, height) = self.size(target);
|
||||
Rectangle::new(Point::new(0, 0), Size::new(width, height))
|
||||
.into_styled(PrimitiveStyle::with_fill(color))
|
||||
.draw(target)
|
||||
}
|
||||
fn draw_softbuttons(&mut self, target: &mut D, labels: [&str; 4]) ->
|
||||
Result<(), <D as DrawTarget>::Error>
|
||||
{
|
||||
let (width, height) = self.size(target);
|
||||
let font = &PROFONT_18_POINT;
|
||||
let style = MonoTextStyleBuilder::new()
|
||||
.font(font)
|
||||
.text_color(D::Color::RED)
|
||||
.background_color(D::Color::BLACK)
|
||||
.build();
|
||||
|
||||
let chsize = font.character_size;
|
||||
let y = height - chsize.height;
|
||||
let xs = [
|
||||
0,
|
||||
width / 3 - chsize.width,
|
||||
2 * (width / 3) - chsize.width,
|
||||
width - chsize.width,
|
||||
];
|
||||
for (&x, v) in xs.iter().zip(labels.iter()) {
|
||||
Text::with_baseline(
|
||||
v,
|
||||
Point::new(x as i32, y as i32),
|
||||
style,
|
||||
Baseline::Top
|
||||
).draw(target)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TimeSelect {
|
||||
cleared: bool,
|
||||
bw: Option<input::ButtonWatcher>,
|
||||
msec: u32,
|
||||
ticks: u32,
|
||||
}
|
||||
|
||||
impl TimeSelect {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cleared: false,
|
||||
bw: None,
|
||||
msec: 1000,
|
||||
ticks: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DrawTarget<Color: ColorSpace>> State<D> for TimeSelect {
|
||||
fn enter(&mut self, _tr: Transition) {
|
||||
self.cleared = false;
|
||||
}
|
||||
|
||||
fn tick(&mut self, ctx: &Context) -> Transition {
|
||||
if let Some(bw) = &mut self.bw {
|
||||
bw.update(&ctx.buttons);
|
||||
} else {
|
||||
self.bw = Some(ctx.buttons.watch());
|
||||
}
|
||||
|
||||
for btn in self.bw.as_mut().unwrap().events() {
|
||||
match btn {
|
||||
0 => self.msec += 500,
|
||||
1 => {
|
||||
if self.msec > 0 {
|
||||
self.msec -= 500;
|
||||
}
|
||||
},
|
||||
3 => {
|
||||
return Transition::Running {
|
||||
start: ctx.ticks,
|
||||
msec: self.msec,
|
||||
};
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
if self.msec >= 3600000 {
|
||||
self.msec = 3600000;
|
||||
}
|
||||
self.ticks = ctx.ticks;
|
||||
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&mut self, target: &mut D) -> Result<(), <D as DrawTarget>::Error>
|
||||
{
|
||||
if !self.cleared {
|
||||
self.clear(target, D::Color::BLACK)?;
|
||||
self.cleared = true;
|
||||
}
|
||||
|
||||
let (width, height) = self.size(target);
|
||||
|
||||
self.draw_softbuttons(target, ["+", "-", " ", "S"])?;
|
||||
|
||||
{
|
||||
let style = MonoTextStyleBuilder::new()
|
||||
.font(&PROFONT_24_POINT)
|
||||
.text_color(D::Color::RED)
|
||||
.background_color(D::Color::BLACK)
|
||||
.build();
|
||||
let chsize = PROFONT_24_POINT.character_size;
|
||||
let chars = 8;
|
||||
|
||||
let twidth = chars * chsize.width;
|
||||
let theight = chsize.height;
|
||||
let x = (width - twidth) / 2;
|
||||
let y = (height - theight)/ 2;
|
||||
|
||||
let min = (self.msec / 1000) / 60;
|
||||
let sec = (self.msec / 1000) % 60;
|
||||
let csec = (self.msec % 1000) / 10;
|
||||
|
||||
let mut buf = arrayvec::ArrayString::<8>::new();
|
||||
write!(&mut buf, "{:02}:{:02}.{:02}", min, sec, csec).unwrap();
|
||||
Text::with_baseline(
|
||||
&buf,
|
||||
Point::new(x as i32, y as i32),
|
||||
style,
|
||||
Baseline::Top
|
||||
).draw(target)?;
|
||||
}
|
||||
|
||||
{
|
||||
let style = MonoTextStyleBuilder::new()
|
||||
.font(&PROFONT_7_POINT)
|
||||
.text_color(D::Color::RED)
|
||||
.background_color(D::Color::BLACK)
|
||||
.build();
|
||||
let mut buf = arrayvec::ArrayString::<16>::new();
|
||||
write!(&mut buf, "ticks: {:08}", self.ticks).unwrap();
|
||||
Text::with_baseline(
|
||||
&buf,
|
||||
Point::new(0, 0),
|
||||
style,
|
||||
Baseline::Top
|
||||
).draw(target)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Running {
|
||||
cleared: bool,
|
||||
msec: u32,
|
||||
msec_display: u32,
|
||||
start: u32,
|
||||
}
|
||||
|
||||
impl Running {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cleared: false,
|
||||
msec_display: 0,
|
||||
msec: 0,
|
||||
start: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DrawTarget<Color: ColorSpace>> State<D> for Running {
|
||||
fn enter(&mut self, tr: Transition) {
|
||||
self.cleared = false;
|
||||
if let Transition::Running { msec, start } = tr {
|
||||
self.msec = msec;
|
||||
self.start = start;
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&mut self, ctx: &Context) -> Transition {
|
||||
let elapsed = ctx.ticks - self.start;
|
||||
if elapsed > self.msec {
|
||||
return Transition::TimeSelect;
|
||||
}
|
||||
|
||||
self.msec_display = self.msec - elapsed;
|
||||
|
||||
Transition::Keep
|
||||
}
|
||||
|
||||
fn draw(&mut self, target: &mut D) -> Result<(), <D as DrawTarget>::Error>
|
||||
{
|
||||
if !self.cleared {
|
||||
self.clear(target, D::Color::RED)?;
|
||||
self.cleared = true;
|
||||
}
|
||||
|
||||
let (width, height) = self.size(target);
|
||||
|
||||
{
|
||||
let style = MonoTextStyleBuilder::new()
|
||||
.font(&PROFONT_24_POINT)
|
||||
.text_color(D::Color::BLACK)
|
||||
.background_color(D::Color::RED)
|
||||
.build();
|
||||
let chsize = PROFONT_24_POINT.character_size;
|
||||
let chars = 8;
|
||||
|
||||
let twidth = chars * chsize.width;
|
||||
let theight = chsize.height;
|
||||
let x = (width - twidth) / 2;
|
||||
let y = (height - theight)/ 2;
|
||||
|
||||
let min = (self.msec_display / 1000) / 60;
|
||||
let sec = (self.msec_display / 1000) % 60;
|
||||
let csec = (self.msec_display % 1000) / 10;
|
||||
|
||||
let mut buf = arrayvec::ArrayString::<8>::new();
|
||||
write!(&mut buf, "{:02}:{:02}.{:02}", min, sec, csec).unwrap();
|
||||
Text::with_baseline(
|
||||
&buf,
|
||||
Point::new(x as i32, y as i32),
|
||||
style,
|
||||
Baseline::Top
|
||||
).draw(target)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ui::{
|
||||
Context,
|
||||
TimeSelect,
|
||||
State,
|
||||
};
|
||||
use crate::input::Buttons;
|
||||
use embedded_graphics::{
|
||||
pixelcolor::Rgb565,
|
||||
prelude::*,
|
||||
};
|
||||
use embedded_graphics_simulator::{
|
||||
SimulatorDisplay,
|
||||
OutputSettingsBuilder,
|
||||
Window,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn time_select() {
|
||||
let mut display : SimulatorDisplay<Rgb565> = SimulatorDisplay::new(Size::new(160, 80));
|
||||
let output_settings = OutputSettingsBuilder::new()
|
||||
.build();
|
||||
let mut buttons = Buttons::new();
|
||||
let mut ts = TimeSelect::new();
|
||||
|
||||
{
|
||||
let s: &mut dyn State<SimulatorDisplay<Rgb565>> = &mut ts;
|
||||
s.enter();
|
||||
s.tick(&Context{
|
||||
buttons: buttons.clone(),
|
||||
ticks: 0,
|
||||
});
|
||||
s.draw(&mut display);
|
||||
}
|
||||
|
||||
|
||||
buttons.update(100, [true, false, false, false]);
|
||||
{
|
||||
let s: &mut dyn State<SimulatorDisplay<Rgb565>> = &mut ts;
|
||||
s.tick(&Context{
|
||||
buttons: buttons.clone(),
|
||||
ticks: 100,
|
||||
});
|
||||
}
|
||||
assert_eq!(ts.msec, 1500);
|
||||
|
||||
buttons.update(200, [false, false, false, false]);
|
||||
{
|
||||
let s: &mut dyn State<SimulatorDisplay<Rgb565>> = &mut ts;
|
||||
s.tick(&Context{
|
||||
buttons: buttons.clone(),
|
||||
ticks: 200,
|
||||
});
|
||||
}
|
||||
assert_eq!(ts.msec, 1500);
|
||||
|
||||
buttons.update(300, [true, false, false, false]);
|
||||
{
|
||||
let s: &mut dyn State<SimulatorDisplay<Rgb565>> = &mut ts;
|
||||
s.tick(&Context{
|
||||
buttons: buttons.clone(),
|
||||
ticks: 300,
|
||||
});
|
||||
}
|
||||
assert_eq!(ts.msec, 2000);
|
||||
|
||||
buttons.update(400, [false, true, false, false]);
|
||||
{
|
||||
let s: &mut dyn State<SimulatorDisplay<Rgb565>> = &mut ts;
|
||||
s.tick(&Context{
|
||||
buttons: buttons.clone(),
|
||||
ticks: 400,
|
||||
});
|
||||
}
|
||||
assert_eq!(ts.msec, 1500);
|
||||
|
||||
Window::new("TimeSelect", &output_settings).show_static(&display);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue