Raspberry Pi Weighting Control System
This project serves as a simple weighting control system, that was realized as a Bachelor Thesis
rc522.cpp
Go to the documentation of this file.
1 /*
2  * This file is slightly modified version of the same name file (but .c) from https://github.com/paulvha/rfid-rc522.git
3  *
4  * contains routines to access the RC522
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * The program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * Created on: 14.08.2013
21  * authorizer: alexs
22  *
23  * version 1.50 / paulvh / July 2017
24  * Fixed number of bugs and code clean-up.
25  */
26 
27 #include <memory>
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h> //this is temorary for exit()
31 #include <unistd.h>
32 #include <spdlog/spdlog.h>ewf
33 #include "rc522.h"
34 
35 int extra_delay=0; // set extra delay on card access calls
36 SPI *spi;
37 
38 // perform init
39 void InitRc522(SPI *p_spi)
40 {
41  if (p_spi) spi = p_spi;
42  else spdlog::critical("rc522.cpp - RC522 didn't recieve SPI");
43  PcdReset();
44 }
45 
46 // start of communication with a card
47 char PcdRequest(uint8_t req_code,uint8_t *pTagType)
48 {
49  char status;
50  uint8_t unLen;
51  uint8_t ucComMF522Buf[MAXRLEN];
52 
53  /*
54  * B7 1 = start transmission of data (with transceive command)
55  * B6 - B4 0 = LSB stored in position 0
56  * B3 not used
57  * B2 - B0 number of bits of last byte that will be transmitted
58  */
59 
61 
62  ucComMF522Buf[0] = req_code;
63 
64  /* write request with length 1, receive in buf and unlen = #bits received*/
65  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen,1);
66 
67  /* expect 2 bytes or 16 bits with card type*/
68  if ((status == TAG_OK) && (unLen == 0x10))
69  {
70  *pTagType = ucComMF522Buf[0];
71  *(pTagType+1) = ucComMF522Buf[1];
72  }
73  else if (status == TAG_COLLISION) {
74 // printf("ATQA %02x%02x\n",ucComMF522Buf[0],ucComMF522Buf[1]);
75  }
76  else if (status != TAG_NOTAG) status = TAG_ERR;
77 
78  return status;
79 }
80 
81 /* Perform anticollision to select a single card and get it's UID
82  * sequence:
83  *
84  * 0x93 0x20 unique identifier is sent by card
85  * 0x93 0x70 UID + 2 CRC to select te card (pcdselect handled))
86  * 0x95 = cascade level 2 ( 7 bytes)
87  * 0x97 = cascade level 3 ( 10 bytes)
88  */
89 char PcdAnticoll(uint8_t cascade, uint8_t *pSnr)
90 {
91  char status;
92  uint8_t i,snr_check=0;
93  uint8_t unLen;
94  uint8_t ucComMF522Buf[MAXRLEN];
95  uint8_t pass=32; // max 32 bits (ISo standard)
96  uint8_t collbits=0;
97 
98  i=0;
99 
100  /*
101  * LSB of the received bit is stored at bit position 0, the second on stored on ps 1
102  * all bits of the last byte will be transferred */
104 
105  // bits received after collision are cleared
106  WriteRawRC(CollReg,0x80);
107 
108  do {
109  /* anti collision commands 0x93, 0x95 or 0x97 */
110  ucComMF522Buf[0] = cascade;
111 
112  /* NVB = number of valid bits/bytes
113  *
114  * NVB : 0x20 = no part of UID is sent = anticollision command
115  *
116  * 0x20 => top 4 bits is byte count = 2 valid bytes to transmit: cascade (or SEL or CL) + NVB
117  * byte count 2 = minimum, 7 max
118  *
119  * 0x20 => bottom 4 bits is bit count = 0 : number of valid data bits (include SEL+NVB) modulo 8
120  *
121  * normal way to connect at first, second the UID will be asked
122  * with collbits set to the correct number of UID bits
123  */
124  ucComMF522Buf[1] = 0x20+collbits;
125 
126  // WriteRawRC(0x0e,0);
127 
128  /* write Transceive command to card*/
129  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2+i,ucComMF522Buf,&unLen,1);
130 
131  if (status == TAG_COLLISION) {
132 
133  collbits=ReadRawRC(CollReg)&0x1f;
134 
135  /* 00 = bit collision of 32nd bit
136  * that sets the length of the UID */
137  if (collbits==0) collbits=32;
138 
139  i=(collbits-1)/8 +1;
140 // printf ("--- %02x %02x %02x %02x %d\n",ucComMF522Buf[0],ucComMF522Buf[1],ucComMF522Buf[2],ucComMF522Buf[3],unLen);
141 
142  ucComMF522Buf[i-1]|=(1<<((collbits-1)%8)); // move collbit to right place
143  ucComMF522Buf[5]=ucComMF522Buf[3];
144  ucComMF522Buf[4]=ucComMF522Buf[2];
145  ucComMF522Buf[3]=ucComMF522Buf[1];
146  ucComMF522Buf[2]=ucComMF522Buf[0];
147 
148  WriteRawRC(BitFramingReg,(collbits % 8));
149 // printf (" %d %d %02x %d\n",collbits,i,ucComMF522Buf[i+1],collbits % 8);
150  }
151  } while ( --pass > 0 && status == TAG_COLLISION);
152 // printf ("na %02x %02x %02x %02x %d\n",ucComMF522Buf[0],ucComMF522Buf[1],ucComMF522Buf[2],ucComMF522Buf[3],unLen);
153 
154  if (status == TAG_OK) // 4 bytes as defined by ISO
155  {
156  for (i=0; i < 4; i++)
157  {
158  *(pSnr+i) = ucComMF522Buf[i];
159  snr_check ^= ucComMF522Buf[i];
160  }
161  // check BCC = block check characters match
162  if (snr_check != ucComMF522Buf[i]) status = TAG_ERR;
163  }
164 
165  return status;
166 }
167 /*
168  * Select a card based on the UID
169  *
170  * cascade :
171  * 0x93 cascade level 1
172  * 0x95 cascade level 2
173  * 0x97 cascade level 3
174  *
175  * pSnr : store received UID
176  * SAK : store the ATS from the SAK
177  *
178  * NVB = 7- = PCD will transmit the UID CLn
179  *
180  * SAK = Select acknowledgement
181  * byte 1 = answer to select (ATS) to determine the card type
182  * byte 2 and 3 are CRC
183  *
184  * in case of double or triple UID only the last SAK is valid
185  */
186 
187 char PcdSelect(uint8_t cascade, uint8_t *pSnr, uint8_t *SAK)
188 {
189  char status;
190  uint8_t i;
191  uint8_t unLen;
192  uint8_t ucComMF522Buf[MAXRLEN];
193  uint8_t CRC_buff[2];
194 
195  ucComMF522Buf[0] = cascade; // 0x93, 0x95 or 0x97
196  ucComMF522Buf[1] = 0x70; // 0x70 : SELECT command
197  ucComMF522Buf[6] = 0; // BCC
198 
199  for (i=0; i<4; i++) // add UID & calc BCC
200  {
201  ucComMF522Buf[i+2] = *(pSnr+i);
202  ucComMF522Buf[6] ^= *(pSnr+i);
203  }
204  // add 2 CRC-A bytes
205  CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
206 
207  /* clear MIFARE Crypto-1 (just in case)*/
208  ClearBitMask(Status2Reg,0x08);
209 
210  /* sent select command */
211  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen,1);
212 
213  // expects 24 bytes response (as for ISO)
214  if ((status == TAG_OK) && (unLen == 0x18))
215  {
216  // calculate CRC
217  CalulateCRC(ucComMF522Buf,1,CRC_buff); // 1 byte used for CRC check
218 
219 // printf("debug %02x%02x %02x%02x ",ucComMF522Buf[1],ucComMF522Buf[2],CRC_buff[0],CRC_buff[1]);
220 
221  // check CRC is correct
222  if ((CRC_buff[0]!=ucComMF522Buf[1])||(CRC_buff[1]!=ucComMF522Buf[2]))
223  status = TAG_ERRCRC;
224 
225  else
226  {
227  *SAK = ucComMF522Buf[0]; // copy SAK
228  status = TAG_OK;
229  }
230  }
231  else
232  status = TAG_ERR;
233 
234  return status;
235 }
236 
237 /* Authorise access to a block address by the RC522
238  *
239  * 0x60 key A /0x61 Key B
240  *
241  * Format :
242  * Authentication command ( 0x60 or 0x61)
243  * Block address
244  * Sector key byte 0
245  * Sector key byte 1
246  * Sector key byte 2
247  * Sector key byte 3
248  * Sector key byte 4
249  * Sector key byte 5
250  * Sector key byte 6
251  * Card serial number byte 0
252  * Card serial number byte 1
253  * Card serial number byte 2
254  * Card serial number byte 3
255  *
256  * 12 bytes in total
257  *
258  */
259 char PcdAuthState(uint8_t auth_mode,uint8_t addr,uint8_t *pKey,uint8_t *pSnr)
260 {
261  char status;
262  uint8_t unLen;
263  uint8_t ucComMF522Buf[MAXRLEN];
264 
265  memset(ucComMF522Buf,0,sizeof(ucComMF522Buf)); // clear buffer
266 
267  ucComMF522Buf[0] = auth_mode;
268  ucComMF522Buf[1] = addr;
269 
270  memcpy(&ucComMF522Buf[2], pKey, 6); // included Key A or KeyB
271  memcpy(&ucComMF522Buf[8], pSnr, 4); // include only first 4 bytes of UID
272 
273  status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen,1);
274 
275  // check that Crypt0-1 bit is set to indicate succesfull authorization
276  if ((status != TAG_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
277  status = TAG_ERR;
278 
279  return(status);
280 }
281 
282 /* peform reading a block from the card
283  * addr = block number (must have been authorised for access before
284  * p = buffer to store 16 bytes from the block
285  */
286 char PcdRead(uint8_t addr,uint8_t *p )
287 {
288  char status;
289  uint8_t unLen;
290  uint8_t i,ucComMF522Buf[MAXRLEN];
291  uint8_t CRC_buff[2];
292 
293  memset(ucComMF522Buf,0,sizeof(ucComMF522Buf)); // clear buffer
294 
295  ucComMF522Buf[0] = PICC_READ; // 0x30 = read
296  ucComMF522Buf[1] = addr; // add address to read
297  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); // add crc
298 
299  // perform read operation from card
300  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen,1);
301 
302  // check status and received bits / bytes 0x90 => 144 / 8 => 18 bytes => 16 data bytes + 2 CRC
303  if ((status == TAG_OK) && (unLen == 0x90))
304  {
305  // calculate CRC
306  CalulateCRC(ucComMF522Buf,16,CRC_buff); // 16 bytes should used for CRC check
307 
308 // printf("debug %02x%02x %02x%02x ",ucComMF522Buf[16],ucComMF522Buf[17],CRC_buff[0],CRC_buff[1]);
309 
310  // check CRC is correct
311  if ((CRC_buff[0]!=ucComMF522Buf[16])||(CRC_buff[1]!=ucComMF522Buf[17]))
312  status = TAG_ERRCRC;
313 
314  else
315  {
316  // copy 16 data bytes received
317  for (i=0; i<16; i++) *(p+i) = ucComMF522Buf[i];
318  }
319  }
320  else
321  status = TAG_ERR;
322 
323  return(status);
324 }
325 /* write block ( 16 bytes) to specific address */
326 char PcdWrite(uint8_t addr, uint8_t *p )
327 {
328  char status;
329  uint8_t unLen;
330  uint8_t i,ucComMF522Buf[MAXRLEN];
331 
332  ucComMF522Buf[0] = PICC_WRITE; // a0
333  ucComMF522Buf[1] = addr; // add addr + CRC
334  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
335 
336  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen,1);
337 
338  // check for ACK
339  if ((status != TAG_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
340  { status = TAG_ERR; }
341 
342  if (status == TAG_OK)
343  {
344  for (i=0; i<16; i++) ucComMF522Buf[i] = *(p+i);
345 
346  CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
347 
348  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen,1);
349 
350  // 0xA is ACK, any other value is NAK
351  // must have received 4 bytes ??
352  if ((status != TAG_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
353  status = TAG_ERR;
354  }
355 
356  return(status);
357 }
358 
359 /* halt or haltA /deselect the current using the selected card
360  * 0x50 00 CRC-A
361  */
362 
363 char PcdHalt(void)
364 {
365  uint8_t status;
366  uint8_t unLen;
367  uint8_t ucComMF522Buf[MAXRLEN];
368 
369  ucComMF522Buf[0] = PICC_HALT; //0x50
370  ucComMF522Buf[1] = 0; //add CRC-A
371  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
372  // sent to card
373  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen,1);
374 
375  Pcd_stopcrypto1();
376 
377  return(status);
378 }
379 
380 /* Restore, decrement or increment a value block
381  * block must have been authorised before
382  * act = PICC_INCREMENT or PICC_DECREMENT or PICC_RESTORE
383  * */
384 
385 char PcdValue(uint8_t act, uint8_t addr, double value)
386 {
387  uint8_t status;
388  uint8_t unLen;
389  uint8_t ucComMF522Buf[MAXRLEN];
390 
391  // sent command and block address
392  ucComMF522Buf[0] = act;
393  ucComMF522Buf[1] = addr;
394 
395  //add CRC-A
396  CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
397 
398  // sent to card
399  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen,1);
400 
401  if (status != TAG_OK)
402  {
403  printf("ERROR - PcdValue(...) cannot send command!!!");
404  return(status);
405  }
406 
407  // sent the amount
408  ucComMF522Buf[0] = ((long long) value & (long long) 0xff);
409  ucComMF522Buf[1] = ((long long) value & (long long) 0xff00) >> 8;
410  ucComMF522Buf[2] = ((long long) value & (long long) 0xff0000) >> 16;
411  ucComMF522Buf[3] = ((long long) value & (long long) 0xff000000) >> 24;
412 
413  //add CRC-A
414  CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
415 
416  /* sent to card
417  *
418  * !!! NO check on time out !!!
419  *
420  * This necessary during data transmission with increment, decrement,
421  * transfer these commands time out as there is NAK responds
422  * to be expected from the PICC.
423  */
424 
425  status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen,0);
426 
427  if (status != TAG_OK) printf("ERROR - PcdValue(...) cannot send value!!!");
428 
429  return(status);
430 }
431 
432 /* stop with crypto1 when ready with communication after authentication */
434 {
435 
436  /* clear MIFARE Crypto-1
437  * needed after authorisation otherwise no further card can be read*/
438  ClearBitMask(Status2Reg,0x08);
439 }
440 /* check whether already authorized
441  * return
442  * 0 = authorized
443  * 1 = not authorized
444  */
446 {
447  if (ReadRawRC(Status2Reg) & 0x08) return(0);
448 
449  return(1);
450 }
451 
452 /* ISO/IEC 13239 standard:
453  *
454  * CRC-A initial value of 0x6363 / not inverted after calc (set in PcdReset)
455  *
456  * pIn = pointer to input values
457  * len = number bytes in input values
458  * pOut = store CRC calculation result.
459  *
460  */
461 void CalulateCRC(uint8_t *pIn ,uint8_t len,uint8_t *pOut )
462 {
463  uint8_t i,n;
464 
465  // clear the calcCRC is active and all data is processed bit
466  ClearBitMask(DivIrqReg,0x04);
467 
468  // cancel any other command that might be pending/executed
470 
471  // flush read/write pointers and ERRORreg BufferOvfl bit
472  SetBitMask(FIFOLevelReg,0x80);
473 
474  // fill the FIFO with the data
475  for (i=0; i<len; i++) WriteRawRC(FIFODataReg, *(pIn +i));
476 
477  // start calculation of the CRC
479 
480  // set a time out
481  i = 0xFF;
482 
483  // loop until time out of CRC has been calculated bit has been set
484  do
485  {
486  n = ReadRawRC(DivIrqReg);
487  i--;
488  }
489  while ((i!=0) && !(n&0x04));
490 
491  // read the calucated CRC value (no check on timeout, CRC is wrong anyway)
492  pOut [0] = ReadRawRC(CRCResultRegL);
493  pOut [1] = ReadRawRC(CRCResultRegM);
494 }
495 
496 /* perform a soft-reset and set the correct values */
497 /* modified by using working python as template */
498 char PcdReset(void)
499 {
500  // perform a softreset
502 
503  // give it time to settle
504  usleep(10000);
505 
506  // wait for Soft power-down to finish
507  // this ins't in the python version, but since it works
508  while (ReadRawRC(CommandReg) & 0x10);
509 
510  // Turn antenna off
511  // not in python, but ok i guess
512  PcdAntennaOff();
513 
514  // give it time to settle
515  usleep(10000);
516 
517  /* setup internal timer (used in PcdComMF522 for timeout)
518  *
519  * This TPrescaler is set to 0xa9 => 169 => 40 khz => 25us
520  * The reload value is 0x3e8 = 1000, as such : 25 ms
521  */
522 
523  /* timer mode
524  * B7 = 1 Timer start automatically at end of transmission
525  * B6/B5 = 00 Non-gated mode (no dependency on MFIN or AUX1 pin)
526  * B4 = 0 No automatic restart (comIRQReg TimeIRQ bit is set at 0)
527  * B3-B0 = 0x0 Higher 4 bits of Tprescaler divider
528  */
529  //WriteRawRC(TModeReg,0x80); // changed value to 0x8D from 0x80
530  WriteRawRC(TModeReg,0x8D); // changed value to 0x8D from 0x80
531 
532  /* B7 -B0 = Tprescaler LSB 7 bits of divider */
533  // changed value from 0xA9 to 0x3E
534  //WriteRawRC(TPrescalerReg,0xA9); // + TmodeReg[3...0]
535  WriteRawRC(TPrescalerReg,0x3E); // + TmodeReg[3...0]
536 
537  /* time reload value, lower 8 bits */
538  //WriteRawRC(TReloadRegL, 0xE8); //changed value from 0xE8 to 30 (dec)
539  WriteRawRC(TReloadRegL, 30); //changed value from 0xE8 to 30 (dec)
540 
541  /* timer reload value, higher 8 bits */
542  //WriteRawRC(TReloadRegH, 0x03); //changed value from 0x03 to 0 (dec)
543  WriteRawRC(TReloadRegH, 0); //changed value from 0x03 to 0 (dec)
544 
545  /* forces a 100% ASK modulation independent of modGsPReg (Type-A)
546  * ASK = Amplitude Shift Keying */
547  // same value, in python called TxAutoReg
548  WriteRawRC(TxASKReg,0x40);
549 
550  /* Preset value
551  * B7 0 CRC does not start with MSB first
552  * B6 0 Not used
553  * B5 1 transmitter can only be started if RF field is generated
554  * B4 0 not used
555  * B3 1 Polarity on MFIN is active high
556  * B2 1 not used
557  * B1 B0 01 CRC preset value 6363 (TYPE-A)*/
558  //changed value from 0x2D to 0x3D
559  //WriteRawRC(ModeReg,0x2D); //CRC initialize value
560  WriteRawRC(ModeReg,0x3D); //CRC initialize value
561 
562  // Turn antenna on
563  PcdAntennaOn();
564 
565  return(TAG_OK);
566 }
567 
568 /* reads a value over SPI
569  * Bit 7 is set to 1 indicating read operation
570  * Bits 6 to 1 define the address
571  * Bit 0 is set to 0
572  */
573 uint8_t ReadRawRC(uint8_t Address)
574 {
575  uint8_t in_buff[2] = {0};
576  uint8_t out_buff[2] = {0};
577 
578  in_buff[0] = ((Address<<1)&0x7E)|0x80;
579  //printf("addr: %d, translated to: %d\n", Address, buff[0]);
580  spi->xfer(in_buff, 2, out_buff, 2);
581  //spi->read(buff, 2);
582  //printf("val: %d %d\n", buff[0], buff[1]);
583  //printf("out buff: %.2x %.2x\n", out_buff[0], out_buff[1]);
584  return (uint8_t) out_buff[1];
585  //return (uint8_t)buff[0];
586 }
587 
588 /* sent a value over SPI
589  * Bit 7 is set to 0 indicating write operation
590  * Bits 6 to 1 define the address
591  * Bit 0 is set to 0
592  */
593 uint8_t WriteRawRC(uint8_t Address, uint8_t value)
594 {
595  uint8_t buff[2];
596 
597  buff[0] = ((Address<<1)&0x7E);
598  buff[1] = value;
599 
600  // using only write, because it doesn't read anyting
601  spi->write(buff, 2);
602 
603  // return error register
604  return(ReadRawRC(ErrorReg));
605 
606 }
607 
608 // set bits in RC522 registers
609 void SetBitMask(uint8_t reg,uint8_t mask)
610 {
611  char tmp = 0x0;
612  tmp = ReadRawRC(reg);
613  WriteRawRC(reg,tmp | mask); // set bit mask
614 
615 }
616 
617 //clear bits in RC522 registers
618 void ClearBitMask(uint8_t reg,uint8_t mask)
619 {
620  char tmp = 0x0;
621  tmp = ReadRawRC(reg);
622  WriteRawRC(reg, tmp & ~mask); // clear bit mask
623 }
624 
625 // communicate with card
626 char PcdComMF522(uint8_t Command,
627  uint8_t *pIn , // buffer to sent
628  uint8_t InLenByte, // num bytes to sent
629  uint8_t *pOut , // buffer to receive
630  uint8_t *pOutLenBit , // num bits stored in receive buffer
631  int CheckTimeout) // check timeout =1
632 {
633 
634  char status = TAG_ERR; // return code
635  uint8_t irqEn = 0x00; // IRQ register content
636  uint8_t waitFor = 0x00;
637  uint8_t lastBits;
638  uint8_t n;
639  uint32_t i;
640  uint8_t PcdErr;
641 
642  switch (Command)
643  {
644  case PCD_AUTHENT:
645  irqEn = 0x12; // enable Idle and low alert interrupts
646  waitFor = 0x10; // expect interrupt to continue (idle interrupt)
647  break;
648  case PCD_TRANSCEIVE:
649  irqEn = 0x77; // enable all alert except high alert interrupt
650  waitFor = 0x30; // expect interrupt to continue (Idle and received end of valid data stream)
651  break;
652  default:
653  printf("FATAL - RC522 unrecognized command in PcdComMF522(...)");
654  exit(1); // TODO alternative instead exit
655  }
656  /*
657  * B7 1 IRQ inverted with respect to Status1reg IRq bit
658  * B6 1 allows transmitter interrupt request
659  * B5 1 Allow receiver interrupt request
660  * B4 1 allow idle interrupt request
661  * B3 1 allow high alert interrupt request
662  * B2 1 allows low alert interrupt request
663  * B1 1 allow error interrupt request
664  * B0 1 allows time interrupt request
665  */
666  WriteRawRC(ComIEnReg,irqEn|0x80);
667 
668  /* clear IRQ inverted respect to status1reg
669  * indicates that the marked bits in the ComIrqReg register are set */
670  ClearBitMask(ComIrqReg,0x80);
671 
672  /* Flushbuffer / clear FIFO*/
673  SetBitMask(FIFOLevelReg,0x80);
674 
675  /* sent command to set RC522 to Idle & cancel any pending execution */
677 
678  /* write data in FIFO data for the length of buffer*/
679  for (i=0; i<InLenByte; i++) WriteRawRC(FIFODataReg, pIn [i]);
680 
681  /* sent the command */
682  WriteRawRC(CommandReg, Command);
683 
684  /* start the transmission of data in Transceive mode*/
685  if (Command == PCD_TRANSCEIVE) SetBitMask(BitFramingReg,0x80);
686 
687  i = 150;
688 
689  /* as long as not count down
690  * Time out has not happened
691  * and other possible wait for interrupts
692  * n&01 = time out has happened (timeout was set in PcdReset as 24ms)
693  * n&waitfor = good interrupts to happen
694  */
695 
696  do
697  {
698  usleep(200);
699 
700  /* read interrupt register */
701  n = ReadRawRC(ComIrqReg);
702  i--;
703  }
704  while (i!=0 && (! (n&0x01)) && (!(n&waitFor)));
705 
706  /* removing start data transmission in transceive */
707  if (Command == PCD_TRANSCEIVE) ClearBitMask(BitFramingReg,0x80);
708 
709  /* maybe something received as no count-down */
710  if (i != 0)
711  {
712  PcdErr=ReadRawRC(ErrorReg);
713 
714  /* check for parity or buffer overflow/protocol err */
715  if (!(PcdErr & 0x11))
716  {
717  status = TAG_OK;
718 
719  /* time out had triggered (~24 ms) */
720  if (n & irqEn & 0x01)
721  {
722  /* necessary to discard during data transmission with increment, decrement,
723  * transfer these commands time out as there is NAK responds
724  * to be expected. */
725  if (CheckTimeout) status = TAG_NOTAG;
726  }
727  else if (Command == PCD_TRANSCEIVE)
728  {
729  /* get # of bytes received in FIFO */
730  n = ReadRawRC(FIFOLevelReg);
731 
732  /* get # valid bits in the last byte 00 = all*/
733  lastBits = ReadRawRC(ControlReg) & 0x07;
734 
735  /* determine the correct amount of bits */
736  if (lastBits) *pOutLenBit = (n-1)*8 + lastBits;
737  else *pOutLenBit = n*8;
738 
739  /* set counter start and maximum good */
740  if (n == 0) n = 1;
741  if (n > MAXRLEN) n = MAXRLEN;
742 
743  /* read the receive information */
744  for (i=0; i < n; i++) {
745  pOut [i] = ReadRawRC(FIFODataReg);
746 
747  /* Based on field testing, usleep seems to be needed from some cards / systems
748  * The usleep code itself takes 70us and as such this takes 80us
749  * that is about the same as the printf underneath and seemed to be necessary
750  * during a field test.
751  *
752  * don't ask me why.... */
753 
754  //usleep(10);
755 
756  //printf ("%s :%d .%02X\n",__func__,i, pOut[i]);
757  }
758 
759  /* Given the comment above, an extra delay can now be requested on the command
760  * line with -E. The 80us mentioned above was resulting in 400us or 500us depending
761  * on the number of databytes that were received.
762  *
763  * allow for 500us extra delay for slow card to recover */
764  if (extra_delay) usleep(500);
765  }
766  }
767  else {
768  printf("Parity or buffer overflow\n");
769  status = TAG_ERR;
770  }
771 
772  /* collision error detected ?*/
773  if (PcdErr & 0x08)
774  {
775  printf("ERROR - RC522 PcdComRF522 Collision!"); // debug print
776  status = TAG_COLLISION;
777  }
778  }
779 
780  SetBitMask(ControlReg,0x80); // stop timer now
781 // printf("%s : status %02x, length of message %d, PCD err %02x\n"
782 // ,__func__, status,*pOutLenBit, PcdErr);
783 
784  return status;
785 }
786 
787 /* Turn tX2RFE on, TX1RFE on (unless on already !)
788  * output signal on pin TX1 and TX2 delivers the 13.56MHZ energy carrier modulated
789  * by the transmission data*/
790 void PcdAntennaOn(void)
791 {
792  // check if not on already
793  if (!(ReadRawRC(TxControlReg) & 0x03))
794  SetBitMask(TxControlReg, 0x03);
795 }
796 
797 /* turn off antenna */
798 void PcdAntennaOff(void)
799 {
800  ClearBitMask(TxControlReg, 0x03);
801 }
char PcdRead(uint8_t addr, uint8_t *p)
Definition: rc522.cpp:286
char PcdAnticoll(uint8_t cascade, uint8_t *pSnr)
Definition: rc522.cpp:89
char PcdValue(uint8_t act, uint8_t addr, double value)
Definition: rc522.cpp:385
int PcdCheckAuth()
Definition: rc522.cpp:445
char PcdHalt(void)
Definition: rc522.cpp:363
char PcdAuthState(uint8_t auth_mode, uint8_t addr, uint8_t *pKey, uint8_t *pSnr)
Definition: rc522.cpp:259
char PcdReset(void)
Definition: rc522.cpp:498
char PcdWrite(uint8_t addr, uint8_t *p)
Definition: rc522.cpp:326
char PcdComMF522(uint8_t Command, uint8_t *pIn, uint8_t InLenByte, uint8_t *pOut, uint8_t *pOutLenBit, int CheckTimeout)
Definition: rc522.cpp:626
SPI * spi
Definition: rc522.cpp:36
void ClearBitMask(uint8_t reg, uint8_t mask)
Definition: rc522.cpp:618
void InitRc522(SPI *p_spi)
Definition: rc522.cpp:39
char PcdRequest(uint8_t req_code, uint8_t *pTagType)
Definition: rc522.cpp:47
ewf int extra_delay
Definition: rc522.cpp:35
void PcdAntennaOn(void)
Definition: rc522.cpp:790
void PcdAntennaOff(void)
Definition: rc522.cpp:798
uint8_t WriteRawRC(uint8_t Address, uint8_t value)
Definition: rc522.cpp:593
void Pcd_stopcrypto1()
Definition: rc522.cpp:433
void SetBitMask(uint8_t reg, uint8_t mask)
Definition: rc522.cpp:609
uint8_t ReadRawRC(uint8_t Address)
Definition: rc522.cpp:573
char PcdSelect(uint8_t cascade, uint8_t *pSnr, uint8_t *SAK)
Definition: rc522.cpp:187
void CalulateCRC(uint8_t *pIn, uint8_t len, uint8_t *pOut)
Definition: rc522.cpp:461
#define Status2Reg
Definition: rc522.h:75
#define ComIEnReg
Definition: rc522.h:69
#define ControlReg
Definition: rc522.h:79
#define FIFOLevelReg
Definition: rc522.h:77
#define TAG_ERR
Definition: rc522.h:127
#define TAG_OK
Definition: rc522.h:125
#define TxASKReg
Definition: rc522.h:87
#define ModeReg
Definition: rc522.h:83
#define PCD_TRANSCEIVE
Definition: rc522.h:42
#define PICC_WRITE
Definition: rc522.h:55
#define TxControlReg
Definition: rc522.h:86
#define PICC_READ
Definition: rc522.h:54
#define TPrescalerReg
Definition: rc522.h:104
#define ComIrqReg
Definition: rc522.h:71
#define TReloadRegH
Definition: rc522.h:105
#define FIFODataReg
Definition: rc522.h:76
#define TReloadRegL
Definition: rc522.h:106
#define MAXRLEN
Definition: rc522.h:64
#define PCD_RESETPHASE
Definition: rc522.h:43
#define TAG_NOTAG
Definition: rc522.h:126
#define TAG_ERRCRC
Definition: rc522.h:128
#define CommandReg
Definition: rc522.h:68
#define ErrorReg
Definition: rc522.h:73
#define TAG_COLLISION
Definition: rc522.h:129
#define PCD_CALCCRC
Definition: rc522.h:44
#define DivIrqReg
Definition: rc522.h:72
#define PCD_IDLE
Definition: rc522.h:38
#define TModeReg
Definition: rc522.h:103
#define CRCResultRegM
Definition: rc522.h:96
#define PCD_AUTHENT
Definition: rc522.h:39
#define CRCResultRegL
Definition: rc522.h:97
#define CollReg
Definition: rc522.h:81
#define PICC_HALT
Definition: rc522.h:60
#define BitFramingReg
Definition: rc522.h:80