]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmddata.c
Merge pull request #1 from holiman/ioprox_fixes
[proxmark3-svn] / client / cmddata.c
CommitLineData
a553f267 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
7fe9b0b7 11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <limits.h>
902cb3c0 15#include "proxmark3.h"
7fe9b0b7 16#include "data.h"
17#include "ui.h"
18#include "graph.h"
19#include "cmdparser.h"
d51b2eda 20#include "util.h"
7fe9b0b7 21#include "cmdmain.h"
22#include "cmddata.h"
23
24static int CmdHelp(const char *Cmd);
25
26int 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 */
72int 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
122int 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
154int CmdBitsamples(const char *Cmd)
155{
156 int cnt = 0;
90d74dc2 157 uint8_t got[12288];
158
159 GetFromBigBuf(got,sizeof(got),0);
160 WaitForResponse(CMD_ACK,NULL);
7fe9b0b7 161
90d74dc2 162 for (int j = 0; j < sizeof(got); j++) {
7fe9b0b7 163 for (int k = 0; k < 8; k++) {
90d74dc2 164 if(got[j] & (1 << (7 - k))) {
7fe9b0b7 165 GraphBuffer[cnt++] = 1;
166 } else {
167 GraphBuffer[cnt++] = 0;
168 }
169 }
7fe9b0b7 170 }
171 GraphTraceLen = cnt;
172 RepaintGraphWindow();
173 return 0;
174}
175
176/*
177 * Convert to a bitstream
178 */
179int 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
241int CmdBuffClear(const char *Cmd)
242{
243 UsbCommand c = {CMD_BUFF_CLEAR};
244 SendCommand(&c);
245 ClearGraph(true);
246 return 0;
247}
248
249int 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 */
260int CmdDetectClockRate(const char *Cmd)
261{
262 int clock = DetectClock(0);
263 PrintAndLog("Auto-detected clock rate: %d", clock);
264 return 0;
265}
266
267int 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
386int CmdGrid(const char *Cmd)
387{
388 sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
7ddb9900 389 PlotGridXdefault= PlotGridX;
390 PlotGridYdefault= PlotGridY;
7fe9b0b7 391 RepaintGraphWindow();
392 return 0;
393}
394
395int CmdHexsamples(const char *Cmd)
396{
4961e292 397 int i, j;
7fe9b0b7 398 int requested = 0;
399 int offset = 0;
4961e292 400 char string_buf[25];
401 char* string_ptr = string_buf;
90d74dc2 402 uint8_t got[40000];
4961e292 403
404 sscanf(Cmd, "%i %i", &requested, &offset);
90d74dc2 405
4961e292 406 /* if no args send something */
407 if (requested == 0) {
90d74dc2 408 requested = 8;
409 }
90d74dc2 410 if (offset + requested > sizeof(got)) {
411 PrintAndLog("Tried to read past end of buffer, <bytes> + <offset> > 40000");
4961e292 412 return 0;
413 }
90d74dc2 414
4961e292 415 GetFromBigBuf(got,requested,offset);
90d74dc2 416 WaitForResponse(CMD_ACK,NULL);
417
4961e292 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 }
7fe9b0b7 434 }
435 return 0;
436}
437
7fe9b0b7 438int CmdHide(const char *Cmd)
439{
440 HideGraphWindow();
441 return 0;
442}
443
444int 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
8d183c53 459int CmdSamples(const char *Cmd)
7fe9b0b7 460{
461 int cnt = 0;
462 int n;
90d74dc2 463 uint8_t got[40000];
464
7fe9b0b7 465 n = strtol(Cmd, NULL, 0);
90d74dc2 466 if (n == 0) n = 512;
467 if (n > sizeof(got)) n = sizeof(got);
a2847518 468
7fe9b0b7 469 PrintAndLog("Reading %d samples\n", n);
90d74dc2 470 GetFromBigBuf(got,n,0);
a2847518 471 WaitForResponse(CMD_ACK,NULL);
90d74dc2 472 for (int j = 0; j < n; j++) {
a2847518 473 GraphBuffer[cnt++] = ((int)got[j]) - 128;
7fe9b0b7 474 }
a2847518 475
7fe9b0b7 476 PrintAndLog("Done!\n");
90d74dc2 477 GraphTraceLen = n;
7fe9b0b7 478 RepaintGraphWindow();
479 return 0;
480}
481
482int CmdLoad(const char *Cmd)
483{
c6f1fb9d 484 FILE *f = fopen(Cmd, "r");
7fe9b0b7 485 if (!f) {
c6f1fb9d 486 PrintAndLog("couldn't open '%s'", Cmd);
7fe9b0b7 487 return 0;
488 }
489
490 GraphTraceLen = 0;
491 char line[80];
492 while (fgets(line, sizeof (line), f)) {
493 GraphBuffer[GraphTraceLen] = atoi(line);
494 GraphTraceLen++;
495 }
496 fclose(f);
497 PrintAndLog("loaded %d samples", GraphTraceLen);
498 RepaintGraphWindow();
499 return 0;
500}
501
502int CmdLtrim(const char *Cmd)
503{
504 int ds = atoi(Cmd);
505
506 for (int i = ds; i < GraphTraceLen; ++i)
507 GraphBuffer[i-ds] = GraphBuffer[i];
508 GraphTraceLen -= ds;
509
510 RepaintGraphWindow();
511 return 0;
512}
513
514/*
515 * Manchester demodulate a bitstream. The bitstream needs to be already in
516 * the GraphBuffer as 0 and 1 values
517 *
518 * Give the clock rate as argument in order to help the sync - the algorithm
519 * resyncs at each pulse anyway.
520 *
521 * Not optimized by any means, this is the 1st time I'm writing this type of
522 * routine, feel free to improve...
523 *
524 * 1st argument: clock rate (as number of samples per clock rate)
525 * Typical values can be 64, 32, 128...
526 */
527int CmdManchesterDemod(const char *Cmd)
528{
529 int i, j, invert= 0;
530 int bit;
531 int clock;
fddf220a 532 int lastval = 0;
7fe9b0b7 533 int low = 0;
534 int high = 0;
535 int hithigh, hitlow, first;
536 int lc = 0;
537 int bitidx = 0;
538 int bit2idx = 0;
539 int warnings = 0;
540
541 /* check if we're inverting output */
c6f1fb9d 542 if (*Cmd == 'i')
7fe9b0b7 543 {
544 PrintAndLog("Inverting output");
545 invert = 1;
fffad860 546 ++Cmd;
7fe9b0b7 547 do
548 ++Cmd;
549 while(*Cmd == ' '); // in case a 2nd argument was given
550 }
551
552 /* Holds the decoded bitstream: each clock period contains 2 bits */
553 /* later simplified to 1 bit after manchester decoding. */
554 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
555 /* int BitStream[GraphTraceLen*2/clock+10]; */
556
557 /* But it does not work if compiling on WIndows: therefore we just allocate a */
558 /* large array */
15cdabd4 559 uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
7fe9b0b7 560
561 /* Detect high and lows */
562 for (i = 0; i < GraphTraceLen; i++)
563 {
564 if (GraphBuffer[i] > high)
565 high = GraphBuffer[i];
566 else if (GraphBuffer[i] < low)
567 low = GraphBuffer[i];
568 }
569
570 /* Get our clock */
571 clock = GetClock(Cmd, high, 1);
572
573 int tolerance = clock/4;
574
575 /* Detect first transition */
576 /* Lo-Hi (arbitrary) */
577 /* skip to the first high */
578 for (i= 0; i < GraphTraceLen; i++)
579 if (GraphBuffer[i] == high)
580 break;
581 /* now look for the first low */
582 for (; i < GraphTraceLen; i++)
583 {
584 if (GraphBuffer[i] == low)
585 {
586 lastval = i;
587 break;
588 }
589 }
590
591 /* If we're not working with 1/0s, demod based off clock */
592 if (high != 1)
593 {
594 bit = 0; /* We assume the 1st bit is zero, it may not be
595 * the case: this routine (I think) has an init problem.
596 * Ed.
597 */
598 for (; i < (int)(GraphTraceLen / clock); i++)
599 {
600 hithigh = 0;
601 hitlow = 0;
602 first = 1;
603
604 /* Find out if we hit both high and low peaks */
605 for (j = 0; j < clock; j++)
606 {
607 if (GraphBuffer[(i * clock) + j] == high)
608 hithigh = 1;
609 else if (GraphBuffer[(i * clock) + j] == low)
610 hitlow = 1;
611
612 /* it doesn't count if it's the first part of our read
613 because it's really just trailing from the last sequence */
614 if (first && (hithigh || hitlow))
615 hithigh = hitlow = 0;
616 else
617 first = 0;
618
619 if (hithigh && hitlow)
620 break;
621 }
622
623 /* If we didn't hit both high and low peaks, we had a bit transition */
624 if (!hithigh || !hitlow)
625 bit ^= 1;
626
627 BitStream[bit2idx++] = bit ^ invert;
628 }
629 }
630
631 /* standard 1/0 bitstream */
632 else
633 {
634
635 /* Then detect duration between 2 successive transitions */
636 for (bitidx = 1; i < GraphTraceLen; i++)
637 {
638 if (GraphBuffer[i-1] != GraphBuffer[i])
639 {
640 lc = i-lastval;
641 lastval = i;
642
643 // Error check: if bitidx becomes too large, we do not
644 // have a Manchester encoded bitstream or the clock is really
645 // wrong!
646 if (bitidx > (GraphTraceLen*2/clock+8) ) {
647 PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
648 return 0;
649 }
650 // Then switch depending on lc length:
651 // Tolerance is 1/4 of clock rate (arbitrary)
652 if (abs(lc-clock/2) < tolerance) {
653 // Short pulse : either "1" or "0"
654 BitStream[bitidx++]=GraphBuffer[i-1];
655 } else if (abs(lc-clock) < tolerance) {
656 // Long pulse: either "11" or "00"
657 BitStream[bitidx++]=GraphBuffer[i-1];
658 BitStream[bitidx++]=GraphBuffer[i-1];
659 } else {
660 // Error
661 warnings++;
662 PrintAndLog("Warning: Manchester decode error for pulse width detection.");
663 PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
664
665 if (warnings > 10)
666 {
667 PrintAndLog("Error: too many detection errors, aborting.");
668 return 0;
669 }
670 }
671 }
672 }
673
674 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
675 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
676 // to stop output at the final bitidx2 value, not bitidx
677 for (i = 0; i < bitidx; i += 2) {
678 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
679 BitStream[bit2idx++] = 1 ^ invert;
680 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
681 BitStream[bit2idx++] = 0 ^ invert;
682 } else {
683 // We cannot end up in this state, this means we are unsynchronized,
684 // move up 1 bit:
685 i++;
686 warnings++;
687 PrintAndLog("Unsynchronized, resync...");
688 PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
689
690 if (warnings > 10)
691 {
692 PrintAndLog("Error: too many decode errors, aborting.");
693 return 0;
694 }
695 }
696 }
697 }
698
699 PrintAndLog("Manchester decoded bitstream");
700 // Now output the bitstream to the scrollback by line of 16 bits
701 for (i = 0; i < (bit2idx-16); i+=16) {
702 PrintAndLog("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
703 BitStream[i],
704 BitStream[i+1],
705 BitStream[i+2],
706 BitStream[i+3],
707 BitStream[i+4],
708 BitStream[i+5],
709 BitStream[i+6],
710 BitStream[i+7],
711 BitStream[i+8],
712 BitStream[i+9],
713 BitStream[i+10],
714 BitStream[i+11],
715 BitStream[i+12],
716 BitStream[i+13],
717 BitStream[i+14],
718 BitStream[i+15]);
719 }
720 return 0;
721}
722
723/* Modulate our data into manchester */
724int CmdManchesterMod(const char *Cmd)
725{
726 int i, j;
727 int clock;
728 int bit, lastbit, wave;
729
730 /* Get our clock */
731 clock = GetClock(Cmd, 0, 1);
732
733 wave = 0;
734 lastbit = 1;
735 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
736 {
737 bit = GraphBuffer[i * clock] ^ 1;
738
739 for (j = 0; j < (int)(clock/2); j++)
740 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
741 for (j = (int)(clock/2); j < clock; j++)
742 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
743
744 /* Keep track of how we start our wave and if we changed or not this time */
745 wave ^= bit ^ lastbit;
746 lastbit = bit;
747 }
748
749 RepaintGraphWindow();
750 return 0;
751}
752
753int CmdNorm(const char *Cmd)
754{
755 int i;
756 int max = INT_MIN, min = INT_MAX;
757
758 for (i = 10; i < GraphTraceLen; ++i) {
759 if (GraphBuffer[i] > max)
760 max = GraphBuffer[i];
761 if (GraphBuffer[i] < min)
762 min = GraphBuffer[i];
763 }
764
765 if (max != min) {
766 for (i = 0; i < GraphTraceLen; ++i) {
767 GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 1000 /
768 (max - min);
769 }
770 }
771 RepaintGraphWindow();
772 return 0;
773}
774
775int CmdPlot(const char *Cmd)
776{
777 ShowGraphWindow();
778 return 0;
779}
780
781int CmdSave(const char *Cmd)
782{
783 FILE *f = fopen(Cmd, "w");
784 if(!f) {
785 PrintAndLog("couldn't open '%s'", Cmd);
786 return 0;
787 }
788 int i;
789 for (i = 0; i < GraphTraceLen; i++) {
790 fprintf(f, "%d\n", GraphBuffer[i]);
791 }
792 fclose(f);
793 PrintAndLog("saved to '%s'", Cmd);
794 return 0;
795}
796
797int CmdScale(const char *Cmd)
798{
799 CursorScaleFactor = atoi(Cmd);
800 if (CursorScaleFactor == 0) {
801 PrintAndLog("bad, can't have zero scale");
802 CursorScaleFactor = 1;
803 }
804 RepaintGraphWindow();
805 return 0;
806}
807
808int CmdThreshold(const char *Cmd)
809{
810 int threshold = atoi(Cmd);
811
812 for (int i = 0; i < GraphTraceLen; ++i) {
813 if (GraphBuffer[i] >= threshold)
814 GraphBuffer[i] = 1;
815 else
7bb9d33e 816 GraphBuffer[i] = -1;
7fe9b0b7 817 }
818 RepaintGraphWindow();
819 return 0;
820}
821
d51b2eda
MHS
822int CmdDirectionalThreshold(const char *Cmd)
823{
824 int8_t upThres = param_get8(Cmd, 0);
825 int8_t downThres = param_get8(Cmd, 1);
826
827 printf("Applying Up Threshold: %d, Down Threshold: %d\n", upThres, downThres);
828
829 int lastValue = GraphBuffer[0];
830 GraphBuffer[0] = 0; // Will be changed at the end, but init 0 as we adjust to last samples value if no threshold kicks in.
831
832 for (int i = 1; i < GraphTraceLen; ++i) {
833 // Apply first threshold to samples heading up
834 if (GraphBuffer[i] >= upThres && GraphBuffer[i] > lastValue)
835 {
836 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
837 GraphBuffer[i] = 1;
838 }
839 // Apply second threshold to samples heading down
840 else if (GraphBuffer[i] <= downThres && GraphBuffer[i] < lastValue)
841 {
842 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
843 GraphBuffer[i] = -1;
844 }
845 else
846 {
847 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
848 GraphBuffer[i] = GraphBuffer[i-1];
849
850 }
851 }
852 GraphBuffer[0] = GraphBuffer[1]; // Aline with first edited sample.
853 RepaintGraphWindow();
854 return 0;
855}
856
7fe9b0b7 857int CmdZerocrossings(const char *Cmd)
858{
859 // Zero-crossings aren't meaningful unless the signal is zero-mean.
860 CmdHpf("");
861
862 int sign = 1;
863 int zc = 0;
864 int lastZc = 0;
865
866 for (int i = 0; i < GraphTraceLen; ++i) {
867 if (GraphBuffer[i] * sign >= 0) {
868 // No change in sign, reproduce the previous sample count.
869 zc++;
870 GraphBuffer[i] = lastZc;
871 } else {
872 // Change in sign, reset the sample count.
873 sign = -sign;
874 GraphBuffer[i] = lastZc;
875 if (sign > 0) {
876 lastZc = zc;
877 zc = 0;
878 }
879 }
880 }
881
882 RepaintGraphWindow();
883 return 0;
884}
885
886static command_t CommandTable[] =
887{
888 {"help", CmdHelp, 1, "This help"},
889 {"amp", CmdAmp, 1, "Amplify peaks"},
57c69556 890 {"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
7fe9b0b7 891 {"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
892 {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
893 {"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
894 {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
895 {"dec", CmdDec, 1, "Decimate samples"},
896 {"detectclock", CmdDetectClockRate, 1, "Detect clock rate"},
897 {"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"},
898 {"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
90d74dc2 899 {"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
7fe9b0b7 900 {"hide", CmdHide, 1, "Hide graph window"},
901 {"hpf", CmdHpf, 1, "Remove DC offset from trace"},
7fe9b0b7 902 {"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
903 {"ltrim", CmdLtrim, 1, "<samples> -- Trim samples from left of trace"},
904 {"mandemod", CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
905 {"manmod", CmdManchesterMod, 1, "[clock rate] -- Manchester modulate a binary stream"},
906 {"norm", CmdNorm, 1, "Normalize max/min to +/-500"},
7ddb9900 907 {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
90d74dc2 908 {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window"},
7fe9b0b7 909 {"save", CmdSave, 1, "<filename> -- Save trace (from graph window)"},
910 {"scale", CmdScale, 1, "<int> -- Set cursor display scale"},
dbf444a1 911 {"threshold", CmdThreshold, 1, "<threshold> -- Maximize/minimize every value in the graph window depending on threshold"},
7fe9b0b7 912 {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"},
d51b2eda 913 {"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
7fe9b0b7 914 {NULL, NULL, 0, NULL}
915};
916
917int CmdData(const char *Cmd)
918{
919 CmdsParse(CommandTable, Cmd);
920 return 0;
921}
922
923int CmdHelp(const char *Cmd)
924{
925 CmdsHelp(CommandTable);
926 return 0;
927}
Impressum, Datenschutz