]> git.zerfleddert.de Git - proxmark3-svn/blame - winsrc/command.cpp
Improved askdemod to detect transitions from peak to peak, instead of zero-crossings...
[proxmark3-svn] / winsrc / command.cpp
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// The actual command interpeter for what the user types at the command line.\r
3// Jonathan Westhues, Sept 2005\r
4// Edits by Gerhard de Koning Gans, Sep 2007 (##)\r
5//-----------------------------------------------------------------------------\r
6#include <windows.h>\r
7#include <stdlib.h>\r
8#include <string.h>\r
9#include <stdio.h>\r
10#include <limits.h>\r
11#include <math.h>\r
12\r
13#include "prox.h"\r
14#include "../common/iso14443_crc.c"\r
15\r
16#define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
9760414b 17#define BIT(x) GraphBuffer[x * clock]\r
18#define BITS (GraphTraceLen / clock)\r
6658905f 19\r
9760414b 20int go = 0;\r
6658905f 21static int CmdHisamplest(char *str, int nrlow);\r
22\r
23static void GetFromBigBuf(BYTE *dest, int bytes)\r
24{\r
25 int n = bytes/4;\r
26\r
27 if(n % 48 != 0) {\r
28 PrintToScrollback("bad len in GetFromBigBuf");\r
29 return;\r
30 }\r
31\r
32 int i;\r
33 for(i = 0; i < n; i += 12) {\r
34 UsbCommand c;\r
35 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
36 c.ext1 = i;\r
37 SendCommand(&c, FALSE);\r
38 ReceiveCommand(&c);\r
39 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 40 PrintToScrollback("bad resp");\r
6658905f 41 return;\r
42 }\r
43\r
44 memcpy(dest+(i*4), c.d.asBytes, 48);\r
45 }\r
46}\r
47\r
d722c4ce 48static void CmdReset(char *str)\r
49{\r
50 UsbCommand c;\r
51 c.cmd = CMD_HARDWARE_RESET;\r
52 SendCommand(&c, FALSE);\r
53}\r
54\r
55\r
6658905f 56static void CmdQuit(char *str)\r
57{\r
58 exit(0);\r
59}\r
60\r
61static void CmdHIDdemodFSK(char *str)\r
62{\r
63 UsbCommand c;\r
64 c.cmd = CMD_HID_DEMOD_FSK;\r
65 SendCommand(&c, FALSE);\r
66}\r
67\r
68static void CmdTune(char *str)\r
69{\r
70 UsbCommand c;\r
71 c.cmd = CMD_MEASURE_ANTENNA_TUNING;\r
72 SendCommand(&c, FALSE);\r
73}\r
74\r
75static void CmdHi15read(char *str)\r
76{\r
77 UsbCommand c;\r
78 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693;\r
79 SendCommand(&c, FALSE);\r
80}\r
81\r
82static void CmdHi14read(char *str)\r
83{\r
84 UsbCommand c;\r
85 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;\r
86 c.ext1 = atoi(str);\r
87 SendCommand(&c, FALSE);\r
88}\r
9760414b 89\r
90\r
91/* New command to read the contents of a SRI512 tag\r
92 * SRI512 tags are ISO14443-B modulated memory tags,\r
93 * this command just dumps the contents of the memory/\r
94 */\r
95static void CmdSri512read(char *str)\r
96{\r
fb25b483 97 UsbCommand c;\r
98 c.cmd = CMD_READ_SRI512_TAG;\r
99 c.ext1 = atoi(str);\r
9760414b 100 SendCommand(&c, FALSE);\r
101}\r
6658905f 102\r
103// ## New command\r
104static void CmdHi14areader(char *str)\r
105{\r
106 UsbCommand c;\r
107 c.cmd = CMD_READER_ISO_14443a;\r
108 c.ext1 = atoi(str);\r
109 SendCommand(&c, FALSE);\r
110}\r
111\r
112// ## New command\r
113static void CmdHi15reader(char *str)\r
114{\r
115 UsbCommand c;\r
116 c.cmd = CMD_READER_ISO_15693;\r
117 c.ext1 = atoi(str);\r
118 SendCommand(&c, FALSE);\r
119}\r
120\r
121// ## New command\r
122static void CmdHi15tag(char *str)\r
123{\r
124 UsbCommand c;\r
125 c.cmd = CMD_SIMTAG_ISO_15693;\r
126 c.ext1 = atoi(str);\r
127 SendCommand(&c, FALSE);\r
128}\r
129\r
130static void CmdHi14read_sim(char *str)\r
131{\r
132 UsbCommand c;\r
133 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM;\r
134 c.ext1 = atoi(str);\r
135 SendCommand(&c, FALSE);\r
136}\r
137\r
138static void CmdHi14readt(char *str)\r
139{\r
140 UsbCommand c;\r
141 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;\r
142 c.ext1 = atoi(str);\r
143 SendCommand(&c, FALSE);\r
144\r
145 //CmdHisamplest(str);\r
146 while(CmdHisamplest(str,atoi(str))==0) {\r
147 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;\r
148 c.ext1 = atoi(str);\r
149 SendCommand(&c, FALSE);\r
150 }\r
151 RepaintGraphWindow();\r
152}\r
153\r
154static void CmdHisimlisten(char *str)\r
155{\r
156 UsbCommand c;\r
157 c.cmd = CMD_SIMULATE_TAG_HF_LISTEN;\r
158 SendCommand(&c, FALSE);\r
159}\r
160\r
161static void CmdHi14sim(char *str)\r
162{\r
163 UsbCommand c;\r
164 c.cmd = CMD_SIMULATE_TAG_ISO_14443;\r
165 SendCommand(&c, FALSE);\r
166}\r
6658905f 167\r
168static void CmdHi14asim(char *str) // ## simulate iso14443a tag\r
169{ // ## greg - added ability to specify tag UID\r
170\r
171 unsigned int hi=0, lo=0;\r
172 int n=0, i=0;\r
173 UsbCommand c;\r
174\r
175 while (sscanf(&str[i++], "%1x", &n ) == 1) {\r
176 hi=(hi<<4)|(lo>>28);\r
177 lo=(lo<<4)|(n&0xf);\r
178 }\r
179\r
180 c.cmd = CMD_SIMULATE_TAG_ISO_14443a;\r
181 // c.ext should be set to *str or convert *str to the correct format for a uid\r
182 c.ext1 = hi;\r
183 c.ext2 = lo;\r
184 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo);\r
185 SendCommand(&c, FALSE);\r
186}\r
187\r
188static void CmdHi14snoop(char *str)\r
189{\r
190 UsbCommand c;\r
191 c.cmd = CMD_SNOOP_ISO_14443;\r
192 SendCommand(&c, FALSE);\r
193}\r
194\r
195static void CmdHi14asnoop(char *str)\r
196{\r
197 UsbCommand c;\r
198 c.cmd = CMD_SNOOP_ISO_14443a;\r
199 SendCommand(&c, FALSE);\r
200}\r
201\r
202static void CmdFPGAOff(char *str) // ## FPGA Control\r
203{\r
204 UsbCommand c;\r
205 c.cmd = CMD_FPGA_MAJOR_MODE_OFF;\r
206 SendCommand(&c, FALSE);\r
207}\r
208\r
9760414b 209/* clear out our graph window */\r
210int CmdClearGraph(int redraw)\r
211{\r
212 int gtl = GraphTraceLen;\r
213 GraphTraceLen = 0;\r
15db5fb7 214\r
9760414b 215 if (redraw)\r
216 RepaintGraphWindow();\r
15db5fb7 217\r
9760414b 218 return gtl;\r
219}\r
220\r
221/* write a bit to the graph */\r
222static void CmdAppendGraph(int redraw, int clock, int bit)\r
6658905f 223{\r
224 int i;\r
225\r
9760414b 226 for (i = 0; i < (int)(clock/2); i++)\r
227 GraphBuffer[GraphTraceLen++] = bit ^ 1;\r
15db5fb7 228\r
229 for (i = (int)(clock/2); i < clock; i++)\r
9760414b 230 GraphBuffer[GraphTraceLen++] = bit;\r
231\r
232 if (redraw)\r
233 RepaintGraphWindow();\r
234}\r
235\r
236/* Function is equivalent of loread + losamples + em410xread\r
237 * looped until an EM410x tag is detected */\r
238static void CmdEM410xwatch(char *str)\r
239{\r
240 char *zero = "";\r
241 char *twok = "2000";\r
242 go = 1;\r
15db5fb7 243\r
9760414b 244 do\r
245 {\r
246 CmdLoread(zero);\r
247 CmdLosamples(twok);\r
248 CmdEM410xread(zero);\r
249 } while (go);\r
250}\r
251\r
252/* Read the ID of an EM410x tag.\r
253 * Format:\r
254 * 1111 1111 1 <-- standard non-repeatable header\r
255 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID\r
256 * ....\r
257 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column\r
258 * 0 <-- stop bit, end of tag\r
259 */\r
260static void CmdEM410xread(char *str)\r
261{\r
262 int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low;\r
263 int parity[4];\r
264 char id[11];\r
265 int BitStream[MAX_GRAPH_TRACE_LEN];\r
266 high = low = 0;\r
15db5fb7 267\r
9760414b 268 /* Detect high and lows and clock */\r
269 for (i = 0; i < GraphTraceLen; i++)\r
270 {\r
271 if (GraphBuffer[i] > high)\r
272 high = GraphBuffer[i];\r
273 else if (GraphBuffer[i] < low)\r
274 low = GraphBuffer[i];\r
15db5fb7 275 }\r
276\r
9760414b 277 /* get clock */\r
278 clock = GetClock(str, high);\r
15db5fb7 279\r
9760414b 280 /* parity for our 4 columns */\r
281 parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
282 header = rows = 0;\r
15db5fb7 283\r
9760414b 284 /* manchester demodulate */\r
285 bit = bit2idx = 0;\r
286 for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
287 {\r
288 hithigh = 0;\r
289 hitlow = 0;\r
290 first = 1;\r
15db5fb7 291\r
9760414b 292 /* Find out if we hit both high and low peaks */\r
293 for (j = 0; j < clock; j++)\r
294 {\r
295 if (GraphBuffer[(i * clock) + j] == high)\r
296 hithigh = 1;\r
297 else if (GraphBuffer[(i * clock) + j] == low)\r
298 hitlow = 1;\r
15db5fb7 299\r
9760414b 300 /* it doesn't count if it's the first part of our read\r
301 because it's really just trailing from the last sequence */\r
302 if (first && (hithigh || hitlow))\r
303 hithigh = hitlow = 0;\r
304 else\r
305 first = 0;\r
15db5fb7 306\r
9760414b 307 if (hithigh && hitlow)\r
308 break;\r
309 }\r
15db5fb7 310\r
9760414b 311 /* If we didn't hit both high and low peaks, we had a bit transition */\r
312 if (!hithigh || !hitlow)\r
313 bit ^= 1;\r
15db5fb7 314\r
9760414b 315 BitStream[bit2idx++] = bit;\r
316 }\r
15db5fb7 317\r
9760414b 318 /* We go till 5 before the graph ends because we'll get that far below */\r
319 for (i = 1; i < bit2idx - 5; i++)\r
320 {\r
321 /* Step 2: We have our header but need our tag ID */\r
322 if (header == 9 && rows < 10)\r
323 {\r
324 /* Confirm parity is correct */\r
325 if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])\r
326 {\r
327 /* Read another byte! */\r
328 sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));\r
329 rows++;\r
15db5fb7 330\r
9760414b 331 /* Keep parity info */\r
332 parity[0] ^= BitStream[i];\r
333 parity[1] ^= BitStream[i+1];\r
334 parity[2] ^= BitStream[i+2];\r
335 parity[3] ^= BitStream[i+3];\r
15db5fb7 336\r
9760414b 337 /* Move 4 bits ahead */\r
338 i += 4;\r
339 }\r
15db5fb7 340\r
9760414b 341 /* Damn, something wrong! reset */\r
342 else\r
343 {\r
344 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);\r
15db5fb7 345\r
9760414b 346 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */\r
347 i -= 9 + (5 * rows) - 5;\r
348\r
349 rows = header = 0;\r
350 }\r
351 }\r
15db5fb7 352\r
9760414b 353 /* Step 3: Got our 40 bits! confirm column parity */\r
354 else if (rows == 10)\r
355 {\r
356 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */\r
357 if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] &&\r
358 BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] &&\r
359 BitStream[i+4] == 0)\r
360 {\r
361 /* Sweet! */\r
362 PrintToScrollback("EM410x Tag ID: %s", id);\r
15db5fb7 363\r
9760414b 364 /* Stop any loops */\r
365 go = 0;\r
366 break;\r
367 }\r
15db5fb7 368\r
9760414b 369 /* Crap! Incorrect parity or no stop bit, start all over */\r
370 else\r
371 {\r
372 rows = header = 0;\r
15db5fb7 373\r
9760414b 374 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */\r
375 i -= 59;\r
376 }\r
377 }\r
15db5fb7 378\r
9760414b 379 /* Step 1: get our header */\r
380 else if (header < 9)\r
381 {\r
382 /* Need 9 consecutive 1's */\r
383 if (BitStream[i] == 1)\r
384 header++;\r
15db5fb7 385\r
9760414b 386 /* We don't have a header, not enough consecutive 1 bits */\r
387 else\r
388 header = 0;\r
389 }\r
390 }\r
391}\r
392\r
393/* emulate an EM410X tag\r
394 * Format:\r
395 * 1111 1111 1 <-- standard non-repeatable header\r
396 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID\r
397 * ....\r
398 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column\r
399 * 0 <-- stop bit, end of tag\r
400 */\r
401static void CmdEM410xsim(char *str)\r
402{\r
403 int i, n, j, h, binary[4], parity[4];\r
404 char *s = "0";\r
15db5fb7 405\r
9760414b 406 /* clock is 64 in EM410x tags */\r
407 int clock = 64;\r
15db5fb7 408\r
9760414b 409 /* clear our graph */\r
410 CmdClearGraph(0);\r
15db5fb7 411\r
9760414b 412 /* write it out a few times */\r
413 for (h = 0; h < 4; h++)\r
414 {\r
415 /* write 9 start bits */\r
416 for (i = 0; i < 9; i++)\r
417 CmdAppendGraph(0, clock, 1);\r
15db5fb7 418\r
9760414b 419 /* for each hex char */\r
420 parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
421 for (i = 0; i < 10; i++)\r
422 {\r
423 /* read each hex char */\r
424 sscanf(&str[i], "%1x", &n);\r
425 for (j = 3; j >= 0; j--, n/= 2)\r
426 binary[j] = n % 2;\r
15db5fb7 427\r
9760414b 428 /* append each bit */\r
429 CmdAppendGraph(0, clock, binary[0]);\r
430 CmdAppendGraph(0, clock, binary[1]);\r
431 CmdAppendGraph(0, clock, binary[2]);\r
432 CmdAppendGraph(0, clock, binary[3]);\r
15db5fb7 433\r
9760414b 434 /* append parity bit */\r
435 CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);\r
15db5fb7 436\r
9760414b 437 /* keep track of column parity */\r
438 parity[0] ^= binary[0];\r
439 parity[1] ^= binary[1];\r
440 parity[2] ^= binary[2];\r
441 parity[3] ^= binary[3];\r
442 }\r
15db5fb7 443\r
9760414b 444 /* parity columns */\r
445 CmdAppendGraph(0, clock, parity[0]);\r
446 CmdAppendGraph(0, clock, parity[1]);\r
447 CmdAppendGraph(0, clock, parity[2]);\r
448 CmdAppendGraph(0, clock, parity[3]);\r
15db5fb7 449\r
9760414b 450 /* stop bit */\r
451 CmdAppendGraph(0, clock, 0);\r
452 }\r
15db5fb7 453\r
9760414b 454 /* modulate that biatch */\r
455 Cmdmanchestermod(s);\r
15db5fb7 456\r
9760414b 457 /* booyah! */\r
458 RepaintGraphWindow();\r
459\r
460 CmdLosim(s);\r
461}\r
462\r
463static void ChkBitstream(char *str)\r
464{\r
465 int i;\r
15db5fb7 466\r
9760414b 467 /* convert to bitstream if necessary */\r
468 for (i = 0; i < (int)(GraphTraceLen / 2); i++)\r
469 {\r
470 if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)\r
471 {\r
472 Cmdbitstream(str);\r
473 break;\r
474 }\r
475 }\r
476}\r
477\r
478static void CmdLosim(char *str)\r
479{\r
480 int i;\r
481 char *zero = "0";\r
15db5fb7 482\r
9760414b 483 /* convert to bitstream if necessary */\r
484 ChkBitstream(str);\r
15db5fb7 485\r
9760414b 486 for (i = 0; i < GraphTraceLen; i += 48) {\r
6658905f 487 UsbCommand c;\r
488 int j;\r
489 for(j = 0; j < 48; j++) {\r
490 c.d.asBytes[j] = GraphBuffer[i+j];\r
491 }\r
492 c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K;\r
493 c.ext1 = i;\r
494 SendCommand(&c, FALSE);\r
495 }\r
496\r
497 UsbCommand c;\r
498 c.cmd = CMD_SIMULATE_TAG_125K;\r
499 c.ext1 = GraphTraceLen;\r
500 SendCommand(&c, FALSE);\r
501}\r
502\r
503static void CmdLoread(char *str)\r
504{\r
505 UsbCommand c;\r
506 // 'h' means higher-low-frequency, 134 kHz\r
507 if(*str == 'h') {\r
508 c.ext1 = 1;\r
509 } else if (*str == '\0') {\r
510 c.ext1 = 0;\r
511 } else {\r
512 PrintToScrollback("use 'loread' or 'loread h'");\r
513 return;\r
514 }\r
515 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K;\r
516 SendCommand(&c, FALSE);\r
517}\r
518\r
519static void CmdLosamples(char *str)\r
520{\r
521 int cnt = 0;\r
522 int i;\r
523 int n;\r
524\r
525 n=atoi(str);\r
526 if (n==0) n=128;\r
527 if (n>16000) n=16000;\r
528\r
529 for(i = 0; i < n; i += 12) {\r
530 UsbCommand c;\r
531 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
532 c.ext1 = i;\r
533 SendCommand(&c, FALSE);\r
534 ReceiveCommand(&c);\r
535 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 536 if (!go)\r
537 PrintToScrollback("bad resp");\r
6658905f 538 return;\r
539 }\r
540 int j;\r
541 for(j = 0; j < 48; j++) {\r
542 GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128;\r
543 }\r
544 }\r
545 GraphTraceLen = n*4;\r
546 RepaintGraphWindow();\r
547}\r
548\r
549static void CmdBitsamples(char *str)\r
550{\r
551 int cnt = 0;\r
552 int i;\r
553 int n;\r
554\r
555 n = 3072;\r
556 for(i = 0; i < n; i += 12) {\r
557 UsbCommand c;\r
558 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
559 c.ext1 = i;\r
560 SendCommand(&c, FALSE);\r
561 ReceiveCommand(&c);\r
562 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 563 PrintToScrollback("bad resp");\r
6658905f 564 return;\r
565 }\r
566 int j, k;\r
567 for(j = 0; j < 48; j++) {\r
568 for(k = 0; k < 8; k++) {\r
569 if(c.d.asBytes[j] & (1 << (7 - k))) {\r
570 GraphBuffer[cnt++] = 1;\r
571 } else {\r
572 GraphBuffer[cnt++] = 0;\r
573 }\r
574 }\r
575 }\r
576 }\r
577 GraphTraceLen = cnt;\r
578 RepaintGraphWindow();\r
579}\r
580\r
581static void CmdHisamples(char *str)\r
582{\r
583 int cnt = 0;\r
584 int i;\r
585 int n;\r
586 n = 1000;\r
587 for(i = 0; i < n; i += 12) {\r
588 UsbCommand c;\r
589 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
590 c.ext1 = i;\r
591 SendCommand(&c, FALSE);\r
592 ReceiveCommand(&c);\r
593 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 594 PrintToScrollback("bad resp");\r
6658905f 595 return;\r
596 }\r
597 int j;\r
598 for(j = 0; j < 48; j++) {\r
599 GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]);\r
600 }\r
601 }\r
602 GraphTraceLen = n*4;\r
603\r
604 RepaintGraphWindow();\r
605}\r
606\r
607\r
608static int CmdHisamplest(char *str, int nrlow)\r
609{\r
610 int cnt = 0;\r
611 int t1, t2;\r
612 int i;\r
613 int n;\r
614 int hasbeennull;\r
615 int show;\r
616\r
617\r
618 n = 1000;\r
619 hasbeennull = 0;\r
620 for(i = 0; i < n; i += 12) {\r
621 UsbCommand c;\r
622 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
623 c.ext1 = i;\r
624 SendCommand(&c, FALSE);\r
625 ReceiveCommand(&c);\r
626 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 627 PrintToScrollback("bad resp");\r
6658905f 628 return 0;\r
629 }\r
630 int j;\r
631 for(j = 0; j < 48; j++) {\r
632 t2 = (int)((BYTE)c.d.asBytes[j]);\r
633 if((t2 ^ 0xC0) & 0xC0) { hasbeennull++; }\r
634\r
635 show = 0;\r
636 switch(show) {\r
637 case 0:\r
638 // combined\r
639 t1 = (t2 & 0x80) ^ (t2 & 0x20);\r
640 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x20);\r
641 break;\r
642\r
643 case 1:\r
644 // only reader\r
645 t1 = (t2 & 0x80);\r
646 t2 = ((t2 << 1) & 0x80);\r
647 break;\r
648\r
649 case 2:\r
650 // only tag\r
651 t1 = (t2 & 0x20);\r
652 t2 = ((t2 << 1) & 0x20);\r
653 break;\r
654\r
655 case 3:\r
656 // both, but tag with other algorithm\r
657 t1 = (t2 & 0x80) ^ (t2 & 0x08);\r
658 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x08);\r
659 break;\r
660 }\r
661\r
662 GraphBuffer[cnt++] = t1;\r
663 GraphBuffer[cnt++] = t2;\r
664 }\r
665 }\r
666 GraphTraceLen = n*4;\r
667// 1130\r
668 if(hasbeennull>nrlow || nrlow==0) {\r
669 PrintToScrollback("hasbeennull=%d", hasbeennull);\r
670 return 1;\r
671 }\r
672 else {\r
673 return 0;\r
674 }\r
675}\r
676\r
677\r
678static void CmdHexsamples(char *str)\r
679{\r
680 int i;\r
681 int n;\r
682\r
683 if(atoi(str) == 0) {\r
684 n = 12;\r
685 } else {\r
686 n = atoi(str)/4;\r
687 }\r
688\r
689 for(i = 0; i < n; i += 12) {\r
690 UsbCommand c;\r
691 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
692 c.ext1 = i;\r
693 SendCommand(&c, FALSE);\r
694 ReceiveCommand(&c);\r
695 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 696 PrintToScrollback("bad resp");\r
6658905f 697 return;\r
698 }\r
699 int j;\r
700 for(j = 0; j < 48; j += 8) {\r
701 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",\r
702 c.d.asBytes[j+0],\r
703 c.d.asBytes[j+1],\r
704 c.d.asBytes[j+2],\r
705 c.d.asBytes[j+3],\r
706 c.d.asBytes[j+4],\r
707 c.d.asBytes[j+5],\r
708 c.d.asBytes[j+6],\r
709 c.d.asBytes[j+7],\r
710 c.d.asBytes[j+8]\r
711 );\r
712 }\r
713 }\r
714}\r
715\r
716static void CmdHisampless(char *str)\r
717{\r
718 int cnt = 0;\r
719 int i;\r
720 int n;\r
721\r
722 if(atoi(str) == 0) {\r
723 n = 1000;\r
724 } else {\r
725 n = atoi(str)/4;\r
726 }\r
727\r
728 for(i = 0; i < n; i += 12) {\r
729 UsbCommand c;\r
730 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
731 c.ext1 = i;\r
732 SendCommand(&c, FALSE);\r
733 ReceiveCommand(&c);\r
734 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
9760414b 735 PrintToScrollback("bad resp");\r
6658905f 736 return;\r
737 }\r
738 int j;\r
739 for(j = 0; j < 48; j++) {\r
740 GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]);\r
741 }\r
742 }\r
743 GraphTraceLen = cnt;\r
744\r
745 RepaintGraphWindow();\r
746}\r
747\r
748static WORD Iso15693Crc(BYTE *v, int n)\r
749{\r
750 DWORD reg;\r
751 int i, j;\r
752\r
753 reg = 0xffff;\r
754 for(i = 0; i < n; i++) {\r
755 reg = reg ^ ((DWORD)v[i]);\r
756 for (j = 0; j < 8; j++) {\r
757 if (reg & 0x0001) {\r
758 reg = (reg >> 1) ^ 0x8408;\r
759 } else {\r
760 reg = (reg >> 1);\r
761 }\r
762 }\r
763 }\r
764\r
765 return (WORD)~reg;\r
766}\r
767\r
768static void CmdHi14bdemod(char *str)\r
769{\r
770 int i, j, iold;\r
771 int isum, qsum;\r
772 int outOfWeakAt;\r
773 BOOL negateI, negateQ;\r
774\r
775 BYTE data[256];\r
776 int dataLen=0;\r
777\r
778 // As received, the samples are pairs, correlations against I and Q\r
779 // square waves. So estimate angle of initial carrier (or just\r
780 // quadrant, actually), and then do the demod.\r
781\r
782 // First, estimate where the tag starts modulating.\r
783 for(i = 0; i < GraphTraceLen; i += 2) {\r
784 if(abs(GraphBuffer[i]) + abs(GraphBuffer[i+1]) > 40) {\r
785 break;\r
786 }\r
787 }\r
788 if(i >= GraphTraceLen) {\r
789 PrintToScrollback("too weak to sync");\r
790 return;\r
791 }\r
792 PrintToScrollback("out of weak at %d", i);\r
793 outOfWeakAt = i;\r
794\r
795 // Now, estimate the phase in the initial modulation of the tag\r
796 isum = 0;\r
797 qsum = 0;\r
798 for(; i < (outOfWeakAt + 16); i += 2) {\r
799 isum += GraphBuffer[i+0];\r
800 qsum += GraphBuffer[i+1];\r
801 }\r
802 negateI = (isum < 0);\r
803 negateQ = (qsum < 0);\r
804\r
805 // Turn the correlation pairs into soft decisions on the bit.\r
806 j = 0;\r
807 for(i = 0; i < GraphTraceLen/2; i++) {\r
808 int si = GraphBuffer[j];\r
809 int sq = GraphBuffer[j+1];\r
810 if(negateI) si = -si;\r
811 if(negateQ) sq = -sq;\r
812 GraphBuffer[i] = si + sq;\r
813 j += 2;\r
814 }\r
815 GraphTraceLen = i;\r
816\r
817 i = outOfWeakAt/2;\r
818 while(GraphBuffer[i] > 0 && i < GraphTraceLen)\r
819 i++;\r
820 if(i >= GraphTraceLen) goto demodError;\r
821\r
822 iold = i;\r
823 while(GraphBuffer[i] < 0 && i < GraphTraceLen)\r
824 i++;\r
825 if(i >= GraphTraceLen) goto demodError;\r
826 if((i - iold) > 23) goto demodError;\r
827\r
828 PrintToScrollback("make it to demod loop");\r
829\r
830 for(;;) {\r
831 iold = i;\r
832 while(GraphBuffer[i] >= 0 && i < GraphTraceLen)\r
833 i++;\r
834 if(i >= GraphTraceLen) goto demodError;\r
835 if((i - iold) > 6) goto demodError;\r
836\r
837 WORD shiftReg = 0;\r
838 if(i + 20 >= GraphTraceLen) goto demodError;\r
839\r
840 for(j = 0; j < 10; j++) {\r
841 int soft = GraphBuffer[i] + GraphBuffer[i+1];\r
842\r
843 if(abs(soft) < ((abs(isum) + abs(qsum))/20)) {\r
844 PrintToScrollback("weak bit");\r
845 }\r
846\r
847 shiftReg >>= 1;\r
848 if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {\r
849 shiftReg |= 0x200;\r
850 }\r
851\r
852 i+= 2;\r
853 }\r
854\r
855 if( (shiftReg & 0x200) &&\r
856 !(shiftReg & 0x001))\r
857 {\r
858 // valid data byte, start and stop bits okay\r
859 PrintToScrollback(" %02x", (shiftReg >> 1) & 0xff);\r
860 data[dataLen++] = (shiftReg >> 1) & 0xff;\r
861 if(dataLen >= sizeof(data)) {\r
862 return;\r
863 }\r
864 } else if(shiftReg == 0x000) {\r
865 // this is EOF\r
866 break;\r
867 } else {\r
868 goto demodError;\r
869 }\r
870 }\r
871\r
872 BYTE first, second;\r
873 ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);\r
874 PrintToScrollback("CRC: %02x %02x (%s)\n", first, second,\r
875 (first == data[dataLen-2] && second == data[dataLen-1]) ?\r
876 "ok" : "****FAIL****");\r
877\r
878 RepaintGraphWindow();\r
879 return;\r
880\r
881demodError:\r
882 PrintToScrollback("demod error");\r
883 RepaintGraphWindow();\r
884}\r
885\r
886static void CmdHi14list(char *str)\r
887{\r
888 BYTE got[960];\r
889 GetFromBigBuf(got, sizeof(got));\r
890\r
891 PrintToScrollback("recorded activity:");\r
892 PrintToScrollback(" time :rssi: who bytes");\r
893 PrintToScrollback("---------+----+----+-----------");\r
894\r
895 int i = 0;\r
896 int prev = -1;\r
897\r
898 for(;;) {\r
899 if(i >= 900) {\r
900 break;\r
901 }\r
902\r
903 BOOL isResponse;\r
904 int timestamp = *((DWORD *)(got+i));\r
905 if(timestamp & 0x80000000) {\r
906 timestamp &= 0x7fffffff;\r
907 isResponse = 1;\r
908 } else {\r
909 isResponse = 0;\r
910 }\r
911 int metric = *((DWORD *)(got+i+4));\r
912\r
913 int len = got[i+8];\r
914\r
915 if(len > 100) {\r
916 break;\r
917 }\r
918 if(i + len >= 900) {\r
919 break;\r
920 }\r
921\r
922 BYTE *frame = (got+i+9);\r
923\r
924 char line[1000] = "";\r
925 int j;\r
926 for(j = 0; j < len; j++) {\r
927 sprintf(line+(j*3), "%02x ", frame[j]);\r
928 }\r
929\r
930 char *crc;\r
931 if(len > 2) {\r
932 BYTE b1, b2;\r
933 ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2);\r
934 if(b1 != frame[len-2] || b2 != frame[len-1]) {\r
935 crc = "**FAIL CRC**";\r
936 } else {\r
937 crc = "";\r
938 }\r
939 } else {\r
940 crc = "(SHORT)";\r
941 }\r
942\r
943 char metricString[100];\r
944 if(isResponse) {\r
945 sprintf(metricString, "%3d", metric);\r
946 } else {\r
947 strcpy(metricString, " ");\r
948 }\r
949\r
950 PrintToScrollback(" +%7d: %s: %s %s %s",\r
951 (prev < 0 ? 0 : timestamp - prev),\r
952 metricString,\r
953 (isResponse ? "TAG" : " "), line, crc);\r
954\r
955 prev = timestamp;\r
956 i += (len + 9);\r
957 }\r
958}\r
959\r
960static void CmdHi14alist(char *str)\r
961{\r
962 BYTE got[1920];\r
963 GetFromBigBuf(got, sizeof(got));\r
964\r
965 PrintToScrollback("recorded activity:");\r
966 PrintToScrollback(" ETU :rssi: who bytes");\r
967 PrintToScrollback("---------+----+----+-----------");\r
968\r
969 int i = 0;\r
970 int prev = -1;\r
971\r
972 for(;;) {\r
973 if(i >= 1900) {\r
974 break;\r
975 }\r
976\r
977 BOOL isResponse;\r
978 int timestamp = *((DWORD *)(got+i));\r
979 if(timestamp & 0x80000000) {\r
980 timestamp &= 0x7fffffff;\r
981 isResponse = 1;\r
982 } else {\r
983 isResponse = 0;\r
984 }\r
985\r
986 int metric = 0;\r
987 int parityBits = *((DWORD *)(got+i+4));\r
988 // 4 bytes of additional information...\r
989 // maximum of 32 additional parity bit information\r
990 //\r
991 // TODO:\r
992 // at each quarter bit period we can send power level (16 levels)\r
993 // or each half bit period in 256 levels.\r
994\r
995\r
996 int len = got[i+8];\r
997\r
998 if(len > 100) {\r
999 break;\r
1000 }\r
1001 if(i + len >= 1900) {\r
1002 break;\r
1003 }\r
1004\r
1005 BYTE *frame = (got+i+9);\r
1006\r
1007 // Break and stick with current result if buffer was not completely full\r
1008 if(frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }\r
1009\r
1010 char line[1000] = "";\r
1011 int j;\r
1012 for(j = 0; j < len; j++) {\r
1013 int oddparity = 0x01;\r
1014 int k;\r
1015\r
1016 for(k=0;k<8;k++) {\r
1017 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);\r
1018 }\r
1019\r
1020 //if((parityBits >> (len - j - 1)) & 0x01) {\r
1021 if(isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {\r
1022 sprintf(line+(j*4), "%02x! ", frame[j]);\r
1023 }\r
1024 else {\r
1025 sprintf(line+(j*4), "%02x ", frame[j]);\r
1026 }\r
1027 }\r
1028\r
1029 char *crc;\r
1030 crc = "";\r
1031 if(len > 2) {\r
1032 BYTE b1, b2;\r
1033 for(j = 0; j < (len - 1); j++) {\r
1034 // gives problems... search for the reason..\r
1035 /*if(frame[j] == 0xAA) {\r
1036 switch(frame[j+1]) {\r
1037 case 0x01:\r
1038 crc = "[1] Two drops close after each other";\r
1039 break;\r
1040 case 0x02:\r
1041 crc = "[2] Potential SOC with a drop in second half of bitperiod";\r
1042 break;\r
1043 case 0x03:\r
1044 crc = "[3] Segment Z after segment X is not possible";\r
1045 break;\r
1046 case 0x04:\r
1047 crc = "[4] Parity bit of a fully received byte was wrong";\r
1048 break;\r
1049 default:\r
1050 crc = "[?] Unknown error";\r
1051 break;\r
1052 }\r
1053 break;\r
1054 }*/\r
1055 }\r
1056\r
1057 if(strlen(crc)==0) {\r
1058 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);\r
1059 if(b1 != frame[len-2] || b2 != frame[len-1]) {\r
1060 crc = (isResponse & (len < 6)) ? "" : " !crc";\r
1061 } else {\r
1062 crc = "";\r
1063 }\r
1064 }\r
1065 } else {\r
1066 crc = ""; // SHORT\r
1067 }\r
1068\r
1069 char metricString[100];\r
1070 if(isResponse) {\r
1071 sprintf(metricString, "%3d", metric);\r
1072 } else {\r
1073 strcpy(metricString, " ");\r
1074 }\r
1075\r
1076 PrintToScrollback(" +%7d: %s: %s %s %s",\r
1077 (prev < 0 ? 0 : (timestamp - prev)),\r
1078 metricString,\r
1079 (isResponse ? "TAG" : " "), line, crc);\r
1080\r
1081 prev = timestamp;\r
1082 i += (len + 9);\r
1083 }\r
1084 CommandFinished = 1;\r
1085}\r
1086\r
1087static void CmdHi15demod(char *str)\r
1088{\r
1089 // The sampling rate is 106.353 ksps/s, for T = 18.8 us\r
1090\r
0e25ae11 1091 // SOF defined as\r
6658905f 1092 // 1) Unmodulated time of 56.64us\r
1093 // 2) 24 pulses of 423.75khz\r
1094 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)\r
1095\r
1096 static const int FrameSOF[] = {\r
1097 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1098 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1099 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1100 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1101 -1, -1, -1, -1,\r
1102 -1, -1, -1, -1,\r
1103 1, 1, 1, 1,\r
1104 1, 1, 1, 1\r
1105 };\r
1106 static const int Logic0[] = {\r
1107 1, 1, 1, 1,\r
1108 1, 1, 1, 1,\r
1109 -1, -1, -1, -1,\r
1110 -1, -1, -1, -1\r
1111 };\r
1112 static const int Logic1[] = {\r
1113 -1, -1, -1, -1,\r
1114 -1, -1, -1, -1,\r
1115 1, 1, 1, 1,\r
1116 1, 1, 1, 1\r
1117 };\r
1118\r
0e25ae11 1119 // EOF defined as\r
6658905f 1120 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)\r
1121 // 2) 24 pulses of 423.75khz\r
1122 // 3) Unmodulated time of 56.64us\r
1123\r
1124 static const int FrameEOF[] = {\r
1125 1, 1, 1, 1,\r
1126 1, 1, 1, 1,\r
1127 -1, -1, -1, -1,\r
1128 -1, -1, -1, -1,\r
1129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1131 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1132 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\r
1133 };\r
1134\r
1135 int i, j;\r
1136 int max = 0, maxPos;\r
1137\r
1138 int skip = 4;\r
1139\r
1140 if(GraphTraceLen < 1000) return;\r
1141\r
1142 // First, correlate for SOF\r
1143 for(i = 0; i < 100; i++) {\r
1144 int corr = 0;\r
1145 for(j = 0; j < arraylen(FrameSOF); j += skip) {\r
1146 corr += FrameSOF[j]*GraphBuffer[i+(j/skip)];\r
1147 }\r
1148 if(corr > max) {\r
1149 max = corr;\r
1150 maxPos = i;\r
1151 }\r
1152 }\r
1153 PrintToScrollback("SOF at %d, correlation %d", maxPos,\r
1154 max/(arraylen(FrameSOF)/skip));\r
1155\r
1156 i = maxPos + arraylen(FrameSOF)/skip;\r
1157 int k = 0;\r
1158 BYTE outBuf[20];\r
1159 memset(outBuf, 0, sizeof(outBuf));\r
1160 BYTE mask = 0x01;\r
1161 for(;;) {\r
1162 int corr0 = 0, corr1 = 0, corrEOF = 0;\r
1163 for(j = 0; j < arraylen(Logic0); j += skip) {\r
1164 corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];\r
1165 }\r
1166 for(j = 0; j < arraylen(Logic1); j += skip) {\r
1167 corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];\r
1168 }\r
1169 for(j = 0; j < arraylen(FrameEOF); j += skip) {\r
1170 corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];\r
1171 }\r
1172 // Even things out by the length of the target waveform.\r
1173 corr0 *= 4;\r
1174 corr1 *= 4;\r
1175\r
1176 if(corrEOF > corr1 && corrEOF > corr0) {\r
1177 PrintToScrollback("EOF at %d", i);\r
1178 break;\r
1179 } else if(corr1 > corr0) {\r
1180 i += arraylen(Logic1)/skip;\r
1181 outBuf[k] |= mask;\r
1182 } else {\r
1183 i += arraylen(Logic0)/skip;\r
1184 }\r
1185 mask <<= 1;\r
1186 if(mask == 0) {\r
1187 k++;\r
1188 mask = 0x01;\r
1189 }\r
1190 if((i+(int)arraylen(FrameEOF)) >= GraphTraceLen) {\r
1191 PrintToScrollback("ran off end!");\r
1192 break;\r
1193 }\r
1194 }\r
1195 if(mask != 0x01) {\r
1196 PrintToScrollback("error, uneven octet! (discard extra bits!)");\r
1197 PrintToScrollback(" mask=%02x", mask);\r
1198 }\r
1199 PrintToScrollback("%d octets", k);\r
1200\r
1201 for(i = 0; i < k; i++) {\r
1202 PrintToScrollback("# %2d: %02x ", i, outBuf[i]);\r
1203 }\r
1204 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf, k-2));\r
1205}\r
1206\r
1207static void CmdTiread(char *str)\r
1208{\r
1209 UsbCommand c;\r
1210 c.cmd = CMD_ACQUIRE_RAW_BITS_TI_TYPE;\r
1211 SendCommand(&c, FALSE);\r
1212}\r
1213\r
1214static void CmdTibits(char *str)\r
1215{\r
1216 int cnt = 0;\r
1217 int i;\r
1218 for(i = 0; i < 1536; i += 12) {\r
1219 UsbCommand c;\r
1220 c.cmd = CMD_DOWNLOAD_RAW_BITS_TI_TYPE;\r
1221 c.ext1 = i;\r
1222 SendCommand(&c, FALSE);\r
1223 ReceiveCommand(&c);\r
1224 if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {\r
9760414b 1225 PrintToScrollback("bad resp");\r
6658905f 1226 return;\r
1227 }\r
1228 int j;\r
1229 for(j = 0; j < 12; j++) {\r
1230 int k;\r
1231 for(k = 31; k >= 0; k--) {\r
1232 if(c.d.asDwords[j] & (1 << k)) {\r
1233 GraphBuffer[cnt++] = 1;\r
1234 } else {\r
1235 GraphBuffer[cnt++] = -1;\r
1236 }\r
1237 }\r
1238 }\r
1239 }\r
1240 GraphTraceLen = 1536*32;\r
1241 RepaintGraphWindow();\r
1242}\r
1243\r
1244static void CmdTidemod(char *cmdline)\r
1245{\r
1246 /* MATLAB as follows:\r
1247f_s = 2000000; % sampling frequency\r
1248f_l = 123200; % low FSK tone\r
1249f_h = 134200; % high FSK tone\r
1250\r
1251T_l = 119e-6; % low bit duration\r
1252T_h = 130e-6; % high bit duration\r
1253\r
1254l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);\r
1255h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);\r
1256\r
1257l = sign(sin(cumsum(l)));\r
1258h = sign(sin(cumsum(h)));\r
1259 */\r
1260 static const int LowTone[] = {\r
1261 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,\r
1262 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1263 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,\r
1264 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,\r
1265 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,\r
1266 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,\r
1267 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,\r
1268 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1269 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,\r
1270 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,\r
1271 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,\r
1272 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,\r
1273 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,\r
1274 };\r
1275 static const int HighTone[] = {\r
1276 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1277 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,\r
1278 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,\r
1279 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,\r
1280 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1281 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,\r
1282 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,\r
1283 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1284 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1285 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,\r
1286 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,\r
1287 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,\r
1288 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1289 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,\r
1290 };\r
1291\r
1292 int convLen = max(arraylen(HighTone), arraylen(LowTone));\r
1293\r
1294 int i;\r
1295 for(i = 0; i < GraphTraceLen - convLen; i++) {\r
1296 int j;\r
1297 int lowSum = 0, highSum = 0;;\r
1298 int lowLen = arraylen(LowTone);\r
1299 int highLen = arraylen(HighTone);\r
1300\r
1301 for(j = 0; j < lowLen; j++) {\r
1302 lowSum += LowTone[j]*GraphBuffer[i+j];\r
1303 }\r
1304 for(j = 0; j < highLen; j++) {\r
1305 highSum += HighTone[j]*GraphBuffer[i+j];\r
1306 }\r
1307 lowSum = abs((100*lowSum) / lowLen);\r
1308 highSum = abs((100*highSum) / highLen);\r
1309 GraphBuffer[i] = (highSum << 16) | lowSum;\r
1310 }\r
1311\r
1312 for(i = 0; i < GraphTraceLen - convLen - 16; i++) {\r
1313 int j;\r
1314 int lowTot = 0, highTot = 0;\r
1315 // 16 and 15 are f_s divided by f_l and f_h, rounded\r
1316 for(j = 0; j < 16; j++) {\r
1317 lowTot += (GraphBuffer[i+j] & 0xffff);\r
1318 }\r
1319 for(j = 0; j < 15; j++) {\r
1320 highTot += (GraphBuffer[i+j] >> 16);\r
1321 }\r
1322 GraphBuffer[i] = lowTot - highTot;\r
1323 }\r
1324\r
1325 GraphTraceLen -= (convLen + 16);\r
1326\r
1327 RepaintGraphWindow();\r
1328\r
1329 // Okay, so now we have unsliced soft decisions; find bit-sync, and then\r
1330 // get some bits.\r
1331\r
1332 int max = 0, maxPos = 0;\r
1333 for(i = 0; i < 6000; i++) {\r
1334 int j;\r
1335 int dec = 0;\r
1336 for(j = 0; j < 8*arraylen(LowTone); j++) {\r
1337 dec -= GraphBuffer[i+j];\r
1338 }\r
1339 for(; j < 8*arraylen(LowTone) + 8*arraylen(HighTone); j++) {\r
1340 dec += GraphBuffer[i+j];\r
1341 }\r
1342 if(dec > max) {\r
1343 max = dec;\r
1344 maxPos = i;\r
1345 }\r
1346 }\r
1347 GraphBuffer[maxPos] = 800;\r
1348 GraphBuffer[maxPos+1] = -800;\r
1349\r
1350 maxPos += 8*arraylen(LowTone);\r
1351 GraphBuffer[maxPos] = 800;\r
1352 GraphBuffer[maxPos+1] = -800;\r
1353 maxPos += 8*arraylen(HighTone);\r
1354\r
1355 GraphBuffer[maxPos] = 800;\r
1356 GraphBuffer[maxPos+1] = -800;\r
1357\r
1358 PrintToScrollback("actual data bits start at sample %d", maxPos);\r
1359\r
1360 PrintToScrollback("length %d/%d", arraylen(HighTone), arraylen(LowTone));\r
1361\r
1362 GraphBuffer[maxPos] = 800;\r
1363 GraphBuffer[maxPos+1] = -800;\r
1364\r
1365 BYTE bits[64+16+8+1];\r
1366 bits[sizeof(bits)-1] = '\0';\r
1367\r
1368 for(i = 0; i < arraylen(bits); i++) {\r
1369 int high = 0;\r
1370 int low = 0;\r
1371 int j;\r
1372 for(j = 0; j < arraylen(LowTone); j++) {\r
1373 low -= GraphBuffer[maxPos+j];\r
1374 }\r
1375 for(j = 0; j < arraylen(HighTone); j++) {\r
1376 high += GraphBuffer[maxPos+j];\r
1377 }\r
1378 if(high > low) {\r
1379 bits[i] = '1';\r
1380 maxPos += arraylen(HighTone);\r
1381 } else {\r
1382 bits[i] = '.';\r
1383 maxPos += arraylen(LowTone);\r
1384 }\r
1385 GraphBuffer[maxPos] = 800;\r
1386 GraphBuffer[maxPos+1] = -800;\r
1387 }\r
1388 PrintToScrollback("bits: '%s'", bits);\r
1389\r
1390 DWORD h = 0, l = 0;\r
1391 for(i = 0; i < 32; i++) {\r
1392 if(bits[i] == '1') {\r
1393 l |= (1<<i);\r
1394 }\r
1395 }\r
1396 for(i = 32; i < 64; i++) {\r
1397 if(bits[i] == '1') {\r
1398 h |= (1<<(i-32));\r
1399 }\r
1400 }\r
1401 PrintToScrollback("hex: %08x %08x", h, l);\r
1402}\r
1403\r
1404static void CmdNorm(char *str)\r
1405{\r
1406 int i;\r
1407 int max = INT_MIN, min = INT_MAX;\r
1408 for(i = 10; i < GraphTraceLen; i++) {\r
1409 if(GraphBuffer[i] > max) {\r
1410 max = GraphBuffer[i];\r
1411 }\r
1412 if(GraphBuffer[i] < min) {\r
1413 min = GraphBuffer[i];\r
1414 }\r
1415 }\r
1416 if(max != min) {\r
1417 for(i = 0; i < GraphTraceLen; i++) {\r
1418 GraphBuffer[i] = (GraphBuffer[i] - ((max + min)/2))*1000/\r
1419 (max - min);\r
1420 }\r
1421 }\r
1422 RepaintGraphWindow();\r
1423}\r
1424\r
1425static void CmdDec(char *str)\r
1426{\r
1427 int i;\r
1428 for(i = 0; i < (GraphTraceLen/2); i++) {\r
1429 GraphBuffer[i] = GraphBuffer[i*2];\r
1430 }\r
1431 GraphTraceLen /= 2;\r
1432 PrintToScrollback("decimated by 2");\r
1433 RepaintGraphWindow();\r
1434}\r
1435\r
1436static void CmdHpf(char *str)\r
1437{\r
1438 int i;\r
1439 int accum = 0;\r
1440 for(i = 10; i < GraphTraceLen; i++) {\r
1441 accum += GraphBuffer[i];\r
1442 }\r
1443 accum /= (GraphTraceLen - 10);\r
1444 for(i = 0; i < GraphTraceLen; i++) {\r
1445 GraphBuffer[i] -= accum;\r
1446 }\r
1447\r
1448 RepaintGraphWindow();\r
1449}\r
1450\r
1451static void CmdZerocrossings(char *str)\r
1452{\r
1453 int i;\r
1454 // Zero-crossings aren't meaningful unless the signal is zero-mean.\r
1455 CmdHpf("");\r
1456\r
1457 int sign = 1;\r
1458 int zc = 0;\r
1459 int lastZc = 0;\r
1460 for(i = 0; i < GraphTraceLen; i++) {\r
1461 if(GraphBuffer[i]*sign >= 0) {\r
1462 // No change in sign, reproduce the previous sample count.\r
1463 zc++;\r
1464 GraphBuffer[i] = lastZc;\r
1465 } else {\r
1466 // Change in sign, reset the sample count.\r
1467 sign = -sign;\r
1468 GraphBuffer[i] = lastZc;\r
1469 if(sign > 0) {\r
1470 lastZc = zc;\r
1471 zc = 0;\r
1472 }\r
1473 }\r
1474 }\r
1475\r
1476 RepaintGraphWindow();\r
1477}\r
1478\r
1479static void CmdLtrim(char *str)\r
1480{\r
1481 int i;\r
1482 int ds = atoi(str);\r
1483\r
1484 for(i = ds; i < GraphTraceLen; i++) {\r
1485 GraphBuffer[i-ds] = GraphBuffer[i];\r
1486 }\r
1487 GraphTraceLen -= ds;\r
1488\r
1489 RepaintGraphWindow();\r
1490}\r
1491\r
1492static void CmdAutoCorr(char *str)\r
1493{\r
1494 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];\r
1495\r
1496 int window = atoi(str);\r
1497\r
1498 if(window == 0) {\r
1499 PrintToScrollback("needs a window");\r
1500 return;\r
1501 }\r
1502\r
1503 if(window >= GraphTraceLen) {\r
1504 PrintToScrollback("window must be smaller than trace (%d samples)",\r
1505 GraphTraceLen);\r
1506 return;\r
1507 }\r
1508\r
1509 PrintToScrollback("performing %d correlations", GraphTraceLen - window);\r
1510\r
1511 int i;\r
1512 for(i = 0; i < GraphTraceLen - window; i++) {\r
1513 int sum = 0;\r
1514 int j;\r
1515 for(j = 0; j < window; j++) {\r
1516 sum += (GraphBuffer[j]*GraphBuffer[i+j]) / 256;\r
1517 }\r
1518 CorrelBuffer[i] = sum;\r
1519 }\r
1520 GraphTraceLen = GraphTraceLen - window;\r
1521 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen*sizeof(int));\r
1522\r
1523 RepaintGraphWindow();\r
1524}\r
1525\r
1526static void CmdVchdemod(char *str)\r
1527{\r
1528 // Is this the entire sync pattern, or does this also include some\r
1529 // data bits that happen to be the same everywhere? That would be\r
1530 // lovely to know.\r
1531 static const int SyncPattern[] = {\r
1532 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1533 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1535 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1536 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1537 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1538 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1539 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1540 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1541 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1542 };\r
1543\r
1544 // So first, we correlate for the sync pattern, and mark that.\r
1545 int bestCorrel = 0, bestPos = 0;\r
1546 int i;\r
1547 // It does us no good to find the sync pattern, with fewer than\r
1548 // 2048 samples after it...\r
1549 for(i = 0; i < (GraphTraceLen-2048); i++) {\r
1550 int sum = 0;\r
1551 int j;\r
1552 for(j = 0; j < arraylen(SyncPattern); j++) {\r
1553 sum += GraphBuffer[i+j]*SyncPattern[j];\r
1554 }\r
1555 if(sum > bestCorrel) {\r
1556 bestCorrel = sum;\r
1557 bestPos = i;\r
1558 }\r
1559 }\r
1560 PrintToScrollback("best sync at %d [metric %d]", bestPos, bestCorrel);\r
1561\r
1562 char bits[257];\r
1563 bits[256] = '\0';\r
1564\r
1565 int worst = INT_MAX;\r
1566 int worstPos;\r
1567\r
1568 for(i = 0; i < 2048; i += 8) {\r
1569 int sum = 0;\r
1570 int j;\r
1571 for(j = 0; j < 8; j++) {\r
1572 sum += GraphBuffer[bestPos+i+j];\r
1573 }\r
1574 if(sum < 0) {\r
1575 bits[i/8] = '.';\r
1576 } else {\r
1577 bits[i/8] = '1';\r
1578 }\r
1579 if(abs(sum) < worst) {\r
1580 worst = abs(sum);\r
1581 worstPos = i;\r
1582 }\r
1583 }\r
1584 PrintToScrollback("bits:");\r
1585 PrintToScrollback("%s", bits);\r
1586 PrintToScrollback("worst metric: %d at pos %d", worst, worstPos);\r
1587\r
1588 if(strcmp(str, "clone")==0) {\r
1589 GraphTraceLen = 0;\r
1590 char *s;\r
1591 for(s = bits; *s; s++) {\r
1592 int j;\r
1593 for(j = 0; j < 16; j++) {\r
1594 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;\r
1595 }\r
1596 }\r
1597 RepaintGraphWindow();\r
1598 }\r
1599}\r
1600\r
a60612db 1601static void CmdIndalademod(char *str)\r
1602{\r
1603 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID\r
1604\r
1605 int state = -1;\r
1606 int count = 0;\r
1607 int i, j;\r
1608 // worst case with GraphTraceLen=64000 is < 4096\r
1609 // under normal conditions it's < 2048\r
1610 BYTE rawbits[4096];\r
1611 int rawbit = 0;\r
1612 int worst = 0, worstPos = 0;\r
1613 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32);\r
1614 for(i = 0; i < GraphTraceLen-1; i += 2) {\r
1615 count+=1;\r
1616 if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {\r
1617 if (state == 0) {\r
1618 for(j = 0; j < count - 8; j += 16) {\r
1619 rawbits[rawbit++] = 0;\r
1620 }\r
1621 if ((abs(count - j)) > worst) {\r
1622 worst = abs(count - j);\r
1623 worstPos = i;\r
1624 }\r
1625 }\r
1626 state = 1;\r
1627 count=0;\r
1628 } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {\r
1629 if (state == 1) {\r
1630 for(j = 0; j < count - 8; j += 16) {\r
1631 rawbits[rawbit++] = 1;\r
1632 }\r
1633 if ((abs(count - j)) > worst) {\r
1634 worst = abs(count - j);\r
1635 worstPos = i;\r
1636 }\r
1637 }\r
1638 state = 0;\r
1639 count=0;\r
1640 }\r
1641 }\r
1642 PrintToScrollback("Recovered %d raw bits", rawbit);\r
1643 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);\r
1644\r
1645 // Finding the start of a UID\r
1646 int uidlen, long_wait;\r
1647 if(strcmp(str, "224") == 0) {\r
1648 uidlen=224;\r
1649 long_wait=30;\r
1650 } else {\r
1651 uidlen=64;\r
1652 long_wait=29;\r
1653 }\r
1654 int start;\r
1655 int first = 0;\r
1656 for(start = 0; start <= rawbit - uidlen; start++) {\r
1657 first = rawbits[start];\r
1658 for(i = start; i < start + long_wait; i++) {\r
1659 if(rawbits[i] != first) {\r
1660 break;\r
1661 }\r
1662 }\r
1663 if(i == (start + long_wait)) {\r
1664 break;\r
1665 }\r
1666 }\r
1667 if(start == rawbit - uidlen + 1) {\r
1668 PrintToScrollback("nothing to wait for");\r
1669 return;\r
1670 }\r
1671\r
1672 // Inverting signal if needed\r
1673 if(first == 1) {\r
1674 for(i = start; i < rawbit; i++) {\r
1675 rawbits[i] = !rawbits[i];\r
1676 }\r
1677 }\r
1678\r
1679 // Dumping UID\r
1680 BYTE bits[224];\r
1681 char showbits[225];\r
1682 showbits[uidlen]='\0';\r
1683 int bit;\r
1684 i = start;\r
1685 int times = 0;\r
1686 if(uidlen > rawbit) {\r
1687 PrintToScrollback("Warning: not enough raw bits to get a full UID");\r
1688 for(bit = 0; bit < rawbit; bit++) {\r
1689 bits[bit] = rawbits[i++];\r
1690 // As we cannot know the parity, let's use "." and "/"\r
1691 showbits[bit] = '.' + bits[bit];\r
1692 }\r
1693 showbits[bit+1]='\0';\r
1694 PrintToScrollback("Partial UID=%s", showbits);\r
1695 return;\r
1696 } else {\r
1697 for(bit = 0; bit < uidlen; bit++) {\r
1698 bits[bit] = rawbits[i++];\r
1699 showbits[bit] = '0' + bits[bit];\r
1700 }\r
1701 times = 1;\r
1702 }\r
1703 PrintToScrollback("UID=%s", showbits);\r
1704\r
1705 // Checking UID against next occurences\r
1706 for(; i + uidlen <= rawbit;) {\r
1707 int failed = 0;\r
1708 for(bit = 0; bit < uidlen; bit++) {\r
1709 if(bits[bit] != rawbits[i++]) {\r
1710 failed = 1;\r
1711 break;\r
1712 }\r
1713 }\r
1714 if (failed == 1) {\r
1715 break;\r
1716 }\r
1717 times += 1;\r
1718 }\r
1719 PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);\r
1720\r
1721 // Remodulating for tag cloning\r
1722 GraphTraceLen = 32*uidlen;\r
1723 i = 0;\r
1724 int phase = 0;\r
1725 for(bit = 0; bit < uidlen; bit++) {\r
1726 if(bits[bit] == 0) {\r
1727 phase = 0;\r
1728 } else {\r
1729 phase = 1;\r
1730 }\r
1731 int j;\r
1732 for(j = 0; j < 32; j++) {\r
1733 GraphBuffer[i++] = phase;\r
1734 phase = !phase;\r
1735 }\r
1736 }\r
1737\r
1738 RepaintGraphWindow();\r
1739}\r
1740\r
6658905f 1741static void CmdFlexdemod(char *str)\r
1742{\r
1743 int i;\r
1744 for(i = 0; i < GraphTraceLen; i++) {\r
1745 if(GraphBuffer[i] < 0) {\r
1746 GraphBuffer[i] = -1;\r
1747 } else {\r
1748 GraphBuffer[i] = 1;\r
1749 }\r
1750 }\r
1751\r
1752#define LONG_WAIT 100\r
1753 int start;\r
1754 for(start = 0; start < GraphTraceLen - LONG_WAIT; start++) {\r
1755 int first = GraphBuffer[start];\r
1756 for(i = start; i < start + LONG_WAIT; i++) {\r
1757 if(GraphBuffer[i] != first) {\r
1758 break;\r
1759 }\r
1760 }\r
1761 if(i == (start + LONG_WAIT)) {\r
1762 break;\r
1763 }\r
1764 }\r
1765 if(start == GraphTraceLen - LONG_WAIT) {\r
1766 PrintToScrollback("nothing to wait for");\r
1767 return;\r
1768 }\r
1769\r
1770 GraphBuffer[start] = 2;\r
1771 GraphBuffer[start+1] = -2;\r
1772\r
1773 BYTE bits[64];\r
1774\r
1775 int bit;\r
1776 i = start;\r
1777 for(bit = 0; bit < 64; bit++) {\r
1778 int j;\r
1779 int sum = 0;\r
1780 for(j = 0; j < 16; j++) {\r
1781 sum += GraphBuffer[i++];\r
1782 }\r
1783 if(sum > 0) {\r
1784 bits[bit] = 1;\r
1785 } else {\r
1786 bits[bit] = 0;\r
1787 }\r
1788 PrintToScrollback("bit %d sum %d", bit, sum);\r
1789 }\r
1790\r
1791 for(bit = 0; bit < 64; bit++) {\r
1792 int j;\r
1793 int sum = 0;\r
1794 for(j = 0; j < 16; j++) {\r
1795 sum += GraphBuffer[i++];\r
1796 }\r
1797 if(sum > 0 && bits[bit] != 1) {\r
1798 PrintToScrollback("oops1 at %d", bit);\r
1799 }\r
1800 if(sum < 0 && bits[bit] != 0) {\r
1801 PrintToScrollback("oops2 at %d", bit);\r
1802 }\r
1803 }\r
1804\r
1805 GraphTraceLen = 32*64;\r
1806 i = 0;\r
1807 int phase = 0;\r
1808 for(bit = 0; bit < 64; bit++) {\r
1809 if(bits[bit] == 0) {\r
1810 phase = 0;\r
1811 } else {\r
1812 phase = 1;\r
1813 }\r
1814 int j;\r
1815 for(j = 0; j < 32; j++) {\r
1816 GraphBuffer[i++] = phase;\r
1817 phase = !phase;\r
1818 }\r
1819 }\r
1820\r
1821 RepaintGraphWindow();\r
1822}\r
9760414b 1823\r
1824/*\r
15db5fb7 1825 * Generic command to demodulate ASK.\r
9760414b 1826 *\r
15db5fb7 1827 * Argument is convention: positive or negative (High mod means zero\r
9760414b 1828 * or high mod means one)\r
1829 *\r
1830 * Updates the Graph trace with 0/1 values\r
1831 *\r
1832 * Arguments:\r
9760414b 1833 * c : 0 or 1\r
1834 */\r
1835\r
1836static void Cmdaskdemod(char *str) {\r
1837 int i;\r
9760414b 1838 int n = 0;\r
15db5fb7 1839 int c,high,low = 0;\r
9760414b 1840\r
1841 // TODO: complain if we do not give 2 arguments here !\r
15db5fb7 1842 sscanf(str, "%i", &c);\r
1843\r
1844 /* Detect high and lows and clock */\r
1845 for (i = 0; i < GraphTraceLen; i++)\r
1846 {\r
1847 if (GraphBuffer[i] > high)\r
1848 high = GraphBuffer[i];\r
1849 else if (GraphBuffer[i] < low)\r
1850 low = GraphBuffer[i];\r
9760414b 1851 }\r
1852\r
15db5fb7 1853 if (GraphBuffer[0] > 0) {\r
1854 GraphBuffer[0] = 1-c;\r
9760414b 1855 } else {\r
15db5fb7 1856 GraphBuffer[0] = c;\r
9760414b 1857 }\r
1858 for(i=1;i<GraphTraceLen;i++) {\r
15db5fb7 1859 /* Transitions are detected at each peak\r
1860 * Transitions are either:\r
1861 * - we're low: transition if we hit a high\r
1862 * - we're high: transition if we hit a low\r
1863 * (we need to do it this way because some tags keep high or\r
1864 * low for long periods, others just reach the peak and go\r
1865 * down)
1866 */\r
1867 if ((GraphBuffer[i]==high) && (GraphBuffer[i-1] == c)) {\r
1868 GraphBuffer[i]=1-c;\r
1869 } else if ((GraphBuffer[i]==low) && (GraphBuffer[i-1] == (1-c))){\r
1870 GraphBuffer[i] = c;\r
9760414b 1871 } else {\r
15db5fb7 1872 /* No transition */\r
9760414b 1873 GraphBuffer[i] = GraphBuffer[i-1];\r
1874 }\r
1875 }\r
1876 RepaintGraphWindow();\r
1877}\r
1878\r
1879/* Print our clock rate */\r
1880static void Cmddetectclockrate(char *str)\r
1881{\r
1882 int clock = detectclock(0);\r
1883 PrintToScrollback("Auto-detected clock rate: %d", clock);\r
1884}\r
1885\r
1886/*\r
1887 * Detect clock rate\r
1888 */\r
1889int detectclock(int peak)\r
1890{\r
1891 int i;\r
1892 int clock = 0xFFFF;\r
1893 int lastpeak = 0;\r
1894\r
1895 /* Detect peak if we don't have one */\r
1896 if (!peak)\r
1897 for (i = 0; i < GraphTraceLen; i++)\r
1898 if (GraphBuffer[i] > peak)\r
1899 peak = GraphBuffer[i];\r
1900\r
1901 for (i = 1; i < GraphTraceLen; i++)\r
1902 {\r
1903 /* If this is the beginning of a peak */\r
1904 if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)\r
1905 {\r
1906 /* Find lowest difference between peaks */\r
1907 if (lastpeak && i - lastpeak < clock)\r
1908 {\r
1909 clock = i - lastpeak;\r
1910 }\r
1911 lastpeak = i;\r
1912 }\r
1913 }\r
15db5fb7 1914\r
9760414b 1915 return clock;\r
1916}\r
1917\r
1918/* Get or auto-detect clock rate */\r
1919int GetClock(char *str, int peak)\r
1920{\r
1921 int clock;\r
15db5fb7 1922\r
9760414b 1923 sscanf(str, "%i", &clock);\r
1924 if (!strcmp(str, ""))\r
1925 clock = 0;\r
1926\r
1927 /* Auto-detect clock */\r
1928 if (!clock)\r
1929 {\r
1930 clock = detectclock(peak);\r
15db5fb7 1931\r
9760414b 1932 /* Only print this message if we're not looping something */\r
1933 if (!go)\r
1934 PrintToScrollback("Auto-detected clock rate: %d", clock);\r
1935 }\r
15db5fb7 1936\r
9760414b 1937 return clock;\r
1938}\r
1939\r
1940/*\r
1941 * Convert to a bitstream\r
1942 */\r
1943static void Cmdbitstream(char *str) {\r
c9f99c01 1944 int i, j;\r
1945 int bit;\r
9760414b 1946 int gtl;\r
1947 int clock;\r
c9f99c01 1948 int low = 0;\r
1949 int high = 0;\r
1950 int hithigh, hitlow, first;\r
9760414b 1951\r
1952 /* Detect high and lows and clock */\r
1953 for (i = 0; i < GraphTraceLen; i++)\r
c9f99c01 1954 {\r
9760414b 1955 if (GraphBuffer[i] > high)\r
1956 high = GraphBuffer[i];\r
1957 else if (GraphBuffer[i] < low)\r
1958 low = GraphBuffer[i];\r
c9f99c01 1959 }\r
9760414b 1960\r
1961 /* Get our clock */\r
1962 clock = GetClock(str, high);\r
15db5fb7 1963\r
9760414b 1964 gtl = CmdClearGraph(0);\r
15db5fb7 1965\r
9760414b 1966 bit = 0;\r
1967 for (i = 0; i < (int)(gtl / clock); i++)\r
1968 {\r
1969 hithigh = 0;\r
1970 hitlow = 0;\r
1971 first = 1;\r
15db5fb7 1972\r
9760414b 1973 /* Find out if we hit both high and low peaks */\r
1974 for (j = 0; j < clock; j++)\r
1975 {\r
1976 if (GraphBuffer[(i * clock) + j] == high)\r
1977 hithigh = 1;\r
1978 else if (GraphBuffer[(i * clock) + j] == low)\r
1979 hitlow = 1;\r
15db5fb7 1980\r
9760414b 1981 /* it doesn't count if it's the first part of our read\r
1982 because it's really just trailing from the last sequence */\r
1983 if (first && (hithigh || hitlow))\r
1984 hithigh = hitlow = 0;\r
1985 else\r
1986 first = 0;\r
15db5fb7 1987\r
9760414b 1988 if (hithigh && hitlow)\r
1989 break;\r
1990 }\r
15db5fb7 1991\r
9760414b 1992 /* If we didn't hit both high and low peaks, we had a bit transition */\r
1993 if (!hithigh || !hitlow)\r
1994 bit ^= 1;\r
1995\r
1996 CmdAppendGraph(0, clock, bit);\r
1997// for (j = 0; j < (int)(clock/2); j++)\r
1998// GraphBuffer[(i * clock) + j] = bit ^ 1;\r
1999// for (j = (int)(clock/2); j < clock; j++)\r
2000// GraphBuffer[(i * clock) + j] = bit;\r
2001 }\r
2002\r
2003 RepaintGraphWindow();\r
2004}\r
2005\r
2006/* Modulate our data into manchester */\r
2007static void Cmdmanchestermod(char *str)\r
2008{\r
2009 int i, j;\r
2010 int clock;\r
2011 int bit, lastbit, wave;\r
15db5fb7 2012\r
9760414b 2013 /* Get our clock */\r
2014 clock = GetClock(str, 0);\r
2015\r
2016 wave = 0;\r
2017 lastbit = 1;\r
2018 for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
2019 {\r
2020 bit = GraphBuffer[i * clock] ^ 1;\r
15db5fb7 2021\r
9760414b 2022 for (j = 0; j < (int)(clock/2); j++)\r
2023 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;\r
2024 for (j = (int)(clock/2); j < clock; j++)\r
2025 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;\r
15db5fb7 2026\r
9760414b 2027 /* Keep track of how we start our wave and if we changed or not this time */\r
2028 wave ^= bit ^ lastbit;\r
2029 lastbit = bit;\r
2030 }\r
15db5fb7 2031\r
9760414b 2032 RepaintGraphWindow();\r
2033}\r
2034\r
2035/*\r
2036 * Manchester demodulate a bitstream. The bitstream needs to be already in\r
2037 * the GraphBuffer as 0 and 1 values\r
2038 *\r
2039 * Give the clock rate as argument in order to help the sync - the algorithm\r
2040 * resyncs at each pulse anyway.\r
2041 *\r
2042 * Not optimized by any means, this is the 1st time I'm writing this type of\r
2043 * routine, feel free to improve...\r
2044 *\r
2045 * 1st argument: clock rate (as number of samples per clock rate)\r
2046 * Typical values can be 64, 32, 128...\r
2047 */\r
2048static void Cmdmanchesterdemod(char *str) {\r
2049 int i, j;\r
2050 int bit;\r
2051 int clock;\r
2052 int lastval;\r
2053 int low = 0;\r
2054 int high = 0;\r
2055 int hithigh, hitlow, first;\r
2056 int lc = 0;\r
2057 int bitidx = 0;\r
2058 int bit2idx = 0;\r
2059 int warnings = 0;\r
2060\r
2061 /* Holds the decoded bitstream: each clock period contains 2 bits */\r
2062 /* later simplified to 1 bit after manchester decoding. */\r
2063 /* Add 10 bits to allow for noisy / uncertain traces without aborting */\r
2064 /* int BitStream[GraphTraceLen*2/clock+10]; */\r
2065\r
2066 /* But it does not work if compiling on WIndows: therefore we just allocate a */\r
2067 /* large array */\r
2068 int BitStream[MAX_GRAPH_TRACE_LEN];\r
2069\r
c9f99c01 2070 /* Detect high and lows */\r
2071 for (i = 0; i < GraphTraceLen; i++)\r
2072 {\r
2073 if (GraphBuffer[i] > high)\r
2074 high = GraphBuffer[i];\r
2075 else if (GraphBuffer[i] < low)\r
2076 low = GraphBuffer[i];\r
2077 }\r
2078\r
9760414b 2079 /* Get our clock */\r
2080 clock = GetClock(str, high);\r
15db5fb7 2081\r
9760414b 2082 int tolerance = clock/4;\r
15db5fb7 2083\r
9760414b 2084 /* Detect first transition */\r
2085 /* Lo-Hi (arbitrary) */\r
c9f99c01 2086 for (i = 0; i < GraphTraceLen; i++)\r
2087 {\r
2088 if (GraphBuffer[i] == low)\r
2089 {\r
9760414b 2090 lastval = i;\r
2091 break;\r
2092 }\r
2093 }\r
c9f99c01 2094\r
2095 /* If we're not working with 1/0s, demod based off clock */\r
2096 if (high != 1)\r
2097 {\r
15db5fb7 2098 bit = 0; /* We assume the 1st bit is zero, it may not be\r
2099 * the case: this routine (I think) has an init problem.\r
2100 * Ed.\r
2101 */\r
2102 for (; i < (int)(GraphTraceLen / clock); i++)\r
c9f99c01 2103 {\r
2104 hithigh = 0;\r
2105 hitlow = 0;\r
2106 first = 1;\r
2107\r
2108 /* Find out if we hit both high and low peaks */\r
2109 for (j = 0; j < clock; j++)\r
2110 {\r
2111 if (GraphBuffer[(i * clock) + j] == high)\r
2112 hithigh = 1;\r
2113 else if (GraphBuffer[(i * clock) + j] == low)\r
2114 hitlow = 1;\r
2115\r
2116 /* it doesn't count if it's the first part of our read\r
2117 because it's really just trailing from the last sequence */\r
2118 if (first && (hithigh || hitlow))\r
2119 hithigh = hitlow = 0;\r
2120 else\r
2121 first = 0;\r
2122\r
2123 if (hithigh && hitlow)\r
2124 break;\r
2125 }\r
2126\r
2127 /* If we didn't hit both high and low peaks, we had a bit transition */\r
2128 if (!hithigh || !hitlow)\r
2129 bit ^= 1;\r
2130\r
2131 BitStream[bit2idx++] = bit;\r
2132 }\r
2133 }\r
2134\r
2135 /* standard 1/0 bitstream */\r
2136 else\r
2137 {\r
9760414b 2138\r
2139 /* Then detect duration between 2 successive transitions */\r
c9f99c01 2140 for (bitidx = 1; i < GraphTraceLen; i++)\r
2141 {\r
2142 if (GraphBuffer[i-1] != GraphBuffer[i])\r
2143 {\r
9760414b 2144 lc = i-lastval;\r
2145 lastval = i;\r
2146\r
2147 // Error check: if bitidx becomes too large, we do not\r
2148 // have a Manchester encoded bitstream or the clock is really\r
2149 // wrong!\r
2150 if (bitidx > (GraphTraceLen*2/clock+8) ) {\r
2151 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");\r
2152 return;\r
2153 }\r
2154 // Then switch depending on lc length:\r
2155 // Tolerance is 1/4 of clock rate (arbitrary)\r
2156 if (abs(lc-clock/2) < tolerance) {\r
2157 // Short pulse : either "1" or "0"\r
2158 BitStream[bitidx++]=GraphBuffer[i-1];\r
2159 } else if (abs(lc-clock) < tolerance) {\r
2160 // Long pulse: either "11" or "00"\r
2161 BitStream[bitidx++]=GraphBuffer[i-1];\r
2162 BitStream[bitidx++]=GraphBuffer[i-1];\r
2163 } else {\r
2164 // Error\r
c9f99c01 2165 warnings++;\r
9760414b 2166 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");\r
2167 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");\r
c9f99c01 2168\r
2169 if (warnings > 100)\r
2170 {\r
2171 PrintToScrollback("Error: too many detection errors, aborting.");\r
2172 return;\r
2173 }\r
9760414b 2174 }\r
2175 }\r
2176 }\r
2177\r
2178 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream\r
2179 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful\r
2180 // to stop output at the final bitidx2 value, not bitidx\r
2181 for (i = 0; i < bitidx; i += 2) {\r
2182 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {\r
2183 BitStream[bit2idx++] = 1;\r
2184 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {\r
2185 BitStream[bit2idx++] = 0;\r
2186 } else {\r
2187 // We cannot end up in this state, this means we are unsynchronized,\r
2188 // move up 1 bit:\r
2189 i++;\r
c9f99c01 2190 warnings++;\r
9760414b 2191 PrintToScrollback("Unsynchronized, resync...");\r
2192 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");\r
c9f99c01 2193\r
2194 if (warnings > 100)\r
2195 {\r
2196 PrintToScrollback("Error: too many decode errors, aborting.");\r
2197 return;\r
2198 }\r
9760414b 2199 }\r
2200 }\r
c9f99c01 2201 }\r
2202\r
2203 PrintToScrollback("Manchester decoded bitstream");\r
9760414b 2204 // Now output the bitstream to the scrollback by line of 16 bits\r
2205 for (i = 0; i < (bit2idx-16); i+=16) {\r
2206 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",\r
2207 BitStream[i],\r
2208 BitStream[i+1],\r
2209 BitStream[i+2],\r
2210 BitStream[i+3],\r
2211 BitStream[i+4],\r
2212 BitStream[i+5],\r
2213 BitStream[i+6],\r
2214 BitStream[i+7],\r
2215 BitStream[i+8],\r
2216 BitStream[i+9],\r
2217 BitStream[i+10],\r
2218 BitStream[i+11],\r
2219 BitStream[i+12],\r
2220 BitStream[i+13],\r
2221 BitStream[i+14],\r
2222 BitStream[i+15]);\r
2223 }\r
2224}\r
2225\r
2226\r
2227\r
2228/*\r
2229 * Usage ???\r
6658905f 2230 */\r
2231static void CmdHiddemod(char *str)\r
2232{\r
2233 if(GraphTraceLen < 4800) {\r
2234 PrintToScrollback("too short; need at least 4800 samples");\r
2235 return;\r
2236 }\r
2237\r
2238 GraphTraceLen = 4800;\r
2239 int i;\r
2240 for(i = 0; i < GraphTraceLen; i++) {\r
2241 if(GraphBuffer[i] < 0) {\r
2242 GraphBuffer[i] = 0;\r
2243 } else {\r
2244 GraphBuffer[i] = 1;\r
2245 }\r
2246 }\r
2247 RepaintGraphWindow();\r
2248}\r
2249\r
2250static void CmdPlot(char *str)\r
2251{\r
2252 ShowGraphWindow();\r
2253}\r
2254\r
2255static void CmdHide(char *str)\r
2256{\r
2257 HideGraphWindow();\r
2258}\r
2259\r
2260static void CmdScale(char *str)\r
2261{\r
2262 CursorScaleFactor = atoi(str);\r
2263 if(CursorScaleFactor == 0) {\r
2264 PrintToScrollback("bad, can't have zero scale");\r
2265 CursorScaleFactor = 1;\r
2266 }\r
2267 RepaintGraphWindow();\r
2268}\r
2269\r
2270static void CmdSave(char *str)\r
2271{\r
2272 FILE *f = fopen(str, "w");\r
2273 if(!f) {\r
2274 PrintToScrollback("couldn't open '%s'", str);\r
2275 return;\r
2276 }\r
2277 int i;\r
2278 for(i = 0; i < GraphTraceLen; i++) {\r
2279 fprintf(f, "%d\n", GraphBuffer[i]);\r
2280 }\r
2281 fclose(f);\r
2282 PrintToScrollback("saved to '%s'", str);\r
2283}\r
2284\r
2285static void CmdLoad(char *str)\r
2286{\r
2287 FILE *f = fopen(str, "r");\r
2288 if(!f) {\r
2289 PrintToScrollback("couldn't open '%s'", str);\r
2290 return;\r
2291 }\r
2292\r
2293 GraphTraceLen = 0;\r
2294 char line[80];\r
2295 while(fgets(line, sizeof(line), f)) {\r
2296 GraphBuffer[GraphTraceLen] = atoi(line);\r
2297 GraphTraceLen++;\r
2298 }\r
2299 fclose(f);\r
2300 PrintToScrollback("loaded %d samples", GraphTraceLen);\r
2301 RepaintGraphWindow();\r
2302}\r
2303\r
2304static void CmdHIDsimTAG(char *str)\r
2305{\r
2306 unsigned int hi=0, lo=0;\r
2307 int n=0, i=0;\r
2308 UsbCommand c;\r
2309\r
2310 while (sscanf(&str[i++], "%1x", &n ) == 1) {\r
2311 hi=(hi<<4)|(lo>>28);\r
2312 lo=(lo<<4)|(n&0xf);\r
2313 }\r
2314\r
2315 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);\r
2316\r
2317 c.cmd = CMD_HID_SIM_TAG;\r
2318 c.ext1 = hi;\r
2319 c.ext2 = lo;\r
2320 SendCommand(&c, FALSE);\r
2321}\r
2322\r
2323static void CmdLcdReset(char *str)\r
2324{\r
2325 UsbCommand c;\r
2326 c.cmd = CMD_LCD_RESET;\r
2327 c.ext1 = atoi(str);\r
2328 SendCommand(&c, FALSE);\r
2329}\r
2330\r
2331static void CmdLcd(char *str)\r
2332{\r
2333 int i, j;\r
2334 UsbCommand c;\r
2335 c.cmd = CMD_LCD;\r
2336 sscanf(str, "%x %d", &i, &j);\r
2337 while (j--) {\r
2338 c.ext1 = i&0x1ff;\r
2339 SendCommand(&c, FALSE);\r
2340 }\r
2341}\r
2342\r
d722c4ce 2343\r
2344\r
6658905f 2345static void CmdTest(char *str)\r
2346{\r
2347}\r
9760414b 2348\r
2349/*\r
2350 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below\r
2351 * 600kHz.\r
2352 */\r
30f2a7d3 2353static void CmdSetDivisor(char *str)\r
2354{\r
2355 UsbCommand c;\r
2356 c.cmd = CMD_SET_LF_DIVISOR;\r
2357 c.ext1 = atoi(str);\r
2358 if (( c.ext1<0) || (c.ext1>255)) {\r
2359 PrintToScrollback("divisor must be between 19 and 255");\r
2360 } else {\r
2361 SendCommand(&c, FALSE);\r
2362 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));\r
2363 }\r
2364}\r
2365\r
2366static void CmdSweepLF(char *str)\r
2367{\r
2368 UsbCommand c;\r
2369 c.cmd = CMD_SWEEP_LF;\r
2370 SendCommand(&c, FALSE);\r
2371}\r
9760414b 2372\r
2373\r
6658905f 2374typedef void HandlerFunction(char *cmdline);\r
2375\r
3f030abe 2376/* in alphabetic order */\r
6658905f 2377static struct {\r
fb25b483 2378 char *name;\r
2379 HandlerFunction *handler;\r
2380 int offline; // 1 if the command can be used when in offline mode\r
9760414b 2381 char *docString;\r
6658905f 2382} CommandTable[] = {\r
3f030abe 2383 "askdemod", Cmdaskdemod,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",\r
2384 "autocorr", CmdAutoCorr,1, "<window length> -- Autocorrelation over window",\r
2385 "bitsamples", CmdBitsamples,0, " Get raw samples as bitstring",\r
2386 "bitstream", Cmdbitstream,1, "[clock rate] -- Convert waveform into a bitstream",\r
2387 "dec", CmdDec,1, " Decimate samples",\r
2388 "detectclock", Cmddetectclockrate,1, " Detect clock rate",\r
2389 "em410xsim", CmdEM410xsim,1, "<UID> -- Simulate EM410x tag",\r
2390 "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag",\r
2391 "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags",\r
2392 "exit", CmdQuit,1, " Exit program",\r
2393 "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass",\r
2394 "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control\r
2395 "hexsamples", CmdHexsamples,0, "<blocks> -- Dump big buffer as hex bytes",\r
2396 "hi14alist", CmdHi14alist,0, " List ISO 14443a history", // ## New list command\r
2397 "hi14areader", CmdHi14areader,0, " Act like an ISO14443 Type A reader", // ## New reader command\r
2398 "hi14asim", CmdHi14asim,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag\r
2399 "hi14asnoop", CmdHi14asnoop,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command\r
2400 "hi14bdemod", CmdHi14bdemod,1, " Demodulate ISO14443 Type B from tag",\r
2401 "hi14list", CmdHi14list,0, " List ISO 14443 history",\r
2402 "hi14read", CmdHi14read,0, " Read HF tag (ISO 14443)",\r
2403 "hi14sim", CmdHi14sim,0, " Fake ISO 14443 tag",\r
2404 "hi14snoop", CmdHi14snoop,0, " Eavesdrop ISO 14443",\r
2405 "hi15demod", CmdHi15demod,1, " Demodulate ISO15693 from tag",\r
2406 "hi15read", CmdHi15read,0, " Read HF tag (ISO 15693)",\r
2407 "hi15reader", CmdHi15reader,0, " Act like an ISO15693 reader", // new command greg\r
2408 "hi15sim", CmdHi15tag,0, " Fake an ISO15693 tag", // new command greg\r
2409 "hiddemod", CmdHiddemod,1, " Demodulate HID Prox Card II (not optimal)",\r
2410 "hide", CmdHide,1, " Hide graph window",\r
2411 "hidfskdemod", CmdHIDdemodFSK,0, " Realtime HID FSK demodulator",\r
2412 "hidsimtag", CmdHIDsimTAG,0, "<ID> -- HID tag simulator",\r
2413 "higet", CmdHi14read_sim,0, "<samples> -- Get samples HF, 'analog'",\r
2414 "hisamples", CmdHisamples,0, " Get raw samples for HF tag",\r
2415 "hisampless", CmdHisampless,0, "<samples> -- Get signed raw samples, HF tag",\r
2416 "hisamplest", CmdHi14readt,0, " Get samples HF, for testing",\r
2417 "hisimlisten", CmdHisimlisten,0, " Get HF samples as fake tag",\r
2418 "hpf", CmdHpf,1, " Remove DC offset from trace",\r
2419 "indalademod", CmdIndalademod,0, "['224'] -- Demodulate samples for Indala",\r
2420 "lcd", CmdLcd,0, "<HEX command> <count> -- Send command/data to LCD",\r
2421 "lcdreset", CmdLcdReset,0, " Hardware reset LCD",\r
2422 "load", CmdLoad,1, "<filename> -- Load trace (to graph window",\r
2423 "loread", CmdLoread,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",\r
2424 "losamples", CmdLosamples,0, "[128 - 16000] -- Get raw samples for LF tag",\r
2425 "losim", CmdLosim,0, " Simulate LF tag",\r
2426 "ltrim", CmdLtrim,1, "<samples> -- Trim samples from left of trace",\r
2427 "mandemod", Cmdmanchesterdemod,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",\r
2428 "manmod", Cmdmanchestermod,1, "[clock rate] -- Manchester modulate a binary stream",\r
2429 "norm", CmdNorm,1, " Normalize max/min to +/-500",\r
2430 "plot", CmdPlot,1, " Show graph window",\r
2431 "quit", CmdQuit,1, " Quit program",\r
2432 "reset", CmdReset,0, " Reset the Proxmark3",\r
2433 "save", CmdSave,1, "<filename> -- Save trace (from graph window)",\r
2434 "scale", CmdScale,1, "<int> -- Set cursor display scale",\r
2435 "setlfdivisor", CmdSetDivisor,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",\r
2436 "sri512read", CmdSri512read,0, "<int> -- Read contents of a SRI512 tag",\r
2437 "sweeplf", CmdSweepLF,0, " Sweep through LF freq range and store results in buffer",\r
2438 "tibits", CmdTibits,0, " Get raw bits for TI-type LF tag",\r
2439 "tidemod", CmdTidemod,0, " Demodulate raw bits for TI-type LF tag",\r
2440 "tiread", CmdTiread,0, " Read a TI-type 134 kHz tag",\r
2441 "tune", CmdTune,0, " Measure antenna tuning",\r
2442 "vchdemod", CmdVchdemod,0, "['clone'] -- Demodulate samples for VeriChip",\r
2443 "zerocrossings", CmdZerocrossings,1, " Count time between zero-crossings",\r
6658905f 2444};\r
2445\r
fb25b483 2446\r
6658905f 2447//-----------------------------------------------------------------------------\r
2448// Entry point into our code: called whenever the user types a command and\r
2449// then presses Enter, which the full command line that they typed.\r
2450//-----------------------------------------------------------------------------\r
2451void CommandReceived(char *cmd)\r
2452{\r
2453 int i;\r
2454\r
2455 PrintToScrollback("> %s", cmd);\r
2456\r
2457 if(strcmp(cmd, "help")==0) {\r
d722c4ce 2458 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");\r
6658905f 2459 PrintToScrollback("\r\nAvailable commands:");\r
2460 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
d722c4ce 2461 if (offline && (CommandTable[i].offline==0)) continue;\r
6658905f 2462 char line[256];\r
2463 memset(line, ' ', sizeof(line));\r
2464 strcpy(line+2, CommandTable[i].name);\r
2465 line[strlen(line)] = ' ';\r
2466 sprintf(line+15, " -- %s", CommandTable[i].docString);\r
2467 PrintToScrollback("%s", line);\r
2468 }\r
2469 PrintToScrollback("");\r
2470 PrintToScrollback("and also: help, cls");\r
2471 return;\r
2472 }\r
2473\r
2474 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
2475 char *name = CommandTable[i].name;\r
2476 if(memcmp(cmd, name, strlen(name))==0 &&\r
2477 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))\r
2478 {\r
2479 cmd += strlen(name);\r
2480 while(*cmd == ' ') {\r
2481 cmd++;\r
2482 }\r
d722c4ce 2483 if (offline && (CommandTable[i].offline==0)) {\r
2484 PrintToScrollback("Offline mode, cannot use this command.");\r
2485 return;\r
2486 }\r
6658905f 2487 (CommandTable[i].handler)(cmd);\r
2488 return;\r
2489 }\r
2490 }\r
2491 PrintToScrollback(">> bad command '%s'", cmd);\r
2492}\r
2493\r
2494//-----------------------------------------------------------------------------\r
2495// Entry point into our code: called whenever we received a packet over USB\r
2496// that we weren't necessarily expecting, for example a debug print.\r
2497//-----------------------------------------------------------------------------\r
2498void UsbCommandReceived(UsbCommand *c)\r
2499{\r
2500 switch(c->cmd) {\r
2501 case CMD_DEBUG_PRINT_STRING: {\r
2502 char s[100];\r
2503 if(c->ext1 > 70 || c->ext1 < 0) {\r
2504 c->ext1 = 0;\r
2505 }\r
2506 memcpy(s, c->d.asBytes, c->ext1);\r
2507 s[c->ext1] = '\0';\r
2508 PrintToScrollback("#db# %s", s);\r
9760414b 2509 break;\r
6658905f 2510 }\r
2511\r
2512 case CMD_DEBUG_PRINT_INTEGERS:\r
2513 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);\r
2514 break;\r
2515\r
2516 case CMD_MEASURED_ANTENNA_TUNING: {\r
2517 int zLf, zHf;\r
2518 int vLf125, vLf134, vHf;\r
2519 vLf125 = c->ext1 & 0xffff;\r
2520 vLf134 = c->ext1 >> 16;\r
2521 vHf = c->ext2;\r
2522 zLf = c->ext3 & 0xffff;\r
2523 zHf = c->ext3 >> 16;\r
2524 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",\r
2525 vLf125/zLf, vLf125, zLf);\r
2526 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",\r
2527 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);\r
2528 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",\r
2529 vHf/zHf, vHf, zHf);\r
2530 break;\r
2531 }\r
2532 default:\r
2533 PrintToScrollback("unrecognized command %08x\n", c->cmd);\r
2534 break;\r
2535 }\r
2536}\r
Impressum, Datenschutz