Merge pull request #1331 from Guilhem7/master
[RRG-proxmark3.git] / armsrc / lfsampling.c
blobed65fcb9b8f52c8cffbffcab5a6d88e2ed44a863
1 //-----------------------------------------------------------------------------
2 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
3 // at your option, any later version. See the LICENSE.txt file for the text of
4 // the license.
5 //-----------------------------------------------------------------------------
6 // Miscellaneous routines for low frequency sampling.
7 //-----------------------------------------------------------------------------
9 #include "lfsampling.h"
11 #include "proxmark3_arm.h"
12 #include "BigBuf.h"
13 #include "fpgaloader.h"
14 #include "ticks.h"
15 #include "dbprint.h"
16 #include "util.h"
17 #include "lfdemod.h"
18 #include "string.h" // memset
19 #include "appmain.h" // print stack
22 Default LF config is set to:
23 decimation = 1 (we keep 1 out of 1 samples)
24 bits_per_sample = 8
25 averaging = YES
26 divisor = 95 (125kHz)
27 trigger_threshold = 0
28 samples_to_skip = 0
29 verbose = YES
31 static sample_config config = { 1, 8, 1, LF_DIVISOR_125, 0, 0, 1} ;
33 // Holds bit packed struct of samples.
34 static BitstreamOut data = {0, 0, 0};
36 // internal struct to keep track of samples gathered
37 static sampling_t samples = {0, 0, 0, 0};
39 void printLFConfig(void) {
40 uint32_t d = config.divisor;
41 DbpString(_CYAN_("LF Sampling config"));
42 Dbprintf(" [q] divisor............. %d ( "_GREEN_("%d.%02d kHz")" )", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
43 Dbprintf(" [b] bits per sample..... %d", config.bits_per_sample);
44 Dbprintf(" [d] decimation.......... %d", config.decimation);
45 Dbprintf(" [a] averaging........... %s", (config.averaging) ? "yes" : "no");
46 Dbprintf(" [t] trigger threshold... %d", config.trigger_threshold);
47 Dbprintf(" [s] samples to skip..... %d ", config.samples_to_skip);
49 DbpString(_CYAN_("LF Sampling Stack"));
50 print_stack_usage();
53 void printSamples(void) {
54 DbpString(_CYAN_("LF Sampling memory usage"));
55 // Dbprintf(" decimation counter...%d", samples.dec_counter);
56 // Dbprintf(" sum..................%u", samples.sum);
57 Dbprintf(" counter.............. " _YELLOW_("%u"), samples.counter);
58 Dbprintf(" total saved.......... " _YELLOW_("%u"), samples.total_saved);
59 print_stack_usage();
62 /**
63 * Called from the USB-handler to set the sampling configuration
64 * The sampling config is used for standard reading and sniffing.
66 * Other functions may read samples and ignore the sampling config,
67 * such as functions to read the UID from a prox tag or similar.
69 * Values set to '-1' implies no change
70 * @brief setSamplingConfig
71 * @param sc
73 void setSamplingConfig(sample_config *sc) {
75 // decimation (1-8) how many bits of adc sample value to save
76 if (sc->decimation > 0 && sc->decimation < 9)
77 config.decimation = sc->decimation;
79 // bits per sample (1-8)
80 if (sc->bits_per_sample > 0 && sc->bits_per_sample < 9)
81 config.bits_per_sample = sc->bits_per_sample;
84 if (sc->averaging > -1)
85 config.averaging = (sc->averaging > 0) ? 1 : 0;
87 // Frequency divisor (19 - 255)
88 if (sc->divisor > 18 && sc->divisor < 256)
89 config.divisor = sc->divisor;
91 // Start saving samples when adc value larger than trigger_threshold
92 if (sc->trigger_threshold > -1)
93 config.trigger_threshold = sc->trigger_threshold;
95 // Skip n adc samples before saving
96 if (sc->samples_to_skip > -1)
97 config.samples_to_skip = sc->samples_to_skip;
99 if (sc->verbose)
100 printLFConfig();
103 sample_config *getSamplingConfig(void) {
104 return &config;
108 * @brief Pushes bit onto the stream
109 * @param stream
110 * @param bit
112 static void pushBit(BitstreamOut *stream, uint8_t bit) {
113 int bytepos = stream->position >> 3; // divide by 8
114 int bitpos = stream->position & 7;
115 *(stream->buffer + bytepos) &= ~(1 << (7 - bitpos));
116 *(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos);
117 stream->position++;
118 stream->numbits++;
121 void initSampleBuffer(uint32_t *sample_size) {
122 initSampleBufferEx(sample_size, false);
125 void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) {
126 if (sample_size == NULL) {
127 Dbprintf("initSampleBufferEx, param NULL");
128 return;
130 BigBuf_free_keep_EM();
132 // We can't erase the buffer now, it would drastically delay the acquisition
133 if (use_malloc) {
135 if (*sample_size == 0) {
136 *sample_size = BigBuf_max_traceLen();
137 data.buffer = BigBuf_get_addr();
138 } else {
139 *sample_size = MIN(*sample_size, BigBuf_max_traceLen());
140 data.buffer = BigBuf_malloc(*sample_size);
143 } else {
144 if (*sample_size == 0) {
145 *sample_size = BigBuf_max_traceLen();
146 } else {
147 *sample_size = MIN(*sample_size, BigBuf_max_traceLen());
149 data.buffer = BigBuf_get_addr();
153 samples.dec_counter = 0;
154 samples.sum = 0;
155 samples.counter = *sample_size;
156 samples.total_saved = 0;
159 uint32_t getSampleCounter(void) {
160 return samples.total_saved;
163 void logSampleSimple(uint8_t sample) {
164 logSample(sample, config.decimation, config.bits_per_sample, config.averaging);
167 void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) {
169 if (!data.buffer) return;
171 // keep track of total gather samples regardless how many was discarded.
172 if (samples.counter-- == 0) return;
174 if (bits_per_sample == 0) bits_per_sample = 1;
175 if (bits_per_sample > 8) bits_per_sample = 8;
176 if (decimation == 0) decimation = 1;
178 if (avg) {
179 samples.sum += sample;
182 // check decimation
183 if (decimation > 1) {
184 samples.dec_counter++;
186 if (samples.dec_counter < decimation) return;
188 samples.dec_counter = 0;
191 // averaging
192 if (avg && decimation > 1) {
193 sample = samples.sum / decimation;
194 samples.sum = 0;
197 // store the sample
198 samples.total_saved++;
200 if (bits_per_sample == 8) {
202 data.buffer[samples.total_saved - 1] = sample;
204 // add number of bits.
205 data.numbits = samples.total_saved << 3;
207 } else {
208 pushBit(&data, sample & 0x80);
209 if (bits_per_sample > 1) pushBit(&data, sample & 0x40);
210 if (bits_per_sample > 2) pushBit(&data, sample & 0x20);
211 if (bits_per_sample > 3) pushBit(&data, sample & 0x10);
212 if (bits_per_sample > 4) pushBit(&data, sample & 0x08);
213 if (bits_per_sample > 5) pushBit(&data, sample & 0x04);
214 if (bits_per_sample > 6) pushBit(&data, sample & 0x02);
219 * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
220 * if not already loaded, sets divisor and starts up the antenna.
221 * @param divisor : 1, 88> 255 or negative ==> 134.8 kHz
222 * 0 or 95 ==> 125 kHz
225 void LFSetupFPGAForADC(int divisor, bool reader_field) {
226 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
227 if ((divisor == 1) || (divisor < 0) || (divisor > 255))
228 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz
229 else if (divisor == 0)
230 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
231 else
232 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
234 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (reader_field ? FPGA_LF_ADC_READER_FIELD : 0));
236 // Connect the A/D to the peak-detected low-frequency path.
237 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
239 // Now set up the SSC to get the ADC samples that are now streaming at us.
240 FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
242 // start a 1.5ticks is 1us
243 StartTicks();
245 // 50ms for the resonant antenna to settle.
246 if (reader_field) {
247 WaitMS(50);
248 } else {
249 WaitMS(1);
254 * Does the sample acquisition. If threshold is specified, the actual sampling
255 * is not commenced until the threshold has been reached.
256 * This method implements decimation and quantization in order to
257 * be able to provide longer sample traces.
258 * Uses the following global settings:
259 * @param decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc.
260 * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample.
261 * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample
262 * value that will be used is the average value of the three samples.
263 * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set
264 * to -1 to ignore threshold.
265 * @param verbose - is true, dbprints the status, else no outputs
266 * @return the number of bits occupied by the samples.
268 uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold,
269 bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip) {
271 initSampleBuffer(&sample_size);
273 if (DBGLEVEL >= DBG_DEBUG) {
274 printSamples();
277 bool trigger_hit = false;
278 uint32_t cancel_counter = 0;
279 int16_t checked = 0;
281 while (BUTTON_PRESS() == false) {
283 // only every 4000th times, in order to save time when collecting samples.
284 // interruptible only when logging not yet triggered
285 if ((checked >= 4000) && trigger_hit == false) {
286 if (data_available()) {
287 checked = -1;
288 break;
289 } else {
290 checked = 0;
293 ++checked;
295 WDT_HIT();
297 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
298 LED_D_ON();
301 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
302 volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
304 // Test point 8 (TP8) can be used to trigger oscilloscope
305 LED_D_OFF();
307 // threshold either high or low values 128 = center 0. if trigger = 178
308 if (trigger_hit == false) {
309 if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
310 if (cancel_after > 0) {
311 cancel_counter++;
312 if (cancel_after == cancel_counter)
313 break;
315 continue;
319 trigger_hit = true;
321 if (samples_to_skip > 0) {
322 samples_to_skip--;
323 continue;
326 logSample(sample, decimation, bits_per_sample, avg);
328 if (samples.total_saved >= sample_size) break;
332 if (verbose) {
333 if (checked == -1) {
334 Dbprintf("lf sampling aborted");
335 } else if ((cancel_counter == cancel_after) && (cancel_after > 0)) {
336 Dbprintf("lf sampling cancelled after %u", cancel_counter);
339 Dbprintf("Done, saved " _YELLOW_("%d")" out of " _YELLOW_("%d")" seen samples at " _YELLOW_("%d")" bits/sample", samples.total_saved, samples.counter, bits_per_sample);
342 // Ensure that DC offset removal and noise check is performed for any device-side processing
343 removeSignalOffset(data.buffer, samples.total_saved);
344 computeSignalProperties(data.buffer, samples.total_saved);
345 return data.numbits;
348 * @brief Does sample acquisition, ignoring the config values set in the sample_config.
349 * This method is typically used by tag-specific readers who just wants to read the samples
350 * the normal way
351 * @param trigger_threshold
352 * @param verbose
353 * @return number of bits sampled
355 uint32_t DoAcquisition_default(int trigger_threshold, bool verbose) {
356 return DoAcquisition(1, 8, 0, trigger_threshold, verbose, 0, 0, 0);
358 uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size) {
359 return DoAcquisition(config.decimation
360 , config.bits_per_sample
361 , config.averaging
362 , config.trigger_threshold
363 , verbose
364 , sample_size
365 , 0 // cancel_after
366 , config.samples_to_skip);
369 uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after) {
370 return DoAcquisition(config.decimation
371 , config.bits_per_sample
372 , config.averaging
373 , trigger_threshold
374 , verbose
375 , sample_size
376 , cancel_after
377 , 0); // samples to skip
380 static uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) {
381 if (verbose)
382 printLFConfig();
384 LFSetupFPGAForADC(config.divisor, reader_field);
385 uint32_t ret = DoAcquisition_config(verbose, sample_size);
386 StopTicks();
387 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
388 return ret;
392 * Initializes the FPGA for reader-mode (field on), and acquires the samples.
393 * @return number of bits sampled
395 uint32_t SampleLF(bool verbose, uint32_t sample_size) {
396 BigBuf_Clear_ext(false);
397 return ReadLF(true, verbose, sample_size);
400 * Initializes the FPGA for sniffer-mode (field off), and acquires the samples.
401 * @return number of bits sampled
403 uint32_t SniffLF(bool verbose, uint32_t sample_size) {
404 BigBuf_Clear_ext(false);
405 return ReadLF(false, verbose, sample_size);
409 * acquisition of T55x7 LF signal. Similar to other LF, but adjusted with @marshmellows thresholds
410 * the data is collected in BigBuf.
412 void doT55x7Acquisition(size_t sample_size) {
414 #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
415 #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
416 #define T55xx_READ_TOL 5
418 uint8_t *dest = BigBuf_get_addr();
419 uint16_t bufsize = BigBuf_max_traceLen();
421 if (bufsize > sample_size)
422 bufsize = sample_size;
424 uint8_t lastSample = 0;
425 uint16_t i = 0, skipCnt = 0;
426 bool startFound = false;
427 bool highFound = false;
428 bool lowFound = false;
430 uint16_t checker = 0;
432 if (DBGLEVEL >= DBG_DEBUG) {
433 Dbprintf("doT55x7Acquisition - after init");
434 print_stack_usage();
437 while (skipCnt < 1000 && (i < bufsize)) {
439 if (BUTTON_PRESS())
440 break;
442 if (checker == 4000) {
443 if (data_available())
444 break;
445 else
446 checker = 0;
447 } else {
448 ++checker;
451 WDT_HIT();
453 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
454 LED_D_ON();
457 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
458 volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
459 LED_D_OFF();
461 // skip until the first high sample above threshold
462 if (!startFound && sample > T55xx_READ_UPPER_THRESHOLD) {
463 highFound = true;
464 } else if (!highFound) {
465 skipCnt++;
466 continue;
468 // skip until the first low sample below threshold
469 if (!startFound && sample < T55xx_READ_LOWER_THRESHOLD) {
470 lastSample = sample;
471 lowFound = true;
472 } else if (!lowFound) {
473 skipCnt++;
474 continue;
477 // skip until first high samples begin to change
478 if (startFound || sample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) {
479 // if just found start - recover last sample
480 if (!startFound) {
481 dest[i++] = lastSample;
482 startFound = true;
484 // collect samples
485 dest[i++] = sample;
491 * acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384
492 * and is Manchester?, we directly gather the manchester data into bigbuff
495 #define COTAG_T1 384
496 #define COTAG_T2 (COTAG_T1 >> 1)
497 #define COTAG_ONE_THRESHOLD 127+5
498 #define COTAG_ZERO_THRESHOLD 127-5
499 #ifndef COTAG_BITS
500 #define COTAG_BITS 264
501 #endif
502 void doCotagAcquisition(void) {
504 uint16_t bufsize = BigBuf_max_traceLen();
505 uint8_t *dest = BigBuf_malloc(bufsize);
507 dest[0] = 0;
509 bool firsthigh = false, firstlow = false;
510 uint16_t i = 0, noise_counter = 0;
512 uint16_t checker = 0;
514 while ((i < bufsize - 1) && (noise_counter < COTAG_T1 << 1)) {
516 if (BUTTON_PRESS())
517 break;
519 if (checker == 4000) {
520 if (data_available())
521 break;
522 else
523 checker = 0;
524 } else {
525 ++checker;
528 WDT_HIT();
530 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
532 volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
534 // find first peak
535 if (firsthigh == false) {
536 if (sample < COTAG_ONE_THRESHOLD) {
537 noise_counter++;
538 continue;
541 noise_counter = 0;
542 firsthigh = true;
545 if (firstlow == false) {
546 if (sample > COTAG_ZERO_THRESHOLD) {
547 noise_counter++;
548 continue;
551 noise_counter = 0;
552 firstlow = true;
555 ++i;
556 if (sample > COTAG_ONE_THRESHOLD) {
557 dest[i] = 255;
558 } else if (sample < COTAG_ZERO_THRESHOLD) {
559 dest[i] = 0;
560 } else {
561 dest[i] = dest[i - 1];
566 // Ensure that DC offset removal and noise check is performed for any device-side processing
567 removeSignalOffset(dest, i);
568 computeSignalProperties(dest, i);
571 uint16_t doCotagAcquisitionManchester(uint8_t *dest, uint16_t destlen) {
573 if (dest == NULL)
574 return 0;
576 dest[0] = 0;
578 bool firsthigh = false, firstlow = false;
579 uint8_t curr = 0, prev = 0;
580 uint16_t i = 0;
581 uint16_t period = 0, checker = 0;
583 while ((i < destlen) && BUTTON_PRESS() == false) {
585 WDT_HIT();
587 if (checker == 4000) {
588 if (data_available())
589 break;
590 else
591 checker = 0;
592 } else {
593 ++checker;
597 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
598 volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
600 // find first peak
601 if (firsthigh == false) {
602 if (sample < COTAG_ONE_THRESHOLD) {
603 continue;
605 firsthigh = true;
608 if (firstlow == false) {
609 if (sample > COTAG_ZERO_THRESHOLD) {
610 continue;
612 firstlow = true;
615 // set sample 255, 0, or previous
616 if (sample > COTAG_ONE_THRESHOLD) {
617 prev = curr;
618 curr = 1;
619 } else if (sample < COTAG_ZERO_THRESHOLD) {
620 prev = curr;
621 curr = 0;
622 } else {
623 curr = prev;
626 // full T1 periods,
627 if (period > 0) {
628 --period;
629 continue;
632 dest[i] = curr;
633 ++i;
634 period = COTAG_T1;
638 return i;