ESPHome  2024.11.1
rc522.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "esphome/core/hal.h"
7 
8 #include <vector>
9 
10 namespace esphome {
11 namespace rc522 {
12 
13 class RC522BinarySensor;
14 class RC522Trigger;
15 class RC522 : public PollingComponent {
16  public:
17  void setup() override;
18 
19  void dump_config() override;
20 
21  void update() override;
22  float get_setup_priority() const override { return setup_priority::DATA; };
23 
24  void loop() override;
25 
26  void register_tag(RC522BinarySensor *tag) { this->binary_sensors_.push_back(tag); }
27  void register_ontag_trigger(RC522Trigger *trig) { this->triggers_ontag_.push_back(trig); }
28  void register_ontagremoved_trigger(RC522Trigger *trig) { this->triggers_ontagremoved_.push_back(trig); }
29 
31 
32  protected:
33  // Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
34  // last value set to 0xff, then compiler uses less ram, it seems some optimisations are triggered
35  enum StatusCode : uint8_t {
36  STATUS_OK, // Success
37  STATUS_WAITING, // Waiting result from RC522 chip
38  STATUS_ERROR, // Error in communication
39  STATUS_COLLISION, // Collision detected
40  STATUS_TIMEOUT, // Timeout in communication.
41  STATUS_NO_ROOM, // A buffer is not big enough.
42  STATUS_INTERNAL_ERROR, // Internal error in the code. Should not happen ;-)
43  STATUS_INVALID, // Invalid argument.
44  STATUS_CRC_WRONG, // The CRC_A does not match
45  STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
46  };
47 
48  enum State {
58  } state_{STATE_NONE};
59 
60  enum PcdRegister : uint8_t {
61  // Page 0: Command and status
62  // 0x00 // reserved for future use
63  COMMAND_REG = 0x01 << 1, // starts and stops command execution
64  COM_I_EN_REG = 0x02 << 1, // enable and disable interrupt request control bits
65  DIV_I_EN_REG = 0x03 << 1, // enable and disable interrupt request control bits
66  COM_IRQ_REG = 0x04 << 1, // interrupt request bits
67  DIV_IRQ_REG = 0x05 << 1, // interrupt request bits
68  ERROR_REG = 0x06 << 1, // error bits showing the error status of the last command executed
69  STATUS1_REG = 0x07 << 1, // communication status bits
70  STATUS2_REG = 0x08 << 1, // receiver and transmitter status bits
71  FIFO_DATA_REG = 0x09 << 1, // input and output of 64 uint8_t FIFO buffer
72  FIFO_LEVEL_REG = 0x0A << 1, // number of uint8_ts stored in the FIFO buffer
73  WATER_LEVEL_REG = 0x0B << 1, // level for FIFO underflow and overflow warning
74  CONTROL_REG = 0x0C << 1, // miscellaneous control registers
75  BIT_FRAMING_REG = 0x0D << 1, // adjustments for bit-oriented frames
76  COLL_REG = 0x0E << 1, // bit position of the first bit-collision detected on the RF interface
77  // 0x0F // reserved for future use
78 
79  // Page 1: Command
80  // 0x10 // reserved for future use
81  MODE_REG = 0x11 << 1, // defines general modes for transmitting and receiving
82  TX_MODE_REG = 0x12 << 1, // defines transmission data rate and framing
83  RX_MODE_REG = 0x13 << 1, // defines reception data rate and framing
84  TX_CONTROL_REG = 0x14 << 1, // controls the logical behavior of the antenna driver pins TX1 and TX2
85  TX_ASK_REG = 0x15 << 1, // controls the setting of the transmission modulation
86  TX_SEL_REG = 0x16 << 1, // selects the internal sources for the antenna driver
87  RX_SEL_REG = 0x17 << 1, // selects internal receiver settings
88  RX_THRESHOLD_REG = 0x18 << 1, // selects thresholds for the bit decoder
89  DEMOD_REG = 0x19 << 1, // defines demodulator settings
90  // 0x1A // reserved for future use
91  // 0x1B // reserved for future use
92  MF_TX_REG = 0x1C << 1, // controls some MIFARE communication transmit parameters
93  MF_RX_REG = 0x1D << 1, // controls some MIFARE communication receive parameters
94  // 0x1E // reserved for future use
95  SERIAL_SPEED_REG = 0x1F << 1, // selects the speed of the serial UART interface
96 
97  // Page 2: Configuration
98  // 0x20 // reserved for future use
99  CRC_RESULT_REG_H = 0x21 << 1, // shows the MSB and LSB values of the CRC calculation
100  CRC_RESULT_REG_L = 0x22 << 1,
101  // 0x23 // reserved for future use
102  MOD_WIDTH_REG = 0x24 << 1, // controls the ModWidth setting?
103  // 0x25 // reserved for future use
104  RF_CFG_REG = 0x26 << 1, // configures the receiver gain
105  GS_N_REG = 0x27 << 1, // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
106  CW_GS_P_REG = 0x28 << 1, // defines the conductance of the p-driver output during periods of no modulation
107  MOD_GS_P_REG = 0x29 << 1, // defines the conductance of the p-driver output during periods of modulation
108  T_MODE_REG = 0x2A << 1, // defines settings for the internal timer
109  T_PRESCALER_REG = 0x2B << 1, // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
110  T_RELOAD_REG_H = 0x2C << 1, // defines the 16-bit timer reload value
111  T_RELOAD_REG_L = 0x2D << 1,
112  T_COUNTER_VALUE_REG_H = 0x2E << 1, // shows the 16-bit timer value
114 
115  // Page 3: Test Registers
116  // 0x30 // reserved for future use
117  TEST_SEL1_REG = 0x31 << 1, // general test signal configuration
118  TEST_SEL2_REG = 0x32 << 1, // general test signal configuration
119  TEST_PIN_EN_REG = 0x33 << 1, // enables pin output driver on pins D1 to D7
120  TEST_PIN_VALUE_REG = 0x34 << 1, // defines the values for D1 to D7 when it is used as an I/O bus
121  TEST_BUS_REG = 0x35 << 1, // shows the status of the internal test bus
122  AUTO_TEST_REG = 0x36 << 1, // controls the digital self-test
123  VERSION_REG = 0x37 << 1, // shows the software version
124  ANALOG_TEST_REG = 0x38 << 1, // controls the pins AUX1 and AUX2
125  TEST_DA_C1_REG = 0x39 << 1, // defines the test value for TestDAC1
126  TEST_DA_C2_REG = 0x3A << 1, // defines the test value for TestDAC2
127  TEST_ADC_REG = 0x3B << 1 // shows the value of ADC I and Q channels
128  // 0x3C // reserved for production tests
129  // 0x3D // reserved for production tests
130  // 0x3E // reserved for production tests
131  // 0x3F // reserved for production tests
132  };
133 
134  // MFRC522 commands. Described in chapter 10 of the datasheet.
135  enum PcdCommand : uint8_t {
136  PCD_IDLE = 0x00, // no action, cancels current command execution
137  PCD_MEM = 0x01, // stores 25 uint8_ts into the internal buffer
138  PCD_GENERATE_RANDOM_ID = 0x02, // generates a 10-uint8_t random ID number
139  PCD_CALC_CRC = 0x03, // activates the CRC coprocessor or performs a self-test
140  PCD_TRANSMIT = 0x04, // transmits data from the FIFO buffer
141  PCD_NO_CMD_CHANGE = 0x07, // no command change, can be used to modify the CommandReg register bits without
142  // affecting the command, for example, the PowerDown bit
143  PCD_RECEIVE = 0x08, // activates the receiver circuits
145  0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
146  PCD_MF_AUTHENT = 0x0E, // performs the MIFARE standard authentication as a reader
147  PCD_SOFT_RESET = 0x0F // resets the MFRC522
148  };
149 
150  // Commands sent to the PICC.
151  enum PiccCommand : uint8_t {
152  // The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
153  PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for
154  // anticollision or selection. 7 bit frame.
155  PICC_CMD_WUPA = 0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and
156  // prepare for anticollision or selection. 7 bit frame.
157  PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
158  PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
159  PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
160  PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
161  PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
162  PICC_CMD_RATS = 0xE0, // Request command for Answer To Reset.
163  // The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.pdf, Section 9)
164  // Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on
165  // the sector.
166  // The read/write commands can also be used for MIFARE Ultralight.
167  PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
168  PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
170  0x30, // Reads one 16 uint8_t block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
171  PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 uint8_t block to the authenticated sector of the PICC. Called
172  // "COMPATIBILITY WRITE" for MIFARE Ultralight.
174  0xC0, // Decrements the contents of a block and stores the result in the internal data register.
176  0xC1, // Increments the contents of a block and stores the result in the internal data register.
177  PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
178  PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
179  // The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
180  // The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
181  PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 uint8_t page to the PICC.
182  };
183 
184  void pcd_reset_();
185  void initialize_();
186  void pcd_antenna_on_();
187  void pcd_antenna_off_();
188 
189  virtual uint8_t pcd_read_register(PcdRegister reg
190  ) = 0;
191 
196  virtual void pcd_read_register(PcdRegister reg,
197  uint8_t count,
198  uint8_t *values,
199  uint8_t rx_align
200  ) = 0;
201  virtual void pcd_write_register(PcdRegister reg,
202  uint8_t value
203  ) = 0;
204 
209  virtual void pcd_write_register(PcdRegister reg,
210  uint8_t count,
211  uint8_t *values
212  ) = 0;
213 
215  uint8_t mask
216  );
218  uint8_t mask
219  );
220 
221  void pcd_transceive_data_(uint8_t send_len);
222 
223  void pcd_calculate_crc_(uint8_t *data,
224  uint8_t length
225  );
226 
231 
232  uint8_t buffer_[9];
233  uint8_t send_len_; // index of first byte for RX
235  uint8_t back_length_;
236  uint8_t uid_buffer_[10]; // buffer to construct the uid (for 7 and 10 bit uids)
237  uint8_t uid_idx_ = 0; // number of read uid bytes e.g. index of the next available position in uid_buffer
238  uint8_t error_counter_ = 0; // to reset if unresponsive
239  uint8_t rx_align_;
240  uint8_t *valid_bits_;
241 
242  GPIOPin *reset_pin_{nullptr};
243  uint8_t reset_count_{0};
244  uint32_t reset_timeout_{0};
245  std::vector<RC522BinarySensor *> binary_sensors_;
246  std::vector<RC522Trigger *> triggers_ontag_;
247  std::vector<RC522Trigger *> triggers_ontagremoved_;
248  std::vector<uint8_t> current_uid_;
249 
250  enum RC522Error {
251  NONE = 0,
253  } error_code_{NONE};
254 };
255 
257  public:
258  void set_uid(const std::vector<uint8_t> &uid) { uid_ = uid; }
259 
260  bool process(std::vector<uint8_t> &data);
261 
262  void on_scan_end() {
263  if (!this->found_) {
264  this->publish_state(false);
265  }
266  this->found_ = false;
267  }
268 
269  protected:
270  std::vector<uint8_t> uid_;
271  bool found_{false};
272 };
273 
274 class RC522Trigger : public Trigger<std::string> {
275  public:
276  void process(std::vector<uint8_t> &data);
277 };
278 
279 } // namespace rc522
280 } // namespace esphome
uint8_t rx_align_
Definition: rc522.h:239
void pcd_reset_()
Performs a soft reset on the MFRC522 chip and waits for it to be ready again.
Definition: rc522.cpp:285
void pcd_set_register_bit_mask_(PcdRegister reg, uint8_t mask)
Sets the bits given in mask in register reg.
Definition: rc522.cpp:340
uint8_t buffer_[9]
buffer for communication, the first bits [0..back_idx-1] are for tx , [back_idx..back_idx+back_len] f...
Definition: rc522.h:232
float get_setup_priority() const override
Definition: rc522.h:22
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
std::vector< RC522Trigger * > triggers_ontag_
Definition: rc522.h:246
void pcd_transceive_data_(uint8_t send_len)
Transfers data to the MFRC522 FIFO, executes a command, waits for completion and transfers data back ...
Definition: rc522.cpp:363
void update() override
Definition: rc522.cpp:117
virtual void pcd_write_register(PcdRegister reg, uint8_t value)=0
void set_reset_pin(GPIOPin *reset)
Definition: rc522.h:30
void dump_config() override
Definition: rc522.cpp:98
This class simplifies creating components that periodically check a state.
Definition: component.h:283
uint8_t back_length_
In: Max number of uint8_ts to write to *backData. Out: The number of uint8_ts returned.
Definition: rc522.h:235
StatusCode await_crc_()
Definition: rc522.cpp:463
uint8_t uid_buffer_[10]
Definition: rc522.h:236
void pcd_calculate_crc_(uint8_t *data, uint8_t length)
Use the CRC coprocessor in the MFRC522 to calculate a CRC_A.
Definition: rc522.cpp:449
std::vector< RC522Trigger * > triggers_ontagremoved_
Definition: rc522.h:247
void setup() override
Definition: rc522.cpp:40
uint8_t * valid_bits_
Definition: rc522.h:240
uint32_t awaiting_comm_time_
Definition: rc522.h:228
uint8_t reset_count_
Definition: rc522.h:243
std::vector< uint8_t > uid_
Definition: rc522.h:270
GPIOPin * reset_pin_
Definition: rc522.h:242
uint16_t reset
Definition: ina226.h:39
void register_ontag_trigger(RC522Trigger *trig)
Definition: rc522.h:27
uint8_t send_len_
Definition: rc522.h:234
enum esphome::rc522::RC522::RC522Error NONE
uint8_t error_counter_
Definition: rc522.h:238
void pcd_antenna_off_()
Turns the antenna off by disabling pins TX1 and TX2.
Definition: rc522.cpp:330
uint32_t reset_timeout_
Definition: rc522.h:244
enum esphome::rc522::RC522::State STATE_NONE
uint16_t length
Definition: tt21100.cpp:12
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
std::vector< uint8_t > current_uid_
Definition: rc522.h:248
Base class for all binary_sensor-type classes.
Definition: binary_sensor.h:37
StatusCode await_transceive_()
Definition: rc522.cpp:383
virtual uint8_t pcd_read_register(PcdRegister reg)=0
void register_tag(RC522BinarySensor *tag)
Definition: rc522.h:26
void pcd_antenna_on_()
Turns the antenna on by enabling pins TX1 and TX2.
Definition: rc522.cpp:320
uint8_t uid_idx_
Definition: rc522.h:237
void loop() override
Definition: rc522.cpp:129
void pcd_clear_register_bit_mask_(PcdRegister reg, uint8_t mask)
Clears the bits given in mask from register reg.
Definition: rc522.cpp:350
void set_uid(const std::vector< uint8_t > &uid)
Definition: rc522.h:258
void register_ontagremoved_trigger(RC522Trigger *trig)
Definition: rc522.h:28
std::vector< RC522BinarySensor * > binary_sensors_
Definition: rc522.h:245