esp_hal_mfrc522/
consts.rs

1// FROM: https://github.com/OSSLibraries/Arduino_MFRC522v2/blob/master/src/MFRC522Constants.h
2
3#[derive(Debug, Clone)]
4pub struct Uid {
5    pub size: u8,
6    pub uid_bytes: [u8; 10],
7    pub sak: u8,
8}
9
10impl Uid {
11    pub fn get_number(&self) -> u128 {
12        match self.size {
13            4 => u32::from_le_bytes(self.uid_bytes[..4].try_into().unwrap_or([0, 0, 0, 0])) as u128,
14            7 => {
15                let mut bytes = [0; 8];
16                bytes[..7].copy_from_slice(&self.uid_bytes[..7]);
17                u64::from_le_bytes(bytes) as u128
18            }
19            10 => {
20                let mut bytes = [0; 16];
21                bytes[..10].copy_from_slice(&self.uid_bytes[..10]);
22                u128::from_le_bytes(bytes)
23            }
24            _ => {
25                log::error!("Wrong bytes count!");
26                unreachable!() // i dont think that this case is reachable
27            }
28        }
29    }
30}
31
32pub struct PCDRegister;
33pub struct PCDCommand;
34pub struct PICCCommand;
35
36#[allow(dead_code, non_upper_case_globals)]
37impl PCDRegister {
38    // Page 0: Command and status
39    //              0x00                    // reserved for future use
40    pub const CommandReg: u8 = 0x01; // starts and stops command execution
41    pub const ComIEnReg: u8 = 0x02; // enable and disable interrupt request control bits
42    pub const DivIEnReg: u8 = 0x03; // enable and disable interrupt request control bits
43    pub const ComIrqReg: u8 = 0x04; // interrupt request bits
44    pub const DivIrqReg: u8 = 0x05; // interrupt request bits
45    pub const ErrorReg: u8 = 0x06; // error bits showing the error status of the last command executed
46    pub const Status1Reg: u8 = 0x07; // communication status bits
47    pub const Status2Reg: u8 = 0x08; // receiver and transmitter status bits
48    pub const FIFODataReg: u8 = 0x09; // input and output of 64 byte FIFO buffer
49    pub const FIFOLevelReg: u8 = 0x0A; // number of bytes stored in the FIFO buffer
50    pub const WaterLevelReg: u8 = 0x0B; // level for FIFO underflow and overflow warning
51    pub const ControlReg: u8 = 0x0C; // miscellaneous control registers
52    pub const BitFramingReg: u8 = 0x0D; // adjustments for bit-oriented frames
53    pub const CollReg: u8 = 0x0E; // bit position of the first bit-collision detected on the RF interface
54    //              0x0F     // reserved for future use
55
56    // Page 1: Command
57    //               0x10     // reserved for future use
58    pub const ModeReg: u8 = 0x11; // defines general modes for transmitting and receiving
59    pub const TxModeReg: u8 = 0x12; // defines transmission data rate and framing
60    pub const RxModeReg: u8 = 0x13; // defines reception data rate and framing
61    pub const TxControlReg: u8 = 0x14; // controls the logical behavior of the antenna driver pins TX1 and TX2
62    pub const TxASKReg: u8 = 0x15; // controls the setting of the transmission modulation
63    pub const TxSelReg: u8 = 0x16; // selects the internal sources for the antenna driver
64    pub const RxSelReg: u8 = 0x17; // selects internal receiver settings
65    pub const RxThresholdReg: u8 = 0x18; // selects thresholds for the bit decoder
66    pub const DemodReg: u8 = 0x19; // defines demodulator settings
67    //               0x1A     // reserved for future use
68    //               0x1B     // reserved for future use
69    pub const MfTxReg: u8 = 0x1C; // controls some MIFARE communication transmit parameters
70    pub const MfRxReg: u8 = 0x1D; // controls some MIFARE communication receive parameters
71    //               0x1E     // reserved for future use
72    pub const SerialSpeedReg: u8 = 0x1F; // selects the speed of the serial UART interface
73
74    // Page 2: Configuration
75    //               0x20        // reserved for future use
76    pub const CRCResultRegH: u8 = 0x21; // shows the MSB and LSB values of the CRC calculation
77    pub const CRCResultRegL: u8 = 0x22;
78    //               0x23        // reserved for future use
79    pub const ModWidthReg: u8 = 0x24; // controls the ModWidth setting?
80    //               0x25        // reserved for future use
81    pub const RFCfgReg: u8 = 0x26; // configures the receiver gain
82    pub const GsNReg: u8 = 0x27; // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
83    pub const CWGsPReg: u8 = 0x28; // defines the conductance of the p-driver output during periods of no modulation
84    pub const ModGsPReg: u8 = 0x29; // defines the conductance of the p-driver output during periods of modulation
85    pub const TModeReg: u8 = 0x2A; // defines settings for the internal timer
86    pub const TPrescalerReg: u8 = 0x2B; // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
87    pub const TReloadRegH: u8 = 0x2C; // defines the 16-bit timer reload value
88    pub const TReloadRegL: u8 = 0x2D;
89    pub const TCounterValueRegH: u8 = 0x2E; // shows the 16-bit timer value
90    pub const TCounterValueRegL: u8 = 0x2F;
91
92    // Page 3: Test Registers
93    //               0x30      // reserved for future use
94    pub const TestSel1Reg: u8 = 0x31; // general test signal configuration
95    pub const TestSel2Reg: u8 = 0x32; // general test signal configuration
96    pub const TestPinEnReg: u8 = 0x33; // enables pin output driver on pins D1 to D7
97    pub const TestPinValueReg: u8 = 0x34; // defines the values for D1 to D7 when it is used as an I/O bus
98    pub const TestBusReg: u8 = 0x35; // shows the status of the internal test bus
99    pub const AutoTestReg: u8 = 0x36; // controls the digital self-test
100    pub const VersionReg: u8 = 0x37; // shows the software version
101    pub const AnalogTestReg: u8 = 0x38; // controls the pins AUX1 and AUX2
102    pub const TestDAC1Reg: u8 = 0x39; // defines the test value for TestDAC1
103    pub const TestDAC2Reg: u8 = 0x3A; // defines the test value for TestDAC2
104    pub const TestADCReg: u8 = 0x3B; // shows the value of ADC I and Q channels
105    //               0x3C      // reserved for production tests
106    //               0x3D      // reserved for production tests
107    //               0x3E      // reserved for production tests
108    //               0x3F      // reserved for production tests
109}
110
111#[allow(dead_code, non_upper_case_globals)]
112impl PCDCommand {
113    pub const Idle: u8 = 0x00; // no action, cancels current command execution
114    pub const Mem: u8 = 0x01; // stores 25 bytes into the internal buffer
115    pub const GenerateRandomID: u8 = 0x02; // generates a 10-byte random ID number
116    pub const CalcCRC: u8 = 0x03; // activates the CRC coprocessor or performs a self-test
117    pub const Transmit: u8 = 0x04; // transmits data from the FIFO buffer
118    pub const NoCmdChange: u8 = 0x07; // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
119    pub const Receive: u8 = 0x08; // activates the receiver circuits
120    pub const Transceive: u8 = 0x0C; // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
121    pub const MFAuthent: u8 = 0x0E; // performs the MIFARE standard authentication as a reader
122    pub const SoftReset: u8 = 0x0F; // resets the MFRC522
123}
124
125#[allow(dead_code, non_upper_case_globals)]
126impl PICCCommand {
127    pub const PICC_CMD_REQA: u8 = 0x26; // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
128    pub const PICC_CMD_WUPA: u8 = 0x52; // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
129    pub const PICC_CMD_CT: u8 = 0x88; // Cascade Tag. Not really a command, but used during anti collision.
130    pub const PICC_CMD_SEL_CL1: u8 = 0x93; // Anti collision/Select, Cascade Level 1
131    pub const PICC_CMD_SEL_CL2: u8 = 0x95; // Anti collision/Select, Cascade Level 2
132    pub const PICC_CMD_SEL_CL3: u8 = 0x97; // Anti collision/Select, Cascade Level 3
133    pub const PICC_CMD_HLTA: u8 = 0x50; // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
134    pub const PICC_CMD_RATS: u8 = 0xE0; // Request command for Answer To Reset.
135    // The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
136    // Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
137    // The read/write commands can also be used for MIFARE Ultralight.
138    pub const PICC_CMD_MF_AUTH_KEY_A: u8 = 0x60; // Perform authentication with Key A
139    pub const PICC_CMD_MF_AUTH_KEY_B: u8 = 0x61; // Perform authentication with Key B
140    pub const PICC_CMD_MF_READ: u8 = 0x30; // Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
141    pub const PICC_CMD_MF_WRITE: u8 = 0xA0; // Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
142    pub const PICC_CMD_MF_DECREMENT: u8 = 0xC0; // Decrements the contents of a block and stores the result in the internal data register.
143    pub const PICC_CMD_MF_INCREMENT: u8 = 0xC1; // Increments the contents of a block and stores the result in the internal data register.
144    pub const PICC_CMD_MF_RESTORE: u8 = 0xC2; // Reads the contents of a block into the internal data register.
145    pub const PICC_CMD_MF_TRANSFER: u8 = 0xB0; // Writes the contents of the internal data register to a block.
146    // The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
147    // The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
148    pub const PICC_CMD_UL_WRITE: u8 = 0xA2; // Writes one 4 byte page to the PICC.
149}
150
151#[derive(Debug, PartialEq)]
152#[allow(dead_code)]
153pub enum PCDVersion {
154    Counterfeit = 0x12,
155    FM17522 = 0x88,
156    FM17522_1 = 0xb2,
157    FM17522E = 0x89,
158    Version0_0 = 0x90,
159    Version1_0 = 0x91,
160    Version2_0 = 0x92,
161    VersionUnknown = 0xff,
162}
163
164#[allow(dead_code)]
165impl PCDVersion {
166    pub fn from_byte(byte: u8) -> Self {
167        match byte {
168            0x12 => PCDVersion::Counterfeit,
169            0x88 => PCDVersion::FM17522,
170            0xb2 => PCDVersion::FM17522_1,
171            0x89 => PCDVersion::FM17522E,
172            0x90 => PCDVersion::Version0_0,
173            0x91 => PCDVersion::Version1_0,
174            0x92 => PCDVersion::Version2_0,
175            _ => PCDVersion::VersionUnknown,
176        }
177    }
178}
179
180#[derive(Debug, PartialEq)]
181#[allow(dead_code)]
182pub enum PICCType {
183    PiccTypeUnknown = 0xff,
184    PiccTypeIso14443_4 = 0x20, // PICC compliant with ISO/IEC 14443-4.
185    PiccTypeIso18092 = 0x40,   // PICC compliant with ISO/IEC 18092 (NFC).
186    PiccTypeMifareMini = 0x09, // MIFARE Classic protocol, 320 bytes.
187    PiccTypeMifare1K = 0x08,   // MIFARE Classic protocol, 1KB.
188    PiccTypeMifare4K = 0x18,   // MIFARE Classic protocol, 4KB.
189    PiccTypeMifareUL = 0x00,   // MIFARE Ultralight or Ultralight C.
190    PiccTypeMifarePlus = 0x10 | 0x11, // MIFARE Plus.
191    PiccTypeMifareDesfire,     // MIFARE DESFire.
192    PiccTypeTnp3XXX = 0x01, // Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure.
193    PiccTypeNotComplete = 0x04, // SAK indicates UID is not complete.
194}
195
196impl PICCType {
197    pub fn from_sak(sak: u8) -> Self {
198        let sak = sak & 0x7F;
199
200        match sak {
201            0x20 => PICCType::PiccTypeIso14443_4,
202            0x40 => PICCType::PiccTypeIso18092,
203            0x09 => PICCType::PiccTypeMifareMini,
204            0x08 => PICCType::PiccTypeMifare1K,
205            0x18 => PICCType::PiccTypeMifare4K,
206            0x00 => PICCType::PiccTypeMifareUL,
207            0x10 | 0x11 => PICCType::PiccTypeMifarePlus,
208            0x01 => PICCType::PiccTypeTnp3XXX,
209            0x04 => PICCType::PiccTypeNotComplete,
210            _ => PICCType::PiccTypeUnknown,
211        }
212    }
213}
214
215#[derive(Debug, PartialEq)]
216pub enum PCDErrorCode {
217    /// Error in communication
218    Error,
219
220    /// Collision detected
221    Collision,
222
223    /// Timeout in communication
224    Timeout,
225
226    /// A buffer is not big enough
227    NoRoom,
228
229    /// Internal error in code.
230    InternalError,
231
232    /// Invalid argument
233    Invalid,
234
235    /// The CRC_A does not match
236    CrcWrong,
237
238    /// Unspecified error
239    Unknown,
240
241    /// MIFARE PICC responded with NAK
242    MifareNack,
243
244    /// SPI error
245    SpiError(embedded_hal_async::spi::ErrorKind),
246
247    /// I2C error
248    I2cError(embedded_hal_async::i2c::ErrorKind),
249
250    /// Any driver error
251    DriverError,
252}
253
254impl PCDErrorCode {
255    pub fn from_spi_error<E: embedded_hal_async::spi::Error>(error: E) -> Self {
256        PCDErrorCode::SpiError(error.kind())
257    }
258
259    pub fn from_i2c_error<E: embedded_hal_async::i2c::Error>(error: E) -> Self {
260        PCDErrorCode::I2cError(error.kind())
261    }
262}
263
264pub enum UidSize {
265    Four,
266    Seven,
267    Ten,
268}
269
270impl UidSize {
271    pub fn to_byte(&self) -> u8 {
272        match self {
273            Self::Four => 4,
274            Self::Seven => 7,
275            Self::Ten => 10,
276        }
277    }
278}