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 //----------------------------------------------------------------------------- 
  13 #include "usb_cdc.h" // for usb_poll_validate_length 
  14 #include "lfsampling.h" 
  16 sample_config config 
= { 1, 8, 1, 95, 0 } ; 
  20         Dbprintf("LF Sampling config: "); 
  21         Dbprintf("  [q] divisor:           %d ", config
.divisor
); 
  22         Dbprintf("  [b] bps:               %d ", config
.bits_per_sample
); 
  23         Dbprintf("  [d] decimation:        %d ", config
.decimation
); 
  24         Dbprintf("  [a] averaging:         %d ", config
.averaging
); 
  25         Dbprintf("  [t] trigger threshold: %d ", config
.trigger_threshold
); 
  30  * Called from the USB-handler to set the sampling configuration 
  31  * The sampling config is used for std reading and snooping. 
  33  * Other functions may read samples and ignore the sampling config, 
  34  * such as functions to read the UID from a prox tag or similar. 
  36  * Values set to '0' implies no change (except for averaging) 
  37  * @brief setSamplingConfig 
  40 void setSamplingConfig(sample_config 
*sc
) 
  42         if(sc
->divisor 
!= 0) config
.divisor 
= sc
->divisor
; 
  43         if(sc
->bits_per_sample
!= 0) config
.bits_per_sample
= sc
->bits_per_sample
; 
  44         if(sc
->decimation
!= 0) config
.decimation
= sc
->decimation
; 
  45         if(sc
->trigger_threshold 
!= -1) config
.trigger_threshold
= sc
->trigger_threshold
; 
  47         config
.averaging
= sc
->averaging
; 
  48         if(config
.bits_per_sample 
> 8)  config
.bits_per_sample 
= 8; 
  49         if(config
.decimation 
< 1)       config
.decimation 
= 1; 
  54 sample_config
* getSamplingConfig() 
  66  * @brief Pushes bit onto the stream 
  70 void pushBit( BitstreamOut
* stream
, uint8_t bit
) 
  72         int bytepos 
= stream
->position 
>> 3; // divide by 8 
  73         int bitpos 
= stream
->position 
& 7; 
  74         *(stream
->buffer
+bytepos
) |= (bit 
> 0) <<  (7 - bitpos
); 
  80 * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream 
  81 * if not already loaded, sets divisor and starts up the antenna. 
  82 * @param divisor : 1, 88> 255 or negative ==> 134.8 KHz 
  86 void LFSetupFPGAForADC(int divisor
, bool lf_field
) 
  88         FpgaDownloadAndGo(FPGA_BITSTREAM_LF
); 
  89         if ( (divisor 
== 1) || (divisor 
< 0) || (divisor 
> 255) ) 
  90                 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, 88); //134.8Khz 
  91         else if (divisor 
== 0) 
  92                 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, 95); //125Khz 
  94                 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, divisor
); 
  96         FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC 
| (lf_field 
? FPGA_LF_ADC_READER_FIELD 
: 0)); 
  98         // Connect the A/D to the peak-detected low-frequency path. 
  99         SetAdcMuxFor(GPIO_MUXSEL_LOPKD
); 
 100         // Give it a bit of time for the resonant antenna to settle. 
 102         // Now set up the SSC to get the ADC samples that are now streaming at us. 
 107  * Does the sample acquisition. If threshold is specified, the actual sampling 
 108  * is not commenced until the threshold has been reached. 
 109  * This method implements decimation and quantization in order to 
 110  * be able to provide longer sample traces. 
 111  * Uses the following global settings: 
 112  * @param decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc. 
 113  * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample. 
 114  * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample 
 115  * value that will be used is the average value of the three samples. 
 116  * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set 
 117  * to -1 to ignore threshold. 
 118  * @param silent - is true, now outputs are made. If false, dbprints the status 
 119  * @return the number of bits occupied by the samples. 
 121 uint32_t DoAcquisition(uint8_t decimation
, uint32_t bits_per_sample
, bool averaging
, int trigger_threshold
, bool silent
) 
 124         uint8_t *dest 
= BigBuf_get_addr(); 
 125     int bufsize 
= BigBuf_max_traceLen(); 
 127         memset(dest
, 0, bufsize
); 
 129         if(bits_per_sample 
< 1) bits_per_sample 
= 1; 
 130         if(bits_per_sample 
> 8) bits_per_sample 
= 8; 
 132         if(decimation 
< 1) decimation 
= 1; 
 134         // Use a bit stream to handle the output 
 135         BitstreamOut data 
= { dest 
, 0, 0}; 
 136         int sample_counter 
= 0; 
 138         //If we want to do averaging 
 139         uint32_t sample_sum 
=0 ; 
 140         uint32_t sample_total_numbers 
=0 ; 
 141         uint32_t sample_total_saved 
=0 ; 
 143         while(!BUTTON_PRESS()) { 
 145                 if (AT91C_BASE_SSC
->SSC_SR 
& AT91C_SSC_TXRDY
) { 
 146                         AT91C_BASE_SSC
->SSC_THR 
= 0x43; 
 149                 if (AT91C_BASE_SSC
->SSC_SR 
& AT91C_SSC_RXRDY
) { 
 150                         sample 
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
; 
 152                         // threshold either high or low values 128 = center 0.  if trigger = 178  
 153                         if ((trigger_threshold 
> 0) && (sample 
< (trigger_threshold
+128)) && (sample 
> (128-trigger_threshold
))) //  
 156                         trigger_threshold 
= 0; 
 157                         sample_total_numbers
++; 
 161                                 sample_sum 
+= sample
; 
 167                                 if(sample_counter 
< decimation
) continue; 
 171                         if(averaging 
&& decimation 
> 1) { 
 172                                 sample 
= sample_sum 
/ decimation
; 
 176                         sample_total_saved 
++; 
 177                         if(bits_per_sample 
== 8){ 
 178                                 dest
[sample_total_saved
-1] = sample
; 
 179                                 data
.numbits 
= sample_total_saved 
<< 3;//Get the return value correct 
 180                                 if(sample_total_saved 
>= bufsize
) break; 
 183                                 pushBit(&data
, sample 
& 0x80); 
 184                                 if(bits_per_sample 
> 1) pushBit(&data
, sample 
& 0x40); 
 185                                 if(bits_per_sample 
> 2) pushBit(&data
, sample 
& 0x20); 
 186                                 if(bits_per_sample 
> 3) pushBit(&data
, sample 
& 0x10); 
 187                                 if(bits_per_sample 
> 4) pushBit(&data
, sample 
& 0x08); 
 188                                 if(bits_per_sample 
> 5) pushBit(&data
, sample 
& 0x04); 
 189                                 if(bits_per_sample 
> 6) pushBit(&data
, sample 
& 0x02); 
 190                                 //Not needed, 8bps is covered above 
 191                                 //if(bits_per_sample > 7)       pushBit(&data, sample & 0x01); 
 192                                 if((data
.numbits 
>> 3) +1  >= bufsize
) break; 
 199                 Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved
, sample_total_numbers
,bits_per_sample
); 
 200                 Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", 
 201                                         dest
[0], dest
[1], dest
[2], dest
[3], dest
[4], dest
[5], dest
[6], dest
[7]); 
 206  * @brief Does sample acquisition, ignoring the config values set in the sample_config. 
 207  * This method is typically used by tag-specific readers who just wants to read the samples 
 209  * @param trigger_threshold 
 211  * @return number of bits sampled 
 213 uint32_t DoAcquisition_default(int trigger_threshold
, bool silent
) 
 215         return DoAcquisition(1,8,0,trigger_threshold
,silent
); 
 217 uint32_t DoAcquisition_config( bool silent
) 
 219         return DoAcquisition(config
.decimation
 
 220                                   ,config
.bits_per_sample
 
 222                                   ,config
.trigger_threshold
 
 226 uint32_t ReadLF(bool activeField
, bool silent
) 
 228         if (!silent
) printConfig(); 
 229         LFSetupFPGAForADC(config
.divisor
, activeField
); 
 230         // Now call the acquisition routine 
 231         return DoAcquisition_config(silent
); 
 235 * Initializes the FPGA for reader-mode (field on), and acquires the samples. 
 236 * @return number of bits sampled 
 238 uint32_t SampleLF(bool printCfg
) 
 240         return ReadLF(true, printCfg
); 
 243 * Initializes the FPGA for snoop-mode (field off), and acquires the samples. 
 244 * @return number of bits sampled 
 249         return ReadLF(false, true); 
 253 * acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds 
 254 * the data is collected in BigBuf. 
 256 void doT55x7Acquisition(size_t sample_size
) { 
 258         #define T55xx_READ_UPPER_THRESHOLD 128+60  // 60 grph 
 259         #define T55xx_READ_LOWER_THRESHOLD 128-60  // -60 grph 
 260         #define T55xx_READ_TOL   5 
 262         uint8_t *dest 
= BigBuf_get_addr(); 
 263         uint16_t bufsize 
= BigBuf_max_traceLen(); 
 265         if ( bufsize 
> sample_size 
) 
 266                 bufsize 
= sample_size
; 
 269         bool startFound 
= false; 
 270         bool highFound 
= false; 
 271         bool lowFound 
= false; 
 272         uint8_t curSample 
= 0; 
 273         uint8_t lastSample 
= 0; 
 274         uint16_t skipCnt 
= 0; 
 275         while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt
<1000 && i
<bufsize 
) { 
 277                 if (AT91C_BASE_SSC
->SSC_SR 
& AT91C_SSC_TXRDY
) { 
 278                         AT91C_BASE_SSC
->SSC_THR 
= 0x43; 
 281                 if (AT91C_BASE_SSC
->SSC_SR 
& AT91C_SSC_RXRDY
) { 
 282                         curSample 
= (uint8_t)AT91C_BASE_SSC
->SSC_RHR
; 
 285                         // skip until the first high sample above threshold 
 286                         if (!startFound 
&& curSample 
> T55xx_READ_UPPER_THRESHOLD
) { 
 287                                 //if (curSample > lastSample)  
 288                                 //      lastSample = curSample; 
 290                         } else if (!highFound
) { 
 294                         // skip until the first Low sample below threshold 
 295                         if (!startFound 
&& curSample 
< T55xx_READ_LOWER_THRESHOLD
) { 
 296                                 //if (curSample > lastSample)  
 297                                 lastSample 
= curSample
; 
 299                         } else if (!lowFound
) { 
 305                         // skip until first high samples begin to change 
 306                         if (startFound 
|| curSample 
> T55xx_READ_LOWER_THRESHOLD
+T55xx_READ_TOL
){ 
 307                                 // if just found start - recover last sample 
 309                                         dest
[i
++] = lastSample
; 
 313                                 dest
[i
++] = curSample
;