Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfe1c6b11a
|
||
|
|
e477462783
|
||
|
|
020ca5cd4b | ||
|
|
7ce3a60a08 | ||
|
|
78765ce595 |
Generated
+168
@@ -229,6 +229,16 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "ch1115"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/ede1998/ch1115.git?rev=2d3a3ba38050efe012e6a210afe3e125ec280c37#2d3a3ba38050efe012e6a210afe3e125ec280c37"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"embedded-graphics-core",
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.3.0"
|
||||
@@ -303,6 +313,7 @@ name = "creaturedex"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"ch1115",
|
||||
"critical-section",
|
||||
"display-interface-spi",
|
||||
"embassy-executor",
|
||||
@@ -311,6 +322,7 @@ dependencies = [
|
||||
"embedded-graphics-core",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-bus",
|
||||
"embedded-hal-compat",
|
||||
"embedded-io 0.7.1",
|
||||
"esp-alloc",
|
||||
"esp-bootloader-esp-idf",
|
||||
@@ -320,6 +332,10 @@ dependencies = [
|
||||
"esp-rtos",
|
||||
"ili9341",
|
||||
"log",
|
||||
"ndef",
|
||||
"pn532",
|
||||
"sh1106",
|
||||
"ssd1306",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -568,6 +584,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"
|
||||
@@ -584,6 +620,17 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ba2aab1ef3793e6f7804162debb5ac5edb93b3d650fbcc5aeb72fcd0e6c03a0"
|
||||
|
||||
[[package]]
|
||||
name = "display-interface-i2c"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d964fa85bbbb5a6ecd06e58699407ac5dc3e3ad72dac0ab7e6b0d00a1cd262d"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "display-interface-spi"
|
||||
version = "0.5.0"
|
||||
@@ -923,6 +970,17 @@ dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal-compat"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08ecac72f6be75ad2d4809c9f07d45502e2e5c9a4e9579077f28d7135de81df3"
|
||||
dependencies = [
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.4.0"
|
||||
@@ -1894,6 +1952,30 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
|
||||
|
||||
[[package]]
|
||||
name = "manyhow"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587"
|
||||
dependencies = [
|
||||
"manyhow-macros",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "manyhow-macros"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495"
|
||||
dependencies = [
|
||||
"proc-macro-utils",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.2.0"
|
||||
@@ -1909,6 +1991,19 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
|
||||
|
||||
[[package]]
|
||||
name = "maybe-async-cfg"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627"
|
||||
dependencies = [
|
||||
"manyhow",
|
||||
"proc-macro2",
|
||||
"pulldown-cmark",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
@@ -1980,6 +2075,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 +2690,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"
|
||||
@@ -2647,6 +2763,17 @@ dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-utils"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
@@ -2676,6 +2803,17 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
|
||||
dependencies = [
|
||||
"bitflags 2.13.1",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
@@ -3002,6 +3140,16 @@ dependencies = [
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sh1106"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc12a0563ec9b3b1f99b1f64613581ebbade1347416a34766564f406c15d1bf3"
|
||||
dependencies = [
|
||||
"embedded-graphics-core",
|
||||
"embedded-hal 0.2.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
@@ -3090,6 +3238,20 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c"
|
||||
|
||||
[[package]]
|
||||
name = "ssd1306"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ed51935bdc6e9e976d3d9a747e768589eaea0cf26f483213bfededc947c8624"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"display-interface-i2c",
|
||||
"display-interface-spi",
|
||||
"embedded-graphics-core",
|
||||
"embedded-hal 1.0.0",
|
||||
"maybe-async-cfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
@@ -3357,6 +3519,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-id-start"
|
||||
version = "1.4.0"
|
||||
|
||||
+10
-1
@@ -34,13 +34,22 @@ esp-hal-wifimanager = { git = "https://github.com/InvisibleUSA/esp-hal-wifimanag
|
||||
esp-println = { version = "0.17.0", features = ["esp32s3", "log-04"] }
|
||||
display-interface-spi = "0.5.0"
|
||||
ili9341 = "0.6.0"
|
||||
ssd1306 = "0.9.0"
|
||||
embedded-hal = "1.0.0"
|
||||
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"
|
||||
ch1115 = { version = "0.1.2", features = ["graphics"] }
|
||||
sh1106 = "0.5.0"
|
||||
embedded-hal-compat = "0.13.0"
|
||||
|
||||
|
||||
[patch.crates-io]
|
||||
ch1115 = { git = "https://github.com/ede1998/ch1115.git", rev = "2d3a3ba38050efe012e6a210afe3e125ec280c37" }
|
||||
|
||||
# For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html
|
||||
[profile.dev]
|
||||
# The default debug profile is too slow and too big for resource-constrained devices.
|
||||
@@ -55,4 +64,4 @@ opt-level = 's'
|
||||
|
||||
[features]
|
||||
default = []
|
||||
wokwi = []
|
||||
wokwi = []
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![deny(
|
||||
clippy::mem_forget,
|
||||
reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
|
||||
holding buffers for the duration of a data transfer."
|
||||
)]
|
||||
|
||||
use ch1115::Ch1115;
|
||||
use core::cell::RefCell;
|
||||
use creaturedex::display::shared_bus::SharedPin;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::Timer;
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::{
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
prelude::*,
|
||||
text::Text,
|
||||
};
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig};
|
||||
use esp_hal::spi::Mode;
|
||||
use esp_hal::spi::master::{Config as SpiConfig, Spi};
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use log::error;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||
error!("{}", panic_info);
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
#[esp_rtos::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
esp_println::logger::init_logger_from_env();
|
||||
|
||||
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: 73744);
|
||||
|
||||
let mut delay = Delay::new();
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let sw_interrupt =
|
||||
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
||||
|
||||
let spi = peripherals.SPI2;
|
||||
let sck = peripherals.GPIO36;
|
||||
let mosi = peripherals.GPIO35;
|
||||
let cs = peripherals.GPIO13;
|
||||
let reset = peripherals.GPIO10;
|
||||
let dc = peripherals.GPIO12;
|
||||
let miso = peripherals.GPIO37;
|
||||
|
||||
let cs = Output::new(cs, Level::High, OutputConfig::default());
|
||||
let dc = Output::new(dc, Level::Low, OutputConfig::default());
|
||||
let reset = Output::new(reset, Level::High, OutputConfig::default());
|
||||
|
||||
let spi = Spi::new(
|
||||
spi,
|
||||
SpiConfig::default()
|
||||
.with_frequency(Rate::from_khz(5000))
|
||||
.with_mode(Mode::_0),
|
||||
)
|
||||
.unwrap()
|
||||
.with_sck(sck)
|
||||
.with_mosi(mosi)
|
||||
.with_miso(miso);
|
||||
|
||||
let spi = RefCell::new(spi);
|
||||
let spi_dev = embedded_hal_bus::spi::RefCellDevice::new(&spi, cs, delay).unwrap();
|
||||
let interface = display_interface_spi::SPIInterface::new(spi_dev, dc);
|
||||
|
||||
let mut display = Ch1115::new(interface, reset, ch1115::Size128x64);
|
||||
display.init(&mut delay).unwrap();
|
||||
|
||||
|
||||
loop {
|
||||
log::info!("Init finished");
|
||||
let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
|
||||
Text::new("Hello OLED", Point::new(10, 20), text_style)
|
||||
.draw(&mut display)
|
||||
.unwrap();
|
||||
|
||||
display.flush().unwrap();
|
||||
Timer::after_millis(1000).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![deny(
|
||||
clippy::mem_forget,
|
||||
reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
|
||||
holding buffers for the duration of a data transfer."
|
||||
)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::Timer;
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::{
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
prelude::*,
|
||||
text::Text,
|
||||
};
|
||||
use embedded_hal_compat::ReverseCompat;
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig};
|
||||
use esp_hal::spi::Mode;
|
||||
use esp_hal::spi::master::{Config as SpiConfig, Spi};
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use log::error;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||
error!("{}", panic_info);
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
// This creates a defaembedded_hal_compatedReverseCompat::reverse(Output::new(cs,Level::High,OutputConfig::default()))vel::High,OutputConfig::default())) more information see: embedded_hal_compat::ForwardCompat::forward(Spi::new(spi,SpiConfig::default().with_frequency(Rate::from_khz(100)).with_mode(Mode::_0),).unwrap().with_sck(sck).with_mosi(mosi))rward(Spi::new(spi,SpiConfig::default().with_frequency(Rate::from_khz(100)).with_mode(Mode::_0),).unwrap().with_sck(sck).with_mosi(mosi)) to allocate larger buffers etc. in main"
|
||||
#[esp_rtos::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
esp_println::logger::init_logger_from_env();
|
||||
|
||||
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: 73744);
|
||||
|
||||
let delay = Delay::new();
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let sw_interrupt =
|
||||
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
||||
|
||||
let spi = peripherals.SPI2;
|
||||
let sck = peripherals.GPIO36;
|
||||
let mosi = peripherals.GPIO35;
|
||||
let cs = peripherals.GPIO13;
|
||||
let reset = peripherals.GPIO10;
|
||||
let dc = peripherals.GPIO12;
|
||||
let miso = peripherals.GPIO37;
|
||||
|
||||
let cs = Output::new(cs, Level::High, OutputConfig::default()).reverse_cell();
|
||||
let dc = Output::new(dc, Level::Low, OutputConfig::default()).reverse_cell();
|
||||
let mut reset = Output::new(reset, Level::High, OutputConfig::default());
|
||||
|
||||
let spi = Spi::new(
|
||||
spi,
|
||||
SpiConfig::default()
|
||||
.with_frequency(Rate::from_khz(5000))
|
||||
.with_mode(Mode::_0),
|
||||
)
|
||||
.unwrap()
|
||||
.with_sck(sck)
|
||||
.with_mosi(mosi)
|
||||
.with_miso(miso)
|
||||
.reverse();
|
||||
|
||||
let mut display: sh1106::mode::GraphicsMode<_> =
|
||||
sh1106::Builder::new().connect_spi(spi, dc, cs).into();
|
||||
|
||||
display.init().unwrap();
|
||||
|
||||
// Hard reset the OLED
|
||||
reset.set_high();
|
||||
delay.delay_millis(1);
|
||||
reset.set_low();
|
||||
delay.delay_millis(10);
|
||||
reset.set_high();
|
||||
|
||||
display.flush().unwrap();
|
||||
|
||||
display.set_pixel(10, 20, 1);
|
||||
|
||||
display.flush().unwrap();
|
||||
|
||||
let mut oled = display;
|
||||
|
||||
oled.clear();
|
||||
|
||||
let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
|
||||
Text::new("Hello OLED", Point::new(10, 20), text_style)
|
||||
.draw(&mut oled)
|
||||
.unwrap();
|
||||
|
||||
oled.flush().unwrap();
|
||||
|
||||
loop {
|
||||
log::info!("Init finished");
|
||||
Timer::after_millis(1000).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![deny(
|
||||
clippy::mem_forget,
|
||||
reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
|
||||
holding buffers for the duration of a data transfer."
|
||||
)]
|
||||
#![deny(clippy::large_stack_frames)]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::Timer;
|
||||
use embedded_graphics::draw_target::DrawTarget;
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::text::Text;
|
||||
use embedded_graphics::{
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use core::cell::RefCell;
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig};
|
||||
use esp_hal::spi::Mode;
|
||||
use esp_hal::spi::master::{Config as SpiConfig, Spi};
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use log::error;
|
||||
use ssd1306::Ssd1306;
|
||||
use ssd1306::mode::DisplayConfig;
|
||||
use ssd1306::rotation::DisplayRotation;
|
||||
use ssd1306::size::DisplaySize128x64;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||
error!("{}", panic_info);
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
// This creates a defaembedded_hal_compatedReverseCompat::reverse(Output::new(cs,Level::High,OutputConfig::default()))vel::High,OutputConfig::default())) more information see: embedded_hal_compat::ForwardCompat::forward(Spi::new(spi,SpiConfig::default().with_frequency(Rate::from_khz(100)).with_mode(Mode::_0),).unwrap().with_sck(sck).with_mosi(mosi))rward(Spi::new(spi,SpiConfig::default().with_frequency(Rate::from_khz(100)).with_mode(Mode::_0),).unwrap().with_sck(sck).with_mosi(mosi)) to allocate larger buffers etc. in main"
|
||||
#[esp_rtos::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
esp_println::logger::init_logger_from_env();
|
||||
|
||||
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: 73744);
|
||||
|
||||
let mut delay = Delay::new();
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let sw_interrupt =
|
||||
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
||||
|
||||
let spi = peripherals.SPI2;
|
||||
let sck = peripherals.GPIO36;
|
||||
let mosi = peripherals.GPIO35;
|
||||
let cs = peripherals.GPIO13;
|
||||
let reset = peripherals.GPIO10;
|
||||
let dc = peripherals.GPIO12;
|
||||
let miso = peripherals.GPIO37;
|
||||
|
||||
let cs = Output::new(cs, Level::High, OutputConfig::default());
|
||||
let dc = Output::new(dc, Level::Low, OutputConfig::default());
|
||||
let mut reset = Output::new(reset, Level::High, OutputConfig::default());
|
||||
|
||||
let spi = Spi::new(
|
||||
spi,
|
||||
SpiConfig::default()
|
||||
.with_frequency(Rate::from_khz(5000))
|
||||
.with_mode(Mode::_0),
|
||||
)
|
||||
.unwrap()
|
||||
.with_sck(sck)
|
||||
.with_mosi(mosi)
|
||||
.with_miso(miso);
|
||||
|
||||
let spi = RefCell::new(spi);
|
||||
let spi_dev = embedded_hal_bus::spi::RefCellDevice::new(&spi, cs, delay).unwrap();
|
||||
let interface = display_interface_spi::SPIInterface::new(spi_dev, dc);
|
||||
let mut display = Ssd1306::new(
|
||||
interface,
|
||||
DisplaySize128x64,
|
||||
DisplayRotation::Rotate0,
|
||||
)
|
||||
.into_buffered_graphics_mode();
|
||||
|
||||
display.reset(&mut reset, &mut delay).unwrap();
|
||||
display.init().unwrap();
|
||||
display.clear(BinaryColor::Off).unwrap();
|
||||
|
||||
|
||||
let mut oled = display;
|
||||
|
||||
let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
|
||||
Text::new("Hello OLED", Point::new(10, 20), text_style)
|
||||
.draw(&mut oled)
|
||||
.unwrap();
|
||||
|
||||
oled.flush().unwrap();
|
||||
|
||||
loop {
|
||||
log::info!("Init finished");
|
||||
Timer::after_millis(1000).await;
|
||||
}
|
||||
}
|
||||
+39
-22
@@ -8,18 +8,26 @@
|
||||
#![deny(clippy::large_stack_frames)]
|
||||
|
||||
use creaturedex::card::mock::{MOCK_PAYLOAD, MOCK_PAYLOAD2};
|
||||
use creaturedex::display::primary_lcd::init_primary_lcd;
|
||||
use creaturedex::display::shared_bus::init_dual_displays;
|
||||
|
||||
use creaturedex::display::views::card_view::render_nfc_payload;
|
||||
use creaturedex::drivers::nfc_pn532::NfcPn532Driver;
|
||||
use creaturedex::navigation::input::init_navigation_button;
|
||||
use creaturedex::navigation::state::NavigationState;
|
||||
use creaturedex::network::wifi::setup_wifi;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::Timer;
|
||||
use embedded_graphics::draw_target::DrawTarget;
|
||||
use embedded_graphics::pixelcolor::Rgb565;
|
||||
use embedded_graphics::pixelcolor::{BinaryColor, Rgb565};
|
||||
use embedded_graphics::prelude::RgbColor;
|
||||
use embedded_graphics::{
|
||||
mono_font::{MonoTextStyle, ascii::FONT_6X10},
|
||||
prelude::*,
|
||||
text::Text,
|
||||
};
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::time::Duration;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use log::error;
|
||||
|
||||
@@ -66,35 +74,44 @@ async fn main(spawner: Spawner) {
|
||||
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
||||
|
||||
let mut display = init_primary_lcd(
|
||||
let (mut display, mut oled) = init_dual_displays(
|
||||
peripherals.SPI2,
|
||||
peripherals.GPIO36,
|
||||
peripherals.GPIO35,
|
||||
peripherals.GPIO37,
|
||||
peripherals.GPIO11,
|
||||
peripherals.GPIO10,
|
||||
peripherals.GPIO12,
|
||||
peripherals.GPIO36, // sck
|
||||
peripherals.GPIO35, // mosi
|
||||
peripherals.GPIO37, // miso
|
||||
peripherals.GPIO11, // primary cs
|
||||
peripherals.GPIO13, // oled cs
|
||||
peripherals.GPIO10, // shared reset
|
||||
peripherals.GPIO12, // shared dc
|
||||
&mut delay,
|
||||
);
|
||||
|
||||
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
|
||||
};
|
||||
oled.clear(BinaryColor::Off).unwrap();
|
||||
|
||||
render_nfc_payload(&mut display, payload);
|
||||
}
|
||||
let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
|
||||
Text::new("Hello OLED", Point::new(10, 20), text_style)
|
||||
.draw(&mut oled)
|
||||
.unwrap();
|
||||
oled.flush().unwrap();
|
||||
|
||||
let text_style = MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE);
|
||||
display.clear_screen(0).unwrap();
|
||||
Text::new("Hello OLED", Point::new(10, 20), text_style).draw(&mut display).unwrap();
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
loop {
|
||||
Timer::after_millis(10).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
pub mod palette;
|
||||
pub mod primary_lcd;
|
||||
pub mod secondary_oled;
|
||||
pub mod shared_bus;
|
||||
pub mod sprite;
|
||||
pub mod tertiary_lcd;
|
||||
pub mod views;
|
||||
|
||||
|
||||
+26
-36
@@ -1,54 +1,42 @@
|
||||
use core::cell::RefCell;
|
||||
use display_interface_spi::SPIInterface;
|
||||
use embedded_graphics::draw_target::DrawTarget;
|
||||
use embedded_graphics::pixelcolor::Rgb565;
|
||||
use embedded_graphics::prelude::RgbColor;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_hal::digital::OutputPin as EhOutputPin;
|
||||
use embedded_hal_bus::spi::RefCellDevice;
|
||||
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::time::Rate;
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig, OutputPin};
|
||||
use ili9341::{DisplaySize240x320, Ili9341, Orientation};
|
||||
|
||||
pub type PrimaryLcdDisplay<'a> = Ili9341<
|
||||
pub type PrimaryLcdDisplay<'a, BUS, DC, RES> = Ili9341<
|
||||
SPIInterface<
|
||||
ExclusiveDevice<Spi<'a, esp_hal::Blocking>, Output<'a>, Delay>,
|
||||
Output<'a>,
|
||||
RefCellDevice<'a, BUS, Output<'a>, Delay>,
|
||||
DC,
|
||||
>,
|
||||
Output<'a>,
|
||||
RES,
|
||||
>;
|
||||
|
||||
pub fn init_primary_lcd(
|
||||
spi2: SPI2<'static>,
|
||||
sck: GPIO36<'static>,
|
||||
mosi: GPIO35<'static>,
|
||||
miso: GPIO37<'static>,
|
||||
cs: GPIO11<'static>,
|
||||
reset: GPIO10<'static>,
|
||||
dc: GPIO12<'static>,
|
||||
pub fn init_primary_lcd_on_bus<'a, BUS, CS, RES, DC>(
|
||||
spi_bus: &'a RefCell<BUS>,
|
||||
cs: CS,
|
||||
reset: RES,
|
||||
dc: DC,
|
||||
delay: &mut Delay,
|
||||
) -> PrimaryLcdDisplay<'static> {
|
||||
let freq = Rate::from_khz(60_000);
|
||||
log::info!("Display freq: {freq}");
|
||||
|
||||
let spi_bus = Spi::new(
|
||||
spi2,
|
||||
Config::default().with_frequency(freq).with_mode(Mode::_0),
|
||||
)
|
||||
.unwrap()
|
||||
.with_sck(sck)
|
||||
.with_mosi(mosi)
|
||||
.with_miso(miso);
|
||||
|
||||
let cs_main = Output::new(cs, Level::High, OutputConfig::default());
|
||||
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);
|
||||
) -> PrimaryLcdDisplay<'a, BUS, DC, RES>
|
||||
where
|
||||
BUS: embedded_hal::spi::SpiBus,
|
||||
CS: OutputPin + 'static,
|
||||
RES: EhOutputPin,
|
||||
DC: EhOutputPin,
|
||||
{
|
||||
let cs_pin = Output::new(cs, Level::High, OutputConfig::default());
|
||||
let spi_dev = RefCellDevice::new(spi_bus, cs_pin, *delay).unwrap();
|
||||
let iface = SPIInterface::new(spi_dev, dc);
|
||||
|
||||
let mut display = Ili9341::new(
|
||||
iface,
|
||||
reset_main,
|
||||
reset,
|
||||
delay,
|
||||
Orientation::Portrait,
|
||||
DisplaySize240x320,
|
||||
@@ -58,3 +46,5 @@ pub fn init_primary_lcd(
|
||||
display.clear(Rgb565::BLACK).unwrap();
|
||||
display
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1 +1,54 @@
|
||||
// Secondary OLED module
|
||||
use core::cell::RefCell;
|
||||
use display_interface_spi::SPIInterface;
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use embedded_graphics::prelude::*;
|
||||
use embedded_hal::digital::OutputPin as EhOutputPin;
|
||||
use embedded_hal_bus::spi::RefCellDevice;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig, OutputPin};
|
||||
use ssd1306::mode::BufferedGraphicsMode;
|
||||
use ssd1306::prelude::*;
|
||||
use ssd1306::Ssd1306;
|
||||
|
||||
pub type SecondaryOledDisplay<'a, BUS, DC> = Ssd1306<
|
||||
SPIInterface<
|
||||
RefCellDevice<'a, BUS, Output<'a>, Delay>,
|
||||
DC,
|
||||
>,
|
||||
DisplaySize128x64,
|
||||
BufferedGraphicsMode<DisplaySize128x64>,
|
||||
>;
|
||||
|
||||
pub fn init_secondary_oled_on_bus<'a, BUS, CS, RES, DC>(
|
||||
spi_bus: &'a RefCell<BUS>,
|
||||
cs: CS,
|
||||
mut res: RES,
|
||||
dc: DC,
|
||||
delay: &mut Delay,
|
||||
) -> SecondaryOledDisplay<'a, BUS, DC>
|
||||
where
|
||||
BUS: embedded_hal::spi::SpiBus,
|
||||
CS: OutputPin + 'static,
|
||||
RES: EhOutputPin,
|
||||
DC: EhOutputPin,
|
||||
{
|
||||
let cs_pin = Output::new(cs, Level::High, OutputConfig::default());
|
||||
let spi_dev = RefCellDevice::new(spi_bus, cs_pin, *delay).unwrap();
|
||||
let interface = SPIInterface::new(spi_dev, dc);
|
||||
|
||||
let mut display = Ssd1306::new(
|
||||
interface,
|
||||
DisplaySize128x64,
|
||||
DisplayRotation::Rotate0,
|
||||
)
|
||||
.into_buffered_graphics_mode();
|
||||
|
||||
display.reset(&mut res, delay).unwrap();
|
||||
display.init().unwrap();
|
||||
display.clear(BinaryColor::Off).unwrap();
|
||||
display.flush().unwrap();
|
||||
|
||||
display
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
use alloc::boxed::Box;
|
||||
use core::cell::RefCell;
|
||||
use embedded_hal::digital::{ErrorType, OutputPin as EhOutputPin, PinState};
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::gpio::interconnect::{PeripheralInput, PeripheralOutput};
|
||||
use esp_hal::gpio::{Level, Output, OutputConfig, OutputPin};
|
||||
use esp_hal::spi::master::{Config as SpiConfig, Spi};
|
||||
use esp_hal::spi::Mode;
|
||||
use esp_hal::time::Rate;
|
||||
use crate::display::primary_lcd::{init_primary_lcd_on_bus, PrimaryLcdDisplay};
|
||||
|
||||
use crate::display::secondary_oled::{init_secondary_oled_on_bus, SecondaryOledDisplay};
|
||||
|
||||
pub struct SharedPin<'a>(pub &'a RefCell<Output<'static>>);
|
||||
|
||||
impl<'a> ErrorType for SharedPin<'a> {
|
||||
type Error = core::convert::Infallible;
|
||||
}
|
||||
|
||||
impl<'a> EhOutputPin for SharedPin<'a> {
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.0.borrow_mut().set_low();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.0.borrow_mut().set_high();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_state(&mut self, state: PinState) -> Result<(), Self::Error> {
|
||||
self.0.borrow_mut().set_state(state);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub type DisplaySpiBus = Spi<'static, esp_hal::Blocking>;
|
||||
pub type DualPrimaryDisplay<'a> = PrimaryLcdDisplay<'a, DisplaySpiBus, SharedPin<'a>, SharedPin<'a>>;
|
||||
pub type DualSecondaryDisplay<'a> = SecondaryOledDisplay<'a, DisplaySpiBus, SharedPin<'a>>;
|
||||
|
||||
pub fn init_dual_displays<SPI, SCK, MOSI, MISO, CS1, CS2, RES, DC>(
|
||||
spi_peripheral: SPI,
|
||||
sck: SCK,
|
||||
mosi: MOSI,
|
||||
miso: MISO,
|
||||
cs_primary: CS1,
|
||||
cs_secondary: CS2,
|
||||
reset_pin: RES,
|
||||
dc_pin: DC,
|
||||
delay: &mut Delay,
|
||||
) -> (DualPrimaryDisplay<'static>, DualSecondaryDisplay<'static>)
|
||||
|
||||
where
|
||||
SPI: esp_hal::spi::master::Instance + 'static,
|
||||
SCK: PeripheralOutput<'static>,
|
||||
MOSI: PeripheralOutput<'static>,
|
||||
MISO: PeripheralInput<'static>,
|
||||
CS1: OutputPin + 'static,
|
||||
CS2: OutputPin + 'static,
|
||||
RES: OutputPin + 'static,
|
||||
DC: OutputPin + 'static,
|
||||
{
|
||||
let spi = Spi::new(
|
||||
spi_peripheral,
|
||||
SpiConfig::default().with_frequency(Rate::from_khz(20_000)).with_mode(Mode::_0),
|
||||
)
|
||||
.unwrap()
|
||||
.with_sck(sck)
|
||||
.with_mosi(mosi)
|
||||
.with_miso(miso);
|
||||
|
||||
let bus_static: &'static RefCell<DisplaySpiBus> = Box::leak(Box::new(RefCell::new(spi)));
|
||||
let reset_static: &'static RefCell<Output<'static>> = Box::leak(Box::new(RefCell::new(
|
||||
Output::new(reset_pin, Level::High, OutputConfig::default()),
|
||||
)));
|
||||
let dc_static: &'static RefCell<Output<'static>> = Box::leak(Box::new(RefCell::new(
|
||||
Output::new(dc_pin, Level::High, OutputConfig::default()),
|
||||
)));
|
||||
|
||||
let primary = init_primary_lcd_on_bus(
|
||||
bus_static,
|
||||
cs_primary,
|
||||
SharedPin(reset_static),
|
||||
SharedPin(dc_static),
|
||||
delay,
|
||||
);
|
||||
|
||||
let secondary = init_secondary_oled_on_bus(
|
||||
bus_static,
|
||||
cs_secondary,
|
||||
SharedPin(reset_static),
|
||||
SharedPin(dc_static),
|
||||
delay,
|
||||
);
|
||||
|
||||
(primary, secondary)
|
||||
}
|
||||
|
||||
+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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user