Compare commits
5
Commits
1f960b2d46
...
6b8d076b3c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b8d076b3c | ||
|
|
88dce365ad | ||
|
|
7ce3a60a08 | ||
|
|
78765ce595 | ||
|
|
5f76802f92 |
Generated
+52
-8
@@ -306,6 +306,7 @@ dependencies = [
|
||||
"critical-section",
|
||||
"display-interface-spi",
|
||||
"embassy-executor",
|
||||
"embassy-futures",
|
||||
"embassy-time",
|
||||
"embedded-graphics",
|
||||
"embedded-graphics-core",
|
||||
@@ -320,6 +321,8 @@ dependencies = [
|
||||
"esp-rtos",
|
||||
"ili9341",
|
||||
"log",
|
||||
"ndef",
|
||||
"pn532",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -568,6 +571,26 @@ dependencies = [
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
|
||||
dependencies = [
|
||||
"derive_more-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more-impl"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
@@ -1508,27 +1531,27 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.33"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
|
||||
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.33"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307"
|
||||
checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.33"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
|
||||
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.33"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
|
||||
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@@ -1980,6 +2003,17 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||
|
||||
[[package]]
|
||||
name = "ndef"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39081400340c14a9fcbb0122c311aca4e34ec2d19e3136613638ae7e2a362dbc"
|
||||
dependencies = [
|
||||
"derive_more",
|
||||
"heapless 0.8.0",
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nonmax"
|
||||
version = "0.5.5"
|
||||
@@ -2584,6 +2618,16 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pn532"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce656b2f9335bedbd8806597f6f78e644a955366673cd9280a0fb67a0d7b35a1"
|
||||
dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.14.0"
|
||||
|
||||
+7
-4
@@ -9,7 +9,7 @@ name = "creaturedex"
|
||||
path = "./src/bin/main.rs"
|
||||
|
||||
[dependencies]
|
||||
esp-hal = { version = "~1.1.0", features = ["esp32s3", "log-04", "unstable"] }
|
||||
esp-hal = { version = "~1.1.0", features = ["esp32s3", "log-04", "unstable"] } #, "embassy", "embassy-time-timg0", "embassy-executor-thread"] }
|
||||
|
||||
esp-rtos = { version = "0.3.0", features = [
|
||||
"embassy",
|
||||
@@ -24,8 +24,10 @@ log = "0.4.27"
|
||||
|
||||
critical-section = "1.2.0"
|
||||
embedded-io = "0.7.1"
|
||||
embassy-executor = { version = "0.10.0", default-features = false }
|
||||
embassy-executor = { version = "0.10.0", features = [
|
||||
] }
|
||||
embassy-time = { version = "0.5.1", default-features = false }
|
||||
embassy-futures = "0.1.2"
|
||||
esp-alloc = "0.10.0"
|
||||
esp-hal-wifimanager = { git = "https://github.com/InvisibleUSA/esp-hal-wifimanager", default-features = false, features = [
|
||||
"ap",
|
||||
@@ -39,7 +41,8 @@ embedded-hal-bus = "0.3.0"
|
||||
embedded-graphics = "0.8.2"
|
||||
embedded-graphics-core = "0.4.1"
|
||||
base64 = { version = "0.22", default-features = false, features = ["alloc"] }
|
||||
|
||||
pn532 = "0.5.0"
|
||||
ndef = "0.5.0"
|
||||
|
||||
# For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html
|
||||
[profile.dev]
|
||||
@@ -55,4 +58,4 @@ opt-level = 's'
|
||||
|
||||
[features]
|
||||
default = []
|
||||
wokwi = []
|
||||
wokwi = []
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
[ "lcd1:MOSI", "esp1:35", "violet", [ "v105.6", "h-124.8", "v-144" ] ],
|
||||
[ "lcd1:SCK", "esp1:36", "white", [ "v115.2", "h-144", "v-86.4" ] ],
|
||||
[ "esp1:37", "lcd1:MISO", "magenta", [ "h57.6", "v105.6", "h172.8" ] ],
|
||||
[ "esp1:22", "lcd1:SCL", "yellow", [ "h48", "v163.2", "h192" ] ],
|
||||
[ "esp1:21", "lcd1:SDA", "cyan", [ "h38.4", "v144", "h211.2" ] ],
|
||||
[ "btn1:1.l", "esp1:GND.2", "green", [ "h-9.6", "v-48" ] ],
|
||||
[ "btn1:2.l", "esp1:38", "green", [ "h-9.6", "v19.4" ] ]
|
||||
],
|
||||
|
||||
+35
-31
@@ -10,7 +10,9 @@
|
||||
use creaturedex::card::mock::{MOCK_PAYLOAD, MOCK_PAYLOAD2};
|
||||
use creaturedex::display::primary_lcd::init_primary_lcd;
|
||||
use creaturedex::display::views::card_view::render_nfc_payload;
|
||||
use creaturedex::navigation::input::init_navigation_button;
|
||||
use creaturedex::drivers::nfc_pn532::NfcPn532Driver;
|
||||
use creaturedex::navigation::inputs::Inputs;
|
||||
use creaturedex::navigation::navigation;
|
||||
use creaturedex::navigation::state::NavigationState;
|
||||
use creaturedex::network::wifi::setup_wifi;
|
||||
use embassy_executor::Spawner;
|
||||
@@ -20,6 +22,8 @@ use embedded_graphics::pixelcolor::Rgb565;
|
||||
use embedded_graphics::prelude::RgbColor;
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||
use esp_hal::time::Duration;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use log::error;
|
||||
|
||||
@@ -31,6 +35,8 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
const HEAP_SIZE: usize = 73744;
|
||||
|
||||
// This creates a default app-descriptor required by the esp-idf bootloader.
|
||||
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
@@ -46,26 +52,15 @@ async fn main(spawner: Spawner) {
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
|
||||
// The following GPIO pins are in use by some feature of the module and should not be used.
|
||||
let _ = peripherals.GPIO27;
|
||||
let _ = peripherals.GPIO28;
|
||||
let _ = peripherals.GPIO29;
|
||||
let _ = peripherals.GPIO30;
|
||||
let _ = peripherals.GPIO31;
|
||||
let _ = peripherals.GPIO32;
|
||||
let _ = peripherals.GPIO33;
|
||||
let _ = peripherals.GPIO34;
|
||||
esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: HEAP_SIZE);
|
||||
|
||||
esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 73744);
|
||||
|
||||
let mut delay = Delay::new();
|
||||
let button1 = init_navigation_button(peripherals.GPIO38);
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let sw_interrupt =
|
||||
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
||||
|
||||
log::info!("Setup complete, entering main loop");
|
||||
|
||||
let mut display = init_primary_lcd(
|
||||
peripherals.SPI2,
|
||||
peripherals.GPIO36,
|
||||
@@ -74,27 +69,36 @@ async fn main(spawner: Spawner) {
|
||||
peripherals.GPIO11,
|
||||
peripherals.GPIO10,
|
||||
peripherals.GPIO12,
|
||||
&mut delay,
|
||||
);
|
||||
|
||||
// setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await;
|
||||
setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await;
|
||||
|
||||
log::info!("Setup complete, entering main loop");
|
||||
|
||||
let mut nav_state = NavigationState::new();
|
||||
|
||||
loop {
|
||||
if button1.is_low() {
|
||||
log::info!("Button pressed!");
|
||||
display.clear(Rgb565::BLACK).unwrap();
|
||||
let payload = if nav_state.toggle_payload() {
|
||||
&MOCK_PAYLOAD
|
||||
} else {
|
||||
&MOCK_PAYLOAD2
|
||||
};
|
||||
|
||||
render_nfc_payload(&mut display, payload);
|
||||
}
|
||||
Timer::after_millis(10).await;
|
||||
let mut nfc_driver =
|
||||
NfcPn532Driver::new(peripherals.I2C0, peripherals.GPIO17, peripherals.GPIO18);
|
||||
let timeout = Duration::from_millis(1000);
|
||||
if nfc_driver.configure_sam(timeout).is_ok() {
|
||||
log::info!("NFC SAM configuration successful");
|
||||
} else {
|
||||
log::error!("NFC SAM configuration failed");
|
||||
}
|
||||
|
||||
log::info!("Setup complete, entering main loop");
|
||||
|
||||
let mut nav_state = NavigationState::new();
|
||||
|
||||
let button_config = InputConfig::default().with_pull(Pull::Up);
|
||||
let mut inputs = Inputs {
|
||||
up: Input::new(peripherals.GPIO38, button_config.clone()),
|
||||
down: Input::new(peripherals.GPIO0, button_config.clone()),
|
||||
left: Input::new(peripherals.GPIO1, button_config.clone()),
|
||||
right: Input::new(peripherals.GPIO2, button_config.clone()),
|
||||
back: Input::new(peripherals.GPIO3, button_config.clone()),
|
||||
ok: Input::new(peripherals.GPIO4, button_config.clone()),
|
||||
};
|
||||
|
||||
spawner.spawn(navigation::run(inputs).expect("run task failed"));
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@ use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig};
|
||||
use esp_hal::peripherals::{GPIO10, GPIO11, GPIO12, GPIO35, GPIO36, GPIO37, SPI2};
|
||||
use esp_hal::spi::{master::{Config, Spi}, Mode};
|
||||
use esp_hal::spi::{
|
||||
Mode,
|
||||
master::{Config, Spi},
|
||||
};
|
||||
use esp_hal::time::Rate;
|
||||
use ili9341::{DisplaySize240x320, Ili9341, Orientation};
|
||||
|
||||
pub type PrimaryLcdDisplay<'a> = Ili9341<
|
||||
SPIInterface<
|
||||
ExclusiveDevice<Spi<'a, esp_hal::Blocking>, Output<'a>, Delay>,
|
||||
Output<'a>,
|
||||
>,
|
||||
SPIInterface<ExclusiveDevice<Spi<'a, esp_hal::Blocking>, Output<'a>, Delay>, Output<'a>>,
|
||||
Output<'a>,
|
||||
>;
|
||||
|
||||
@@ -26,7 +26,6 @@ pub fn init_primary_lcd(
|
||||
cs: GPIO11<'static>,
|
||||
reset: GPIO10<'static>,
|
||||
dc: GPIO12<'static>,
|
||||
delay: &mut Delay,
|
||||
) -> PrimaryLcdDisplay<'static> {
|
||||
let freq = Rate::from_khz(60_000);
|
||||
log::info!("Display freq: {freq}");
|
||||
@@ -40,8 +39,10 @@ pub fn init_primary_lcd(
|
||||
.with_mosi(mosi)
|
||||
.with_miso(miso);
|
||||
|
||||
let mut delay = Delay::new();
|
||||
|
||||
let cs_main = Output::new(cs, Level::High, OutputConfig::default());
|
||||
let spi_dev = ExclusiveDevice::new(spi_bus, cs_main, *delay).unwrap();
|
||||
let spi_dev = ExclusiveDevice::new(spi_bus, cs_main, delay).unwrap();
|
||||
let reset_main = Output::new(reset, Level::High, OutputConfig::default());
|
||||
let spi_dc = Output::new(dc, Level::High, OutputConfig::default());
|
||||
let iface = SPIInterface::new(spi_dev, spi_dc);
|
||||
@@ -49,7 +50,7 @@ pub fn init_primary_lcd(
|
||||
let mut display = Ili9341::new(
|
||||
iface,
|
||||
reset_main,
|
||||
delay,
|
||||
&mut delay,
|
||||
Orientation::Portrait,
|
||||
DisplaySize240x320,
|
||||
)
|
||||
|
||||
+146
-1
@@ -1 +1,146 @@
|
||||
// Drivers nfc_pn532 module
|
||||
use alloc::vec::Vec;
|
||||
use core::convert::Infallible;
|
||||
use esp_hal::gpio::interconnect::{PeripheralInput, PeripheralOutput};
|
||||
use esp_hal::i2c::master::{Config as I2cConfig, I2c};
|
||||
use esp_hal::peripherals::I2C0;
|
||||
use esp_hal::time::{Duration, Instant, Rate};
|
||||
use log::{error, info};
|
||||
use pn532::i2c::I2CInterface;
|
||||
use pn532::requests::SAMMode;
|
||||
use pn532::{nb, Pn532, Request};
|
||||
|
||||
/// Timer implementation required by `pn532::CountDown`.
|
||||
pub struct TimerWrapper {
|
||||
start: Instant,
|
||||
duration: Duration,
|
||||
counter: u32,
|
||||
}
|
||||
|
||||
impl TimerWrapper {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
start: Instant::now(),
|
||||
duration: Duration::ZERO,
|
||||
counter: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TimerWrapper {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl pn532::CountDown for TimerWrapper {
|
||||
type Time = Duration;
|
||||
|
||||
fn start<T>(&mut self, timeout: T)
|
||||
where
|
||||
T: Into<Self::Time>,
|
||||
{
|
||||
self.start = Instant::now();
|
||||
self.duration = timeout.into();
|
||||
self.counter = 0;
|
||||
}
|
||||
|
||||
fn wait(&mut self) -> nb::Result<(), Infallible> {
|
||||
let elapsed = self.start.elapsed();
|
||||
self.counter += 1;
|
||||
if elapsed >= self.duration {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(nb::Error::WouldBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Pn532Device<'a> = Pn532<I2CInterface<I2c<'a, esp_hal::Blocking>>, TimerWrapper, 32>;
|
||||
|
||||
/// PN532 NFC reader driver.
|
||||
pub struct NfcPn532Driver<'a> {
|
||||
pn532: Pn532Device<'a>,
|
||||
}
|
||||
|
||||
impl<'a> NfcPn532Driver<'a> {
|
||||
pub fn new<SDA, SCL>(i2c0: I2C0<'static>, sda: SDA, scl: SCL) -> Self
|
||||
where
|
||||
SDA: PeripheralInput<'static> + PeripheralOutput<'static>,
|
||||
SCL: PeripheralInput<'static> + PeripheralOutput<'static>,
|
||||
{
|
||||
let config = I2cConfig::default().with_frequency(Rate::from_khz(20));
|
||||
let i2c = I2c::new(i2c0, config)
|
||||
.expect("Failed to init I2C")
|
||||
.with_sda(sda)
|
||||
.with_scl(scl);
|
||||
|
||||
let pn532 = Pn532::new(I2CInterface { i2c }, TimerWrapper::new());
|
||||
Self { pn532 }
|
||||
}
|
||||
|
||||
pub fn configure_sam(&mut self, timeout: Duration) -> Result<(), ()> {
|
||||
if let Err(e) = self.pn532.process(
|
||||
&Request::sam_configuration(SAMMode::Normal, false),
|
||||
0,
|
||||
timeout,
|
||||
) {
|
||||
error!("Could not initialize PN532: {e:?}");
|
||||
Err(())
|
||||
} else {
|
||||
info!("Successfully init'ed PN532");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll_target(&mut self, timeout: Duration) -> Result<(), ()> {
|
||||
match self.pn532.process(&Request::INLIST_ONE_ISO_A_TARGET, 23, timeout) {
|
||||
Ok(uid) => {
|
||||
info!("uid = {uid:?}");
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
info!("No NFC card found: {e:?}");
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_nfc_page(iteration: u8, bytes: &[u8]) -> Result<[u8; 4], ()> {
|
||||
let success = bytes.first().is_some_and(|x| *x == 0);
|
||||
if success {
|
||||
let mut arr = [0; 4];
|
||||
arr.copy_from_slice(&bytes[1..5]);
|
||||
Ok(arr)
|
||||
} else {
|
||||
info!("err {iteration}: {:02x?}", bytes);
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_card_data(&mut self) -> Result<Vec<u8>, ()> {
|
||||
let ms_1000 = Duration::from_millis(1000);
|
||||
self.poll_target(Duration::from_secs(10))?;
|
||||
|
||||
let mut data: Vec<u8> = Vec::with_capacity(858);
|
||||
|
||||
for i in 0x04..=230 {
|
||||
let mut parse_result = Err(());
|
||||
while parse_result.is_err() {
|
||||
let Ok(result) = self.pn532.process(&Request::ntag_read(i), 17, ms_1000) else {
|
||||
continue;
|
||||
};
|
||||
parse_result = Self::parse_nfc_page(i, result);
|
||||
}
|
||||
let bytes = parse_result.unwrap();
|
||||
data.extend(bytes);
|
||||
}
|
||||
|
||||
info!("Full data: {data:02x?}");
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn device_mut(&mut self) -> &mut Pn532Device<'a> {
|
||||
&mut self.pn532
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,2 +1,4 @@
|
||||
pub mod input;
|
||||
pub mod inputs;
|
||||
pub mod main_menu;
|
||||
pub mod navigation;
|
||||
pub mod state;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||
use esp_hal::peripherals::GPIO38;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum NavCommand {
|
||||
NextCard,
|
||||
PrevCard,
|
||||
Select,
|
||||
ScanTag,
|
||||
}
|
||||
|
||||
pub fn init_navigation_button(pin: GPIO38<'static>) -> Input<'static> {
|
||||
let button_config = InputConfig::default().with_pull(Pull::Up);
|
||||
Input::new(pin, button_config)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||
use esp_hal::peripherals::Peripherals;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum NavCommand {
|
||||
NextCard,
|
||||
PrevCard,
|
||||
Select,
|
||||
ScanTag,
|
||||
}
|
||||
|
||||
pub struct Inputs {
|
||||
pub up: Input<'static>,
|
||||
pub down: Input<'static>,
|
||||
pub left: Input<'static>,
|
||||
pub right: Input<'static>,
|
||||
pub back: Input<'static>,
|
||||
pub ok: Input<'static>,
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
use crate::navigation::inputs::Inputs;
|
||||
|
||||
pub const MAX_SELECTED: i8 = 3;
|
||||
|
||||
pub struct MainMenu {
|
||||
pub selected: i8,
|
||||
}
|
||||
|
||||
impl MainMenu {
|
||||
pub async fn display(self: &Self) {}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
use crate::navigation::inputs::Inputs;
|
||||
use crate::navigation::main_menu::{MAX_SELECTED, MainMenu};
|
||||
|
||||
use embassy_futures::select::Either6;
|
||||
use embassy_futures::select::select6;
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn run(mut inputs: Inputs) {
|
||||
let mut state = MainMenu { selected: 0 };
|
||||
|
||||
loop {
|
||||
let selection = select6(
|
||||
inputs.up.wait_for_low(),
|
||||
inputs.down.wait_for_low(),
|
||||
inputs.left.wait_for_low(),
|
||||
inputs.right.wait_for_low(),
|
||||
inputs.ok.wait_for_low(),
|
||||
inputs.back.wait_for_low(),
|
||||
)
|
||||
.await;
|
||||
|
||||
let value = match selection {
|
||||
Either6::First(_) => (state.selected.wrapping_sub(1)) % MAX_SELECTED,
|
||||
Either6::Second(_) => (state.selected.wrapping_add(1)) % MAX_SELECTED,
|
||||
_ => continue, // Either6::Third(_) => ,
|
||||
// Either6::Fourth(_) => (),
|
||||
// Either6::Fifth(_) => (),
|
||||
// Either6::Sixth(_) => (),
|
||||
};
|
||||
|
||||
state.selected = value;
|
||||
|
||||
state.display().await
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user