Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

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