2015-01-31 06:03:44 +08:00
//-----------------------------------------------------------------------------
2022-01-06 09:19:46 +08:00
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
2015-01-31 06:03:44 +08:00
//-----------------------------------------------------------------------------
// Miscellaneous routines for low frequency sampling.
//-----------------------------------------------------------------------------
# include "lfsampling.h"
2015-02-27 03:35:35 +08:00
2019-08-08 22:57:33 +08:00
# include "proxmark3_arm.h"
# include "BigBuf.h"
# include "fpgaloader.h"
# include "ticks.h"
# include "dbprint.h"
# include "util.h"
# include "lfdemod.h"
2020-01-08 05:05:01 +08:00
# include "string.h" // memset
2020-06-23 17:21:17 +08:00
# include "appmain.h" // print stack
2019-08-08 22:57:33 +08:00
2017-02-01 21:11:11 +08:00
/*
Default LF config is set to :
2019-03-10 03:34:41 +08:00
decimation = 1 ( we keep 1 out of 1 samples )
bits_per_sample = 8
averaging = YES
2019-08-06 19:51:10 +08:00
divisor = 95 ( 125 kHz )
2019-03-10 03:34:41 +08:00
trigger_threshold = 0
2019-10-12 05:14:57 +08:00
samples_to_skip = 0
verbose = YES
2019-03-10 03:34:41 +08:00
*/
2021-07-29 16:51:31 +08:00
static sample_config def_config = {
2021-07-29 21:00:00 +08:00
. decimation = 1 ,
. bits_per_sample = 8 ,
. averaging = 1 ,
. divisor = LF_DIVISOR_125 ,
. trigger_threshold = 0 ,
. samples_to_skip = 0 ,
. verbose = false ,
} ;
2021-07-29 16:51:31 +08:00
static sample_config config = { 1 , 8 , 1 , LF_DIVISOR_125 , 0 , 0 , true } ;
2015-01-31 06:03:44 +08:00
2020-06-23 17:21:17 +08:00
// Holds bit packed struct of samples.
2021-08-22 04:24:58 +08:00
static BitstreamOut_t data = { 0 , 0 , 0 } ;
2020-06-23 17:21:17 +08:00
// internal struct to keep track of samples gathered
static sampling_t samples = { 0 , 0 , 0 , 0 } ;
2020-09-07 06:48:36 +08:00
void printLFConfig ( void ) {
2019-10-03 23:45:43 +08:00
uint32_t d = config . divisor ;
2020-06-12 01:20:59 +08:00
DbpString ( _CYAN_ ( " LF Sampling config " ) ) ;
2021-05-11 22:11:33 +08:00
Dbprintf ( " [q] divisor............. %d ( " _GREEN_ ( " %d.%02d kHz " ) " ) " , d , 12000 / ( d + 1 ) , ( ( 1200000 + ( d + 1 ) / 2 ) / ( d + 1 ) ) - ( ( 12000 / ( d + 1 ) ) * 100 ) ) ;
Dbprintf ( " [b] bits per sample..... %d " , config . bits_per_sample ) ;
Dbprintf ( " [d] decimation.......... %d " , config . decimation ) ;
Dbprintf ( " [a] averaging........... %s " , ( config . averaging ) ? " yes " : " no " ) ;
Dbprintf ( " [t] trigger threshold... %d " , config . trigger_threshold ) ;
Dbprintf ( " [s] samples to skip..... %d " , config . samples_to_skip ) ;
2021-07-28 15:51:35 +08:00
DbpString ( " " ) ;
2020-06-23 17:21:17 +08:00
}
void printSamples ( void ) {
2020-07-02 18:34:48 +08:00
DbpString ( _CYAN_ ( " LF Sampling memory usage " ) ) ;
// Dbprintf(" decimation counter...%d", samples.dec_counter);
// Dbprintf(" sum..................%u", samples.sum);
2021-05-11 22:11:33 +08:00
Dbprintf ( " counter.............. " _YELLOW_ ( " %u " ) , samples . counter ) ;
Dbprintf ( " total saved.......... " _YELLOW_ ( " %u " ) , samples . total_saved ) ;
2020-06-23 17:21:17 +08:00
print_stack_usage ( ) ;
2015-01-31 06:03:44 +08:00
}
2021-07-29 16:51:31 +08:00
void setDefaultSamplingConfig ( void ) {
setSamplingConfig ( & def_config ) ;
}
2015-01-31 06:03:44 +08:00
/**
* Called from the USB - handler to set the sampling configuration
2020-01-10 02:28:44 +08:00
* The sampling config is used for standard reading and sniffing .
2015-01-31 06:03:44 +08:00
*
* Other functions may read samples and ignore the sampling config ,
* such as functions to read the UID from a prox tag or similar .
*
2020-01-10 02:28:44 +08:00
* Values set to ' - 1 ' implies no change
2015-01-31 06:03:44 +08:00
* @ brief setSamplingConfig
* @ param sc
*/
2023-08-15 14:07:19 +08:00
void setSamplingConfig ( const sample_config * sc ) {
2019-03-09 15:59:13 +08:00
2020-01-10 02:28:44 +08:00
// decimation (1-8) how many bits of adc sample value to save
2021-02-03 23:00:33 +08:00
if ( sc - > decimation > 0 & & sc - > decimation < 9 )
2020-01-10 02:28:44 +08:00
config . decimation = sc - > decimation ;
// bits per sample (1-8)
2021-02-03 23:00:33 +08:00
if ( sc - > bits_per_sample > 0 & & sc - > bits_per_sample < 9 )
2020-01-10 02:28:44 +08:00
config . bits_per_sample = sc - > bits_per_sample ;
//
if ( sc - > averaging > - 1 )
config . averaging = ( sc - > averaging > 0 ) ? 1 : 0 ;
2020-01-13 00:30:29 +08:00
2020-01-10 02:28:44 +08:00
// Frequency divisor (19 - 255)
if ( sc - > divisor > 18 & & sc - > divisor < 256 )
config . divisor = sc - > divisor ;
2020-01-13 00:30:29 +08:00
2020-01-10 02:28:44 +08:00
// Start saving samples when adc value larger than trigger_threshold
2020-01-13 00:30:29 +08:00
if ( sc - > trigger_threshold > - 1 )
2020-01-10 02:28:44 +08:00
config . trigger_threshold = sc - > trigger_threshold ;
2020-01-13 00:30:29 +08:00
// Skip n adc samples before saving
2020-01-10 02:28:44 +08:00
if ( sc - > samples_to_skip > - 1 )
config . samples_to_skip = sc - > samples_to_skip ;
2015-01-31 06:03:44 +08:00
2019-10-12 05:14:57 +08:00
if ( sc - > verbose )
2020-09-07 06:48:36 +08:00
printLFConfig ( ) ;
2015-01-31 06:03:44 +08:00
}
2020-03-05 18:16:05 +08:00
sample_config * getSamplingConfig ( void ) {
2019-03-10 03:34:41 +08:00
return & config ;
2015-01-31 06:03:44 +08:00
}
2015-02-27 03:35:35 +08:00
2015-01-31 06:03:44 +08:00
/**
* @ brief Pushes bit onto the stream
* @ param stream
* @ param bit
*/
2021-08-22 04:24:58 +08:00
static void pushBit ( BitstreamOut_t * stream , uint8_t bit ) {
2019-03-10 03:34:41 +08:00
int bytepos = stream - > position > > 3 ; // divide by 8
int bitpos = stream - > position & 7 ;
2020-01-16 00:29:01 +08:00
* ( stream - > buffer + bytepos ) & = ~ ( 1 < < ( 7 - bitpos ) ) ;
2019-03-10 07:00:59 +08:00
* ( stream - > buffer + bytepos ) | = ( bit > 0 ) < < ( 7 - bitpos ) ;
2019-03-10 03:34:41 +08:00
stream - > position + + ;
stream - > numbits + + ;
2015-01-31 06:03:44 +08:00
}
2015-02-27 03:35:35 +08:00
2020-01-08 05:05:01 +08:00
void initSampleBuffer ( uint32_t * sample_size ) {
2020-01-29 11:37:10 +08:00
initSampleBufferEx ( sample_size , false ) ;
}
void initSampleBufferEx ( uint32_t * sample_size , bool use_malloc ) {
2020-05-09 03:13:01 +08:00
if ( sample_size = = NULL ) {
Dbprintf ( " initSampleBufferEx, param NULL " ) ;
return ;
}
2020-08-21 20:50:14 +08:00
BigBuf_free_keep_EM ( ) ;
2020-01-15 05:08:43 +08:00
2020-01-29 11:37:10 +08:00
// We can't erase the buffer now, it would drastically delay the acquisition
if ( use_malloc ) {
2020-01-15 05:08:43 +08:00
2020-05-09 03:13:01 +08:00
if ( * sample_size = = 0 ) {
2020-03-11 00:10:05 +08:00
* sample_size = BigBuf_max_traceLen ( ) ;
2020-01-29 11:37:10 +08:00
data . buffer = BigBuf_get_addr ( ) ;
} else {
* sample_size = MIN ( * sample_size , BigBuf_max_traceLen ( ) ) ;
data . buffer = BigBuf_malloc ( * sample_size ) ;
}
2020-01-08 05:05:01 +08:00
2020-01-29 11:37:10 +08:00
} else {
2020-05-09 03:13:01 +08:00
if ( * sample_size = = 0 ) {
2020-01-29 11:37:10 +08:00
* sample_size = BigBuf_max_traceLen ( ) ;
2020-06-22 18:57:28 +08:00
} else {
* sample_size = MIN ( * sample_size , BigBuf_max_traceLen ( ) ) ;
2020-01-29 11:37:10 +08:00
}
data . buffer = BigBuf_get_addr ( ) ;
2020-01-15 05:08:43 +08:00
}
2020-01-08 05:05:01 +08:00
2022-04-10 19:15:24 +08:00
// reset data stream
data . numbits = 0 ;
data . position = 0 ;
// reset samples
2020-01-08 05:05:01 +08:00
samples . dec_counter = 0 ;
samples . sum = 0 ;
2020-06-23 17:21:17 +08:00
samples . counter = * sample_size ;
2020-01-08 05:05:01 +08:00
samples . total_saved = 0 ;
}
2020-05-10 22:59:38 +08:00
uint32_t getSampleCounter ( void ) {
2020-01-08 05:05:01 +08:00
return samples . total_saved ;
}
2020-01-16 17:42:39 +08:00
void logSampleSimple ( uint8_t sample ) {
logSample ( sample , config . decimation , config . bits_per_sample , config . averaging ) ;
}
2020-01-10 02:28:44 +08:00
void logSample ( uint8_t sample , uint8_t decimation , uint8_t bits_per_sample , bool avg ) {
2020-01-08 05:05:01 +08:00
if ( ! data . buffer ) return ;
2020-06-23 17:21:17 +08:00
// keep track of total gather samples regardless how many was discarded.
if ( samples . counter - - = = 0 ) return ;
2020-08-13 18:25:04 +08:00
if ( bits_per_sample = = 0 ) bits_per_sample = 1 ;
2020-01-08 05:05:01 +08:00
if ( bits_per_sample > 8 ) bits_per_sample = 8 ;
if ( decimation = = 0 ) decimation = 1 ;
if ( avg ) {
samples . sum + = sample ;
}
// check decimation
if ( decimation > 1 ) {
samples . dec_counter + + ;
if ( samples . dec_counter < decimation ) return ;
samples . dec_counter = 0 ;
}
// averaging
if ( avg & & decimation > 1 ) {
sample = samples . sum / decimation ;
samples . sum = 0 ;
}
// store the sample
samples . total_saved + + ;
if ( bits_per_sample = = 8 ) {
data . buffer [ samples . total_saved - 1 ] = sample ;
// add number of bits.
data . numbits = samples . total_saved < < 3 ;
} else {
pushBit ( & data , sample & 0x80 ) ;
if ( bits_per_sample > 1 ) pushBit ( & data , sample & 0x40 ) ;
if ( bits_per_sample > 2 ) pushBit ( & data , sample & 0x20 ) ;
if ( bits_per_sample > 3 ) pushBit ( & data , sample & 0x10 ) ;
if ( bits_per_sample > 4 ) pushBit ( & data , sample & 0x08 ) ;
if ( bits_per_sample > 5 ) pushBit ( & data , sample & 0x04 ) ;
if ( bits_per_sample > 6 ) pushBit ( & data , sample & 0x02 ) ;
}
}
2015-01-31 06:03:44 +08:00
/**
* Setup the FPGA to listen for samples . This method downloads the FPGA bitstream
* if not already loaded , sets divisor and starts up the antenna .
2019-05-09 07:07:34 +08:00
* @ param divisor : 1 , 88 > 255 or negative = = > 134.8 kHz
* 0 or 95 = = > 125 kHz
2015-01-31 06:03:44 +08:00
*
* */
2020-01-23 00:41:59 +08:00
void LFSetupFPGAForADC ( int divisor , bool reader_field ) {
2019-03-10 03:34:41 +08:00
FpgaDownloadAndGo ( FPGA_BITSTREAM_LF ) ;
2019-03-10 07:00:59 +08:00
if ( ( divisor = = 1 ) | | ( divisor < 0 ) | | ( divisor > 255 ) )
2019-10-09 02:57:35 +08:00
FpgaSendCommand ( FPGA_CMD_SET_DIVISOR , LF_DIVISOR_134 ) ; //~134kHz
2019-03-10 03:34:41 +08:00
else if ( divisor = = 0 )
2019-10-09 02:57:35 +08:00
FpgaSendCommand ( FPGA_CMD_SET_DIVISOR , LF_DIVISOR_125 ) ; //125kHz
2019-03-10 03:34:41 +08:00
else
FpgaSendCommand ( FPGA_CMD_SET_DIVISOR , divisor ) ;
2020-01-23 00:41:59 +08:00
FpgaWriteConfWord ( FPGA_MAJOR_MODE_LF_READER | ( reader_field ? FPGA_LF_ADC_READER_FIELD : 0 ) ) ;
2019-03-10 03:34:41 +08:00
// Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor ( GPIO_MUXSEL_LOPKD ) ;
2020-06-23 17:21:17 +08:00
2019-03-10 03:34:41 +08:00
// Now set up the SSC to get the ADC samples that are now streaming at us.
2020-07-02 18:34:48 +08:00
FpgaSetupSsc ( FPGA_MAJOR_MODE_LF_READER ) ;
2020-01-23 00:41:59 +08:00
2019-03-10 03:34:41 +08:00
// start a 1.5ticks is 1us
StartTicks ( ) ;
2020-08-25 21:34:10 +08:00
// 50ms for the resonant antenna to settle.
2020-09-20 18:59:30 +08:00
if ( reader_field ) {
2020-08-25 21:34:10 +08:00
WaitMS ( 50 ) ;
2020-09-20 18:59:30 +08:00
} else {
WaitMS ( 1 ) ;
}
2015-01-31 06:03:44 +08:00
}
/**
* Does the sample acquisition . If threshold is specified , the actual sampling
* is not commenced until the threshold has been reached .
* This method implements decimation and quantization in order to
* be able to provide longer sample traces .
* Uses the following global settings :
* @ param decimation - how much should the signal be decimated . A decimation of N means we keep 1 in N samples , etc .
* @ param bits_per_sample - bits per sample . Max 8 , min 1 bit per sample .
* @ param averaging If set to true , decimation will use averaging , so that if e . g . decimation is 3 , the sample
* value that will be used is the average value of the three samples .
* @ param trigger_threshold - a threshold . The sampling won ' t commence until this threshold has been reached . Set
* to - 1 to ignore threshold .
2020-01-08 05:05:01 +08:00
* @ param verbose - is true , dbprints the status , else no outputs
2015-01-31 06:03:44 +08:00
* @ return the number of bits occupied by the samples .
*/
2020-01-10 02:28:44 +08:00
uint32_t DoAcquisition ( uint8_t decimation , uint8_t bits_per_sample , bool avg , int16_t trigger_threshold ,
2021-11-18 21:26:41 +08:00
bool verbose , uint32_t sample_size , uint32_t cancel_after , int32_t samples_to_skip , bool ledcontrol ) {
2019-03-10 03:34:41 +08:00
2023-01-22 23:38:09 +08:00
initSampleBuffer ( & sample_size ) ; // sample size in bytes
sample_size < < = 3 ; // sample size in bits
sample_size / = bits_per_sample ; // sample count
2019-03-10 03:34:41 +08:00
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2020-06-23 17:21:17 +08:00
printSamples ( ) ;
}
2020-09-07 00:32:23 +08:00
bool trigger_hit = false ;
2019-03-10 03:34:41 +08:00
uint32_t cancel_counter = 0 ;
2020-01-08 05:05:01 +08:00
int16_t checked = 0 ;
2019-07-13 06:38:30 +08:00
2020-06-22 18:57:28 +08:00
while ( BUTTON_PRESS ( ) = = false ) {
2020-01-08 05:05:01 +08:00
2020-08-25 21:34:10 +08:00
// only every 4000th times, in order to save time when collecting samples.
2020-05-09 06:23:46 +08:00
// interruptible only when logging not yet triggered
2020-09-07 00:32:23 +08:00
if ( ( checked > = 4000 ) & & trigger_hit = = false ) {
2020-02-22 20:32:42 +08:00
if ( data_available ( ) ) {
2020-01-08 05:05:01 +08:00
checked = - 1 ;
2019-06-09 20:15:31 +08:00
break ;
2020-01-08 05:05:01 +08:00
} else {
2019-10-04 16:24:04 +08:00
checked = 0 ;
2020-01-08 05:05:01 +08:00
}
2019-06-09 20:15:31 +08:00
}
2019-10-04 16:24:04 +08:00
+ + checked ;
2019-07-13 06:38:30 +08:00
2019-03-10 03:34:41 +08:00
WDT_HIT ( ) ;
2021-11-18 21:26:41 +08:00
if ( ledcontrol & & ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_TXRDY ) ) {
2020-01-08 05:05:01 +08:00
LED_D_ON ( ) ;
}
2019-03-10 03:34:41 +08:00
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
2020-01-08 05:05:01 +08:00
volatile uint8_t sample = ( uint8_t ) AT91C_BASE_SSC - > SSC_RHR ;
2019-03-10 03:34:41 +08:00
2020-09-07 00:32:23 +08:00
// Test point 8 (TP8) can be used to trigger oscilloscope
2021-11-18 21:26:41 +08:00
if ( ledcontrol ) LED_D_OFF ( ) ;
2019-03-10 03:34:41 +08:00
// threshold either high or low values 128 = center 0. if trigger = 178
2020-09-07 00:32:23 +08:00
if ( trigger_hit = = false ) {
2020-09-07 16:35:09 +08:00
if ( ( trigger_threshold > 0 ) & & ( sample < ( trigger_threshold + 128 ) ) & & ( sample > ( 128 - trigger_threshold ) ) ) {
if ( cancel_after > 0 ) {
cancel_counter + + ;
if ( cancel_after = = cancel_counter )
break ;
}
continue ;
2019-03-10 03:34:41 +08:00
}
2020-09-07 00:32:23 +08:00
}
2019-03-10 03:34:41 +08:00
2020-09-07 00:32:23 +08:00
trigger_hit = true ;
2019-09-29 08:43:01 +08:00
2019-09-30 17:41:25 +08:00
if ( samples_to_skip > 0 ) {
samples_to_skip - - ;
2019-09-29 08:43:01 +08:00
continue ;
}
2020-01-08 05:05:01 +08:00
logSample ( sample , decimation , bits_per_sample , avg ) ;
2019-03-10 03:34:41 +08:00
2020-01-08 05:05:01 +08:00
if ( samples . total_saved > = sample_size ) break ;
2019-03-10 03:34:41 +08:00
}
}
2020-08-13 18:25:04 +08:00
2020-01-08 05:05:01 +08:00
if ( verbose ) {
2020-09-07 00:32:23 +08:00
if ( checked = = - 1 ) {
Dbprintf ( " lf sampling aborted " ) ;
2020-09-30 20:27:19 +08:00
} else if ( ( cancel_counter = = cancel_after ) & & ( cancel_after > 0 ) ) {
2020-09-07 00:32:23 +08:00
Dbprintf ( " lf sampling cancelled after %u " , cancel_counter ) ;
}
2020-04-22 08:22:55 +08:00
Dbprintf ( " Done, saved " _YELLOW_ ( " %d " ) " out of " _YELLOW_ ( " %d " ) " seen samples at " _YELLOW_ ( " %d " ) " bits/sample " , samples . total_saved , samples . counter , bits_per_sample ) ;
2019-03-10 03:34:41 +08:00
}
// Ensure that DC offset removal and noise check is performed for any device-side processing
2023-02-11 18:42:58 +08:00
if ( bits_per_sample = = 8 ) {
2023-01-22 23:41:07 +08:00
// these functions only consider bps==8
removeSignalOffset ( data . buffer , samples . total_saved ) ;
computeSignalProperties ( data . buffer , samples . total_saved ) ;
}
2019-03-10 03:34:41 +08:00
return data . numbits ;
2015-01-31 06:03:44 +08:00
}
/**
* @ brief Does sample acquisition , ignoring the config values set in the sample_config .
* This method is typically used by tag - specific readers who just wants to read the samples
* the normal way
* @ param trigger_threshold
2020-01-08 05:05:01 +08:00
* @ param verbose
2015-01-31 06:03:44 +08:00
* @ return number of bits sampled
*/
2021-11-18 21:26:41 +08:00
uint32_t DoAcquisition_default ( int trigger_threshold , bool verbose , bool ledcontrol ) {
return DoAcquisition ( 1 , 8 , 0 , trigger_threshold , verbose , 0 , 0 , 0 , ledcontrol ) ;
2015-01-31 06:03:44 +08:00
}
2021-11-18 21:26:41 +08:00
uint32_t DoAcquisition_config ( bool verbose , uint32_t sample_size , bool ledcontrol ) {
2019-03-10 03:34:41 +08:00
return DoAcquisition ( config . decimation
2019-03-10 07:00:59 +08:00
, config . bits_per_sample
, config . averaging
, config . trigger_threshold
2020-01-08 05:05:01 +08:00
, verbose
2019-03-10 07:00:59 +08:00
, sample_size
2020-09-07 00:32:23 +08:00
, 0 // cancel_after
2021-11-18 21:26:41 +08:00
, config . samples_to_skip
, ledcontrol ) ;
2017-02-24 22:45:24 +08:00
}
2021-11-18 21:26:41 +08:00
uint32_t DoPartialAcquisition ( int trigger_threshold , bool verbose , uint32_t sample_size , uint32_t cancel_after , bool ledcontrol ) {
2020-09-07 00:32:23 +08:00
return DoAcquisition ( config . decimation
, config . bits_per_sample
, config . averaging
, trigger_threshold
, verbose
, sample_size
, cancel_after
2021-11-18 21:26:41 +08:00
, 0
, ledcontrol ) ; // samples to skip
2015-01-31 06:03:44 +08:00
}
2021-11-18 21:26:41 +08:00
static uint32_t ReadLF ( bool reader_field , bool verbose , uint32_t sample_size , bool ledcontrol ) {
2020-01-08 05:05:01 +08:00
if ( verbose )
2020-09-07 06:48:36 +08:00
printLFConfig ( ) ;
2020-01-08 05:05:01 +08:00
2020-01-23 00:41:59 +08:00
LFSetupFPGAForADC ( config . divisor , reader_field ) ;
2021-11-18 21:26:41 +08:00
uint32_t ret = DoAcquisition_config ( verbose , sample_size , ledcontrol ) ;
2020-09-07 00:32:23 +08:00
StopTicks ( ) ;
2019-03-12 06:12:31 +08:00
FpgaWriteConfWord ( FPGA_MAJOR_MODE_OFF ) ;
return ret ;
2015-01-31 06:03:44 +08:00
}
/**
* Initializes the FPGA for reader - mode ( field on ) , and acquires the samples .
* @ return number of bits sampled
* */
2021-11-18 21:26:41 +08:00
uint32_t SampleLF ( bool verbose , uint32_t sample_size , bool ledcontrol ) {
2019-03-10 03:34:41 +08:00
BigBuf_Clear_ext ( false ) ;
2021-11-18 21:26:41 +08:00
return ReadLF ( true , verbose , sample_size , ledcontrol ) ;
2015-01-31 06:03:44 +08:00
}
/**
2019-03-12 20:15:39 +08:00
* Initializes the FPGA for sniffer - mode ( field off ) , and acquires the samples .
2015-01-31 06:03:44 +08:00
* @ return number of bits sampled
* */
2021-11-18 21:26:41 +08:00
uint32_t SniffLF ( bool verbose , uint32_t sample_size , bool ledcontrol ) {
2019-03-10 03:34:41 +08:00
BigBuf_Clear_ext ( false ) ;
2021-11-18 21:26:41 +08:00
return ReadLF ( false , verbose , sample_size , ledcontrol ) ;
2015-01-31 06:03:44 +08:00
}
2015-10-15 16:23:15 +08:00
/**
2018-02-15 04:45:36 +08:00
* acquisition of T55x7 LF signal . Similar to other LF , but adjusted with @ marshmellows thresholds
2015-10-15 16:23:15 +08:00
* the data is collected in BigBuf .
* */
2021-11-18 21:26:41 +08:00
void doT55x7Acquisition ( size_t sample_size , bool ledcontrol ) {
2015-10-15 16:23:15 +08:00
2019-03-10 07:00:59 +08:00
# define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
# define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
# define T55xx_READ_TOL 5
2019-03-10 03:34:41 +08:00
uint8_t * dest = BigBuf_get_addr ( ) ;
uint16_t bufsize = BigBuf_max_traceLen ( ) ;
2019-03-10 07:00:59 +08:00
if ( bufsize > sample_size )
2019-03-10 03:34:41 +08:00
bufsize = sample_size ;
2020-01-08 05:05:01 +08:00
uint8_t lastSample = 0 ;
2019-03-10 03:34:41 +08:00
uint16_t i = 0 , skipCnt = 0 ;
bool startFound = false ;
bool highFound = false ;
bool lowFound = false ;
2019-07-13 06:38:30 +08:00
2019-06-09 21:32:34 +08:00
uint16_t checker = 0 ;
2020-08-13 18:25:04 +08:00
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2020-06-23 17:21:17 +08:00
Dbprintf ( " doT55x7Acquisition - after init " ) ;
print_stack_usage ( ) ;
}
2019-07-13 06:38:30 +08:00
while ( skipCnt < 1000 & & ( i < bufsize ) ) {
2020-08-13 18:25:04 +08:00
2020-06-23 17:21:17 +08:00
if ( BUTTON_PRESS ( ) )
break ;
if ( checker = = 4000 ) {
if ( data_available ( ) )
2019-06-09 21:32:34 +08:00
break ;
else
checker = 0 ;
} else {
+ + checker ;
}
2019-03-10 03:34:41 +08:00
WDT_HIT ( ) ;
2021-11-18 21:26:41 +08:00
if ( ledcontrol & & ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_TXRDY ) ) {
2020-01-08 05:05:01 +08:00
LED_D_ON ( ) ;
}
2019-03-10 03:34:41 +08:00
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
2020-01-08 05:05:01 +08:00
volatile uint8_t sample = ( uint8_t ) AT91C_BASE_SSC - > SSC_RHR ;
2021-11-18 21:26:41 +08:00
if ( ledcontrol ) LED_D_OFF ( ) ;
2019-03-10 03:34:41 +08:00
// skip until the first high sample above threshold
2020-01-08 05:05:01 +08:00
if ( ! startFound & & sample > T55xx_READ_UPPER_THRESHOLD ) {
2019-03-10 03:34:41 +08:00
highFound = true ;
} else if ( ! highFound ) {
skipCnt + + ;
continue ;
}
// skip until the first low sample below threshold
2020-01-08 05:05:01 +08:00
if ( ! startFound & & sample < T55xx_READ_LOWER_THRESHOLD ) {
lastSample = sample ;
2019-03-10 03:34:41 +08:00
lowFound = true ;
} else if ( ! lowFound ) {
skipCnt + + ;
continue ;
}
// skip until first high samples begin to change
2020-01-08 05:05:01 +08:00
if ( startFound | | sample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL ) {
2019-03-10 03:34:41 +08:00
// if just found start - recover last sample
if ( ! startFound ) {
dest [ i + + ] = lastSample ;
startFound = true ;
}
// collect samples
2020-01-08 05:05:01 +08:00
dest [ i + + ] = sample ;
2019-03-10 03:34:41 +08:00
}
}
}
2015-10-28 04:47:21 +08:00
}
2017-02-02 22:32:21 +08:00
/**
* acquisition of Cotag LF signal . Similart to other LF , since the Cotag has such long datarate RF / 384
* and is Manchester ? , we directly gather the manchester data into bigbuff
* */
# define COTAG_T1 384
2020-08-25 21:34:10 +08:00
# define COTAG_T2 (COTAG_T1 >> 1)
# define COTAG_ONE_THRESHOLD 127+5
# define COTAG_ZERO_THRESHOLD 127-5
2017-02-24 22:45:24 +08:00
# ifndef COTAG_BITS
# define COTAG_BITS 264
# endif
2020-08-25 21:34:10 +08:00
void doCotagAcquisition ( void ) {
2017-02-02 22:32:21 +08:00
2020-07-02 18:34:48 +08:00
uint16_t bufsize = BigBuf_max_traceLen ( ) ;
2020-08-25 21:34:10 +08:00
uint8_t * dest = BigBuf_malloc ( bufsize ) ;
2019-03-10 03:34:41 +08:00
dest [ 0 ] = 0 ;
2020-08-13 18:25:04 +08:00
2020-08-25 21:34:10 +08:00
bool firsthigh = false , firstlow = false ;
uint16_t i = 0 , noise_counter = 0 ;
2019-07-13 06:38:30 +08:00
2020-12-02 00:06:49 +08:00
uint16_t checker = 0 ;
2020-09-07 00:32:23 +08:00
while ( ( i < bufsize - 1 ) & & ( noise_counter < COTAG_T1 < < 1 ) ) {
2020-08-13 18:25:04 +08:00
2020-06-23 17:21:17 +08:00
if ( BUTTON_PRESS ( ) )
break ;
2020-12-12 21:46:40 +08:00
2020-12-02 00:06:49 +08:00
if ( checker = = 4000 ) {
if ( data_available ( ) )
break ;
else
checker = 0 ;
} else {
+ + checker ;
}
2020-08-13 18:25:04 +08:00
2019-03-10 03:34:41 +08:00
WDT_HIT ( ) ;
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
2020-08-25 21:34:10 +08:00
2020-01-08 05:05:01 +08:00
volatile uint8_t sample = ( uint8_t ) AT91C_BASE_SSC - > SSC_RHR ;
2019-03-10 03:34:41 +08:00
// find first peak
2020-08-25 21:34:10 +08:00
if ( firsthigh = = false ) {
2019-03-10 03:34:41 +08:00
if ( sample < COTAG_ONE_THRESHOLD ) {
noise_counter + + ;
continue ;
}
2020-08-25 21:34:10 +08:00
2019-03-10 03:34:41 +08:00
noise_counter = 0 ;
2020-08-25 21:34:10 +08:00
firsthigh = true ;
2019-03-10 03:34:41 +08:00
}
2020-08-25 21:34:10 +08:00
if ( firstlow = = false ) {
2019-03-10 07:00:59 +08:00
if ( sample > COTAG_ZERO_THRESHOLD ) {
2019-03-10 03:34:41 +08:00
noise_counter + + ;
continue ;
}
2020-08-25 21:34:10 +08:00
2019-03-10 03:34:41 +08:00
noise_counter = 0 ;
2020-08-25 21:34:10 +08:00
firstlow = true ;
2019-03-10 03:34:41 +08:00
}
2020-09-07 00:32:23 +08:00
+ + i ;
2020-09-07 16:35:09 +08:00
if ( sample > COTAG_ONE_THRESHOLD ) {
dest [ i ] = 255 ;
} else if ( sample < COTAG_ZERO_THRESHOLD ) {
dest [ i ] = 0 ;
} else {
dest [ i ] = dest [ i - 1 ] ;
2020-08-25 21:34:10 +08:00
}
2019-03-10 03:34:41 +08:00
}
}
2019-11-04 22:13:59 +08:00
// Ensure that DC offset removal and noise check is performed for any device-side processing
2020-08-25 21:34:10 +08:00
removeSignalOffset ( dest , i ) ;
computeSignalProperties ( dest , i ) ;
2017-02-02 22:32:21 +08:00
}
2020-08-25 21:34:10 +08:00
uint16_t doCotagAcquisitionManchester ( uint8_t * dest , uint16_t destlen ) {
2019-03-10 03:34:41 +08:00
2020-08-25 21:34:10 +08:00
if ( dest = = NULL )
return 0 ;
2020-09-07 16:35:09 +08:00
2019-03-10 03:34:41 +08:00
dest [ 0 ] = 0 ;
2020-08-13 18:25:04 +08:00
2020-08-25 21:34:10 +08:00
bool firsthigh = false , firstlow = false ;
uint8_t curr = 0 , prev = 0 ;
uint16_t i = 0 ;
2020-12-02 00:06:49 +08:00
uint16_t period = 0 , checker = 0 ;
2020-08-13 18:25:04 +08:00
2020-08-25 21:34:10 +08:00
while ( ( i < destlen ) & & BUTTON_PRESS ( ) = = false ) {
2019-03-10 03:34:41 +08:00
WDT_HIT ( ) ;
2020-12-02 00:06:49 +08:00
if ( checker = = 4000 ) {
if ( data_available ( ) )
break ;
else
checker = 0 ;
} else {
+ + checker ;
}
2019-03-10 03:34:41 +08:00
if ( AT91C_BASE_SSC - > SSC_SR & AT91C_SSC_RXRDY ) {
2020-01-08 05:05:01 +08:00
volatile uint8_t sample = ( uint8_t ) AT91C_BASE_SSC - > SSC_RHR ;
2019-03-10 03:34:41 +08:00
// find first peak
2020-08-25 21:34:10 +08:00
if ( firsthigh = = false ) {
2019-03-10 03:34:41 +08:00
if ( sample < COTAG_ONE_THRESHOLD ) {
continue ;
}
2020-08-25 21:34:10 +08:00
firsthigh = true ;
2019-03-10 03:34:41 +08:00
}
2020-08-25 21:34:10 +08:00
if ( firstlow = = false ) {
2019-03-10 07:00:59 +08:00
if ( sample > COTAG_ZERO_THRESHOLD ) {
2019-03-10 03:34:41 +08:00
continue ;
}
2020-08-25 21:34:10 +08:00
firstlow = true ;
2019-03-10 03:34:41 +08:00
}
// set sample 255, 0, or previous
2019-03-10 07:00:59 +08:00
if ( sample > COTAG_ONE_THRESHOLD ) {
2019-03-10 03:34:41 +08:00
prev = curr ;
curr = 1 ;
2019-03-12 06:12:31 +08:00
} else if ( sample < COTAG_ZERO_THRESHOLD ) {
2019-03-10 03:34:41 +08:00
prev = curr ;
curr = 0 ;
2019-03-12 06:12:31 +08:00
} else {
2019-03-10 03:34:41 +08:00
curr = prev ;
}
// full T1 periods,
2019-03-10 07:00:59 +08:00
if ( period > 0 ) {
2019-03-10 03:34:41 +08:00
- - period ;
continue ;
}
2020-08-25 21:34:10 +08:00
dest [ i ] = curr ;
+ + i ;
2019-03-10 03:34:41 +08:00
period = COTAG_T1 ;
}
}
2020-08-25 21:34:10 +08:00
return i ;
2019-03-09 02:06:55 +08:00
}