Add read/write for felica

felica types refactor
This commit is contained in:
2026-08-27 10:02:50 +08:00
parent 0810cdb892
commit 86373a2d33
19 changed files with 875 additions and 184 deletions
+14 -32
View File
@@ -27,31 +27,15 @@ const WRITE_FRAME_CAPACITY: usize = 64;
#[derive(Clone, Copy, Debug, Default)]
pub struct NoReset;
/// A PN532 reset pin (`RSTPD_N`, active-low).
///
/// Implemented for any [`OutputPin`] as well as for [`NoReset`] (which does
/// nothing). A reset pin is optional but strongly recommended: without a reset
/// pulse the PN532 can end up in an uninitialised state and NACK subsequent
/// commands (surfacing as `Error::Transport(AcknowledgeCheckFailed(Data))`).
pub trait ResetPin {
/// Assert reset (drive the pin low).
fn assert(&mut self);
/// Deassert reset (drive the pin high).
fn deassert(&mut self);
}
impl ErrorType for NoReset { type Error = Infallible; }
impl ResetPin for NoReset {
fn assert(&mut self) {}
fn deassert(&mut self) {}
}
impl<P: OutputPin> ResetPin for P {
fn assert(&mut self) {
let _ = self.set_low();
impl OutputPin for NoReset {
fn set_low(&mut self) -> Result<(), Self::Error> {
panic!("NoReset should not be used")
}
fn deassert(&mut self) {
let _ = self.set_high();
fn set_high(&mut self) -> Result<(), Self::Error> {
panic!("NoReset should not be used")
}
}
@@ -126,7 +110,7 @@ impl<I2C, D> I2cInterface<I2C, D, NoReset, NoIrq> {
}
}
impl<I2C, D, RST: ResetPin> I2cInterface<I2C, D, RST, NoIrq> {
impl<I2C, D, RST: OutputPin> I2cInterface<I2C, D, RST, NoIrq> {
/// Create an interface with a reset pin (`RSTPD_N`).
pub fn with_reset(i2c: I2C, delay: D, reset: RST) -> Self {
Self {
@@ -152,7 +136,7 @@ impl<I2C, D, IRQ: InputPin> I2cInterface<I2C, D, NoReset, IRQ> {
}
}
impl<I2C, D, RST: ResetPin, IRQ: InputPin> I2cInterface<I2C, D, RST, IRQ> {
impl<I2C, D, RST: OutputPin, IRQ: InputPin> I2cInterface<I2C, D, RST, IRQ> {
/// Create an interface with both a reset pin and an IRQ pin.
pub fn with_reset_irq(i2c: I2C, delay: D, reset: RST, irq: IRQ) -> Self {
Self {
@@ -176,7 +160,7 @@ impl<I2C, D, RST, IRQ> Interface for I2cInterface<I2C, D, RST, IRQ>
where
I2C: I2c,
D: DelayNs,
RST: ResetPin,
RST: OutputPin,
IRQ: InputPin,
{
type TransportError = I2C::Error;
@@ -184,10 +168,10 @@ where
fn begin(&mut self) -> Result<(), Error<Self::TransportError>> {
// Pulse RSTPD_N: high -> low -> wait -> high -> wait. This mirrors the
// Adafruit library's begin() reset sequence.
self.reset.deassert();
self.reset.assert();
self.reset.set_high().unwrap();
self.reset.set_low().unwrap();
self.delay.delay_ms(400);
self.reset.deassert();
self.reset.set_high().unwrap();
// Let the PN532 boot after the reset is released. The Adafruit library
// waits ~10 ms + a 500 ms wakeup here; give it a full 500 ms.
self.delay.delay_ms(500);
@@ -230,13 +214,11 @@ where
frame[idx] = (!sum).wrapping_add(1);
frame[idx + 1] = PN532_POSTAMBLE;
#[cfg(feature = "defmt")]
defmt::debug!("pn532: write cmd=0x{:02X} len={}", header[0], frame_len);
crate::debug!("pn532: write cmd=0x{:02X} len={}", header[0], frame_len);
self.i2c
.write(PN532_I2C_ADDRESS, &frame[..frame_len])
.map_err(Error::Transport)?;
#[cfg(feature = "defmt")]
defmt::debug!("pn532: write ACKed, reading ACK frame");
crate::debug!("pn532: write ACKed, reading ACK frame");
self.read_ack_frame()
}