1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Miscellaneous routines for low frequency sampling.
17 //-----------------------------------------------------------------------------
19 #include "lfsampling.h"
21 #include "proxmark3_arm.h"
23 #include "fpgaloader.h"
28 #include "string.h" // memset
29 #include "appmain.h" // print stack
30 #include "usb_cdc.h" // real-time sampling
33 Default LF config is set to:
34 decimation = 1 (we keep 1 out of 1 samples)
43 static const sample_config def_config
= {
47 .divisor
= LF_DIVISOR_125
,
48 .trigger_threshold
= 0,
53 static sample_config config
= { 1, 8, 1, LF_DIVISOR_125
, 0, 0, true} ;
55 // Holds bit packed struct of samples.
56 static BitstreamOut_t data
= {0, 0, 0};
58 // internal struct to keep track of samples gathered
59 static sampling_t samples
= {0, 0, 0, 0};
61 void printLFConfig(void) {
62 uint32_t d
= config
.divisor
;
63 DbpString(_CYAN_("LF Sampling config"));
64 Dbprintf(" [q] divisor............. %d ( "_GREEN_("%d.%02d kHz")" )", d
, 12000 / (d
+ 1), ((1200000 + (d
+ 1) / 2) / (d
+ 1)) - ((12000 / (d
+ 1)) * 100));
65 Dbprintf(" [b] bits per sample..... %d", config
.bits_per_sample
);
66 Dbprintf(" [d] decimation.......... %d", config
.decimation
);
67 Dbprintf(" [a] averaging........... %s", (config
.averaging
) ? "yes" : "no");
68 Dbprintf(" [t] trigger threshold... %d", config
.trigger_threshold
);
69 Dbprintf(" [s] samples to skip..... %d ", config
.samples_to_skip
);
73 void printSamples(void) {
74 DbpString(_CYAN_("LF Sampling memory usage"));
75 // Dbprintf(" decimation counter...%d", samples.dec_counter);
76 // Dbprintf(" sum..................%u", samples.sum);
77 Dbprintf(" counter.............. " _YELLOW_("%u"), samples
.counter
);
78 Dbprintf(" total saved.......... " _YELLOW_("%u"), samples
.total_saved
);
83 void setDefaultSamplingConfig(void) {
84 setSamplingConfig(&def_config
);
88 * Called from the USB-handler to set the sampling configuration
89 * The sampling config is used for standard reading and sniffing.
91 * Other functions may read samples and ignore the sampling config,
92 * such as functions to read the UID from a prox tag or similar.
94 * Values set to '-1' implies no change
95 * @brief setSamplingConfig
98 void setSamplingConfig(const sample_config
*sc
) {
100 // decimation (1-8) how many bits of adc sample value to save
101 if (sc
->decimation
> 0 && sc
->decimation
< 9)
102 config
.decimation
= sc
->decimation
;
104 // bits per sample (1-8)
105 if (sc
->bits_per_sample
> 0 && sc
->bits_per_sample
< 9)
106 config
.bits_per_sample
= sc
->bits_per_sample
;
109 if (sc
->averaging
> -1)
110 config
.averaging
= (sc
->averaging
> 0) ? 1 : 0;
112 // Frequency divisor (19 - 255)
113 if (sc
->divisor
> 18 && sc
->divisor
< 256)
114 config
.divisor
= sc
->divisor
;
116 // Start saving samples when adc value larger than trigger_threshold
117 if (sc
->trigger_threshold
> -1)
118 config
.trigger_threshold
= sc
->trigger_threshold
;
120 // Skip n adc samples before saving
121 if (sc
->samples_to_skip
> -1)
122 config
.samples_to_skip
= sc
->samples_to_skip
;
128 sample_config
*getSamplingConfig(void) {
132 void initSampleBuffer(uint32_t *sample_size
) {
133 initSampleBufferEx(sample_size
, false);
136 void initSampleBufferEx(uint32_t *sample_size
, bool use_malloc
) {
138 if (sample_size
== NULL
) {
142 BigBuf_free_keep_EM();
144 // We can't erase the buffer now, it would drastically delay the acquisition
147 if (*sample_size
== 0) {
148 *sample_size
= BigBuf_max_traceLen();
149 data
.buffer
= BigBuf_get_addr();
151 *sample_size
= MIN(*sample_size
, BigBuf_max_traceLen());
152 data
.buffer
= BigBuf_malloc(*sample_size
);
156 if (*sample_size
== 0) {
157 *sample_size
= BigBuf_max_traceLen();
159 *sample_size
= MIN(*sample_size
, BigBuf_max_traceLen());
161 data
.buffer
= BigBuf_get_addr();
169 samples
.dec_counter
= 0;
171 samples
.counter
= *sample_size
;
172 samples
.total_saved
= 0;
175 uint32_t getSampleCounter(void) {
176 return samples
.total_saved
;
179 void logSampleSimple(uint8_t sample
) {
180 logSample(sample
, config
.decimation
, config
.bits_per_sample
, config
.averaging
);
183 void logSample(uint8_t sample
, uint8_t decimation
, uint8_t bits_per_sample
, bool avg
) {
189 // keep track of total gather samples regardless how many was discarded.
190 if (samples
.counter
-- == 0) {
194 if (bits_per_sample
== 0) {
198 if (bits_per_sample
> 8) {
202 if (decimation
== 0) {
207 samples
.sum
+= sample
;
211 if (decimation
> 1) {
212 samples
.dec_counter
++;
214 if (samples
.dec_counter
< decimation
) {
218 samples
.dec_counter
= 0;
222 if (avg
&& decimation
> 1) {
223 sample
= samples
.sum
/ decimation
;
228 samples
.total_saved
++;
230 if (bits_per_sample
== 8) {
232 data
.buffer
[samples
.total_saved
- 1] = sample
;
234 // add number of bits.
235 data
.numbits
= samples
.total_saved
<< 3;
238 // truncate trailing data
239 sample
>>= 8 - bits_per_sample
;
240 sample
<<= 8 - bits_per_sample
;
242 uint8_t bits_offset
= data
.numbits
& 0x7;
243 uint8_t bits_cap
= 8 - bits_offset
;
245 // write the current byte
246 data
.buffer
[data
.numbits
>> 3] |= sample
>> bits_offset
;
247 uint32_t numbits
= data
.numbits
+ bits_cap
;
249 // write the remaining bits to the next byte
250 data
.buffer
[numbits
>> 3] |= sample
<< (bits_cap
);
251 data
.numbits
+= bits_per_sample
;
256 * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
257 * if not already loaded, sets divisor and starts up the antenna.
258 * @param divisor : 1, 88> 255 or negative ==> 134.8 kHz
259 * 0 or 95 ==> 125 kHz
262 void LFSetupFPGAForADC(int divisor
, bool reader_field
) {
263 FpgaDownloadAndGo(FPGA_BITSTREAM_LF
);
264 if ((divisor
== 1) || (divisor
< 0) || (divisor
> 255)) {
265 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, LF_DIVISOR_134
); //~134kHz
266 } else if (divisor
== 0) {
267 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, LF_DIVISOR_125
); //125kHz
269 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, divisor
);
272 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER
| (reader_field
? FPGA_LF_ADC_READER_FIELD
: 0));
274 // Connect the A/D to the peak-detected low-frequency path.
275 SetAdcMuxFor(GPIO_MUXSEL_LOPKD
);
277 // Now set up the SSC to get the ADC samples that are now streaming at us.
278 FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER
);
280 // start a 1.5ticks is 1us
283 // 50ms for the resonant antenna to settle.
292 * Does the sample acquisition. If threshold is specified, the actual sampling
293 * is not commenced until the threshold has been reached.
294 * This method implements decimation and quantization in order to
295 * be able to provide longer sample traces.
296 * Uses the following global settings:
297 * @param decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc.
298 * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample.
299 * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample
300 * value that will be used is the average value of the three samples.
301 * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set
302 * to -1 to ignore threshold.
303 * @param verbose - is true, dbprints the status, else no outputs
304 * @return the number of bits occupied by the samples.
306 uint32_t DoAcquisition(uint8_t decimation
, uint8_t bits_per_sample
, bool avg
, int16_t trigger_threshold
,
307 bool verbose
, uint32_t sample_size
, uint32_t cancel_after
, int32_t samples_to_skip
, bool ledcontrol
) {
309 initSampleBuffer(&sample_size
); // sample size in bytes
310 sample_size
<<= 3; // sample size in bits
311 sample_size
/= bits_per_sample
; // sample count
313 if (g_dbglevel
>= DBG_DEBUG
) {
317 bool trigger_hit
= false;
318 uint32_t cancel_counter
= 0;
321 while (BUTTON_PRESS() == false) {
323 // only every 4000th times, in order to save time when collecting samples.
324 // interruptible only when logging not yet triggered
325 if (trigger_hit
== false && (checked
>= 4000)) {
326 if (data_available()) {
337 if (ledcontrol
&& (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_TXRDY
)) {
341 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
342 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
344 // (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope
345 if (ledcontrol
) LED_D_OFF();
347 // threshold either high or low values 128 = center 0. if trigger = 178
348 if (trigger_hit
== false) {
349 if ((trigger_threshold
> 0) && (sample
< (trigger_threshold
+ 128)) && (sample
> (128 - trigger_threshold
))) {
350 if (cancel_after
> 0) {
352 if (cancel_after
== cancel_counter
)
360 if (samples_to_skip
> 0) {
365 logSample(sample
, decimation
, bits_per_sample
, avg
);
367 if (samples
.total_saved
>= sample_size
) break;
373 Dbprintf("lf sampling aborted");
374 } else if ((cancel_counter
== cancel_after
) && (cancel_after
> 0)) {
375 Dbprintf("lf sampling cancelled after %u", cancel_counter
);
378 Dbprintf("Done, saved " _YELLOW_("%d")" out of " _YELLOW_("%d")" seen samples at " _YELLOW_("%d")" bits/sample", samples
.total_saved
, samples
.counter
, bits_per_sample
);
381 // Ensure that DC offset removal and noise check is performed for any device-side processing
382 if (bits_per_sample
== 8) {
383 // these functions only consider bps==8
384 removeSignalOffset(data
.buffer
, samples
.total_saved
);
385 computeSignalProperties(data
.buffer
, samples
.total_saved
);
391 * @brief Does sample acquisition, ignoring the config values set in the sample_config.
392 * This method is typically used by tag-specific readers who just wants to read the samples
394 * @param trigger_threshold
396 * @return number of bits sampled
398 uint32_t DoAcquisition_default(int trigger_threshold
, bool verbose
, bool ledcontrol
) {
399 return DoAcquisition(1, 8, 0, trigger_threshold
, verbose
, 0, 0, 0, ledcontrol
);
401 uint32_t DoAcquisition_config(bool verbose
, uint32_t sample_size
, bool ledcontrol
) {
402 return DoAcquisition(config
.decimation
403 , config
.bits_per_sample
405 , config
.trigger_threshold
409 , config
.samples_to_skip
413 uint32_t DoPartialAcquisition(int trigger_threshold
, bool verbose
, uint32_t sample_size
, uint32_t cancel_after
, bool ledcontrol
) {
414 return DoAcquisition(config
.decimation
415 , config
.bits_per_sample
422 , ledcontrol
); // samples to skip
425 static uint32_t ReadLF(bool reader_field
, bool verbose
, uint32_t sample_size
, bool ledcontrol
) {
429 LFSetupFPGAForADC(config
.divisor
, reader_field
);
430 uint32_t ret
= DoAcquisition_config(verbose
, sample_size
, ledcontrol
);
432 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
437 * Initializes the FPGA for reader-mode (field on), and acquires the samples.
438 * @return number of bits sampled
440 uint32_t SampleLF(bool verbose
, uint32_t sample_size
, bool ledcontrol
) {
441 BigBuf_Clear_ext(false);
442 return ReadLF(true, verbose
, sample_size
, ledcontrol
);
446 * Do LF sampling and send samples to the USB
448 * Uses parameters in config. Only bits_per_sample = 8 is working now
450 * @param reader_field - true for reading tags, false for sniffing
451 * @return sampling result
453 int ReadLF_realtime(bool reader_field
) {
454 // parameters from config and constants
455 const uint8_t bits_per_sample
= config
.bits_per_sample
;
456 const int16_t trigger_threshold
= config
.trigger_threshold
;
457 int32_t samples_to_skip
= config
.samples_to_skip
;
458 const uint8_t decimation
= config
.decimation
;
460 const int8_t size_threshold_table
[9] = {0, 64, 64, 60, 64, 60, 60, 56, 64};
461 const int8_t size_threshold
= size_threshold_table
[bits_per_sample
];
463 // DoAcquisition() start
464 uint8_t last_byte
= 0;
465 uint8_t curr_byte
= 0;
466 int return_value
= PM3_SUCCESS
;
468 uint32_t sample_buffer_len
= AT91C_USB_EP_IN_SIZE
;
469 initSampleBuffer(&sample_buffer_len
);
470 if (sample_buffer_len
!= AT91C_USB_EP_IN_SIZE
) {
474 bool trigger_hit
= false;
477 return_value
= async_usb_write_start();
478 if (return_value
!= PM3_SUCCESS
) {
482 BigBuf_Clear_ext(false);
483 LFSetupFPGAForADC(config
.divisor
, reader_field
);
485 while (BUTTON_PRESS() == false) {
486 // only every 4000th times, in order to save time when collecting samples.
487 // interruptible only when logging not yet triggered
488 if (trigger_hit
== false && (checked
>= 4000)) {
489 if (data_available()) {
500 if ((AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_TXRDY
)) {
504 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
505 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
507 // (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope
510 // threshold either high or low values 128 = center 0. if trigger = 178
511 if (trigger_hit
== false) {
512 if ((trigger_threshold
> 0) && (sample
< (trigger_threshold
+ 128)) && (sample
> (128 - trigger_threshold
))) {
518 if (samples_to_skip
> 0) {
523 logSample(sample
, decimation
, bits_per_sample
, false);
525 // Write to USB FIFO if byte changed
526 curr_byte
= data
.numbits
>> 3;
527 if (curr_byte
> last_byte
) {
528 async_usb_write_pushByte(data
.buffer
[last_byte
]);
530 last_byte
= curr_byte
;
532 if (samples
.total_saved
== size_threshold
) {
533 // Request USB transmission and change FIFO bank
534 if (async_usb_write_requestWrite() == false) {
535 return_value
= PM3_EIO
;
542 samples
.counter
= size_threshold
;
543 samples
.total_saved
= 0;
545 } else if (samples
.total_saved
== 1) {
546 // Check if there is any data from client
547 if (data_available_fast()) {
554 return_value
= async_usb_write_stop();
559 // DoAcquisition() end
561 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
565 * Initializes the FPGA for sniffer-mode (field off), and acquires the samples.
566 * @return number of bits sampled
568 uint32_t SniffLF(bool verbose
, uint32_t sample_size
, bool ledcontrol
) {
569 BigBuf_Clear_ext(false);
570 return ReadLF(false, verbose
, sample_size
, ledcontrol
);
574 * acquisition of T55x7 LF signal. Similar to other LF, but adjusted with @marshmellows thresholds
575 * the data is collected in BigBuf.
577 void doT55x7Acquisition(size_t sample_size
, bool ledcontrol
) {
579 #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
580 #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
581 #define T55xx_READ_TOL 5
583 uint8_t *dest
= BigBuf_get_addr();
584 uint16_t bufsize
= BigBuf_max_traceLen();
586 if (bufsize
> sample_size
)
587 bufsize
= sample_size
;
589 uint8_t lastSample
= 0;
590 uint16_t i
= 0, skipCnt
= 0;
591 bool startFound
= false;
592 bool highFound
= false;
593 bool lowFound
= false;
595 uint16_t checker
= 0;
597 if (g_dbglevel
>= DBG_DEBUG
) {
598 Dbprintf("doT55x7Acquisition - after init");
602 while (skipCnt
< 1000 && (i
< bufsize
)) {
607 if (checker
== 4000) {
608 if (data_available())
618 if (ledcontrol
&& (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_TXRDY
)) {
622 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
623 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
624 if (ledcontrol
) LED_D_OFF();
626 // skip until the first high sample above threshold
627 if (!startFound
&& sample
> T55xx_READ_UPPER_THRESHOLD
) {
629 } else if (!highFound
) {
633 // skip until the first low sample below threshold
634 if (!startFound
&& sample
< T55xx_READ_LOWER_THRESHOLD
) {
637 } else if (!lowFound
) {
642 // skip until first high samples begin to change
643 if (startFound
|| sample
> T55xx_READ_LOWER_THRESHOLD
+ T55xx_READ_TOL
) {
644 // if just found start - recover last sample
645 if (startFound
== false) {
646 dest
[i
++] = lastSample
;
658 * acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384
659 * and is Manchester?, we directly gather the manchester data into bigbuff
663 #define COTAG_T2 (COTAG_T1 >> 1)
664 #define COTAG_ONE_THRESHOLD 127+5
665 #define COTAG_ZERO_THRESHOLD 127-5
667 #define COTAG_BITS 264
669 void doCotagAcquisition(void) {
671 uint16_t bufsize
= BigBuf_max_traceLen();
672 uint8_t *dest
= BigBuf_malloc(bufsize
);
676 bool firsthigh
= false, firstlow
= false;
677 uint16_t i
= 0, noise_counter
= 0;
679 uint16_t checker
= 0;
681 while ((i
< bufsize
- 1) && (noise_counter
< COTAG_T1
<< 1)) {
686 if (checker
== 4000) {
687 if (data_available())
697 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
699 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
702 if (firsthigh
== false) {
703 if (sample
< COTAG_ONE_THRESHOLD
) {
712 if (firstlow
== false) {
713 if (sample
> COTAG_ZERO_THRESHOLD
) {
722 if (sample
> COTAG_ONE_THRESHOLD
) {
725 } else if (sample
< COTAG_ZERO_THRESHOLD
) {
729 dest
[i
] = dest
[i
- 1];
735 // Ensure that DC offset removal and noise check is performed for any device-side processing
736 removeSignalOffset(dest
, i
);
737 computeSignalProperties(dest
, i
);
740 uint16_t doCotagAcquisitionManchester(uint8_t *dest
, uint16_t destlen
) {
747 bool firsthigh
= false, firstlow
= false;
748 uint8_t curr
= 0, prev
= 0;
750 uint16_t period
= 0, checker
= 0;
752 while ((i
< destlen
) && BUTTON_PRESS() == false) {
756 if (checker
== 4000) {
757 if (data_available())
766 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
767 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
770 if (firsthigh
== false) {
771 if (sample
< COTAG_ONE_THRESHOLD
) {
777 if (firstlow
== false) {
778 if (sample
> COTAG_ZERO_THRESHOLD
) {
784 // set sample 255, 0, or previous
785 if (sample
> COTAG_ONE_THRESHOLD
) {
788 } else if (sample
< COTAG_ZERO_THRESHOLD
) {