Raspberry Pi Weighting Control System
This project serves as a simple weighting control system, that was realized as a Bachelor Thesis
Classes | Functions | Variables
rfid_reader Namespace Reference

Classes

struct  rfid_tag
 RFID tag structure. Stores data read from SPI. More...
 

Functions

void push_event (rfid_tag tag, uint8_t flags)
 
int init (const char *, uint8_t, uint32_t, uint16_t, uint8_t)
 RFID reader init through values. More...
 
int init_from_conf ()
 RFID reader init from loaded configuration. More...
 
void print_card_serial (rfid_tag *tag)
 
void start_reading_cards ()
 Loop that is run in its own thread, reading the RFID reader. More...
 
void clean ()
 Stops the reading thread. More...
 
char detect_tag (uint16_t *tag_type, uint8_t *buff)
 This function detects if a RFID tag was put near the reader. More...
 
char read_tag_serialn (uint8_t *serial, uint8_t *serial_size, uint8_t *ser_ack, uint8_t *buff)
 This function reads the serial number of RIFD tag put near the reader. More...
 
int read_tag (rfid_tag *tag)
 This function is a loop handling the scanner. More...
 
rfid_eventpoll_event ()
 Polls event from RFID event_queue. More...
 
void clear_event_queue ()
 Clears event queue, discarding all waiting events. More...
 

Variables

std::queue< rfid_eventevent_queue
 
std::mutex eq_mutex
 
std::unique_ptr< spi_config_t > spi_config
 
std::unique_ptr< SPI > my_spi = nullptr
 
bool reading_cards = true
 

Function Documentation

◆ clean()

void rfid_reader::clean ( )

Stops the reading thread.

Definition at line 106 of file rfid_reader.cpp.

106  {
107  spdlog::info("rfid_reader.cpp - Cleaning SPI RFID Reader (RC522)");
108  reading_cards = false;
109  // my_spi is unique_ptr, should destruct automatically
110  }
bool reading_cards
Definition: rfid_reader.cpp:20

◆ clear_event_queue()

void rfid_reader::clear_event_queue ( )

Clears event queue, discarding all waiting events.

Definition at line 291 of file rfid_reader.cpp.

291  {
292  for (size_t i = 0; i < event_queue.size(); i++) {
293  event_queue.pop();
294  }
295  }
std::queue< rfid_event > event_queue
Definition: rfid_reader.cpp:15

◆ detect_tag()

char rfid_reader::detect_tag ( uint16_t *  tag_type,
uint8_t *  buff 
)

This function detects if a RFID tag was put near the reader.

This function was implemented by paulvha https://github.com/paulvha/rfid-rc522.git

Returns
char

Definition at line 112 of file rfid_reader.cpp.

112  {
113  char status;
114  status = PcdRequest(PICC_REQALL, buff);
115 
116  if (status == TAG_OK) {
117  *tag_type = buff[0] << 8 | buff[1];
118  }
119 
120  return status;
121  }
char PcdRequest(uint8_t req_code, uint8_t *pTagType)
Definition: rc522.cpp:47
#define TAG_OK
Definition: rc522.h:125
#define PICC_REQALL
Definition: rc522.h:48

◆ init()

int rfid_reader::init ( const char *  ,
uint8_t  ,
uint32_t  ,
uint16_t  ,
uint8_t   
)

RFID reader init through values.

Returns
int

Definition at line 25 of file rfid_reader.cpp.

25  {
26  spi_config = std::unique_ptr<spi_config_t>(new spi_config_t());
27  spi_config->mode = mode;
28  spi_config->speed = speed;
29  spi_config->delay = delay;
30  spi_config->bits_per_word = bits_per_word;
31 
32  spdlog::info("rfid_reader.cpp - Initializing SPI RFID Reader (RC522)");
33 
34  my_spi = std::unique_ptr<SPI>(new SPI(device, spi_config.get()));
35 
36  if (!my_spi->begin()) {
37  spdlog::critical("rfid_reader.cpp - Failed to start SPI communication for RC522");
38  return 1;
39  }
40 
41  spdlog::info("rfid_reader.cpp - Successfully initialized SPI RFID Reader (RC522)");
42  InitRc522(my_spi.get());
43  return 0;
44  }
std::unique_ptr< SPI > my_spi
Definition: rfid_reader.cpp:19
std::unique_ptr< spi_config_t > spi_config
Definition: rfid_reader.cpp:18
void InitRc522(SPI *p_spi)
Definition: rc522.cpp:39

◆ init_from_conf()

int rfid_reader::init_from_conf ( )

RFID reader init from loaded configuration.

Returns
int

Definition at line 46 of file rfid_reader.cpp.

46  {
47  app_workspace_ns::spi_config *config = &(app_workspace::get_instance()->main_config->rfid_conf);
48  spdlog::info("rfid_reader.cpp - Initializing SPI RFID Reader (RC522) with config (enable debug to print config)");
49  spdlog::debug("rfid_reader.cpp - dev: {0}" , config->dev);
50  spdlog::debug("rfid_reader.cpp - mode: {0}" , config->config->mode);
51  spdlog::debug("rfid_reader.cpp - bits_p_w: {0}", config->config->bits_per_word);
52  spdlog::debug("rfid_reader.cpp - speed: {0}" , config->config->speed);
53  spdlog::debug("rfid_reader.cpp - delay: {0}" , config->config->delay);
54 
55  my_spi = std::unique_ptr<SPI>(new SPI(config->dev.c_str(), config->config.get()));
56 
57  if (!my_spi->begin()) {
58  spdlog::critical("rfid_reader.cpp - Failed to start SPI communication for RC522");
59  return 1;
60  }
61 
62  spdlog::info("rfid_reader.cpp - Successfully initialized SPI RFID Reader (RC522)");
63  InitRc522(my_spi.get());
64  return 0;
65  }
static std::unique_ptr< app_workspace > & get_instance()
Get the instance app_workspace which is a singleton.
Structure holding SPI device and SPI config which is a library structure "spi_config_t".
std::unique_ptr< spi_config_t > config

◆ poll_event()

rfid_event * rfid_reader::poll_event ( )

Polls event from RFID event_queue.

Returns
rfid_event*

Definition at line 278 of file rfid_reader.cpp.

278  {
279  if (event_queue.size() <= 0)
280  return NULL;
281 
282  // probably don't need to lock thread for poll, but better safe than sorry
283  std::lock_guard<std::mutex> eq_guard(eq_mutex);
284 
285  rfid_event* res = &event_queue.front();
286  event_queue.pop();
287 
288  return res;
289  }
std::mutex eq_mutex
Definition: rfid_reader.cpp:16
Structure used for RFID event. This structure contains read tag and flags of the event.
Definition: rfid_reader.h:100

◆ print_card_serial()

void rfid_reader::print_card_serial ( rfid_tag tag)

Definition at line 67 of file rfid_reader.cpp.

67  {
68  spdlog::debug("rfid_reader.cpp - Read RFID tag. Serial:");
69  // printf isn't very elegant, but this is a debug function anyway
70  for (int i = 0; i < tag->serial_size; i++) {
71  printf("%d", tag->serial[i]);
72  }
73  printf("\n");
74  }

◆ push_event()

void rfid_reader::push_event ( rfid_tag  tag,
uint8_t  flags 
)

This function creates a RFID event and pushes it into the event queue

Definition at line 270 of file rfid_reader.cpp.

270  {
271  rfid_event event = {};
272 
273  event.tag = tag;
274  event.flags = flags;
275  event_queue.push(event);
276  }
rfid_reader::rfid_tag tag
Definition: rfid_reader.h:101

◆ read_tag()

int rfid_reader::read_tag ( rfid_tag tag)

This function is a loop handling the scanner.

This function was implemented by paulvha and modified by trestikp (me) https://github.com/paulvha/rfid-rc522.git

Returns
char

Definition at line 175 of file rfid_reader.cpp.

175  {
176  int status;
177  uint8_t buff[MAXRLEN];
178  //rfid_tag tag;
179  //p_printf(BLUE,"Hold your card for the reader "); // debug "reding card"
180 
181  do {
182  status = detect_tag(&(tag->tag_type), buff);
183 
184  if (status == TAG_NOTAG) { // no card - wait
185  usleep(RFID_READ_INTERVAL);
186  continue;
187  } else if (status != TAG_OK && status != TAG_COLLISION) {
188  // issue with tag reading ?
189  spdlog::debug("rfid_reader.cpp - Issue reading tag, trying again...");
190  usleep(RFID_READ_INTERVAL / 2);
191  continue;
192  }
193 
194  //maybe set buff mem to 0?
195 
196  // read serial number & SAK
197  status = read_tag_serialn(tag->serial, &(tag->serial_size), tag->ser_ack, buff);
198 
199  } while (status != TAG_OK && reading_cards);
200 
201  spdlog::debug("rfid_reader.cpp - Found card");
202 
203  /* determine memory details
204  * but this is very cryptic and hard to exactly discover
205  * SAK = Select acknowledgement has card details in it but still...
206  * nearly mission impossible
207  */
208 
209  tag->max_blocks = 0;
210 
211  switch (tag->tag_type) {
212  case 0x4400:
213 
214  if (tag->ser_ack[0] == 0x0) {
215  spdlog::debug("rfid_reader.cpp - Ultralight card");
216  spdlog::debug("rfid_reader.cpp - NOT supported by this program");
217  } else if (tag->ser_ack[0] == 0x8) {
218  spdlog::debug("rfid_reader.cpp - Mifare Classic(1K) or PLUS card (2K)");
219  spdlog::debug("rfid_reader.cpp - In case of PLUS card, we will only read the first 1K (64 blocks)");
220  tag->max_blocks=64;
221  tag->page_step=1; // increment to read the card
222  } else if (tag->ser_ack[0] == 0x9) {// 20 blocks (5 sectors x 4 blocks) x 16 bytes
223  spdlog::debug("rfid_reader.cpp - Mifare MINI(0.3K)");
224  tag->max_blocks=20;
225  tag->page_step=1; // increment to read the card
226  } else if (tag->ser_ack[0] == 0x18) {
227  spdlog::debug("rfid_reader.cpp - PLUS card (4K)");
228  spdlog::debug("rfid_reader.cpp - Can only access the first 128 blocks (NOT last 8 sectore with 16 blocks)");
229  tag->max_blocks=128;
230  tag->page_step=1; // increment to read the card
231  }
232  break;
233 
234  case 0x0400:
235  if (tag->ser_ack[0] == 0x8) { // 64 blocks of 16 bytes / Ul card
236  spdlog::debug("rfid_reader.cpp - Mifare Classic(1K) or SmartMX with MIFARE 1K emulation");
237  tag->max_blocks=64;
238  tag->page_step=1; // increment to read the card
239  } else if (tag->ser_ack[0] == 0x9) { // 20 blocks (5 sectors x 4 blocks) x 16 bytes
240  spdlog::debug("rfid_reader.cpp - Mifare MINI(0.3K)");
241  tag->max_blocks=20;
242  tag->page_step=1; // increment to read the card
243  }
244  break;
245 
246  case 0x0200:
247  if (tag->ser_ack[0] == 0x18) { // 64 blocks of 16 bytes / Ul card
248  spdlog::debug("rfid_reader.cpp - Mifare Classic(4K) or SmartMX with MIFARE 4K emulation");
249  spdlog::debug("rfid_reader.cpp - Can only access the first 128 blocks (NOT last 8 sectore with 16 blocks)");
250  tag->max_blocks=127;
251  tag->page_step=1; // increment to read the card
252  } else if (tag->ser_ack[0] == 0x9) { // 20 blocks (5 sectors x 4 blocks) x 16 bytes
253  spdlog::debug("rfid_reader.cpp - Mifare MINI(0.3K)");
254  tag->max_blocks=20;
255  tag->page_step=1; // increment to read the card
256  }
257  break;
258  }
259 
260  if (tag->max_blocks == 0) {
261  spdlog::error("rfid_reader.cpp - Read card, BUT card type not known");
262  //PcdHalt();
263  // set card reading loop var to false - stop reading cards?
264  }
265 
266  return status;
267  }
char read_tag_serialn(uint8_t *serial, uint8_t *serial_size, uint8_t *ser_ack, uint8_t *buff)
This function reads the serial number of RIFD tag put near the reader.
char detect_tag(uint16_t *tag_type, uint8_t *buff)
This function detects if a RFID tag was put near the reader.
#define MAXRLEN
Definition: rc522.h:64
#define TAG_NOTAG
Definition: rc522.h:126
#define TAG_COLLISION
Definition: rc522.h:129
#define RFID_READ_INTERVAL
Definition: rfid_reader.cpp:12

◆ read_tag_serialn()

char rfid_reader::read_tag_serialn ( uint8_t *  serial,
uint8_t *  serial_size,
uint8_t *  ser_ack,
uint8_t *  buff 
)

This function reads the serial number of RIFD tag put near the reader.

This function was implemented by paulvha https://github.com/paulvha/rfid-rc522.git

Returns
char

Definition at line 123 of file rfid_reader.cpp.

123  {
124  /* get basic UID from card */
125  if (PcdAnticoll(PICC_ANTICOLL1, buff) != TAG_OK) return TAG_ERR;
126 
127  /* select the card */
128  if (PcdSelect(PICC_ANTICOLL1, buff, ser_ack) != TAG_OK) return TAG_ERR;
129 
130  if (buff[0]== 0x88) { // 0x88 is CT = Cascade Tag (means next level to get UID)
131 
132  //copy UID0, UID1, UID2
133  memcpy(serial, &buff[1],3);
134 
135  // 0x95 => get cascade level 2 and select
136  if (PcdAnticoll(PICC_ANTICOLL2, buff)!= TAG_OK) return TAG_ERR;
137 
138  if (PcdSelect(PICC_ANTICOLL2, buff, ser_ack) != TAG_OK) return TAG_ERR;
139 
140  if (buff[0]==0x88)
141  {
142  // add UID3, UID4 and UID5
143  memcpy(serial + 3, &buff[1], 3);
144 
145  // 0x97 => get even more extended serial number
146 
147  if (PcdAnticoll(PICC_ANTICOLL3, buff) != TAG_OK) return TAG_ERR;
148 
149  if (PcdSelect(PICC_ANTICOLL3, buff, ser_ack) != TAG_OK) return TAG_ERR;
150 
151  // add UID6, UID7, UID8 UID9
152  memcpy(serial + 6, buff, 4);
153  *serial_size = 10; // 10 byte UID (triple size UID) PSS
154  } else {
155  // add UID3, UID4, UID5 UID6
156  memcpy(serial + 3, buff, 4);
157  /* 7 byte UID (double size) Mifare Ultralight, Ultralight C, Desfire
158  * Desfire EV1 and Mifare Plus (7 B UID)
159  */
160  *serial_size = 7; // 7 byte Unique ID (double size UID)
161  }
162  } else {
163  //copy UID0, UID1, UID2, UID3
164  memcpy(serial, &buff[0], 4);
165  /* 4 byte non-unique ID (single byte UID) - discontinued end 2010
166  * were set at manufacturing.
167  * used on Mifare Classic 1K, Mifare Classic 4K and some Mifare Plus versions
168  */
169  *serial_size = 4;
170  }
171 
172  return TAG_OK;
173  }
char PcdAnticoll(uint8_t cascade, uint8_t *pSnr)
Definition: rc522.cpp:89
char PcdSelect(uint8_t cascade, uint8_t *pSnr, uint8_t *SAK)
Definition: rc522.cpp:187
#define TAG_ERR
Definition: rc522.h:127
#define PICC_ANTICOLL3
Definition: rc522.h:51
#define PICC_ANTICOLL2
Definition: rc522.h:50
#define PICC_ANTICOLL1
Definition: rc522.h:49

◆ start_reading_cards()

void rfid_reader::start_reading_cards ( )

Loop that is run in its own thread, reading the RFID reader.

Definition at line 76 of file rfid_reader.cpp.

76  {
77  uint8_t flags;
78  int rv;
79  rfid_tag tag;
80  std::chrono::time_point<std::chrono::high_resolution_clock> last_read =
81  std::chrono::high_resolution_clock::now();
82  std::chrono::time_point<std::chrono::high_resolution_clock> current_read;
83 
84  while (reading_cards) {
85  flags = RFID_FLAGS_NONE;
86  rv = read_tag(&tag);
87  current_read = std::chrono::high_resolution_clock::now();
88 
89  if (rv != TAG_OK) {
90  spdlog::error("rfid_reader.cpp - read_tag() finished but returned error state");
91  } else {
92  spdlog::info("rfid_reader.cpp - Successfully read RFID tag. Pushing into RFID event queue.");
93 
94  std::chrono::duration<double, std::milli> diff = last_read - current_read;
95  if (diff.count() > REPEATING_FLAG_DELAY) {
96  flags |= RFID_FLAGS_REPEATING;
97  }
98  //print_card_serial(&tag);
99  push_event(tag, flags);
100  }
101 
102  last_read = current_read; //maybe change its to ::now()
103  }
104  }
int read_tag(rfid_tag *tag)
This function is a loop handling the scanner.
void push_event(rfid_tag tag, uint8_t flags)
#define REPEATING_FLAG_DELAY
Definition: rfid_reader.cpp:11
@ RFID_FLAGS_REPEATING
Definition: rfid_reader.h:93
@ RFID_FLAGS_NONE
Definition: rfid_reader.h:92

Variable Documentation

◆ eq_mutex

std::mutex rfid_reader::eq_mutex

Definition at line 16 of file rfid_reader.cpp.

◆ event_queue

std::queue<rfid_event> rfid_reader::event_queue

Definition at line 15 of file rfid_reader.cpp.

◆ my_spi

std::unique_ptr<SPI> rfid_reader::my_spi = nullptr

Definition at line 19 of file rfid_reader.cpp.

◆ reading_cards

bool rfid_reader::reading_cards = true

Definition at line 20 of file rfid_reader.cpp.

◆ spi_config

std::unique_ptr<spi_config_t> rfid_reader::spi_config

Definition at line 18 of file rfid_reader.cpp.