]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmddata.c
minor fix - got too comment happy removing test code
[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 */
b3b70669 72 //this method is dependant on all highs and lows to be the same(or clipped) this could be an issue[marshmellow]
73 //might be able to use clock to help identify highs and lows with some more tolerance
74 //but for now I will try a fuzz factor
7fe9b0b7 75int Cmdaskdemod(const char *Cmd)
76{
77 int i;
78 int c, high = 0, low = 0;
79
80 // TODO: complain if we do not give 2 arguments here !
81 // (AL - this doesn't make sense! we're only using one argument!!!)
82 sscanf(Cmd, "%i", &c);
83
84 /* Detect high and lows and clock */
b3b70669 85 // (AL - clock???)
7fe9b0b7 86 for (i = 0; i < GraphTraceLen; ++i)
87 {
88 if (GraphBuffer[i] > high)
89 high = GraphBuffer[i];
90 else if (GraphBuffer[i] < low)
91 low = GraphBuffer[i];
92 }
93 if (c != 0 && c != 1) {
94 PrintAndLog("Invalid argument: %s", Cmd);
95 return 0;
96 }
b3b70669 97 //prime loop
7fe9b0b7 98 if (GraphBuffer[0] > 0) {
99 GraphBuffer[0] = 1-c;
100 } else {
101 GraphBuffer[0] = c;
102 }
e888ed8e 103 //13% fuzz [marshmellow]
104 high=(int)(0.87*high);
105 low=(int)(0.87*low);
7fe9b0b7 106 for (i = 1; i < GraphTraceLen; ++i) {
107 /* Transitions are detected at each peak
108 * Transitions are either:
109 * - we're low: transition if we hit a high
110 * - we're high: transition if we hit a low
111 * (we need to do it this way because some tags keep high or
112 * low for long periods, others just reach the peak and go
113 * down)
114 */
ae2f73c1 115 //[marhsmellow] change == to >= for high and <= for low for fuzz
116 if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) {
7fe9b0b7 117 GraphBuffer[i] = 1 - c;
ae2f73c1 118 } else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){
7fe9b0b7 119 GraphBuffer[i] = c;
120 } else {
121 /* No transition */
122 GraphBuffer[i] = GraphBuffer[i - 1];
123 }
124 }
125 RepaintGraphWindow();
126 return 0;
127}
128
e888ed8e 129void printBitStream(uint8_t BitStream[], uint32_t bitLen){
130 uint32_t i = 0;
131 if (bitLen<16) return;
132 if (bitLen>512) bitLen=512;
133 for (i = 0; i < (bitLen-16); i+=16) {
134 PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
135 BitStream[i],
136 BitStream[i+1],
137 BitStream[i+2],
138 BitStream[i+3],
139 BitStream[i+4],
140 BitStream[i+5],
141 BitStream[i+6],
142 BitStream[i+7],
143 BitStream[i+8],
144 BitStream[i+9],
145 BitStream[i+10],
146 BitStream[i+11],
147 BitStream[i+12],
148 BitStream[i+13],
149 BitStream[i+14],
150 BitStream[i+15]);
151 }
152 return;
153}
154
155//by marshmellow
156//takes 2 arguments - clock and invert both as integers
157//prints binary found and saves in graphbuffer for further commands
158int Cmdaskrawdemod(const char *Cmd)
159{
160 uint32_t i;
161 int invert=0; //invert default
162 int high = 0, low = 0;
163 int clk=64; //clock default
164 uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0};
165 sscanf(Cmd, "%i %i", &clk, &invert);
166 if (!(clk>8)){
167 PrintAndLog("Invalid argument: %s",Cmd);
168 return 0;
169 }
170 if (invert != 0 && invert != 1) {
171 PrintAndLog("Invalid argument: %s", Cmd);
172 return 0;
173 }
174 uint32_t initLoopMax = 1000;
175 if (initLoopMax>GraphTraceLen) initLoopMax=GraphTraceLen;
176 // Detect high and lows
177 PrintAndLog("Using Clock: %d and invert=%d",clk,invert);
178 for (i = 0; i < initLoopMax; ++i) //1000 samples should be plenty to find high and low values
179 {
180 if (GraphBuffer[i] > high)
181 high = GraphBuffer[i];
182 else if (GraphBuffer[i] < low)
183 low = GraphBuffer[i];
184 }
185 if ((high < 30) && ((high !=1)||(low !=-1))){ //throw away static - allow 1 and -1 (in case of threshold command first)
186 PrintAndLog("no data found");
187 return 0;
188 }
189 //13% fuzz in case highs and lows aren't clipped [marshmellow]
190 high=(int)(0.75*high);
191 low=(int)(0.75*low);
192
193 //PrintAndLog("valid high: %d - valid low: %d",high,low);
194 int lastBit = 0; //set first clock check
195 uint32_t bitnum = 0; //output counter
196 uint8_t tol = 32;//clock tolerance adjust
197 uint32_t iii = 0;
198 uint32_t gLen = GraphTraceLen;
199 if (gLen > 500) gLen=500;
200 uint8_t errCnt =0;
201
202 //PrintAndLog("lastbit - %d",lastBit);
203
204 //loop to find first wave that works
205 for (iii=0; iii < gLen; ++iii){
206 if ((GraphBuffer[iii]>=high)||(GraphBuffer[iii]<=low)){
207 lastBit=iii-clk;
208 //loop through to see if this start location works
209 for (i = iii; i < GraphTraceLen; ++i) {
210 if ((GraphBuffer[i] >= high) && ((i-lastBit)>(clk-((int)clk/tol)))) { // && GraphBuffer[i-1] < high
211 lastBit+=clk;
212 BitStream[bitnum] = invert;
213 bitnum++;
214 } else if ((GraphBuffer[i] <= low) && ((i-lastBit)>(clk-((int)clk/tol)))){
215 //low found and we are expecting a bar
216 lastBit+=clk;
217 BitStream[bitnum] = 1-invert;
218 bitnum++;
219 } else {
220 //mid value found or no bar supposed to be here
221 if ((i-lastBit)>(clk+((int)(clk/tol)))){
222 //should have hit a high or low based on clock!!
223
224 /*
225 //debug
226 PrintAndLog("no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(clk/tol)))),(lastBit+(clk+((int)(clk/tol)))),lastBit);
227 if (bitnum > 0){
228 BitStream[bitnum]=77;
229 bitnum++;
230 }
231 */
232
233 errCnt++;
234 lastBit+=clk;//skip over until hit too many errors
235 if (errCnt>((GraphTraceLen/1000)*2)){ //allow 2 errors for every 1000 samples else start over
236 errCnt=0;
237 bitnum=0;//start over
238 break;
239 }
240 }
241 }
242 }
ea7d657f 243
e888ed8e 244 //debug
245 if ((bitnum>64) && (BitStream[bitnum-1]!=77)) break;
ea7d657f 246
e888ed8e 247 }
248 }
249 ClearGraph(0);
250 //move BitStream back to GraphBuffer
251 for (i=0; i < bitnum; ++i){
252 GraphBuffer[i]=BitStream[i];
253 }
254 GraphTraceLen=bitnum;
255 RepaintGraphWindow();
256
257 //output
258 if (errCnt>0){
259 PrintAndLog("# Error during Demoding: %d\n",errCnt);
260 }
261 PrintAndLog("ASK decoded bitstream:");
262 // Now output the bitstream to the scrollback by line of 16 bits
263 printBitStream(BitStream,bitnum);
264
265 return 0;
266}
267
7fe9b0b7 268int CmdAutoCorr(const char *Cmd)
269{
270 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
271
272 int window = atoi(Cmd);
273
274 if (window == 0) {
275 PrintAndLog("needs a window");
276 return 0;
277 }
278 if (window >= GraphTraceLen) {
279 PrintAndLog("window must be smaller than trace (%d samples)",
280 GraphTraceLen);
281 return 0;
282 }
283
284 PrintAndLog("performing %d correlations", GraphTraceLen - window);
285
286 for (int i = 0; i < GraphTraceLen - window; ++i) {
287 int sum = 0;
288 for (int j = 0; j < window; ++j) {
289 sum += (GraphBuffer[j]*GraphBuffer[i + j]) / 256;
290 }
291 CorrelBuffer[i] = sum;
292 }
293 GraphTraceLen = GraphTraceLen - window;
294 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen * sizeof (int));
295
296 RepaintGraphWindow();
297 return 0;
298}
299
300int CmdBitsamples(const char *Cmd)
301{
302 int cnt = 0;
90d74dc2 303 uint8_t got[12288];
304
305 GetFromBigBuf(got,sizeof(got),0);
306 WaitForResponse(CMD_ACK,NULL);
7fe9b0b7 307
90d74dc2 308 for (int j = 0; j < sizeof(got); j++) {
7fe9b0b7 309 for (int k = 0; k < 8; k++) {
90d74dc2 310 if(got[j] & (1 << (7 - k))) {
7fe9b0b7 311 GraphBuffer[cnt++] = 1;
312 } else {
313 GraphBuffer[cnt++] = 0;
314 }
315 }
7fe9b0b7 316 }
317 GraphTraceLen = cnt;
318 RepaintGraphWindow();
319 return 0;
320}
321
322/*
323 * Convert to a bitstream
324 */
325int CmdBitstream(const char *Cmd)
326{
327 int i, j;
328 int bit;
329 int gtl;
330 int clock;
331 int low = 0;
332 int high = 0;
333 int hithigh, hitlow, first;
334
335 /* Detect high and lows and clock */
336 for (i = 0; i < GraphTraceLen; ++i)
337 {
338 if (GraphBuffer[i] > high)
339 high = GraphBuffer[i];
340 else if (GraphBuffer[i] < low)
341 low = GraphBuffer[i];
342 }
343
344 /* Get our clock */
345 clock = GetClock(Cmd, high, 1);
346 gtl = ClearGraph(0);
347
348 bit = 0;
349 for (i = 0; i < (int)(gtl / clock); ++i)
350 {
351 hithigh = 0;
352 hitlow = 0;
353 first = 1;
354 /* Find out if we hit both high and low peaks */
355 for (j = 0; j < clock; ++j)
356 {
357 if (GraphBuffer[(i * clock) + j] == high)
358 hithigh = 1;
359 else if (GraphBuffer[(i * clock) + j] == low)
360 hitlow = 1;
361 /* it doesn't count if it's the first part of our read
362 because it's really just trailing from the last sequence */
363 if (first && (hithigh || hitlow))
364 hithigh = hitlow = 0;
365 else
366 first = 0;
367
368 if (hithigh && hitlow)
369 break;
370 }
371
372 /* If we didn't hit both high and low peaks, we had a bit transition */
373 if (!hithigh || !hitlow)
374 bit ^= 1;
375
376 AppendGraph(0, clock, bit);
377// for (j = 0; j < (int)(clock/2); j++)
378// GraphBuffer[(i * clock) + j] = bit ^ 1;
379// for (j = (int)(clock/2); j < clock; j++)
380// GraphBuffer[(i * clock) + j] = bit;
381 }
382
383 RepaintGraphWindow();
384 return 0;
385}
386
387int CmdBuffClear(const char *Cmd)
388{
389 UsbCommand c = {CMD_BUFF_CLEAR};
390 SendCommand(&c);
391 ClearGraph(true);
392 return 0;
393}
394
395int CmdDec(const char *Cmd)
396{
397 for (int i = 0; i < (GraphTraceLen / 2); ++i)
398 GraphBuffer[i] = GraphBuffer[i * 2];
399 GraphTraceLen /= 2;
400 PrintAndLog("decimated by 2");
401 RepaintGraphWindow();
402 return 0;
403}
404
405/* Print our clock rate */
406int CmdDetectClockRate(const char *Cmd)
407{
408 int clock = DetectClock(0);
409 PrintAndLog("Auto-detected clock rate: %d", clock);
410 return 0;
411}
412
b3b70669 413//demod GraphBuffer wave to 0s and 1s for each wave - 0s for short waves 1s for long waves
414size_t fsk_wave_demod(int size)
415{
416 uint32_t last_transition = 0;
417 uint32_t idx = 1;
418 uint32_t maxVal = 0;
419 // we don't care about actual value, only if it's more or less than a
420 // threshold essentially we capture zero crossings for later analysis
421 for(idx=1; idx<size; idx++){
422 if(maxVal<GraphBuffer[idx]) maxVal = GraphBuffer[idx];
423 }
424 // set close to the top of the wave threshold with 13% margin for error
425 // less likely to get a false transition up there.
426 // (but have to be careful not to go too high and miss some short waves)
427 uint32_t threshold_value = (uint32_t)(maxVal*.87);
428 idx=1;
429 // int threshold_value = 100;
430
431 // sync to first lo-hi transition, and threshold
432 // PrintAndLog("FSK init complete size: %d",size);//debug
433 // Need to threshold first sample
434 if(GraphBuffer[0] < threshold_value) GraphBuffer[0] = 0;
435 else GraphBuffer[0] = 1;
436 size_t numBits = 0;
437 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
438 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
439 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
440 for(idx = 1; idx < size; idx++) {
441 // threshold current value
442 if (GraphBuffer[idx] < threshold_value) GraphBuffer[idx] = 0;
443 else GraphBuffer[idx] = 1;
444 // Check for 0->1 transition
445 if (GraphBuffer[idx-1] < GraphBuffer[idx]) { // 0 -> 1 transition
446 if (idx-last_transition<6){
447 // do nothing with extra garbage (shouldn't be any) noise tolerance?
448 } else if(idx-last_transition < 9) {
449 GraphBuffer[numBits]=1;
450 // Other fsk demods reverse this making the short waves 1 and long waves 0
451 // this is really backwards... smaller waves will typically be 0 and larger 1 [marshmellow]
452 // but will leave as is and invert when needed later
453 } else{
454 GraphBuffer[numBits]=0;
455 }
456 last_transition = idx;
457 numBits++;
458 // PrintAndLog("numbits %d",numBits);
459 }
460 }
461 return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
462}
463uint32_t myround(float f)
464{
465 if (f >= UINT_MAX) return UINT_MAX;
466 return (uint32_t) (f + (float)0.5);
467}
468//translate 11111100000 to 10
469size_t aggregate_bits(int size, uint8_t rfLen, uint8_t maxConsequtiveBits, uint8_t invert) //,uint8_t l2h_crossing_value
470{
471 int lastval=GraphBuffer[0];
472 uint32_t idx=0;
473 size_t numBits=0;
474 uint32_t n=1;
475 uint32_t n2=0;
476 for( idx=1; idx < size; idx++) {
477
478 if (GraphBuffer[idx]==lastval) {
479 n++;
480 continue;
481 }
482 // if lastval was 1, we have a 1->0 crossing
483 if ( GraphBuffer[idx-1]==1 ) {
484 n=myround((float)(n+1)/((float)(rfLen)/(float)8)); //-2 noise tolerance
485
486 // n=(n+1) / h2l_crossing_value;
487 //truncating could get us into trouble
488 //now we will try with actual clock (RF/64 or RF/50) variable instead
489 //then devide with float casting then truncate after more acurate division
490 //and round to nearest int
491 //like n = (((float)n)/(float)rfLen/(float)10);
492 } else {// 0->1 crossing
493 n=myround((float)(n+1)/((float)(rfLen-2)/(float)10)); // as int 120/6 = 20 as float 120/(64/10) = 18 (18.75)
494 //n=(n+1) / l2h_crossing_value;
495 }
496 if (n == 0) n = 1; //this should never happen... should we error if it does?
497
498 if (n < maxConsequtiveBits) // Consecutive //when the consecutive bits are low - the noise tolerance can be high
499 //if it is high then we must be careful how much noise tolerance we allow
500 {
501 if (invert==0){ // do not invert bits
502 for (n2=0; n2<n; n2++){
503 GraphBuffer[numBits+n2]=GraphBuffer[idx-1];
504 }
505 //memset(GraphBuffer+numBits, GraphBuffer[idx-1] , n);
506 }else{ // invert bits
507 for (n2=0; n2<n; n2++){
508 GraphBuffer[numBits+n2]=GraphBuffer[idx-1]^1;
509 }
510 //memset(GraphBuffer+numBits, GraphBuffer[idx-1]^1 , n);
511 }
512 numBits += n;
513 }
514 n=0;
515 lastval=GraphBuffer[idx];
516 }//end for
517 return numBits;
518}
519// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
520size_t fskdemod(uint8_t rfLen, uint8_t invert)
521{
522 //uint8_t h2l_crossing_value = 6;
523 //uint8_t l2h_crossing_value = 5;
524
525 // if (rfLen==64) //currently only know settings for RF/64 change from default if option entered
526 // {
527 // h2l_crossing_value=8; //or 8 as 64/8 = 8
528 // l2h_crossing_value=6; //or 6.4 as 64/10 = 6.4
529 // }
530 size_t size = GraphTraceLen;
531 // FSK demodulator
532 size = fsk_wave_demod(size);
533 size = aggregate_bits(size,rfLen,192,invert);
534 // size = aggregate_bits(size, h2l_crossing_value, l2h_crossing_value,192, invert); //192=no limit to same values
535 //done messing with GraphBuffer - repaint
536 RepaintGraphWindow();
537 return size;
538}
539uint32_t bytebits_to_byte(int* src, int numbits)
540{
541 uint32_t num = 0;
542 for(int i = 0 ; i < numbits ; i++)
543 {
544 num = (num << 1) | (*src);
545 src++;
546 }
547 return num;
548}
549
550//fsk demod and print binary
e888ed8e 551int CmdFSKrawdemod(const char *Cmd)
b3b70669 552{
553 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
554 //set defaults
555 uint8_t rfLen = 50;
556 uint8_t invert=0;
557 //set options from parameters entered with the command
558 if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
559 rfLen=param_get8(Cmd, 0); //if rfLen option only is used
560 if (rfLen==1){
561 invert=1; //if invert option only is used
562 rfLen = 50;
563 } else if(rfLen==0) rfLen=50;
564 }
565 if (strlen(Cmd)>2) {
566 rfLen=param_get8(Cmd, 0); //if both options are used
567 invert=param_get8(Cmd,1);
568 }
569 PrintAndLog("Args invert: %d \nClock:%d",invert,rfLen);
570
571 size_t size = fskdemod(rfLen,invert);
572
573 PrintAndLog("FSK decoded bitstream:");
574 // Now output the bitstream to the scrollback by line of 16 bits
575 if(size > (7*32)+2) size = (7*32)+2; //only output a max of 7 blocks of 32 bits most tags will have full bit stream inside that sample size
576
577 for (int i = 2; i < (size-16); i+=16) {
578 PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
579 GraphBuffer[i],
580 GraphBuffer[i+1],
581 GraphBuffer[i+2],
582 GraphBuffer[i+3],
583 GraphBuffer[i+4],
584 GraphBuffer[i+5],
585 GraphBuffer[i+6],
586 GraphBuffer[i+7],
587 GraphBuffer[i+8],
588 GraphBuffer[i+9],
589 GraphBuffer[i+10],
590 GraphBuffer[i+11],
591 GraphBuffer[i+12],
592 GraphBuffer[i+13],
593 GraphBuffer[i+14],
594 GraphBuffer[i+15]);
595 }
596 ClearGraph(1);
597 return 0;
598}
599
600int CmdFSKdemodHID(const char *Cmd)
601{
602 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
603 //set defaults
604 uint8_t rfLen = 50;
605 uint8_t invert=0;//param_get8(Cmd, 0);
606 size_t idx=0;
607 uint32_t hi2=0, hi=0, lo=0;
608
609 //get binary from fsk wave
610 size_t size = fskdemod(rfLen,invert);
611
612 // final loop, go over previously decoded fsk data and now manchester decode into usable tag ID
613 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
614 int frame_marker_mask[] = {1,1,1,0,0,0};
615 int numshifts = 0;
616 idx = 0;
617 while( idx + 6 < size) {
618 // search for a start of frame marker
619
620 if ( memcmp(GraphBuffer+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
621 { // frame marker found
622 idx+=6;//sizeof(frame_marker_mask); //size of int is >6
623 while(GraphBuffer[idx] != GraphBuffer[idx+1] && idx < size-2)
624 {
625 // Keep going until next frame marker (or error)
626 // Shift in a bit. Start by shifting high registers
627 hi2 = (hi2<<1)|(hi>>31);
628 hi = (hi<<1)|(lo>>31);
629 //Then, shift in a 0 or one into low
630 if (GraphBuffer[idx] && !GraphBuffer[idx+1]) // 1 0
631 lo=(lo<<1)|0;
632 else // 0 1
633 lo=(lo<<1)|1;
634 numshifts++;
635 idx += 2;
636 }
637
638 //PrintAndLog("Num shifts: %d ", numshifts);
639 // Hopefully, we read a tag and hit upon the next frame marker
640 if(idx + 6 < size)
641 {
642 if ( memcmp(GraphBuffer+(idx), frame_marker_mask, sizeof(frame_marker_mask)) == 0)
643 {
644 if (hi2 != 0){ //extra large HID tags
645 PrintAndLog("TAG ID: %x%08x%08x (%d)",
646 (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
647 }
648 else { //standard HID tags <38 bits
649 //Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
650 uint8_t bitlen = 0;
651 uint32_t fc = 0;
652 uint32_t cardnum = 0;
653 if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
654 uint32_t lo2=0;
655 lo2=(((hi & 15) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
656 uint8_t idx3 = 1;
657 while(lo2>1){ //find last bit set to 1 (format len bit)
658 lo2=lo2>>1;
659 idx3++;
660 }
661 bitlen =idx3+19;
662 fc =0;
663 cardnum=0;
664 if(bitlen==26){
665 cardnum = (lo>>1)&0xFFFF;
666 fc = (lo>>17)&0xFF;
667 }
668 if(bitlen==37){
669 cardnum = (lo>>1)&0x7FFFF;
670 fc = ((hi&0xF)<<12)|(lo>>20);
671 }
672 if(bitlen==34){
673 cardnum = (lo>>1)&0xFFFF;
674 fc= ((hi&1)<<15)|(lo>>17);
675 }
676 if(bitlen==35){
677 cardnum = (lo>>1)&0xFFFFF;
678 fc = ((hi&1)<<11)|(lo>>21);
679 }
680 }
681 else { //if bit 38 is not set then 37 bit format is used
682 bitlen= 37;
683 fc =0;
684 cardnum=0;
685 if(bitlen==37){
686 cardnum = (lo>>1)&0x7FFFF;
687 fc = ((hi&0xF)<<12)|(lo>>20);
688 }
689 }
690
691 PrintAndLog("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
692 (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
693 (unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
694 ClearGraph(1);
695 return 0;
696 }
697 }
698 }
699 // reset
700 hi2 = hi = lo = 0;
701 numshifts = 0;
702 }else
703 {
704 idx++;
705 }
706 }
707 if (idx + sizeof(frame_marker_mask) >= size){
708 PrintAndLog("start bits for hid not found");
709 PrintAndLog("FSK decoded bitstream:");
710 // Now output the bitstream to the scrollback by line of 16 bits
711 if(size > (7*32)+2) size = (7*32)+2; //only output a max of 7 blocks of 32 bits most tags will have full bit stream inside that sample size
e888ed8e 712 printBitStream(GraphBuffer,size);
713 /*
b3b70669 714 for (int i = 2; i < (size-16); i+=16) {
715 PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
716 GraphBuffer[i],
717 GraphBuffer[i+1],
718 GraphBuffer[i+2],
719 GraphBuffer[i+3],
720 GraphBuffer[i+4],
721 GraphBuffer[i+5],
722 GraphBuffer[i+6],
723 GraphBuffer[i+7],
724 GraphBuffer[i+8],
725 GraphBuffer[i+9],
726 GraphBuffer[i+10],
727 GraphBuffer[i+11],
728 GraphBuffer[i+12],
729 GraphBuffer[i+13],
730 GraphBuffer[i+14],
731 GraphBuffer[i+15]);
732 }
e888ed8e 733 */
b3b70669 734 }
735 ClearGraph(1);
736 return 0;
737}
738
739
740int CmdFSKdemodIO(const char *Cmd)
741{
742 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
743 //set defaults
744 uint8_t rfLen = 64;
745 uint8_t invert=1;
746 size_t idx=0;
747 uint8_t testMax=0;
748 //test samples are not just noise
749 if (GraphTraceLen < 64) return 0;
750 for(idx=0;idx<64;idx++){
751 if (testMax<GraphBuffer[idx]) testMax=GraphBuffer[idx];
752 }
753 idx=0;
754 //get full binary from fsk wave
755 size_t size = fskdemod(rfLen,invert);
756
757 //if not just noise
758 //PrintAndLog("testMax %d",testMax);
759 if (testMax>40){
760 //Index map
761 //0 10 20 30 40 50 60
762 //| | | | | | |
763 //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
764 //-----------------------------------------------------------------------------
765 //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
766 //
767 //XSF(version)facility:codeone+codetwo (raw)
768 //Handle the data
769 int mask[] = {0,0,0,0,0,0,0,0,0,1};
770 for( idx=0; idx < (size - 74); idx++) {
771 if ( memcmp(GraphBuffer + idx, mask, sizeof(mask))==0) {
772 //frame marker found
773 if (GraphBuffer[idx+17]==1 && GraphBuffer[idx+26]==1 && GraphBuffer[idx+35]==1 && GraphBuffer[idx+44]==1 && GraphBuffer[idx+53]==1){
774 //confirmed proper separator bits found
775
776 PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx], GraphBuffer[idx+1], GraphBuffer[idx+2], GraphBuffer[idx+3], GraphBuffer[idx+4], GraphBuffer[idx+5], GraphBuffer[idx+6], GraphBuffer[idx+7], GraphBuffer[idx+8]);
777 PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+9], GraphBuffer[idx+10], GraphBuffer[idx+11],GraphBuffer[idx+12],GraphBuffer[idx+13],GraphBuffer[idx+14],GraphBuffer[idx+15],GraphBuffer[idx+16],GraphBuffer[idx+17]);
778 PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+18], GraphBuffer[idx+19], GraphBuffer[idx+20],GraphBuffer[idx+21],GraphBuffer[idx+22],GraphBuffer[idx+23],GraphBuffer[idx+24],GraphBuffer[idx+25],GraphBuffer[idx+26]);
779 PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+27], GraphBuffer[idx+28], GraphBuffer[idx+29],GraphBuffer[idx+30],GraphBuffer[idx+31],GraphBuffer[idx+32],GraphBuffer[idx+33],GraphBuffer[idx+34],GraphBuffer[idx+35]);
780 PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+36], GraphBuffer[idx+37], GraphBuffer[idx+38],GraphBuffer[idx+39],GraphBuffer[idx+40],GraphBuffer[idx+41],GraphBuffer[idx+42],GraphBuffer[idx+43],GraphBuffer[idx+44]);
781 PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+45], GraphBuffer[idx+46], GraphBuffer[idx+47],GraphBuffer[idx+48],GraphBuffer[idx+49],GraphBuffer[idx+50],GraphBuffer[idx+51],GraphBuffer[idx+52],GraphBuffer[idx+53]);
782 PrintAndLog("%d%d%d%d%d%d%d%d %d%d",GraphBuffer[idx+54],GraphBuffer[idx+55],GraphBuffer[idx+56],GraphBuffer[idx+57],GraphBuffer[idx+58],GraphBuffer[idx+59],GraphBuffer[idx+60],GraphBuffer[idx+61],GraphBuffer[idx+62],GraphBuffer[idx+63]);
783
784 uint32_t code = bytebits_to_byte(GraphBuffer+idx,32);
785 uint32_t code2 = bytebits_to_byte(GraphBuffer+idx+32,32);
786 short version = bytebits_to_byte(GraphBuffer+idx+27,8); //14,4
787 uint8_t facilitycode = bytebits_to_byte(GraphBuffer+idx+19,8) ;
788 uint16_t number = (bytebits_to_byte(GraphBuffer+idx+36,8)<<8)|(bytebits_to_byte(GraphBuffer+idx+45,8)); //36,9
789
790 PrintAndLog("XSF(%02d)%02x:%d (%08x%08x)",version,facilitycode,number,code,code2);
791 ClearGraph(1);
792 return 0;
793 } else {
794 PrintAndLog("thought we had a valid tag but did not match format");
795 }
796 }
797 }
798 if (idx >= (size-74)){
799 PrintAndLog("start bits for io prox not found");
800 PrintAndLog("FSK decoded bitstream:");
801 // Now output the bitstream to the scrollback by line of 16 bits
802 if(size > (7*32)+2) size = (7*32)+2; //only output a max of 7 blocks of 32 bits most tags will have full bit stream inside that sample size
e888ed8e 803 printBitStream(GraphBuffer,size);
804 /*
b3b70669 805 for (int i = 2; i < (size-16); i+=16) {
806 PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
807 GraphBuffer[i],
808 GraphBuffer[i+1],
809 GraphBuffer[i+2],
810 GraphBuffer[i+3],
811 GraphBuffer[i+4],
812 GraphBuffer[i+5],
813 GraphBuffer[i+6],
814 GraphBuffer[i+7],
815 GraphBuffer[i+8],
816 GraphBuffer[i+9],
817 GraphBuffer[i+10],
818 GraphBuffer[i+11],
819 GraphBuffer[i+12],
820 GraphBuffer[i+13],
821 GraphBuffer[i+14],
822 GraphBuffer[i+15]);
e888ed8e 823 }
824 */
b3b70669 825 }
826 }
827 ClearGraph(1);
828 return 0;
829}
e888ed8e 830int CmdFSKdemod(const char *Cmd) //old CmdFSKdemod needs updating
7fe9b0b7 831{
832 static const int LowTone[] = {
833 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
834 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
835 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
836 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
837 1, 1, 1, 1, 1, -1, -1, -1, -1, -1
838 };
839 static const int HighTone[] = {
840 1, 1, 1, 1, 1, -1, -1, -1, -1,
841 1, 1, 1, 1, -1, -1, -1, -1,
842 1, 1, 1, 1, -1, -1, -1, -1,
843 1, 1, 1, 1, -1, -1, -1, -1,
844 1, 1, 1, 1, -1, -1, -1, -1,
845 1, 1, 1, 1, -1, -1, -1, -1, -1,
846 };
847
848 int lowLen = sizeof (LowTone) / sizeof (int);
849 int highLen = sizeof (HighTone) / sizeof (int);
b3b70669 850 int convLen = (highLen > lowLen) ? highLen : lowLen; //if highlen > lowLen then highlen else lowlen
7fe9b0b7 851 uint32_t hi = 0, lo = 0;
852
853 int i, j;
854 int minMark = 0, maxMark = 0;
b3b70669 855
7fe9b0b7 856 for (i = 0; i < GraphTraceLen - convLen; ++i) {
857 int lowSum = 0, highSum = 0;
858
859 for (j = 0; j < lowLen; ++j) {
860 lowSum += LowTone[j]*GraphBuffer[i+j];
861 }
862 for (j = 0; j < highLen; ++j) {
863 highSum += HighTone[j] * GraphBuffer[i + j];
864 }
865 lowSum = abs(100 * lowSum / lowLen);
866 highSum = abs(100 * highSum / highLen);
867 GraphBuffer[i] = (highSum << 16) | lowSum;
868 }
869
870 for(i = 0; i < GraphTraceLen - convLen - 16; ++i) {
871 int lowTot = 0, highTot = 0;
872 // 10 and 8 are f_s divided by f_l and f_h, rounded
873 for (j = 0; j < 10; ++j) {
874 lowTot += (GraphBuffer[i+j] & 0xffff);
875 }
876 for (j = 0; j < 8; j++) {
877 highTot += (GraphBuffer[i + j] >> 16);
878 }
879 GraphBuffer[i] = lowTot - highTot;
880 if (GraphBuffer[i] > maxMark) maxMark = GraphBuffer[i];
881 if (GraphBuffer[i] < minMark) minMark = GraphBuffer[i];
882 }
883
884 GraphTraceLen -= (convLen + 16);
885 RepaintGraphWindow();
886
b3b70669 887 // Find bit-sync (3 lo followed by 3 high) (HID ONLY)
7fe9b0b7 888 int max = 0, maxPos = 0;
889 for (i = 0; i < 6000; ++i) {
890 int dec = 0;
891 for (j = 0; j < 3 * lowLen; ++j) {
892 dec -= GraphBuffer[i + j];
893 }
894 for (; j < 3 * (lowLen + highLen ); ++j) {
895 dec += GraphBuffer[i + j];
896 }
897 if (dec > max) {
898 max = dec;
899 maxPos = i;
900 }
901 }
902
903 // place start of bit sync marker in graph
904 GraphBuffer[maxPos] = maxMark;
905 GraphBuffer[maxPos + 1] = minMark;
906
907 maxPos += j;
908
909 // place end of bit sync marker in graph
910 GraphBuffer[maxPos] = maxMark;
911 GraphBuffer[maxPos+1] = minMark;
912
913 PrintAndLog("actual data bits start at sample %d", maxPos);
914 PrintAndLog("length %d/%d", highLen, lowLen);
915
916 uint8_t bits[46];
917 bits[sizeof(bits)-1] = '\0';
918
919 // find bit pairs and manchester decode them
920 for (i = 0; i < arraylen(bits) - 1; ++i) {
921 int dec = 0;
922 for (j = 0; j < lowLen; ++j) {
923 dec -= GraphBuffer[maxPos + j];
924 }
925 for (; j < lowLen + highLen; ++j) {
926 dec += GraphBuffer[maxPos + j];
927 }
928 maxPos += j;
929 // place inter bit marker in graph
930 GraphBuffer[maxPos] = maxMark;
931 GraphBuffer[maxPos + 1] = minMark;
932
933 // hi and lo form a 64 bit pair
934 hi = (hi << 1) | (lo >> 31);
935 lo = (lo << 1);
936 // store decoded bit as binary (in hi/lo) and text (in bits[])
937 if(dec < 0) {
938 bits[i] = '1';
939 lo |= 1;
940 } else {
941 bits[i] = '0';
942 }
943 }
944 PrintAndLog("bits: '%s'", bits);
945 PrintAndLog("hex: %08x %08x", hi, lo);
946 return 0;
947}
e888ed8e 948
7fe9b0b7 949int CmdGrid(const char *Cmd)
950{
951 sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
7ddb9900 952 PlotGridXdefault= PlotGridX;
953 PlotGridYdefault= PlotGridY;
7fe9b0b7 954 RepaintGraphWindow();
955 return 0;
956}
957
958int CmdHexsamples(const char *Cmd)
959{
4961e292 960 int i, j;
7fe9b0b7 961 int requested = 0;
962 int offset = 0;
4961e292 963 char string_buf[25];
964 char* string_ptr = string_buf;
90d74dc2 965 uint8_t got[40000];
4961e292 966
967 sscanf(Cmd, "%i %i", &requested, &offset);
90d74dc2 968
4961e292 969 /* if no args send something */
970 if (requested == 0) {
90d74dc2 971 requested = 8;
972 }
90d74dc2 973 if (offset + requested > sizeof(got)) {
974 PrintAndLog("Tried to read past end of buffer, <bytes> + <offset> > 40000");
4961e292 975 return 0;
976 }
90d74dc2 977
4961e292 978 GetFromBigBuf(got,requested,offset);
90d74dc2 979 WaitForResponse(CMD_ACK,NULL);
980
4961e292 981 i = 0;
982 for (j = 0; j < requested; j++) {
983 i++;
984 string_ptr += sprintf(string_ptr, "%02x ", got[j]);
985 if (i == 8) {
986 *(string_ptr - 1) = '\0'; // remove the trailing space
987 PrintAndLog("%s", string_buf);
988 string_buf[0] = '\0';
989 string_ptr = string_buf;
990 i = 0;
991 }
992 if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes
993 *(string_ptr - 1) = '\0';
994 PrintAndLog("%s", string_buf);
995 string_buf[0] = '\0';
996 }
7fe9b0b7 997 }
998 return 0;
999}
1000
7fe9b0b7 1001int CmdHide(const char *Cmd)
1002{
1003 HideGraphWindow();
1004 return 0;
1005}
1006
1007int CmdHpf(const char *Cmd)
1008{
1009 int i;
1010 int accum = 0;
1011
1012 for (i = 10; i < GraphTraceLen; ++i)
1013 accum += GraphBuffer[i];
1014 accum /= (GraphTraceLen - 10);
1015 for (i = 0; i < GraphTraceLen; ++i)
1016 GraphBuffer[i] -= accum;
1017
1018 RepaintGraphWindow();
1019 return 0;
1020}
1021
8d183c53 1022int CmdSamples(const char *Cmd)
7fe9b0b7 1023{
1024 int cnt = 0;
1025 int n;
90d74dc2 1026 uint8_t got[40000];
1027
7fe9b0b7 1028 n = strtol(Cmd, NULL, 0);
b3b70669 1029 if (n == 0) n = 6000;
90d74dc2 1030 if (n > sizeof(got)) n = sizeof(got);
a2847518 1031
7fe9b0b7 1032 PrintAndLog("Reading %d samples\n", n);
90d74dc2 1033 GetFromBigBuf(got,n,0);
a2847518 1034 WaitForResponse(CMD_ACK,NULL);
90d74dc2 1035 for (int j = 0; j < n; j++) {
a2847518 1036 GraphBuffer[cnt++] = ((int)got[j]) - 128;
7fe9b0b7 1037 }
a2847518 1038
7fe9b0b7 1039 PrintAndLog("Done!\n");
90d74dc2 1040 GraphTraceLen = n;
7fe9b0b7 1041 RepaintGraphWindow();
1042 return 0;
1043}
1044
d6a120a2
MHS
1045int CmdTuneSamples(const char *Cmd)
1046{
1047 int cnt = 0;
1048 int n = 255;
1049 uint8_t got[255];
1050
1051 PrintAndLog("Reading %d samples\n", n);
1052 GetFromBigBuf(got,n,7256); // armsrc/apps.h: #define FREE_BUFFER_OFFSET 7256
1053 WaitForResponse(CMD_ACK,NULL);
1054 for (int j = 0; j < n; j++) {
1055 GraphBuffer[cnt++] = ((int)got[j]) - 128;
1056 }
1057
1058 PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n");
1059 PrintAndLog("\n");
1060 GraphTraceLen = n;
1061 RepaintGraphWindow();
1062 return 0;
1063}
1064
7fe9b0b7 1065int CmdLoad(const char *Cmd)
1066{
c6f1fb9d 1067 FILE *f = fopen(Cmd, "r");
7fe9b0b7 1068 if (!f) {
c6f1fb9d 1069 PrintAndLog("couldn't open '%s'", Cmd);
7fe9b0b7 1070 return 0;
1071 }
1072
1073 GraphTraceLen = 0;
1074 char line[80];
1075 while (fgets(line, sizeof (line), f)) {
1076 GraphBuffer[GraphTraceLen] = atoi(line);
1077 GraphTraceLen++;
1078 }
1079 fclose(f);
1080 PrintAndLog("loaded %d samples", GraphTraceLen);
1081 RepaintGraphWindow();
1082 return 0;
1083}
1084
1085int CmdLtrim(const char *Cmd)
1086{
1087 int ds = atoi(Cmd);
1088
1089 for (int i = ds; i < GraphTraceLen; ++i)
1090 GraphBuffer[i-ds] = GraphBuffer[i];
1091 GraphTraceLen -= ds;
1092
1093 RepaintGraphWindow();
1094 return 0;
1095}
1096
1097/*
1098 * Manchester demodulate a bitstream. The bitstream needs to be already in
1099 * the GraphBuffer as 0 and 1 values
1100 *
1101 * Give the clock rate as argument in order to help the sync - the algorithm
1102 * resyncs at each pulse anyway.
1103 *
1104 * Not optimized by any means, this is the 1st time I'm writing this type of
1105 * routine, feel free to improve...
1106 *
1107 * 1st argument: clock rate (as number of samples per clock rate)
1108 * Typical values can be 64, 32, 128...
1109 */
1110int CmdManchesterDemod(const char *Cmd)
1111{
1112 int i, j, invert= 0;
1113 int bit;
1114 int clock;
fddf220a 1115 int lastval = 0;
7fe9b0b7 1116 int low = 0;
1117 int high = 0;
1118 int hithigh, hitlow, first;
1119 int lc = 0;
1120 int bitidx = 0;
1121 int bit2idx = 0;
1122 int warnings = 0;
1123
1124 /* check if we're inverting output */
c6f1fb9d 1125 if (*Cmd == 'i')
7fe9b0b7 1126 {
1127 PrintAndLog("Inverting output");
1128 invert = 1;
fffad860 1129 ++Cmd;
7fe9b0b7 1130 do
1131 ++Cmd;
1132 while(*Cmd == ' '); // in case a 2nd argument was given
1133 }
1134
1135 /* Holds the decoded bitstream: each clock period contains 2 bits */
1136 /* later simplified to 1 bit after manchester decoding. */
1137 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
1138 /* int BitStream[GraphTraceLen*2/clock+10]; */
1139
1140 /* But it does not work if compiling on WIndows: therefore we just allocate a */
1141 /* large array */
90e278d3 1142 uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0};
7fe9b0b7 1143
1144 /* Detect high and lows */
1145 for (i = 0; i < GraphTraceLen; i++)
1146 {
1147 if (GraphBuffer[i] > high)
1148 high = GraphBuffer[i];
1149 else if (GraphBuffer[i] < low)
1150 low = GraphBuffer[i];
1151 }
1152
1153 /* Get our clock */
1154 clock = GetClock(Cmd, high, 1);
1155
1156 int tolerance = clock/4;
1157
1158 /* Detect first transition */
1159 /* Lo-Hi (arbitrary) */
1160 /* skip to the first high */
1161 for (i= 0; i < GraphTraceLen; i++)
1162 if (GraphBuffer[i] == high)
1163 break;
1164 /* now look for the first low */
1165 for (; i < GraphTraceLen; i++)
1166 {
1167 if (GraphBuffer[i] == low)
1168 {
1169 lastval = i;
1170 break;
1171 }
1172 }
1173
1174 /* If we're not working with 1/0s, demod based off clock */
1175 if (high != 1)
1176 {
1177 bit = 0; /* We assume the 1st bit is zero, it may not be
1178 * the case: this routine (I think) has an init problem.
1179 * Ed.
1180 */
1181 for (; i < (int)(GraphTraceLen / clock); i++)
1182 {
1183 hithigh = 0;
1184 hitlow = 0;
1185 first = 1;
1186
1187 /* Find out if we hit both high and low peaks */
1188 for (j = 0; j < clock; j++)
1189 {
1190 if (GraphBuffer[(i * clock) + j] == high)
1191 hithigh = 1;
1192 else if (GraphBuffer[(i * clock) + j] == low)
1193 hitlow = 1;
1194
1195 /* it doesn't count if it's the first part of our read
1196 because it's really just trailing from the last sequence */
1197 if (first && (hithigh || hitlow))
1198 hithigh = hitlow = 0;
1199 else
1200 first = 0;
1201
1202 if (hithigh && hitlow)
1203 break;
1204 }
1205
1206 /* If we didn't hit both high and low peaks, we had a bit transition */
1207 if (!hithigh || !hitlow)
1208 bit ^= 1;
1209
1210 BitStream[bit2idx++] = bit ^ invert;
1211 }
1212 }
1213
1214 /* standard 1/0 bitstream */
1215 else
1216 {
1217
1218 /* Then detect duration between 2 successive transitions */
1219 for (bitidx = 1; i < GraphTraceLen; i++)
1220 {
1221 if (GraphBuffer[i-1] != GraphBuffer[i])
1222 {
b3b70669 1223 lc = i-lastval;
1224 lastval = i;
1225
1226 // Error check: if bitidx becomes too large, we do not
1227 // have a Manchester encoded bitstream or the clock is really
1228 // wrong!
1229 if (bitidx > (GraphTraceLen*2/clock+8) ) {
1230 PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
1231 return 0;
1232 }
1233 // Then switch depending on lc length:
1234 // Tolerance is 1/4 of clock rate (arbitrary)
1235 if (abs(lc-clock/2) < tolerance) {
1236 // Short pulse : either "1" or "0"
1237 BitStream[bitidx++]=GraphBuffer[i-1];
1238 } else if (abs(lc-clock) < tolerance) {
1239 // Long pulse: either "11" or "00"
1240 BitStream[bitidx++]=GraphBuffer[i-1];
1241 BitStream[bitidx++]=GraphBuffer[i-1];
1242 } else {
7fe9b0b7 1243 // Error
1244 warnings++;
b3b70669 1245 PrintAndLog("Warning: Manchester decode error for pulse width detection.");
1246 PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
7fe9b0b7 1247
1248 if (warnings > 10)
1249 {
1250 PrintAndLog("Error: too many detection errors, aborting.");
1251 return 0;
1252 }
1253 }
1254 }
1255 }
1256
1257 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
1258 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
1259 // to stop output at the final bitidx2 value, not bitidx
1260 for (i = 0; i < bitidx; i += 2) {
1261 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
1262 BitStream[bit2idx++] = 1 ^ invert;
b3b70669 1263 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
1264 BitStream[bit2idx++] = 0 ^ invert;
1265 } else {
1266 // We cannot end up in this state, this means we are unsynchronized,
1267 // move up 1 bit:
1268 i++;
7fe9b0b7 1269 warnings++;
b3b70669 1270 PrintAndLog("Unsynchronized, resync...");
1271 PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
7fe9b0b7 1272
1273 if (warnings > 10)
1274 {
1275 PrintAndLog("Error: too many decode errors, aborting.");
1276 return 0;
1277 }
1278 }
1279 }
1280 }
1281
1282 PrintAndLog("Manchester decoded bitstream");
1283 // Now output the bitstream to the scrollback by line of 16 bits
1284 for (i = 0; i < (bit2idx-16); i+=16) {
1285 PrintAndLog("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
1286 BitStream[i],
1287 BitStream[i+1],
1288 BitStream[i+2],
1289 BitStream[i+3],
1290 BitStream[i+4],
1291 BitStream[i+5],
1292 BitStream[i+6],
1293 BitStream[i+7],
1294 BitStream[i+8],
1295 BitStream[i+9],
1296 BitStream[i+10],
1297 BitStream[i+11],
1298 BitStream[i+12],
1299 BitStream[i+13],
1300 BitStream[i+14],
1301 BitStream[i+15]);
1302 }
1303 return 0;
1304}
1305
1306/* Modulate our data into manchester */
1307int CmdManchesterMod(const char *Cmd)
1308{
1309 int i, j;
1310 int clock;
1311 int bit, lastbit, wave;
1312
1313 /* Get our clock */
1314 clock = GetClock(Cmd, 0, 1);
1315
1316 wave = 0;
1317 lastbit = 1;
1318 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
1319 {
1320 bit = GraphBuffer[i * clock] ^ 1;
1321
1322 for (j = 0; j < (int)(clock/2); j++)
1323 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
1324 for (j = (int)(clock/2); j < clock; j++)
1325 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
1326
1327 /* Keep track of how we start our wave and if we changed or not this time */
1328 wave ^= bit ^ lastbit;
1329 lastbit = bit;
1330 }
1331
1332 RepaintGraphWindow();
1333 return 0;
1334}
1335
1336int CmdNorm(const char *Cmd)
1337{
1338 int i;
1339 int max = INT_MIN, min = INT_MAX;
1340
1341 for (i = 10; i < GraphTraceLen; ++i) {
1342 if (GraphBuffer[i] > max)
1343 max = GraphBuffer[i];
1344 if (GraphBuffer[i] < min)
1345 min = GraphBuffer[i];
1346 }
1347
1348 if (max != min) {
1349 for (i = 0; i < GraphTraceLen; ++i) {
1350 GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 1000 /
1351 (max - min);
1352 }
1353 }
1354 RepaintGraphWindow();
1355 return 0;
1356}
1357
1358int CmdPlot(const char *Cmd)
1359{
1360 ShowGraphWindow();
1361 return 0;
1362}
1363
1364int CmdSave(const char *Cmd)
1365{
1366 FILE *f = fopen(Cmd, "w");
1367 if(!f) {
1368 PrintAndLog("couldn't open '%s'", Cmd);
1369 return 0;
1370 }
1371 int i;
1372 for (i = 0; i < GraphTraceLen; i++) {
1373 fprintf(f, "%d\n", GraphBuffer[i]);
1374 }
1375 fclose(f);
1376 PrintAndLog("saved to '%s'", Cmd);
1377 return 0;
1378}
1379
1380int CmdScale(const char *Cmd)
1381{
1382 CursorScaleFactor = atoi(Cmd);
1383 if (CursorScaleFactor == 0) {
1384 PrintAndLog("bad, can't have zero scale");
1385 CursorScaleFactor = 1;
1386 }
1387 RepaintGraphWindow();
1388 return 0;
1389}
1390
1391int CmdThreshold(const char *Cmd)
1392{
1393 int threshold = atoi(Cmd);
1394
1395 for (int i = 0; i < GraphTraceLen; ++i) {
1396 if (GraphBuffer[i] >= threshold)
1397 GraphBuffer[i] = 1;
1398 else
7bb9d33e 1399 GraphBuffer[i] = -1;
7fe9b0b7 1400 }
1401 RepaintGraphWindow();
1402 return 0;
1403}
1404
d51b2eda
MHS
1405int CmdDirectionalThreshold(const char *Cmd)
1406{
1407 int8_t upThres = param_get8(Cmd, 0);
1408 int8_t downThres = param_get8(Cmd, 1);
1409
1410 printf("Applying Up Threshold: %d, Down Threshold: %d\n", upThres, downThres);
1411
1412 int lastValue = GraphBuffer[0];
1413 GraphBuffer[0] = 0; // Will be changed at the end, but init 0 as we adjust to last samples value if no threshold kicks in.
1414
1415 for (int i = 1; i < GraphTraceLen; ++i) {
1416 // Apply first threshold to samples heading up
1417 if (GraphBuffer[i] >= upThres && GraphBuffer[i] > lastValue)
1418 {
1419 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
1420 GraphBuffer[i] = 1;
1421 }
1422 // Apply second threshold to samples heading down
1423 else if (GraphBuffer[i] <= downThres && GraphBuffer[i] < lastValue)
1424 {
1425 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
1426 GraphBuffer[i] = -1;
1427 }
1428 else
1429 {
1430 lastValue = GraphBuffer[i]; // Buffer last value as we overwrite it.
1431 GraphBuffer[i] = GraphBuffer[i-1];
1432
1433 }
1434 }
1435 GraphBuffer[0] = GraphBuffer[1]; // Aline with first edited sample.
1436 RepaintGraphWindow();
1437 return 0;
1438}
1439
7fe9b0b7 1440int CmdZerocrossings(const char *Cmd)
1441{
1442 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1443 CmdHpf("");
1444
1445 int sign = 1;
1446 int zc = 0;
1447 int lastZc = 0;
1448
1449 for (int i = 0; i < GraphTraceLen; ++i) {
1450 if (GraphBuffer[i] * sign >= 0) {
1451 // No change in sign, reproduce the previous sample count.
1452 zc++;
1453 GraphBuffer[i] = lastZc;
1454 } else {
1455 // Change in sign, reset the sample count.
1456 sign = -sign;
1457 GraphBuffer[i] = lastZc;
1458 if (sign > 0) {
1459 lastZc = zc;
1460 zc = 0;
1461 }
1462 }
1463 }
1464
1465 RepaintGraphWindow();
1466 return 0;
1467}
1468
1469static command_t CommandTable[] =
1470{
1471 {"help", CmdHelp, 1, "This help"},
1472 {"amp", CmdAmp, 1, "Amplify peaks"},
57c69556 1473 {"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
e888ed8e 1474 {"askrawdemod", Cmdaskrawdemod, 1, "[clock] [invert<0 or 1>] -- Attempt to demodulate simple ASK tags and output binary (args optional-defaults='64 0'"},
7fe9b0b7 1475 {"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
1476 {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
1477 {"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
1478 {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
1479 {"dec", CmdDec, 1, "Decimate samples"},
1480 {"detectclock", CmdDetectClockRate, 1, "Detect clock rate"},
e888ed8e 1481 {"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"},
1482 {"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate graph window as a HID FSK using raw"},
1483 {"fskiodemod", CmdFSKdemodIO, 1, "Demodulate graph window as an IO Prox FSK using raw"},
1484 {"fskrawdemod", CmdFSKrawdemod, 1, "[clock rate] [invert] Demodulate graph window from FSK to binary (clock = 64 or 50)(invert = 1 or 0)"},
7fe9b0b7 1485 {"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
90d74dc2 1486 {"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
7fe9b0b7 1487 {"hide", CmdHide, 1, "Hide graph window"},
1488 {"hpf", CmdHpf, 1, "Remove DC offset from trace"},
7fe9b0b7 1489 {"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
1490 {"ltrim", CmdLtrim, 1, "<samples> -- Trim samples from left of trace"},
1491 {"mandemod", CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
1492 {"manmod", CmdManchesterMod, 1, "[clock rate] -- Manchester modulate a binary stream"},
1493 {"norm", CmdNorm, 1, "Normalize max/min to +/-500"},
7ddb9900 1494 {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
90d74dc2 1495 {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window"},
d6a120a2 1496 {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"},
7fe9b0b7 1497 {"save", CmdSave, 1, "<filename> -- Save trace (from graph window)"},
1498 {"scale", CmdScale, 1, "<int> -- Set cursor display scale"},
dbf444a1 1499 {"threshold", CmdThreshold, 1, "<threshold> -- Maximize/minimize every value in the graph window depending on threshold"},
7fe9b0b7 1500 {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"},
d51b2eda 1501 {"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
7fe9b0b7 1502 {NULL, NULL, 0, NULL}
1503};
1504
1505int CmdData(const char *Cmd)
1506{
1507 CmdsParse(CommandTable, Cmd);
1508 return 0;
1509}
1510
1511int CmdHelp(const char *Cmd)
1512{
1513 CmdsHelp(CommandTable);
1514 return 0;
1515}
Impressum, Datenschutz