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