style
[RRG-proxmark3.git] / armsrc / lfadc.c
blob38d6558d8b74329ef4c9b57ce8f957031814165e
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
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.
8 //
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 // LF ADC read/write implementation
17 //-----------------------------------------------------------------------------
19 #include "lfadc.h"
20 #include "lfsampling.h"
21 #include "fpgaloader.h"
22 #include "ticks.h"
23 #include "dbprint.h"
24 #include "appmain.h"
26 // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
27 // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
28 // Carrier periods (T0) have duration of 8 microseconds (us), which is 1/125000 per second
29 // T0 = TIMER_CLOCK1 / 125000 = 192
30 //#define T0 192
32 // Sam7s has three counters, we will use the first TIMER_COUNTER_0 (aka TC0)
33 // using TIMER_CLOCK3 (aka AT91C_TC_CLKS_TIMER_DIV3_CLOCK)
34 // as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz
35 // Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency)
36 // T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6
37 //#define HITAG_T0 3
39 //////////////////////////////////////////////////////////////////////////////
40 // Exported global variables
41 //////////////////////////////////////////////////////////////////////////////
43 bool g_logging = true;
45 //////////////////////////////////////////////////////////////////////////////
46 // Global variables
47 //////////////////////////////////////////////////////////////////////////////
49 static bool rising_edge = false;
50 static bool reader_mode = false;
52 //////////////////////////////////////////////////////////////////////////////
53 // Auxiliary functions
54 //////////////////////////////////////////////////////////////////////////////
56 bool lf_test_periods(size_t expected, size_t count) {
57 // Compute 10% deviation (integer operation, so rounded down)
58 size_t diviation = expected / 10;
59 return ((count > (expected - diviation)) && (count < (expected + diviation)));
62 //////////////////////////////////////////////////////////////////////////////
63 // Low frequency (LF) adc passthrough functionality
64 //////////////////////////////////////////////////////////////////////////////
65 static uint8_t previous_adc_val = 0; //0xFF;
66 static uint8_t adc_avg = 0;
68 uint8_t get_adc_avg(void) {
69 return adc_avg;
71 void lf_sample_mean(void) {
72 uint8_t periods = 0;
73 uint32_t adc_sum = 0;
74 while (periods < 32) {
75 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
76 adc_sum += AT91C_BASE_SSC->SSC_RHR;
77 periods++;
80 // division by 32
81 adc_avg = adc_sum >> 5;
82 previous_adc_val = adc_avg;
84 if (g_dbglevel >= DBG_EXTENDED) {
85 Dbprintf("LF ADC average %u", adc_avg);
89 static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
91 #define LIMIT_DEV 20
93 // timeout limit to 100 000 w/o
94 uint32_t timeout = 100000;
95 size_t periods = 0;
96 uint8_t avg_peak = adc_avg + LIMIT_DEV;
97 uint8_t avg_through = adc_avg - LIMIT_DEV;
99 while (BUTTON_PRESS() == false) {
100 WDT_HIT();
102 timeout--;
103 if (timeout == 0) {
104 return 0;
107 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
108 AT91C_BASE_SSC->SSC_THR = 0x00;
109 continue;
112 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
114 periods++;
116 // reset timeout
117 timeout = 100000;
119 volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR;
121 if (g_logging) {
122 logSampleSimple(adc_val);
125 // Only test field changes if state of adc values matter
126 if (wait == false) {
127 // Test if we are locating a field modulation (100% ASK = complete field drop)
128 if (detect_gap) {
129 // Only return when the field completely disappeared
130 if (adc_val == 0) {
131 return periods;
134 } else {
135 // Trigger on a modulation swap by observing an edge change
136 if (rising_edge) {
138 if ((previous_adc_val > avg_peak) && (adc_val <= previous_adc_val)) {
139 rising_edge = false;
140 return periods;
143 } else {
145 if ((previous_adc_val < avg_through) && (adc_val >= previous_adc_val)) {
146 rising_edge = true;
147 return periods;
154 previous_adc_val = adc_val;
156 if (periods >= max) {
157 return 0;
162 if (g_logging) {
163 logSampleSimple(0xFF);
166 return 0;
169 size_t lf_count_edge_periods(size_t max) {
170 return lf_count_edge_periods_ex(max, false, false);
173 size_t lf_detect_gap(size_t max) {
174 return lf_count_edge_periods_ex(max, false, true);
177 void lf_reset_counter(void) {
179 // TODO: find out the correct reset settings for tag and reader mode
180 // if (reader_mode) {
181 // Reset values for reader mode
182 rising_edge = false;
183 previous_adc_val = 0xFF;
185 // } else {
186 // Reset values for tag/transponder mode
187 // rising_edge = false;
188 // previous_adc_val = 0xFF;
189 // }
192 bool lf_get_tag_modulation(void) {
193 return (rising_edge == false);
196 bool lf_get_reader_modulation(void) {
197 return rising_edge;
200 void lf_wait_periods(size_t periods) {
201 // wait detect gap
202 lf_count_edge_periods_ex(periods, true, false);
205 void lf_init(bool reader, bool simulate, bool ledcontrol) {
207 StopTicks();
209 reader_mode = reader;
211 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
213 sample_config *sc = getSamplingConfig();
214 sc->decimation = 1;
215 sc->averaging = 0;
217 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
219 if (reader) {
220 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
221 } else {
223 if (simulate) {
224 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
225 } else {
226 // Sniff
227 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC);
228 // FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
232 // Connect the A/D to the peak-detected low-frequency path.
233 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
235 // Now set up the SSC to get the ADC samples that are now streaming at us.
236 FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
238 // When in reader mode, give the field a bit of time to settle.
239 // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered.
240 SpinDelay(10);
242 // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation
243 AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
244 AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
245 LOW(GPIO_SSC_DOUT);
247 // Enable peripheral Clock for TIMER_CLOCK 0
248 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
249 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
250 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
252 // Enable peripheral Clock for TIMER_CLOCK 1
253 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
254 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
255 AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK;
257 // Clear all leds
258 if (ledcontrol) LEDsoff();
260 // Reset and enable timers
261 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
262 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
264 // Assert a sync signal. This sets all timers to 0 on next active clock edge
265 AT91C_BASE_TCB->TCB_BCR = 1;
267 // Prepare data trace
268 uint32_t bufsize = 10000;
270 // use malloc
271 if (g_logging) {
272 initSampleBufferEx(&bufsize, true);
275 lf_sample_mean();
278 void lf_finalize(bool ledcontrol) {
279 // Disable timers
280 AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
281 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
283 // return stolen pin to SSP
284 AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
285 AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
287 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
289 if (ledcontrol) LEDsoff();
291 StartTicks();
294 size_t lf_detect_field_drop(size_t max) {
296 size_t periods = 0;
297 // int16_t checked = 0;
299 while (BUTTON_PRESS() == false) {
301 // // only every 1000th times, in order to save time when collecting samples.
302 // if (checked == 4000) {
303 // if (data_available()) {
304 // checked = -1;
305 // break;
306 // } else {
307 // checked = 0;
308 // }
309 // }
310 // ++checked;
312 WDT_HIT();
314 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
315 periods++;
316 volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR;
318 if (g_logging) logSampleSimple(adc_val);
320 if (adc_val == 0) {
321 rising_edge = false;
322 return periods;
325 if (periods == max) return 0;
329 return 0;
332 void lf_modulation(bool modulation) {
333 if (modulation) {
334 HIGH(GPIO_SSC_DOUT);
335 } else {
336 LOW(GPIO_SSC_DOUT);
340 // simulation
341 static void lf_manchester_send_bit(uint8_t bit) {
342 lf_modulation(bit != 0);
343 lf_wait_periods(16);
344 lf_modulation(bit == 0);
345 lf_wait_periods(32);
348 // simulation
349 bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len, bool ledcontrol) {
351 if (ledcontrol) LED_B_ON();
353 lf_manchester_send_bit(1);
354 lf_manchester_send_bit(1);
355 lf_manchester_send_bit(1);
356 lf_manchester_send_bit(1);
357 lf_manchester_send_bit(1);
359 // Send the content of the frame
360 for (size_t i = 0; i < frame_len; i++) {
361 lf_manchester_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
364 if (ledcontrol) LED_B_OFF();
365 return true;