Skip to content

Commit 92d2cb2

Browse files
committed
refactor: scan multiple tags
1 parent 8693cd9 commit 92d2cb2

File tree

4 files changed

+105
-70
lines changed

4 files changed

+105
-70
lines changed

Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,12 @@ menu "RC522"
1111
writing incorrect access bits, which could render the sector
1212
unusable.
1313

14+
config RC522_PICC_SLOT_COUNT
15+
int "Number of available tag slots for RC522 devices"
16+
default 2
17+
range 1 8
18+
help
19+
This option sets the number of available tag slots for RC522 devices.
20+
Each slot can hold one tag. The default value is 2.
21+
1422
endmenu

include/rc522_picc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ typedef enum
6666
* this state to get the complete UID.
6767
*
6868
* The PICC enters the ACTIVE State when it is selected with its complete UID.
69+
*
70+
* Not used though
6971
*/
7072
RC522_PICC_STATE_READY,
7173

@@ -99,6 +101,8 @@ typedef enum
99101
* Cascade levels are handled inside this state to get complete UID.
100102
*
101103
* The PICC enters the ACTIVE* State when it is selected with its complete UID.
104+
*
105+
* Not used though
102106
*/
103107
RC522_PICC_STATE_READY_H,
104108

@@ -145,6 +149,7 @@ typedef struct
145149
uint8_t sak;
146150
rc522_picc_type_t type;
147151
rc522_picc_state_t state;
152+
uint32_t last_seen;
148153
} rc522_picc_t;
149154

150155
typedef struct

internal/rc522_types_internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <esp_bit_defs.h>
66
#include <freertos/FreeRTOS.h>
77
#include <freertos/event_groups.h>
8+
#include "sdkconfig.h"
89
#include "rc522_types.h"
910
#include "rc522_picc.h"
1011

@@ -14,6 +15,8 @@ extern "C" {
1415

1516
#define RC522_LOG_TAG "rc522"
1617

18+
#define RC522_PICC_SLOT_COUNT CONFIG_RC522_PICC_SLOT_COUNT
19+
1720
#define RC522_POLL_INTERVAL_MS_DEFAULT (120)
1821
#define RC522_POLL_INTERVAL_MS_MIN (50)
1922
#define RC522_TASK_STACK_SIZE_DEFAULT (4 * 1024)
@@ -38,7 +41,7 @@ struct rc522
3841
TaskHandle_t task_handle; /*<! Handle of task */
3942
esp_event_loop_handle_t event_handle; /*<! Handle of event loop */
4043
rc522_state_t state; /*<! Current state */
41-
rc522_picc_t picc;
44+
rc522_picc_t picc[RC522_PICC_SLOT_COUNT];
4245
EventGroupHandle_t bits;
4346
};
4447

src/rc522.c

Lines changed: 88 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)