@@ -122,7 +122,9 @@ esp_err_t rc522_create(const rc522_config_t *config, rc522_handle_t *out_rc522)
122122 rc522_handle_t rc522 = calloc (1 , sizeof (struct rc522 ));
123123 ESP_RETURN_ON_FALSE (rc522 != NULL , ESP_ERR_NO_MEM , TAG , "nomem" );
124124
125- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_IDLE , false);
125+ for (int i = 0 ; i < RC522_PICC_SLOT_COUNT ; i ++ ) {
126+ rc522 -> picc [i ].state = RC522_PICC_STATE_IDLE ;
127+ }
126128
127129 esp_err_t ret = ESP_OK ;
128130
@@ -211,7 +213,6 @@ void rc522_task(void *arg)
211213 uint32_t last_poll_ms = 0 ;
212214 const uint32_t task_delay_ms = 50 ;
213215 const uint32_t picc_heartbeat_failure_threshold_ms = (2 * task_delay_ms );
214- uint32_t picc_heartbeat_failure_at_ms = 0 ;
215216 bool mutex_taken = false;
216217 const uint16_t mutex_take_timeout_ms = 4000 ;
217218
@@ -246,86 +247,104 @@ void rc522_task(void *arg)
246247 }
247248
248249 bool should_poll = (rc522_millis () - last_poll_ms ) > rc522 -> config -> poll_interval_ms ;
249-
250- if (rc522 -> picc .state == RC522_PICC_STATE_IDLE || rc522 -> picc .state == RC522_PICC_STATE_HALT ) {
250+ if (should_poll ) {
251251 rc522_picc_atqa_desc_t atqa ;
252-
253- if (rc522 -> picc .state == RC522_PICC_STATE_IDLE && ((ret = rc522_picc_reqa (rc522 , & atqa )) != ESP_OK )) {
254- continue ;
252+ bool known_present [RC522_PICC_SLOT_COUNT ] = { false };
253+ uint8_t scan_known_remaining = 0 ;
254+ for (int i = 0 ; i < RC522_PICC_SLOT_COUNT ; i ++ ) {
255+ if (rc522 -> picc [i ].state != RC522_PICC_STATE_IDLE ) {
256+ scan_known_remaining ++ ;
257+ }
255258 }
256259
257- if (rc522 -> picc .state == RC522_PICC_STATE_HALT && ((ret = rc522_picc_wupa (rc522 , & atqa )) != ESP_OK )) {
258- continue ;
260+ rc522_picc_t new_picc [RC522_PICC_SLOT_COUNT ];
261+ uint8_t new_picc_count = 0 ;
262+ for (int i = 0 ; i < RC522_PICC_SLOT_COUNT ; i ++ ) {
263+ new_picc [i ].state = RC522_PICC_STATE_IDLE ;
259264 }
260265
261- // card is present
262- rc522 -> picc .atqa = atqa ;
263-
264- if (rc522 -> picc .state == RC522_PICC_STATE_IDLE ) {
265- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_READY , true);
266- }
267- else if (rc522 -> picc .state == RC522_PICC_STATE_HALT ) {
268- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_READY_H , true);
269- }
270- }
271-
272- if (should_poll
273- && (rc522 -> picc .state == RC522_PICC_STATE_READY || rc522 -> picc .state == RC522_PICC_STATE_READY_H )) {
274- rc522_picc_uid_t uid ;
275- uint8_t sak ;
276-
277- ret = rc522_picc_select (rc522 , & uid , & sak , false);
278- last_poll_ms = rc522_millis ();
266+ for (;;) {
267+ if (new_picc_count >= RC522_PICC_SLOT_COUNT ) {
268+ break ;
269+ }
279270
280- if (ret != ESP_OK ) {
281- if (ret != RC522_ERR_RX_TIMEOUT && ret != RC522_ERR_INVALID_ATQA && ret != RC522_ERR_INVALID_SAK ) {
282- RC522_LOGW ("select failed (err=%04" RC522_X ")" , ret );
271+ rc522_picc_uid_t uid = { .length = 0 };
272+ if (scan_known_remaining ) {
273+ // find the next known picc uid to select
274+ for (int i = scan_known_remaining - 1 ; i >= 0 ; i -- ) {
275+ if (rc522 -> picc [i ].state != RC522_PICC_STATE_IDLE ) {
276+ memcpy (& uid , & rc522 -> picc [i ].uid , sizeof (rc522_picc_uid_t ));
277+ break ;
278+ }
279+ }
280+ scan_known_remaining -- ;
281+ ret = rc522_picc_wupa (rc522 , & atqa );
282+ if (ret != ESP_OK ) {
283+ scan_known_remaining = 0 ;
284+ continue ;
285+ }
286+ } else {
287+ ret = rc522_picc_reqa (rc522 , & atqa );
288+ if (ret != ESP_OK ) {
289+ break ;
290+ }
283291 }
284- else {
285- RC522_LOGD ("select failed (err=%04" RC522_X ")" , ret );
292+
293+ uint8_t sak ;
294+ ret = rc522_picc_select (rc522 , & uid , & sak , uid .length );
295+ if (ret != ESP_OK ) {
296+ continue ;
286297 }
287298
288- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_IDLE , true);
289- continue ;
290- }
291-
292- memcpy (& rc522 -> picc .uid , & uid , sizeof (rc522_picc_uid_t ));
293- rc522 -> picc .sak = sak ;
294- rc522 -> picc .type = rc522_picc_get_type (& rc522 -> picc );
295-
296- if (rc522 -> picc .state == RC522_PICC_STATE_READY ) {
297- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_ACTIVE , true);
298- }
299- else if (rc522 -> picc .state == RC522_PICC_STATE_READY_H ) {
300- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_ACTIVE_H , true);
301- }
302-
303- picc_heartbeat_failure_at_ms = 0 ;
304-
305- continue ;
306- }
307-
308- if (rc522 -> picc .state == RC522_PICC_STATE_ACTIVE || rc522 -> picc .state == RC522_PICC_STATE_ACTIVE_H ) {
309- if (picc_heartbeat_failure_at_ms != 0
310- && ((rc522_millis () - picc_heartbeat_failure_at_ms ) > picc_heartbeat_failure_threshold_ms )) {
311- picc_heartbeat_failure_at_ms = 0 ;
312- rc522_picc_set_state (rc522 , & rc522 -> picc , RC522_PICC_STATE_IDLE , true);
313- continue ;
314- }
299+ int8_t known_index = -1 ;
300+ for (int i = 0 ; i < RC522_PICC_SLOT_COUNT ; i ++ ) {
301+ if (rc522 -> picc [i ].state != RC522_PICC_STATE_IDLE ) {
302+ if (rc522 -> picc [i ].uid .length == uid .length
303+ && memcmp (rc522 -> picc [i ].uid .value , uid .value , uid .length ) == 0 ) {
304+ known_index = i ;
305+ break ;
306+ }
307+ }
308+ }
315309
316- if ((ret = rc522_picc_heartbeat (rc522 , & rc522 -> picc , NULL , NULL )) == ESP_OK ) {
317- picc_heartbeat_failure_at_ms = 0 ;
318- }
319- else if (picc_heartbeat_failure_at_ms == 0 ) {
320- picc_heartbeat_failure_at_ms = rc522_millis ();
310+ if (known_index >= 0 ) {
311+ if (known_present [known_index ]) {
312+ // already processed
313+ rc522_picc_halta (rc522 , & rc522 -> picc [known_index ]);
314+ continue ;
315+ }
316+ known_present [known_index ] = true;
317+ rc522 -> picc [known_index ].sak = sak ;
318+ rc522 -> picc [known_index ].atqa = atqa ;
319+ rc522 -> picc [known_index ].last_seen = rc522_millis ();
320+ rc522_picc_set_state (rc522 , & rc522 -> picc [known_index ], RC522_PICC_STATE_ACTIVE_H , true);
321+ rc522_picc_halta (rc522 , & rc522 -> picc [known_index ]);
322+ rc522_picc_set_state (rc522 , & rc522 -> picc [known_index ], RC522_PICC_STATE_HALT , true);
323+ } else {
324+ memcpy (& new_picc [new_picc_count ].uid , & uid , sizeof (rc522_picc_uid_t ));
325+ new_picc [new_picc_count ].sak = sak ;
326+ new_picc [new_picc_count ].atqa = atqa ;
327+ new_picc [new_picc_count ].type = rc522_picc_get_type (& new_picc [new_picc_count ]);
328+ new_picc [new_picc_count ].last_seen = rc522_millis ();
329+ rc522_picc_set_state (rc522 , & new_picc [new_picc_count ], RC522_PICC_STATE_ACTIVE , true);
330+ rc522_picc_halta (rc522 , & new_picc [new_picc_count ]);
331+ rc522_picc_set_state (rc522 , & new_picc [new_picc_count ], RC522_PICC_STATE_HALT , true);
332+ new_picc_count ++ ;
333+ }
321334 }
322335
323- if (ret != ESP_OK ) {
324- RC522_LOGD ("heartbeat failed (err=%04" RC522_X ")" , ret );
336+ // merge new_picc into rc522->picc array, the picc will be ignored if there is no space
337+ for (int i = 0 ; i < RC522_PICC_SLOT_COUNT ; i ++ ) {
338+ if (rc522 -> picc [i ].state != RC522_PICC_STATE_IDLE
339+ && !known_present [i ]
340+ && rc522 -> picc [i ].last_seen + picc_heartbeat_failure_threshold_ms < rc522_millis ()) {
341+ rc522_picc_set_state (rc522 , & rc522 -> picc [i ], RC522_PICC_STATE_IDLE , true);
342+ }
343+ if (rc522 -> picc [i ].state == RC522_PICC_STATE_IDLE && new_picc_count ) {
344+ memcpy (& rc522 -> picc [i ], & new_picc [new_picc_count - 1 ], sizeof (rc522_picc_t ));
345+ new_picc_count -- ;
346+ }
325347 }
326-
327- // card is still in the field
328- continue ;
329348 }
330349 }
331350
0 commit comments