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}