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
5 //-----------------------------------------------------------------------------
6 // Miscellaneous routines for low frequency sampling.
7 //-----------------------------------------------------------------------------
9 #include "lfsampling.h"
11 #include "proxmark3_arm.h"
13 #include "fpgaloader.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)
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"));
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
);
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
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
;
103 sample_config
*getSamplingConfig(void) {
108 * @brief Pushes bit onto the stream
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
);
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");
130 BigBuf_free_keep_EM();
132 // We can't erase the buffer now, it would drastically delay the acquisition
135 if (*sample_size
== 0) {
136 *sample_size
= BigBuf_max_traceLen();
137 data
.buffer
= BigBuf_get_addr();
139 *sample_size
= MIN(*sample_size
, BigBuf_max_traceLen());
140 data
.buffer
= BigBuf_malloc(*sample_size
);
144 if (*sample_size
== 0) {
145 *sample_size
= BigBuf_max_traceLen();
147 *sample_size
= MIN(*sample_size
, BigBuf_max_traceLen());
149 data
.buffer
= BigBuf_get_addr();
153 samples
.dec_counter
= 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;
179 samples
.sum
+= sample
;
183 if (decimation
> 1) {
184 samples
.dec_counter
++;
186 if (samples
.dec_counter
< decimation
) return;
188 samples
.dec_counter
= 0;
192 if (avg
&& decimation
> 1) {
193 sample
= samples
.sum
/ decimation
;
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;
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
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
245 // 50ms for the resonant antenna to settle.
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
) {
277 bool trigger_hit
= false;
278 uint32_t cancel_counter
= 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()) {
297 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_TXRDY
) {
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
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) {
312 if (cancel_after
== cancel_counter
)
321 if (samples_to_skip
> 0) {
326 logSample(sample
, decimation
, bits_per_sample
, avg
);
328 if (samples
.total_saved
>= sample_size
) break;
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
);
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
351 * @param trigger_threshold
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
362 , config
.trigger_threshold
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
377 , 0); // samples to skip
380 static uint32_t ReadLF(bool reader_field
, bool verbose
, uint32_t sample_size
) {
384 LFSetupFPGAForADC(config
.divisor
, reader_field
);
385 uint32_t ret
= DoAcquisition_config(verbose
, sample_size
);
387 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
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");
437 while (skipCnt
< 1000 && (i
< bufsize
)) {
442 if (checker
== 4000) {
443 if (data_available())
453 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_TXRDY
) {
457 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
458 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
461 // skip until the first high sample above threshold
462 if (!startFound
&& sample
> T55xx_READ_UPPER_THRESHOLD
) {
464 } else if (!highFound
) {
468 // skip until the first low sample below threshold
469 if (!startFound
&& sample
< T55xx_READ_LOWER_THRESHOLD
) {
472 } else if (!lowFound
) {
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
481 dest
[i
++] = lastSample
;
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
496 #define COTAG_T2 (COTAG_T1 >> 1)
497 #define COTAG_ONE_THRESHOLD 127+5
498 #define COTAG_ZERO_THRESHOLD 127-5
500 #define COTAG_BITS 264
502 void doCotagAcquisition(void) {
504 uint16_t bufsize
= BigBuf_max_traceLen();
505 uint8_t *dest
= BigBuf_malloc(bufsize
);
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)) {
519 if (checker
== 4000) {
520 if (data_available())
530 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
532 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
535 if (firsthigh
== false) {
536 if (sample
< COTAG_ONE_THRESHOLD
) {
545 if (firstlow
== false) {
546 if (sample
> COTAG_ZERO_THRESHOLD
) {
556 if (sample
> COTAG_ONE_THRESHOLD
) {
558 } else if (sample
< COTAG_ZERO_THRESHOLD
) {
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
) {
578 bool firsthigh
= false, firstlow
= false;
579 uint8_t curr
= 0, prev
= 0;
581 uint16_t period
= 0, checker
= 0;
583 while ((i
< destlen
) && BUTTON_PRESS() == false) {
587 if (checker
== 4000) {
588 if (data_available())
597 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
598 volatile uint8_t sample
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
;
601 if (firsthigh
== false) {
602 if (sample
< COTAG_ONE_THRESHOLD
) {
608 if (firstlow
== false) {
609 if (sample
> COTAG_ZERO_THRESHOLD
) {
615 // set sample 255, 0, or previous
616 if (sample
> COTAG_ONE_THRESHOLD
) {
619 } else if (sample
< COTAG_ZERO_THRESHOLD
) {