Some more fixes to longer lf recordings. Now also supports longer snoops, and an additional command 'lf config' has been defined, instead of having to specify all params for every call
This commit is contained in:
@@ -14,7 +14,7 @@ APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_
|
||||
#-DWITH_LCD
|
||||
|
||||
#SRC_LCD = fonts.c LCD.c
|
||||
SRC_LF = lfops.c hitag2.c
|
||||
SRC_LF = lfops.c hitag2.c lfsampling.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
|
||||
SRC_ISO14443b = iso14443.c
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "legicrf.h"
|
||||
#include <hitag2.h>
|
||||
|
||||
#include "lfsampling.h"
|
||||
#ifdef WITH_LCD
|
||||
#include "LCD.h"
|
||||
#endif
|
||||
@@ -629,16 +629,17 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||
|
||||
switch(c->cmd) {
|
||||
#ifdef WITH_LF
|
||||
case CMD_SET_LF_SAMPLING_CONFIG:
|
||||
setSamplingConfig((sample_config *) c->d.asBytes);
|
||||
break;
|
||||
case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
||||
AcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2]);
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
cmd_send(CMD_ACK,SampleLF(),0,0,0,0);
|
||||
break;
|
||||
case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
||||
ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
|
||||
break;
|
||||
case CMD_LF_SNOOP_RAW_ADC_SAMPLES:
|
||||
SnoopLFRawAdcSamples(c->arg[0], c->arg[1]);
|
||||
cmd_send(CMD_ACK,0,0,0,0,0);
|
||||
cmd_send(CMD_ACK,SnoopLF(),0,0,0,0);
|
||||
break;
|
||||
case CMD_HID_DEMOD_FSK:
|
||||
CmdHIDdemodFSK(c->arg[0], 0, 0, 1);
|
||||
@@ -910,7 +911,8 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,0,((byte_t*)BigBuf)+c->arg[0]+i,len);
|
||||
}
|
||||
// Trigger a finish downloading signal with an ACK frame
|
||||
cmd_send(CMD_ACK,bits_per_sample,decimation,0,0,0);
|
||||
// We put a 1 in arg[0] to alert the host we're also sending sample_config
|
||||
cmd_send(CMD_ACK,1,0,0,getSamplingConfig(),sizeof(sample_config));
|
||||
LED_B_OFF();
|
||||
break;
|
||||
|
||||
|
||||
@@ -81,8 +81,6 @@ int AvgAdc(int ch);
|
||||
void ToSendStuffBit(int b);
|
||||
void ToSendReset(void);
|
||||
void ListenReaderField(int limit);
|
||||
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold);
|
||||
void DoAcquisition125k(int trigger_threshold);
|
||||
extern int ToSendMax;
|
||||
extern uint8_t ToSend[];
|
||||
extern uint32_t BigBuf[];
|
||||
@@ -147,7 +145,7 @@ extern uint8_t decimation;
|
||||
extern uint8_t bits_per_sample ;
|
||||
extern bool averaging;
|
||||
|
||||
void AcquireRawAdcSamples125k(int divisor,int arg1, int arg2);
|
||||
void AcquireRawAdcSamples125k(int divisor);
|
||||
void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
|
||||
void ReadTItag(void);
|
||||
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
|
||||
|
||||
241
armsrc/lfops.c
241
armsrc/lfops.c
@@ -15,231 +15,44 @@
|
||||
#include "crc16.h"
|
||||
#include "string.h"
|
||||
#include "lfdemod.h"
|
||||
|
||||
uint8_t decimation = 1;
|
||||
uint8_t bits_per_sample = 8;
|
||||
bool averaging = 1;
|
||||
#include "lfsampling.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t * buffer;
|
||||
uint32_t numbits;
|
||||
uint32_t position;
|
||||
} BitstreamOut;
|
||||
/**
|
||||
* @brief Pushes bit onto the stream
|
||||
* @param stream
|
||||
* @param bit
|
||||
* Function to do a modulation and then get samples.
|
||||
* @param delay_off
|
||||
* @param period_0
|
||||
* @param period_1
|
||||
* @param command
|
||||
*/
|
||||
void pushBit( BitstreamOut* stream, uint8_t bit)
|
||||
{
|
||||
int bytepos = stream->position >> 3; // divide by 8
|
||||
int bitpos = stream->position & 7;
|
||||
*(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos);
|
||||
stream->position++;
|
||||
stream->numbits++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* - decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc.
|
||||
* - bits_per_sample - bits per sample. Max 8, min 1 bit per sample.
|
||||
* - 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.
|
||||
* @param silent - is true, now outputs are made. If false, dbprints the status
|
||||
* @return the number of bits occupied by the samples.
|
||||
*/
|
||||
uint32_t DoAcquisition125k_internal(int trigger_threshold,bool silent)
|
||||
{
|
||||
//.
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
int bufsize = BIGBUF_SIZE;
|
||||
memset(dest, 0, bufsize);
|
||||
|
||||
if(bits_per_sample < 1) bits_per_sample = 1;
|
||||
if(bits_per_sample > 8) bits_per_sample = 8;
|
||||
|
||||
if(decimation < 1) decimation = 1;
|
||||
|
||||
// Use a bit stream to handle the output
|
||||
BitstreamOut data = { dest , 0, 0};
|
||||
int sample_counter = 0;
|
||||
uint8_t sample = 0;
|
||||
//If we want to do averaging
|
||||
uint32_t sample_sum =0 ;
|
||||
uint32_t sample_total_numbers =0 ;
|
||||
uint32_t sample_total_saved =0 ;
|
||||
|
||||
while(!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||
LED_D_ON();
|
||||
}
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
LED_D_OFF();
|
||||
if (trigger_threshold != -1 && sample < trigger_threshold)
|
||||
continue;
|
||||
|
||||
trigger_threshold = -1;
|
||||
sample_total_numbers++;
|
||||
|
||||
if(averaging)
|
||||
{
|
||||
sample_sum += sample;
|
||||
}
|
||||
//Check decimation
|
||||
if(decimation > 1)
|
||||
{
|
||||
sample_counter++;
|
||||
if(sample_counter < decimation) continue;
|
||||
sample_counter = 0;
|
||||
}
|
||||
//Averaging
|
||||
if(averaging && decimation > 1) {
|
||||
sample = sample_sum / decimation;
|
||||
sample_sum =0;
|
||||
}
|
||||
//Store the sample
|
||||
sample_total_saved ++;
|
||||
if(bits_per_sample == 8){
|
||||
dest[sample_total_saved-1] = sample;
|
||||
data.numbits = sample_total_saved << 3;//Get the return value correct
|
||||
if(sample_total_saved >= bufsize) break;
|
||||
}
|
||||
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);
|
||||
//Not needed, 8bps is covered above
|
||||
//if(bits_per_sample > 7) pushBit(&data, sample & 0x01);
|
||||
if((data.numbits >> 3) +1 >= bufsize) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!silent)
|
||||
{
|
||||
Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved, sample_total_numbers,bits_per_sample);
|
||||
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
|
||||
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
|
||||
}
|
||||
return data.numbits;
|
||||
}
|
||||
/**
|
||||
* Perform sample aquisition.
|
||||
*/
|
||||
void DoAcquisition125k(int trigger_threshold)
|
||||
{
|
||||
DoAcquisition125k_internal(trigger_threshold, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
|
||||
* if not already loaded, sets divisor and starts up the antenna.
|
||||
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
|
||||
* 0 or 95 ==> 125 KHz
|
||||
*
|
||||
**/
|
||||
void LFSetupFPGAForADC(int divisor, bool lf_field)
|
||||
{
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
||||
else if (divisor == 0)
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
else
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0));
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
// Give it a bit of time for the resonant antenna to settle.
|
||||
SpinDelay(50);
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
}
|
||||
/**
|
||||
* Initializes the FPGA, and acquires the samples.
|
||||
**/
|
||||
void AcquireRawAdcSamples125k(int divisor,int arg1, int arg2)
|
||||
{
|
||||
if (arg1 != 0)
|
||||
{
|
||||
averaging = (arg1 & 0x80) != 0;
|
||||
bits_per_sample = (arg1 & 0x0F);
|
||||
}
|
||||
if(arg2 != 0)
|
||||
{
|
||||
decimation = arg2;
|
||||
}
|
||||
|
||||
Dbprintf("Sampling config: ");
|
||||
Dbprintf(" divisor: %d ", divisor);
|
||||
Dbprintf(" bps: %d ", bits_per_sample);
|
||||
Dbprintf(" decimation: %d ", decimation);
|
||||
Dbprintf(" averaging: %d ", averaging);
|
||||
|
||||
LFSetupFPGAForADC(divisor, true);
|
||||
// Now call the acquisition routine
|
||||
DoAcquisition125k_internal(-1,false);
|
||||
}
|
||||
/**
|
||||
* Initializes the FPGA for snoop-mode, and acquires the samples.
|
||||
**/
|
||||
|
||||
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold)
|
||||
{
|
||||
LFSetupFPGAForADC(divisor, false);
|
||||
DoAcquisition125k(trigger_threshold);
|
||||
}
|
||||
|
||||
void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command)
|
||||
{
|
||||
|
||||
/* Make sure the tag is reset */
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(2500);
|
||||
|
||||
|
||||
int divisor_used = 95; // 125 KHz
|
||||
// see if 'h' was specified
|
||||
|
||||
if (command[strlen((char *) command) - 1] == 'h')
|
||||
divisor_used = 88; // 134.8 KHz
|
||||
|
||||
sample_config sc = { 0,0,1, divisor_used, 0};
|
||||
setSamplingConfig(&sc);
|
||||
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
// Give it a bit of time for the resonant antenna to settle.
|
||||
SpinDelay(50);
|
||||
/* Make sure the tag is reset */
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(2500);
|
||||
|
||||
// And a little more time for the tag to fully power up
|
||||
SpinDelay(2000);
|
||||
LFSetupFPGAForADC(sc.divisor, 1);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
// And a little more time for the tag to fully power up
|
||||
SpinDelay(2000);
|
||||
|
||||
// now modulate the reader field
|
||||
while(*command != '\0' && *command != ' ') {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
SpinDelayUs(delay_off);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
LED_D_ON();
|
||||
@@ -251,14 +64,16 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1,
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LED_D_OFF();
|
||||
SpinDelayUs(delay_off);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
|
||||
|
||||
// now do the read
|
||||
DoAcquisition125k(-1);
|
||||
DoAcquisition_config(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* blank r/w tag data stream
|
||||
...0000000000000000 01111111
|
||||
1010101010101010101010101010101010101010101010101010101010101010
|
||||
@@ -745,8 +560,8 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||
WDT_HIT();
|
||||
if (ledcontrol) LED_A_ON();
|
||||
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
// FSK demodulator
|
||||
DoAcquisition_default(-1,true);
|
||||
// FSK demodulator
|
||||
size = HIDdemodFSK(dest, sizeof(BigBuf), &hi2, &hi, &lo);
|
||||
|
||||
WDT_HIT();
|
||||
@@ -833,8 +648,8 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||
WDT_HIT();
|
||||
if (ledcontrol) LED_A_ON();
|
||||
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
size = sizeof(BigBuf);
|
||||
DoAcquisition_default(-1,true);
|
||||
size = sizeof(BigBuf);
|
||||
//Dbprintf("DEBUG: Buffer got");
|
||||
//askdemod and manchester decode
|
||||
errCnt = askmandemod(dest, &size, &clk, &invert);
|
||||
@@ -884,8 +699,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||
while(!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
if (ledcontrol) LED_A_ON();
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
//fskdemod and get start index
|
||||
DoAcquisition_default(-1,true);
|
||||
//fskdemod and get start index
|
||||
WDT_HIT();
|
||||
idx = IOdemodFSK(dest,sizeof(BigBuf));
|
||||
if (idx>0){
|
||||
@@ -1489,7 +1304,9 @@ int DemodPCF7931(uint8_t **outBlocks) {
|
||||
int lmin=128, lmax=128;
|
||||
uint8_t dir;
|
||||
|
||||
AcquireRawAdcSamples125k(0,0,0);
|
||||
LFSetupFPGAForADC(95, true);
|
||||
DoAcquisition_default(0, 0);
|
||||
|
||||
|
||||
lmin = 64;
|
||||
lmax = 192;
|
||||
|
||||
251
armsrc/lfsampling.c
Normal file
251
armsrc/lfsampling.c
Normal file
@@ -0,0 +1,251 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Miscellaneous routines for low frequency sampling.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "apps.h"
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "lfsampling.h"
|
||||
|
||||
sample_config config = { 1, 8, 1, 88, 0 } ;
|
||||
|
||||
void printConfig()
|
||||
{
|
||||
Dbprintf("Sampling config: ");
|
||||
Dbprintf(" [q] divisor: %d ", config.divisor);
|
||||
Dbprintf(" [b] bps: %d ", config.bits_per_sample);
|
||||
Dbprintf(" [d] decimation: %d ", config.decimation);
|
||||
Dbprintf(" [a] averaging: %d ", config.averaging);
|
||||
Dbprintf(" [t] trigger threshold: %d ", config.trigger_threshold);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called from the USB-handler to set the sampling configuration
|
||||
* The sampling config is used for std reading and snooping.
|
||||
*
|
||||
* Other functions may read samples and ignore the sampling config,
|
||||
* such as functions to read the UID from a prox tag or similar.
|
||||
*
|
||||
* Values set to '0' implies no change (except for averaging)
|
||||
* @brief setSamplingConfig
|
||||
* @param sc
|
||||
*/
|
||||
void setSamplingConfig(sample_config *sc)
|
||||
{
|
||||
if(sc->divisor != 0) config.divisor = sc->divisor;
|
||||
if(sc->bits_per_sample!= 0) config.bits_per_sample= sc->bits_per_sample;
|
||||
if(sc->decimation!= 0) config.decimation= sc->decimation;
|
||||
if(sc->trigger_threshold != -1) config.trigger_threshold= sc->trigger_threshold;
|
||||
|
||||
config.averaging= sc->averaging;
|
||||
if(config.bits_per_sample > 8) config.bits_per_sample = 8;
|
||||
if(config.decimation < 1) config.decimation = 1;
|
||||
|
||||
printConfig();
|
||||
}
|
||||
|
||||
sample_config* getSamplingConfig()
|
||||
{
|
||||
return &config;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t * buffer;
|
||||
uint32_t numbits;
|
||||
uint32_t position;
|
||||
} BitstreamOut;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Pushes bit onto the stream
|
||||
* @param stream
|
||||
* @param bit
|
||||
*/
|
||||
void pushBit( BitstreamOut* stream, uint8_t bit)
|
||||
{
|
||||
int bytepos = stream->position >> 3; // divide by 8
|
||||
int bitpos = stream->position & 7;
|
||||
*(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos);
|
||||
stream->position++;
|
||||
stream->numbits++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
|
||||
* if not already loaded, sets divisor and starts up the antenna.
|
||||
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
|
||||
* 0 or 95 ==> 125 KHz
|
||||
*
|
||||
**/
|
||||
void LFSetupFPGAForADC(int divisor, bool lf_field)
|
||||
{
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
|
||||
else if (divisor == 0)
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
|
||||
else
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0));
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
// Give it a bit of time for the resonant antenna to settle.
|
||||
SpinDelay(50);
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param silent - is true, now outputs are made. If false, dbprints the status
|
||||
* @return the number of bits occupied by the samples.
|
||||
*/
|
||||
|
||||
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold,bool silent)
|
||||
{
|
||||
//.
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
int bufsize = BIGBUF_SIZE;
|
||||
memset(dest, 0, bufsize);
|
||||
|
||||
if(bits_per_sample < 1) bits_per_sample = 1;
|
||||
if(bits_per_sample > 8) bits_per_sample = 8;
|
||||
|
||||
if(decimation < 1) decimation = 1;
|
||||
|
||||
// Use a bit stream to handle the output
|
||||
BitstreamOut data = { dest , 0, 0};
|
||||
int sample_counter = 0;
|
||||
uint8_t sample = 0;
|
||||
//If we want to do averaging
|
||||
uint32_t sample_sum =0 ;
|
||||
uint32_t sample_total_numbers =0 ;
|
||||
uint32_t sample_total_saved =0 ;
|
||||
|
||||
while(!BUTTON_PRESS()) {
|
||||
WDT_HIT();
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x43;
|
||||
LED_D_ON();
|
||||
}
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
LED_D_OFF();
|
||||
if (trigger_threshold > 0 && sample < trigger_threshold)
|
||||
continue;
|
||||
|
||||
trigger_threshold = 0;
|
||||
sample_total_numbers++;
|
||||
|
||||
if(averaging)
|
||||
{
|
||||
sample_sum += sample;
|
||||
}
|
||||
//Check decimation
|
||||
if(decimation > 1)
|
||||
{
|
||||
sample_counter++;
|
||||
if(sample_counter < decimation) continue;
|
||||
sample_counter = 0;
|
||||
}
|
||||
//Averaging
|
||||
if(averaging && decimation > 1) {
|
||||
sample = sample_sum / decimation;
|
||||
sample_sum =0;
|
||||
}
|
||||
//Store the sample
|
||||
sample_total_saved ++;
|
||||
if(bits_per_sample == 8){
|
||||
dest[sample_total_saved-1] = sample;
|
||||
data.numbits = sample_total_saved << 3;//Get the return value correct
|
||||
if(sample_total_saved >= bufsize) break;
|
||||
}
|
||||
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);
|
||||
//Not needed, 8bps is covered above
|
||||
//if(bits_per_sample > 7) pushBit(&data, sample & 0x01);
|
||||
if((data.numbits >> 3) +1 >= bufsize) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!silent)
|
||||
{
|
||||
Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved, sample_total_numbers,bits_per_sample);
|
||||
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
|
||||
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
|
||||
}
|
||||
return data.numbits;
|
||||
}
|
||||
/**
|
||||
* @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
|
||||
* @param silent
|
||||
* @return number of bits sampled
|
||||
*/
|
||||
uint32_t DoAcquisition_default(int trigger_threshold, bool silent)
|
||||
{
|
||||
return DoAcquisition(1,8,0,trigger_threshold,silent);
|
||||
}
|
||||
uint32_t DoAcquisition_config( bool silent)
|
||||
{
|
||||
return DoAcquisition(config.decimation
|
||||
,config.bits_per_sample
|
||||
,config.averaging
|
||||
,config.trigger_threshold
|
||||
,silent);
|
||||
}
|
||||
|
||||
uint32_t ReadLF(bool activeField)
|
||||
{
|
||||
printConfig();
|
||||
LFSetupFPGAForADC(config.divisor, activeField);
|
||||
// Now call the acquisition routine
|
||||
return DoAcquisition_config(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
**/
|
||||
uint32_t SampleLF()
|
||||
{
|
||||
return ReadLF(true);
|
||||
}
|
||||
/**
|
||||
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
**/
|
||||
|
||||
uint32_t SnoopLF()
|
||||
{
|
||||
return ReadLF(false);
|
||||
}
|
||||
59
armsrc/lfsampling.h
Normal file
59
armsrc/lfsampling.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef LFSAMPLING_H
|
||||
#define LFSAMPLING_H
|
||||
|
||||
/**
|
||||
* Initializes the FPGA for reader-mode (field on), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
**/
|
||||
uint32_t SampleLF();
|
||||
|
||||
/**
|
||||
* Initializes the FPGA for snoop-mode (field off), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
**/
|
||||
|
||||
uint32_t SnoopLF();
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param silent
|
||||
* @return number of bits sampled
|
||||
*/
|
||||
uint32_t DoAcquisition_default(int trigger_threshold, bool silent);
|
||||
/**
|
||||
* @brief Does sample acquisition, using the config values set in the sample_config.
|
||||
* @param trigger_threshold
|
||||
* @param silent
|
||||
* @return number of bits sampled
|
||||
*/
|
||||
|
||||
uint32_t DoAcquisition_config( bool silent);
|
||||
|
||||
/**
|
||||
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
|
||||
* if not already loaded, sets divisor and starts up the antenna.
|
||||
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
|
||||
* 0 or 95 ==> 125 KHz
|
||||
*
|
||||
**/
|
||||
void LFSetupFPGAForADC(int divisor, bool lf_field);
|
||||
|
||||
|
||||
/**
|
||||
* Called from the USB-handler to set the sampling configuration
|
||||
* The sampling config is used for std reading and snooping.
|
||||
*
|
||||
* Other functions may read samples and ignore the sampling config,
|
||||
* such as functions to read the UID from a prox tag or similar.
|
||||
*
|
||||
* Values set to '0' implies no change (except for averaging)
|
||||
* @brief setSamplingConfig
|
||||
* @param sc
|
||||
*/
|
||||
void setSamplingConfig(sample_config *sc);
|
||||
|
||||
sample_config * getSamplingConfig();
|
||||
#endif // LFSAMPLING_H
|
||||
Reference in New Issue
Block a user