From 8a858dee5317ee46c4d37eb1c9565b65f04b7bbd Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 1 Dec 2025 00:23:08 -0600 Subject: [PATCH] Initial commit --- .cargo/config.toml | 14 + .gitignore | 22 + Cargo.lock | 1403 +++++++++++++++++++++++++++++++++++ Cargo.toml | 44 ++ build.rs | 56 ++ rust-toolchain.toml | 2 + src/Logisoso_24_ol.u8g2font | Bin 0 -> 4146 bytes src/bin/main.rs | 206 +++++ src/display.rs | 454 ++++++++++++ src/init.rs | 114 +++ src/lib.rs | 15 + src/setting_screen.rs | 501 +++++++++++++ src/state.rs | 387 ++++++++++ src/touch.rs | 406 ++++++++++ 14 files changed, 3624 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 rust-toolchain.toml create mode 100644 src/Logisoso_24_ol.u8g2font create mode 100644 src/bin/main.rs create mode 100644 src/display.rs create mode 100644 src/init.rs create mode 100644 src/lib.rs create mode 100644 src/setting_screen.rs create mode 100644 src/state.rs create mode 100644 src/touch.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..0f5c9fa --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,14 @@ +[target.xtensa-esp32-none-elf] +runner = "espflash flash --monitor --chip esp32" + +[env] + +[build] +rustflags = [ + "-C", "link-arg=-nostartfiles", +] + +target = "xtensa-esp32-none-elf" + +[unstable] +build-std = ["alloc", "core"] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2c6725 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# will have compiled files and executables +debug/ +target/ + +# Editor configuration +.vscode/ +.zed/ +.helix/ +.nvim.lua + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8d56265 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1403 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "allocator-api2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c583acf993cf4245c4acb0a2cc2ab1f9cc097de73411bb6d3647ff6af2b1013d" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitfield" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419" +dependencies = [ + "bitfield-macros", +] + +[[package]] +name = "bitfield-macros" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.111", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "delegate" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" +dependencies = [ + "embassy-futures", + "embassy-hal-internal", + "embassy-sync 0.7.2", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-futures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" + +[[package]] +name = "embassy-hal-internal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" +dependencies = [ + "num-traits", +] + +[[package]] +name = "embassy-sync" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async 0.6.1", + "futures-sink", + "futures-util", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-sync" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async 0.6.1", + "futures-core", + "futures-sink", + "heapless 0.8.0", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-graphics" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0649998afacf6d575d126d83e68b78c0ab0e00ca2ac7e9b3db11b4cbe8274ef0" +dependencies = [ + "az", + "byteorder", + "embedded-graphics-core", + "float-cmp", + "micromath", +] + +[[package]] +name = "embedded-graphics-core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba9ecd261f991856250d2207f6d8376946cd9f412a2165d3b75bc87a0bc7a044" +dependencies = [ + "az", + "byteorder", +] + +[[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 = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-bus" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513e0b3a8fb7d3013a8ae17a834283f170deaf7d0eeab0a7c1a36ad4dd356d22" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io 0.6.1", +] + +[[package]] +name = "embedded-io-async" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564b9f813c544241430e147d8bc454815ef9ac998878d30cc3055449f7fd4c0" +dependencies = [ + "embedded-io 0.7.1", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "enumset" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "esp-alloc" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "641e43d6a60244429117ef2fa7a47182120c7561336ea01f6fb08d634f46bae1" +dependencies = [ + "allocator-api2", + "cfg-if", + "document-features", + "enumset", + "esp-config", + "esp-sync", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "esp-backtrace" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3318413fb566c7227387f67736cf70cd74d80a11f2bb31c7b95a9eb48d079669" +dependencies = [ + "cfg-if", + "document-features", + "esp-config", + "esp-metadata-generated", + "esp-println", + "heapless 0.9.2", + "riscv", + "semihosting", + "xtensa-lx", +] + +[[package]] +name = "esp-bootloader-esp-idf" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a56964ab5479ac20c9cf76fa3b0d3f2233b20b5d8554e81ef5d65f63c20567" +dependencies = [ + "cfg-if", + "document-features", + "embedded-storage", + "esp-config", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-rom-sys", + "jiff", + "strum", +] + +[[package]] +name = "esp-config" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102871054f8dd98202177b9890cb4b71d0c6fe1f1413b7a379a8e0841fc2473c" +dependencies = [ + "document-features", + "esp-metadata-generated", + "serde", + "serde_yaml", + "somni-expr", +] + +[[package]] +name = "esp-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54786287c0a61ca0f78cb0c338a39427551d1be229103b4444591796c579e093" +dependencies = [ + "bitfield", + "bitflags", + "bytemuck", + "cfg-if", + "critical-section", + "delegate", + "digest", + "document-features", + "embassy-embedded-hal", + "embassy-futures", + "embassy-sync 0.7.2", + "embedded-can", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-io 0.6.1", + "embedded-io 0.7.1", + "embedded-io-async 0.6.1", + "embedded-io-async 0.7.0", + "enumset", + "esp-config", + "esp-hal-procmacros", + "esp-metadata-generated", + "esp-riscv-rt", + "esp-rom-sys", + "esp-sync", + "esp32", + "esp32c2", + "esp32c3", + "esp32c6", + "esp32h2", + "esp32s2", + "esp32s3", + "fugit", + "instability", + "nb 1.1.0", + "paste", + "portable-atomic", + "rand_core 0.6.4", + "rand_core 0.9.3", + "riscv", + "sha1", + "sha2", + "strum", + "ufmt-write", + "xtensa-lx", + "xtensa-lx-rt", +] + +[[package]] +name = "esp-hal-procmacros" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e025a7a7a0affdb4ff913b5c4494aef96ee03d085bf83c27453ae3a71d50da6" +dependencies = [ + "document-features", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.111", + "termcolor", +] + +[[package]] +name = "esp-metadata-generated" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a93e39c8ad8d390d248dc7b9f4b59a873f313bf535218b8e2351356972399e3" + +[[package]] +name = "esp-println" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a30e6c9fbcc01c348d46706fef8131c7775ab84c254a3cd65d0cd3f6414d592" +dependencies = [ + "document-features", + "esp-metadata-generated", + "esp-sync", + "log", + "portable-atomic", +] + +[[package]] +name = "esp-riscv-rt" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502744a5b1e7268d27fd2a4e56ad45efe42ead517d6c517a6961540de949b0ee" +dependencies = [ + "document-features", + "riscv", + "riscv-rt", +] + +[[package]] +name = "esp-rom-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd66cccc6dd2d13e9f33668a57717ab14a6d217180ec112e6be533de93e7ecbf" +dependencies = [ + "cfg-if", + "document-features", + "esp-metadata-generated", +] + +[[package]] +name = "esp-sync" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d44974639b4e88914f83fe60d2832c00276657d7d857628fdfc966cc7302e8a8" +dependencies = [ + "cfg-if", + "document-features", + "embassy-sync 0.6.2", + "embassy-sync 0.7.2", + "esp-metadata-generated", + "riscv", + "xtensa-lx", +] + +[[package]] +name = "esp32" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b76170a463d18f888a1ad258031901036fd827a9ef126733053ba5f8739fb0c8" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32c2" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e62cf8932966b8d445b6f1832977b468178f0a84effb2e9fda89f60c24d45aa3" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32c3" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356af3771d0d6536c735bf71136594f4d1cbb506abf6e0c51a6639e9bf4e7988" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32c6" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5e511df672d79cd63365c92045135e01ba952b6bddd25b660baff5e1110f6b" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32h2" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4a50bbd1380931e095e0973b9b12f782a9c481f2edf1f7c42e7eb4ff736d6d" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32s2" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98574d4c577fbe888fe3e6df7fc80d25a05624d9998f7d7de1500ae21fcca78f" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "esp32s3" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1810d8ee4845ef87542af981e38eb80ab531d0ef1061e1486014ab7af74c337a" +dependencies = [ + "critical-section", + "vcell", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fugit" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e639847d312d9a82d2e75b0edcc1e934efcc64e6cb7aa94f0b1fbec0bc231d6" +dependencies = [ + "gcd", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "instability" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6778b0196eefee7df739db78758e5cf9b37412268bfa5650bfeed028aed20d9c" +dependencies = [ + "darling 0.20.11", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "micromath" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" + +[[package]] +name = "mipidsi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba34dcbf61182ffa6992b5a4d9b566d5a99df127fd93f6d314213347329e92f" +dependencies = [ + "embedded-graphics-core", + "embedded-hal 1.0.0", + "heapless 0.8.0", + "nb 1.1.0", +] + +[[package]] +name = "mtgcount-rs-2" +version = "0.1.0" +dependencies = [ + "critical-section", + "embedded-graphics", + "embedded-hal-bus", + "esp-alloc", + "esp-backtrace", + "esp-bootloader-esp-idf", + "esp-hal", + "esp-println", + "micromath", + "mipidsi", + "u8g2-fonts", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" + +[[package]] +name = "riscv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05cfa3f7b30c84536a9025150d44d26b8e1cc20ddf436448d74cd9591eefb25" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d323d13972c1b104aa036bc692cd08b822c8bbf23d79a27c526095856499799" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "riscv-rt" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d07b9f3a0eff773fc4df11f44ada4fa302e529bff4b7fe7e6a4b98a65ce9174" +dependencies = [ + "riscv", + "riscv-pac", + "riscv-rt-macros", + "riscv-target-parser", +] + +[[package]] +name = "riscv-rt-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c3138fdd8d128b2d81829842a3e0ce771b3712f7b6318ed1476b0695e7d330" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "riscv-target-parser" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1376b15f3ff160e9b1e8ea564ce427f2f6fcf77528cc0a8bf405cb476f9cea7" + +[[package]] +name = "rlsf" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "svgbobdoc", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "semihosting" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5669d73a3503b5d34db3359c8c87d1b33ba68b2630c153e340d106c15a8626a7" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "somni-expr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed9b7648d5e8b2df6c5e49940c54bcdd2b4dd71eafc6e8f1c714eb4581b0f53" +dependencies = [ + "somni-parser", +] + +[[package]] +name = "somni-parser" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "u8g2-fonts" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825f57be1429fd60f335a4aade11e128a7ae4f89d75ca3a003cb8410a91093f7" +dependencies = [ + "embedded-graphics-core", +] + +[[package]] +name = "ufmt-write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + +[[package]] +name = "xtensa-lx" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e012d667b0aa6d2592ace8ef145a98bff3e76cca7a644f4181ecd7a916ed289b" +dependencies = [ + "critical-section", +] + +[[package]] +name = "xtensa-lx-rt" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8709f037fb123fe7ff146d2bce86f9dc0dfc53045c016bfd9d703317b6502845" +dependencies = [ + "document-features", + "xtensa-lx", + "xtensa-lx-rt-proc-macros", +] + +[[package]] +name = "xtensa-lx-rt-proc-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96fb42cd29c42f8744c74276e9f5bee7b06685bbe5b88df891516d72cb320450" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..25233f0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,44 @@ +[package] +edition = "2024" +name = "mtgcount-rs-2" +rust-version = "1.88" +version = "0.1.0" + +[[bin]] +name = "mtgcount-rs-2" +path = "./src/bin/main.rs" + +[dependencies] +esp-hal = { version = "1.0.0", features = ["esp32", "unstable"] } + + +esp-bootloader-esp-idf = { version = "0.4.0", features = ["esp32"] } + +critical-section = "1.2.0" +esp-alloc = "0.9.0" +esp-backtrace = { version = "0.18.1", features = [ + "esp32", + "panic-handler", + "println", +] } +esp-println = { version = "0.16.1", features = ["esp32"] } +embedded-hal-bus = "0.3.0" +mipidsi = "0.9.0" +embedded-graphics = "0.8.1" +u8g2-fonts = "0.7.2" +micromath = "2.1.0" + + +[profile.dev] +# Rust debug is too slow. +# For debug builds always builds with some optimization +opt-level = "s" + +[profile.release] +codegen-units = 1 # LLVM can perform better optimizations using a single thread +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 's' +overflow-checks = false diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..ecd01e7 --- /dev/null +++ b/build.rs @@ -0,0 +1,56 @@ +fn main() { + linker_be_nice(); + // make sure linkall.x is the last linker script (otherwise might cause problems with flip-link) + println!("cargo:rustc-link-arg=-Tlinkall.x"); +} + +fn linker_be_nice() { + let args: Vec = std::env::args().collect(); + if args.len() > 1 { + let kind = &args[1]; + let what = &args[2]; + + match kind.as_str() { + "undefined-symbol" => match what.as_str() { + "_defmt_timestamp" => { + eprintln!(); + eprintln!( + "💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`" + ); + eprintln!(); + } + "_stack_start" => { + eprintln!(); + eprintln!("💡 Is the linker script `linkall.x` missing?"); + eprintln!(); + } + "esp_rtos_initialized" | "esp_rtos_yield_task" | "esp_rtos_task_create" => { + eprintln!(); + eprintln!( + "💡 `esp-radio` has no scheduler enabled. Make sure you have initialized `esp-rtos` or provided an external scheduler." + ); + eprintln!(); + } + "embedded_test_linker_file_not_added_to_rustflags" => { + eprintln!(); + eprintln!( + "💡 `embedded-test` not found - make sure `embedded-test.x` is added as a linker script for tests" + ); + eprintln!(); + } + _ => (), + }, + // we don't have anything helpful for "missing-lib" yet + _ => { + std::process::exit(1); + } + } + + std::process::exit(0); + } + + println!( + "cargo:rustc-link-arg=-Wl,--error-handling-script={}", + std::env::current_exe().unwrap().display() + ); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..a2f5ab5 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/src/Logisoso_24_ol.u8g2font b/src/Logisoso_24_ol.u8g2font new file mode 100644 index 0000000000000000000000000000000000000000..afcf466fa11705754ace4defb755407c1e5914e2 GIT binary patch literal 4146 zcmbtXdr(tn7QYb818B&-0nG&pxkZ z<%aCNAvn1S+9XW7Bp?H}V+-y>cXxJ*A`>un)!H5G*qPR{j&=IS&g{~t>S0!`LYt|8}u6)#M6sDljIfgp${ee;-r)(C6>i| zys~>)6$ntdN^BG(RL&}QmR>?4nX69!`*l3a%YE$L*D($|%P;}}E8bC86aD>Gm zmFnw{#lzG0^@<&0oc`#EEiJ469{BT6_!E8h^h846_QjkADp_0JDmnZCHNay<3@gg= z2C(qNba#+)2dQ9IX+wLvuiZyqDik(D_&P8YA0OnQNFXYTiDs-b6WXV@NtLT}aVaj) z3A6%(K&t``gCM;$lWO0%s>d&c)G~oxf@2XBQ1r9PPv4DVF)Sv5%2xAtOT^sM>Z)(I zI?WcdWtfCCsOz!}*JChCQw$Y~Q8b0HYCQ(66>Bad@0>IVisOlO>E$A7wxXNILhFRC z_FPY~@ByK{y|SB^R#BAIDw#U4pL$^#FZ7^F6gaSGkQb&zG2Q(94Y_CTscZ71LWmIK zyCv^z78lWpujh-k#Y=|0e}n&(Q1F#7DFmXN*Co1Q;0VtfPi?R?0B(Q!#oCQ0*R%+T zT!Bi^VuGp)!Rz5^{i*40cQ8v-`c}f9`1;!Cf{x(t(yB4AvS-u473=JqiHUgHste)E zbBCRe2?)+_%_gWu2?iWaY53OK9EaE}R@3;@cQ+3WhSnEw+t1hCaFH(m7jyE{(|S*k z$`+sp(>9cV**ER`#r@5NiNeXk#=a)W+uz)>wN|xc&>IKjEqm+sRT_zt7ZbO}Y|J`+ znds)dY{^P{F#F5xTr&>5{gCu}2l9tXEFU+vlJ>U5)Li<**;&nqr})z8`(JH(1Ocx- z8^#FDNAAuOVWfw*>3*OqK2C)w2Jwy_pYGnjf9HYh(ti}41K6vx{i=1{Z>Z0CrzmRV zw-H&kYyc%Ur7bi_sxTm=0Cx2-n4gJ8qnmnA|qEZPGj`Ip-EmPmYMZEMTTt zs?gQv!Wy^?S^t83RsF+Ym3MTbs9tn|mPb$+4G+k|^8R?}PLlTz$V#+2BOFD#wDoo~ zWV9}*@F7rOmJUV2vT8k{y+FEQ&@7;l_faYl0Pdl?O;yBkXL!gOVdh54KllAN@6431&-gkHe2G;sSWfFBkI z+}S`2I-c3%=pz3U`!cQBrjILD6?{KGKLy!p!IB>V0NkBqgWQ%ST0_+k)}?JF*F!(D zaJoeLC0N)$5Ei0Lh#v5VP*xTV8MV9IS7WD!PPH&5W+$GvCQqu&m8v+QQzBA07m;F0 z7yuy{pMn}|xOIL|fkpLr+er8p*B28WYY7)lhT zt4{JLsjx4jwQ0?^|67xQB8je+#(P#pVJDsAG|Vu55wk!nEn*pZT7jQS`lt0luvRjz zm->eO?fGv3?Sn~COWHICGy2g_g-;iylgwl)PqVSk7Y`MsG?dwpuQjdUvd5k*=b9;rd(sw9EzP72pI`Nq19r94kKWq3f3E7t&MbCoXy?7r~szbbU7EMlWqgq z7gu?+GNqY42$JQ^^7g<%W~uC9dqm|KJ5uS*o8!6anCs%c>GnCtvM+V>jo6b{T$u5= zxYRB=NaZ;HIscrv=m{Apl>C`PeZju9W!qYg4LxB!8Q52n_T!x7D1rIg`36A_|H=D~ z&K4FOjrFrkH0>wCrn($YvE-@D;p+vSsL8!M$=(N)@78LF_PsU6&+LdA~mz5?-KZQN>*{!}8p|v;5|!Y*T(}8kfq&oeF!G znKY^{op-xE!kO$|G|jmI>~~C8hSi4Sp-{M-93QcwQnMW{;7D)Jm7*)qcK*{3Z8@7g zOtBM5-EL*Aq$XTd-D@BoC0L@S3yGc9)^Me?=F}i~E>J?9$$Y;gPv4toZws}-^j+G9 zvlZQeke{QO)bB#?b}2g=6^8xkE`8Re>|c+EKH%sTf2y(2U0KR{WMNtsMyG2(JRpa_Nfjap2rgAFhN>k&eyAPfZILXI%7SDKlf*~j=q0a(-mgPTgKOzn|c&Tj3F zd^Zn1{o|v;sD$^-lW)yb{G37o!eZ?CI_9MjTCU-o$`ykU2ebcO4Dz3S7~lciukHoD zcR2aE^^0Kof%3F0@jVZsC;J}vToN*b8DJ(whoHT{+Z@RL%Lu4hT!LU%?bGzkyx&bl z)K-&LtJA_Y9mI;X6M8|@JM+i4*H-UC0`>J;1mr)r_?lx5khc+J+7UmzqYNummK@;i z*V#^Q?L8VANs%0_@7CoJ&3BMNpG#sLSiPQq;34h|?zO5ckLMS;Bj9c*pokbrMVEn8 zI1J>1RFFo}i6k$@A{)3C1vL-Y%D0itdmEsi?%+U`uk1GhJf4|MsJvDCgrOHe87-SLYp3g9_!dB)ClyKDVzizd!wD4i5*Bo{)b4lqMM? zV^Wv=U2c-RG#Sre;zsZ&(IfK+R8)zU|$Dy(md`T<*KLJYl9$~gkmb5KpX zCLNRRQ|`&Glmxx2F|nJgAU|6}e!jKcZ1cUlo1%SFvY)ljJoN tyyp{&@zK}t8gsR={+F)e3zE%D+Uq&JaVg&$qyoIis1O35jQM#8`Zw`jA#VTx literal 0 HcmV?d00001 diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 0000000..1f8ae90 --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,206 @@ +#![no_std] +#![no_main] +#![deny( + clippy::mem_forget, + reason = "mem::forget is generally not safe to do with esp_hal types, especially those \ + holding buffers for the duration of a data transfer." +)] + +use embedded_graphics::framebuffer::{Framebuffer, buffer_size}; +use embedded_graphics::pixelcolor::raw::LittleEndian; +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::draw_target::DrawTarget; +use embedded_graphics::image::ImageDrawable; + +use esp_backtrace as _; + +use esp_hal::clock::CpuClock; +use esp_hal::gpio::{InputConfig, OutputConfig}; +use esp_hal::main; +use esp_hal::rtc_cntl::Rtc; +use esp_hal::rtc_cntl::sleep::{GpioWakeupSource, RtcSleepConfig}; + +use esp_println::println; +use mtgcount_rs_2::{self, TP_GESTURE, TP_X, TP_Y}; + +extern crate alloc; + +// This creates a default app-descriptor required by the esp-idf bootloader. +// For more information see: +esp_bootloader_esp_idf::esp_app_desc!(); + +#[main] +fn main() -> ! { + // generator version: 1.0.1 + + let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); + let peripherals = esp_hal::init(config); + + let pins = mtgcount_rs_2::init::UsedPins::init(peripherals); + + let mut buffer = [0_u8;256]; + + esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 16000); + + let mut iic = pins.init_iic(); + let mut display = pins.init_display(&mut buffer); + let mut framebuf: Framebuffer(240, 240)}> = Framebuffer::new(); + + println!("Begin backlight setup"); + println!("Start Low Power backlight config"); + let low_power = unsafe {esp_hal::peripherals::LPWR::steal()}; + low_power.register_block().clk_conf().modify(|_,w| w.ck8m_force_pd().clear_bit()); + low_power.register_block().clk_conf().modify(|_,w| w.ck8m_force_pu().set_bit()); + low_power.register_block().clk_conf().modify(|_,w| w.enb_ck8m().clear_bit()); + low_power.register_block().clk_conf().modify(|_,w| w.dig_clk8m_en().set_bit()); + + println!("Init Backlight peripherals"); + let (led, bl, rtcio) = pins.init_backlight(); + + let mux = unsafe{esp_hal::peripherals::IO_MUX::steal()}; + mux.register_block().gpio32().modify(|_,w| w.mcu_oe().set_bit()); + rtcio.register_block().enable().modify(|_,w| unsafe{w.enable().bits(0x80_00_00)}); + rtcio.register_block().xtal_32k_pad().modify(|_,w| w.x32n_hold().clear_bit()); + rtcio.register_block().xtal_32k_pad().modify(|_,w| unsafe{w.x32n_fun_sel().bits(0)}); + rtcio.register_block().xtal_32k_pad().modify(|_,w| w.x32n_slp_oe().set_bit()); + + let _ledc = esp_hal::ledc::Ledc::new(led); + + println!("Set apb_clk_sel"); + let test = unsafe {esp_hal::peripherals::LEDC::steal()}; + test.register_block().conf().write(|w| w.apb_clk_sel().clear_bit()); + test.register_block().lstimer(0).conf().modify(|_,w| w.para_up().set_bit()); + + let precision = 1 << 8u64; + let divisor = ((8_000_000u64) << 8) / 1_000 / precision; + println!("Set up lstimer0"); + println!("Lstimer divisor is:{}", divisor); + + test.register_block().lstimer(0).conf().modify(|_,w| unsafe { + w.tick_sel().bit(true); + w.rst().clear_bit(); + w.pause().clear_bit(); + w.div_num().bits(divisor as u32); + w.duty_res().bits(8) + }); + test.register_block().lstimer(0).conf().modify(|_,w| w.para_up().set_bit()); + + let mut duty_percent = 100; + let duty_range = 2u32.pow(8); + let mut duty_value = (duty_range * duty_percent) / 100; + println!("Setup channel0"); + + test.register_block().lsch(0).duty().write(|w| unsafe { + w.duty().bits(duty_value<<4) + }); + test.register_block().lsch(0).conf1().write(|w| unsafe { + w.duty_start().set_bit(); + w.duty_inc().set_bit(); + w.duty_num().bits(0x1); + w.duty_cycle().bits(0x1); + w.duty_scale().bits(0x0) + }); + test.register_block().lsch(0).conf0().modify(|_,w| w.para_up().set_bit()); + + println!("Configure output signal"); + let newbl: esp_hal::gpio::interconnect::OutputSignal = bl.into(); + println!("line1"); + newbl.apply_output_config(&OutputConfig::default().with_drive_mode(esp_hal::gpio::DriveMode::PushPull)); + println!("line2"); + newbl.set_output_enable(true); + println!("Completed output signal config"); + + test.register_block().lsch(0).hpoint().write(|w| unsafe { + w.hpoint().bits(0x0) + }); + println!("Completed hpoint set"); + + test.register_block().lsch(0).conf0().modify(|_,w| unsafe { + w.sig_out_en().set_bit().timer_sel().bits(0) + }); + println!("Completed signal output enable"); + test.register_block().lsch(0).conf1().write(|w| unsafe { + w.duty_start().set_bit(); + w.duty_inc().set_bit(); + w.duty_num().bits(0x1); + w.duty_cycle().bits(0x1); + w.duty_scale().bits(0x0) + }); + test.register_block().lsch(0).conf0().modify(|_,w| w.para_up().set_bit()); + println!("Completed channel0 reupdate"); + + let signal = esp_hal::gpio::OutputSignal::LEDC_LS_SIG0; + signal.connect_to(&newbl); + println!("End Backlight setup"); + //end bl + + let mut read_buffer = [0_u8;1]; + + esp_alloc::heap_allocator!(size: 16 * 1024); + + let pinconf = InputConfig::default(); + let irq = pins.irq(); + let _wake_pin = esp_hal::gpio::Input::new(irq, pinconf).wakeup_enable(true,esp_hal::gpio::WakeEvent::LowLevel).unwrap(); + + let waker = GpioWakeupSource::new(); + println!("Start Sleep Config setup"); + let mut rtc_control = Rtc::new(low_power); + println!("line1"); + let mut rtc_config: RtcSleepConfig = RtcSleepConfig::default(); + println!("line2"); + rtc_config.set_int_8m_pd_en(false); + println!("Finish Sleep Config setup"); + + //let loop_delay = esp_hal::delay::Delay::new(); + + let mut gesture; + let mut x; + let mut y; + + println!("Systemstate init"); + let mut state = mtgcount_rs_2::state::SystemState::new(); + println!("screen: {:?}", state.screen); + + framebuf.clear(state.settings.color_scheme.get_color(&mtgcount_rs_2::display::ColorType::Background)).unwrap(); + display.clear(state.settings.color_scheme.get_color(&mtgcount_rs_2::display::ColorType::Background)).unwrap(); + mtgcount_rs_2::display::draw_screen(&state, &mut framebuf); + framebuf.as_image().draw(&mut display).unwrap(); + + loop { + //println!("Enterd Loop"); + iic.write_read(0x15, &[TP_GESTURE], &mut read_buffer).expect("Failed to do iic"); + gesture = read_buffer[0]; + iic.write_read(0x15, &[TP_X], &mut read_buffer).expect("Failed to do iic"); + x = read_buffer[0]; + iic.write_read(0x15, &[TP_Y], &mut read_buffer).expect("Failed to do iic"); + y = read_buffer[0]; + + mtgcount_rs_2::touch::get_touch_action(x as f32, y as f32, gesture, &mut state); + + duty_percent = state.settings.brightness as u32; + duty_value = (duty_range * duty_percent) / 100; + + //println!("Duty Percent: {}%", duty_percent); + + test.register_block().lsch(0).duty().write(|w| unsafe {w.duty().bits(duty_value<<4)}); + + test.register_block().lsch(0).conf1().write(|w| unsafe { + w.duty_start().set_bit(); + w.duty_inc().set_bit(); + w.duty_num().bits(0x1); + w.duty_cycle().bits(0x1); + w.duty_scale().bits(0x0) + }); + + test.register_block().lsch(0).conf0().modify(|_,w| w.para_up().set_bit()); + + mtgcount_rs_2::display::draw_screen(&state, &mut framebuf); + framebuf.as_image().draw(&mut display).unwrap(); + + framebuf.clear(state.settings.color_scheme.get_color(&mtgcount_rs_2::display::ColorType::Background)).unwrap(); + + rtc_control.sleep(&rtc_config,&[&waker]); + } + + // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0/examples/src/bin +} diff --git a/src/display.rs b/src/display.rs new file mode 100644 index 0000000..784340c --- /dev/null +++ b/src/display.rs @@ -0,0 +1,454 @@ +use embedded_graphics::prelude::{Angle, DrawTarget, Point, Primitive, RgbColor}; +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::Drawable; + +use u8g2_fonts::Font; +use u8g2_fonts::{fonts::{u8g2_font_7x13_tr, u8g2_font_9x15B_tr, u8g2_font_logisoso24_tr, u8g2_font_logisoso42_tr, u8g2_font_open_iconic_all_2x_t, u8g2_font_open_iconic_check_4x_t}, FontRenderer}; + +use micromath::F32Ext; + +extern crate alloc; +use alloc::{vec::Vec, string::ToString}; +use embedded_graphics::primitives::PrimitiveStyle; + +use crate::state::{MainScreenItem, Screen, SystemState}; +use crate::setting_screen::{setting_screen, setting_scroll}; + +pub const LARGE_FONT:FontRenderer = FontRenderer::new::(); +pub const MED_PLUS_FONT:FontRenderer = FontRenderer::new::(); +pub const MED_FONT:FontRenderer = FontRenderer::new::(); +pub const SMALL_FONT:FontRenderer = FontRenderer::new::(); +pub const ICONS:FontRenderer = FontRenderer::new::(); +pub const CHECK:FontRenderer = FontRenderer::new::(); +pub const TESTFONT:FontRenderer = FontRenderer::new::(); + +const LIGHTCREAM: Rgb565 = Rgb565::new(31, 62, 26); +const LIGHTBLUE: Rgb565 = Rgb565::new(21, 55, 30); +const DARKBLUE: Rgb565 = Rgb565::new(1, 27, 22); +const LIGHTGREY: Rgb565 = Rgb565::new(25, 48, 23); +const DARKGREY: Rgb565 = Rgb565::new(8, 16, 8); +const LIGHTRED: Rgb565 = Rgb565::new(30, 42, 17); +const LIGHTGREEN: Rgb565 = Rgb565::new(19,52,21); + + +const ALMOSTBLACK: Rgb565 = Rgb565::new(3, 6, 3); + + + + +const CENTER: Point = Point::new(120, 120); + +#[derive(Debug,Clone, Copy)] +pub enum ColorType { + Primary, + Secondary, + Tertiary, + Background +} + +#[derive(Debug,Clone, Copy)] +pub enum ColorScheme { + Light, + Dark, + White, + Blue, + Black, + Red, + Green, + Azorius, + Dimir, +} + +impl ColorScheme { + pub fn get_color(&self, color_type: &ColorType) -> Rgb565 { + match self { + Self::Light => { + match color_type { + ColorType::Primary => Rgb565::BLACK, + ColorType::Secondary => Rgb565::BLACK, + ColorType::Tertiary => Rgb565::BLACK, + ColorType::Background => Rgb565::WHITE, + } + }, + Self::Dark => { + match color_type { + ColorType::Primary => Rgb565::WHITE, + ColorType::Secondary => ALMOSTBLACK, + ColorType::Tertiary => Rgb565::WHITE, + ColorType::Background => Rgb565::BLACK, + } + }, + Self::White => { + match color_type { + ColorType::Primary => Rgb565::BLACK, + ColorType::Secondary => Rgb565::BLACK, + ColorType::Tertiary => Rgb565::BLACK, + ColorType::Background => LIGHTCREAM, + } + }, + Self::Blue => { + match color_type { + ColorType::Primary => Rgb565::BLACK, + ColorType::Secondary => DARKBLUE, + ColorType::Tertiary => Rgb565::BLACK, + ColorType::Background => LIGHTBLUE + } + }, + Self::Black => { + match color_type { + ColorType::Primary => Rgb565::BLACK, + ColorType::Secondary => Rgb565::BLACK, + ColorType::Tertiary => Rgb565::BLACK, + ColorType::Background => LIGHTGREY, + } + }, + Self::Red => { + match color_type { + ColorType::Primary => Rgb565::BLACK, + ColorType::Secondary => Rgb565::BLACK, + ColorType::Tertiary => Rgb565::BLACK, + ColorType::Background => LIGHTRED, + } + }, + Self::Green => { + match color_type { + ColorType::Primary => Rgb565::BLACK, + ColorType::Secondary => Rgb565::BLACK, + ColorType::Tertiary => Rgb565::BLACK, + ColorType::Background => LIGHTGREEN, + } + }, + Self::Azorius => { + match color_type { + ColorType::Primary => DARKBLUE, + ColorType::Secondary => DARKBLUE, + ColorType::Tertiary => DARKBLUE, + ColorType::Background => LIGHTCREAM, + } + }, + Self::Dimir => { + match color_type { + ColorType::Primary => DARKGREY, + ColorType::Secondary => DARKGREY, + ColorType::Tertiary => DARKGREY, + ColorType::Background => LIGHTBLUE, + } + }, + } + } + + pub(crate) fn as_str(&self) -> &'static str { + match self { + ColorScheme::Light => "Light", + ColorScheme::Dark => "Dark", + ColorScheme::White => "White", + ColorScheme::Blue => "Blue", + ColorScheme::Black => "Black", + ColorScheme::Red => "Red", + ColorScheme::Green => "Green", + ColorScheme::Azorius => "Azorius", + ColorScheme::Dimir => "Dmir", + } + } + + pub fn inc(self) -> Self { + let mut tmp:u8 = self.into(); + tmp += 1; + if tmp > 8 { + tmp = 0 + } + Self::from(tmp) + } + + pub fn dec(self) -> Self { + let tmp:u8 = self.into(); + let tmp = tmp.checked_sub(1); + let tmp = match tmp { + Some(u) => u, + None => 8, + }; + Self::from(tmp) + } +} + +pub const COLORSCHEMES: usize = 9; + +impl From for ColorScheme { + + fn from(value: u8) -> Self { + match value { + 1 => Self::Dark, + 2 => Self::White, + 3 => Self::Blue, + 4 => Self::Black, + 5 => Self::Red, + 6 => Self::Green, + 7 => Self::Azorius, + 8 => Self::Dimir, + _ => Self::Light, + } + } +} + +impl Into for ColorScheme { + fn into(self) -> u8 { + match self { + ColorScheme::Light => 0, + ColorScheme::Dark => 1, + ColorScheme::White => 2, + ColorScheme::Blue => 3, + ColorScheme::Black => 4, + ColorScheme::Red => 5, + ColorScheme::Green => 6, + ColorScheme::Azorius => 7, + ColorScheme::Dimir => 8, + } + } +} + +pub fn draw_screen>(ctx: &SystemState, target: &mut A) -> () { + + let primary = ctx.settings.color_scheme.get_color(&ColorType::Primary); + let background = ctx.settings.color_scheme.get_color(&ColorType::Background); + + _ = target.clear(background); + + match &ctx.screen { + Screen::Main(selection) => { + + let style = PrimitiveStyle::with_stroke(ctx.settings.color_scheme.get_color(&ColorType::Secondary), 3); + + let bottom_count = + ctx.settings.show_cmd_tax as u8 + + ctx.settings.show_energy as u8 + + ctx.settings.show_experience as u8 + + ctx.settings.show_infect as u8 + + ctx.settings.show_tickets as u8; + + if (ctx.settings.opponenets > 0) & (ctx.settings.opponenets < 7) { + let top_positions = ctx.positions.get_top_list(ctx.settings.opponenets); + + for (pos, dmg) in top_positions.iter().zip(ctx.game.cmd_dmg) { + + _ = SMALL_FONT.render_aligned( + dmg.as_string_horizontal().as_str(), + pos.position, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + } + + let start = (ctx.settings.opponenets as f32 * 15.)-90.; + let sweep = ctx.settings.opponenets as f32 * -30.; + let arc = embedded_graphics::primitives::Arc::with_center(CENTER, 160, Angle::from_degrees(start), Angle::from_degrees(sweep)); + + //println!("start: {}", start); + + let _ = arc.into_styled(style).draw(target); + + for i in 0..= ctx.settings.opponenets { + let angle = (start + 90. - (30.*(i as f32))) * crate::DEG_TO_RAD; + let (sin_t, cos_t) = angle.sin_cos(); + //println!("angle: {}, sin: {}, cos: {}", angle, sin_t, cos_t); + + let line1 = Point::new( + ((79. * sin_t)+120.) as i32, + ((-79. * cos_t)+120.) as i32 + ); + let line2 = Point::new( + ((125. * sin_t)+120.) as i32, + ((-125. * cos_t)+120.) as i32 + ); + + let drawline = embedded_graphics::primitives::Line::new(line1, line2); + + //println!("{:?}", drawline); + let _ = drawline.into_styled(style).draw(target); + + } + } + + if bottom_count != 0 { + let bottom_positions = ctx.positions.get_bottom_list(bottom_count); + + let mut bottom_vec = Vec::with_capacity(bottom_count as usize); + + if ctx.settings.show_cmd_tax { + let tmp = ctx.game.cmd_tax.as_string_horizontal(); + bottom_vec.push((tmp, '\u{0092}')); + } + if ctx.settings.show_energy { + let tmp = ctx.game.energy.to_string(); + bottom_vec.push((tmp,'\u{0060}')); + } + if ctx.settings.show_experience { + let tmp = ctx.game.experience.to_string(); + bottom_vec.push((tmp,'\u{0103}')); + } + if ctx.settings.show_tickets { + let tmp = ctx.game.tickets.to_string(); + bottom_vec.push((tmp, '\u{0106}')); + } + if ctx.settings.show_infect { + let tmp = ctx.game.infect.to_string(); + bottom_vec.push((tmp,'\u{005c}')); + } + + for (pos, content) in bottom_positions.iter().zip(bottom_vec) { + + _ = SMALL_FONT.render_aligned( + content.0.as_str(), + pos.position, + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target); + + _ = ICONS.render_aligned( + content.1, + pos.position, + u8g2_fonts::types::VerticalPosition::Top, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target); + } + + let start = (bottom_count as f32 * 15.)+90.; + let sweep = bottom_count as f32 * -30.; + let arc = embedded_graphics::primitives::Arc::with_center(CENTER, 160, Angle::from_degrees(start), Angle::from_degrees(sweep)); + let _ = arc.into_styled(style).draw(target); + + for i in 0..=bottom_count { + let angle = (start + 90. - (30.*(i as f32))) * crate::DEG_TO_RAD; + let (sin_t, cos_t) = angle.sin_cos(); + //println!("angle: {}, sin: {}, cos: {}", angle, sin_t, cos_t); + + let line1 = Point::new( + ((79. * sin_t)+120.) as i32, + ((-79. * cos_t)+120.) as i32 + ); + let line2 = Point::new( + ((125. * sin_t)+120.) as i32, + ((-125. * cos_t)+120.) as i32 + ); + + let drawline = embedded_graphics::primitives::Line::new(line1, line2); + + //println!("{:?}", drawline); + let _ = drawline.into_styled(style).draw(target); + } + } + + let center_item = match selection { + MainScreenItem::Dmg1 => (ctx.game.cmd_dmg[0].as_string_horizontal(),"Opponent 1"), + MainScreenItem::Dmg2 => (ctx.game.cmd_dmg[1].as_string_horizontal(),"Opponent 2"), + MainScreenItem::Dmg3 => (ctx.game.cmd_dmg[2].as_string_horizontal(),"Opponent 3"), + MainScreenItem::Dmg4 => (ctx.game.cmd_dmg[3].as_string_horizontal(),"Opponent 4"), + MainScreenItem::Dmg5 => (ctx.game.cmd_dmg[4].as_string_horizontal(),"Opponent 5"), + MainScreenItem::Dmg6 => (ctx.game.cmd_dmg[5].as_string_horizontal(),"Opponent 6"), + MainScreenItem::Tax => (ctx.game.cmd_tax.as_string_horizontal(),"Commander Tax"), + MainScreenItem::Energy => (ctx.game.energy.to_string(),"Energy"), + MainScreenItem::Experience => (ctx.game.experience.to_string(),"Experience"), + MainScreenItem::Tickets => (ctx.game.tickets.to_string(),"Tickets"), + MainScreenItem::Poison => (ctx.game.infect.to_string(),"Poison"), + _ => (ctx.game.life.to_string(),"Life"), + }; + + let _ = LARGE_FONT.render_aligned( + center_item.0.as_str(), + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let _ = SMALL_FONT.render_aligned( + center_item.1, + Point::new(120, 150), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let content = match selection { + MainScreenItem::Dmg1 => Some(0), + MainScreenItem::Dmg2 => Some(1), + MainScreenItem::Dmg3 => Some(2), + MainScreenItem::Dmg4 => Some(3), + MainScreenItem::Dmg5 => Some(4), + MainScreenItem::Dmg6 => Some(5), + _ => None, + }; + + if let Some(pos) = content { + let content = if ctx.game.cmd_dmg[pos].is_partner { + "0" + } else { + "0|0" + }; + + let _ = SMALL_FONT.render_aligned( + content, + Point { x: 120, y: 170 }, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + } else if *selection == MainScreenItem::Tax { + let content = if ctx.game.cmd_tax.is_partner { + "0" + } else { + "0|0" + }; + + let _ = SMALL_FONT.render_aligned( + content, + Point { x: 120, y: 170 }, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + } + } + Screen::Settings(selection) => { + setting_scroll(ctx, selection, target); + } + } +} + +pub struct TestFont { + +} + +impl Font for TestFont { + const DATA: &'static [u8] = include_bytes!("Logisoso_24_ol.u8g2font"); +} +/* +opponents 1-6 + +life total + +tax +energy +experience +tix +poison + +opponents +starting life +new game +colors +brightness + +show tax +show energy +show experience +show tickets +show poison +*/ \ No newline at end of file diff --git a/src/init.rs b/src/init.rs new file mode 100644 index 0000000..c384197 --- /dev/null +++ b/src/init.rs @@ -0,0 +1,114 @@ +use core::cell::Cell; +use embedded_hal_bus::spi::ExclusiveDevice; +use esp_hal::{delay::Delay, gpio::Output, i2c::master::I2c, peripherals::*, spi::master::Spi, time::Rate, Blocking}; +use mipidsi::{interface::SpiInterface, models::GC9A01}; + +pub struct UsedPins<'a> { + sda: Cell>>, + scl: Cell>>, + irq: Cell>>, + tp_rst: Cell>>, + + sclk: Cell>>, + mosi: Cell>>, + cs: Cell>>, + dc: Cell>>, + reset: Cell>>, + bl: Cell>>, + + iic: Cell>>, + spi: Cell>>, + lpwr: Cell>>, + ledc: Cell>>, + //dport: Cell>>, + io_mux: Cell>>, + //rtc_io: Cell>>, +} + +impl<'a> UsedPins<'a> { + + pub fn init(peripherals: esp_hal::peripherals::Peripherals) -> Self { + + UsedPins { + sda: Cell::new(Some(peripherals.GPIO21)), + scl: Cell::new(Some(peripherals.GPIO22)), + irq: Cell::new(Some(peripherals.GPIO19)), + tp_rst: Cell::new(Some(peripherals.GPIO4)), + + sclk: Cell::new(Some(peripherals.GPIO14)), + mosi: Cell::new(Some(peripherals.GPIO15)), + cs: Cell::new(Some(peripherals.GPIO5)), + dc: Cell::new(Some(peripherals.GPIO27)), + reset: Cell::new(Some(peripherals.GPIO33)), + bl: Cell::new(Some(peripherals.GPIO32)), + + iic: Cell::new(Some(peripherals.I2C0)), + spi: Cell::new(Some(peripherals.SPI2)), + lpwr: Cell::new(Some(peripherals.LPWR)), + + ledc: Cell::new(Some(peripherals.LEDC)), + //dport: Cell::new(Some(peripherals.DPORT)), + io_mux: Cell::new(Some(peripherals.RTC_IO)), + //rtc_io: Cell::new(Some(peripherals.LPWR)), + } + } + + pub fn irq(&self) -> GPIO19 { + let irq = self.irq.replace(None).unwrap(); + irq + } + + pub fn tp_rst(&self) -> GPIO4 { + let tp_rst = self.tp_rst.replace(None).unwrap(); + tp_rst + } + + pub fn get_lpwr(&self) -> LPWR<'a> { + let pin = self.lpwr.replace(None).unwrap(); + pin + } + + pub fn init_backlight(&self) -> (LEDC<'a>, GPIO32<'a>, RTC_IO<'a>) { + let bl = self.bl.replace(None).unwrap(); + let ledc = self.ledc.replace(None).unwrap(); + //let rtc_io = self.rtc_io.replace(None).unwrap(); + let io_mux = self.io_mux.replace(None).unwrap(); + + (ledc, bl, io_mux) + } + + pub fn init_iic(&self) -> I2c<'_, Blocking> { + let mut iic = I2c::new(self.iic.replace(None).unwrap(), esp_hal::i2c::master::Config::default()).unwrap() + .with_sda(self.sda.replace(None).unwrap()) + .with_scl(self.scl.replace(None).unwrap()); + + iic.write(0x15, &[0xFA_u8, 0b00010001]).expect("Failed to set irqctl"); + + iic + } + + pub fn init_display(&'a self, buffer: &'a mut [u8]) -> mipidsi::Display, Output<'a>, Delay>, Output<'a>>, GC9A01, Output<'a>> { + let spi = Spi::new( + self.spi.replace(None).unwrap(), + esp_hal::spi::master::Config::default() + .with_frequency(Rate::from_mhz(40)) + ).unwrap() + .with_sck(self.sclk.replace(None).unwrap()) + .with_mosi(self.mosi.replace(None).unwrap()); + + let cs_pin = esp_hal::gpio::Output::new(self.cs.replace(None).unwrap(), esp_hal::gpio::Level::Low, esp_hal::gpio::OutputConfig::default()); + let dc_pin = esp_hal::gpio::Output::new(self.dc.replace(None).unwrap(), esp_hal::gpio::Level::High, esp_hal::gpio::OutputConfig::default()); + let rs_pin = esp_hal::gpio::Output::new(self.reset.replace(None).unwrap(), esp_hal::gpio::Level::High, esp_hal::gpio::OutputConfig::default().with_pull(esp_hal::gpio::Pull::Up)); + let mut delay = esp_hal::delay::Delay::new(); + + let spi_dev = ExclusiveDevice::new(spi, cs_pin, delay).unwrap(); + let mipi_interface = mipidsi::interface::SpiInterface::new(spi_dev, dc_pin, buffer); + let display = mipidsi::Builder::new(GC9A01, mipi_interface) + .reset_pin(rs_pin) + .invert_colors(mipidsi::options::ColorInversion::Inverted) + .color_order(mipidsi::options::ColorOrder::Bgr) + .init(&mut delay).unwrap(); + + display + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b831cd0 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,15 @@ +#![no_std] + +pub mod init; +pub mod state; +pub mod display; +pub mod touch; +pub mod setting_screen; + +pub const IIC_ADDRESS: u8 = 0x15_u8; +pub const TP_GESTURE: u8 = 0x01_u8; +pub const TP_X: u8 = 0x04_u8; +pub const TP_Y: u8 = 0x06_u8; + +pub const RAD_TO_DEG: f32 = 57.2957795; +pub const DEG_TO_RAD: f32 = 0.017453293; \ No newline at end of file diff --git a/src/setting_screen.rs b/src/setting_screen.rs new file mode 100644 index 0000000..4edd2f7 --- /dev/null +++ b/src/setting_screen.rs @@ -0,0 +1,501 @@ +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::prelude::{DrawTarget, Point, Primitive, RgbColor, Size}; +use embedded_graphics::primitives::{PrimitiveStyleBuilder, Rectangle}; +use embedded_graphics::Drawable; + +extern crate alloc; +use alloc::{vec::Vec, string::ToString}; +use u8g2_fonts::types::{FontColor, HorizontalAlignment, VerticalPosition}; + +use crate::state::{SettingScreenEntry, SettingScreenItem, SystemState}; +use crate::display::{CHECK, MED_FONT, MED_PLUS_FONT, SMALL_FONT, TESTFONT}; + +use crate::display::{ColorScheme, COLORSCHEMES}; + +pub(crate) fn setting_screen(ctx: &SystemState, selection: &SettingScreenItem, target: &mut A) -> () + where A: DrawTarget +{ + let primary = ctx.settings.color_scheme.get_color(&crate::display::ColorType::Primary); + let background = ctx.settings.color_scheme.get_color(&crate::display::ColorType::Background); + + let top_count = 5; + let bottom_count = 5; + + let top_positions = &ctx.positions.top_setting_locations; + let bottom_positions = &ctx.positions.bottom_setting_locations; + + let mut top_vec = Vec::with_capacity(top_count as usize); + + top_vec.push("Opponents"); + top_vec.push("Starting\nLife"); + top_vec.push("New Game"); + top_vec.push("Color\nScheme"); + top_vec.push("Brightness"); + + let mut bottom_vec = Vec::with_capacity(bottom_count as usize); + + bottom_vec.push("Commander\nTax"); + bottom_vec.push("Energy"); + bottom_vec.push("Exp"); + bottom_vec.push("Tix"); + bottom_vec.push("Poison"); + + for (pos, content) in top_positions.iter().chain(bottom_positions.iter()).zip(top_vec.into_iter().chain(bottom_vec.into_iter())) { + _ = SMALL_FONT.render_aligned( + content, + pos.position, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target); + } + + match selection.entry { + SettingScreenEntry::NewGame => { + let _ = MED_FONT.render_aligned( + "Start\nNew Game.", + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::Opponents => { + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.opponenets.to_string().as_str(), + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let _ = TESTFONT.render_aligned( + ctx.settings.opponenets.to_string().as_str(), + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(Rgb565::RED), + target + ); + }, + SettingScreenEntry::StartingLife => { + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.starting_life.to_string().as_str(), + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::Colors => { + let current_scheme_number: u8 = ctx.settings.color_scheme.into(); + let prev_scheme_number; + let check_sub = current_scheme_number.checked_sub(1); + if let Some(p) = check_sub { + prev_scheme_number = p; + } else { + prev_scheme_number = COLORSCHEMES as u8 - 1; + } + let prev_scheme: ColorScheme = prev_scheme_number.into(); + + let next_scheme_number; + let check_add = current_scheme_number + 1; + if check_add >= COLORSCHEMES as u8 { + next_scheme_number = 0; + } else { + next_scheme_number = check_add; + } + let next_scheme: ColorScheme = next_scheme_number.into(); + + let _ = MED_FONT.render_aligned( + prev_scheme.as_str(), + Point::new(120, 80), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.color_scheme.as_str(), + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let _ = MED_FONT.render_aligned( + next_scheme.as_str(), + Point::new(120, 160), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::Brightness => { + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.brightness.as_str(), + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::ShowTax => { + //Yes/No rendering + let _ = MED_FONT.render_aligned( + "Show\nCommand Tax?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_cmd_tax)); + }, + SettingScreenEntry::ShowEnergy => { + //Yes/No rendering + let _ = MED_FONT.render_aligned( + "Show\nEnergy?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_energy)); + }, + SettingScreenEntry::ShowExperience => { + //Yes/No rendering + let _ = MED_FONT.render_aligned( + "Show\nExperience?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_experience)); + }, + SettingScreenEntry::ShowTickets => { + //Yes/No rendering + let _ = MED_FONT.render_aligned( + "Show\nTickets?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_tickets)); + }, + SettingScreenEntry::ShowPoison => { + //Yes/No rendering + let _ = MED_FONT.render_aligned( + "Show\nPoison?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_infect)); + }, + }; +} + +fn draw_yes_no>(primary: Rgb565, background: Rgb565, display: &mut A, selected: Option) -> () { + let yes_color; + let no_color; + let rect_point; + + if let Some(sel) = selected { + if sel { + yes_color = background; + no_color = primary; + rect_point = Point::new(75, 125); + } else { + yes_color = primary; + no_color = background; + rect_point = Point::new(120,125); + } + let style = PrimitiveStyleBuilder::new() + .fill_color(primary) + .build(); + + let _ = Rectangle::new(rect_point, Size::new(45, 25)).into_styled(style).draw(display); + } else { + yes_color = primary; + no_color = primary; + } + + _ = MED_FONT.render_aligned( + "Yes", + Point{x: 110, y: 130}, + u8g2_fonts::types::VerticalPosition::Top, + u8g2_fonts::types::HorizontalAlignment::Right, + u8g2_fonts::types::FontColor::Transparent(yes_color), + display, + ); + + _ = MED_FONT.render_aligned( + "No", + Point{x: 135, y: 130}, + u8g2_fonts::types::VerticalPosition::Top, + u8g2_fonts::types::HorizontalAlignment::Left, + u8g2_fonts::types::FontColor::Transparent(no_color), + display, + ); +} + +pub(crate) fn setting_scroll(ctx: &SystemState, selection: &SettingScreenItem, target: &mut A) -> () + where A: DrawTarget +{ + let primary = ctx.settings.color_scheme.get_color(&crate::display::ColorType::Primary); + let background = ctx.settings.color_scheme.get_color(&crate::display::ColorType::Background); + + if !selection.inner { + let above = selection.entry.prev().as_str(); + let selected = selection.entry.as_str(); + let below = selection.entry.next().as_str(); + + let _above = MED_FONT.render_aligned( + above, + Point::new(120, 50), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(primary), + target + ); + + let _selected = MED_PLUS_FONT.render_aligned( + selected, + Point::new(120, 120), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(primary), + target + ); + + let _below = MED_FONT.render_aligned( + below, + Point::new(120, 190), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(primary), + target + ); + } else { + setting_item(target); + match selection.entry { + SettingScreenEntry::NewGame => { + let _ = MED_PLUS_FONT.render_aligned( + selection.entry.as_str(), + Point::new(120, 120), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(primary), + target, + ); + }, + SettingScreenEntry::Opponents => { + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.opponenets.to_string().as_str(), + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::StartingLife => { + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.starting_life.to_string().as_str(), + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::Colors => { + let current_scheme_number: u8 = ctx.settings.color_scheme.into(); + let prev_scheme_number; + let check_sub = current_scheme_number.checked_sub(1); + if let Some(p) = check_sub { + prev_scheme_number = p; + } else { + prev_scheme_number = COLORSCHEMES as u8 - 1; + } + let prev_scheme: ColorScheme = prev_scheme_number.into(); + + let next_scheme_number; + let check_add = current_scheme_number + 1; + if check_add >= COLORSCHEMES as u8 { + next_scheme_number = 0; + } else { + next_scheme_number = check_add; + } + let next_scheme: ColorScheme = next_scheme_number.into(); + + let _ = MED_FONT.render_aligned( + prev_scheme.as_str(), + Point::new(120, 70), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.color_scheme.as_str(), + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + + let _ = MED_FONT.render_aligned( + next_scheme.as_str(), + Point::new(120, 170), + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + }, + SettingScreenEntry::Brightness => { + let _ = MED_PLUS_FONT.render_aligned( + ctx.settings.brightness.as_str(), + ctx.positions.center, + u8g2_fonts::types::VerticalPosition::Center, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + } + SettingScreenEntry::ShowTax => { + let _ = MED_FONT.render_aligned( + "Show\nCommand Tax?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_cmd_tax)); + }, + SettingScreenEntry::ShowEnergy => { + let _ = MED_FONT.render_aligned( + "Show\nEnergy?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_energy)); + }, + SettingScreenEntry::ShowExperience => { + let _ = MED_FONT.render_aligned( + "Show\nExperience?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_experience)); + }, + SettingScreenEntry::ShowTickets => { + let _ = MED_FONT.render_aligned( + "Show\nTickets?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_tickets)); + }, + SettingScreenEntry::ShowPoison => { + let _ = MED_FONT.render_aligned( + "Show\nPoison?", + Point::new(120, 120), + u8g2_fonts::types::VerticalPosition::Bottom, + u8g2_fonts::types::HorizontalAlignment::Center, + u8g2_fonts::types::FontColor::Transparent(primary), + target + ); + draw_yes_no(primary, background, target, Some(ctx.settings.show_infect)); + }, + } + } +} + +pub fn setting_item(target: &mut A) -> () + where A: DrawTarget +{ + let _okay_outline_1 = CHECK.render_aligned( + '\u{0040}', + Point::new(26, 121), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(Rgb565::BLACK), + target + ); + let _okay_outline_2 = CHECK.render_aligned( + '\u{0040}', + Point::new(26, 119), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(Rgb565::BLACK), + target + ); + let _okay_outline_3 = CHECK.render_aligned( + '\u{0040}', + Point::new(24, 121), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(Rgb565::BLACK), + target + ); + let _okay_outline_4 = CHECK.render_aligned( + '\u{0040}', + Point::new(24, 119), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(Rgb565::BLACK), + target + ); + + let _okay = CHECK.render_aligned( + '\u{0040}', + Point::new(25, 120), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(Rgb565::new(1, 54, 10)), + target + ); + + let _cancel = CHECK.render_aligned( + '\u{0044}', + Point::new(215, 120), + VerticalPosition::Center, + HorizontalAlignment::Center, + FontColor::Transparent(Rgb565::new(25, 8, 5)), + target + ); +} + + +/* +setting scroller -> internal screen check ok/ x cancel +*/ \ No newline at end of file diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..735d41e --- /dev/null +++ b/src/state.rs @@ -0,0 +1,387 @@ +use core::panic; + +use crate::display::ColorScheme; +use embedded_graphics::prelude::{Angle, Point}; + +extern crate alloc; +use alloc::{string::String, string::ToString}; + +pub struct SystemState { + pub settings: Settings, + pub game: Game, + pub positions: Positions, + pub screen: Screen, +} + +impl SystemState { + pub fn new() -> Self { + Self { + settings: Settings { + opponenets: 1, + starting_life: 40, + brightness: Brightness::Three, + color_scheme: ColorScheme::Dark, + show_cmd_tax: true, + show_infect: true, + show_energy: true, + show_experience: true, + show_tickets: true, + }, + game: Game { life: 40, cmd_dmg: [CommanderDamage{main: 0, partner: 0, is_partner: true};6], infect: 0, cmd_tax: CommanderDamage { main: 0, partner: 0, is_partner: false }, energy: 0, experience: 0, tickets: 0, monarch: false}, + positions: Positions::init(), + screen: Screen::Main(MainScreenItem::Life), + } + } +} + +pub struct Settings { + pub opponenets: u8, + pub starting_life: i32, + pub color_scheme: ColorScheme, + pub brightness: Brightness, + pub show_cmd_tax: bool, + pub show_infect: bool, + pub show_experience: bool, + pub show_energy: bool, + pub show_tickets: bool, +} + +pub struct Game { + pub life: i32, + pub cmd_dmg: [CommanderDamage;6], + pub cmd_tax: CommanderDamage, + pub infect: u8, + pub energy: u16, + pub experience: u16, + pub tickets: u16, + pub monarch: bool, +} + +#[derive(Debug, Clone, Copy)] +pub struct CommanderDamage { + pub main: u8, + pub partner: u8, + pub is_partner: bool, +} + +impl CommanderDamage { + pub fn as_string_horizontal(&self) -> String { + match self.is_partner { + true => { + let mut tmpa = self.main.to_string(); + let tmpb = self.partner.to_string(); + tmpa.push('|'); + tmpa.push_str(&tmpb); + tmpa + }, + false => { + self.main.to_string() + } + } + } + pub fn as_string_vetical(&self) -> String { + match self.is_partner { + true => { + let mut tmpa = self.main.to_string(); + let tmpb = self.partner.to_string(); + tmpa.push('\n'); + tmpa.push_str(&tmpb); + tmpa + }, + false => { + self.main.to_string() + } + } + } +} + +pub struct Positions { + top_even: [PeripheralLocation;6], + top_odd: [PeripheralLocation;5], + bottom_even: [PeripheralLocation;6], + bottom_odd: [PeripheralLocation;5], + pub top_setting_locations: [PeripheralLocation;5], + pub bottom_setting_locations: [PeripheralLocation;5], + pub center: Point, +} + +impl Positions { + pub fn init() -> Self { + let top_odd = [ + PeripheralLocation{ position: Point::new(38, 71), angle: Angle::from_degrees(150.)}, + PeripheralLocation{ position: Point::new(72, 37), angle: Angle::from_degrees(120.)}, + PeripheralLocation{ position: Point::new(120, 20), angle: Angle::from_degrees(90.)}, + PeripheralLocation{ position: Point::new(168, 37), angle: Angle::from_degrees(60.)}, + PeripheralLocation{ position: Point::new(202, 71), angle: Angle::from_degrees(30.)}, + ]; + let top_even = [ + PeripheralLocation{ position: Point::new(23, 96), angle: Angle::from_degrees(165.)}, + PeripheralLocation{ position: Point::new(53, 52), angle: Angle::from_degrees(135.)}, + PeripheralLocation{ position: Point::new(95, 27), angle: Angle::from_degrees(105.)}, + PeripheralLocation{ position: Point::new(145, 27), angle: Angle::from_degrees(75.)}, + PeripheralLocation{ position: Point::new(187, 52), angle: Angle::from_degrees(45.)}, + PeripheralLocation{ position: Point::new(212, 96), angle: Angle::from_degrees(15.)}, + ]; + let bottom_odd = [ + PeripheralLocation{ position: Point::new(32, 170), angle: Angle::from_degrees(210.)}, + PeripheralLocation{ position: Point::new(70, 208), angle: Angle::from_degrees(240.)}, + PeripheralLocation{ position: Point::new(120, 215), angle: Angle::from_degrees(270.)}, + PeripheralLocation{ position: Point::new(168, 203), angle: Angle::from_degrees(300.)}, + PeripheralLocation{ position: Point::new(202, 169), angle: Angle::from_degrees(330.)}, + ]; + let bottom_even = [ + PeripheralLocation{ position: Point::new(28, 146), angle: Angle::from_degrees(195.)}, + PeripheralLocation{ position: Point::new(48, 190), angle: Angle::from_degrees(225.)}, + PeripheralLocation{ position: Point::new(95, 213), angle: Angle::from_degrees(255.)}, + PeripheralLocation{ position: Point::new(145, 213), angle: Angle::from_degrees(285.)}, + PeripheralLocation{ position: Point::new(187, 188), angle: Angle::from_degrees(315.)}, + PeripheralLocation{ position: Point::new(212, 146), angle: Angle::from_degrees(345.)}, + ]; + let top_setting_locations = [ + PeripheralLocation{ position: Point::new(38, 91), angle: Angle::from_degrees(162.)}, + PeripheralLocation{ position: Point::new(64, 53), angle: Angle::from_degrees(126.)}, + PeripheralLocation{ position: Point::new(120, 25), angle: Angle::from_degrees(90.)}, + PeripheralLocation{ position: Point::new(176, 53), angle: Angle::from_degrees(54.)}, + PeripheralLocation{ position: Point::new(210, 91), angle: Angle::from_degrees(18.)}, + ]; + let bottom_setting_locations = [ + PeripheralLocation{ position: Point::new(33, 170), angle: Angle::from_degrees(210.)},//(43,169) + PeripheralLocation{ position: Point::new(72, 203), angle: Angle::from_degrees(240.)}, + PeripheralLocation{ position: Point::new(120, 215), angle: Angle::from_degrees(270.)}, + PeripheralLocation{ position: Point::new(168, 203), angle: Angle::from_degrees(300.)}, + PeripheralLocation{ position: Point::new(202, 169), angle: Angle::from_degrees(330.)}, + ]; + + Self { + top_even, + top_odd, + bottom_even, + bottom_odd, + top_setting_locations, + bottom_setting_locations, + center: Point { x: 120, y: 120 } + } + } + + pub fn get_top_list(&self, count: u8) -> &[PeripheralLocation] { + match count { + 1 => &self.top_odd[2..3], + 2 => &self.top_even[2..4], + 3 => &self.top_odd[1..4], + 4 => &self.top_even[1..5], + 5 => &self.top_odd, + 6 => &self.top_even, + _ => panic!("Invalid count") + } + } + pub fn get_bottom_list(&self, count: u8) -> &[PeripheralLocation] { + match count { + 1 => &self.bottom_odd[2..3], + 2 => &self.bottom_even[2..4], + 3 => &self.bottom_odd[1..4], + 4 => &self.bottom_even[1..5], + 5 => &self.bottom_odd, + 6 => &self.bottom_even, + _ => panic!("Invalid count") + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum Screen{ + Main(MainScreenItem), + Settings(SettingScreenItem), +} + +#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] +pub enum MainScreenItem { + Life, + Dmg1, + Dmg2, + Dmg3, + Dmg4, + Dmg5, + Dmg6, + Tax, + Energy, + Experience, + Tickets, + Poison, +} + + +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct SettingScreenItem { + pub entry: SettingScreenEntry, + pub inner: bool, + pub prev: Option, +} + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum SettingScreenEntry { + NewGame, + Opponents, + StartingLife, + Colors, + Brightness, + ShowTax, + ShowEnergy, + ShowExperience, + ShowTickets, + ShowPoison, +} + +impl SettingScreenEntry { + pub fn prev(&self) -> Self { + match self { + SettingScreenEntry::NewGame => Self::ShowPoison, + SettingScreenEntry::Opponents => Self::NewGame, + SettingScreenEntry::StartingLife => Self::Opponents, + SettingScreenEntry::Colors => Self::StartingLife, + SettingScreenEntry::Brightness => Self::Colors, + SettingScreenEntry::ShowTax => Self::Brightness, + SettingScreenEntry::ShowEnergy => Self::ShowTax, + SettingScreenEntry::ShowExperience => Self::ShowEnergy, + SettingScreenEntry::ShowTickets => Self::ShowExperience, + SettingScreenEntry::ShowPoison => Self::ShowTickets, + } + } + + pub fn next(&self) -> Self { + match self { + SettingScreenEntry::NewGame => Self::Opponents, + SettingScreenEntry::Opponents => Self::StartingLife, + SettingScreenEntry::StartingLife => Self::Colors, + SettingScreenEntry::Colors => Self::Brightness, + SettingScreenEntry::Brightness => Self::ShowTax, + SettingScreenEntry::ShowTax => Self::ShowEnergy, + SettingScreenEntry::ShowEnergy => Self::ShowExperience, + SettingScreenEntry::ShowExperience => Self::ShowTickets, + SettingScreenEntry::ShowTickets => Self::ShowPoison, + SettingScreenEntry::ShowPoison => Self::NewGame, + } + } + + pub fn as_str(&self) -> &'static str { + match self { + SettingScreenEntry::NewGame => "New Game", + SettingScreenEntry::Opponents => "Opponents", + SettingScreenEntry::StartingLife => "Starting\nLife", + SettingScreenEntry::Colors => "Color\nScheme", + SettingScreenEntry::Brightness => "Brightness", + SettingScreenEntry::ShowTax => "Show\nCommander\nTax", + SettingScreenEntry::ShowEnergy => "Show\nEnergy", + SettingScreenEntry::ShowExperience => "Show\nExperience", + SettingScreenEntry::ShowTickets => "Show\nTickets", + SettingScreenEntry::ShowPoison => "Show\nPoison", + } + } +} + +#[derive(Clone, Copy)] +pub enum Brightness { + One, + Two, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine, + Ten, +} + +impl Brightness { + pub fn inc(self) -> Self { + match self { + Brightness::One => Self::Two, + Brightness::Two => Self::Three, + Brightness::Three => Self::Four, + Brightness::Four => Self::Five, + Brightness::Five => Self::Six, + Brightness::Six => Self::Seven, + Brightness::Seven => Self::Eight, + Brightness::Eight => Self::Nine, + Brightness::Nine => Self::Ten, + Brightness::Ten => Self::Ten, + } + } + + pub fn dec(self) -> Self { + match self { + Brightness::One => Self::One, + Brightness::Two => Self::One, + Brightness::Three => Self::Two, + Brightness::Four => Self::Three, + Brightness::Five => Self::Four, + Brightness::Six => Self::Five, + Brightness::Seven => Self::Six, + Brightness::Eight => Self::Seven, + Brightness::Nine => Self::Eight, + Brightness::Ten => Self::Nine, + } + } + pub fn as_str(&self) -> &'static str { + match self { + Brightness::One => "Min", + Brightness::Two => "2", + Brightness::Three => "3", + Brightness::Four => "4", + Brightness::Five => "5", + Brightness::Six => "6", + Brightness::Seven => "7", + Brightness::Eight => "8", + Brightness::Nine => "9", + Brightness::Ten => "Max", + } + } +} + +impl Into for Brightness { + fn into(self) -> u32 { + match self { + Brightness::One => 15, + Brightness::Two => 20, + Brightness::Three => 30, + Brightness::Four => 40, + Brightness::Five => 50, + Brightness::Six => 60, + Brightness::Seven => 70, + Brightness::Eight => 80, + Brightness::Nine => 90, + Brightness::Ten => 100, + } + } +} + +impl From for Brightness { + fn from(value: u32) -> Self { + if value <= 15 { + Brightness::One + } else if value <= 20 { + Brightness::Two + } else if value <= 30 { + Brightness::Three + } else if value <= 40 { + Brightness::Four + } else if value <= 50 { + Brightness::Five + } else if value <= 60 { + Brightness::Six + } else if value <= 70 { + Brightness::Seven + } else if value <= 80 { + Brightness::Eight + } else if value <= 90 { + Brightness::Nine + } else { + Brightness::Ten + } + } +} + +pub struct PeripheralLocation { + pub position: Point, + pub angle: Angle, +} \ No newline at end of file diff --git a/src/touch.rs b/src/touch.rs new file mode 100644 index 0000000..bd62be8 --- /dev/null +++ b/src/touch.rs @@ -0,0 +1,406 @@ +use crate::{display::ColorScheme, state::{CommanderDamage, Game, MainScreenItem, Screen, SettingScreenEntry, SettingScreenItem, SystemState}}; + +const CMDDMGLIST: [MainScreenItem;6] = [ + MainScreenItem::Dmg1, + MainScreenItem::Dmg2, + MainScreenItem::Dmg3, + MainScreenItem::Dmg4, + MainScreenItem::Dmg5, + MainScreenItem::Dmg6, +]; + +pub fn get_touch_action(x: f32, y: f32, gesture: u8, ctx: &mut SystemState) -> () { + let x = x - 120.; + let y = -(y - 120.); + let touch_rad = (x*x)+(y*y); + let angle; + + let next_state; + + if (gesture == 0x3) | (gesture == 0x4) { + ctx.screen = match &ctx.screen { + Screen::Main(_) => Screen::Settings(SettingScreenItem { entry: SettingScreenEntry::NewGame, inner: false , prev: None}), + Screen::Settings(_) => Screen::Main(MainScreenItem::Life), + }; + return; + } + + match &ctx.screen { + Screen::Main(selected) => { + + let mut bottom_selectable_list: [Option;5] = [const {None};5]; + let mut pos = 0; + if ctx.settings.show_cmd_tax { + bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Tax); + pos += 1; + } + if ctx.settings.show_energy { + bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Energy); + pos+=1; + }; + if ctx.settings.show_experience { + bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Experience); + pos+=1; + }; + if ctx.settings.show_tickets { + bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Tickets); + pos+=1; + }; + if ctx.settings.show_infect { + bottom_selectable_list[pos] = Some(crate::state::MainScreenItem::Poison); + }; + + let bottom_count = bottom_selectable_list.iter().fold(0, |acc, x| acc+x.is_some() as u8); + + if touch_rad > (70.*70.) { + angle = atan2_norm(y, x)*90.; + //ctx.game.life = angle as i32; //debug + let top; + let check_angles = if y >= 0. { + if ctx.settings.opponenets == 0 { + return; + } + top = true; + ctx.positions.get_top_list(ctx.settings.opponenets) + } else { + if bottom_count == 0 { + return; + } + top = false; + ctx.positions.get_bottom_list(bottom_count) + }; + + let touch_item = match check_angles.iter().position(|x| (x.angle.to_degrees()-angle).abs()<15.) { + Some(loc) => loc, + None => return, + }; + + let sel_match = if top { + Some(CMDDMGLIST.into_iter().nth(touch_item).unwrap_or(MainScreenItem::Dmg1)) + } else { + bottom_selectable_list[touch_item] + }; + + if let Some(selected_item) = sel_match { + if selected_item == *selected { + next_state = Screen::Main(MainScreenItem::Life); + } else { + next_state = Screen::Main(selected_item); + } + } else { + next_state = Screen::Main(MainScreenItem::Life); + } + + } else { + match selected { + crate::state::MainScreenItem::Life => { + let d = touch_inc_dec(y, gesture); + ctx.game.life = ctx.game.life.saturating_add(d as i32); + }, + + crate::state::MainScreenItem::Dmg1 => { + cmd_dmg_w_swap(ctx, x, y, gesture, 0); + }, + crate::state::MainScreenItem::Dmg2 => { + cmd_dmg_w_swap(ctx, x, y, gesture, 1); + }, + crate::state::MainScreenItem::Dmg3 => { + cmd_dmg_w_swap(ctx, x, y, gesture, 2); + }, + crate::state::MainScreenItem::Dmg4 => { + cmd_dmg_w_swap(ctx, x, y, gesture, 3); + }, + crate::state::MainScreenItem::Dmg5 => { + cmd_dmg_w_swap(ctx, x, y, gesture, 4); + }, + crate::state::MainScreenItem::Dmg6 => { + cmd_dmg_w_swap(ctx, x, y, gesture, 5); + }, + + crate::state::MainScreenItem::Tax => { + cmd_tax_w_swap(ctx, x, y, gesture); + }, + crate::state::MainScreenItem::Energy => { + let d = touch_inc_dec(y, gesture); + ctx.game.energy = ctx.game.energy.saturating_add_signed(d.into()); + }, + crate::state::MainScreenItem::Experience => { + let d = touch_inc_dec(y, gesture); + ctx.game.experience = ctx.game.experience.saturating_add_signed(d.into()); + }, + crate::state::MainScreenItem::Tickets => { + let d = touch_inc_dec(y, gesture); + ctx.game.tickets = ctx.game.tickets.saturating_add_signed(d.into()); + }, + crate::state::MainScreenItem::Poison => { + let d = touch_inc_dec(y, gesture); + ctx.game.infect = ctx.game.infect.saturating_add_signed(d.into()); + }, + }; + next_state = ctx.screen; + }; + }, + Screen::Settings(selected) => { + if !selected.inner { + if gesture == 0x01_u8 { + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.prev(), inner: false, prev: selected.prev }); + } else if gesture == 0x02_u8 { + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.next(), inner: false, prev: selected.prev }); + } else { + if y > 55. { + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.prev(), inner: false, prev: selected.prev}); + } else if y < -55. { + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry.next(), inner: false, prev: selected.prev }); + } else { + let prev = match selected.entry { + SettingScreenEntry::NewGame => None, + SettingScreenEntry::Opponents => Some(ctx.settings.opponenets as u32), + SettingScreenEntry::StartingLife => Some(ctx.settings.starting_life as u32), + SettingScreenEntry::Colors => Some(Into::::into(ctx.settings.color_scheme) as u32), + SettingScreenEntry::Brightness => Some(ctx.settings.brightness.into()), + SettingScreenEntry::ShowTax => Some(ctx.settings.show_cmd_tax as u32), + SettingScreenEntry::ShowEnergy => Some(ctx.settings.show_energy as u32), + SettingScreenEntry::ShowExperience => Some(ctx.settings.show_experience as u32), + SettingScreenEntry::ShowTickets => Some(ctx.settings.show_tickets as u32), + SettingScreenEntry::ShowPoison => Some(ctx.settings.show_infect as u32), + }; + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: true, prev: prev}); + } + } + } else { + if x < -75. { + match selected.entry { + SettingScreenEntry::NewGame => { + ctx.game = Game { + life: ctx.settings.starting_life, + cmd_dmg: [CommanderDamage{main: 0, partner: 0, is_partner: false};6], + cmd_tax: CommanderDamage { main: 0, partner: 0, is_partner: false }, + infect: 0, + energy: 0, + experience: 0, + tickets: 0, + monarch: false, + }; + next_state = Screen::Main(MainScreenItem::Life); + }, + _ => { + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: false, prev: None }) + } + } + } else if x > 75. { + match selected.entry { + SettingScreenEntry::NewGame => {}, + SettingScreenEntry::Opponents => { + ctx.settings.opponenets = selected.prev.unwrap_or(0) as u8; + }, + SettingScreenEntry::StartingLife => { + ctx.settings.starting_life = selected.prev.unwrap_or(0) as i32; + }, + SettingScreenEntry::Colors => { + ctx.settings.color_scheme =Into::::into(selected.prev.unwrap_or(0) as u8); + }, + SettingScreenEntry::Brightness => { + ctx.settings.brightness = selected.prev.unwrap_or(0).into(); + }, + SettingScreenEntry::ShowTax => { + ctx.settings.show_cmd_tax = selected.prev.unwrap_or_default() != 0; + }, + SettingScreenEntry::ShowEnergy => { + ctx.settings.show_energy = selected.prev.unwrap_or_default() != 0; + }, + SettingScreenEntry::ShowExperience => { + ctx.settings.show_experience = selected.prev.unwrap_or_default() != 0; + }, + SettingScreenEntry::ShowTickets => { + ctx.settings.show_tickets = selected.prev.unwrap_or_default() != 0; + }, + SettingScreenEntry::ShowPoison => { + ctx.settings.show_infect = selected.prev.unwrap_or_default() != 0; + }, + } + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: false, prev: None }) + } else { + match selected.entry { + SettingScreenEntry::NewGame => { + + }, + SettingScreenEntry::Opponents => { + ctx.settings.opponenets = ctx.settings.opponenets.saturating_add_signed(touch_inc_dec(y, gesture)); + }, + SettingScreenEntry::StartingLife => { + ctx.settings.starting_life = ctx.settings.starting_life.saturating_add(touch_inc_dec(y, gesture) as i32); + }, + SettingScreenEntry::Colors => { + if y > 40. { + ctx.settings.color_scheme = ctx.settings.color_scheme.dec(); + } else if y < -40. { + ctx.settings.color_scheme = ctx.settings.color_scheme.inc(); + } + }, + SettingScreenEntry::Brightness => { + let tmp = touch_inc_dec(y, gesture); + if tmp > 0 { + ctx.settings.brightness = ctx.settings.brightness.inc(); + } else { + ctx.settings.brightness = ctx.settings.brightness.dec(); + } + }, + SettingScreenEntry::ShowTax => { + let det = select_button(x, y, gesture); + if let Some(i) = det { + ctx.settings.show_cmd_tax = i; + } + }, + SettingScreenEntry::ShowEnergy => { + let det = select_button(x, y, gesture); + if let Some(i) = det { + ctx.settings.show_energy = i; + } + }, + SettingScreenEntry::ShowExperience => { + let det = select_button(x, y, gesture); + if let Some(i) = det { + ctx.settings.show_experience = i; + } + }, + SettingScreenEntry::ShowTickets => { + let det = select_button(x, y, gesture); + if let Some(i) = det { + ctx.settings.show_tickets = i; + } + }, + SettingScreenEntry::ShowPoison => { + let det = select_button(x, y, gesture); + if let Some(i) = det { + ctx.settings.show_infect = i; + } + }, + } + next_state = Screen::Settings(SettingScreenItem { entry: selected.entry, inner: selected.inner, prev: selected.prev }) + } + } + } + } + ctx.screen = next_state; +} + +/// Approximates `atan2(y,x)` normalized to the `[0, 4)` range with a maximum +/// error of `0.1620` degrees. +fn atan2_norm(lhs: f32, rhs: f32) -> f32 { + const SIGN_MASK: u32 = 0x8000_0000; + const B: f32 = 0.596_227; + + let y = lhs; + let x = rhs; + + // Extract sign bits from floating point values + let ux_s = SIGN_MASK & x.to_bits(); + let uy_s = SIGN_MASK & y.to_bits(); + + // Determine quadrant offset + let q = ((!ux_s & uy_s) >> 29 | ux_s >> 30) as f32; + + // Calculate arctangent in the first quadrant + let bxy_a = (B * x * y).abs(); + let n = bxy_a + y * y; + let atan_1q = n / (x * x + bxy_a + n); + + // Translate it to the proper quadrant + let uatan_2q = (ux_s ^ uy_s) | atan_1q.to_bits(); + q + f32::from_bits(uatan_2q) +} + +fn touch_inc_dec(y: f32, gesture: u8) -> i8 { + if gesture == 0x05 { + if y >= 0. { + 1 + } else { + -1 + } + } else if gesture == 0x02 { + 5 + } else if gesture == 0x01 { + -5 + } else { + 0 + } +} + +fn touch_left_right(x: f32, y: f32, gesture: u8) -> (i8, bool) { + if x <= 0. { + (touch_inc_dec(y, gesture), true) + } else { + (touch_inc_dec(y, gesture), false) + } +} + +fn cmd_dmg_calc(ctx: &mut SystemState, x: f32, y: f32, gesture: u8, pos: usize) { + if ctx.game.cmd_dmg[pos].is_partner { + let (d, left) = touch_left_right(x, y, gesture); + if left { + ctx.game.cmd_dmg[pos].main = ctx.game.cmd_dmg[pos].main.saturating_add_signed(d); + } else { + ctx.game.cmd_dmg[pos].partner = ctx.game.cmd_dmg[pos].partner.saturating_add_signed(d); + } + } else { + let d = touch_inc_dec(y, gesture); + ctx.game.cmd_dmg[pos].main = ctx.game.cmd_dmg[pos].main.saturating_add_signed(d); + } +} + +fn cmd_tax_calc(ctx: &mut SystemState, x: f32, y: f32, gesture: u8) { + if ctx.game.cmd_tax.is_partner { + let (mut d, left) = touch_left_right(x, y, gesture); + + if d >= 0 { + d = 2; + } else { + d =-2; + } + + if left { + ctx.game.cmd_tax.main = ctx.game.cmd_tax.main.saturating_add_signed(d); + } else { + ctx.game.cmd_tax.partner = ctx.game.cmd_tax.partner.saturating_add_signed(d); + } + } else { + let mut d = touch_inc_dec(y, gesture); + + if d >= 0 { + d = 2; + } else { + d =-2; + } + + ctx.game.cmd_tax.main = ctx.game.cmd_tax.main.saturating_add_signed(d); + } +} + +/// true is left selection false is right selection +fn select_button(x: f32, y: f32, _gesture: u8) -> Option { + if (y<60.) & (y>-60.) { + if x<=0. { + Some(true) + } else { + Some(false) + } + } else { + None + } +} + +fn cmd_dmg_w_swap(ctx: &mut SystemState, x: f32, y: f32, gesture: u8, pos: usize) { + if (x>-20.) & (x<20.) & (y< -30.)&(y>-50.) { + ctx.game.cmd_dmg[pos].is_partner = !ctx.game.cmd_dmg[pos].is_partner; + } else { + cmd_dmg_calc(ctx, x, y, gesture, pos); + } +} + +fn cmd_tax_w_swap(ctx: &mut SystemState, x: f32, y: f32, gesture: u8) { + if (x>-20.) & (x<20.) & (y< -30.)&(y>-50.) { + ctx.game.cmd_tax.is_partner = !ctx.game.cmd_tax.is_partner; + } else { + cmd_tax_calc(ctx, x, y, gesture); + } +} \ No newline at end of file