1 //-----------------------------------------------------------------------------
2 // Routines to support ISO 15693. This includes both the reader software and
3 // the `fake tag' modes, but at the moment I've implemented only the reader
4 // stuff, and that barely.
5 // Jonathan Westhues, split Nov 2006
7 // Modified by Greg Jones, Jan 2009 to perform modulation onboard in arm rather than on PC
8 // Also added additional reader commands (SELECT, READ etc.)
10 //-----------------------------------------------------------------------------
11 #include <proxmark3.h>
16 // FROM winsrc\prox.h //////////////////////////////////
17 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
19 //-----------------------------------------------------------------------------
20 // Map a sequence of octets (~layer 2 command) into the set of bits to feed
21 // to the FPGA, to transmit that command to the tag.
22 //-----------------------------------------------------------------------------
24 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
27 // 1) Unmodulated time of 56.64us
28 // 2) 24 pulses of 423.75khz
29 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
31 static const int FrameSOF
[] = {
32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
35 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
41 static const int Logic0
[] = {
47 static const int Logic1
[] = {
55 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
56 // 2) 24 pulses of 423.75khz
57 // 3) Unmodulated time of 56.64us
59 static const int FrameEOF
[] = {
64 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
65 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
70 static void CodeIso15693AsReader(BYTE
*cmd
, int n
)
76 // Give it a bit of slack at the beginning
77 for(i
= 0; i
< 24; i
++) {
89 for(i
= 0; i
< n
; i
++) {
90 for(j
= 0; j
< 8; j
+= 2) {
91 int these
= (cmd
[i
] >> j
) & 3;
141 // And slack at the end, too.
142 for(i
= 0; i
< 24; i
++) {
147 //-----------------------------------------------------------------------------
148 // The CRC used by ISO 15693.
149 //-----------------------------------------------------------------------------
150 static WORD
Crc(BYTE
*v
, int n
)
156 for(i
= 0; i
< n
; i
++) {
157 reg
= reg
^ ((DWORD
)v
[i
]);
158 for (j
= 0; j
< 8; j
++) {
160 reg
= (reg
>> 1) ^ 0x8408;
170 char *strcat(char *dest
, const char *src
)
172 size_t dest_len
= strlen(dest
);
175 for (i
= 0 ; src
[i
] != '\0' ; i
++)
176 dest
[dest_len
+ i
] = src
[i
];
177 dest
[dest_len
+ i
] = '\0';
182 ////////////////////////////////////////// code to do 'itoa'
184 /* reverse: reverse string s in place */
185 void reverse(char s
[])
189 for (i
= 0, j
= strlen(s
)-1; i
<j
; i
++, j
--) {
196 /* itoa: convert n to characters in s */
197 void itoa(int n
, char s
[])
201 if ((sign
= n
) < 0) /* record sign */
202 n
= -n
; /* make n positive */
204 do { /* generate digits in reverse order */
205 s
[i
++] = n
% 10 + '0'; /* get next digit */
206 } while ((n
/= 10) > 0); /* delete it */
213 //////////////////////////////////////// END 'itoa' CODE
215 //-----------------------------------------------------------------------------
216 // Encode (into the ToSend buffers) an identify request, which is the first
217 // thing that you must send to a tag to get a response.
218 //-----------------------------------------------------------------------------
219 static void BuildIdentifyRequest(void)
224 // one sub-carrier, inventory, 1 slot, fast rate
225 // AFI is at bit 5 (1<<4) when doing an INVENTORY
226 cmd
[0] = (1 << 2) | (1 << 5) | (1 << 1);
227 // inventory command code
236 CodeIso15693AsReader(cmd
, sizeof(cmd
));
239 static void __attribute__((unused
)) BuildSysInfoRequest(BYTE
*uid
)
244 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
245 // followed by teh block data
246 // one sub-carrier, inventory, 1 slot, fast rate
247 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
248 // System Information command code
250 // UID may be optionally specified here
259 cmd
[9]= 0xe0; // always e0 (not exactly unique)
261 crc
= Crc(cmd
, 10); // the crc needs to be calculated over 2 bytes
262 cmd
[10] = crc
& 0xff;
265 CodeIso15693AsReader(cmd
, sizeof(cmd
));
268 static void BuildSelectRequest( BYTE uid
[])
271 // uid[6]=0x31; // this is getting ignored - the uid array is not happening...
275 // one sub-carrier, inventory, 1 slot, fast rate
276 //cmd[0] = (1 << 2) | (1 << 5) | (1 << 1); // INVENTROY FLAGS
277 cmd
[0] = (1 << 4) | (1 << 5) | (1 << 1); // Select and addressed FLAGS
278 // SELECT command code
281 // cmd[2] = uid[0];//0x32;
282 // cmd[3]= uid[1];//0x4b;
283 // cmd[4] = uid[2];//0x03;
284 // cmd[5] = uid[3];//0x01;
285 // cmd[6] = uid[4];//0x00;
286 // cmd[7] = uid[5];//0x10;
287 // cmd[8] = uid[6];//0x05;
294 cmd
[8] = 0x05; // infineon?
296 cmd
[9]= 0xe0; // always e0 (not exactly unique)
298 // DbpIntegers(cmd[8],cmd[7],cmd[6]);
300 crc
= Crc(cmd
, 10); // the crc needs to be calculated over 10 bytes
301 cmd
[10] = crc
& 0xff;
304 CodeIso15693AsReader(cmd
, sizeof(cmd
));
307 static void __attribute__((unused
)) BuildReadBlockRequest(BYTE
*uid
, BYTE blockNumber
)
312 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
313 // followed by teh block data
314 // one sub-carrier, inventory, 1 slot, fast rate
315 cmd
[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit
316 // READ BLOCK command code
318 // UID may be optionally specified here
327 cmd
[9]= 0xe0; // always e0 (not exactly unique)
328 // Block number to read
329 cmd
[10] = blockNumber
;//0x00;
331 crc
= Crc(cmd
, 11); // the crc needs to be calculated over 2 bytes
332 cmd
[11] = crc
& 0xff;
335 CodeIso15693AsReader(cmd
, sizeof(cmd
));
338 static void __attribute__((unused
)) BuildReadMultiBlockRequest(BYTE
*uid
)
343 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
344 // followed by teh block data
345 // one sub-carrier, inventory, 1 slot, fast rate
346 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
347 // READ Multi BLOCK command code
349 // UID may be optionally specified here
358 cmd
[9]= 0xe0; // always e0 (not exactly unique)
359 // First Block number to read
361 // Number of Blocks to read
362 cmd
[11] = 0x2f; // read quite a few
364 crc
= Crc(cmd
, 12); // the crc needs to be calculated over 2 bytes
365 cmd
[12] = crc
& 0xff;
368 CodeIso15693AsReader(cmd
, sizeof(cmd
));
371 static void __attribute__((unused
)) BuildArbitraryRequest(BYTE
*uid
,BYTE CmdCode
)
376 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
377 // followed by teh block data
378 // one sub-carrier, inventory, 1 slot, fast rate
379 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
380 // READ BLOCK command code
382 // UID may be optionally specified here
391 cmd
[9]= 0xe0; // always e0 (not exactly unique)
397 // cmd[13] = 0x00; //Now the CRC
398 crc
= Crc(cmd
, 12); // the crc needs to be calculated over 2 bytes
399 cmd
[12] = crc
& 0xff;
402 CodeIso15693AsReader(cmd
, sizeof(cmd
));
405 static void __attribute__((unused
)) BuildArbitraryCustomRequest(BYTE uid
[], BYTE CmdCode
)
410 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
411 // followed by teh block data
412 // one sub-carrier, inventory, 1 slot, fast rate
413 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
414 // READ BLOCK command code
416 // UID may be optionally specified here
425 cmd
[9]= 0xe0; // always e0 (not exactly unique)
427 cmd
[10] = 0x05; // for custom codes this must be manufcturer code
431 // cmd[13] = 0x00; //Now the CRC
432 crc
= Crc(cmd
, 12); // the crc needs to be calculated over 2 bytes
433 cmd
[12] = crc
& 0xff;
436 CodeIso15693AsReader(cmd
, sizeof(cmd
));
439 /////////////////////////////////////////////////////////////////////////
440 // Now the VICC>VCD responses when we are simulating a tag
441 ////////////////////////////////////////////////////////////////////
443 static void BuildInventoryResponse(void)
448 // one sub-carrier, inventory, 1 slot, fast rate
449 // AFI is at bit 5 (1<<4) when doing an INVENTORY
450 cmd
[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);
463 cmd
[10] = crc
& 0xff;
466 CodeIso15693AsReader(cmd
, sizeof(cmd
));
469 //-----------------------------------------------------------------------------
470 // Transmit the command (to the tag) that was placed in ToSend[].
471 //-----------------------------------------------------------------------------
472 static void TransmitTo15693Tag(const BYTE
*cmd
, int len
, int *samples
, int *wait
)
476 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
477 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX
);
478 if(*wait
< 10) { *wait
= 10; }
480 // for(c = 0; c < *wait;) {
481 // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
482 // AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
485 // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
486 // volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
494 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
495 AT91C_BASE_SSC
->SSC_THR
= cmd
[c
];
501 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
502 volatile DWORD r
= AT91C_BASE_SSC
->SSC_RHR
;
507 *samples
= (c
+ *wait
) << 3;
510 //-----------------------------------------------------------------------------
511 // Transmit the command (to the reader) that was placed in ToSend[].
512 //-----------------------------------------------------------------------------
513 static void TransmitTo15693Reader(const BYTE
*cmd
, int len
, int *samples
, int *wait
)
517 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
518 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
); // No requirement to energise my coils
519 if(*wait
< 10) { *wait
= 10; }
523 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
524 AT91C_BASE_SSC
->SSC_THR
= cmd
[c
];
530 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
531 volatile DWORD r
= AT91C_BASE_SSC
->SSC_RHR
;
536 *samples
= (c
+ *wait
) << 3;
539 static int GetIso15693AnswerFromTag(BYTE
*receivedResponse
, int maxLen
, int *samples
, int *elapsed
)
542 BYTE
*dest
= (BYTE
*)BigBuf
;
548 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
549 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
553 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
554 AT91C_BASE_SSC
->SSC_THR
= 0x43;
556 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
558 b
= (SBYTE
)AT91C_BASE_SSC
->SSC_RHR
;
560 // The samples are correlations against I and Q versions of the
561 // tone that the tag AM-modulates, so every other sample is I,
562 // every other is Q. We just want power, so abs(I) + abs(Q) is
563 // close to what we want.
591 //////////////////////////////////////////
592 /////////// DEMODULATE ///////////////////
593 //////////////////////////////////////////
596 int max
= 0, maxPos
=0;
600 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
602 // First, correlate for SOF
603 for(i
= 0; i
< 100; i
++) {
605 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
606 corr
+= FrameSOF
[j
]*dest
[i
+(j
/skip
)];
613 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
615 int k
= 0; // this will be our return value
617 // greg - If correlation is less than 1 then there's little point in continuing
618 if ((max
/(arraylen(FrameSOF
)/skip
)) >= 1)
621 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
624 memset(outBuf
, 0, sizeof(outBuf
));
627 int corr0
= 0, corr1
= 0, corrEOF
= 0;
628 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
629 corr0
+= Logic0
[j
]*dest
[i
+(j
/skip
)];
631 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
632 corr1
+= Logic1
[j
]*dest
[i
+(j
/skip
)];
634 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
635 corrEOF
+= FrameEOF
[j
]*dest
[i
+(j
/skip
)];
637 // Even things out by the length of the target waveform.
641 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
642 // DbpString("EOF at %d", i);
644 } else if(corr1
> corr0
) {
645 i
+= arraylen(Logic1
)/skip
;
648 i
+= arraylen(Logic0
)/skip
;
655 if((i
+(int)arraylen(FrameEOF
)) >= 2000) {
656 DbpString("ran off end!");
661 DbpString("error, uneven octet! (discard extra bits!)");
662 /// DbpString(" mask=%02x", mask);
666 // strcat(str1," octets read");
668 // DbpString( str1); // DbpString("%d octets", k);
670 // for(i = 0; i < k; i+=3) {
671 // //DbpString("# %2d: %02x ", i, outBuf[i]);
672 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
675 for(i
= 0; i
< k
; i
++) {
676 receivedResponse
[i
] = outBuf
[i
];
678 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))
679 return k
; // return the number of bytes demodulated
681 /// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
685 // Now the GetISO15693 message from sniffing command
686 static int GetIso15693AnswerFromSniff(BYTE
*receivedResponse
, int maxLen
, int *samples
, int *elapsed
)
689 BYTE
*dest
= (BYTE
*)BigBuf
;
695 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
696 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
700 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
701 AT91C_BASE_SSC
->SSC_THR
= 0x43;
703 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
705 b
= (SBYTE
)AT91C_BASE_SSC
->SSC_RHR
;
707 // The samples are correlations against I and Q versions of the
708 // tone that the tag AM-modulates, so every other sample is I,
709 // every other is Q. We just want power, so abs(I) + abs(Q) is
710 // close to what we want.
738 //////////////////////////////////////////
739 /////////// DEMODULATE ///////////////////
740 //////////////////////////////////////////
743 int max
= 0, maxPos
=0;
747 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
749 // First, correlate for SOF
750 for(i
= 0; i
< 19000; i
++) {
752 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
753 corr
+= FrameSOF
[j
]*dest
[i
+(j
/skip
)];
760 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
762 int k
= 0; // this will be our return value
764 // greg - If correlation is less than 1 then there's little point in continuing
765 if ((max
/(arraylen(FrameSOF
)/skip
)) >= 1) // THIS SHOULD BE 1
768 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
771 memset(outBuf
, 0, sizeof(outBuf
));
774 int corr0
= 0, corr1
= 0, corrEOF
= 0;
775 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
776 corr0
+= Logic0
[j
]*dest
[i
+(j
/skip
)];
778 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
779 corr1
+= Logic1
[j
]*dest
[i
+(j
/skip
)];
781 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
782 corrEOF
+= FrameEOF
[j
]*dest
[i
+(j
/skip
)];
784 // Even things out by the length of the target waveform.
788 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
789 // DbpString("EOF at %d", i);
791 } else if(corr1
> corr0
) {
792 i
+= arraylen(Logic1
)/skip
;
795 i
+= arraylen(Logic0
)/skip
;
802 if((i
+(int)arraylen(FrameEOF
)) >= 2000) {
803 DbpString("ran off end!");
808 DbpString("error, uneven octet! (discard extra bits!)");
809 /// DbpString(" mask=%02x", mask);
813 // strcat(str1," octets read");
815 // DbpString( str1); // DbpString("%d octets", k);
817 // for(i = 0; i < k; i+=3) {
818 // //DbpString("# %2d: %02x ", i, outBuf[i]);
819 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
822 for(i
= 0; i
< k
; i
++) {
823 receivedResponse
[i
] = outBuf
[i
];
825 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))
826 return k
; // return the number of bytes demodulated
828 /// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
831 //-----------------------------------------------------------------------------
832 // Start to read an ISO 15693 tag. We send an identify request, then wait
833 // for the response. The response is not demodulated, just left in the buffer
834 // so that it can be downloaded to a PC and processed there.
835 //-----------------------------------------------------------------------------
836 void AcquireRawAdcSamplesIso15693(void)
839 BYTE
*dest
= (BYTE
*)BigBuf
;
844 BuildIdentifyRequest();
846 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
848 // Give the tags time to energize
849 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
852 // Now send the command
854 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX
);
858 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
859 AT91C_BASE_SSC
->SSC_THR
= ToSend
[c
];
861 if(c
== ToSendMax
+3) {
865 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
866 volatile DWORD r
= AT91C_BASE_SSC
->SSC_RHR
;
872 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
877 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
878 AT91C_BASE_SSC
->SSC_THR
= 0x43;
880 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
882 b
= (SBYTE
)AT91C_BASE_SSC
->SSC_RHR
;
884 // The samples are correlations against I and Q versions of the
885 // tone that the tag AM-modulates, so every other sample is I,
886 // every other is Q. We just want power, so abs(I) + abs(Q) is
887 // close to what we want.
916 //-----------------------------------------------------------------------------
917 // Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
918 // all demodulation performed in arm rather than host. - greg
919 //-----------------------------------------------------------------------------
920 void ReaderIso15693(DWORD parameter
)
927 //DbpString(parameter);
929 //BYTE *answer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
930 BYTE
*answer1
= (((BYTE
*)BigBuf
) + 3660); //
931 BYTE
*answer2
= (((BYTE
*)BigBuf
) + 3760);
932 BYTE
*answer3
= (((BYTE
*)BigBuf
) + 3860);
933 //BYTE *TagUID= (((BYTE *)BigBuf) + 3960); // where we hold the uid for hi15reader
934 // int answerLen0 = 0;
940 memset(BigBuf
+ 3660, 0, 300);
945 // Start from off (no field generated)
946 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
949 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
952 // Give the tags time to energize
953 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
966 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
967 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
968 BYTE TagUID
[7]; // where we hold the uid for hi15reader
970 // BuildIdentifyRequest();
971 // //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
972 // TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
973 // // Now wait for a response
974 // responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
975 // if (responseLen0 >=12) // we should do a better check than this
977 // // really we should check it is a valid mesg
978 // // but for now just grab what we think is the uid
979 // TagUID[0] = receivedAnswer0[2];
980 // TagUID[1] = receivedAnswer0[3];
981 // TagUID[2] = receivedAnswer0[4];
982 // TagUID[3] = receivedAnswer0[5];
983 // TagUID[4] = receivedAnswer0[6];
984 // TagUID[5] = receivedAnswer0[7];
985 // TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
986 // DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
989 // Now send the IDENTIFY command
990 BuildIdentifyRequest();
991 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
992 TransmitTo15693Tag(ToSend
,ToSendMax
,&tsamples
, &wait
); // No longer ToSendMax+3
993 // Now wait for a response
994 answerLen1
= GetIso15693AnswerFromTag(answer1
, 100, &samples
, &elapsed
) ;
996 if (answerLen1
>=12) // we should do a better check than this
999 TagUID
[0] = answer1
[2];
1000 TagUID
[1] = answer1
[3];
1001 TagUID
[2] = answer1
[4];
1002 TagUID
[3] = answer1
[5];
1003 TagUID
[4] = answer1
[6];
1004 TagUID
[5] = answer1
[7];
1005 TagUID
[6] = answer1
[8]; // IC Manufacturer code
1007 // Now send the SELECT command
1008 BuildSelectRequest(TagUID
);
1009 TransmitTo15693Tag(ToSend
,ToSendMax
,&tsamples
, &wait
); // No longer ToSendMax+3
1010 // Now wait for a response
1011 answerLen2
= GetIso15693AnswerFromTag(answer2
, 100, &samples
, &elapsed
);
1013 // Now send the MULTI READ command
1014 // BuildArbitraryRequest(*TagUID,parameter);
1015 BuildArbitraryCustomRequest(TagUID
,parameter
);
1016 // BuildReadBlockRequest(*TagUID,parameter);
1017 // BuildSysInfoRequest(*TagUID);
1018 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1019 TransmitTo15693Tag(ToSend
,ToSendMax
,&tsamples
, &wait
); // No longer ToSendMax+3
1020 // Now wait for a response
1021 answerLen3
= GetIso15693AnswerFromTag(answer3
, 100, &samples
, &elapsed
) ;
1025 Dbprintf("%d octets read from IDENTIFY request: %x %x %x %x %x %x %x %x %x", answerLen1
,
1026 answer1
[0], answer1
[1], answer1
[2],
1027 answer1
[3], answer1
[4], answer1
[5],
1028 answer1
[6], answer1
[7], answer1
[8]);
1030 Dbprintf("%d octets read from SELECT request: %x %x %x %x %x %x %x %x %x", answerLen2
,
1031 answer2
[0], answer2
[1], answer2
[2],
1032 answer2
[3], answer2
[4], answer2
[5],
1033 answer2
[6], answer2
[7], answer2
[8]);
1035 Dbprintf("%d octets read from XXX request: %x %x %x %x %x %x %x %x %x", answerLen3
,
1036 answer3
[0], answer3
[1], answer3
[2],
1037 answer3
[3], answer3
[4], answer3
[5],
1038 answer3
[6], answer3
[7], answer3
[8]);
1042 // for(i = 0; i < responseLen3; i++) {
1043 // itoa(str1,receivedAnswer3[i]);
1044 // strcat(str2,str1);
1054 //-----------------------------------------------------------------------------
1055 // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
1056 // all demodulation performed in arm rather than host. - greg
1057 //-----------------------------------------------------------------------------
1058 void SimTagIso15693(DWORD parameter
)
1065 BYTE
*answer1
= (((BYTE
*)BigBuf
) + 3660); //
1069 memset(answer1
, 0, 100);
1074 // Start from off (no field generated)
1075 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
1078 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
1081 // Give the tags time to energize
1082 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!
1095 answerLen1
= GetIso15693AnswerFromSniff(answer1
, 100, &samples
, &elapsed
) ;
1097 if (answerLen1
>=1) // we should do a better check than this
1099 // Build a suitable reponse to the reader INVENTORY cocmmand
1100 BuildInventoryResponse();
1101 TransmitTo15693Reader(ToSend
,ToSendMax
, &tsamples
, &wait
);
1104 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1
,
1105 answer1
[0], answer1
[1], answer1
[2],
1106 answer1
[3], answer1
[4], answer1
[5],
1107 answer1
[6], answer1
[7], answer1
[8]);