]> git.zerfleddert.de Git - proxmark3-svn/blame - winsrc/command.cpp
Added traces for EM4102, HID Prox II and Indala LF cards
[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
214 \r
215 if (redraw)\r
216 RepaintGraphWindow();\r
217 \r
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
228 \r
229 for (i = (int)(clock/2); i < clock; i++) \r
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
243 \r
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
267 \r
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
275 } \r
276 \r
277 /* get clock */\r
278 clock = GetClock(str, high);\r
279 \r
280 /* parity for our 4 columns */\r
281 parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
282 header = rows = 0;\r
283 \r
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
291 \r
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
299 \r
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
306 \r
307 if (hithigh && hitlow)\r
308 break;\r
309 }\r
310 \r
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
314 \r
315 BitStream[bit2idx++] = bit;\r
316 }\r
317 \r
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
330 \r
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
336 \r
337 /* Move 4 bits ahead */\r
338 i += 4;\r
339 }\r
340 \r
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
345 \r
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
352 \r
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
363 \r
364 /* Stop any loops */\r
365 go = 0;\r
366 break;\r
367 }\r
368 \r
369 /* Crap! Incorrect parity or no stop bit, start all over */\r
370 else\r
371 {\r
372 rows = header = 0;\r
373 \r
374 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */\r
375 i -= 59;\r
376 }\r
377 }\r
378 \r
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
385 \r
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
405 \r
406 /* clock is 64 in EM410x tags */\r
407 int clock = 64;\r
408 \r
409 /* clear our graph */\r
410 CmdClearGraph(0);\r
411 \r
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
418 \r
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
427 \r
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
433 \r
434 /* append parity bit */\r
435 CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);\r
436 \r
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
443 \r
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
449 \r
450 /* stop bit */\r
451 CmdAppendGraph(0, clock, 0);\r
452 }\r
453 \r
454 /* modulate that biatch */\r
455 Cmdmanchestermod(s);\r
456 \r
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
466 \r
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
482 \r
483 /* convert to bitstream if necessary */\r
484 ChkBitstream(str);\r
485 \r
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
1825 * Generic command to demodulate ASK. bit length in argument.\r
1826 * Giving the bit length helps discriminate ripple effects\r
1827 * upon zero crossing for noisy traces.\r
1828 *\r
1829 * Second is convention: positive or negative (High mod means zero\r
1830 * or high mod means one)\r
1831 *\r
1832 * Updates the Graph trace with 0/1 values\r
1833 *\r
1834 * Arguments:\r
1835 * sl : bit length in terms of number of samples per bit\r
1836 * (use yellow/purple markers to compute).\r
1837 * c : 0 or 1\r
1838 */\r
1839\r
1840static void Cmdaskdemod(char *str) {\r
1841 int i;\r
1842 int sign = 1;\r
1843 int n = 0;\r
6658905f 1844 int c = 0;\r
9760414b 1845 int t1 = 0;\r
1846\r
1847 // TODO: complain if we do not give 2 arguments here !\r
1848 sscanf(str, "%i %i", &n, &c);\r
1849 if (c == 0) {\r
1850 c = 1 ;\r
1851 } else {\r
1852 c = -1;\r
1853 }\r
1854\r
1855 if (GraphBuffer[0]*c > 0) {\r
1856 GraphBuffer[0] = 1;\r
1857 } else {\r
1858 GraphBuffer[0] = 0;\r
1859 }\r
1860 for(i=1;i<GraphTraceLen;i++) {\r
1861 /* Analyse signal within the symbol length */\r
1862 /* Decide if we crossed a zero */\r
1863 if (GraphBuffer[i]*sign < 0) {\r
1864 /* Crossed a zero, check if this is a ripple or not */\r
1865 if ( (i-t1) > n/4 ) {\r
1866 sign = -sign;\r
1867 t1=i;\r
1868 if (GraphBuffer[i]*c > 0){\r
1869 GraphBuffer[i]=1;\r
1870 } else {\r
1871 GraphBuffer[i]=0;\r
1872 }\r
1873 } else {\r
1874 /* This is a ripple, set the current sample value\r
1875 to the same as previous */\r
1876 GraphBuffer[i] = GraphBuffer[i-1];\r
1877 }\r
1878 } else {\r
1879 GraphBuffer[i] = GraphBuffer[i-1];\r
1880 }\r
1881 }\r
1882 RepaintGraphWindow();\r
1883}\r
1884\r
1885/* Print our clock rate */\r
1886static void Cmddetectclockrate(char *str)\r
1887{\r
1888 int clock = detectclock(0);\r
1889 PrintToScrollback("Auto-detected clock rate: %d", clock);\r
1890}\r
1891\r
1892/*\r
1893 * Detect clock rate\r
1894 */\r
1895int detectclock(int peak)\r
1896{\r
1897 int i;\r
1898 int clock = 0xFFFF;\r
1899 int lastpeak = 0;\r
1900\r
1901 /* Detect peak if we don't have one */\r
1902 if (!peak)\r
1903 for (i = 0; i < GraphTraceLen; i++)\r
1904 if (GraphBuffer[i] > peak)\r
1905 peak = GraphBuffer[i];\r
1906\r
1907 for (i = 1; i < GraphTraceLen; i++)\r
1908 {\r
1909 /* If this is the beginning of a peak */\r
1910 if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)\r
1911 {\r
1912 /* Find lowest difference between peaks */\r
1913 if (lastpeak && i - lastpeak < clock)\r
1914 {\r
1915 clock = i - lastpeak;\r
1916 }\r
1917 lastpeak = i;\r
1918 }\r
1919 }\r
1920 \r
1921 return clock;\r
1922}\r
1923\r
1924/* Get or auto-detect clock rate */\r
1925int GetClock(char *str, int peak)\r
1926{\r
1927 int clock;\r
1928 \r
1929 sscanf(str, "%i", &clock);\r
1930 if (!strcmp(str, ""))\r
1931 clock = 0;\r
1932\r
1933 /* Auto-detect clock */\r
1934 if (!clock)\r
1935 {\r
1936 clock = detectclock(peak);\r
1937 \r
1938 /* Only print this message if we're not looping something */\r
1939 if (!go)\r
1940 PrintToScrollback("Auto-detected clock rate: %d", clock);\r
1941 }\r
1942 \r
1943 return clock;\r
1944}\r
1945\r
1946/*\r
1947 * Convert to a bitstream\r
1948 */\r
1949static void Cmdbitstream(char *str) {\r
c9f99c01 1950 int i, j;\r
1951 int bit;\r
9760414b 1952 int gtl;\r
1953 int clock;\r
c9f99c01 1954 int low = 0;\r
1955 int high = 0;\r
1956 int hithigh, hitlow, first;\r
9760414b 1957\r
1958 /* Detect high and lows and clock */\r
1959 for (i = 0; i < GraphTraceLen; i++)\r
c9f99c01 1960 {\r
9760414b 1961 if (GraphBuffer[i] > high)\r
1962 high = GraphBuffer[i];\r
1963 else if (GraphBuffer[i] < low)\r
1964 low = GraphBuffer[i];\r
c9f99c01 1965 }\r
9760414b 1966\r
1967 /* Get our clock */\r
1968 clock = GetClock(str, high);\r
1969 \r
1970 gtl = CmdClearGraph(0);\r
1971 \r
1972 bit = 0;\r
1973 for (i = 0; i < (int)(gtl / clock); i++)\r
1974 {\r
1975 hithigh = 0;\r
1976 hitlow = 0;\r
1977 first = 1;\r
1978 \r
1979 /* Find out if we hit both high and low peaks */\r
1980 for (j = 0; j < clock; j++)\r
1981 {\r
1982 if (GraphBuffer[(i * clock) + j] == high)\r
1983 hithigh = 1;\r
1984 else if (GraphBuffer[(i * clock) + j] == low)\r
1985 hitlow = 1;\r
1986 \r
1987 /* it doesn't count if it's the first part of our read\r
1988 because it's really just trailing from the last sequence */\r
1989 if (first && (hithigh || hitlow))\r
1990 hithigh = hitlow = 0;\r
1991 else\r
1992 first = 0;\r
1993 \r
1994 if (hithigh && hitlow)\r
1995 break;\r
1996 }\r
1997 \r
1998 /* If we didn't hit both high and low peaks, we had a bit transition */\r
1999 if (!hithigh || !hitlow)\r
2000 bit ^= 1;\r
2001\r
2002 CmdAppendGraph(0, clock, bit);\r
2003// for (j = 0; j < (int)(clock/2); j++)\r
2004// GraphBuffer[(i * clock) + j] = bit ^ 1;\r
2005// for (j = (int)(clock/2); j < clock; j++)\r
2006// GraphBuffer[(i * clock) + j] = bit;\r
2007 }\r
2008\r
2009 RepaintGraphWindow();\r
2010}\r
2011\r
2012/* Modulate our data into manchester */\r
2013static void Cmdmanchestermod(char *str)\r
2014{\r
2015 int i, j;\r
2016 int clock;\r
2017 int bit, lastbit, wave;\r
2018 \r
2019 /* Get our clock */\r
2020 clock = GetClock(str, 0);\r
2021\r
2022 wave = 0;\r
2023 lastbit = 1;\r
2024 for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
2025 {\r
2026 bit = GraphBuffer[i * clock] ^ 1;\r
2027 \r
2028 for (j = 0; j < (int)(clock/2); j++)\r
2029 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;\r
2030 for (j = (int)(clock/2); j < clock; j++)\r
2031 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;\r
2032 \r
2033 /* Keep track of how we start our wave and if we changed or not this time */\r
2034 wave ^= bit ^ lastbit;\r
2035 lastbit = bit;\r
2036 }\r
2037 \r
2038 RepaintGraphWindow();\r
2039}\r
2040\r
2041/*\r
2042 * Manchester demodulate a bitstream. The bitstream needs to be already in\r
2043 * the GraphBuffer as 0 and 1 values\r
2044 *\r
2045 * Give the clock rate as argument in order to help the sync - the algorithm\r
2046 * resyncs at each pulse anyway.\r
2047 *\r
2048 * Not optimized by any means, this is the 1st time I'm writing this type of\r
2049 * routine, feel free to improve...\r
2050 *\r
2051 * 1st argument: clock rate (as number of samples per clock rate)\r
2052 * Typical values can be 64, 32, 128...\r
2053 */\r
2054static void Cmdmanchesterdemod(char *str) {\r
2055 int i, j;\r
2056 int bit;\r
2057 int clock;\r
2058 int lastval;\r
2059 int low = 0;\r
2060 int high = 0;\r
2061 int hithigh, hitlow, first;\r
2062 int lc = 0;\r
2063 int bitidx = 0;\r
2064 int bit2idx = 0;\r
2065 int warnings = 0;\r
2066\r
2067 /* Holds the decoded bitstream: each clock period contains 2 bits */\r
2068 /* later simplified to 1 bit after manchester decoding. */\r
2069 /* Add 10 bits to allow for noisy / uncertain traces without aborting */\r
2070 /* int BitStream[GraphTraceLen*2/clock+10]; */\r
2071\r
2072 /* But it does not work if compiling on WIndows: therefore we just allocate a */\r
2073 /* large array */\r
2074 int BitStream[MAX_GRAPH_TRACE_LEN];\r
2075\r
c9f99c01 2076 /* Detect high and lows */\r
2077 for (i = 0; i < GraphTraceLen; i++)\r
2078 {\r
2079 if (GraphBuffer[i] > high)\r
2080 high = GraphBuffer[i];\r
2081 else if (GraphBuffer[i] < low)\r
2082 low = GraphBuffer[i];\r
2083 }\r
2084\r
9760414b 2085 /* Get our clock */\r
2086 clock = GetClock(str, high);\r
2087 \r
2088 int tolerance = clock/4;\r
2089 \r
2090 /* Detect first transition */\r
2091 /* Lo-Hi (arbitrary) */\r
c9f99c01 2092 for (i = 0; i < GraphTraceLen; i++)\r
2093 {\r
2094 if (GraphBuffer[i] == low)\r
2095 {\r
9760414b 2096 lastval = i;\r
2097 break;\r
2098 }\r
2099 }\r
c9f99c01 2100\r
2101 /* If we're not working with 1/0s, demod based off clock */\r
2102 if (high != 1)\r
2103 {\r
2104 bit = 0;\r
9760414b 2105 for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
c9f99c01 2106 {\r
2107 hithigh = 0;\r
2108 hitlow = 0;\r
2109 first = 1;\r
2110\r
2111 /* Find out if we hit both high and low peaks */\r
2112 for (j = 0; j < clock; j++)\r
2113 {\r
2114 if (GraphBuffer[(i * clock) + j] == high)\r
2115 hithigh = 1;\r
2116 else if (GraphBuffer[(i * clock) + j] == low)\r
2117 hitlow = 1;\r
2118\r
2119 /* it doesn't count if it's the first part of our read\r
2120 because it's really just trailing from the last sequence */\r
2121 if (first && (hithigh || hitlow))\r
2122 hithigh = hitlow = 0;\r
2123 else\r
2124 first = 0;\r
2125\r
2126 if (hithigh && hitlow)\r
2127 break;\r
2128 }\r
2129\r
2130 /* If we didn't hit both high and low peaks, we had a bit transition */\r
2131 if (!hithigh || !hitlow)\r
2132 bit ^= 1;\r
2133\r
2134 BitStream[bit2idx++] = bit;\r
2135 }\r
2136 }\r
2137\r
2138 /* standard 1/0 bitstream */\r
2139 else\r
2140 {\r
9760414b 2141\r
2142 /* Then detect duration between 2 successive transitions */\r
c9f99c01 2143 for (bitidx = 1; i < GraphTraceLen; i++)\r
2144 {\r
2145 if (GraphBuffer[i-1] != GraphBuffer[i])\r
2146 {\r
9760414b 2147 lc = i-lastval;\r
2148 lastval = i;\r
2149\r
2150 // Error check: if bitidx becomes too large, we do not\r
2151 // have a Manchester encoded bitstream or the clock is really\r
2152 // wrong!\r
2153 if (bitidx > (GraphTraceLen*2/clock+8) ) {\r
2154 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");\r
2155 return;\r
2156 }\r
2157 // Then switch depending on lc length:\r
2158 // Tolerance is 1/4 of clock rate (arbitrary)\r
2159 if (abs(lc-clock/2) < tolerance) {\r
2160 // Short pulse : either "1" or "0"\r
2161 BitStream[bitidx++]=GraphBuffer[i-1];\r
2162 } else if (abs(lc-clock) < tolerance) {\r
2163 // Long pulse: either "11" or "00"\r
2164 BitStream[bitidx++]=GraphBuffer[i-1];\r
2165 BitStream[bitidx++]=GraphBuffer[i-1];\r
2166 } else {\r
2167 // Error\r
c9f99c01 2168 warnings++;\r
9760414b 2169 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");\r
2170 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");\r
c9f99c01 2171\r
2172 if (warnings > 100)\r
2173 {\r
2174 PrintToScrollback("Error: too many detection errors, aborting.");\r
2175 return;\r
2176 }\r
9760414b 2177 }\r
2178 }\r
2179 }\r
2180\r
2181 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream\r
2182 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful\r
2183 // to stop output at the final bitidx2 value, not bitidx\r
2184 for (i = 0; i < bitidx; i += 2) {\r
2185 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {\r
2186 BitStream[bit2idx++] = 1;\r
2187 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {\r
2188 BitStream[bit2idx++] = 0;\r
2189 } else {\r
2190 // We cannot end up in this state, this means we are unsynchronized,\r
2191 // move up 1 bit:\r
2192 i++;\r
c9f99c01 2193 warnings++;\r
9760414b 2194 PrintToScrollback("Unsynchronized, resync...");\r
2195 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");\r
c9f99c01 2196\r
2197 if (warnings > 100)\r
2198 {\r
2199 PrintToScrollback("Error: too many decode errors, aborting.");\r
2200 return;\r
2201 }\r
9760414b 2202 }\r
2203 }\r
c9f99c01 2204 }\r
2205\r
2206 PrintToScrollback("Manchester decoded bitstream");\r
9760414b 2207 // Now output the bitstream to the scrollback by line of 16 bits\r
2208 for (i = 0; i < (bit2idx-16); i+=16) {\r
2209 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",\r
2210 BitStream[i],\r
2211 BitStream[i+1],\r
2212 BitStream[i+2],\r
2213 BitStream[i+3],\r
2214 BitStream[i+4],\r
2215 BitStream[i+5],\r
2216 BitStream[i+6],\r
2217 BitStream[i+7],\r
2218 BitStream[i+8],\r
2219 BitStream[i+9],\r
2220 BitStream[i+10],\r
2221 BitStream[i+11],\r
2222 BitStream[i+12],\r
2223 BitStream[i+13],\r
2224 BitStream[i+14],\r
2225 BitStream[i+15]);\r
2226 }\r
2227}\r
2228\r
2229\r
2230\r
2231/*\r
2232 * Usage ???\r
6658905f 2233 */\r
2234static void CmdHiddemod(char *str)\r
2235{\r
2236 if(GraphTraceLen < 4800) {\r
2237 PrintToScrollback("too short; need at least 4800 samples");\r
2238 return;\r
2239 }\r
2240\r
2241 GraphTraceLen = 4800;\r
2242 int i;\r
2243 for(i = 0; i < GraphTraceLen; i++) {\r
2244 if(GraphBuffer[i] < 0) {\r
2245 GraphBuffer[i] = 0;\r
2246 } else {\r
2247 GraphBuffer[i] = 1;\r
2248 }\r
2249 }\r
2250 RepaintGraphWindow();\r
2251}\r
2252\r
2253static void CmdPlot(char *str)\r
2254{\r
2255 ShowGraphWindow();\r
2256}\r
2257\r
2258static void CmdHide(char *str)\r
2259{\r
2260 HideGraphWindow();\r
2261}\r
2262\r
2263static void CmdScale(char *str)\r
2264{\r
2265 CursorScaleFactor = atoi(str);\r
2266 if(CursorScaleFactor == 0) {\r
2267 PrintToScrollback("bad, can't have zero scale");\r
2268 CursorScaleFactor = 1;\r
2269 }\r
2270 RepaintGraphWindow();\r
2271}\r
2272\r
2273static void CmdSave(char *str)\r
2274{\r
2275 FILE *f = fopen(str, "w");\r
2276 if(!f) {\r
2277 PrintToScrollback("couldn't open '%s'", str);\r
2278 return;\r
2279 }\r
2280 int i;\r
2281 for(i = 0; i < GraphTraceLen; i++) {\r
2282 fprintf(f, "%d\n", GraphBuffer[i]);\r
2283 }\r
2284 fclose(f);\r
2285 PrintToScrollback("saved to '%s'", str);\r
2286}\r
2287\r
2288static void CmdLoad(char *str)\r
2289{\r
2290 FILE *f = fopen(str, "r");\r
2291 if(!f) {\r
2292 PrintToScrollback("couldn't open '%s'", str);\r
2293 return;\r
2294 }\r
2295\r
2296 GraphTraceLen = 0;\r
2297 char line[80];\r
2298 while(fgets(line, sizeof(line), f)) {\r
2299 GraphBuffer[GraphTraceLen] = atoi(line);\r
2300 GraphTraceLen++;\r
2301 }\r
2302 fclose(f);\r
2303 PrintToScrollback("loaded %d samples", GraphTraceLen);\r
2304 RepaintGraphWindow();\r
2305}\r
2306\r
2307static void CmdHIDsimTAG(char *str)\r
2308{\r
2309 unsigned int hi=0, lo=0;\r
2310 int n=0, i=0;\r
2311 UsbCommand c;\r
2312\r
2313 while (sscanf(&str[i++], "%1x", &n ) == 1) {\r
2314 hi=(hi<<4)|(lo>>28);\r
2315 lo=(lo<<4)|(n&0xf);\r
2316 }\r
2317\r
2318 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);\r
2319\r
2320 c.cmd = CMD_HID_SIM_TAG;\r
2321 c.ext1 = hi;\r
2322 c.ext2 = lo;\r
2323 SendCommand(&c, FALSE);\r
2324}\r
2325\r
2326static void CmdLcdReset(char *str)\r
2327{\r
2328 UsbCommand c;\r
2329 c.cmd = CMD_LCD_RESET;\r
2330 c.ext1 = atoi(str);\r
2331 SendCommand(&c, FALSE);\r
2332}\r
2333\r
2334static void CmdLcd(char *str)\r
2335{\r
2336 int i, j;\r
2337 UsbCommand c;\r
2338 c.cmd = CMD_LCD;\r
2339 sscanf(str, "%x %d", &i, &j);\r
2340 while (j--) {\r
2341 c.ext1 = i&0x1ff;\r
2342 SendCommand(&c, FALSE);\r
2343 }\r
2344}\r
2345\r
d722c4ce 2346\r
2347\r
6658905f 2348static void CmdTest(char *str)\r
2349{\r
2350}\r
9760414b 2351\r
2352/*\r
2353 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below\r
2354 * 600kHz.\r
2355 */\r
30f2a7d3 2356static void CmdSetDivisor(char *str)\r
2357{\r
2358 UsbCommand c;\r
2359 c.cmd = CMD_SET_LF_DIVISOR;\r
2360 c.ext1 = atoi(str);\r
2361 if (( c.ext1<0) || (c.ext1>255)) {\r
2362 PrintToScrollback("divisor must be between 19 and 255");\r
2363 } else {\r
2364 SendCommand(&c, FALSE);\r
2365 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));\r
2366 }\r
2367}\r
2368\r
2369static void CmdSweepLF(char *str)\r
2370{\r
2371 UsbCommand c;\r
2372 c.cmd = CMD_SWEEP_LF;\r
2373 SendCommand(&c, FALSE);\r
2374}\r
9760414b 2375\r
2376\r
6658905f 2377typedef void HandlerFunction(char *cmdline);\r
2378\r
3f030abe 2379/* in alphabetic order */\r
6658905f 2380static struct {\r
fb25b483 2381 char *name;\r
2382 HandlerFunction *handler;\r
2383 int offline; // 1 if the command can be used when in offline mode\r
9760414b 2384 char *docString;\r
6658905f 2385} CommandTable[] = {\r
3f030abe 2386 "askdemod", Cmdaskdemod,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",\r
2387 "autocorr", CmdAutoCorr,1, "<window length> -- Autocorrelation over window",\r
2388 "bitsamples", CmdBitsamples,0, " Get raw samples as bitstring",\r
2389 "bitstream", Cmdbitstream,1, "[clock rate] -- Convert waveform into a bitstream",\r
2390 "dec", CmdDec,1, " Decimate samples",\r
2391 "detectclock", Cmddetectclockrate,1, " Detect clock rate",\r
2392 "em410xsim", CmdEM410xsim,1, "<UID> -- Simulate EM410x tag",\r
2393 "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag",\r
2394 "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags",\r
2395 "exit", CmdQuit,1, " Exit program",\r
2396 "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass",\r
2397 "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control\r
2398 "hexsamples", CmdHexsamples,0, "<blocks> -- Dump big buffer as hex bytes",\r
2399 "hi14alist", CmdHi14alist,0, " List ISO 14443a history", // ## New list command\r
2400 "hi14areader", CmdHi14areader,0, " Act like an ISO14443 Type A reader", // ## New reader command\r
2401 "hi14asim", CmdHi14asim,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag\r
2402 "hi14asnoop", CmdHi14asnoop,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command\r
2403 "hi14bdemod", CmdHi14bdemod,1, " Demodulate ISO14443 Type B from tag",\r
2404 "hi14list", CmdHi14list,0, " List ISO 14443 history",\r
2405 "hi14read", CmdHi14read,0, " Read HF tag (ISO 14443)",\r
2406 "hi14sim", CmdHi14sim,0, " Fake ISO 14443 tag",\r
2407 "hi14snoop", CmdHi14snoop,0, " Eavesdrop ISO 14443",\r
2408 "hi15demod", CmdHi15demod,1, " Demodulate ISO15693 from tag",\r
2409 "hi15read", CmdHi15read,0, " Read HF tag (ISO 15693)",\r
2410 "hi15reader", CmdHi15reader,0, " Act like an ISO15693 reader", // new command greg\r
2411 "hi15sim", CmdHi15tag,0, " Fake an ISO15693 tag", // new command greg\r
2412 "hiddemod", CmdHiddemod,1, " Demodulate HID Prox Card II (not optimal)",\r
2413 "hide", CmdHide,1, " Hide graph window",\r
2414 "hidfskdemod", CmdHIDdemodFSK,0, " Realtime HID FSK demodulator",\r
2415 "hidsimtag", CmdHIDsimTAG,0, "<ID> -- HID tag simulator",\r
2416 "higet", CmdHi14read_sim,0, "<samples> -- Get samples HF, 'analog'",\r
2417 "hisamples", CmdHisamples,0, " Get raw samples for HF tag",\r
2418 "hisampless", CmdHisampless,0, "<samples> -- Get signed raw samples, HF tag",\r
2419 "hisamplest", CmdHi14readt,0, " Get samples HF, for testing",\r
2420 "hisimlisten", CmdHisimlisten,0, " Get HF samples as fake tag",\r
2421 "hpf", CmdHpf,1, " Remove DC offset from trace",\r
2422 "indalademod", CmdIndalademod,0, "['224'] -- Demodulate samples for Indala",\r
2423 "lcd", CmdLcd,0, "<HEX command> <count> -- Send command/data to LCD",\r
2424 "lcdreset", CmdLcdReset,0, " Hardware reset LCD",\r
2425 "load", CmdLoad,1, "<filename> -- Load trace (to graph window",\r
2426 "loread", CmdLoread,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",\r
2427 "losamples", CmdLosamples,0, "[128 - 16000] -- Get raw samples for LF tag",\r
2428 "losim", CmdLosim,0, " Simulate LF tag",\r
2429 "ltrim", CmdLtrim,1, "<samples> -- Trim samples from left of trace",\r
2430 "mandemod", Cmdmanchesterdemod,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",\r
2431 "manmod", Cmdmanchestermod,1, "[clock rate] -- Manchester modulate a binary stream",\r
2432 "norm", CmdNorm,1, " Normalize max/min to +/-500",\r
2433 "plot", CmdPlot,1, " Show graph window",\r
2434 "quit", CmdQuit,1, " Quit program",\r
2435 "reset", CmdReset,0, " Reset the Proxmark3",\r
2436 "save", CmdSave,1, "<filename> -- Save trace (from graph window)",\r
2437 "scale", CmdScale,1, "<int> -- Set cursor display scale",\r
2438 "setlfdivisor", CmdSetDivisor,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",\r
2439 "sri512read", CmdSri512read,0, "<int> -- Read contents of a SRI512 tag",\r
2440 "sweeplf", CmdSweepLF,0, " Sweep through LF freq range and store results in buffer",\r
2441 "tibits", CmdTibits,0, " Get raw bits for TI-type LF tag",\r
2442 "tidemod", CmdTidemod,0, " Demodulate raw bits for TI-type LF tag",\r
2443 "tiread", CmdTiread,0, " Read a TI-type 134 kHz tag",\r
2444 "tune", CmdTune,0, " Measure antenna tuning",\r
2445 "vchdemod", CmdVchdemod,0, "['clone'] -- Demodulate samples for VeriChip",\r
2446 "zerocrossings", CmdZerocrossings,1, " Count time between zero-crossings",\r
6658905f 2447};\r
2448\r
fb25b483 2449\r
6658905f 2450//-----------------------------------------------------------------------------\r
2451// Entry point into our code: called whenever the user types a command and\r
2452// then presses Enter, which the full command line that they typed.\r
2453//-----------------------------------------------------------------------------\r
2454void CommandReceived(char *cmd)\r
2455{\r
2456 int i;\r
2457\r
2458 PrintToScrollback("> %s", cmd);\r
2459\r
2460 if(strcmp(cmd, "help")==0) {\r
d722c4ce 2461 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");\r
6658905f 2462 PrintToScrollback("\r\nAvailable commands:");\r
2463 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
d722c4ce 2464 if (offline && (CommandTable[i].offline==0)) continue;\r
6658905f 2465 char line[256];\r
2466 memset(line, ' ', sizeof(line));\r
2467 strcpy(line+2, CommandTable[i].name);\r
2468 line[strlen(line)] = ' ';\r
2469 sprintf(line+15, " -- %s", CommandTable[i].docString);\r
2470 PrintToScrollback("%s", line);\r
2471 }\r
2472 PrintToScrollback("");\r
2473 PrintToScrollback("and also: help, cls");\r
2474 return;\r
2475 }\r
2476\r
2477 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
2478 char *name = CommandTable[i].name;\r
2479 if(memcmp(cmd, name, strlen(name))==0 &&\r
2480 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))\r
2481 {\r
2482 cmd += strlen(name);\r
2483 while(*cmd == ' ') {\r
2484 cmd++;\r
2485 }\r
d722c4ce 2486 if (offline && (CommandTable[i].offline==0)) {\r
2487 PrintToScrollback("Offline mode, cannot use this command.");\r
2488 return;\r
2489 }\r
6658905f 2490 (CommandTable[i].handler)(cmd);\r
2491 return;\r
2492 }\r
2493 }\r
2494 PrintToScrollback(">> bad command '%s'", cmd);\r
2495}\r
2496\r
2497//-----------------------------------------------------------------------------\r
2498// Entry point into our code: called whenever we received a packet over USB\r
2499// that we weren't necessarily expecting, for example a debug print.\r
2500//-----------------------------------------------------------------------------\r
2501void UsbCommandReceived(UsbCommand *c)\r
2502{\r
2503 switch(c->cmd) {\r
2504 case CMD_DEBUG_PRINT_STRING: {\r
2505 char s[100];\r
2506 if(c->ext1 > 70 || c->ext1 < 0) {\r
2507 c->ext1 = 0;\r
2508 }\r
2509 memcpy(s, c->d.asBytes, c->ext1);\r
2510 s[c->ext1] = '\0';\r
2511 PrintToScrollback("#db# %s", s);\r
9760414b 2512 break;\r
6658905f 2513 }\r
2514\r
2515 case CMD_DEBUG_PRINT_INTEGERS:\r
2516 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);\r
2517 break;\r
2518\r
2519 case CMD_MEASURED_ANTENNA_TUNING: {\r
2520 int zLf, zHf;\r
2521 int vLf125, vLf134, vHf;\r
2522 vLf125 = c->ext1 & 0xffff;\r
2523 vLf134 = c->ext1 >> 16;\r
2524 vHf = c->ext2;\r
2525 zLf = c->ext3 & 0xffff;\r
2526 zHf = c->ext3 >> 16;\r
2527 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",\r
2528 vLf125/zLf, vLf125, zLf);\r
2529 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",\r
2530 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);\r
2531 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",\r
2532 vHf/zHf, vHf, zHf);\r
2533 break;\r
2534 }\r
2535 default:\r
2536 PrintToScrollback("unrecognized command %08x\n", c->cmd);\r
2537 break;\r
2538 }\r
2539}\r
Impressum, Datenschutz