Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

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