initial commit, fw

main
q3k 2022-02-13 13:35:32 +00:00
commit dfe4a17296
11 changed files with 1471 additions and 0 deletions

2
fw/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
firmware.bin

754
fw/Cargo.lock generated Normal file
View File

@ -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"

5
fw/Cargo.toml Normal file
View File

@ -0,0 +1,5 @@
[workspace]
members = [
"cross",
"dtlogic",
]

3
fw/build.sh Normal file
View File

@ -0,0 +1,3 @@
cd cross
cargo build --release
llvm-objcopy -O binary ../target/riscv32imac-unknown-none-elf/release/cross ../firmware.bin

9
fw/cross/.cargo/config Normal file
View File

@ -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"

21
fw/cross/Cargo.toml Normal file
View File

@ -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"

152
fw/cross/src/main.rs Normal file
View File

@ -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;
}
}

14
fw/dtlogic/Cargo.toml Normal file
View File

@ -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 }

148
fw/dtlogic/src/input.rs Normal file
View File

@ -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![]);
}
}

6
fw/dtlogic/src/lib.rs Normal file
View File

@ -0,0 +1,6 @@
#![feature(trait_alias)]
#![feature(associated_type_bounds)]
#![cfg_attr(not(test), no_std)]
pub mod input;
pub mod ui;

357
fw/dtlogic/src/ui.rs Normal file
View File

@ -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);
}
}