]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmddata.c
b34ed8e017e3b294a01b5b71267b5085e390420c
[proxmark3-svn] / client / cmddata.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Data and Graph commands
9 //-----------------------------------------------------------------------------
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <limits.h>
15 #include "proxmark3.h"
16 #include "data.h"
17 #include "ui.h"
18 #include "graph.h"
19 #include "cmdparser.h"
20 #include "util.h"
21 #include "cmdmain.h"
22 #include "cmddata.h"
23
24 static int CmdHelp(const char *Cmd);
25
26 int CmdAmp(const char *Cmd)
27 {
28 int i, rising, falling;
29 int max = INT_MIN, min = INT_MAX;
30
31 for (i = 10; i < GraphTraceLen; ++i) {
32 if (GraphBuffer[i] > max)
33 max = GraphBuffer[i];
34 if (GraphBuffer[i] < min)
35 min = GraphBuffer[i];
36 }
37
38 if (max != min) {
39 rising = falling= 0;
40 for (i = 0; i < GraphTraceLen; ++i) {
41 if (GraphBuffer[i + 1] < GraphBuffer[i]) {
42 if (rising) {
43 GraphBuffer[i] = max;
44 rising = 0;
45 }
46 falling = 1;
47 }
48 if (GraphBuffer[i + 1] > GraphBuffer[i]) {
49 if (falling) {
50 GraphBuffer[i] = min;
51 falling = 0;
52 }
53 rising= 1;
54 }
55 }
56 }
57 RepaintGraphWindow();
58 return 0;
59 }
60
61 /*
62 * Generic command to demodulate ASK.
63 *
64 * Argument is convention: positive or negative (High mod means zero
65 * or high mod means one)
66 *
67 * Updates the Graph trace with 0/1 values
68 *
69 * Arguments:
70 * c : 0 or 1
71 */
72 int Cmdaskdemod(const char *Cmd)
73 {
74 int i;
75 int c, high = 0, low = 0;
76
77 // TODO: complain if we do not give 2 arguments here !
78 // (AL - this doesn't make sense! we're only using one argument!!!)
79 sscanf(Cmd, "%i", &c);
80
81 /* Detect high and lows and clock */
82 // (AL - clock???)
83 for (i = 0; i < GraphTraceLen; ++i)
84 {
85 if (GraphBuffer[i] > high)
86 high = GraphBuffer[i];
87 else if (GraphBuffer[i] < low)
88 low = GraphBuffer[i];
89 }
90 if (c != 0 && c != 1) {
91 PrintAndLog("Invalid argument: %s", Cmd);
92 return 0;
93 }
94
95 if (GraphBuffer[0] > 0) {
96 GraphBuffer[0] = 1-c;
97 } else {
98 GraphBuffer[0] = c;
99 }
100 for (i = 1; i < GraphTraceLen; ++i) {
101 /* Transitions are detected at each peak
102 * Transitions are either:
103 * - we're low: transition if we hit a high
104 * - we're high: transition if we hit a low
105 * (we need to do it this way because some tags keep high or
106 * low for long periods, others just reach the peak and go
107 * down)
108 */
109 if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) {
110 GraphBuffer[i] = 1 - c;
111 } else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){
112 GraphBuffer[i] = c;
113 } else {
114 /* No transition */
115 GraphBuffer[i] = GraphBuffer[i - 1];
116 }
117 }
118 RepaintGraphWindow();
119 return 0;
120 }
121
122 int CmdAutoCorr(const char *Cmd)
123 {
124 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
125
126 int window = atoi(Cmd);
127
128 if (window == 0) {
129 PrintAndLog("needs a window");
130 return 0;
131 }
132 if (window >= GraphTraceLen) {
133 PrintAndLog("window must be smaller than trace (%d samples)",
134 GraphTraceLen);
135 return 0;
136 }
137
138 PrintAndLog("performing %d correlations", GraphTraceLen - window);
139
140 for (int i = 0; i < GraphTraceLen - window; ++i) {
141 int sum = 0;
142 for (int j = 0; j < window; ++j) {
143 sum += (GraphBuffer[j]*GraphBuffer[i + j]) / 256;
144 }
145 CorrelBuffer[i] = sum;
146 }
147 GraphTraceLen = GraphTraceLen - window;
148 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen * sizeof (int));
149
150 RepaintGraphWindow();
151 return 0;
152 }
153
154 int CmdBitsamples(const char *Cmd)
155 {
156 int cnt = 0;
157 uint8_t got[12288];
158
159 GetFromBigBuf(got,sizeof(got),0);
160 WaitForResponse(CMD_ACK,NULL);
161
162 for (int j = 0; j < sizeof(got); j++) {
163 for (int k = 0; k < 8; k++) {
164 if(got[j] & (1 << (7 - k))) {
165 GraphBuffer[cnt++] = 1;
166 } else {
167 GraphBuffer[cnt++] = 0;
168 }
169 }
170 }
171 GraphTraceLen = cnt;
172 RepaintGraphWindow();
173 return 0;
174 }
175
176 /*
177 * Convert to a bitstream
178 */
179 int CmdBitstream(const char *Cmd)
180 {
181 int i, j;
182 int bit;
183 int gtl;
184 int clock;
185 int low = 0;
186 int high = 0;
187 int hithigh, hitlow, first;
188
189 /* Detect high and lows and clock */
190 for (i = 0; i < GraphTraceLen; ++i)
191 {
192 if (GraphBuffer[i] > high)
193 high = GraphBuffer[i];
194 else if (GraphBuffer[i] < low)
195 low = GraphBuffer[i];
196 }
197
198 /* Get our clock */
199 clock = GetClock(Cmd, high, 1);
200 gtl = ClearGraph(0);
201
202 bit = 0;
203 for (i = 0; i < (int)(gtl / clock); ++i)
204 {
205 hithigh = 0;
206 hitlow = 0;
207 first = 1;
208 /* Find out if we hit both high and low peaks */
209 for (j = 0; j < clock; ++j)
210 {
211 if (GraphBuffer[(i * clock) + j] == high)
212 hithigh = 1;
213 else if (GraphBuffer[(i * clock) + j] == low)
214 hitlow = 1;
215 /* it doesn't count if it's the first part of our read
216 because it's really just trailing from the last sequence */
217 if (first && (hithigh || hitlow))
218 hithigh = hitlow = 0;
219 else
220 first = 0;
221
222 if (hithigh && hitlow)
223 break;
224 }
225
226 /* If we didn't hit both high and low peaks, we had a bit transition */
227 if (!hithigh || !hitlow)
228 bit ^= 1;
229
230 AppendGraph(0, clock, bit);
231 // for (j = 0; j < (int)(clock/2); j++)
232 // GraphBuffer[(i * clock) + j] = bit ^ 1;
233 // for (j = (int)(clock/2); j < clock; j++)
234 // GraphBuffer[(i * clock) + j] = bit;
235 }
236
237 RepaintGraphWindow();
238 return 0;
239 }
240
241 int CmdBuffClear(const char *Cmd)
242 {
243 UsbCommand c = {CMD_BUFF_CLEAR};
244 SendCommand(&c);
245 ClearGraph(true);
246 return 0;
247 }
248
249 int CmdDec(const char *Cmd)
250 {
251 for (int i = 0; i < (GraphTraceLen / 2); ++i)
252 GraphBuffer[i] = GraphBuffer[i * 2];
253 GraphTraceLen /= 2;
254 PrintAndLog("decimated by 2");
255 RepaintGraphWindow();
256 return 0;
257 }
258
259 /* Print our clock rate */
260 int CmdDetectClockRate(const char *Cmd)
261 {
262 int clock = DetectClock(0);
263 PrintAndLog("Auto-detected clock rate: %d", clock);
264 return 0;
265 }
266
267 int CmdFSKdemod(const char *Cmd)
268 {
269 static const int LowTone[] = {
270 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
271 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
272 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
273 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
274 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
275 };
276 static const int HighTone[] = {
277 1, 1, 1, 1, 1, -1, -1, -1, -1,
278 1, 1, 1, 1, -1, -1, -1, -1,
279 1, 1, 1, 1, -1, -1, -1, -1,
280 1, 1, 1, 1, -1, -1, -1, -1,
281 1, 1, 1, 1, -1, -1, -1, -1,
282 1, 1, 1, 1, -1, -1, -1, -1, -1,
283 };
284
285 int lowLen = sizeof (LowTone) / sizeof (int);
286 int highLen = sizeof (HighTone) / sizeof (int);
287 int convLen = (highLen > lowLen) ? highLen : lowLen;
288 uint32_t hi = 0, lo = 0;
289
290 int i, j;
291 int minMark = 0, maxMark = 0;
292
293 for (i = 0; i < GraphTraceLen - convLen; ++i) {
294 int lowSum = 0, highSum = 0;
295
296 for (j = 0; j < lowLen; ++j) {
297 lowSum += LowTone[j]*GraphBuffer[i+j];
298 }
299 for (j = 0; j < highLen; ++j) {
300 highSum += HighTone[j] * GraphBuffer[i + j];
301 }
302 lowSum = abs(100 * lowSum / lowLen);
303 highSum = abs(100 * highSum / highLen);
304 GraphBuffer[i] = (highSum << 16) | lowSum;
305 }
306
307 for(i = 0; i < GraphTraceLen - convLen - 16; ++i) {
308 int lowTot = 0, highTot = 0;
309 // 10 and 8 are f_s divided by f_l and f_h, rounded
310 for (j = 0; j < 10; ++j) {
311 lowTot += (GraphBuffer[i+j] & 0xffff);
312 }
313 for (j = 0; j < 8; j++) {
314 highTot += (GraphBuffer[i + j] >> 16);
315 }
316 GraphBuffer[i] = lowTot - highTot;
317 if (GraphBuffer[i] > maxMark) maxMark = GraphBuffer[i];
318 if (GraphBuffer[i] < minMark) minMark = GraphBuffer[i];
319 }
320
321 GraphTraceLen -= (convLen + 16);
322 RepaintGraphWindow();
323
324 // Find bit-sync (3 lo followed by 3 high)
325 int max = 0, maxPos = 0;
326 for (i = 0; i < 6000; ++i) {
327 int dec = 0;
328 for (j = 0; j < 3 * lowLen; ++j) {
329 dec -= GraphBuffer[i + j];
330 }
331 for (; j < 3 * (lowLen + highLen ); ++j) {
332 dec += GraphBuffer[i + j];
333 }
334 if (dec > max) {
335 max = dec;
336 maxPos = i;
337 }
338 }
339
340 // place start of bit sync marker in graph
341 GraphBuffer[maxPos] = maxMark;
342 GraphBuffer[maxPos + 1] = minMark;
343
344 maxPos += j;
345
346 // place end of bit sync marker in graph
347 GraphBuffer[maxPos] = maxMark;
348 GraphBuffer[maxPos+1] = minMark;
349
350 PrintAndLog("actual data bits start at sample %d", maxPos);
351 PrintAndLog("length %d/%d", highLen, lowLen);
352
353 uint8_t bits[46];
354 bits[sizeof(bits)-1] = '\0';
355
356 // find bit pairs and manchester decode them
357 for (i = 0; i < arraylen(bits) - 1; ++i) {
358 int dec = 0;
359 for (j = 0; j < lowLen; ++j) {
360 dec -= GraphBuffer[maxPos + j];
361 }
362 for (; j < lowLen + highLen; ++j) {
363 dec += GraphBuffer[maxPos + j];
364 }
365 maxPos += j;
366 // place inter bit marker in graph
367 GraphBuffer[maxPos] = maxMark;
368 GraphBuffer[maxPos + 1] = minMark;
369
370 // hi and lo form a 64 bit pair
371 hi = (hi << 1) | (lo >> 31);
372 lo = (lo << 1);
373 // store decoded bit as binary (in hi/lo) and text (in bits[])
374 if(dec < 0) {
375 bits[i] = '1';
376 lo |= 1;
377 } else {
378 bits[i] = '0';
379 }
380 }
381 PrintAndLog("bits: '%s'", bits);
382 PrintAndLog("hex: %08x %08x", hi, lo);
383 return 0;
384 }
385
386 int CmdGrid(const char *Cmd)
387 {
388 sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
389 PlotGridXdefault= PlotGridX;
390 PlotGridYdefault= PlotGridY;
391 RepaintGraphWindow();
392 return 0;
393 }
394
395 int CmdHexsamples(const char *Cmd)
396 {
397 int i, j;
398 int requested = 0;
399 int offset = 0;
400 char string_buf[25];
401 char* string_ptr = string_buf;
402 uint8_t got[40000];
403
404 sscanf(Cmd, "%i %i", &requested, &offset);
405
406 /* if no args send something */
407 if (requested == 0) {
408 requested = 8;
409 }
410 if (offset + requested > sizeof(got)) {
411 PrintAndLog("Tried to read past end of buffer, <bytes> + <offset> > 40000");
412 return 0;
413 }
414
415 GetFromBigBuf(got,requested,offset);
416 WaitForResponse(CMD_ACK,NULL);
417
418 i = 0;
419 for (j = 0; j < requested; j++) {
420 i++;
421 string_ptr += sprintf(string_ptr, "%02x ", got[j]);
422 if (i == 8) {
423 *(string_ptr - 1) = '\0'; // remove the trailing space
424 PrintAndLog("%s", string_buf);
425 string_buf[0] = '\0';
426 string_ptr = string_buf;
427 i = 0;
428 }
429 if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes
430 *(string_ptr - 1) = '\0';
431 PrintAndLog("%s", string_buf);
432 string_buf[0] = '\0';
433 }
434 }
435 return 0;
436 }
437
438 int CmdHide(const char *Cmd)
439 {
440 HideGraphWindow();
441 return 0;
442 }
443
444 int CmdHpf(const char *Cmd)
445 {
446 int i;
447 int accum = 0;
448
449 for (i = 10; i < GraphTraceLen; ++i)
450 accum += GraphBuffer[i];
451 accum /= (GraphTraceLen - 10);
452 for (i = 0; i < GraphTraceLen; ++i)
453 GraphBuffer[i] -= accum;
454
455 RepaintGraphWindow();
456 return 0;
457 }
458
459 int CmdSamples(const char *Cmd)
460 {
461 int cnt = 0;
462 int n;
463 uint8_t got[40000];
464
465 n = strtol(Cmd, NULL, 0);
466 if (n == 0) n = 512;
467 if (n > sizeof(got)) n = sizeof(got);
468
469 PrintAndLog("Reading %d samples\n", n);
470 GetFromBigBuf(got,n,0);
471 WaitForResponse(CMD_ACK,NULL);
472 for (int j = 0; j < n; j++) {
473 GraphBuffer[cnt++] = ((int)got[j]) - 128;
474 }
475
476 PrintAndLog("Done!\n");
477 GraphTraceLen = n;
478 RepaintGraphWindow();
479 return 0;
480 }
481
482 int CmdTuneSamples(const char *Cmd)
483 {
484 int cnt = 0;
485 int n = 255;
486 uint8_t got[255];
487
488 PrintAndLog("Reading %d samples\n", n);
489 GetFromBigBuf(got,n,7256); // armsrc/apps.h: #define FREE_BUFFER_OFFSET 7256
490 WaitForResponse(CMD_ACK,NULL);
491 for (int j = 0; j < n; j++) {
492 GraphBuffer[cnt++] = ((int)got[j]) - 128;
493 }
494
495 PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n");
496 PrintAndLog("\n");
497 GraphTraceLen = n;
498 RepaintGraphWindow();
499 return 0;
500 }
501
502 int CmdLoad(const char *Cmd)
503 {
504 FILE *f = fopen(Cmd, "r");
505 if (!f) {
506 PrintAndLog("couldn't open '%s'", Cmd);
507 return 0;
508 }
509
510 GraphTraceLen = 0;
511 char line[80];
512 while (fgets(line, sizeof (line), f)) {
513 GraphBuffer[GraphTraceLen] = atoi(line);
514 GraphTraceLen++;
515 }
516 fclose(f);
517 PrintAndLog("loaded %d samples", GraphTraceLen);
518 RepaintGraphWindow();
519 return 0;
520 }
521
522 int CmdLtrim(const char *Cmd)
523 {
524 int ds = atoi(Cmd);
525
526 for (int i = ds; i < GraphTraceLen; ++i)
527 GraphBuffer[i-ds] = GraphBuffer[i];
528 GraphTraceLen -= ds;
529
530 RepaintGraphWindow();
531 return 0;
532 }
533
534 /*
535 * Manchester demodulate a bitstream. The bitstream needs to be already in
536 * the GraphBuffer as 0 and 1 values
537 *
538 * Give the clock rate as argument in order to help the sync - the algorithm
539 * resyncs at each pulse anyway.
540 *
541 * Not optimized by any means, this is the 1st time I'm writing this type of
542 * routine, feel free to improve...
543 *
544 * 1st argument: clock rate (as number of samples per clock rate)
545 * Typical values can be 64, 32, 128...
546 */
547 int CmdManchesterDemod(const char *Cmd)
548 {
549 int i, j, invert= 0;
550 int bit;
551 int clock;
552 int lastval = 0;
553 int low = 0;
554 int high = 0;
555 int hithigh, hitlow, first;
556 int lc = 0;
557 int bitidx = 0;
558 int bit2idx = 0;
559 int warnings = 0;
560
561 /* check if we're inverting output */
562 if (*Cmd == 'i')
563 {
564 PrintAndLog("Inverting output");
565 invert = 1;
566 ++Cmd;
567 do
568 ++Cmd;
569 while(*Cmd == ' '); // in case a 2nd argument was given
570 }
571
572 /* Holds the decoded bitstream: each clock period contains 2 bits */
573 /* later simplified to 1 bit after manchester decoding. */
574 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
575 /* int BitStream[GraphTraceLen*2/clock+10]; */
576
577 /* But it does not work if compiling on WIndows: therefore we just allocate a */
578 /* large array */
579 uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0};
580
581 /* Detect high and lows */
582 for (i = 0; i < GraphTraceLen; i++)
583 {
584 if (GraphBuffer[i] > high)
585 high = GraphBuffer[i];
586 else if (GraphBuffer[i] < low)
587 low = GraphBuffer[i];
588 }
589
590 /* Get our clock */
591 clock = GetClock(Cmd, high, 1);
592
593 int tolerance = clock/4;
594
595 /* Detect first transition */
596 /* Lo-Hi (arbitrary) */
597 /* skip to the first high */
598 for (i= 0; i < GraphTraceLen; i++)
599 if (GraphBuffer[i] == high)
600 break;
601 /* now look for the first low */
602 for (; i < GraphTraceLen; i++)
603 {
604 if (GraphBuffer[i] == low)
605 {
606 lastval = i;
607 break;
608 }
609 }
610
611 /* If we're not working with 1/0s, demod based off clock */
612 if (high != 1)
613 {
614 bit = 0; /* We assume the 1st bit is zero, it may not be
615 * the case: this routine (I think) has an init problem.
616 * Ed.
617 */
618 for (; i < (int)(GraphTraceLen / clock); i++)
619 {
620 hithigh = 0;
621 hitlow = 0;
622 first = 1;
623
624 /* Find out if we hit both high and low peaks */
625 for (j = 0; j < clock; j++)
626 {
627 if (GraphBuffer[(i * clock) + j] == high)
628 hithigh = 1;
629 else if (GraphBuffer[(i * clock) + j] == low)
630 hitlow = 1;
631
632 /* it doesn't count if it's the first part of our read
633 because it's really just trailing from the last sequence */
634 if (first && (hithigh || hitlow))
635 hithigh = hitlow = 0;
636 else
637 first = 0;
638
639 if (hithigh && hitlow)
640 break;
641 }
642
643 /* If we didn't hit both high and low peaks, we had a bit transition */
644 if (!hithigh || !hitlow)
645 bit ^= 1;
646
647 BitStream[bit2idx++] = bit ^ invert;
648 }
649 }
650
651 /* standard 1/0 bitstream */
652 else
653 {
654
655 /* Then detect duration between 2 successive transitions */
656 for (bitidx = 1; i < GraphTraceLen; i++)
657 {
658 if (GraphBuffer[i-1] != GraphBuffer[i])
659 {
660 lc = i-lastval;
661 lastval = i;
662
663 // Error check: if bitidx becomes too large, we do not
664 // have a Manchester encoded bitstream or the clock is really
665 // wrong!
666 if (bitidx > (GraphTraceLen*2/clock+8) ) {
667 PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
668 return 0;
669 }
670 // Then switch depending on lc length:
671 // Tolerance is 1/4 of clock rate (arbitrary)
672 if (abs(lc-clock/2) < tolerance) {
673 // Short pulse : either "1" or "0"
674 BitStream[bitidx++]=GraphBuffer[i-1];
675 } else if (abs(lc-clock) < tolerance) {
676 // Long pulse: either "11" or "00"
677 BitStream[bitidx++]=GraphBuffer[i-1];
678 BitStream[bitidx++]=GraphBuffer[i-1];
679 } else {
680 // Error
681 warnings++;
682 PrintAndLog("Warning: Manchester decode error for pulse width detection.");
683 PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
684
685 if (warnings > 10)
686 {
687 PrintAndLog("Error: too many detection errors, aborting.");
688 return 0;
689 }
690 }
691 }
692 }
693
694 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
695 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
696 // to stop output at the final bitidx2 value, not bitidx
697 for (i = 0; i < bitidx; i += 2) {
698 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
699 BitStream[bit2idx++] = 1 ^ invert;
700 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
701 BitStream[bit2idx++] = 0 ^ invert;
702 } else {
703 // We cannot end up in this state, this means we are unsynchronized,
704 // move up 1 bit:
705 i++;
706 warnings++;
707 PrintAndLog("Unsynchronized, resync...");
708 PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
709
710 if (warnings > 10)
711 {
712 PrintAndLog("Error: too many decode errors, aborting.");
713 return 0;
714 }
715 }
716 }
717 }
718
719 PrintAndLog("Manchester decoded bitstream");
720 // Now output the bitstream to the scrollback by line of 16 bits
721 for (i = 0; i < (bit2idx-16); i+=16) {
722 PrintAndLog("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
723 BitStream[i],
724 BitStream[i+1],
725 BitStream[i+2],
726 BitStream[i+3],
727 BitStream[i+4],
728 BitStream[i+5],
729 BitStream[i+6],
730 BitStream[i+7],
731 BitStream[i+8],
732 BitStream[i+9],
733 BitStream[i+10],
734 BitStream[i+11],
735 BitStream[i+12],
736 BitStream[i+13],
737 BitStream[i+14],
738 BitStream[i+15]);
739 }
740 return 0;
741 }
742
743 /* Modulate our data into manchester */
744 int CmdManchesterMod(const char *Cmd)
745 {
746 int i, j;
747 int clock;
748 int bit, lastbit, wave;
749
750 /* Get our clock */
751 clock = GetClock(Cmd, 0, 1);
752
753 wave = 0;
754 lastbit = 1;
755 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
756 {
757 bit = GraphBuffer[i * clock] ^ 1;
758
759 for (j = 0; j < (int)(clock/2); j++)
760 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
761 for (j = (int)(clock/2); j < clock; j++)
762 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
763
764 /* Keep track of how we start our wave and if we changed or not this time */
765 wave ^= bit ^ lastbit;
766 lastbit = bit;
767 }
768
769 RepaintGraphWindow();
770 return 0;
771 }
772
773 int CmdNorm(const char *Cmd)
774 {
775 int i;
776 int max = INT_MIN, min = INT_MAX;
777
778 for (i = 10; i < GraphTraceLen; ++i) {
779 if (GraphBuffer[i] > max)
780 max = GraphBuffer[i];
781 if (GraphBuffer[i] < min)
782 min = GraphBuffer[i];
783 }
784
785 if (max != min) {
786 for (i = 0; i < GraphTraceLen; ++i) {
787 GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 1000 /
788 (max - min);
789 }
790 }
791 RepaintGraphWindow();
792 return 0;
793 }
794
795 int CmdPlot(const char *Cmd)
796 {
797 ShowGraphWindow();
798 return 0;
799 }
800
801 int CmdSave(const char *Cmd)
802 {
803 FILE *f = fopen(Cmd, "w");
804 if(!f) {
805 PrintAndLog("couldn't open '%s'", Cmd);
806 return 0;
807 }
808 int i;
809 for (i = 0; i < GraphTraceLen; i++) {
810 fprintf(f, "%d\n", GraphBuffer[i]);
811 }
812 fclose(f);
813 PrintAndLog("saved to '%s'", Cmd);
814 return 0;
815 }
816
817 int CmdScale(const char *Cmd)
818 {
819 CursorScaleFactor = atoi(Cmd);
820 if (CursorScaleFactor == 0) {
821 PrintAndLog("bad, can't have zero scale");
822 CursorScaleFactor = 1;
823 }
824 RepaintGraphWindow();
825 return 0;
826 }
827
828 int CmdThreshold(const char *Cmd)
829 {
830 int threshold = atoi(Cmd);
831
832 for (int i = 0; i < GraphTraceLen; ++i) {
833 if (GraphBuffer[i] >= threshold)
834 GraphBuffer[i] = 1;
835 else
836 GraphBuffer[i] = -1;
837 }
838 RepaintGraphWindow();
839 return 0;
840 }
841
842 int CmdDirectionalThreshold(const char *Cmd)
843 {
844 int8_t upThres = param_get8(Cmd, 0);
845 int8_t downThres = param_get8(Cmd, 1);
846
847 printf("Applying Up Threshold: %d, Down Threshold: %d\n", upThres, downThres);
848
849 int lastValue = GraphBuffer[0];
850 GraphBuffer[0] = 0; // Will be changed at the end, but init 0 as we adjust to last samples value if no threshold kicks in.
851
852 for (int i = 1; i < GraphTraceLen; ++i) {
853 // Apply first threshold to samples heading up
854 if (GraphBuffer[i] >= upThres && GraphBuffer[i] > lastValue)
855 {
856 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
857 GraphBuffer[i] = 1;
858 }
859 // Apply second threshold to samples heading down
860 else if (GraphBuffer[i] <= downThres && GraphBuffer[i] < lastValue)
861 {
862 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
863 GraphBuffer[i] = -1;
864 }
865 else
866 {
867 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
868 GraphBuffer[i] = GraphBuffer[i-1];
869
870 }
871 }
872 GraphBuffer[0] = GraphBuffer[1]; // Aline with first edited sample.
873 RepaintGraphWindow();
874 return 0;
875 }
876
877 int CmdZerocrossings(const char *Cmd)
878 {
879 // Zero-crossings aren't meaningful unless the signal is zero-mean.
880 CmdHpf("");
881
882 int sign = 1;
883 int zc = 0;
884 int lastZc = 0;
885
886 for (int i = 0; i < GraphTraceLen; ++i) {
887 if (GraphBuffer[i] * sign >= 0) {
888 // No change in sign, reproduce the previous sample count.
889 zc++;
890 GraphBuffer[i] = lastZc;
891 } else {
892 // Change in sign, reset the sample count.
893 sign = -sign;
894 GraphBuffer[i] = lastZc;
895 if (sign > 0) {
896 lastZc = zc;
897 zc = 0;
898 }
899 }
900 }
901
902 RepaintGraphWindow();
903 return 0;
904 }
905
906 static command_t CommandTable[] =
907 {
908 {"help", CmdHelp, 1, "This help"},
909 {"amp", CmdAmp, 1, "Amplify peaks"},
910 {"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
911 {"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
912 {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
913 {"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
914 {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
915 {"dec", CmdDec, 1, "Decimate samples"},
916 {"detectclock", CmdDetectClockRate, 1, "Detect clock rate"},
917 {"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"},
918 {"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
919 {"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
920 {"hide", CmdHide, 1, "Hide graph window"},
921 {"hpf", CmdHpf, 1, "Remove DC offset from trace"},
922 {"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
923 {"ltrim", CmdLtrim, 1, "<samples> -- Trim samples from left of trace"},
924 {"mandemod", CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
925 {"manmod", CmdManchesterMod, 1, "[clock rate] -- Manchester modulate a binary stream"},
926 {"norm", CmdNorm, 1, "Normalize max/min to +/-500"},
927 {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
928 {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window"},
929 {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"},
930 {"save", CmdSave, 1, "<filename> -- Save trace (from graph window)"},
931 {"scale", CmdScale, 1, "<int> -- Set cursor display scale"},
932 {"threshold", CmdThreshold, 1, "<threshold> -- Maximize/minimize every value in the graph window depending on threshold"},
933 {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"},
934 {"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
935 {NULL, NULL, 0, NULL}
936 };
937
938 int CmdData(const char *Cmd)
939 {
940 CmdsParse(CommandTable, Cmd);
941 return 0;
942 }
943
944 int CmdHelp(const char *Cmd)
945 {
946 CmdsHelp(CommandTable);
947 return 0;
948 }
Impressum, Datenschutz