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"
14 // FROM winsrc\prox.h //////////////////////////////////
15 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
17 //-----------------------------------------------------------------------------
18 // Map a sequence of octets (~layer 2 command) into the set of bits to feed
19 // to the FPGA, to transmit that command to the tag.
20 //-----------------------------------------------------------------------------
22 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
25 // 1) Unmodulated time of 56.64us
26 // 2) 24 pulses of 423.75khz
27 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
29 static const int FrameSOF
[] = {
30 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
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,
39 static const int Logic0
[] = {
45 static const int Logic1
[] = {
53 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
54 // 2) 24 pulses of 423.75khz
55 // 3) Unmodulated time of 56.64us
57 static const int FrameEOF
[] = {
62 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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
68 static void CodeIso15693AsReader(BYTE
*cmd
, int n
)
74 // Give it a bit of slack at the beginning
75 for(i
= 0; i
< 24; i
++) {
87 for(i
= 0; i
< n
; i
++) {
88 for(j
= 0; j
< 8; j
+= 2) {
89 int these
= (cmd
[i
] >> j
) & 3;
139 // And slack at the end, too.
140 for(i
= 0; i
< 24; i
++) {
145 //-----------------------------------------------------------------------------
146 // The CRC used by ISO 15693.
147 //-----------------------------------------------------------------------------
148 static WORD
Crc(BYTE
*v
, int n
)
154 for(i
= 0; i
< n
; i
++) {
155 reg
= reg
^ ((DWORD
)v
[i
]);
156 for (j
= 0; j
< 8; j
++) {
158 reg
= (reg
>> 1) ^ 0x8408;
168 char *strcat(char *dest
, const char *src
)
170 size_t dest_len
= strlen(dest
);
173 for (i
= 0 ; src
[i
] != '\0' ; i
++)
174 dest
[dest_len
+ i
] = src
[i
];
175 dest
[dest_len
+ i
] = '\0';
180 ////////////////////////////////////////// code to do 'itoa'
182 /* reverse: reverse string s in place */
183 void reverse(char s
[])
187 for (i
= 0, j
= strlen(s
)-1; i
<j
; i
++, j
--) {
194 /* itoa: convert n to characters in s */
195 void itoa(int n
, char s
[])
199 if ((sign
= n
) < 0) /* record sign */
200 n
= -n
; /* make n positive */
202 do { /* generate digits in reverse order */
203 s
[i
++] = n
% 10 + '0'; /* get next digit */
204 } while ((n
/= 10) > 0); /* delete it */
211 //////////////////////////////////////// END 'itoa' CODE
213 //-----------------------------------------------------------------------------
214 // Encode (into the ToSend buffers) an identify request, which is the first
215 // thing that you must send to a tag to get a response.
216 //-----------------------------------------------------------------------------
217 static void BuildIdentifyRequest(void)
222 // one sub-carrier, inventory, 1 slot, fast rate
223 // AFI is at bit 5 (1<<4) when doing an INVENTORY
224 cmd
[0] = (1 << 2) | (1 << 5) | (1 << 1);
225 // inventory command code
234 CodeIso15693AsReader(cmd
, sizeof(cmd
));
237 static void __attribute__((unused
)) BuildSysInfoRequest(BYTE
*uid
)
242 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
243 // followed by teh block data
244 // one sub-carrier, inventory, 1 slot, fast rate
245 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
246 // System Information command code
248 // UID may be optionally specified here
257 cmd
[9]= 0xe0; // always e0 (not exactly unique)
259 crc
= Crc(cmd
, 10); // the crc needs to be calculated over 2 bytes
260 cmd
[10] = crc
& 0xff;
263 CodeIso15693AsReader(cmd
, sizeof(cmd
));
266 static void BuildSelectRequest( BYTE uid
[])
269 // uid[6]=0x31; // this is getting ignored - the uid array is not happening...
273 // one sub-carrier, inventory, 1 slot, fast rate
274 //cmd[0] = (1 << 2) | (1 << 5) | (1 << 1); // INVENTROY FLAGS
275 cmd
[0] = (1 << 4) | (1 << 5) | (1 << 1); // Select and addressed FLAGS
276 // SELECT command code
279 // cmd[2] = uid[0];//0x32;
280 // cmd[3]= uid[1];//0x4b;
281 // cmd[4] = uid[2];//0x03;
282 // cmd[5] = uid[3];//0x01;
283 // cmd[6] = uid[4];//0x00;
284 // cmd[7] = uid[5];//0x10;
285 // cmd[8] = uid[6];//0x05;
292 cmd
[8] = 0x05; // infineon?
294 cmd
[9]= 0xe0; // always e0 (not exactly unique)
296 // DbpIntegers(cmd[8],cmd[7],cmd[6]);
298 crc
= Crc(cmd
, 10); // the crc needs to be calculated over 10 bytes
299 cmd
[10] = crc
& 0xff;
302 CodeIso15693AsReader(cmd
, sizeof(cmd
));
305 static void __attribute__((unused
)) BuildReadBlockRequest(BYTE
*uid
, BYTE blockNumber
)
310 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
311 // followed by teh block data
312 // one sub-carrier, inventory, 1 slot, fast rate
313 cmd
[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit
314 // READ BLOCK command code
316 // UID may be optionally specified here
325 cmd
[9]= 0xe0; // always e0 (not exactly unique)
326 // Block number to read
327 cmd
[10] = blockNumber
;//0x00;
329 crc
= Crc(cmd
, 11); // the crc needs to be calculated over 2 bytes
330 cmd
[11] = crc
& 0xff;
333 CodeIso15693AsReader(cmd
, sizeof(cmd
));
336 static void __attribute__((unused
)) BuildReadMultiBlockRequest(BYTE
*uid
)
341 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
342 // followed by teh block data
343 // one sub-carrier, inventory, 1 slot, fast rate
344 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
345 // READ Multi BLOCK command code
347 // UID may be optionally specified here
356 cmd
[9]= 0xe0; // always e0 (not exactly unique)
357 // First Block number to read
359 // Number of Blocks to read
360 cmd
[11] = 0x2f; // read quite a few
362 crc
= Crc(cmd
, 12); // the crc needs to be calculated over 2 bytes
363 cmd
[12] = crc
& 0xff;
366 CodeIso15693AsReader(cmd
, sizeof(cmd
));
369 static void __attribute__((unused
)) BuildArbitraryRequest(BYTE
*uid
,BYTE CmdCode
)
374 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
375 // followed by teh block data
376 // one sub-carrier, inventory, 1 slot, fast rate
377 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
378 // READ BLOCK command code
380 // UID may be optionally specified here
389 cmd
[9]= 0xe0; // always e0 (not exactly unique)
395 // cmd[13] = 0x00; //Now the CRC
396 crc
= Crc(cmd
, 12); // the crc needs to be calculated over 2 bytes
397 cmd
[12] = crc
& 0xff;
400 CodeIso15693AsReader(cmd
, sizeof(cmd
));
403 static void __attribute__((unused
)) BuildArbitraryCustomRequest(BYTE uid
[], BYTE CmdCode
)
408 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
409 // followed by teh block data
410 // one sub-carrier, inventory, 1 slot, fast rate
411 cmd
[0] = (1 << 5) | (1 << 1); // no SELECT bit
412 // READ BLOCK command code
414 // UID may be optionally specified here
423 cmd
[9]= 0xe0; // always e0 (not exactly unique)
425 cmd
[10] = 0x05; // for custom codes this must be manufcturer code
429 // cmd[13] = 0x00; //Now the CRC
430 crc
= Crc(cmd
, 12); // the crc needs to be calculated over 2 bytes
431 cmd
[12] = crc
& 0xff;
434 CodeIso15693AsReader(cmd
, sizeof(cmd
));
437 /////////////////////////////////////////////////////////////////////////
438 // Now the VICC>VCD responses when we are simulating a tag
439 ////////////////////////////////////////////////////////////////////
441 static void BuildInventoryResponse(void)
446 // one sub-carrier, inventory, 1 slot, fast rate
447 // AFI is at bit 5 (1<<4) when doing an INVENTORY
448 cmd
[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);
461 cmd
[10] = crc
& 0xff;
464 CodeIso15693AsReader(cmd
, sizeof(cmd
));
467 //-----------------------------------------------------------------------------
468 // Transmit the command (to the tag) that was placed in ToSend[].
469 //-----------------------------------------------------------------------------
470 static void TransmitTo15693Tag(const BYTE
*cmd
, int len
, int *samples
, int *wait
)
474 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
475 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX
);
476 if(*wait
< 10) { *wait
= 10; }
478 // for(c = 0; c < *wait;) {
479 // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
480 // AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
483 // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
484 // volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
492 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
493 AT91C_BASE_SSC
->SSC_THR
= cmd
[c
];
499 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
500 volatile DWORD r
= AT91C_BASE_SSC
->SSC_RHR
;
505 *samples
= (c
+ *wait
) << 3;
508 //-----------------------------------------------------------------------------
509 // Transmit the command (to the reader) that was placed in ToSend[].
510 //-----------------------------------------------------------------------------
511 static void TransmitTo15693Reader(const BYTE
*cmd
, int len
, int *samples
, int *wait
)
515 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
516 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
); // No requirement to energise my coils
517 if(*wait
< 10) { *wait
= 10; }
521 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
522 AT91C_BASE_SSC
->SSC_THR
= cmd
[c
];
528 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
529 volatile DWORD r
= AT91C_BASE_SSC
->SSC_RHR
;
534 *samples
= (c
+ *wait
) << 3;
537 static int GetIso15693AnswerFromTag(BYTE
*receivedResponse
, int maxLen
, int *samples
, int *elapsed
)
540 BYTE
*dest
= (BYTE
*)BigBuf
;
546 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
547 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
551 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
552 AT91C_BASE_SSC
->SSC_THR
= 0x43;
554 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
556 b
= (SBYTE
)AT91C_BASE_SSC
->SSC_RHR
;
558 // The samples are correlations against I and Q versions of the
559 // tone that the tag AM-modulates, so every other sample is I,
560 // every other is Q. We just want power, so abs(I) + abs(Q) is
561 // close to what we want.
589 //////////////////////////////////////////
590 /////////// DEMODULATE ///////////////////
591 //////////////////////////////////////////
594 int max
= 0, maxPos
=0;
598 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
600 // First, correlate for SOF
601 for(i
= 0; i
< 100; i
++) {
603 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
604 corr
+= FrameSOF
[j
]*dest
[i
+(j
/skip
)];
611 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
613 int k
= 0; // this will be our return value
615 // greg - If correlation is less than 1 then there's little point in continuing
616 if ((max
/(arraylen(FrameSOF
)/skip
)) >= 1)
619 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
622 memset(outBuf
, 0, sizeof(outBuf
));
625 int corr0
= 0, corr1
= 0, corrEOF
= 0;
626 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
627 corr0
+= Logic0
[j
]*dest
[i
+(j
/skip
)];
629 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
630 corr1
+= Logic1
[j
]*dest
[i
+(j
/skip
)];
632 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
633 corrEOF
+= FrameEOF
[j
]*dest
[i
+(j
/skip
)];
635 // Even things out by the length of the target waveform.
639 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
640 // DbpString("EOF at %d", i);
642 } else if(corr1
> corr0
) {
643 i
+= arraylen(Logic1
)/skip
;
646 i
+= arraylen(Logic0
)/skip
;
653 if((i
+(int)arraylen(FrameEOF
)) >= 2000) {
654 DbpString("ran off end!");
659 DbpString("error, uneven octet! (discard extra bits!)");
660 /// DbpString(" mask=%02x", mask);
664 // strcat(str1," octets read");
666 // DbpString( str1); // DbpString("%d octets", k);
668 // for(i = 0; i < k; i+=3) {
669 // //DbpString("# %2d: %02x ", i, outBuf[i]);
670 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
673 for(i
= 0; i
< k
; i
++) {
674 receivedResponse
[i
] = outBuf
[i
];
676 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))
677 return k
; // return the number of bytes demodulated
679 /// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
683 // Now the GetISO15693 message from sniffing command
684 static int GetIso15693AnswerFromSniff(BYTE
*receivedResponse
, int maxLen
, int *samples
, int *elapsed
)
687 BYTE
*dest
= (BYTE
*)BigBuf
;
693 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
694 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
698 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
699 AT91C_BASE_SSC
->SSC_THR
= 0x43;
701 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
703 b
= (SBYTE
)AT91C_BASE_SSC
->SSC_RHR
;
705 // The samples are correlations against I and Q versions of the
706 // tone that the tag AM-modulates, so every other sample is I,
707 // every other is Q. We just want power, so abs(I) + abs(Q) is
708 // close to what we want.
736 //////////////////////////////////////////
737 /////////// DEMODULATE ///////////////////
738 //////////////////////////////////////////
741 int max
= 0, maxPos
=0;
745 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
747 // First, correlate for SOF
748 for(i
= 0; i
< 19000; i
++) {
750 for(j
= 0; j
< arraylen(FrameSOF
); j
+= skip
) {
751 corr
+= FrameSOF
[j
]*dest
[i
+(j
/skip
)];
758 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
760 int k
= 0; // this will be our return value
762 // greg - If correlation is less than 1 then there's little point in continuing
763 if ((max
/(arraylen(FrameSOF
)/skip
)) >= 1) // THIS SHOULD BE 1
766 i
= maxPos
+ arraylen(FrameSOF
)/skip
;
769 memset(outBuf
, 0, sizeof(outBuf
));
772 int corr0
= 0, corr1
= 0, corrEOF
= 0;
773 for(j
= 0; j
< arraylen(Logic0
); j
+= skip
) {
774 corr0
+= Logic0
[j
]*dest
[i
+(j
/skip
)];
776 for(j
= 0; j
< arraylen(Logic1
); j
+= skip
) {
777 corr1
+= Logic1
[j
]*dest
[i
+(j
/skip
)];
779 for(j
= 0; j
< arraylen(FrameEOF
); j
+= skip
) {
780 corrEOF
+= FrameEOF
[j
]*dest
[i
+(j
/skip
)];
782 // Even things out by the length of the target waveform.
786 if(corrEOF
> corr1
&& corrEOF
> corr0
) {
787 // DbpString("EOF at %d", i);
789 } else if(corr1
> corr0
) {
790 i
+= arraylen(Logic1
)/skip
;
793 i
+= arraylen(Logic0
)/skip
;
800 if((i
+(int)arraylen(FrameEOF
)) >= 2000) {
801 DbpString("ran off end!");
806 DbpString("error, uneven octet! (discard extra bits!)");
807 /// DbpString(" mask=%02x", mask);
811 // strcat(str1," octets read");
813 // DbpString( str1); // DbpString("%d octets", k);
815 // for(i = 0; i < k; i+=3) {
816 // //DbpString("# %2d: %02x ", i, outBuf[i]);
817 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
820 for(i
= 0; i
< k
; i
++) {
821 receivedResponse
[i
] = outBuf
[i
];
823 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))
824 return k
; // return the number of bytes demodulated
826 /// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
829 //-----------------------------------------------------------------------------
830 // Start to read an ISO 15693 tag. We send an identify request, then wait
831 // for the response. The response is not demodulated, just left in the buffer
832 // so that it can be downloaded to a PC and processed there.
833 //-----------------------------------------------------------------------------
834 void AcquireRawAdcSamplesIso15693(void)
837 BYTE
*dest
= (BYTE
*)BigBuf
;
842 BuildIdentifyRequest();
844 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
846 // Give the tags time to energize
847 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
850 // Now send the command
852 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX
);
856 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
857 AT91C_BASE_SSC
->SSC_THR
= ToSend
[c
];
859 if(c
== ToSendMax
+3) {
863 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
864 volatile DWORD r
= AT91C_BASE_SSC
->SSC_RHR
;
870 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
875 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_TXRDY
)) {
876 AT91C_BASE_SSC
->SSC_THR
= 0x43;
878 if(AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
880 b
= (SBYTE
)AT91C_BASE_SSC
->SSC_RHR
;
882 // The samples are correlations against I and Q versions of the
883 // tone that the tag AM-modulates, so every other sample is I,
884 // every other is Q. We just want power, so abs(I) + abs(Q) is
885 // close to what we want.
914 //-----------------------------------------------------------------------------
915 // Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
916 // all demodulation performed in arm rather than host. - greg
917 //-----------------------------------------------------------------------------
918 void ReaderIso15693(DWORD parameter
)
925 //DbpString(parameter);
927 //BYTE *answer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
928 BYTE
*answer1
= (((BYTE
*)BigBuf
) + 3660); //
929 BYTE
*answer2
= (((BYTE
*)BigBuf
) + 3760);
930 BYTE
*answer3
= (((BYTE
*)BigBuf
) + 3860);
931 //BYTE *TagUID= (((BYTE *)BigBuf) + 3960); // where we hold the uid for hi15reader
932 // int answerLen0 = 0;
938 memset(BigBuf
+ 3660, 0, 300);
943 // Start from off (no field generated)
944 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
947 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
950 // Give the tags time to energize
951 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
);
964 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
965 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
966 BYTE TagUID
[7]; // where we hold the uid for hi15reader
968 // BuildIdentifyRequest();
969 // //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
970 // TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
971 // // Now wait for a response
972 // responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
973 // if (responseLen0 >=12) // we should do a better check than this
975 // // really we should check it is a valid mesg
976 // // but for now just grab what we think is the uid
977 // TagUID[0] = receivedAnswer0[2];
978 // TagUID[1] = receivedAnswer0[3];
979 // TagUID[2] = receivedAnswer0[4];
980 // TagUID[3] = receivedAnswer0[5];
981 // TagUID[4] = receivedAnswer0[6];
982 // TagUID[5] = receivedAnswer0[7];
983 // TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
984 // DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
987 // Now send the IDENTIFY command
988 BuildIdentifyRequest();
989 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
990 TransmitTo15693Tag(ToSend
,ToSendMax
,&tsamples
, &wait
); // No longer ToSendMax+3
991 // Now wait for a response
992 answerLen1
= GetIso15693AnswerFromTag(answer1
, 100, &samples
, &elapsed
) ;
994 if (answerLen1
>=12) // we should do a better check than this
997 TagUID
[0] = answer1
[2];
998 TagUID
[1] = answer1
[3];
999 TagUID
[2] = answer1
[4];
1000 TagUID
[3] = answer1
[5];
1001 TagUID
[4] = answer1
[6];
1002 TagUID
[5] = answer1
[7];
1003 TagUID
[6] = answer1
[8]; // IC Manufacturer code
1005 // Now send the SELECT command
1006 BuildSelectRequest(TagUID
);
1007 TransmitTo15693Tag(ToSend
,ToSendMax
,&tsamples
, &wait
); // No longer ToSendMax+3
1008 // Now wait for a response
1009 answerLen2
= GetIso15693AnswerFromTag(answer2
, 100, &samples
, &elapsed
);
1011 // Now send the MULTI READ command
1012 // BuildArbitraryRequest(*TagUID,parameter);
1013 BuildArbitraryCustomRequest(TagUID
,parameter
);
1014 // BuildReadBlockRequest(*TagUID,parameter);
1015 // BuildSysInfoRequest(*TagUID);
1016 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1017 TransmitTo15693Tag(ToSend
,ToSendMax
,&tsamples
, &wait
); // No longer ToSendMax+3
1018 // Now wait for a response
1019 answerLen3
= GetIso15693AnswerFromTag(answer3
, 100, &samples
, &elapsed
) ;
1023 Dbprintf("%d octets read from IDENTIFY request: %x %x %x %x %x %x %x %x %x", answerLen1
,
1024 answer1
[0], answer1
[1], answer1
[2],
1025 answer1
[3], answer1
[4], answer1
[5],
1026 answer1
[6], answer1
[7], answer1
[8]);
1028 Dbprintf("%d octets read from SELECT request: %x %x %x %x %x %x %x %x %x", answerLen2
,
1029 answer2
[0], answer2
[1], answer2
[2],
1030 answer2
[3], answer2
[4], answer2
[5],
1031 answer2
[6], answer2
[7], answer2
[8]);
1033 Dbprintf("%d octets read from XXX request: %x %x %x %x %x %x %x %x %x", answerLen3
,
1034 answer3
[0], answer3
[1], answer3
[2],
1035 answer3
[3], answer3
[4], answer3
[5],
1036 answer3
[6], answer3
[7], answer3
[8]);
1040 // for(i = 0; i < responseLen3; i++) {
1041 // itoa(str1,receivedAnswer3[i]);
1042 // strcat(str2,str1);
1052 //-----------------------------------------------------------------------------
1053 // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
1054 // all demodulation performed in arm rather than host. - greg
1055 //-----------------------------------------------------------------------------
1056 void SimTagIso15693(DWORD parameter
)
1063 BYTE
*answer1
= (((BYTE
*)BigBuf
) + 3660); //
1067 memset(answer1
, 0, 100);
1072 // Start from off (no field generated)
1073 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
1076 SetAdcMuxFor(GPIO_MUXSEL_HIPKD
);
1079 // Give the tags time to energize
1080 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!
1093 answerLen1
= GetIso15693AnswerFromSniff(answer1
, 100, &samples
, &elapsed
) ;
1095 if (answerLen1
>=1) // we should do a better check than this
1097 // Build a suitable reponse to the reader INVENTORY cocmmand
1098 BuildInventoryResponse();
1099 TransmitTo15693Reader(ToSend
,ToSendMax
, &tsamples
, &wait
);
1102 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1
,
1103 answer1
[0], answer1
[1], answer1
[2],
1104 answer1
[3], answer1
[4], answer1
[5],
1105 answer1
[6], answer1
[7], answer1
[8]);