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