Initial Commit
This commit is contained in:
14
.cargo/config.toml
Normal file
14
.cargo/config.toml
Normal file
@@ -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"]
|
||||||
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# 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/
|
||||||
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"rust-lang.rust-analyzer",
|
||||||
|
"tamasfe.even-better-toml",
|
||||||
|
"fill-labs.dependi"
|
||||||
|
]
|
||||||
|
}
|
||||||
13
.vscode/settings.json
vendored
Normal file
13
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.cargo.allTargets": false,
|
||||||
|
"rust-analyzer.cargo.target": "xtensa-esp32-none-elf",
|
||||||
|
"rust-analyzer.server.extraEnv": {
|
||||||
|
"RUSTUP_TOOLCHAIN": "stable"
|
||||||
|
},
|
||||||
|
"rust-analyzer.check.extraEnv": {
|
||||||
|
"RUSTUP_TOOLCHAIN": "esp"
|
||||||
|
},
|
||||||
|
"rust-analyzer.cargo.extraEnv": {
|
||||||
|
"RUSTUP_TOOLCHAIN": "esp"
|
||||||
|
},
|
||||||
|
}
|
||||||
1231
Cargo.lock
generated
Normal file
1231
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
Cargo.toml
Normal file
42
Cargo.toml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "mtgcount-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "mtgcount-rs"
|
||||||
|
path = "./src/bin/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
critical-section = "1.2.0"
|
||||||
|
display-interface = "0.5.0"
|
||||||
|
embedded-graphics = "0.8.1"
|
||||||
|
embedded-hal = "1.0.0"
|
||||||
|
embedded-hal-bus = "0.3.0"
|
||||||
|
esp-alloc = "0.7.0"
|
||||||
|
esp-backtrace = { version = "0.15.1", features = [
|
||||||
|
"esp32",
|
||||||
|
"exception-handler",
|
||||||
|
"panic-handler",
|
||||||
|
"println",
|
||||||
|
] }
|
||||||
|
esp-hal = { version = "1.0.0-beta.0", features = ["esp32", "unstable"] }
|
||||||
|
esp-println = { version = "0.13.0", features = ["esp32"] }
|
||||||
|
esp32 = "0.38.0"
|
||||||
|
micromath = "2.1.0"
|
||||||
|
mipidsi = "0.9.0"
|
||||||
|
u8g2-fonts = "0.7.1"
|
||||||
|
|
||||||
|
[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
|
||||||
40
build.rs
Normal file
40
build.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
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<String> = 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!();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
// 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()
|
||||||
|
);
|
||||||
|
}
|
||||||
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "esp"
|
||||||
216
src/bin/main.rs
Normal file
216
src/bin/main.rs
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use embedded_graphics::framebuffer::{buffer_size, Framebuffer};
|
||||||
|
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::{self, InputConfig, OutputConfig};
|
||||||
|
use esp_hal::rtc_cntl::sleep::{GpioWakeupSource, RtcSleepConfig};
|
||||||
|
use esp_hal::rtc_cntl::Rtc;
|
||||||
|
use esp_hal::main;
|
||||||
|
|
||||||
|
use esp_println::println;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use mtgcount_rs::{self, TP_GESTURE, TP_X, TP_Y};
|
||||||
|
|
||||||
|
#[main]
|
||||||
|
fn main() -> ! {
|
||||||
|
// generator version: 0.3.1
|
||||||
|
println!("Startup init");
|
||||||
|
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||||
|
let peripherals = esp_hal::init(config);
|
||||||
|
|
||||||
|
let pins = mtgcount_rs::init::UsedPins::init(peripherals);
|
||||||
|
|
||||||
|
let mut buffer = [0_u8;256];
|
||||||
|
|
||||||
|
//set clocks;
|
||||||
|
|
||||||
|
let mut iic = pins.init_iic();
|
||||||
|
let mut display = pins.init_display(&mut buffer);
|
||||||
|
let mut framebuf: Framebuffer<Rgb565, _, LittleEndian, 240, 240, {buffer_size::<Rgb565>(240, 240)}> = Framebuffer::new();
|
||||||
|
//let mut bgbuf: Framebuffer<Rgb565, _, LittleEndian, 240, 240, {buffer_size::<Rgb565>(240, 240)}> = Framebuffer::new();
|
||||||
|
|
||||||
|
|
||||||
|
//start bl
|
||||||
|
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);
|
||||||
|
//ledc.set_global_slow_clock(esp_hal::ledc::LSGlobalClkSource::APBClk);
|
||||||
|
|
||||||
|
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 mut lstimer0 = ledc.timer::<LowSpeed>(esp_hal::ledc::timer::Number::Timer0);
|
||||||
|
//lstimer0.configure(esp_hal::ledc::timer::config::Config {
|
||||||
|
// duty: esp_hal::ledc::timer::config::Duty::Duty5Bit,
|
||||||
|
// clock_source: esp_hal::ledc::timer::LSClockSource::APBClk,
|
||||||
|
// frequency: Rate::from_khz(2),
|
||||||
|
//}).unwrap();
|
||||||
|
|
||||||
|
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 channel0 = ledc.channel(esp_hal::ledc::channel::Number::Channel0, bl);
|
||||||
|
//channel0.configure(esp_hal::ledc::channel::config::Config {
|
||||||
|
// timer: &lstimer0,
|
||||||
|
// duty_pct: 50,
|
||||||
|
// pin_config: esp_hal::ledc::channel::config::PinConfig::PushPull,
|
||||||
|
//}).unwrap();
|
||||||
|
|
||||||
|
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(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::state::SystemState::new();
|
||||||
|
println!("screen: {:?}", state.screen);
|
||||||
|
|
||||||
|
framebuf.clear(state.settings.color_scheme.get_color(&mtgcount_rs::display::ColorType::Background)).unwrap();
|
||||||
|
display.clear(state.settings.color_scheme.get_color(&mtgcount_rs::display::ColorType::Background)).unwrap();
|
||||||
|
mtgcount_rs::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::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::display::draw_screen(&state, &mut framebuf);
|
||||||
|
framebuf.as_image().draw(&mut display).unwrap();
|
||||||
|
|
||||||
|
framebuf.clear(state.settings.color_scheme.get_color(&mtgcount_rs::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-beta.0/examples/src/bin
|
||||||
|
}
|
||||||
205
src/bin/mini_ulp.s
Normal file
205
src/bin/mini_ulp.s
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
REG_WR 0x103, 0x17, 0x17, 1
|
||||||
|
REG_WR 0x123, 0x18, 0x18, 0
|
||||||
|
REG_WR 0x123, 0x11, 0x11, 1
|
||||||
|
REG_WR 0x123, 0x06, 0x06, 1
|
||||||
|
entry:
|
||||||
|
MOVE R0, dutycycle //6
|
||||||
|
LD R0, R0, 0 //8
|
||||||
|
LSH R1, R0, 4 //6
|
||||||
|
ADD R0, R0, R1 //6
|
||||||
|
ADD R0, R0, 10 //6
|
||||||
|
JUMP R0 //4
|
||||||
|
//36
|
||||||
|
0x0a:
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 12 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 717 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 12 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 717 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 12 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 717 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 12 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 677 //6
|
||||||
|
JUMP entry //4
|
||||||
|
0x22:
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 84 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 645 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 84 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 645 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 84 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 645 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 84 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 605 //6
|
||||||
|
JUMP entry //4
|
||||||
|
0x3a:
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 156 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 573 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 156 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 573 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 156 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 573 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 156 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 533 //6
|
||||||
|
JUMP entry //4
|
||||||
|
0x52:
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 228 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 501 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 228 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 501 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 228 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 501 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 228 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 461 //6
|
||||||
|
JUMP entry //4
|
||||||
|
0x6a:
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 300 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 429 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 300 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 429 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 300 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 429 //6
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 300 //6
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1 //12
|
||||||
|
WAIT 389 //6
|
||||||
|
JUMP entry //4
|
||||||
|
0x82:
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 357
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 372
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 357
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 372
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 357
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 372
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 357
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 332
|
||||||
|
JUMP entry
|
||||||
|
0x9a:
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 285
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 444
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 285
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 444
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 285
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 444
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 285
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 404
|
||||||
|
JUMP entry
|
||||||
|
0xb2:
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 213
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 516
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 213
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 516
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 213
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 516
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 213
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 476
|
||||||
|
JUMP entry
|
||||||
|
0xca:
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 141
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 606
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 141
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 606
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 141
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 606
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 141
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 566
|
||||||
|
JUMP entry
|
||||||
|
0xe2:
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 69
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 660
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 69
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 660
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 69
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 660
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 69
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 620
|
||||||
|
JUMP entry
|
||||||
|
0xfa:
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 12
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 1482
|
||||||
|
REG_WR 0x102, 0x17, 0x17, 1
|
||||||
|
WAIT 12
|
||||||
|
REG_WR 0x101, 0x17, 0x17, 1
|
||||||
|
WAIT 1442
|
||||||
|
JUMP entry
|
||||||
|
|
||||||
|
dutycycle:
|
||||||
|
.long 0
|
||||||
1551
src/bin/ulp_program.s
Normal file
1551
src/bin/ulp_program.s
Normal file
File diff suppressed because it is too large
Load Diff
447
src/display.rs
Normal file
447
src/display.rs
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
use embedded_graphics::prelude::{Angle, DrawTarget, Point, Primitive, RgbColor};
|
||||||
|
use embedded_graphics::pixelcolor::Rgb565;
|
||||||
|
use embedded_graphics::Drawable;
|
||||||
|
|
||||||
|
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::<u8g2_font_logisoso42_tr>();
|
||||||
|
pub const MED_PLUS_FONT:FontRenderer = FontRenderer::new::<u8g2_font_logisoso24_tr>();
|
||||||
|
pub const MED_FONT:FontRenderer = FontRenderer::new::<u8g2_font_9x15B_tr>();
|
||||||
|
pub const SMALL_FONT:FontRenderer = FontRenderer::new::<u8g2_font_7x13_tr>();
|
||||||
|
pub const ICONS:FontRenderer = FontRenderer::new::<u8g2_font_open_iconic_all_2x_t>();
|
||||||
|
pub const CHECK:FontRenderer = FontRenderer::new::<u8g2_font_open_iconic_check_4x_t>();
|
||||||
|
|
||||||
|
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<u8> 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<u8> 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<A: DrawTarget<Color = Rgb565>>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
115
src/init.rs
Normal file
115
src/init.rs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
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<Option<GPIO21<'a>>>,
|
||||||
|
scl: Cell<Option<GPIO22<'a>>>,
|
||||||
|
irq: Cell<Option<GPIO19<'a>>>,
|
||||||
|
tp_rst: Cell<Option<GPIO4<'a>>>,
|
||||||
|
|
||||||
|
sclk: Cell<Option<GPIO14<'a>>>,
|
||||||
|
mosi: Cell<Option<GPIO15<'a>>>,
|
||||||
|
cs: Cell<Option<GPIO5<'a>>>,
|
||||||
|
dc: Cell<Option<GPIO27<'a>>>,
|
||||||
|
reset: Cell<Option<GPIO33<'a>>>,
|
||||||
|
bl: Cell<Option<GPIO32<'a>>>,
|
||||||
|
|
||||||
|
iic: Cell<Option<I2C0<'a>>>,
|
||||||
|
spi: Cell<Option<SPI2<'a>>>,
|
||||||
|
lpwr: Cell<Option<LPWR<'a>>>,
|
||||||
|
ledc: Cell<Option<LEDC<'a>>>,
|
||||||
|
//dport: Cell<Option<DPORT<'a>>>,
|
||||||
|
io_mux: Cell<Option<RTC_IO<'a>>>,
|
||||||
|
//rtc_io: Cell<Option<LPWR<'a>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<SpiInterface<'a, ExclusiveDevice<esp_hal::spi::master::Spi<'a, Blocking>, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
15
src/lib.rs
Normal file
15
src/lib.rs
Normal file
@@ -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;
|
||||||
492
src/setting_screen.rs
Normal file
492
src/setting_screen.rs
Normal file
@@ -0,0 +1,492 @@
|
|||||||
|
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, SMALL_FONT, MED_FONT, MED_PLUS_FONT};
|
||||||
|
|
||||||
|
use crate::display::{ColorScheme, COLORSCHEMES};
|
||||||
|
|
||||||
|
pub(crate) fn setting_screen<A>(ctx: &SystemState, selection: &SettingScreenItem, target: &mut A) -> ()
|
||||||
|
where A: DrawTarget<Color = Rgb565>
|
||||||
|
{
|
||||||
|
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
|
||||||
|
);
|
||||||
|
},
|
||||||
|
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<A: DrawTarget<Color = Rgb565>>(primary: Rgb565, background: Rgb565, display: &mut A, selected: Option<bool>) -> () {
|
||||||
|
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<A>(ctx: &SystemState, selection: &SettingScreenItem, target: &mut A) -> ()
|
||||||
|
where A: DrawTarget<Color = Rgb565>
|
||||||
|
{
|
||||||
|
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<A>(target: &mut A) -> ()
|
||||||
|
where A: DrawTarget<Color = Rgb565>
|
||||||
|
{
|
||||||
|
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
|
||||||
|
*/
|
||||||
387
src/state.rs
Normal file
387
src/state.rs
Normal file
@@ -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<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<u32> 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<u32> 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,
|
||||||
|
}
|
||||||
406
src/touch.rs
Normal file
406
src/touch.rs
Normal file
@@ -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<MainScreenItem>;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::<u8>::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::<ColorScheme>::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<bool> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
149
template.yaml
Normal file
149
template.yaml
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
options:
|
||||||
|
- !Option
|
||||||
|
name: unstable-hal
|
||||||
|
display_name: Enable unstable HAL features.
|
||||||
|
help: "This configuration enables unstable esp-hal features.
|
||||||
|
These come with no stability guarantees, and could be changed or removed at any time."
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: alloc
|
||||||
|
display_name: Enable allocations via the esp-alloc crate.
|
||||||
|
help: esp-alloc comes with no stability guarantees at this time.
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: wifi
|
||||||
|
display_name: Enable Wi-Fi via the esp-wifi crate.
|
||||||
|
help: esp-wifi comes with no stability guarantees at this time.
|
||||||
|
requires:
|
||||||
|
- alloc
|
||||||
|
- unstable-hal
|
||||||
|
chips:
|
||||||
|
- esp32
|
||||||
|
- esp32c2
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- esp32s2
|
||||||
|
- esp32s3
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: ble
|
||||||
|
display_name: Enable BLE via the esp-wifi crate.
|
||||||
|
help: esp-wifi comes with no stability guarantees at this time.
|
||||||
|
requires:
|
||||||
|
- alloc
|
||||||
|
- unstable-hal
|
||||||
|
chips:
|
||||||
|
- esp32
|
||||||
|
- esp32c2
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- esp32h2
|
||||||
|
- esp32s3
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: embassy
|
||||||
|
display_name: Add embassy framework support.
|
||||||
|
help: esp-hal-embassy comes with no stability guarantees at this time.
|
||||||
|
requires:
|
||||||
|
- unstable-hal
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: probe-rs
|
||||||
|
display_name: Use probe-rs to flash and monitor instead of espflash.
|
||||||
|
help: probe-rs is a debugger that connects to the chips over JTAG. It can be used to flash and
|
||||||
|
monitor, and it can also be used to interactively debug an application, or run tests on the
|
||||||
|
hardware. Semihosting or RTT-based technologies like defmt-rtt require probe-rs.
|
||||||
|
chips:
|
||||||
|
- esp32c6
|
||||||
|
- esp32h2
|
||||||
|
- esp32s3
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: probe-rs
|
||||||
|
display_name: Use probe-rs to flash and monitor instead of espflash.
|
||||||
|
help: probe-rs is a debugger that connects to the chips over JTAG. It can be used to flash and
|
||||||
|
monitor, and it can also be used to interactively debug an application, or run tests on the
|
||||||
|
hardware. Semihosting or RTT-based technologies like defmt-rtt require probe-rs.
|
||||||
|
|
||||||
|
probe-rs requires a debug probe like esp-prog, and will not work with USB-UART adapters that
|
||||||
|
often come on development boards.
|
||||||
|
chips:
|
||||||
|
- esp32
|
||||||
|
- esp32s2
|
||||||
|
- esp32c2
|
||||||
|
- esp32c3
|
||||||
|
|
||||||
|
- !Category
|
||||||
|
name: flashing-probe-rs
|
||||||
|
display_name: Flashing, logging and debugging (probe-rs)
|
||||||
|
requires:
|
||||||
|
- probe-rs
|
||||||
|
options:
|
||||||
|
- !Option
|
||||||
|
name: defmt
|
||||||
|
display_name: Use defmt to print messages.
|
||||||
|
selection_group: log-frontend
|
||||||
|
- !Option
|
||||||
|
name: panic-rtt-target
|
||||||
|
display_name: Use panic-rtt-target as the panic handler.
|
||||||
|
selection_group: panic-handler
|
||||||
|
requires:
|
||||||
|
- probe-rs
|
||||||
|
|
||||||
|
- !Category
|
||||||
|
name: flashing-espflash
|
||||||
|
display_name: Flashing, logging and debugging (espflash)
|
||||||
|
requires:
|
||||||
|
- "!probe-rs"
|
||||||
|
options:
|
||||||
|
- !Option
|
||||||
|
name: log
|
||||||
|
display_name: Use the log crate to print messages.
|
||||||
|
selection_group: log-frontend
|
||||||
|
requires:
|
||||||
|
- "!probe-rs"
|
||||||
|
- !Option
|
||||||
|
name: defmt
|
||||||
|
display_name: Use defmt to print messages.
|
||||||
|
selection_group: log-frontend
|
||||||
|
- !Option
|
||||||
|
name: esp-backtrace
|
||||||
|
display_name: Use esp-backtrace as the panic handler.
|
||||||
|
selection_group: panic-handler
|
||||||
|
requires:
|
||||||
|
- "!probe-rs"
|
||||||
|
|
||||||
|
- !Category
|
||||||
|
name: optional
|
||||||
|
display_name: Options
|
||||||
|
options:
|
||||||
|
- !Option
|
||||||
|
name: wokwi
|
||||||
|
display_name: Add support for Wokwi simulation using VS Code Wokwi extension.
|
||||||
|
chips:
|
||||||
|
- esp32
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- esp32h2
|
||||||
|
- esp32s2
|
||||||
|
- esp32s3
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: dev-container
|
||||||
|
display_name: Add support for VS Code Dev Containers and GitHub Codespaces.
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: ci
|
||||||
|
display_name: Add GitHub Actions support with some basic checks.
|
||||||
|
|
||||||
|
- !Category
|
||||||
|
name: editor
|
||||||
|
display_name: Optional editor config files for rust-analyzer
|
||||||
|
options:
|
||||||
|
- !Option
|
||||||
|
name: helix
|
||||||
|
display_name: Add rust-analyzer settings for Helix Editor
|
||||||
|
|
||||||
|
- !Option
|
||||||
|
name: vscode
|
||||||
|
display_name: Add rust-analyzer settings for Visual Studio Code
|
||||||
Reference in New Issue
Block a user