Skip to content
This repository was archived by the owner on Jun 8, 2022. It is now read-only.

Commit 1ded2e4

Browse files
committed
Version 1.8
1 parent 000843a commit 1ded2e4

6 files changed

+309
-8
lines changed

PN5180.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -336,11 +336,14 @@ bool PN5180::sendData(uint8_t *data, int len, uint8_t validBits) {
336336
* preceding an RF data reception, no exception is raised but the data read back from the
337337
* reception buffer is invalid. If the condition is not fulfilled, an exception is raised.
338338
*/
339-
uint8_t * PN5180::readData(int len) {
339+
uint8_t * PN5180::readData(int len, uint8_t *buffer /* = NULL */) {
340340
if (len > 508) {
341341
Serial.println(F("*** FATAL: Reading more than 508 bytes is not supported!"));
342342
return 0L;
343343
}
344+
if (NULL == buffer) {
345+
buffer = readBuffer;
346+
}
344347

345348
PN5180DEBUG(F("Reading Data (len="));
346349
PN5180DEBUG(len);
@@ -349,13 +352,13 @@ uint8_t * PN5180::readData(int len) {
349352
uint8_t cmd[2] = { PN5180_READ_DATA, 0x00 };
350353

351354
SPI.beginTransaction(PN5180_SPI_SETTINGS);
352-
transceiveCommand(cmd, 2, readBuffer, len);
355+
transceiveCommand(cmd, 2, buffer, len);
353356
SPI.endTransaction();
354357

355358
#ifdef DEBUG
356359
PN5180DEBUG(F("Data read: "));
357360
for (int i=0; i<len; i++) {
358-
PN5180DEBUG(formatHex(readBuffer[i]));
361+
PN5180DEBUG(formatHex(buffer[i]));
359362
PN5180DEBUG(" ");
360363
}
361364
PN5180DEBUG("\n");

PN5180.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class PN5180 {
103103
/* cmd 0x09 */
104104
bool sendData(uint8_t *data, int len, uint8_t validBits = 0);
105105
/* cmd 0x0a */
106-
uint8_t * readData(int len);
106+
uint8_t * readData(int len, uint8_t *buffer = NULL);
107107

108108
/* cmd 0x11 */
109109
bool loadRFConfig(uint8_t txConf, uint8_t rxConf);

PN5180ISO14443.cpp

+242
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
// NAME: PN5180ISO14443.h
2+
//
3+
// DESC: ISO14443 protocol on NXP Semiconductors PN5180 module for Arduino.
4+
//
5+
// Copyright (c) 2019 by Dirk Carstensen. All rights reserved.
6+
//
7+
// This file is part of the PN5180 library for the Arduino environment.
8+
//
9+
// This library is free software; you can redistribute it and/or
10+
// modify it under the terms of the GNU Lesser General Public
11+
// License as published by the Free Software Foundation; either
12+
// version 2.1 of the License, or (at your option) any later version.
13+
//
14+
// This library is distributed in the hope that it will be useful,
15+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
// Lesser General Public License for more details.
18+
//
19+
// #define DEBUG 1
20+
21+
#include <Arduino.h>
22+
#include "PN5180ISO14443.h"
23+
#include <PN5180.h>
24+
#include "Debug.h"
25+
26+
PN5180ISO14443::PN5180ISO14443(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin)
27+
: PN5180(SSpin, BUSYpin, RSTpin) {
28+
}
29+
30+
bool PN5180ISO14443::setupRF() {
31+
PN5180DEBUG(F("Loading RF-Configuration...\n"));
32+
if (loadRFConfig(0x00, 0x80)) { // ISO14443 parameters
33+
PN5180DEBUG(F("done.\n"));
34+
}
35+
else return false;
36+
37+
PN5180DEBUG(F("Turning ON RF field...\n"));
38+
if (setRF_on()) {
39+
PN5180DEBUG(F("done.\n"));
40+
}
41+
else return false;
42+
43+
return true;
44+
}
45+
46+
uint16_t PN5180ISO14443::rxBytesReceived() {
47+
uint32_t rxStatus;
48+
uint16_t len = 0;
49+
readRegister(RX_STATUS, &rxStatus);
50+
// Lower 9 bits has length
51+
len = (uint16_t)(rxStatus & 0x000001ff);
52+
return len;
53+
}
54+
/*
55+
* buffer : must be 10 byte array
56+
* buffer[0-1] is ATQA
57+
* buffer[2] is sak
58+
* buffer[3..6] is 4 byte UID
59+
* buffer[7..9] is remaining 3 bytes of UID for 7 Byte UID tags
60+
* kind : 0 we send REQA, 1 we send WUPA
61+
*
62+
* return value: the uid length:
63+
* - zero if no tag was recognized
64+
* - single Size UID (4 byte)
65+
* - double Size UID (7 byte)
66+
* - triple Size UID (10 byte) - not yet supported
67+
*/
68+
uint8_t PN5180ISO14443::activateTypeA(uint8_t *buffer, uint8_t kind) {
69+
uint8_t cmd[7];
70+
uint8_t uidLength = 0;
71+
// Load standard TypeA protocol
72+
if (!loadRFConfig(0x0, 0x80))
73+
return 0;
74+
75+
// OFF Crypto
76+
if (!writeRegisterWithAndMask(SYSTEM_CONFIG, 0xFFFFFFBF))
77+
return 0;
78+
// Clear RX CRC
79+
if (!writeRegisterWithAndMask(CRC_RX_CONFIG, 0xFFFFFFFE))
80+
return 0;
81+
// Clear TX CRC
82+
if (!writeRegisterWithAndMask(CRC_TX_CONFIG, 0xFFFFFFFE))
83+
return 0;
84+
//Send REQA/WUPA, 7 bits in last byte
85+
cmd[0] = (kind == 0) ? 0x26 : 0x52;
86+
if (!sendData(cmd, 1, 0x07))
87+
return 0;
88+
// READ 2 bytes ATQA into buffer
89+
if (!readData(2, buffer))
90+
return 0;
91+
//Send Anti collision 1, 8 bits in last byte
92+
cmd[0] = 0x93;
93+
cmd[1] = 0x20;
94+
if (!sendData(cmd, 2, 0x00))
95+
return 0;
96+
//Read 5 bytes, we will store at offset 2 for later usage
97+
if (!readData(5, cmd+2))
98+
return 0;
99+
//Enable RX CRC calculation
100+
if (!writeRegisterWithOrMask(CRC_RX_CONFIG, 0x01))
101+
return 0;
102+
//Enable TX CRC calculation
103+
if (!writeRegisterWithOrMask(CRC_TX_CONFIG, 0x01))
104+
return 0;
105+
//Send Select anti collision 1, the remaining bytes are already in offset 2 onwards
106+
cmd[0] = 0x93;
107+
cmd[1] = 0x70;
108+
if (!sendData(cmd, 7, 0x00))
109+
return 0;
110+
//Read 1 byte SAK into buffer[2]
111+
if (!readData(1, buffer+2))
112+
return 0;
113+
// Check if the tag is 4 Byte UID or 7 byte UID and requires anti collision 2
114+
// If Bit 3 is 0 it is 4 Byte UID
115+
if ((buffer[2] & 0x04) == 0) {
116+
// Take first 4 bytes of anti collision as UID store at offset 3 onwards. job done
117+
for (int i = 0; i < 4; i++) buffer[3+i] = cmd[2 + i];
118+
uidLength = 4;
119+
}
120+
else {
121+
// Take First 3 bytes of UID, Ignore first byte 88(CT)
122+
if (cmd[2] != 0x88)
123+
return 0;
124+
for (int i = 0; i < 3; i++) buffer[3+i] = cmd[3 + i];
125+
// Clear RX CRC
126+
if (!writeRegisterWithAndMask(CRC_RX_CONFIG, 0xFFFFFFFE))
127+
return 0;
128+
// Clear TX CRC
129+
if (!writeRegisterWithAndMask(CRC_TX_CONFIG, 0xFFFFFFFE))
130+
return 0;
131+
// Do anti collision 2
132+
cmd[0] = 0x95;
133+
cmd[1] = 0x20;
134+
if (!sendData(cmd, 2, 0x00))
135+
return 0;
136+
//Read 5 bytes. we will store at offset 2 for later use
137+
if (!readData(5, cmd+2))
138+
return 0;
139+
// first 4 bytes belongs to last 4 UID bytes, we keep it.
140+
for (int i = 0; i < 4; i++) {
141+
buffer[6 + i] = cmd[2+i];
142+
}
143+
//Enable RX CRC calculation
144+
if (!writeRegisterWithOrMask(CRC_RX_CONFIG, 0x01))
145+
return 0;
146+
//Enable TX CRC calculation
147+
if (!writeRegisterWithOrMask(CRC_TX_CONFIG, 0x01))
148+
return 0;
149+
//Send Select anti collision 2
150+
cmd[0] = 0x95;
151+
cmd[1] = 0x70;
152+
if (!sendData(cmd, 7, 0x00))
153+
return 0;
154+
//Read 1 byte SAK into buffer[2]
155+
if (!readData(1, buffer + 2))
156+
return 0;
157+
uidLength = 7;
158+
}
159+
return uidLength;
160+
}
161+
162+
bool PN5180ISO14443::mifareBlockRead(uint8_t blockno, uint8_t *buffer) {
163+
bool success = false;
164+
uint16_t len;
165+
uint8_t cmd[2];
166+
// Send mifare command 30,blockno
167+
cmd[0] = 0x30;
168+
cmd[1] = blockno;
169+
if (!sendData(cmd, 2, 0x00))
170+
return false;
171+
//Check if we have received any data from the tag
172+
delay(5);
173+
len = rxBytesReceived();
174+
if (len == 16) {
175+
// READ 16 bytes into buffer
176+
if (readData(16, buffer))
177+
success = true;
178+
}
179+
return success;
180+
}
181+
182+
183+
uint8_t PN5180ISO14443::mifareBlockWrite16(uint8_t blockno, uint8_t *buffer) {
184+
uint8_t cmd[1];
185+
// Clear RX CRC
186+
writeRegisterWithAndMask(CRC_RX_CONFIG, 0xFFFFFFFE);
187+
188+
// Mifare write part 1
189+
cmd[0] = 0xA0;
190+
cmd[1] = blockno;
191+
sendData(cmd, 2, 0x00);
192+
readData(1, cmd);
193+
194+
// Mifare write part 2
195+
sendData(buffer,16, 0x00);
196+
delay(10);
197+
198+
// Read ACK/NAK
199+
readData(1, cmd);
200+
201+
//Enable RX CRC calculation
202+
writeRegisterWithOrMask(CRC_RX_CONFIG, 0x1);
203+
return cmd[0];
204+
}
205+
206+
bool PN5180ISO14443::mifareHalt() {
207+
uint8_t cmd[1];
208+
//mifare Halt
209+
cmd[0] = 0x50;
210+
cmd[1] = 0x00;
211+
sendData(cmd, 2, 0x00);
212+
return true;
213+
}
214+
215+
uint8_t PN5180ISO14443::readCardSerial(uint8_t *buffer) {
216+
217+
uint8_t response[10];
218+
uint8_t uidLength;
219+
// Always return 10 bytes
220+
// Offset 0..1 is ATQA
221+
// Offset 2 is SAK.
222+
// UID 4 bytes : offset 3 to 6 is UID, offset 7 to 9 to Zero
223+
// UID 7 bytes : offset 3 to 9 is UID
224+
for (int i = 0; i < 10; i++) response[i] = 0;
225+
uidLength = activateTypeA(response, 1);
226+
if ((response[0] == 0xFF) && (response[1] == 0xFF))
227+
return 0;
228+
// check for valid uid
229+
if ((response[3] == 0x00) && (response[4] == 0x00) && (response[5] == 0x00) && (response[6] == 0x00))
230+
return 0;
231+
if ((response[3] == 0xFF) && (response[4] == 0xFF) && (response[5] == 0xFF) && (response[6] == 0xFF))
232+
return 0;
233+
for (int i = 0; i < 7; i++) buffer[i] = response[i+3];
234+
mifareHalt();
235+
return uidLength;
236+
}
237+
238+
bool PN5180ISO14443::isCardPresent() {
239+
uint8_t buffer[10];
240+
return (readCardSerial(buffer) >=4);
241+
}
242+

PN5180ISO14443.h

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// NAME: PN5180ISO14443.h
2+
//
3+
// DESC: ISO14443 protocol on NXP Semiconductors PN5180 module for Arduino.
4+
//
5+
// Copyright (c) 2019 by Dirk Carstensen. All rights reserved.
6+
//
7+
// This file is part of the PN5180 library for the Arduino environment.
8+
//
9+
// This library is free software; you can redistribute it and/or
10+
// modify it under the terms of the GNU Lesser General Public
11+
// License as published by the Free Software Foundation; either
12+
// version 2.1 of the License, or (at your option) any later version.
13+
//
14+
// This library is distributed in the hope that it will be useful,
15+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
// Lesser General Public License for more details.
18+
//
19+
#ifndef PN5180ISO14443_H
20+
#define PN5180ISO14443_H
21+
22+
#include "PN5180.h"
23+
24+
class PN5180ISO14443 : public PN5180 {
25+
26+
public:
27+
PN5180ISO14443(uint8_t SSpin, uint8_t BUSYpin, uint8_t RSTpin);
28+
29+
private:
30+
uint16_t rxBytesReceived();
31+
public:
32+
// Mifare TypeA
33+
uint8_t activateTypeA(uint8_t *buffer, uint8_t kind);
34+
bool mifareBlockRead(uint8_t blockno,uint8_t *buffer);
35+
uint8_t mifareBlockWrite16(uint8_t blockno, uint8_t *buffer);
36+
bool mifareHalt();
37+
/*
38+
* Helper functions
39+
*/
40+
public:
41+
bool setupRF();
42+
uint8_t readCardSerial(uint8_t *buffer);
43+
bool isCardPresent();
44+
};
45+
46+
#endif /* PN5180ISO14443_H */

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,19 @@ Arduino Uno / Arduino ESP-32 library for PN5180-NFC Module from NXP Semiconducto
77

88
Release Notes:
99

10+
Version 1.8 - 19.08.2021
11+
12+
* Added readData and ISO1443 support.
13+
14+
Version 1.7 - 12.07.2021
15+
16+
* Migrated branch from Dirk Carstensen for ISO14443 tags to the library.
17+
* See https://github.com/tueddy/PN5180-Library/tree/ISO14443
18+
1019
Version 1.6 - 13.03.2021
1120

1221
* Added PN5180::writeEEPROM
13-
22+
1423
Version 1.5 - 29.01.2020
1524

1625
* Fixed offset in readSingleBlock. Was off by 1.

keywords.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
#######################################
22
# Syntax Coloring Map For PN5180-Library
3-
#######################################
3+
#######################################
44
# Class
55
#######################################
66

77
PN5180 KEYWORD1
88
PN5180ISO15693 KEYWORD1
9+
PN5180ISO14443 KEYWORD1
910

1011
#######################################
11-
# Methods and Functions
12-
#######################################
12+
# Methods and Functions
13+
#######################################
1314

1415
writeRegister KEYWORD2
1516
writeRegisterWithOrMask KEYWORD2

0 commit comments

Comments
 (0)