Subversion Repositories Code-Repo

Rev

Rev 158 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
155 Kevin 1
#include <xc.h>
2
#include <string.h>
3
#include <delays.h>
4
#include "defines.h"
158 Kevin 5
#include "sensor_nfc_PN532.h"
6
#include "base_I2C.h"
155 Kevin 7
 
8
static NFC_DATA *nfc_data_p;
9
 
10
// Const value arrays for comparison use
11
static const char pn532response_firmwarevers[] = {0x01, 0x00, 0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
12
static const char pn532ack[] = {0x01, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
13
 
14
void NFC_Init(NFC_DATA *data) {
15
    nfc_data_p = data;
16
 
17
    NFC_IRQ_TRIS = 1; // IRQ Pin is RC5
18
 
19
/* NFC reset is disabled due to lack of pins */
20
//    NFC_RESET_TRIS = 0; // Reset Pin is RC2
21
//
22
//    // Reset the PN532
23
//    NFC_RESET_LAT = 1;
24
//    NFC_RESET_LAT = 0;
25
//    Delay10TCYx(1);
26
//    NFC_RESET_LAT = 1;
27
}
28
 
29
// Configures the SAM (Secure Access Module)
30
char NFC_SAMConfig() {
31
    nfc_data_p->packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
32
    nfc_data_p->packetbuffer[1] = 0x01; // Normal mode
33
    nfc_data_p->packetbuffer[2] = 0x14; // Timeout 50ms * 20 = 1s
34
    nfc_data_p->packetbuffer[3] = 0x01; // Use IRQ pin
35
 
36
    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 4))
37
        return 0;
38
 
39
    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 8);
40
 
41
    return (nfc_data_p->packetbuffer[7] == 0x15);
42
}
43
 
44
// Checks the firmware version of the PN5xx chip
45
NFC_FIRMWARE_VERSION NFC_Get_Firmware_Version(void) {
46
    NFC_FIRMWARE_VERSION response = {0, 0, 0, 0};
47
 
48
    // Create and send command
49
    nfc_data_p->packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
50
 
51
    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 1))
52
        return response;
53
 
54
    // Read back data from the PN532
55
    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 12);
56
 
57
    // Compare and check returned values
58
    if (strncmp((char *) nfc_data_p->packetbuffer, (char *) pn532response_firmwarevers, 8) != 0)
59
        return response;
60
 
61
    // Save and return info
62
    response.IC = nfc_data_p->packetbuffer[8];
63
    response.Ver = nfc_data_p->packetbuffer[9];
64
    response.Rev = nfc_data_p->packetbuffer[10];
65
    response.Support = nfc_data_p->packetbuffer[11];
66
 
67
    return response;
68
}
69
 
70
// Sends a command and waits a specified period for the ACK
71
char NFC_Send_Command_Check_Ack(char *cmd, char cmdlen) {
72
    unsigned int timer = 0;
73
 
74
    // Write the command
75
    NFC_I2C_Write_Cmd(cmd, cmdlen);
76
 
77
    // Wait for chip to be ready
78
    while (NFC_I2C_Read_Status() != PN532_I2C_READY) {
79
        if (PN532_TIMEOUT != 0) {
80
            timer += 1;
81
            if (timer > PN532_TIMEOUT)
82
                return 0;
83
        }
84
        Delay10TCYx(1);
85
    }
86
 
87
    // Check ACK
88
    if (!NFC_I2C_Read_ACK()) {
89
        return 0;
90
    }
91
 
92
    return 1;
93
}
94
 
95
// Passive polling, waits for an ISO14443A target to enter the field
96
char NFC_Read_Passive_Target_ID(NFC_TargetDataMiFare *cardData) {
97
    nfc_data_p->packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
98
    nfc_data_p->packetbuffer[1] = 2; // Max 2 cards at once
99
    nfc_data_p->packetbuffer[2] = PN532_MIFARE_ISO14443A;  // Mifare only
100
 
101
    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 3))
102
        return 0;
103
 
104
    // Wait for IRQ line
105
    while (NFC_I2C_Read_Status() != PN532_I2C_READY);
106
 
107
    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 35);
108
 
109
    /* InListPassiveTarget response should be in the following format:
110
     * Byte         Description
111
     * ----------   ------------------
112
     * b0           Data ACK
113
     * b1..7        Frame header and preamble
114
     * b8           Tags found
115
     * b9..N        NFC_TargetDataMiFare[2]
116
     * bN+1..N+2    Checksum + postamble
117
     */
118
 
119
    // Check # of tags found
120
    if (!nfc_data_p->packetbuffer[8])
121
        return 0;
122
 
123
    // Save data from first card
124
    if (nfc_data_p->packetbuffer[13] == 4) {
125
        memcpy((char *)&cardData[0], (const char *)&nfc_data_p->packetbuffer[9], 9);
126
    } else {
127
        memcpy((char *)&cardData[0], (const char *)&nfc_data_p->packetbuffer[9], 12);
128
    }
129
 
130
    // Save data from second card
131
    if (nfc_data_p->packetbuffer[8] == 2) {
132
        // Offset will vary depending on length of first card
133
        if (nfc_data_p->packetbuffer[13] == 4) {
134
            if (nfc_data_p->packetbuffer[22] == 4) {
135
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[18], 9);
136
            } else {
137
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[18], 12);
138
            }
139
        } else { // Length of first UID is 7
140
            if (nfc_data_p->packetbuffer[25] == 4) {
141
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[21], 9);
142
            } else {
143
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[21], 12);
144
            }
145
        }
146
    }
147
 
148
    // Return the number of cards detected
149
    return nfc_data_p->packetbuffer[8];
150
}
151
 
152
// Active polling, returns number of cards in the field
153
char NFC_Poll_Targets(char number, char period, NFC_TargetDataMiFare *cardData) {
154
    nfc_data_p->packetbuffer[0] = PN532_COMMAND_INAUTOPOLL;
155
    nfc_data_p->packetbuffer[1] = number; // Number of polling
156
    nfc_data_p->packetbuffer[2] = period; // Polling period in units of 150ms
157
    nfc_data_p->packetbuffer[3] = 0x10; // Check for Mifare cards only
158
 
159
    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 4))
160
        return 0;
161
 
162
    // Wait for IRQ line
163
    while (NFC_I2C_Read_Status() != PN532_I2C_READY);
164
 
165
    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 37);
166
 
167
    /* InAutoPoll response should be in the following format:
168
     * Byte         Description
169
     * ----------   ------------------
170
     * b0           Data ACK
171
     * b1..7        Frame header and preamble
172
     * b6           Tags found
173
     * b7           Polled target type (should be 0x10 Mifare)
174
     * b8           TargetData length (1/2)
175
     * b9..N        NFC_TargetDataMiFare[1/2]
176
     * bN+1..N+2    Checksum + postamble
177
     */
178
 
179
    // Check # of tags found
180
    if (!nfc_data_p->packetbuffer[8])
181
        return 0;
182
 
183
        // Save data from first card
184
    if (nfc_data_p->packetbuffer[15] == 4) {
185
        memcpy((char *)&cardData[0], (const char *)&nfc_data_p->packetbuffer[11], 9);
186
    } else {
187
        memcpy((char *)&cardData[0], (const char *)&nfc_data_p->packetbuffer[11], 12);
188
    }
189
 
190
    // Save data from second card
191
    if (nfc_data_p->packetbuffer[8] == 2) {
192
        // Offset will vary depending on length of first card
193
        if (nfc_data_p->packetbuffer[15] == 4) {
194
            if (nfc_data_p->packetbuffer[26] == 4) {
195
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[22], 9);
196
            } else {
197
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[22], 12);
198
            }
199
        } else {
200
            if (nfc_data_p->packetbuffer[29] == 4) {
201
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[25], 9);
202
            } else {
203
                memcpy((char *)&cardData[1], (const char *)&nfc_data_p->packetbuffer[25], 12);
204
            }
205
        }
206
    }
207
 
208
    // Return the number of cards detected
209
    return nfc_data_p->packetbuffer[8];
210
}
211
 
212
//// Indicates whether the specified block number is the first block
213
////      in the sector (block 0 relative to the current sector)
214
//char NFC_mifareclassic_IsFirstBlock(unsigned long uiBlock) {
215
//    // Test if we are in the small or big sectors
216
//    if (uiBlock < 128)
217
//        return ((uiBlock) % 4 == 0);
218
//    else
219
//        return ((uiBlock) % 16 == 0);
220
//}
221
 
222
//// Indicates whether the specified block number is the sector trailer
223
//char NFC_mifareclassic_IsTrailerBlock(unsigned long uiBlock) {
224
//    // Test if we are in the small or big sectors
225
//    if (uiBlock < 128)
226
//        return ((uiBlock + 1) % 4 == 0);
227
//    else
228
//        return ((uiBlock + 1) % 16 == 0);
229
//}
230
 
231
//// Tries to authenticate a block of memory on a MIFARE card using the INDATAEXCHANGE command
232
//char NFC_mifareclassic_AuthenticateBlock(char *uid, char uidLen, unsigned long blockNumber, char keyNumber, char *keyData) {
233
//    // See section 7.3.8 of the PN532 User Manual
234
//    // blockNumber = The block number to authenticate.  (0..63 for 1KB cards, and 0..255 for 4KB cards)\
235
//    // keyNumber = Which key type to use during authentication (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
236
//    // keyData = Pointer to a byte array containing the 6 byte key value
237
//
238
//    // Assemble frame data
239
//    nfc_data_p->packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
240
//    nfc_data_p->packetbuffer[1] = 1; /* Max card numbers */
241
//    nfc_data_p->packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_A : MIFARE_CMD_AUTH_B;
242
//    nfc_data_p->packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
243
//    for (char i = 0; i < 6; i++) {
244
//        nfc_data_p->packetbuffer[4 + i] = keyData[i];
245
//    }
246
//    for (char i = 0; i < uidLen; i++) {
247
//        nfc_data_p->packetbuffer[10 + i] = uid[i];
248
//    }
249
//
250
//    // Send frame and check for ACK
251
//    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 10 + uidLen))
252
//        return 0;
253
//
254
//    // Read response from PN532
255
//    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 12);
256
//
257
//    return 1;
258
//}
259
 
260
//// Tries to read an entire 16-byte data block at the specified block address
261
//char NFC_mifareclassic_ReadDataBlock(char blockNumber, char *data) {
262
//    // Assemble frame data
263
//    nfc_data_p->packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
264
//    nfc_data_p->packetbuffer[1] = 1; /* Card number */
265
//    nfc_data_p->packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
266
//    nfc_data_p->packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
267
//
268
//    // Send frame and check for ACK
269
//    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 4))
270
//        return 0;
271
//
272
//    // Read reponse
273
//    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 26);
274
//
275
//    // If byte 9 isnt 0x00 we probably have and error
276
//    if (nfc_data_p->packetbuffer[8] != 0x00) {
277
//        return 0;
278
//    }
279
//
280
//    // Copy the 16 data bytes into the data buffer
281
//    // Block contents starts at byte 10 of a valid response
282
//    for (char i = 0; i < 16; i++) {
283
//        data[i] = nfc_data_p->packetbuffer[9 + i];
284
//    }
285
//
286
//    return 1;
287
//}
288
 
289
//// Tries to write an entire 16-byte data block at the specified block address
290
//char NFC_mifareclassic_WriteDataBlock(char blockNumber, char *data) {
291
//    // Assemble frame data
292
//    nfc_data_p->packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
293
//    nfc_data_p->packetbuffer[1] = 1; /* Card number */
294
//    nfc_data_p->packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
295
//    nfc_data_p->packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
296
//    for (char i = 0; i < 16; i++) { /* Data Payload */
297
//        nfc_data_p->packetbuffer[4 + i] = data[i];
298
//    }
299
//
300
//    // Send frame and check for ACK
301
//    if (!NFC_Send_Command_Check_Ack(nfc_data_p->packetbuffer, 20))
302
//        return 0;
303
//
304
//    // Read response
305
//    NFC_I2C_Read_Data(nfc_data_p->packetbuffer, 26);
306
//
307
//    return 1;
308
//}
309
 
310
//// Formats a Mifare Classic card to store NDEF Records
311
//char NFC_mifareclassic_FormatNDEF(void) {
312
//    char sectorbuffer1[16] = {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
313
//    char sectorbuffer2[16] = {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1};
314
//    char sectorbuffer3[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
315
//
316
//    // Write blocks 1 and 2
317
//    if (!NFC_mifareclassic_WriteDataBlock(1, sectorbuffer1))
318
//        return 0;
319
//    if (!NFC_mifareclassic_WriteDataBlock(2, sectorbuffer2))
320
//        return 0;
321
//    // Write key A and access rights
322
//    if (!NFC_mifareclassic_WriteDataBlock(3, sectorbuffer3))
323
//        return 0;
324
//
325
//    return 1;
326
//}
327
 
328
//// Writes an NDEF URI Record to the specified sector (1..15)
329
///* Note that this function assumes that the Mifare Classic card is
330
//    already formatted to work as an "NFC Forum Tag" and uses a MAD1
331
//    file system.  You can use the NXP TagWriter app on Android to
332
//    properly format cards for this. */
333
//char NFC_mifareclassic_WriteNDEFURI(char sectorNumber, char uriIdentifier, const char * url) {
334
//    // uriIdentifier = The uri identifier code (0 = none, 0x01 = "http://www.", etc.)
335
//    // url = The uri text to write (max 38 characters)
336
//
337
//    // Figure out how long the string is
338
//    char len = strlen(url);
339
//
340
//    char sectorbuffer1[16] = {0x00, 0x00, 0x03, len + 5, 0xD1, 0x01, len + 1, 0x55, uriIdentifier, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
341
//    char sectorbuffer2[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
342
//    char sectorbuffer3[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
343
//    char sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
344
//
345
//    // Make sure we're within a 1K limit for the sector number
346
//    if ((sectorNumber < 1) || (sectorNumber > 15))
347
//        return 0;
348
//
349
//    // Make sure the URI payload is between 1 and 38 chars
350
//    if ((len < 1) || (len > 38))
351
//        return 0;
352
//
353
//    if (len <= 6) {
354
//        // Unlikely we'll get a url this short, but why not ...
355
//        memcpy(sectorbuffer1 + 9, url, len);
356
//        sectorbuffer1[len + 9] = 0xFE;
357
//    } else if (len == 7) {
358
//        // 0xFE needs to be wrapped around to next block
359
//        memcpy(sectorbuffer1 + 9, url, len);
360
//        sectorbuffer2[0] = 0xFE;
361
//    } else if ((len > 7) || (len <= 22)) {
362
//        // Url fits in two blocks
363
//        memcpy(sectorbuffer1 + 9, url, 7);
364
//        memcpy(sectorbuffer2, url + 7, len - 7);
365
//        sectorbuffer2[len - 7] = 0xFE;
366
//    } else if (len == 23) {
367
//        // 0xFE needs to be wrapped around to final block
368
//        memcpy(sectorbuffer1 + 9, url, 7);
369
//        memcpy(sectorbuffer2, url + 7, len - 7);
370
//        sectorbuffer3[0] = 0xFE;
371
//    } else {
372
//        // Url fits in three blocks
373
//        memcpy(sectorbuffer1 + 9, url, 7);
374
//        memcpy(sectorbuffer2, url + 7, 16);
375
//        memcpy(sectorbuffer3, url + 23, len - 24);
376
//        sectorbuffer3[len - 22] = 0xFE;
377
//    }
378
//
379
//    // Now write all three blocks back to the card
380
//    if (!(NFC_mifareclassic_WriteDataBlock(sectorNumber * 4, sectorbuffer1)))
381
//        return 0;
382
//    if (!(NFC_mifareclassic_WriteDataBlock((sectorNumber * 4) + 1, sectorbuffer2)))
383
//        return 0;
384
//    if (!(NFC_mifareclassic_WriteDataBlock((sectorNumber * 4) + 2, sectorbuffer3)))
385
//        return 0;
386
//    if (!(NFC_mifareclassic_WriteDataBlock((sectorNumber * 4) + 3, sectorbuffer4)))
387
//        return 0;
388
//
389
//    return 1;
390
//}
391
 
392
// Reads and checks for the ACK signal
393
char NFC_I2C_Read_ACK() {
394
    char buffer[7];
395
 
396
    // Check ACK
397
    NFC_I2C_Read_Data(buffer, 6);
398
 
399
    // Return if the 7 bytes matches the ACK pattern
400
    return (strncmp((char *) buffer, (char *) pn532ack, 7) == 0);
401
}
402
 
403
// Checks the IRQ pin to know if the PN532 is ready
404
char NFC_I2C_Read_Status() {
405
    if (NFC_IRQ_PORT == 1) {
406
        return PN532_I2C_BUSY;
407
    } else {
408
        return PN532_I2C_READY;
409
    }
410
}
411
 
412
// Reads n bytes of data from the PN532 via I2C
413
void NFC_I2C_Read_Data(char *buffer, char length) {
414
    char result;
415
 
416
    // Wait for IRQ to go low
417
    while (NFC_I2C_Read_Status() != PN532_I2C_READY);
418
 
419
    // Read bytes from PN532 into buffer
420
    I2C_Master_Recv(PN532_I2C_ADDRESS, length + 2);
421
    result = I2C_Get_Status();
422
    while (!result) {
423
        result = I2C_Get_Status();
424
    }
425
    I2C_Read_Buffer((char *) buffer);
426
 
427
    /* Remaining packet byte layout is as follows:
428
     Byte       Description
429
     -----      ----------------------
430
     * 0        Data ready ACK
431
     * 1        Preamble (0x00)
432
     * 2-3      Start code (0x00,0xFF)
433
     * 4        Length (TFI to N)
434
     * 5        Length Checksum (Length + LCS = 0x00)
435
     * 6        TFI (Frame identifier)
436
     *              0xD4 - Host to PN532
437
     *              0xD5 - PN532 to Host
438
     * 7-N      Data (Length - 1 bytes)
439
     * N+1      Data checksum (TFI + Data~N + DCS = 0x00)
440
     * N+2      Postamble (0x00)              */
441
}
442
 
443
// Writes a command to the PN532, automatically inserting the preamble and required frame details (checksum, len, etc.)
444
void NFC_I2C_Write_Cmd(char* cmd, char cmdlen) {
445
    char checksum;
446
    char buffer[PN532_PACKBUFFSIZ + 8];
447
    char buffer_ind = 6;
448
    cmdlen++;
449
 
450
    checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2 + PN532_HOSTTOPN532;
451
 
452
    // Fill out required frame fields
453
    buffer[0] = PN532_PREAMBLE;
454
    buffer[1] = PN532_PREAMBLE;
455
    buffer[2] = PN532_STARTCODE2;
456
    buffer[3] = cmdlen;
457
    buffer[4] = ~cmdlen + 1;
458
    buffer[5] = PN532_HOSTTOPN532;
459
 
460
 
461
    // Copy cmd to be sent
462
    for (char i = 0; i < cmdlen - 1; i++) {
463
        checksum += cmd[i];
464
        buffer[buffer_ind] = cmd[i];
465
        buffer_ind++;
466
    }
467
 
468
    buffer[buffer_ind] = ~checksum;
469
    buffer_ind++;
470
    buffer[buffer_ind] = PN532_POSTAMBLE;
471
    buffer_ind++;
472
 
473
    I2C_Master_Send(PN532_I2C_ADDRESS, buffer_ind, buffer);
474
}