]> git.zerfleddert.de Git - proxmark3-svn/blame - winsrc/command.cpp
Various traces from tags for testing and educational purposes
[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
2379static struct {\r
fb25b483 2380 char *name;\r
2381 HandlerFunction *handler;\r
2382 int offline; // 1 if the command can be used when in offline mode\r
9760414b 2383 char *docString;\r
6658905f 2384} CommandTable[] = {\r
d722c4ce 2385 "tune", CmdTune,0, "measure antenna tuning",\r
2386 "tiread", CmdTiread,0, "read a TI-type 134 kHz tag",\r
2387 "tibits", CmdTibits,0, "get raw bits for TI-type LF tag",\r
2388 "tidemod", CmdTidemod,0, "demod raw bits for TI-type LF tag",\r
2389 "vchdemod", CmdVchdemod,0, "demod samples for VeriChip",\r
2390 "plot", CmdPlot,1, "show graph window",\r
2391 "hide", CmdHide,1, "hide graph window",\r
2392 "losim", CmdLosim,0, "simulate LF tag",\r
9760414b 2393 "em410xsim", CmdEM410xsim,1, "simulate EM410x tag",\r
2394 "em410xread", CmdEM410xread,1, "extract ID from EM410x tag",\r
2395 "em410xwatch", CmdEM410xwatch,0, "watches for EM410x tags",\r
d722c4ce 2396 "loread", CmdLoread,0, "read (125/134 kHz) LF ID-only tag",\r
fb25b483 2397 "losamples", CmdLosamples,0, "get raw samples for LF tag",\r
2398 "hisamples", CmdHisamples,0, "get raw samples for HF tag",\r
2399 "hisampless", CmdHisampless,0, "get signed raw samples, HF tag",\r
2400 "hisamplest", CmdHi14readt,0, "get samples HF, for testing",\r
d722c4ce 2401 "higet", CmdHi14read_sim,0, "get samples HF, 'analog'",\r
fb25b483 2402 "bitsamples", CmdBitsamples,0, "get raw samples as bitstring",\r
2403 "hexsamples", CmdHexsamples,0, "dump big buffer as hex bytes",\r
d722c4ce 2404 "hi15read", CmdHi15read,0, "read HF tag (ISO 15693)",\r
fb25b483 2405 "hi15reader", CmdHi15reader,0, "act like an ISO15693 reader", // new command greg\r
d722c4ce 2406 "hi15sim", CmdHi15tag,0, "fake an ISO15693 tag", // new command greg\r
2407 "hi14read", CmdHi14read,0, "read HF tag (ISO 14443)",\r
fb25b483 2408 "sri512read", CmdSri512read,0, "Read contents of a SRI512 tag",\r
2409 "hi14areader", CmdHi14areader,0, "act like an ISO14443 Type A reader", // ## New reader command\r
2410 "hi15demod", CmdHi15demod,1, "demod ISO15693 from tag",\r
2411 "hi14bdemod", CmdHi14bdemod,1, "demod ISO14443 Type B from tag",\r
d722c4ce 2412 "autocorr", CmdAutoCorr,1, "autocorrelation over window",\r
2413 "norm", CmdNorm,1, "normalize max/min to +/-500",\r
2414 "dec", CmdDec,1, "decimate",\r
2415 "hpf", CmdHpf,1, "remove DC offset from trace",\r
fb25b483 2416 "zerocrossings", CmdZerocrossings,1, "count time between zero-crossings",\r
d722c4ce 2417 "ltrim", CmdLtrim,1, "trim from left of trace",\r
2418 "scale", CmdScale,1, "set cursor display scale",\r
fb25b483 2419 "flexdemod", CmdFlexdemod,1, "demod samples for FlexPass",\r
d722c4ce 2420 "save", CmdSave,1, "save trace (from graph window)",\r
2421 "load", CmdLoad,1, "load trace (to graph window",\r
fb25b483 2422 "hisimlisten", CmdHisimlisten,0, "get HF samples as fake tag",\r
d722c4ce 2423 "hi14sim", CmdHi14sim,0, "fake ISO 14443 tag",\r
2424 "hi14asim", CmdHi14asim,0, "fake ISO 14443a tag", // ## Simulate 14443a tag\r
fb25b483 2425 "hi14snoop", CmdHi14snoop,0, "eavesdrop ISO 14443",\r
2426 "hi14asnoop", CmdHi14asnoop,0, "eavesdrop ISO 14443 Type A", // ## New snoop command\r
d722c4ce 2427 "hi14list", CmdHi14list,0, "list ISO 14443 history",\r
fb25b483 2428 "hi14alist", CmdHi14alist,0, "list ISO 14443a history", // ## New list command\r
d722c4ce 2429 "hiddemod", CmdHiddemod,1, "HID Prox Card II (not optimal)",\r
fb25b483 2430 "hidfskdemod", CmdHIDdemodFSK,0, "HID FSK demodulator",\r
d722c4ce 2431 "indalademod", CmdIndalademod,0, "demod samples for Indala",\r
2432 "askdemod", Cmdaskdemod,1, "Attempt to demodulate simple ASK tags",\r
9760414b 2433 "bitstream", Cmdbitstream,1, "Convert waveform into a bitstream",\r
fb25b483 2434 "hidsimtag", CmdHIDsimTAG,0, "HID tag simulator",\r
d722c4ce 2435 "mandemod", Cmdmanchesterdemod,1, "Try a Manchester demodulation on a binary stream",\r
9760414b 2436 "manmod", Cmdmanchestermod,1, "Manchester modulate a binary stream",\r
2437 "detectclock", Cmddetectclockrate,1, "Detect clock rate",\r
d722c4ce 2438 "fpgaoff", CmdFPGAOff,0, "set FPGA off", // ## FPGA Control\r
2439 "lcdreset", CmdLcdReset,0, "Hardware reset LCD",\r
2440 "lcd", CmdLcd,0, "Send command/data to LCD",\r
fb25b483 2441 "setlfdivisor", CmdSetDivisor,0, "Drive LF antenna at 12Mhz/(divisor+1)",\r
d722c4ce 2442 "sweeplf", CmdSweepLF,0, "Sweep through LF freq range and store results in buffer",\r
2443 "reset", CmdReset,0, "Reset the Proxmark3",\r
2444 "quit", CmdQuit,1, "quit program"\r
6658905f 2445};\r
2446\r
fb25b483 2447\r
6658905f 2448//-----------------------------------------------------------------------------\r
2449// Entry point into our code: called whenever the user types a command and\r
2450// then presses Enter, which the full command line that they typed.\r
2451//-----------------------------------------------------------------------------\r
2452void CommandReceived(char *cmd)\r
2453{\r
2454 int i;\r
2455\r
2456 PrintToScrollback("> %s", cmd);\r
2457\r
2458 if(strcmp(cmd, "help")==0) {\r
d722c4ce 2459 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");\r
6658905f 2460 PrintToScrollback("\r\nAvailable commands:");\r
2461 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
d722c4ce 2462 if (offline && (CommandTable[i].offline==0)) continue;\r
6658905f 2463 char line[256];\r
2464 memset(line, ' ', sizeof(line));\r
2465 strcpy(line+2, CommandTable[i].name);\r
2466 line[strlen(line)] = ' ';\r
2467 sprintf(line+15, " -- %s", CommandTable[i].docString);\r
2468 PrintToScrollback("%s", line);\r
2469 }\r
2470 PrintToScrollback("");\r
2471 PrintToScrollback("and also: help, cls");\r
2472 return;\r
2473 }\r
2474\r
2475 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
2476 char *name = CommandTable[i].name;\r
2477 if(memcmp(cmd, name, strlen(name))==0 &&\r
2478 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))\r
2479 {\r
2480 cmd += strlen(name);\r
2481 while(*cmd == ' ') {\r
2482 cmd++;\r
2483 }\r
d722c4ce 2484 if (offline && (CommandTable[i].offline==0)) {\r
2485 PrintToScrollback("Offline mode, cannot use this command.");\r
2486 return;\r
2487 }\r
6658905f 2488 (CommandTable[i].handler)(cmd);\r
2489 return;\r
2490 }\r
2491 }\r
2492 PrintToScrollback(">> bad command '%s'", cmd);\r
2493}\r
2494\r
2495//-----------------------------------------------------------------------------\r
2496// Entry point into our code: called whenever we received a packet over USB\r
2497// that we weren't necessarily expecting, for example a debug print.\r
2498//-----------------------------------------------------------------------------\r
2499void UsbCommandReceived(UsbCommand *c)\r
2500{\r
2501 switch(c->cmd) {\r
2502 case CMD_DEBUG_PRINT_STRING: {\r
2503 char s[100];\r
2504 if(c->ext1 > 70 || c->ext1 < 0) {\r
2505 c->ext1 = 0;\r
2506 }\r
2507 memcpy(s, c->d.asBytes, c->ext1);\r
2508 s[c->ext1] = '\0';\r
2509 PrintToScrollback("#db# %s", s);\r
9760414b 2510 break;\r
6658905f 2511 }\r
2512\r
2513 case CMD_DEBUG_PRINT_INTEGERS:\r
2514 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);\r
2515 break;\r
2516\r
2517 case CMD_MEASURED_ANTENNA_TUNING: {\r
2518 int zLf, zHf;\r
2519 int vLf125, vLf134, vHf;\r
2520 vLf125 = c->ext1 & 0xffff;\r
2521 vLf134 = c->ext1 >> 16;\r
2522 vHf = c->ext2;\r
2523 zLf = c->ext3 & 0xffff;\r
2524 zHf = c->ext3 >> 16;\r
2525 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",\r
2526 vLf125/zLf, vLf125, zLf);\r
2527 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",\r
2528 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);\r
2529 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",\r
2530 vHf/zHf, vHf, zHf);\r
2531 break;\r
2532 }\r
2533 default:\r
2534 PrintToScrollback("unrecognized command %08x\n", c->cmd);\r
2535 break;\r
2536 }\r
2537}\r
Impressum, Datenschutz