Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6f43d1055
|
||
|
|
07c5210d7b |
Generated
+18
-1
@@ -96,6 +96,12 @@ dependencies = [
|
|||||||
"vsimd",
|
"vsimd",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitfield"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f798d2d157e547aa99aab0967df39edd0b70307312b6f8bd2848e6abe40896e0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitfield"
|
name = "bitfield"
|
||||||
version = "0.19.5"
|
version = "0.19.5"
|
||||||
@@ -321,6 +327,7 @@ dependencies = [
|
|||||||
"esp-hal-wifimanager",
|
"esp-hal-wifimanager",
|
||||||
"esp-println",
|
"esp-println",
|
||||||
"esp-rtos",
|
"esp-rtos",
|
||||||
|
"i2c-character-display",
|
||||||
"ili9341",
|
"ili9341",
|
||||||
"log",
|
"log",
|
||||||
"ndef",
|
"ndef",
|
||||||
@@ -1099,7 +1106,7 @@ version = "1.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2bfcf2a0842903717f4663f6a08512c32b0f6b2d7fb7db3c8a6895d2e6d49f72"
|
checksum = "2bfcf2a0842903717f4663f6a08512c32b0f6b2d7fb7db3c8a6895d2e6d49f72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitfield",
|
"bitfield 0.19.5",
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -1681,6 +1688,16 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "i2c-character-display"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86a620ec16541e28c0e52ce21cd23d734a5d7efaae3d609b2a58694b0ef67739"
|
||||||
|
dependencies = [
|
||||||
|
"bitfield 0.17.0",
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ ndef = "0.5.0"
|
|||||||
num_enum = { version = "0.7.6", default-features = false }
|
num_enum = { version = "0.7.6", default-features = false }
|
||||||
embassy-sync = "0.8.0"
|
embassy-sync = "0.8.0"
|
||||||
embedded-hal-async = "1.0.0"
|
embedded-hal-async = "1.0.0"
|
||||||
|
i2c-character-display = "0.5.1"
|
||||||
|
|
||||||
# For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html
|
# For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|||||||
+91
-80
@@ -1,82 +1,93 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"author": "CreatureDex",
|
"author": "CreatureDex",
|
||||||
"editor": "wokwi",
|
"editor": "wokwi",
|
||||||
"parts": [
|
"parts": [
|
||||||
{
|
{
|
||||||
"type": "board-esp32-s3-devkitc-1",
|
"type": "board-esp32-s3-devkitc-1",
|
||||||
"id": "esp1",
|
"id": "esp1",
|
||||||
"top": 67.2,
|
"top": 67.2,
|
||||||
"left": -263.96,
|
"left": -263.96,
|
||||||
"attrs": {}
|
"attrs": {}
|
||||||
},
|
},
|
||||||
{ "type": "wokwi-ili9341", "id": "lcd1", "top": -200.8, "left": 354.9, "attrs": {} },
|
{ "type": "wokwi-ili9341", "id": "lcd1", "top": -200.8, "left": 354.9, "attrs": {} },
|
||||||
{
|
{
|
||||||
"type": "wokwi-pushbutton",
|
"type": "wokwi-pushbutton",
|
||||||
"id": "btn-up",
|
"id": "btn-up",
|
||||||
"top": -99.4,
|
"top": -99.4,
|
||||||
"left": -76.8,
|
"left": -76.8,
|
||||||
"attrs": { "color": "RebeccaPurple", "xray": "1", "key": "1", "label": "Up" }
|
"attrs": { "color": "RebeccaPurple", "xray": "1", "key": "1", "label": "Up" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "wokwi-pushbutton",
|
"type": "wokwi-pushbutton",
|
||||||
"id": "btn-down",
|
"id": "btn-down",
|
||||||
"top": 25.4,
|
"top": 25.4,
|
||||||
"left": -76.8,
|
"left": -76.8,
|
||||||
"attrs": { "color": "green", "xray": "1", "key": "1", "label": "Down" }
|
"attrs": { "color": "green", "xray": "1", "key": "1", "label": "Down" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "wokwi-pushbutton",
|
"type": "wokwi-pushbutton",
|
||||||
"id": "btn-left",
|
"id": "btn-left",
|
||||||
"top": -32.2,
|
"top": -32.2,
|
||||||
"left": -163.2,
|
"left": -163.2,
|
||||||
"attrs": { "color": "yellow", "xray": "1", "key": "1", "label": "Left" }
|
"attrs": { "color": "yellow", "xray": "1", "key": "1", "label": "Left" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "wokwi-pushbutton",
|
"type": "wokwi-pushbutton",
|
||||||
"id": "btn-right",
|
"id": "btn-right",
|
||||||
"top": -32.2,
|
"top": -32.2,
|
||||||
"left": 19.2,
|
"left": 19.2,
|
||||||
"attrs": { "color": "red", "xray": "1", "key": "1", "label": "Right" }
|
"attrs": { "color": "red", "xray": "1", "key": "1", "label": "Right" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "wokwi-pushbutton",
|
"type": "wokwi-pushbutton",
|
||||||
"id": "btn-back",
|
"id": "btn-back",
|
||||||
"top": -99.4,
|
"top": -99.4,
|
||||||
"left": 115.2,
|
"left": 115.2,
|
||||||
"attrs": { "color": "Magenta", "xray": "1", "key": "1", "label": "Back" }
|
"attrs": { "color": "Magenta", "xray": "1", "key": "1", "label": "Back" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "wokwi-pushbutton",
|
"type": "wokwi-pushbutton",
|
||||||
"id": "btn-ok",
|
"id": "btn-ok",
|
||||||
"top": 25.4,
|
"top": 25.4,
|
||||||
"left": 115.2,
|
"left": 115.2,
|
||||||
"attrs": { "color": "Lime", "xray": "1", "key": "1", "label": "Ok" }
|
"attrs": { "color": "Lime", "xray": "1", "key": "1", "label": "Ok" }
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"connections": [
|
"type": "wokwi-lcd1602",
|
||||||
[ "esp1:TX", "$serialMonitor:RX", "", [] ],
|
"id": "lcd2",
|
||||||
[ "esp1:RX", "$serialMonitor:TX", "", [] ],
|
"top": -291.2,
|
||||||
[ "lcd1:VCC", "esp1:3V3", "red", [ "v19.2", "h-57.6", "v-105.6", "h-124.95" ] ],
|
"left": -167.2,
|
||||||
[ "lcd1:GND", "esp1:GND.2", "black", [ "v28.8", "h-76.8", "v-76.8" ] ],
|
"attrs": { "pins": "i2c" }
|
||||||
[ "lcd1:CS", "esp1:11", "orange", [ "v0" ] ],
|
}
|
||||||
[ "lcd1:D/C", "esp1:12", "gold", [ "v0" ] ],
|
],
|
||||||
[ "lcd1:RESET", "esp1:10", "brown", [ "v0" ] ],
|
"connections": [
|
||||||
[ "lcd1:MOSI", "esp1:35", "violet", [ "v105.6", "h-124.8", "v-144" ] ],
|
[ "esp1:TX", "$serialMonitor:RX", "", [] ],
|
||||||
[ "lcd1:SCK", "esp1:36", "white", [ "v115.2", "h-144", "v-86.4" ] ],
|
[ "esp1:RX", "$serialMonitor:TX", "", [] ],
|
||||||
[ "esp1:37", "lcd1:MISO", "magenta", [ "h57.6", "v105.6", "h172.8" ] ],
|
[ "lcd1:VCC", "esp1:3V3", "red", [ "v19.2", "h-57.6", "v-105.6", "h-124.95" ] ],
|
||||||
[ "btn-up:2.l", "esp1:38", "purple", [ "h-9.6", "v19.4" ] ],
|
[ "lcd1:GND", "esp1:GND.2", "black", [ "v28.8", "h-76.8", "v-76.8" ] ],
|
||||||
[ "btn-up:1.l", "esp1:GND.2", "black", [ "h0" ] ],
|
[ "lcd1:CS", "esp1:11", "orange", [ "v0" ] ],
|
||||||
[ "btn-down:1.l", "esp1:GND.2", "black", [ "h0" ] ],
|
[ "lcd1:D/C", "esp1:12", "gold", [ "v0" ] ],
|
||||||
[ "btn-down:2.l", "esp1:39", "green", [ "h-19.2", "v115.4" ] ],
|
[ "lcd1:RESET", "esp1:10", "brown", [ "v0" ] ],
|
||||||
[ "btn-left:2.l", "esp1:40", "yellow", [ "h0", "v173" ] ],
|
[ "lcd1:MOSI", "esp1:35", "violet", [ "v105.6", "h-124.8", "v-144" ] ],
|
||||||
[ "btn-left:1.l", "esp1:GND.2", "black", [ "h0" ] ],
|
[ "lcd1:SCK", "esp1:36", "white", [ "v115.2", "h-144", "v-86.4" ] ],
|
||||||
[ "btn-right:2.l", "esp1:41", "red", [ "h-19.2", "v153.8" ] ],
|
[ "esp1:37", "lcd1:MISO", "magenta", [ "h57.6", "v105.6", "h172.8" ] ],
|
||||||
[ "btn-right:1.l", "btn-left:1.r", "black", [ "h-96", "v28.8" ] ],
|
[ "btn-up:2.l", "esp1:38", "purple", [ "h-9.6", "v19.4" ] ],
|
||||||
[ "btn-back:2.l", "esp1:42", "Magenta", [ "h-19.2", "v211.58" ] ],
|
[ "btn-up:1.l", "esp1:GND.2", "black", [ "h0" ] ],
|
||||||
[ "btn-back:1.l", "btn-up:1.r", "black", [ "h0" ] ],
|
[ "btn-down:1.l", "esp1:GND.2", "black", [ "h0" ] ],
|
||||||
[ "btn-ok:1.l", "btn-down:1.r", "black", [ "h0" ] ],
|
[ "btn-down:2.l", "esp1:39", "green", [ "h-19.2", "v115.4" ] ],
|
||||||
[ "btn-ok:2.l", "esp1:45", "Lime", [ "h-9.6", "v173" ] ]
|
[ "btn-left:2.l", "esp1:40", "yellow", [ "h0", "v173" ] ],
|
||||||
],
|
[ "btn-left:1.l", "esp1:GND.2", "black", [ "h0" ] ],
|
||||||
"dependencies": {}
|
[ "btn-right:2.l", "esp1:41", "red", [ "h-19.2", "v153.8" ] ],
|
||||||
|
[ "btn-right:1.l", "btn-left:1.r", "black", [ "h-96", "v28.8" ] ],
|
||||||
|
[ "btn-back:2.l", "esp1:42", "Magenta", [ "h-19.2", "v211.58" ] ],
|
||||||
|
[ "btn-back:1.l", "btn-up:1.r", "black", [ "h0" ] ],
|
||||||
|
[ "btn-ok:1.l", "btn-down:1.r", "black", [ "h0" ] ],
|
||||||
|
[ "btn-ok:2.l", "esp1:45", "Lime", [ "h-9.6", "v173" ] ],
|
||||||
|
[ "lcd2:GND", "esp1:GND.2", "black", [ "h0" ] ],
|
||||||
|
[ "lcd2:VCC", "esp1:3V3.1", "red", [ "h0" ] ],
|
||||||
|
[ "lcd2:SDA", "esp1:17", "green", [ "h-134.4", "v413" ] ],
|
||||||
|
[ "lcd2:SCL", "esp1:18", "green", [ "h-124.8", "v38.7" ] ]
|
||||||
|
],
|
||||||
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
+26
-6
@@ -11,14 +11,19 @@ use alloc::boxed::Box;
|
|||||||
use creaturedex::card::decoder::split_nfc_hex;
|
use creaturedex::card::decoder::split_nfc_hex;
|
||||||
use creaturedex::card::model::Card;
|
use creaturedex::card::model::Card;
|
||||||
use creaturedex::display::primary_lcd::{PrimaryLcdDisplay, init_primary_lcd};
|
use creaturedex::display::primary_lcd::{PrimaryLcdDisplay, init_primary_lcd};
|
||||||
|
use creaturedex::display::tertiary_lcd::{init_tertiary_lcd, write_wrapped};
|
||||||
use creaturedex::drivers::nfc_pn532::NfcPn532Driver;
|
use creaturedex::drivers::nfc_pn532::NfcPn532Driver;
|
||||||
use creaturedex::navigation::inputs::Inputs;
|
use creaturedex::navigation::inputs::Inputs;
|
||||||
use creaturedex::navigation::navigation::{self, CARD_DATA};
|
use creaturedex::navigation::navigation::{self, CARD_DATA};
|
||||||
use creaturedex::network::wifi::setup_wifi;
|
use creaturedex::network::wifi::setup_wifi;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
|
use embedded_hal_bus::i2c::AtomicDevice;
|
||||||
|
use embedded_hal_bus::util::AtomicCell;
|
||||||
|
use esp_hal::Blocking;
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
use esp_hal::gpio::{Input, InputConfig, Pull};
|
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
|
use esp_hal::i2c::master::{Config as I2cConfig, I2c};
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
@@ -63,14 +68,29 @@ async fn main(spawner: Spawner) {
|
|||||||
peripherals.GPIO12, // shared dc
|
peripherals.GPIO12, // shared dc
|
||||||
)));
|
)));
|
||||||
|
|
||||||
setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await;
|
let config = I2cConfig::default().with_frequency(esp_hal::time::Rate::from_khz(20));
|
||||||
|
let i2c = match I2c::new(peripherals.I2C0, config) {
|
||||||
|
Ok(bus) => bus.with_sda(peripherals.GPIO17).with_scl(peripherals.GPIO18),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Shared I2C bus initialization failed for GPIO17/GPIO18: {e:?}");
|
||||||
|
panic!("Shared I2C bus initialization failed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let shared_i2c = Box::leak(Box::new(AtomicCell::new(i2c)));
|
||||||
|
log::info!("Shared I2C bus ready on GPIO17 (SDA) and GPIO18 (SCL)");
|
||||||
|
|
||||||
let mut nfc_driver =
|
let mut lcd = init_tertiary_lcd(AtomicDevice::new(shared_i2c));
|
||||||
NfcPn532Driver::new(peripherals.I2C0, peripherals.GPIO17, peripherals.GPIO18);
|
if let Err(_) = write_wrapped(&mut lcd, "Testing more than 16 chars what happens now?") {
|
||||||
|
log::error!("Tertiary LCD startup text write failed over shared I2C bus; check the shared bus, wiring, and device responses");
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup_wifi(peripherals.WIFI, peripherals.FLASH, &spawner).await;
|
||||||
|
|
||||||
|
let mut nfc_driver = NfcPn532Driver::new(AtomicDevice::new(shared_i2c));
|
||||||
if nfc_driver.configure_sam().await.is_ok() {
|
if nfc_driver.configure_sam().await.is_ok() {
|
||||||
log::info!("NFC SAM configuration successful");
|
log::info!("NFC SAM configuration successful on the shared I2C bus");
|
||||||
} else {
|
} else {
|
||||||
log::error!("NFC SAM configuration failed");
|
log::error!("NFC SAM configuration failed on the shared I2C bus");
|
||||||
}
|
}
|
||||||
|
|
||||||
let button_config = InputConfig::default().with_pull(Pull::Up);
|
let button_config = InputConfig::default().with_pull(Pull::Up);
|
||||||
@@ -90,7 +110,7 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn nfc_driver_task(mut nfc_driver: NfcPn532Driver<'static>) {
|
async fn nfc_driver_task(mut nfc_driver: NfcPn532Driver<AtomicDevice<'static, I2c<'static, Blocking>>>) {
|
||||||
loop {
|
loop {
|
||||||
while CARD_DATA.lock().await.is_none() {
|
while CARD_DATA.lock().await.is_none() {
|
||||||
match nfc_driver.read_card_data().await {
|
match nfc_driver.read_card_data().await {
|
||||||
|
|||||||
@@ -1 +1,88 @@
|
|||||||
// Tertiary LCD module
|
use embedded_hal::i2c::I2c;
|
||||||
|
use esp_hal::delay::Delay;
|
||||||
|
use i2c_character_display::{CharacterDisplayPCF8574T, LcdDisplayType};
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
pub type TertiaryLcd<I2C> = CharacterDisplayPCF8574T<I2C, Delay>;
|
||||||
|
|
||||||
|
pub fn init_tertiary_lcd<I2C>(i2c: I2C) -> TertiaryLcd<I2C>
|
||||||
|
where
|
||||||
|
I2C: I2c,
|
||||||
|
{
|
||||||
|
let mut lcd = CharacterDisplayPCF8574T::new(i2c, LcdDisplayType::Lcd16x2, Delay::new());
|
||||||
|
match lcd.init() {
|
||||||
|
Ok(()) => {
|
||||||
|
log::info!("I2C tertiary LCD initialized on PCF8574T at address 0x27");
|
||||||
|
lcd
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
error!("I2C tertiary LCD init failed on PCF8574T at address 0x27; check bus wiring, power, and device address");
|
||||||
|
panic!("tertiary LCD initialization failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_line<I2C>(
|
||||||
|
lcd: &mut TertiaryLcd<I2C>,
|
||||||
|
line: u8,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<(), i2c_character_display::CharacterDisplayError<I2C>>
|
||||||
|
where
|
||||||
|
I2C: I2c,
|
||||||
|
{
|
||||||
|
if let Err(e) = lcd.set_cursor(0, line) {
|
||||||
|
error!("I2C LCD cursor move failed on line {line}; bus or device may be unavailable");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
if let Err(e) = lcd.print(text) {
|
||||||
|
error!("I2C LCD print failed on line {line}; payload length={} and device may be busy or disconnected", text.len());
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_wrapped<I2C>(
|
||||||
|
lcd: &mut TertiaryLcd<I2C>,
|
||||||
|
text: &str,
|
||||||
|
) -> Result<(), i2c_character_display::CharacterDisplayError<I2C>>
|
||||||
|
where
|
||||||
|
I2C: I2c,
|
||||||
|
{
|
||||||
|
const DISPLAY_WIDTH: usize = 16;
|
||||||
|
const DISPLAY_ROWS: usize = 2;
|
||||||
|
|
||||||
|
if let Err(e) = lcd.clear() {
|
||||||
|
error!("I2C LCD clear failed before wrapped write; check the shared bus and display response");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut offset = 0;
|
||||||
|
for row in 0..DISPLAY_ROWS {
|
||||||
|
let remaining = &text[offset..];
|
||||||
|
if remaining.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let chunk = if remaining.len() > DISPLAY_WIDTH {
|
||||||
|
&remaining[..DISPLAY_WIDTH]
|
||||||
|
} else {
|
||||||
|
remaining
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = lcd.set_cursor(0, row as u8) {
|
||||||
|
error!("I2C LCD cursor move failed while writing wrapped row {row}; bus may be busy or device unresponsive");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
if let Err(e) = lcd.print(chunk) {
|
||||||
|
error!("I2C LCD wrapped write failed on row {row}; chunk length={} and text may exceed display width", chunk.len());
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
offset += chunk.len();
|
||||||
|
|
||||||
|
if offset >= text.len() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
+23
-27
@@ -1,9 +1,7 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use esp_hal::gpio::interconnect::{PeripheralInput, PeripheralOutput};
|
use embedded_hal::i2c::I2c;
|
||||||
use esp_hal::i2c::master::{Config as I2cConfig, I2c};
|
use esp_hal::time::{Duration, Instant};
|
||||||
use esp_hal::peripherals::I2C0;
|
|
||||||
use esp_hal::time::{Duration, Instant, Rate};
|
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use pn532::i2c::I2CInterface;
|
use pn532::i2c::I2CInterface;
|
||||||
use pn532::requests::SAMMode;
|
use pn532::requests::SAMMode;
|
||||||
@@ -55,25 +53,21 @@ impl pn532::CountDown for TimerWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Pn532Device<'a> = Pn532<I2CInterface<I2c<'a, esp_hal::Blocking>>, (), 32>;
|
pub type Pn532Device<I2C> = Pn532<I2CInterface<I2C>, (), 32>;
|
||||||
|
|
||||||
/// PN532 NFC reader driver.
|
/// PN532 NFC reader driver.
|
||||||
pub struct NfcPn532Driver<'a> {
|
pub struct NfcPn532Driver<I2C>
|
||||||
pn532: Pn532Device<'a>,
|
where
|
||||||
|
I2C: I2c,
|
||||||
|
{
|
||||||
|
pn532: Pn532Device<I2C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NfcPn532Driver<'a> {
|
impl<I2C> NfcPn532Driver<I2C>
|
||||||
pub fn new<SDA, SCL>(i2c0: I2C0<'static>, sda: SDA, scl: SCL) -> Self
|
where
|
||||||
where
|
I2C: I2c,
|
||||||
SDA: PeripheralInput<'static> + PeripheralOutput<'static>,
|
{
|
||||||
SCL: PeripheralInput<'static> + PeripheralOutput<'static>,
|
pub fn new(i2c: I2C) -> Self {
|
||||||
{
|
|
||||||
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_async(I2CInterface { i2c });
|
let pn532 = Pn532::new_async(I2CInterface { i2c });
|
||||||
Self { pn532 }
|
Self { pn532 }
|
||||||
}
|
}
|
||||||
@@ -83,10 +77,10 @@ impl<'a> NfcPn532Driver<'a> {
|
|||||||
&Request::sam_configuration(SAMMode::Normal, false),
|
&Request::sam_configuration(SAMMode::Normal, false),
|
||||||
0,
|
0,
|
||||||
).await {
|
).await {
|
||||||
error!("Could not initialize PN532: {e:?}");
|
error!("PN532 SAM configuration failed over I2C: {e:?}");
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
info!("Successfully init'ed PN532");
|
info!("PN532 SAM configuration successful on shared I2C bus");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,11 +88,11 @@ impl<'a> NfcPn532Driver<'a> {
|
|||||||
pub async fn poll_target(&mut self) -> Result<(), ()> {
|
pub async fn poll_target(&mut self) -> Result<(), ()> {
|
||||||
match self.pn532.process_async(&Request::INLIST_ONE_ISO_A_TARGET, 23).await {
|
match self.pn532.process_async(&Request::INLIST_ONE_ISO_A_TARGET, 23).await {
|
||||||
Ok(uid) => {
|
Ok(uid) => {
|
||||||
info!("uid = {uid:?}");
|
info!("PN532 detected NFC target UID: {uid:?}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!("No NFC card found: {e:?}");
|
info!("No NFC card found on shared I2C bus: {e:?}");
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,12 +111,14 @@ impl<'a> NfcPn532Driver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read_card_data(&mut self) -> Result<Vec<u8>, ()> {
|
pub async fn read_card_data(&mut self) -> Result<Vec<u8>, ()> {
|
||||||
self.poll_target().await?;
|
if let Err(e) = self.poll_target().await {
|
||||||
|
error!("PN532 I2C target poll failed before reading card data: {e:?}");
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
let mut data: Vec<u8> = Vec::with_capacity(858);
|
let mut data: Vec<u8> = Vec::with_capacity(858);
|
||||||
|
|
||||||
for i in 0x0B..=230 {
|
for i in 0x0B..=230 {
|
||||||
|
|
||||||
let mut parse_result = Err(());
|
let mut parse_result = Err(());
|
||||||
while parse_result.is_err() {
|
while parse_result.is_err() {
|
||||||
let Ok(result) = self.pn532.process_async(&Request::ntag_read(i), 17).await else {
|
let Ok(result) = self.pn532.process_async(&Request::ntag_read(i), 17).await else {
|
||||||
@@ -139,11 +135,11 @@ impl<'a> NfcPn532Driver<'a> {
|
|||||||
data.extend(bytes);
|
data.extend(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Full data: {data:02x?}");
|
info!("PN532 full card payload read over I2C: {:02x?}", data);
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_mut(&mut self) -> &mut Pn532Device<'a> {
|
pub fn device_mut(&mut self) -> &mut Pn532Device<I2C> {
|
||||||
&mut self.pn532
|
&mut self.pn532
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ impl Inputs {
|
|||||||
match index {
|
match index {
|
||||||
0 => ButtonAction::Up,
|
0 => ButtonAction::Up,
|
||||||
1 => ButtonAction::Down,
|
1 => ButtonAction::Down,
|
||||||
2 => ButtonAction::Back,
|
2 => ButtonAction::Left,
|
||||||
3 => ButtonAction::Ok,
|
3 => ButtonAction::Right,
|
||||||
4 => ButtonAction::Ok,
|
4 => ButtonAction::Ok,
|
||||||
5 => ButtonAction::Back,
|
5 => ButtonAction::Back,
|
||||||
id => panic!("Unknown button {id} pressed"),
|
id => panic!("Unknown button {id} pressed"),
|
||||||
|
|||||||
Reference in New Issue
Block a user