mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-19 21:03:23 -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
|
||||
// always use when we are talking to the FPGA. Both RX and TX are enabled.
|
||||
// Set up the synchronous serial port with the set of options that fits
|
||||
// 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.
|
||||
AT91C_BASE_PIOA->PIO_ASR =
|
||||
|
@ -134,11 +134,15 @@ void FpgaSetupSsc(void)
|
|||
// on RX clock rising edge, sampled on falling edge
|
||||
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
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
|
||||
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_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_RNCR = len; // ... with same number of bytes
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go!
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = sample_count; // ... with same number of samples AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go!
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
void FpgaSendCommand(uint16_t cmd, uint16_t v);
|
||||
void FpgaWriteConfWord(uint8_t v);
|
||||
void FpgaDownloadAndGo(int bitstream_version);
|
||||
void FpgaSetupSsc(void);
|
||||
void FpgaSetupSsc(uint8_t mode);
|
||||
void SetupSpi(int mode);
|
||||
bool FpgaSetupSscDma(uint8_t *buf, int len);
|
||||
void Fpga_print_status();
|
||||
|
|
|
@ -37,7 +37,7 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
|
|||
// Select correct configs
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
|
||||
|
|
|
@ -676,7 +676,7 @@ void RAMFUNC SnoopIClass(void)
|
|||
Demod.state = DEMOD_UNSYNCD;
|
||||
|
||||
// Setup for the DMA.
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
upTo = dmaBuf;
|
||||
lastRxCounter = DMA_BUFFER_SIZE;
|
||||
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
|
||||
|
@ -1163,7 +1163,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
|
|||
StartCountSspClk();
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
|
||||
// To control where we are in the protocol
|
||||
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);
|
||||
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
while(!BUTTON_PRESS()) {
|
||||
if((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){
|
||||
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;
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
|
||||
if (wait)
|
||||
{
|
||||
|
@ -1586,7 +1586,7 @@ void setupIclassReader()
|
|||
clear_trace();
|
||||
|
||||
// Setup SSC
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
// Start from off (no field generated)
|
||||
// Signal field is off with the appropriate LED
|
||||
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) {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A);
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, split Nov 2006
|
||||
// piwi 2018
|
||||
//
|
||||
// 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
|
||||
|
@ -16,8 +17,8 @@
|
|||
|
||||
#include "iso14443crc.h"
|
||||
|
||||
#define RECEIVE_SAMPLES_TIMEOUT 2000
|
||||
#define ISO14443B_DMA_BUFFER_SIZE 256
|
||||
#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 128
|
||||
|
||||
// PCB Block number for APDUs
|
||||
static uint8_t pcb_blocknum = 0;
|
||||
|
@ -374,7 +375,7 @@ void SimulateIso14443bTag(void)
|
|||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
|
||||
cmdsRecvd = 0;
|
||||
|
||||
|
@ -440,7 +441,7 @@ void SimulateIso14443bTag(void)
|
|||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
|
||||
AT91C_BASE_SSC->SSC_THR = 0xff;
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
|
||||
|
||||
// Transmit the response.
|
||||
uint16_t i = 0;
|
||||
|
@ -535,60 +536,11 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
|
|||
|
||||
#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)))
|
||||
|
||||
//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); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
*/
|
||||
|
||||
#define AMPLITUDE(ci,cq) (MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2))
|
||||
switch(Demod.state) {
|
||||
case DEMOD_UNSYNCD:
|
||||
CHECK_FOR_SUBCARRIER();
|
||||
if(v > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
|
||||
if(AMPLITUDE(ci,cq) > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected
|
||||
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
||||
Demod.sumI = ci;
|
||||
Demod.sumQ = cq;
|
||||
|
@ -598,8 +550,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
|
|||
|
||||
case DEMOD_PHASE_REF_TRAINING:
|
||||
if(Demod.posCount < 8) {
|
||||
CHECK_FOR_SUBCARRIER();
|
||||
if (v > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
if (AMPLITUDE(ci,cq) > SUBCARRIER_DETECT_THRESHOLD) {
|
||||
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
|
||||
// note: synchronization time > 80 1/fs
|
||||
Demod.sumI += ci;
|
||||
|
@ -743,9 +694,10 @@ static void DemodInit(uint8_t *data)
|
|||
*/
|
||||
static void GetSamplesFor14443bDemod(int n, bool quiet)
|
||||
{
|
||||
int max = 0;
|
||||
int maxBehindBy = 0;
|
||||
bool gotFrame = false;
|
||||
int lastRxCounter, ci, cq, samples = 0;
|
||||
int lastRxCounter, samples = 0;
|
||||
int8_t ci, cq;
|
||||
|
||||
// Allocate memory from BigBuf for some buffers
|
||||
// free all previous allocations first
|
||||
|
@ -755,15 +707,19 @@ static void GetSamplesFor14443bDemod(int n, bool quiet)
|
|||
uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
|
||||
// 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.
|
||||
DemodInit(receivedResponse);
|
||||
|
||||
// wait for last transfer to complete
|
||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY))
|
||||
|
||||
// Setup and start DMA.
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
||||
|
||||
int8_t *upTo = dmaBuf;
|
||||
uint16_t *upTo = dmaBuf;
|
||||
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
||||
|
||||
// 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);
|
||||
|
||||
for(;;) {
|
||||
int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
|
||||
if(behindBy > max) max = 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;
|
||||
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1);
|
||||
if(behindBy > maxBehindBy) {
|
||||
maxBehindBy = behindBy;
|
||||
}
|
||||
lastRxCounter -= 2;
|
||||
if(lastRxCounter <= 0) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
samples += 2;
|
||||
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 || gotFrame) {
|
||||
if(samples > n) {
|
||||
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
|
||||
if (tracing && Demod.len > 0) {
|
||||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
|
@ -820,11 +777,7 @@ static void TransmitFor14443b(void)
|
|||
{
|
||||
int c;
|
||||
|
||||
FpgaSetupSsc();
|
||||
|
||||
while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0xff;
|
||||
}
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||
|
||||
// Signal field is ON with the appropriate Red LED
|
||||
LED_D_ON();
|
||||
|
@ -832,31 +785,15 @@ static void TransmitFor14443b(void)
|
|||
LED_B_ON();
|
||||
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;
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = ToSend[c];
|
||||
AT91C_BASE_SSC->SSC_THR = ~ToSend[c];
|
||||
c++;
|
||||
if(c >= ToSendMax) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
|
||||
(void)r;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
LED_B_OFF(); // Finished sending
|
||||
|
@ -874,19 +811,14 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
|
|||
|
||||
ToSendReset();
|
||||
|
||||
// Establish initial reference level
|
||||
for(i = 0; i < 40; i++) {
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
// Send SOF
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
// Stop bits/EGT
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
// Start bit
|
||||
ToSendStuffBit(0);
|
||||
// Data bits
|
||||
|
@ -899,19 +831,18 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len)
|
|||
}
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
// Send EOF
|
||||
ToSendStuffBit(1);
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
for(i = 0; i < 8; i++) {
|
||||
// Stop bit
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
// And then a little more, to make sure that the last character makes
|
||||
// it out before we switch to rx mode.
|
||||
for(i = 0; i < 24; i++) {
|
||||
// Send EOF
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
ToSendStuffBit(1);
|
||||
|
||||
// ensure that last byte is filled up
|
||||
for(i = 0; i < 8; i++) {
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
|
@ -951,7 +882,7 @@ int iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *respo
|
|||
// send
|
||||
CodeAndTransmit14443bAsReader(message_frame, message_length + 4);
|
||||
// get response
|
||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT*100, true);
|
||||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||
if(Demod.len < 3)
|
||||
{
|
||||
return 0;
|
||||
|
@ -1011,7 +942,7 @@ int iso14443b_select_card()
|
|||
void iso14443b_setup() {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Set up the synchronous serial port
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||
// connect Demodulated Signal to ADC:
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
|
@ -1019,9 +950,6 @@ void iso14443b_setup() {
|
|||
LED_D_ON();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||
|
||||
// Start the timer
|
||||
StartCountSspClk();
|
||||
|
||||
DemodReset();
|
||||
UartReset();
|
||||
}
|
||||
|
@ -1047,7 +975,7 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
|||
SpinDelay(200);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
// Now give it time to spin up.
|
||||
// Signal field is on with the appropriate LED
|
||||
|
@ -1065,6 +993,8 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
|||
|
||||
if (Demod.len == 0) {
|
||||
DbpString("No response from tag");
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return;
|
||||
} else {
|
||||
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);
|
||||
if (Demod.len != 3) {
|
||||
Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return;
|
||||
}
|
||||
// Check the CRC of the answer:
|
||||
ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
|
||||
if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
|
||||
DbpString("CRC Error reading select response.");
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return;
|
||||
}
|
||||
// Check response from the tag: should be the same UID as the command we just sent:
|
||||
if (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;
|
||||
}
|
||||
|
||||
|
@ -1102,6 +1038,8 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
|||
GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, true);
|
||||
if (Demod.len != 10) {
|
||||
Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return;
|
||||
}
|
||||
// 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);
|
||||
if (Demod.len != 6) { // Check if we got an answer from the tag
|
||||
DbpString("Expected 6 bytes from tag, got less...");
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return;
|
||||
}
|
||||
// The check the CRC of the answer (use cmd1 as temporary variable):
|
||||
|
@ -1149,6 +1089,9 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
|||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1171,11 +1114,6 @@ void ReadSTMemoryIso14443b(uint32_t dwLast)
|
|||
*/
|
||||
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);
|
||||
BigBuf_free();
|
||||
|
||||
|
@ -1183,10 +1121,10 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
set_tracing(true);
|
||||
|
||||
// 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;
|
||||
int8_t *upTo;
|
||||
int ci, cq;
|
||||
uint16_t *upTo;
|
||||
int8_t ci, cq;
|
||||
int maxBehindBy = 0;
|
||||
|
||||
// Count of samples received so far, so that we can include timing
|
||||
|
@ -1211,7 +1149,7 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Setup for the DMA.
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
upTo = dmaBuf;
|
||||
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
|
||||
FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE);
|
||||
|
@ -1219,46 +1157,48 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
|
||||
bool TagIsActive = 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.
|
||||
for(;;) {
|
||||
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
|
||||
(ISO14443B_DMA_BUFFER_SIZE-1);
|
||||
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1);
|
||||
if(behindBy > maxBehindBy) {
|
||||
maxBehindBy = behindBy;
|
||||
}
|
||||
|
||||
if(behindBy < 2) continue;
|
||||
if(behindBy < 1) continue;
|
||||
|
||||
ci = upTo[0];
|
||||
cq = upTo[1];
|
||||
upTo += 2;
|
||||
lastRxCounter -= 2;
|
||||
if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
|
||||
upTo = dmaBuf;
|
||||
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 again
|
||||
lastRxCounter += ISO14443B_DMA_BUFFER_SIZE;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
|
||||
AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
|
||||
if(behindBy > (9*ISO14443B_DMA_BUFFER_SIZE/10)) {
|
||||
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();
|
||||
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()) {
|
||||
DbpString("cancelled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
samples += 2;
|
||||
samples++;
|
||||
|
||||
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
|
||||
if(Handle14443bUartBit(ci & 0x01)) {
|
||||
if(triggered && tracing) {
|
||||
triggered = true;
|
||||
if(tracing) {
|
||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
||||
}
|
||||
/* And ready to receive another command. */
|
||||
|
@ -1268,7 +1208,8 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
DemodReset();
|
||||
}
|
||||
if(Handle14443bUartBit(cq & 0x01)) {
|
||||
if(triggered && tracing) {
|
||||
triggered = true;
|
||||
if(tracing) {
|
||||
LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, true);
|
||||
}
|
||||
/* And ready to receive another command. */
|
||||
|
@ -1280,8 +1221,8 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
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(Handle14443bSamplesDemod(ci | 0x01, cq | 0x01)) {
|
||||
if(!ReaderIsActive && triggered) { // no need to try decoding tag data if the reader is sending or not yet triggered
|
||||
if(Handle14443bSamplesDemod(ci/2, cq/2)) {
|
||||
|
||||
//Use samples as a time measurement
|
||||
if(tracing)
|
||||
|
@ -1289,8 +1230,6 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
uint8_t parity[MAX_PARITY_SIZE];
|
||||
LogTrace(Demod.output, Demod.len, samples, samples, parity, false);
|
||||
}
|
||||
triggered = true;
|
||||
|
||||
// And ready to receive another response.
|
||||
DemodReset();
|
||||
}
|
||||
|
@ -1301,7 +1240,6 @@ void RAMFUNC SnoopIso14443b(void)
|
|||
|
||||
FpgaDisableSscDma();
|
||||
LEDsoff();
|
||||
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
|
||||
DbpString("Snoop statistics:");
|
||||
Dbprintf(" Max behind by: %i", maxBehindBy);
|
||||
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);
|
||||
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){
|
||||
set_tracing(true);
|
||||
|
|
|
@ -227,26 +227,14 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w
|
|||
{
|
||||
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);
|
||||
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;
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = cmd[c];
|
||||
AT91C_BASE_SSC->SSC_THR = ~cmd[c];
|
||||
c++;
|
||||
if(c >= len) {
|
||||
break;
|
||||
|
@ -300,36 +288,25 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
|
|||
{
|
||||
int c = 0;
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
int getNext = 0;
|
||||
|
||||
int8_t prev = 0;
|
||||
|
||||
// NOW READ RESPONSE
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
c = 0;
|
||||
getNext = false;
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
int8_t b;
|
||||
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
|
||||
// tone that the tag AM-modulates, so every other sample is I,
|
||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
||||
// close to what we want.
|
||||
if(getNext) {
|
||||
uint8_t r = AMPLITUDE(b, prev);
|
||||
// tone that the tag AM-modulates. We just want power.
|
||||
int8_t i = iq >> 8;
|
||||
int8_t q = iq;
|
||||
uint8_t r = AMPLITUDE(i, q);
|
||||
|
||||
dest[c++] = r;
|
||||
|
||||
if(c >= 4000) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
prev = b;
|
||||
}
|
||||
|
||||
getNext = !getNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,36 +418,26 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
|
|||
{
|
||||
int c = 0;
|
||||
uint8_t *dest = BigBuf_get_addr();
|
||||
int getNext = 0;
|
||||
|
||||
int8_t prev = 0;
|
||||
|
||||
// NOW READ RESPONSE
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
|
||||
c = 0;
|
||||
getNext = false;
|
||||
for(;;) {
|
||||
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
|
||||
// tone that the tag AM-modulates, so every other sample is I,
|
||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
||||
// close to what we want.
|
||||
if(getNext) {
|
||||
uint8_t r = AMPLITUDE(b, prev);
|
||||
// tone that the tag AM-modulates. We just want power,
|
||||
// so abs(I) + abs(Q) is close to what we want.
|
||||
int8_t i = iq >> 8;
|
||||
int8_t q = iq;
|
||||
uint8_t r = AMPLITUDE(i, q);
|
||||
|
||||
dest[c++] = r;
|
||||
|
||||
if(c >= BIGBUF_SIZE) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
prev = b;
|
||||
}
|
||||
|
||||
getNext = !getNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,8 +552,6 @@ void AcquireRawAdcSamplesIso15693(void)
|
|||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
int c = 0;
|
||||
int getNext = 0;
|
||||
int8_t prev = 0;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
BuildIdentifyRequest();
|
||||
|
@ -598,13 +563,13 @@ void AcquireRawAdcSamplesIso15693(void)
|
|||
SpinDelay(100);
|
||||
|
||||
// Now send the command
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
|
||||
|
||||
c = 0;
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = ToSend[c];
|
||||
AT91C_BASE_SSC->SSC_THR = ~ToSend[c];
|
||||
c++;
|
||||
if(c == ToSendMax+3) {
|
||||
break;
|
||||
|
@ -613,32 +578,25 @@ void AcquireRawAdcSamplesIso15693(void)
|
|||
WDT_HIT();
|
||||
}
|
||||
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
c = 0;
|
||||
getNext = false;
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
int8_t b;
|
||||
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
|
||||
// tone that the tag AM-modulates, so every other sample is I,
|
||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
||||
// close to what we want.
|
||||
if(getNext) {
|
||||
uint8_t r = AMPLITUDE(b, prev);
|
||||
// tone that the tag AM-modulates. We just want power,
|
||||
// so abs(I) + abs(Q) is close to what we want.
|
||||
int8_t i = iq >> 8;
|
||||
int8_t q = iq;
|
||||
uint8_t r = AMPLITUDE(i, q);
|
||||
|
||||
dest[c++] = r;
|
||||
|
||||
if(c >= 4000) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
prev = b;
|
||||
}
|
||||
|
||||
getNext = !getNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -649,12 +607,10 @@ void RecordRawAdcSamplesIso15693(void)
|
|||
uint8_t *dest = BigBuf_get_addr();
|
||||
|
||||
int c = 0;
|
||||
int getNext = 0;
|
||||
int8_t prev = 0;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
// Setup SSC
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
// Start from off (no field generated)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -667,33 +623,24 @@ void RecordRawAdcSamplesIso15693(void)
|
|||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
c = 0;
|
||||
getNext = false;
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
int8_t b;
|
||||
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
|
||||
// tone that the tag AM-modulates, so every other sample is I,
|
||||
// every other is Q. We just want power, so abs(I) + abs(Q) is
|
||||
// close to what we want.
|
||||
if(getNext) {
|
||||
uint8_t r = AMPLITUDE(b, prev);
|
||||
// tone that the tag AM-modulates. We just want power,
|
||||
// so abs(I) + abs(Q) is close to what we want.
|
||||
int8_t i = iq >> 8;
|
||||
int8_t q = iq;
|
||||
uint8_t r = AMPLITUDE(i, q);
|
||||
|
||||
dest[c++] = r;
|
||||
|
||||
if(c >= 14000) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
prev = b;
|
||||
}
|
||||
|
||||
getNext = !getNext;
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
Dbprintf("fin record");
|
||||
Dbprintf("finished recording");
|
||||
}
|
||||
|
||||
|
||||
|
@ -714,7 +661,7 @@ void Iso15693InitReader() {
|
|||
SpinDelay(10);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
// Give the tags time to energize
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
@ -973,7 +920,7 @@ void ReaderIso15693(uint32_t parameter)
|
|||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
// Setup SSC
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
// Start from off (no field generated)
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
|
@ -1075,7 +1022,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
|
|||
memset(buf, 0x00, 100);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
// Start from off (no field generated)
|
||||
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)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static inline uint8_t rx_byte_from_fpga() {
|
||||
static inline uint16_t rx_frame_from_fpga() {
|
||||
for(;;) {
|
||||
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)) {
|
||||
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:
|
||||
// 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
|
||||
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
|
||||
// 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.
|
||||
static inline bool rx_bit() {
|
||||
int32_t cq = 0;
|
||||
int32_t ci = 0;
|
||||
int32_t sum_cq = 0;
|
||||
int32_t sum_ci = 0;
|
||||
|
||||
// skip first 5 I/Q pairs
|
||||
for(size_t i = 0; i<5; ++i) {
|
||||
(int8_t)rx_byte_from_fpga();
|
||||
(int8_t)rx_byte_from_fpga();
|
||||
(void)rx_frame_from_fpga();
|
||||
}
|
||||
|
||||
// sample next 8 I/Q pairs
|
||||
for(size_t i = 0; i<8; ++i) {
|
||||
cq += (int8_t)rx_byte_from_fpga();
|
||||
ci += (int8_t)rx_byte_from_fpga();
|
||||
uint16_t iq = rx_frame_from_fpga();
|
||||
int8_t ci = (int8_t)(iq >> 8);
|
||||
int8_t cq = (int8_t)(iq & 0xff);
|
||||
sum_ci += ci;
|
||||
sum_cq += cq;
|
||||
}
|
||||
|
||||
// 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
|
||||
return ((power >> 3) > INPUT_THRESHOLD);
|
||||
|
@ -131,12 +130,12 @@ static inline bool rx_bit() {
|
|||
|
||||
static inline void tx_bit(bool bit) {
|
||||
// insert pause
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
last_frame_end += RWD_TIME_PAUSE;
|
||||
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;
|
||||
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
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
last_frame_end += RWD_TIME_PAUSE;
|
||||
while(GET_TICKS < last_frame_end) { };
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
}
|
||||
|
||||
static uint32_t rx_frame(uint8_t len) {
|
||||
|
@ -265,12 +264,12 @@ static void init_reader(bool clear_mem) {
|
|||
LED_D_ON();
|
||||
|
||||
// configure SSC with defaults
|
||||
FpgaSetupSsc();
|
||||
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
|
||||
// re-claim GPIO_SSC_DOUT as GPIO and enable output
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
// init crc calculator
|
||||
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
|
||||
|
|
|
@ -284,7 +284,7 @@ static void init_tag() {
|
|||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// 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
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
|
|
@ -1818,7 +1818,7 @@ void Cotag(uint32_t arg0) {
|
|||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
// 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
|
||||
StartTicks();
|
||||
|
|
|
@ -101,7 +101,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field)
|
|||
// 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();
|
||||
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
|
||||
|
||||
// set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35
|
||||
// (send two frames with 8 Bits each)
|
||||
if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000)
|
||||
// set ssp_frame signal for corr_i_cnt = 0..3
|
||||
// (send one frame with 16 Bits)
|
||||
if(corr_i_cnt[5:2] == 4'b0000)
|
||||
ssp_frame = 1'b1;
|
||||
else
|
||||
ssp_frame = 1'b0;
|
||||
|
|
|
@ -42,11 +42,11 @@ begin
|
|||
pwr_hi <= ck_1356megb;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= ~ssp_dout;
|
||||
pwr_oe4 <= ssp_dout;
|
||||
end
|
||||
else
|
||||
begin
|
||||
pwr_hi <= ck_1356megb & ssp_dout;
|
||||
pwr_hi <= ck_1356megb & ~ssp_dout;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= 1'b0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue