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