mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-19 12:59:44 -07:00
rework iso14443b device functions including FPGA I/Q signal transfer (#669)
* rework iso14443b device functions * hf_read_rx_xcorr.v: transfer i/q pair in one 16bit frame * hi_read_tx.v: invert ssp_dout. When nothing is transferred (ssp_dout=0), this results in no modulation (carrier on) * adjust arm sources accordingly * iso14443b.c: switch off carrier after hf 14b sri512read and hf 14b srix4kread * iso14443b.c: fix DMA circular buffer handling
This commit is contained in:
parent
53edb044c0
commit
6a5d4e17f4
14 changed files with 212 additions and 321 deletions
|
@ -112,10 +112,10 @@ void SetupSpi(int mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Set up the synchronous serial port, with the one set of options that we
|
// Set up the synchronous serial port with the set of options that fits
|
||||||
// always use when we are talking to the FPGA. Both RX and TX are enabled.
|
// the FPGA mode. Both RX and TX are always enabled.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void FpgaSetupSsc(void)
|
void FpgaSetupSsc(uint8_t FPGA_mode)
|
||||||
{
|
{
|
||||||
// First configure the GPIOs, and get ourselves a clock.
|
// First configure the GPIOs, and get ourselves a clock.
|
||||||
AT91C_BASE_PIOA->PIO_ASR =
|
AT91C_BASE_PIOA->PIO_ASR =
|
||||||
|
@ -134,11 +134,15 @@ void FpgaSetupSsc(void)
|
||||||
// on RX clock rising edge, sampled on falling edge
|
// on RX clock rising edge, sampled on falling edge
|
||||||
AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);
|
AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);
|
||||||
|
|
||||||
// 8 bits per transfer, no loopback, MSB first, 1 transfer per sync
|
// 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync
|
||||||
// pulse, no output sync
|
// pulse, no output sync
|
||||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
if ((FPGA_mode & 0xe0) == FPGA_MAJOR_MODE_HF_READER_RX_XCORR) {
|
||||||
|
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||||
|
} else {
|
||||||
|
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||||
|
}
|
||||||
|
|
||||||
// clock comes from TK pin, no clock output, outputs change on falling
|
// TX clock comes from TK pin, no clock output, outputs change on falling
|
||||||
// edge of TK, sample on rising edge of TK, start on positive-going edge of sync
|
// edge of TK, sample on rising edge of TK, start on positive-going edge of sync
|
||||||
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
|
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
|
||||||
|
|
||||||
|
@ -154,16 +158,15 @@ void FpgaSetupSsc(void)
|
||||||
// ourselves, not to another buffer). The stuff to manipulate those buffers
|
// ourselves, not to another buffer). The stuff to manipulate those buffers
|
||||||
// is in apps.h, because it should be inlined, for speed.
|
// is in apps.h, because it should be inlined, for speed.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool FpgaSetupSscDma(uint8_t *buf, int len)
|
bool FpgaSetupSscDma(uint8_t *buf, uint16_t sample_count)
|
||||||
{
|
{
|
||||||
if (buf == NULL) return false;
|
if (buf == NULL) return false;
|
||||||
|
|
||||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
|
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
|
||||||
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address
|
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address
|
||||||
AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes
|
AT91C_BASE_PDC_SSC->PDC_RCR = sample_count; // transfer this many samples
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address
|
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes
|
AT91C_BASE_PDC_SSC->PDC_RNCR = sample_count; // ... with same number of samples AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go!
|
||||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go!
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||||
void FpgaWriteConfWord(uint8_t v);
|
void FpgaWriteConfWord(uint8_t v);
|
||||||
void FpgaDownloadAndGo(int bitstream_version);
|
void FpgaDownloadAndGo(int bitstream_version);
|
||||||
void FpgaSetupSsc(void);
|
void FpgaSetupSsc(uint8_t mode);
|
||||||
void SetupSpi(int mode);
|
void SetupSpi(int mode);
|
||||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||||
void Fpga_print_status();
|
void Fpga_print_status();
|
||||||
|
|
|
@ -37,7 +37,7 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
|
||||||
// Select correct configs
|
// Select correct configs
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
// Set up the synchronous serial port
|
// Set up the synchronous serial port
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||||
// connect Demodulated Signal to ADC:
|
// connect Demodulated Signal to ADC:
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||||
|
|
|
@ -676,7 +676,7 @@ void RAMFUNC SnoopIClass(void)
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
|
|
||||||
// Setup for the DMA.
|
// Setup for the DMA.
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||||
upTo = dmaBuf;
|
upTo = dmaBuf;
|
||||||
lastRxCounter = DMA_BUFFER_SIZE;
|
lastRxCounter = DMA_BUFFER_SIZE;
|
||||||
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
|
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
|
||||||
|
@ -1163,7 +1163,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
|
||||||
StartCountSspClk();
|
StartCountSspClk();
|
||||||
// We need to listen to the high-frequency, peak-detected path.
|
// We need to listen to the high-frequency, peak-detected path.
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||||
|
|
||||||
// To control where we are in the protocol
|
// To control where we are in the protocol
|
||||||
int cmdsRecvd = 0;
|
int cmdsRecvd = 0;
|
||||||
|
@ -1360,7 +1360,7 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
|
||||||
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||||
while(!BUTTON_PRESS()) {
|
while(!BUTTON_PRESS()) {
|
||||||
if((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){
|
if((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){
|
||||||
b = AT91C_BASE_SSC->SSC_RHR; (void) b;
|
b = AT91C_BASE_SSC->SSC_RHR; (void) b;
|
||||||
|
@ -1398,7 +1398,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
|
||||||
int c;
|
int c;
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||||
|
|
||||||
if (wait)
|
if (wait)
|
||||||
{
|
{
|
||||||
|
@ -1586,7 +1586,7 @@ void setupIclassReader()
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
// Setup SSC
|
// Setup SSC
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||||
// Start from off (no field generated)
|
// Start from off (no field generated)
|
||||||
// Signal field is off with the appropriate LED
|
// Signal field is off with the appropriate LED
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
|
|
|
@ -1889,7 +1889,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
|
||||||
void iso14443a_setup(uint8_t fpga_minor_mode) {
|
void iso14443a_setup(uint8_t fpga_minor_mode) {
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
// Set up the synchronous serial port
|
// Set up the synchronous serial port
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||||
// connect Demodulated Signal to ADC:
|
// connect Demodulated Signal to ADC:
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Jonathan Westhues, split Nov 2006
|
// Jonathan Westhues, split Nov 2006
|
||||||
|
// piwi 2018
|
||||||
//
|
//
|
||||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
// 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
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||||
|
@ -16,8 +17,8 @@
|
||||||
|
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
|
|
||||||
#define RECEIVE_SAMPLES_TIMEOUT 2000
|
#define RECEIVE_SAMPLES_TIMEOUT 1000 // TR0 max is 256/fs = 256/(848kHz) = 302us or 64 samples from FPGA. 1000 seems to be much too high?
|
||||||
#define ISO14443B_DMA_BUFFER_SIZE 256
|
#define ISO14443B_DMA_BUFFER_SIZE 128
|
||||||
|
|
||||||
// PCB Block number for APDUs
|
// PCB Block number for APDUs
|
||||||
static uint8_t pcb_blocknum = 0;
|
static uint8_t pcb_blocknum = 0;
|
||||||
|
@ -374,7 +375,7 @@ void SimulateIso14443bTag(void)
|
||||||
|
|
||||||
// We need to listen to the high-frequency, peak-detected path.
|
// We need to listen to the high-frequency, peak-detected path.
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||||
|
|
||||||
cmdsRecvd = 0;
|
cmdsRecvd = 0;
|
||||||
|
|
||||||
|
@ -440,7 +441,7 @@ void SimulateIso14443bTag(void)
|
||||||
LED_D_OFF();
|
LED_D_OFF();
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
|
||||||
AT91C_BASE_SSC->SSC_THR = 0xff;
|
AT91C_BASE_SSC->SSC_THR = 0xff;
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||||
|
|
||||||
// Transmit the response.
|
// Transmit the response.
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
|
@ -535,60 +536,11 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
|
||||||
|
|
||||||
#define SUBCARRIER_DETECT_THRESHOLD 8
|
#define SUBCARRIER_DETECT_THRESHOLD 8
|
||||||
|
|
||||||
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq)
|
|
||||||
/* #define CHECK_FOR_SUBCARRIER() { \
|
|
||||||
v = ci; \
|
|
||||||
if(v < 0) v = -v; \
|
|
||||||
if(cq > 0) { \
|
|
||||||
v += cq; \
|
|
||||||
} else { \
|
|
||||||
v -= cq; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
|
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
|
||||||
|
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
|
||||||
//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
|
|
||||||
#define CHECK_FOR_SUBCARRIER() { \
|
|
||||||
v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if(ci < 0) { \
|
|
||||||
if(cq < 0) { \ // ci < 0, cq < 0
|
|
||||||
if (cq < ci) { \
|
|
||||||
v = -cq - (ci >> 1); \
|
|
||||||
} else { \
|
|
||||||
v = -ci - (cq >> 1); \
|
|
||||||
} \
|
|
||||||
} else { \ // ci < 0, cq >= 0
|
|
||||||
if (cq < -ci) { \
|
|
||||||
v = -ci + (cq >> 1); \
|
|
||||||
} else { \
|
|
||||||
v = cq - (ci >> 1); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
if(cq < 0) { \ // ci >= 0, cq < 0
|
|
||||||
if (-cq < ci) { \
|
|
||||||
v = ci - (cq >> 1); \
|
|
||||||
} else { \
|
|
||||||
v = -cq + (ci >> 1); \
|
|
||||||
} \
|
|
||||||
} else { \ // ci >= 0, cq >= 0
|
|
||||||
if (cq < ci) { \
|
|
||||||
v = ci + (cq >> 1); \
|
|
||||||
} else { \
|
|
||||||
v = cq + (ci >> 1); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch(Demod.state) {
|
switch(Demod.state) {
|
||||||
case DEMOD_UNSYNCD:
|
case DEMOD_UNSYNCD:
|
||||||
CHECK_FOR_SUBCARRIER();
|
if(AMPLITUDE(ci,cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
|
||||||
if(v > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
|
|
||||||
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
||||||
Demod.sumI = ci;
|
Demod.sumI = ci;
|
||||||
Demod.sumQ = cq;
|
Demod.sumQ = cq;
|
||||||
|
@ -598,8 +550,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
|
||||||
|
|
||||||
case DEMOD_PHASE_REF_TRAINING:
|
case DEMOD_PHASE_REF_TRAINING:
|
||||||
if(Demod.posCount < 8) {
|
if(Demod.posCount < 8) {
|
||||||
CHECK_FOR_SUBCARRIER();
|
if (AMPLITUDE(ci,cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||||
if (v > SUBCARRIER_DETECT_THRESHOLD) {
|
|
||||||
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
||||||
// note: synchronization time > 80 1/fs
|
// note: synchronization time > 80 1/fs
|
||||||
Demod.sumI += ci;
|
Demod.sumI += ci;
|
||||||
|
@ -743,10 +694,11 @@ static void DemodInit(uint8_t *data)
|
||||||
*/
|
*/
|
||||||
static void GetSamplesFor14443bDemod(int n, bool quiet)
|
static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||||
{
|
{
|
||||||
int max = 0;
|
int maxBehindBy = 0;
|
||||||
bool gotFrame = false;
|
bool gotFrame = false;
|
||||||
int lastRxCounter, ci, cq, samples = 0;
|
int lastRxCounter, samples = 0;
|
||||||
|
int8_t ci, cq;
|
||||||
|
|
||||||
// Allocate memory from BigBuf for some buffers
|
// Allocate memory from BigBuf for some buffers
|
||||||
// free all previous allocations first
|
// free all previous allocations first
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
@ -755,15 +707,19 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||||
uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
|
uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
uint16_t *dmaBuf = (uint16_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE * sizeof(uint16_t));
|
||||||
|
|
||||||
// Set up the demodulator for tag -> reader responses.
|
// Set up the demodulator for tag -> reader responses.
|
||||||
DemodInit(receivedResponse);
|
DemodInit(receivedResponse);
|
||||||
|
|
||||||
|
// wait for last transfer to complete
|
||||||
|
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY))
|
||||||
|
|
||||||
// Setup and start DMA.
|
// Setup and start DMA.
|
||||||
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
||||||
|
|
||||||
int8_t *upTo = dmaBuf;
|
uint16_t *upTo = dmaBuf;
|
||||||
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
||||||
|
|
||||||
// Signal field is ON with the appropriate LED:
|
// Signal field is ON with the appropriate LED:
|
||||||
|
@ -772,39 +728,40 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
|
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1);
|
||||||
if(behindBy > max) max = behindBy;
|
if(behindBy > maxBehindBy) {
|
||||||
|
maxBehindBy = behindBy;
|
||||||
while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1)) > 2) {
|
|
||||||
ci = upTo[0];
|
|
||||||
cq = upTo[1];
|
|
||||||
upTo += 2;
|
|
||||||
if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
|
|
||||||
upTo = dmaBuf;
|
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
|
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
|
|
||||||
}
|
|
||||||
lastRxCounter -= 2;
|
|
||||||
if(lastRxCounter <= 0) {
|
|
||||||
lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
samples += 2;
|
|
||||||
|
|
||||||
if(Handle14443bSamplesDemod(ci, cq)) {
|
|
||||||
gotFrame = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(samples > n || gotFrame) {
|
if(behindBy < 1) continue;
|
||||||
|
|
||||||
|
ci = *upTo >> 8;
|
||||||
|
cq = *upTo;
|
||||||
|
upTo++;
|
||||||
|
lastRxCounter--;
|
||||||
|
if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content.
|
||||||
|
upTo = dmaBuf; // start reading the circular buffer from the beginning
|
||||||
|
lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated.
|
||||||
|
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and
|
||||||
|
AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; // DMA Next Counter registers
|
||||||
|
}
|
||||||
|
samples++;
|
||||||
|
|
||||||
|
if(Handle14443bSamplesDemod(ci, cq)) {
|
||||||
|
gotFrame = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(samples > n) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
FpgaDisableSscDma();
|
||||||
|
|
||||||
if (!quiet) Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d", max, samples, gotFrame, Demod.len, Demod.sumI, Demod.sumQ);
|
if (!quiet) Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d", maxBehindBy, samples, gotFrame, Demod.len, Demod.sumI, Demod.sumQ);
|
||||||
//Tracing
|
//Tracing
|
||||||
if (tracing && Demod.len > 0) {
|
if (tracing && Demod.len > 0) {
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
|
@ -820,11 +777,7 @@ static void TransmitFor14443b(void)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
|
|
||||||
while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signal field is ON with the appropriate Red LED
|
// Signal field is ON with the appropriate Red LED
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
@ -832,31 +785,15 @@ static void TransmitFor14443b(void)
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||||
|
|
||||||
for(c = 0; c < 10;) {
|
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
|
||||||
AT91C_BASE_SSC->SSC_THR = 0xff;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
|
||||||
volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
(void)r;
|
|
||||||
}
|
|
||||||
WDT_HIT();
|
|
||||||
}
|
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = ToSend[c];
|
AT91C_BASE_SSC->SSC_THR = ~ToSend[c];
|
||||||
c++;
|
c++;
|
||||||
if(c >= ToSendMax) {
|
if(c >= ToSendMax) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
|
||||||
volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
(void)r;
|
|
||||||
}
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
}
|
}
|
||||||
LED_B_OFF(); // Finished sending
|
LED_B_OFF(); // Finished sending
|
||||||
|
@ -874,19 +811,14 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
|
||||||
|
|
||||||
ToSendReset();
|
ToSendReset();
|
||||||
|
|
||||||
// Establish initial reference level
|
|
||||||
for(i = 0; i < 40; i++) {
|
|
||||||
ToSendStuffBit(1);
|
|
||||||
}
|
|
||||||
// Send SOF
|
// Send SOF
|
||||||
for(i = 0; i < 10; i++) {
|
for(i = 0; i < 10; i++) {
|
||||||
ToSendStuffBit(0);
|
ToSendStuffBit(0);
|
||||||
}
|
}
|
||||||
|
ToSendStuffBit(1);
|
||||||
|
ToSendStuffBit(1);
|
||||||
|
|
||||||
for(i = 0; i < len; i++) {
|
for(i = 0; i < len; i++) {
|
||||||
// Stop bits/EGT
|
|
||||||
ToSendStuffBit(1);
|
|
||||||
ToSendStuffBit(1);
|
|
||||||
// Start bit
|
// Start bit
|
||||||
ToSendStuffBit(0);
|
ToSendStuffBit(0);
|
||||||
// Data bits
|
// Data bits
|
||||||
|
@ -899,19 +831,18 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
|
||||||
}
|
}
|
||||||
b >>= 1;
|
b >>= 1;
|
||||||
}
|
}
|
||||||
}
|
// Stop bit
|
||||||
// Send EOF
|
|
||||||
ToSendStuffBit(1);
|
|
||||||
for(i = 0; i < 10; i++) {
|
|
||||||
ToSendStuffBit(0);
|
|
||||||
}
|
|
||||||
for(i = 0; i < 8; i++) {
|
|
||||||
ToSendStuffBit(1);
|
ToSendStuffBit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And then a little more, to make sure that the last character makes
|
// Send EOF
|
||||||
// it out before we switch to rx mode.
|
for(i = 0; i < 10; i++) {
|
||||||
for(i = 0; i < 24; i++) {
|
ToSendStuffBit(0);
|
||||||
|
}
|
||||||
|
ToSendStuffBit(1);
|
||||||
|
|
||||||
|
// ensure that last byte is filled up
|
||||||
|
for(i = 0; i < 8; i++) {
|
||||||
ToSendStuffBit(1);
|
ToSendStuffBit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,7 +882,7 @@ int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *respo
|
||||||
// send
|
// send
|
||||||
CodeAndTransmit14443bAsReader(message_frame, message_length + 4);
|
CodeAndTransmit14443bAsReader(message_frame, message_length + 4);
|
||||||
// get response
|
// get response
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, true);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
if(Demod.len < 3)
|
if(Demod.len < 3)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1011,7 +942,7 @@ int iso14443b_select_card()
|
||||||
void iso14443b_setup() {
|
void iso14443b_setup() {
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
// Set up the synchronous serial port
|
// Set up the synchronous serial port
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
// connect Demodulated Signal to ADC:
|
// connect Demodulated Signal to ADC:
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
|
@ -1019,9 +950,6 @@ void iso14443b_setup() {
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||||
|
|
||||||
// Start the timer
|
|
||||||
StartCountSspClk();
|
|
||||||
|
|
||||||
DemodReset();
|
DemodReset();
|
||||||
UartReset();
|
UartReset();
|
||||||
}
|
}
|
||||||
|
@ -1047,7 +975,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
SpinDelay(200);
|
SpinDelay(200);
|
||||||
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
// Now give it time to spin up.
|
// Now give it time to spin up.
|
||||||
// Signal field is on with the appropriate LED
|
// Signal field is on with the appropriate LED
|
||||||
|
@ -1065,6 +993,8 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
|
|
||||||
if (Demod.len == 0) {
|
if (Demod.len == 0) {
|
||||||
DbpString("No response from tag");
|
DbpString("No response from tag");
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x",
|
Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x",
|
||||||
|
@ -1080,17 +1010,23 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
if (Demod.len != 3) {
|
if (Demod.len != 3) {
|
||||||
Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
|
Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check the CRC of the answer:
|
// Check the CRC of the answer:
|
||||||
ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
|
ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
|
||||||
if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
|
if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
|
||||||
DbpString("CRC Error reading select response.");
|
DbpString("CRC Error reading select response.");
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check response from the tag: should be the same UID as the command we just sent:
|
// Check response from the tag: should be the same UID as the command we just sent:
|
||||||
if (cmd1[1] != Demod.output[0]) {
|
if (cmd1[1] != Demod.output[0]) {
|
||||||
Dbprintf("Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]);
|
Dbprintf("Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]);
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,6 +1038,8 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
if (Demod.len != 10) {
|
if (Demod.len != 10) {
|
||||||
Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
|
Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The check the CRC of the answer (use cmd1 as temporary variable):
|
// The check the CRC of the answer (use cmd1 as temporary variable):
|
||||||
|
@ -1131,6 +1069,8 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||||
if (Demod.len != 6) { // Check if we got an answer from the tag
|
if (Demod.len != 6) { // Check if we got an answer from the tag
|
||||||
DbpString("Expected 6 bytes from tag, got less...");
|
DbpString("Expected 6 bytes from tag, got less...");
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The check the CRC of the answer (use cmd1 as temporary variable):
|
// The check the CRC of the answer (use cmd1 as temporary variable):
|
||||||
|
@ -1149,6 +1089,9 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LED_D_OFF();
|
||||||
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1171,11 +1114,6 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
||||||
*/
|
*/
|
||||||
void RAMFUNC SnoopIso14443b(void)
|
void RAMFUNC SnoopIso14443b(void)
|
||||||
{
|
{
|
||||||
// We won't start recording the frames that we acquire until we trigger;
|
|
||||||
// a good trigger condition to get started is probably when we see a
|
|
||||||
// response from the tag.
|
|
||||||
int triggered = true; // TODO: set and evaluate trigger condition
|
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
|
|
||||||
|
@ -1183,10 +1121,10 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
||||||
// The DMA buffer, used to stream samples from the FPGA
|
// The DMA buffer, used to stream samples from the FPGA
|
||||||
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
|
uint16_t *dmaBuf = (uint16_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE * sizeof(uint16_t));
|
||||||
int lastRxCounter;
|
int lastRxCounter;
|
||||||
int8_t *upTo;
|
uint16_t *upTo;
|
||||||
int ci, cq;
|
int8_t ci, cq;
|
||||||
int maxBehindBy = 0;
|
int maxBehindBy = 0;
|
||||||
|
|
||||||
// Count of samples received so far, so that we can include timing
|
// Count of samples received so far, so that we can include timing
|
||||||
|
@ -1211,7 +1149,7 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
// Setup for the DMA.
|
// Setup for the DMA.
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
upTo = dmaBuf;
|
upTo = dmaBuf;
|
||||||
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
||||||
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
||||||
|
@ -1219,46 +1157,48 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
|
|
||||||
bool TagIsActive = false;
|
bool TagIsActive = false;
|
||||||
bool ReaderIsActive = false;
|
bool ReaderIsActive = false;
|
||||||
|
// We won't start recording the frames that we acquire until we trigger.
|
||||||
|
// A good trigger condition to get started is probably when we see a
|
||||||
|
// reader command
|
||||||
|
bool triggered = false;
|
||||||
|
|
||||||
// And now we loop, receiving samples.
|
// And now we loop, receiving samples.
|
||||||
for(;;) {
|
for(;;) {
|
||||||
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
|
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1);
|
||||||
(ISO14443B_DMA_BUFFER_SIZE-1);
|
|
||||||
if(behindBy > maxBehindBy) {
|
if(behindBy > maxBehindBy) {
|
||||||
maxBehindBy = behindBy;
|
maxBehindBy = behindBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(behindBy < 2) continue;
|
if(behindBy < 1) continue;
|
||||||
|
|
||||||
ci = upTo[0];
|
ci = *upTo>>8;
|
||||||
cq = upTo[1];
|
cq = *upTo;
|
||||||
upTo += 2;
|
upTo++;
|
||||||
lastRxCounter -= 2;
|
lastRxCounter--;
|
||||||
if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
|
if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content.
|
||||||
upTo = dmaBuf;
|
upTo = dmaBuf; // start reading the circular buffer from the beginning again
|
||||||
lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
|
lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
|
if(behindBy > (9*ISO14443B_DMA_BUFFER_SIZE/10)) {
|
||||||
AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
|
Dbprintf("About to blow circular buffer - aborted! behindBy=%d", behindBy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated.
|
||||||
|
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and
|
||||||
|
AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; // DMA Next Counter registers
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if(behindBy > (9*ISO14443B_DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
|
|
||||||
Dbprintf("blew circular buffer! behindBy=%d", behindBy);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!tracing) {
|
|
||||||
DbpString("Reached trace limit");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(BUTTON_PRESS()) {
|
if(BUTTON_PRESS()) {
|
||||||
DbpString("cancelled");
|
DbpString("cancelled");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
samples += 2;
|
samples++;
|
||||||
|
|
||||||
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
||||||
if(Handle14443bUartBit(ci & 0x01)) {
|
if(Handle14443bUartBit(ci & 0x01)) {
|
||||||
if(triggered && tracing) {
|
triggered = true;
|
||||||
|
if(tracing) {
|
||||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
||||||
}
|
}
|
||||||
/* And ready to receive another command. */
|
/* And ready to receive another command. */
|
||||||
|
@ -1268,7 +1208,8 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
DemodReset();
|
DemodReset();
|
||||||
}
|
}
|
||||||
if(Handle14443bUartBit(cq & 0x01)) {
|
if(Handle14443bUartBit(cq & 0x01)) {
|
||||||
if(triggered && tracing) {
|
triggered = true;
|
||||||
|
if(tracing) {
|
||||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
||||||
}
|
}
|
||||||
/* And ready to receive another command. */
|
/* And ready to receive another command. */
|
||||||
|
@ -1280,8 +1221,8 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
|
ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time
|
if(!ReaderIsActive && triggered) { // no need to try decoding tag data if the reader is sending or not yet triggered
|
||||||
if(Handle14443bSamplesDemod(ci | 0x01, cq | 0x01)) {
|
if(Handle14443bSamplesDemod(ci/2, cq/2)) {
|
||||||
|
|
||||||
//Use samples as a time measurement
|
//Use samples as a time measurement
|
||||||
if(tracing)
|
if(tracing)
|
||||||
|
@ -1289,8 +1230,6 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
uint8_t parity[MAX_PARITY_SIZE];
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
LogTrace(Demod.output, Demod.len, samples, samples, parity, false);
|
LogTrace(Demod.output, Demod.len, samples, samples, parity, false);
|
||||||
}
|
}
|
||||||
triggered = true;
|
|
||||||
|
|
||||||
// And ready to receive another response.
|
// And ready to receive another response.
|
||||||
DemodReset();
|
DemodReset();
|
||||||
}
|
}
|
||||||
|
@ -1301,7 +1240,6 @@ void RAMFUNC SnoopIso14443b(void)
|
||||||
|
|
||||||
FpgaDisableSscDma();
|
FpgaDisableSscDma();
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
|
||||||
DbpString("Snoop statistics:");
|
DbpString("Snoop statistics:");
|
||||||
Dbprintf(" Max behind by: %i", maxBehindBy);
|
Dbprintf(" Max behind by: %i", maxBehindBy);
|
||||||
Dbprintf(" Uart State: %x", Uart.state);
|
Dbprintf(" Uart State: %x", Uart.state);
|
||||||
|
@ -1327,7 +1265,11 @@ void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, u
|
||||||
{
|
{
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
|
||||||
|
// switch field on and give tag some time to power up
|
||||||
|
LED_D_ON();
|
||||||
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
|
SpinDelay(10);
|
||||||
|
|
||||||
if (datalen){
|
if (datalen){
|
||||||
set_tracing(true);
|
set_tracing(true);
|
||||||
|
|
|
@ -227,26 +227,14 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
if(*wait < 10) { *wait = 10; }
|
if(*wait < 10) { *wait = 10; }
|
||||||
|
|
||||||
// for(c = 0; c < *wait;) {
|
|
||||||
// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
|
||||||
// AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
|
|
||||||
// c++;
|
|
||||||
// }
|
|
||||||
// if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
|
||||||
// volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
// (void)r;
|
|
||||||
// }
|
|
||||||
// WDT_HIT();
|
|
||||||
// }
|
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = cmd[c];
|
AT91C_BASE_SSC->SSC_THR = ~cmd[c];
|
||||||
c++;
|
c++;
|
||||||
if(c >= len) {
|
if(c >= len) {
|
||||||
break;
|
break;
|
||||||
|
@ -300,36 +288,25 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int getNext = 0;
|
|
||||||
|
|
||||||
int8_t prev = 0;
|
|
||||||
|
|
||||||
// NOW READ RESPONSE
|
// NOW READ RESPONSE
|
||||||
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = false;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
int8_t b;
|
uint16_t iq = AT91C_BASE_SSC->SSC_RHR;
|
||||||
b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
|
|
||||||
// The samples are correlations against I and Q versions of the
|
// The samples are correlations against I and Q versions of the
|
||||||
// tone that the tag AM-modulates, so every other sample is I,
|
// tone that the tag AM-modulates. We just want power.
|
||||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
int8_t i = iq >> 8;
|
||||||
// close to what we want.
|
int8_t q = iq;
|
||||||
if(getNext) {
|
uint8_t r = AMPLITUDE(i, q);
|
||||||
uint8_t r = AMPLITUDE(b, prev);
|
|
||||||
|
|
||||||
dest[c++] = r;
|
dest[c++] = r;
|
||||||
|
|
||||||
if(c >= 4000) {
|
if(c >= 4000) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
prev = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNext = !getNext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,36 +418,26 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
int getNext = 0;
|
|
||||||
|
|
||||||
int8_t prev = 0;
|
|
||||||
|
|
||||||
// NOW READ RESPONSE
|
// NOW READ RESPONSE
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = false;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint16_t iq = AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
|
||||||
// The samples are correlations against I and Q versions of the
|
// The samples are correlations against I and Q versions of the
|
||||||
// tone that the tag AM-modulates, so every other sample is I,
|
// tone that the tag AM-modulates. We just want power,
|
||||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
// so abs(I) + abs(Q) is close to what we want.
|
||||||
// close to what we want.
|
int8_t i = iq >> 8;
|
||||||
if(getNext) {
|
int8_t q = iq;
|
||||||
uint8_t r = AMPLITUDE(b, prev);
|
uint8_t r = AMPLITUDE(i, q);
|
||||||
|
|
||||||
dest[c++] = r;
|
dest[c++] = r;
|
||||||
|
|
||||||
if(c >= BIGBUF_SIZE) {
|
if(c >= BIGBUF_SIZE) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
prev = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNext = !getNext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,8 +552,6 @@ void AcquireRawAdcSamplesIso15693(void)
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
int getNext = 0;
|
|
||||||
int8_t prev = 0;
|
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
BuildIdentifyRequest();
|
BuildIdentifyRequest();
|
||||||
|
@ -598,13 +563,13 @@ void AcquireRawAdcSamplesIso15693(void)
|
||||||
SpinDelay(100);
|
SpinDelay(100);
|
||||||
|
|
||||||
// Now send the command
|
// Now send the command
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||||
AT91C_BASE_SSC->SSC_THR = ToSend[c];
|
AT91C_BASE_SSC->SSC_THR = ~ToSend[c];
|
||||||
c++;
|
c++;
|
||||||
if(c == ToSendMax+3) {
|
if(c == ToSendMax+3) {
|
||||||
break;
|
break;
|
||||||
|
@ -613,32 +578,25 @@ void AcquireRawAdcSamplesIso15693(void)
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = false;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
int8_t b;
|
uint16_t iq = AT91C_BASE_SSC->SSC_RHR;
|
||||||
b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
|
|
||||||
// The samples are correlations against I and Q versions of the
|
// The samples are correlations against I and Q versions of the
|
||||||
// tone that the tag AM-modulates, so every other sample is I,
|
// tone that the tag AM-modulates. We just want power,
|
||||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
// so abs(I) + abs(Q) is close to what we want.
|
||||||
// close to what we want.
|
int8_t i = iq >> 8;
|
||||||
if(getNext) {
|
int8_t q = iq;
|
||||||
uint8_t r = AMPLITUDE(b, prev);
|
uint8_t r = AMPLITUDE(i, q);
|
||||||
|
|
||||||
dest[c++] = r;
|
dest[c++] = r;
|
||||||
|
|
||||||
if(c >= 4000) {
|
if(c >= 4000) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
prev = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNext = !getNext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,16 +607,14 @@ void RecordRawAdcSamplesIso15693(void)
|
||||||
uint8_t *dest = BigBuf_get_addr();
|
uint8_t *dest = BigBuf_get_addr();
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
int getNext = 0;
|
|
||||||
int8_t prev = 0;
|
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
// Setup SSC
|
// Setup SSC
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
// Start from off (no field generated)
|
// Start from off (no field generated)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
SpinDelay(200);
|
SpinDelay(200);
|
||||||
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
|
@ -667,33 +623,24 @@ void RecordRawAdcSamplesIso15693(void)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
getNext = false;
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
int8_t b;
|
uint16_t iq = AT91C_BASE_SSC->SSC_RHR;
|
||||||
b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
||||||
|
|
||||||
// The samples are correlations against I and Q versions of the
|
// The samples are correlations against I and Q versions of the
|
||||||
// tone that the tag AM-modulates, so every other sample is I,
|
// tone that the tag AM-modulates. We just want power,
|
||||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
// so abs(I) + abs(Q) is close to what we want.
|
||||||
// close to what we want.
|
int8_t i = iq >> 8;
|
||||||
if(getNext) {
|
int8_t q = iq;
|
||||||
uint8_t r = AMPLITUDE(b, prev);
|
uint8_t r = AMPLITUDE(i, q);
|
||||||
|
|
||||||
dest[c++] = r;
|
dest[c++] = r;
|
||||||
|
|
||||||
if(c >= 14000) {
|
if(c >= 14000) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
prev = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNext = !getNext;
|
|
||||||
WDT_HIT();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dbprintf("fin record");
|
Dbprintf("finished recording");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -714,7 +661,7 @@ void Iso15693InitReader() {
|
||||||
SpinDelay(10);
|
SpinDelay(10);
|
||||||
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
// Give the tags time to energize
|
// Give the tags time to energize
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
@ -973,7 +920,7 @@ void ReaderIso15693(uint32_t parameter)
|
||||||
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
// Setup SSC
|
// Setup SSC
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
// Start from off (no field generated)
|
// Start from off (no field generated)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
@ -1075,7 +1022,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
||||||
memset(buf, 0x00, 100);
|
memset(buf, 0x00, 100);
|
||||||
|
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
// Start from off (no field generated)
|
// Start from off (no field generated)
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
|
|
|
@ -63,11 +63,11 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
|
||||||
// I/O interface abstraction (FPGA -> ARM)
|
// I/O interface abstraction (FPGA -> ARM)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static inline uint8_t rx_byte_from_fpga() {
|
static inline uint16_t rx_frame_from_fpga() {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
// wait for byte be become available in rx holding register
|
// wait for frame be become available in rx holding register
|
||||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
return AT91C_BASE_SSC->SSC_RHR;
|
return AT91C_BASE_SSC->SSC_RHR;
|
||||||
}
|
}
|
||||||
|
@ -88,33 +88,32 @@ static inline uint8_t rx_byte_from_fpga() {
|
||||||
// To reduce CPU time the amplitude is approximated by using linear functions:
|
// To reduce CPU time the amplitude is approximated by using linear functions:
|
||||||
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
|
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
|
||||||
//
|
//
|
||||||
// Note: The SSC receiver is never synchronized the calculation my be performed
|
|
||||||
// on a I/Q pair from two subsequent correlations, but does not matter.
|
|
||||||
//
|
|
||||||
// The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
|
// The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
|
||||||
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
|
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
|
||||||
// also.
|
// also.
|
||||||
//
|
//
|
||||||
// The demedulated should be alligned to the bit periode by the caller. This is
|
// The demodulated should be alligned to the bit period by the caller. This is
|
||||||
// done in rx_bit and rx_ack.
|
// done in rx_bit and rx_ack.
|
||||||
static inline bool rx_bit() {
|
static inline bool rx_bit() {
|
||||||
int32_t cq = 0;
|
int32_t sum_cq = 0;
|
||||||
int32_t ci = 0;
|
int32_t sum_ci = 0;
|
||||||
|
|
||||||
// skip first 5 I/Q pairs
|
// skip first 5 I/Q pairs
|
||||||
for(size_t i = 0; i<5; ++i) {
|
for(size_t i = 0; i<5; ++i) {
|
||||||
(int8_t)rx_byte_from_fpga();
|
(void)rx_frame_from_fpga();
|
||||||
(int8_t)rx_byte_from_fpga();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sample next 8 I/Q pairs
|
// sample next 8 I/Q pairs
|
||||||
for(size_t i = 0; i<8; ++i) {
|
for(size_t i = 0; i<8; ++i) {
|
||||||
cq += (int8_t)rx_byte_from_fpga();
|
uint16_t iq = rx_frame_from_fpga();
|
||||||
ci += (int8_t)rx_byte_from_fpga();
|
int8_t ci = (int8_t)(iq >> 8);
|
||||||
|
int8_t cq = (int8_t)(iq & 0xff);
|
||||||
|
sum_ci += ci;
|
||||||
|
sum_cq += cq;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate power
|
// calculate power
|
||||||
int32_t power = (MAX(ABS(ci), ABS(cq)) + (MIN(ABS(ci), ABS(cq)) >> 1));
|
int32_t power = (MAX(ABS(sum_ci), ABS(sum_cq)) + MIN(ABS(sum_ci), ABS(sum_cq))/2);
|
||||||
|
|
||||||
// compare average (power / 8) to threshold
|
// compare average (power / 8) to threshold
|
||||||
return ((power >> 3) > INPUT_THRESHOLD);
|
return ((power >> 3) > INPUT_THRESHOLD);
|
||||||
|
@ -131,12 +130,12 @@ static inline bool rx_bit() {
|
||||||
|
|
||||||
static inline void tx_bit(bool bit) {
|
static inline void tx_bit(bool bit) {
|
||||||
// insert pause
|
// insert pause
|
||||||
LOW(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
last_frame_end += RWD_TIME_PAUSE;
|
last_frame_end += RWD_TIME_PAUSE;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while(GET_TICKS < last_frame_end) { };
|
||||||
HIGH(GPIO_SSC_DOUT);
|
|
||||||
|
|
||||||
// return to high, wait for bit periode to end
|
// return to carrier on, wait for bit periode to end
|
||||||
|
LOW(GPIO_SSC_DOUT);
|
||||||
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
|
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while(GET_TICKS < last_frame_end) { };
|
||||||
}
|
}
|
||||||
|
@ -166,10 +165,10 @@ static void tx_frame(uint32_t frame, uint8_t len) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// add pause to mark end of the frame
|
// add pause to mark end of the frame
|
||||||
LOW(GPIO_SSC_DOUT);
|
HIGH(GPIO_SSC_DOUT);
|
||||||
last_frame_end += RWD_TIME_PAUSE;
|
last_frame_end += RWD_TIME_PAUSE;
|
||||||
while(GET_TICKS < last_frame_end) { };
|
while(GET_TICKS < last_frame_end) { };
|
||||||
HIGH(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t rx_frame(uint8_t len) {
|
static uint32_t rx_frame(uint8_t len) {
|
||||||
|
@ -265,12 +264,12 @@ static void init_reader(bool clear_mem) {
|
||||||
LED_D_ON();
|
LED_D_ON();
|
||||||
|
|
||||||
// configure SSC with defaults
|
// configure SSC with defaults
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||||
|
|
||||||
// re-claim GPIO_SSC_DOUT as GPIO and enable output
|
// re-claim GPIO_SSC_DOUT as GPIO and enable output
|
||||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||||
HIGH(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
|
|
||||||
// init crc calculator
|
// init crc calculator
|
||||||
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
|
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
|
||||||
|
|
|
@ -284,7 +284,7 @@ static void init_tag() {
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
// configure SSC with defaults
|
// configure SSC with defaults
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||||
|
|
||||||
// first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT
|
// first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
|
|
|
@ -1818,7 +1818,7 @@ void Cotag(uint32_t arg0) {
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||||
|
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_ADC);
|
||||||
|
|
||||||
// start clock - 1.5ticks is 1us
|
// start clock - 1.5ticks is 1us
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
|
|
@ -101,7 +101,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field)
|
||||||
// Give it a bit of time for the resonant antenna to settle.
|
// Give it a bit of time for the resonant antenna to settle.
|
||||||
SpinDelay(50);
|
SpinDelay(50);
|
||||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||||
FpgaSetupSsc();
|
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_ADC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
|
@ -197,9 +197,9 @@ begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35
|
// set ssp_frame signal for corr_i_cnt = 0..3
|
||||||
// (send two frames with 8 Bits each)
|
// (send one frame with 16 Bits)
|
||||||
if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000)
|
if(corr_i_cnt[5:2] == 4'b0000)
|
||||||
ssp_frame = 1'b1;
|
ssp_frame = 1'b1;
|
||||||
else
|
else
|
||||||
ssp_frame = 1'b0;
|
ssp_frame = 1'b0;
|
||||||
|
|
|
@ -42,11 +42,11 @@ begin
|
||||||
pwr_hi <= ck_1356megb;
|
pwr_hi <= ck_1356megb;
|
||||||
pwr_oe1 <= 1'b0;
|
pwr_oe1 <= 1'b0;
|
||||||
pwr_oe3 <= 1'b0;
|
pwr_oe3 <= 1'b0;
|
||||||
pwr_oe4 <= ~ssp_dout;
|
pwr_oe4 <= ssp_dout;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
pwr_hi <= ck_1356megb & ssp_dout;
|
pwr_hi <= ck_1356megb & ~ssp_dout;
|
||||||
pwr_oe1 <= 1'b0;
|
pwr_oe1 <= 1'b0;
|
||||||
pwr_oe3 <= 1'b0;
|
pwr_oe3 <= 1'b0;
|
||||||
pwr_oe4 <= 1'b0;
|
pwr_oe4 <= 1'b0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue