From 51d4f6f1146b083f12381419bbfb6addd550e6a3 Mon Sep 17 00:00:00 2001 From: pwpiwi <pwpiwi@users.noreply.github.com> Date: Fri, 12 Jun 2015 07:43:00 +0200 Subject: [PATCH] fixing iso14443b (issue #103): - fix: IQ demodulator (FPGA) - fix: approximately align reader signal delay to tag response delay (FPGA) - fix: remove deprecated RSSI calculation to improve decoder speed (iso14443b.c) - fix: better approximation of signal amplitude to avoid false carrier detection (iso14443b.c) - fix: remove initial power off in iso14443b raw command (iso14443b.c) - add: enable tracing for iso14443b raw command (iso14443b.c) - fix: client crashed when checking CRC for incomplete responses (iso14433b.c) - speeding up snoop to avoid circular buffer overflow - added some comments for better documentation - rename functions (iso14443 -> iso14443b) - remove unused code in hi_read_rx_xcorr.v --- armsrc/appmain.c | 12 +- armsrc/apps.h | 8 +- armsrc/iso14443b.c | 476 ++++++++++++++++++++-------------------- client/cmdhf14b.c | 14 +- fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/fpga_hf.v | 11 +- fpga/hi_read_rx_xcorr.v | 78 ++----- 7 files changed, 279 insertions(+), 320 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c226c726..9bfa5ea7 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -263,7 +263,7 @@ void SimulateTagHfListen(void) // We're using this mode just so that I can test it out; the simulated // tag mode would work just as well and be simpler. FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_SNOOP); // We need to listen to the high-frequency, peak-detected path. SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -783,19 +783,19 @@ void UsbPacketReceived(uint8_t *packet, int len) #ifdef WITH_ISO14443b case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443: - AcquireRawAdcSamplesIso14443(c->arg[0]); + AcquireRawAdcSamplesIso14443b(c->arg[0]); break; case CMD_READ_SRI512_TAG: - ReadSTMemoryIso14443(0x0F); + ReadSTMemoryIso14443b(0x0F); break; case CMD_READ_SRIX4K_TAG: - ReadSTMemoryIso14443(0x7F); + ReadSTMemoryIso14443b(0x7F); break; case CMD_SNOOP_ISO_14443: - SnoopIso14443(); + SnoopIso14443b(); break; case CMD_SIMULATE_TAG_ISO_14443: - SimulateIso14443Tag(); + SimulateIso14443bTag(); break; case CMD_ISO_14443B_COMMAND: SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); diff --git a/armsrc/apps.h b/armsrc/apps.h index 6360b664..542f3a65 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -141,10 +141,10 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); /// iso14443.h -void SimulateIso14443Tag(void); -void AcquireRawAdcSamplesIso14443(uint32_t parameter); -void ReadSTMemoryIso14443(uint32_t); -void RAMFUNC SnoopIso14443(void); +void SimulateIso14443bTag(void); +void AcquireRawAdcSamplesIso14443b(uint32_t parameter); +void ReadSTMemoryIso14443b(uint32_t); +void RAMFUNC SnoopIso14443b(void); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); /// iso14443a.h diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 4e40bb68..f598df3c 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -5,9 +5,8 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Routines to support ISO 14443. This includes both the reader software and -// the `fake tag' modes. At the moment only the Type B modulation is -// supported. +// Routines to support ISO 14443B. This includes both the reader software and +// the `fake tag' modes. //----------------------------------------------------------------------------- #include "proxmark3.h" @@ -17,15 +16,8 @@ #include "iso14443crc.h" -//static void GetSamplesFor14443(int weTx, int n); - -/*#define DEMOD_TRACE_SIZE 4096 -#define READER_TAG_BUFFER_SIZE 2048 -#define TAG_READER_BUFFER_SIZE 2048 -#define DEMOD_DMA_BUFFER_SIZE 1024 -*/ - #define RECEIVE_SAMPLES_TIMEOUT 2000 +#define ISO14443B_DMA_BUFFER_SIZE 512 //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using @@ -104,14 +96,14 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) ToSendStuffBit(1); } - // Send SOF. + // Send EOF. for(i = 0; i < 10; i++) { ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); } - for(i = 0; i < 10; i++) { + for(i = 0; i < 2; i++) { ToSendStuffBit(1); ToSendStuffBit(1); ToSendStuffBit(1); @@ -120,9 +112,6 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) // Convert from last byte pos to length ToSendMax++; - - // Add a few more for slop - ToSendMax += 2; } //----------------------------------------------------------------------------- @@ -146,6 +135,9 @@ static struct { } Uart; /* Receive & handle a bit coming from the reader. + * + * This function is called 4 times per bit (every 2 subcarrier cycles). + * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us * * LED handling: * LED A -> ON once we have received the SOF and are expecting the rest. @@ -154,7 +146,7 @@ static struct { * Returns: true if we received a EOF * false if we are still waiting for some more */ -static int Handle14443UartBit(int bit) +static int Handle14443bUartBit(int bit) { switch(Uart.state) { case STATE_UNSYNCD: @@ -169,9 +161,9 @@ static int Handle14443UartBit(int bit) case STATE_GOT_FALLING_EDGE_OF_SOF: Uart.posCnt++; - if(Uart.posCnt == 2) { + if(Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit if(bit) { - if(Uart.bitCnt >= 10) { + if(Uart.bitCnt > 9) { // we've seen enough consecutive // zeros that it's a valid SOF Uart.posCnt = 0; @@ -189,7 +181,7 @@ static int Handle14443UartBit(int bit) Uart.bitCnt++; } if(Uart.posCnt >= 4) Uart.posCnt = 0; - if(Uart.bitCnt > 14) { + if(Uart.bitCnt > 12) { // Give up if we see too many zeros without // a one, too. Uart.state = STATE_ERROR_WAIT; @@ -199,7 +191,7 @@ static int Handle14443UartBit(int bit) case STATE_AWAITING_START_BIT: Uart.posCnt++; if(bit) { - if(Uart.posCnt > 25) { + if(Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs // stayed high for too long between // characters, error Uart.state = STATE_ERROR_WAIT; @@ -283,12 +275,12 @@ static int Handle14443UartBit(int bit) // Assume that we're called with the SSC (to the FPGA) and ADC path set // correctly. //----------------------------------------------------------------------------- -static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen) +static int GetIso14443bCommandFromReader(uint8_t *received, int *len, int maxLen) { uint8_t mask; int i, bit; - // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen + // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED LED_D_OFF(); @@ -314,7 +306,7 @@ static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen) mask = 0x80; for(i = 0; i < 8; i++, mask >>= 1) { bit = (b & mask); - if(Handle14443UartBit(bit)) { + if(Handle14443bUartBit(bit)) { *len = Uart.byteCnt; return TRUE; } @@ -327,9 +319,13 @@ static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen) // Main loop of simulated tag: receive commands from reader, decide what // response to send, and send it. //----------------------------------------------------------------------------- -void SimulateIso14443Tag(void) +void SimulateIso14443bTag(void) { + // the only command we understand is REQB, AFI=0, Select All, N=0: static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + // ... and we respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, + // supports only 106kBit/s in both directions, max frame size = 32Bytes, + // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: static const uint8_t response1[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 @@ -338,10 +334,9 @@ void SimulateIso14443Tag(void) uint8_t *resp; int respLen; - uint8_t *resp1 = BigBuf_get_addr() + 800; - int resp1Len; - - uint8_t *receivedCmd = BigBuf_get_addr(); + // allocate command receive buffer + BigBuf_free(); + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); int len; int i; @@ -349,10 +344,12 @@ void SimulateIso14443Tag(void) int cmdsRecvd = 0; FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - memset(receivedCmd, 0x44, 400); + // prepare the (only one) tag answer: CodeIso14443bAsTag(response1, sizeof(response1)); - memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax; + uint8_t *resp1 = BigBuf_malloc(ToSendMax); + memcpy(resp1, ToSend, ToSendMax); + uint16_t resp1Len = ToSendMax; // We need to listen to the high-frequency, peak-detected path. SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -363,14 +360,14 @@ void SimulateIso14443Tag(void) for(;;) { uint8_t b1, b2; - if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) { - Dbprintf("button pressed, received %d commands", cmdsRecvd); - break; - } + if(!GetIso14443bCommandFromReader(receivedCmd, &len, 100)) { + Dbprintf("button pressed, received %d commands", cmdsRecvd); + break; + } // Good, look at the command now. - if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) { + if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0) { resp = resp1; respLen = resp1Len; } else { Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd); @@ -385,8 +382,6 @@ void SimulateIso14443Tag(void) break; } - memset(receivedCmd, 0x44, 32); - cmdsRecvd++; if(cmdsRecvd > 0x30) { @@ -444,8 +439,10 @@ static struct { int bitCount; int posCount; int thisBit; +/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. int metric; int metricN; +*/ uint16_t shiftReg; uint8_t *output; int len; @@ -456,6 +453,9 @@ static struct { /* * Handles reception of a bit from the tag * + * This function is called 2 times per bit (every 4 subcarrier cycles). + * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 4,72us + * * LED handling: * LED C -> ON once we have received the SOF and are expecting the rest. * LED C -> OFF once we have received EOF or are unsynced @@ -464,12 +464,12 @@ static struct { * false if we are still waiting for some more * */ -static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) +static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) { int v; - // The soft decision on the bit uses an estimate of just the - // quadrant of the reference angle, not the exact angle. +// The soft decision on the bit uses an estimate of just the +// quadrant of the reference angle, not the exact angle. #define MAKE_SOFT_DECISION() { \ if(Demod.sumI > 0) { \ v = ci; \ @@ -483,47 +483,87 @@ static RAMFUNC int Handle14443SamplesDemod(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))) +#define CHECK_FOR_SUBCARRIER() { \ + 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) { case DEMOD_UNSYNCD: - v = ci; - if(v < 0) v = -v; - if(cq > 0) { - v += cq; - } else { - v -= cq; - } - if(v > 40) { - Demod.posCount = 0; + CHECK_FOR_SUBCARRIER(); + if(v > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected Demod.state = DEMOD_PHASE_REF_TRAINING; - Demod.sumI = 0; - Demod.sumQ = 0; - } + Demod.sumI = ci; + Demod.sumQ = cq; + Demod.posCount = 1; + } break; case DEMOD_PHASE_REF_TRAINING: if(Demod.posCount < 8) { - Demod.sumI += ci; - Demod.sumQ += cq; - } else if(Demod.posCount > 100) { - // error, waited too long - Demod.state = DEMOD_UNSYNCD; - } else { - MAKE_SOFT_DECISION(); - if(v < 0) { - Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF; - Demod.posCount = 0; + CHECK_FOR_SUBCARRIER(); + if (v > 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; + Demod.sumQ += cq; + Demod.posCount++; + } else { // subcarrier lost + Demod.state = DEMOD_UNSYNCD; } + } else { + Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF; } - Demod.posCount++; break; case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: MAKE_SOFT_DECISION(); - if(v < 0) { + if(v < 0) { // logic '0' detected Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; - Demod.posCount = 0; + Demod.posCount = 0; // start of SOF sequence } else { - if(Demod.posCount > 100) { + if(Demod.posCount > 200/4) { // maximum length of TR1 = 200 1/fs Demod.state = DEMOD_UNSYNCD; } } @@ -531,37 +571,40 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) break; case DEMOD_GOT_FALLING_EDGE_OF_SOF: + Demod.posCount++; MAKE_SOFT_DECISION(); if(v > 0) { - if(Demod.posCount < 12) { + if(Demod.posCount < 9*2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges Demod.state = DEMOD_UNSYNCD; } else { LED_C_ON(); // Got SOF Demod.state = DEMOD_AWAITING_START_BIT; Demod.posCount = 0; Demod.len = 0; +/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. Demod.metricN = 0; Demod.metric = 0; +*/ } } else { - if(Demod.posCount > 100) { + if(Demod.posCount > 12*2) { // low phase of SOF too long (> 12 etu) Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); } } - Demod.posCount++; break; case DEMOD_AWAITING_START_BIT: + Demod.posCount++; MAKE_SOFT_DECISION(); if(v > 0) { - if(Demod.posCount > 10) { + if(Demod.posCount > 3*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); } - } else { + } else { // start bit detected Demod.bitCount = 0; - Demod.posCount = 1; + Demod.posCount = 1; // this was the first half Demod.thisBit = v; Demod.shiftReg = 0; Demod.state = DEMOD_RECEIVING_DATA; @@ -570,28 +613,30 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) case DEMOD_RECEIVING_DATA: MAKE_SOFT_DECISION(); - if(Demod.posCount == 0) { + if(Demod.posCount == 0) { // first half of bit Demod.thisBit = v; Demod.posCount = 1; - } else { + } else { // second half of bit Demod.thisBit += v; +/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. if(Demod.thisBit > 0) { Demod.metric += Demod.thisBit; } else { Demod.metric -= Demod.thisBit; } (Demod.metricN)++; +*/ Demod.shiftReg >>= 1; - if(Demod.thisBit > 0) { + if(Demod.thisBit > 0) { // logic '1' Demod.shiftReg |= 0x200; } Demod.bitCount++; if(Demod.bitCount == 10) { uint16_t s = Demod.shiftReg; - if((s & 0x200) && !(s & 0x001)) { + if((s & 0x200) && !(s & 0x001)) { // stop bit == '1', start bit == '0' uint8_t b = (s >> 1); Demod.output[Demod.len] = b; Demod.len++; @@ -600,7 +645,7 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); if(s == 0x000) { - // This is EOF + // This is EOF (start, stop and all data bits == '0' return TRUE; } } @@ -624,6 +669,7 @@ static void DemodReset() // Clear out the state of the "UART" that receives from the tag. Demod.len = 0; Demod.state = DEMOD_UNSYNCD; + Demod.posCount = 0; memset(Demod.output, 0x00, MAX_FRAME_SIZE); } @@ -653,14 +699,12 @@ static void UartInit(uint8_t *data) /* * Demodulate the samples we received from the tag, also log to tracebuffer - * weTx: set to 'TRUE' if we behave like a reader - * set to 'FALSE' if we behave like a snooper * quiet: set to 'TRUE' to disable debug output */ -static void GetSamplesFor14443Demod(int weTx, int n, int quiet) +static void GetSamplesFor14443bDemod(int n, bool quiet) { int max = 0; - int gotFrame = FALSE; + bool gotFrame = FALSE; int lastRxCounter, ci, cq, samples = 0; // Allocate memory from BigBuf for some buffers @@ -671,57 +715,56 @@ static void GetSamplesFor14443Demod(int weTx, int n, int 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(DMA_BUFFER_SIZE); + int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); // Set up the demodulator for tag -> reader responses. DemodInit(receivedResponse); // Setup and start DMA. - FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE); + FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); int8_t *upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; // Signal field is ON with the appropriate LED: - if (weTx) LED_D_ON(); else LED_D_OFF(); + LED_D_ON(); // And put the FPGA in the appropriate mode - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); for(;;) { int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR; if(behindBy > max) max = behindBy; - while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1)) - > 2) - { + 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 + DMA_BUFFER_SIZE) { + if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { upTo = dmaBuf; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; } lastRxCounter -= 2; if(lastRxCounter <= 0) { - lastRxCounter += DMA_BUFFER_SIZE; + lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; } samples += 2; - if(Handle14443SamplesDemod(ci, cq)) { - gotFrame = 1; + if(Handle14443bSamplesDemod(ci, cq)) { + gotFrame = TRUE; + break; } } - if(samples > n) { + if(samples > n || gotFrame) { break; } } + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; - if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len); + + 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); //Tracing if (tracing && Demod.len > 0) { uint8_t parity[MAX_PARITY_SIZE]; @@ -731,43 +774,10 @@ static void GetSamplesFor14443Demod(int weTx, int n, int quiet) } -//----------------------------------------------------------------------------- -// Read the tag's response. We just receive a stream of slightly-processed -// samples from the FPGA, which we will later do some signal processing on, -// to get the bits. -//----------------------------------------------------------------------------- -/*static void GetSamplesFor14443(int weTx, int n) -{ - uint8_t *dest = (uint8_t *)BigBuf; - int c; - - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP)); - - c = 0; - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x43; - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - int8_t b; - b = (int8_t)AT91C_BASE_SSC->SSC_RHR; - - dest[c++] = (uint8_t)b; - - if(c >= n) { - break; - } - } - } -}*/ - - //----------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- -static void TransmitFor14443(void) +static void TransmitFor14443b(void) { int c; @@ -781,8 +791,7 @@ static void TransmitFor14443(void) LED_D_ON(); // Signal we are transmitting with the Green LED 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)) { @@ -817,7 +826,7 @@ static void TransmitFor14443(void) //----------------------------------------------------------------------------- // Code a layer 2 command (string of octets, including CRC) into ToSend[], -// so that it is ready to transmit to the tag using TransmitFor14443(). +// so that it is ready to transmit to the tag using TransmitFor14443b(). //----------------------------------------------------------------------------- static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { @@ -873,16 +882,16 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) //----------------------------------------------------------------------------- -// Read an ISO 14443 tag. We send it some set of commands, and record the +// Read an ISO 14443B tag. We send it some set of commands, and record the // responses. // The command name is misleading, it actually decodes the reponse in HEX // into the output buffer (read the result using hexsamples, not hisamples) // // obsolete function only for test //----------------------------------------------------------------------------- -void AcquireRawAdcSamplesIso14443(uint32_t parameter) +void AcquireRawAdcSamplesIso14443b(uint32_t parameter) { - uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; // REQB with AFI=0, Request All, N=0 SendRawCommand14443B(sizeof(cmd1),1,1,cmd1); } @@ -894,7 +903,7 @@ void AcquireRawAdcSamplesIso14443(uint32_t parameter) static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { CodeIso14443bAsReader(cmd, len); - TransmitFor14443(); + TransmitFor14443b(); if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; GetParity(cmd, len, parity); @@ -904,7 +913,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) //----------------------------------------------------------------------------- -// Read a SRI512 ISO 14443 tag. +// Read a SRI512 ISO 14443B tag. // // SRI512 tags are just simple memory tags, here we're looking at making a dump // of the contents of the memory. No anticollision algorithm is done, we assume @@ -912,7 +921,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) // // I tried to be systematic and check every answer of the tag, every CRC, etc... //----------------------------------------------------------------------------- -void ReadSTMemoryIso14443(uint32_t dwLast) +void ReadSTMemoryIso14443b(uint32_t dwLast) { clear_trace(); set_tracing(TRUE); @@ -933,15 +942,15 @@ void ReadSTMemoryIso14443(uint32_t dwLast) // Signal field is on with the appropriate LED LED_D_ON(); FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); + FPGA_MAJOR_MODE_HF_READER_RX_XCORR); SpinDelay(200); // First command: wake up the tag using the INITIATE command - uint8_t cmd1[] = { 0x06, 0x00, 0x97, 0x5b}; + uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b}; CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); // LED_A_OFF(); if (Demod.len == 0) { @@ -949,7 +958,7 @@ void ReadSTMemoryIso14443(uint32_t dwLast) return; } else { Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x", - Demod.output[0], Demod.output[1],Demod.output[2]); + Demod.output[0], Demod.output[1], Demod.output[2]); } // There is a response, SELECT the uid DbpString("Now SELECT tag:"); @@ -959,22 +968,22 @@ void ReadSTMemoryIso14443(uint32_t dwLast) CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); // LED_A_OFF(); if (Demod.len != 3) { - Dbprintf("Expected 3 bytes from tag, got %d", Demod.len); - return; + Dbprintf("Expected 3 bytes from tag, got %d", Demod.len); + 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."); - return; + DbpString("CRC Error reading select response."); + 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: %x %x", cmd1[1], Demod.output[0]); - return; + Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]); + return; } // Tag is now selected, // First get the tag's UID: @@ -983,22 +992,22 @@ void ReadSTMemoryIso14443(uint32_t dwLast) CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); // LED_A_OFF(); if (Demod.len != 10) { - Dbprintf("Expected 10 bytes from tag, got %d", Demod.len); - return; + Dbprintf("Expected 10 bytes from tag, got %d", Demod.len); + return; } // The check the CRC of the answer (use cmd1 as temporary variable): ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]); - if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) { - Dbprintf("CRC Error reading block! - Below: expected, got %x %x", - (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]); - // Do not return;, let's go on... (we should retry, maybe ?) + if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) { + Dbprintf("CRC Error reading block! - Below: expected, got %x %x", + (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]); + // Do not return;, let's go on... (we should retry, maybe ?) } Dbprintf("Tag UID (64 bits): %08x %08x", - (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4], - (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]); + (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4], + (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]); // Now loop to read all 16 blocks, address from 0 to last block Dbprintf("Tag memory dump, block 0 to %d",dwLast); @@ -1006,7 +1015,7 @@ void ReadSTMemoryIso14443(uint32_t dwLast) i = 0x00; dwLast++; for (;;) { - if (i == dwLast) { + if (i == dwLast) { DbpString("System area block (0xff):"); i = 0xff; } @@ -1015,25 +1024,25 @@ void ReadSTMemoryIso14443(uint32_t dwLast) CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); // LED_A_OFF(); if (Demod.len != 6) { // Check if we got an answer from the tag - DbpString("Expected 6 bytes from tag, got less..."); - return; + DbpString("Expected 6 bytes from tag, got less..."); + return; } // The check the CRC of the answer (use cmd1 as temporary variable): ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]); - if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) { - Dbprintf("CRC Error reading block! - Below: expected, got %x %x", - (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]); - // Do not return;, let's go on... (we should retry, maybe ?) + if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) { + Dbprintf("CRC Error reading block! - Below: expected, got %x %x", + (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]); + // Do not return;, let's go on... (we should retry, maybe ?) } // Now print out the memory location: Dbprintf("Address=%x, Contents=%x, CRC=%x", i, - (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], - (Demod.output[4]<<8)+Demod.output[5]); + (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], + (Demod.output[4]<<8)+Demod.output[5]); if (i == 0xff) { - break; + break; } i++; } @@ -1054,10 +1063,10 @@ void ReadSTMemoryIso14443(uint32_t dwLast) * Memory usage for this function, (within BigBuf) * Last Received command (reader->tag) - MAX_FRAME_SIZE * Last Received command (tag->reader) - MAX_FRAME_SIZE - * DMA Buffer, 1024 bytes (samples) - DMA_BUFFER_SIZE + * DMA Buffer - ISO14443B_DMA_BUFFER_SIZE * Demodulated samples received - all the rest */ -void RAMFUNC SnoopIso14443(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 @@ -1071,7 +1080,7 @@ void RAMFUNC SnoopIso14443(void) set_tracing(TRUE); // The DMA buffer, used to stream samples from the FPGA - int8_t *dmaBuf = (int8_t*) BigBuf_malloc(DMA_BUFFER_SIZE); + int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); int lastRxCounter; int8_t *upTo; int ci, cq; @@ -1089,24 +1098,21 @@ void RAMFUNC SnoopIso14443(void) Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen()); Dbprintf(" Reader -> tag: %i bytes", MAX_FRAME_SIZE); Dbprintf(" tag -> Reader: %i bytes", MAX_FRAME_SIZE); - Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE); + Dbprintf(" DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE); - // Signal field is off with the appropriate LED - LED_D_OFF(); + // Signal field is off, no reader signal, no tag signal + LEDsoff(); // And put the FPGA in the appropriate mode - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - FPGA_HF_READER_RX_XCORR_SNOOP); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_SNOOP); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Setup for the DMA. FpgaSetupSsc(); upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE); + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; + FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); uint8_t parity[MAX_PARITY_SIZE]; - LED_A_ON(); bool TagIsActive = FALSE; bool ReaderIsActive = FALSE; @@ -1114,50 +1120,56 @@ void RAMFUNC SnoopIso14443(void) // And now we loop, receiving samples. for(;;) { int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & - (DMA_BUFFER_SIZE-1); + (ISO14443B_DMA_BUFFER_SIZE-1); if(behindBy > maxBehindBy) { maxBehindBy = behindBy; - if(behindBy > (9*DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not? - Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); - break; - } } + if(behindBy < 2) continue; ci = upTo[0]; cq = upTo[1]; upTo += 2; lastRxCounter -= 2; - if(upTo >= dmaBuf + DMA_BUFFER_SIZE) { + if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { upTo = dmaBuf; - lastRxCounter += DMA_BUFFER_SIZE; + lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; + 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=0x%x", behindBy); + break; + } + if(!tracing) { + DbpString("Reached trace limit"); + break; + } + if(BUTTON_PRESS()) { + DbpString("cancelled"); + break; + } } samples += 2; if (!TagIsActive) { // no need to try decoding reader data if the tag is sending - if(Handle14443UartBit(ci & 0x01)) { + if(Handle14443bUartBit(ci & 0x01)) { if(triggered && tracing) { GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE); + LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); } - if(Uart.byteCnt==0) Dbprintf("[1] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt); - /* And ready to receive another command. */ UartReset(); /* And also reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ DemodReset(); } - if(Handle14443UartBit(cq & 0x01)) { + if(Handle14443bUartBit(cq & 0x01)) { if(triggered && tracing) { GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace(Uart.output,Uart.byteCnt,samples, samples, parity, TRUE); + LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); } - if(Uart.byteCnt==0) Dbprintf("[2] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt); - /* And ready to receive another command. */ UartReset(); /* And also reset the demod code, which might have been */ @@ -1168,7 +1180,7 @@ void RAMFUNC SnoopIso14443(void) } if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time - if(Handle14443SamplesDemod(ci & 0xFE, cq & 0xFE)) { + if(Handle14443bSamplesDemod(ci & 0xFE, cq & 0xFE)) { //Use samples as a time measurement if(tracing) @@ -1178,31 +1190,17 @@ void RAMFUNC SnoopIso14443(void) LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE); } triggered = TRUE; - LED_A_OFF(); - LED_B_ON(); // And ready to receive another response. DemodReset(); } - TagIsActive = (Demod.state != DEMOD_UNSYNCD); - } - - WDT_HIT(); - - if(!tracing) { - DbpString("Reached trace limit"); - break; + TagIsActive = (Demod.state > DEMOD_PHASE_REF_TRAINING); } - if(BUTTON_PRESS()) { - DbpString("cancelled"); - break; - } } + FpgaDisableSscDma(); - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); + LEDsoff(); AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; DbpString("Snoop statistics:"); Dbprintf(" Max behind by: %i", maxBehindBy); @@ -1228,38 +1226,36 @@ void RAMFUNC SnoopIso14443(void) void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[]) { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - if(!powerfield) - { + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); + + set_tracing(TRUE); + +/* if(!powerfield) { // Make sure that we start from off, since the tags are stateful; // confusing things will happen if we don't reset them between reads. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelay(200); } + */ - if(!GETBIT(GPIO_LED_D)) - { - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); - - // Now give it time to spin up. - // Signal field is on with the appropriate LED - LED_D_ON(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); - SpinDelay(200); - } + // if(!GETBIT(GPIO_LED_D)) { // if field is off + // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + // // Signal field is on with the appropriate LED + // LED_D_ON(); + // SpinDelay(200); + // } CodeAndTransmit14443bAsReader(data, datalen); - if(recv) - { - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); - uint16_t iLen = MIN(Demod.len,USB_CMD_DATA_SIZE); - cmd_send(CMD_ACK,iLen,0,0,Demod.output,iLen); + if(recv) { + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE); + cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen); } - if(!powerfield) - { + + if(!powerfield) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 525ffcc6..21a4e179 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -288,7 +288,7 @@ int CmdHF14BCmdRaw (const char *cmd) { if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { recv = resp.d.asBytes; PrintAndLog("received %i octets",resp.arg[0]); - if(!resp.arg[0]) + if(resp.arg[0] == 0) return 0; hexout = (char *)malloc(resp.arg[0] * 3 + 1); if (hexout != NULL) { @@ -298,11 +298,13 @@ int CmdHF14BCmdRaw (const char *cmd) { } PrintAndLog("%s", hexout); free(hexout); - ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second); - if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) { - PrintAndLog("CRC OK"); - } else { - PrintAndLog("CRC failed"); + if (resp.arg[0] > 2) { + ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second); + if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) { + PrintAndLog("CRC OK"); + } else { + PrintAndLog("CRC failed"); + } } } else { PrintAndLog("malloc failed your client has low memory?"); diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 53078a782422c09596f006d95c85ae45da20072d..717dad13eb67e5ef2cfeb39da3c4a0f6e9e04fd3 100644 GIT binary patch literal 42175 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 X6@LG!3>EnA;7jp)4pq`p{!9KJU6^^c literal 42175 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 diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index a2100df6..e84081b3 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -67,15 +67,10 @@ assign major_mode = conf_word[7:5]; // some fraction of the buffers) wire hi_read_tx_shallow_modulation = conf_word[0]; -// For the high-frequency receive correlator: frequency against which to -// correlate. -wire hi_read_rx_xcorr_848 = conf_word[0]; -// and whether to drive the coil (reader) or just short it (snooper) +// For the high-frequency receive correlator: +// whether to drive the coil (reader) or just short it (snooper) wire hi_read_rx_xcorr_snoop = conf_word[1]; -// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4 -wire hi_read_rx_xcorr_quarter = conf_word[2]; - // For the high-frequency simulated tag: what kind of modulation to use. wire [2:0] hi_simulate_mod_type = conf_word[2:0]; @@ -102,7 +97,7 @@ hi_read_rx_xcorr hrxc( hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk, cross_hi, cross_lo, hrxc_dbg, - hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter + hi_read_rx_xcorr_snoop ); hi_simulate hs( diff --git a/fpga/hi_read_rx_xcorr.v b/fpga/hi_read_rx_xcorr.v index 06142637..a6a99cd5 100644 --- a/fpga/hi_read_rx_xcorr.v +++ b/fpga/hi_read_rx_xcorr.v @@ -10,7 +10,7 @@ module hi_read_rx_xcorr( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - xcorr_is_848, snoop, xcorr_quarter_freq + snoop ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -20,58 +20,20 @@ module hi_read_rx_xcorr( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input xcorr_is_848, snoop, xcorr_quarter_freq; + input snoop; // Carrier is steady on through this, unless we're snooping. assign pwr_hi = ck_1356megb & (~snoop); assign pwr_oe1 = 1'b0; -assign pwr_oe2 = 1'b0; assign pwr_oe3 = 1'b0; assign pwr_oe4 = 1'b0; -reg ssp_clk; -reg ssp_frame; - -reg fc_div_2; -always @(posedge ck_1356meg) - fc_div_2 = ~fc_div_2; - -reg fc_div_4; -always @(posedge fc_div_2) - fc_div_4 = ~fc_div_4; - -reg fc_div_8; -always @(posedge fc_div_4) - fc_div_8 = ~fc_div_8; - -reg adc_clk; - -always @(xcorr_is_848 or xcorr_quarter_freq or ck_1356meg) - if(~xcorr_quarter_freq) - begin - if(xcorr_is_848) - // The subcarrier frequency is fc/16; we will sample at fc, so that - // means the subcarrier is 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 ... - adc_clk <= ck_1356meg; - else - // The subcarrier frequency is fc/32; we will sample at fc/2, and - // the subcarrier will look identical. - adc_clk <= fc_div_2; - end - else - begin - if(xcorr_is_848) - // The subcarrier frequency is fc/64 - adc_clk <= fc_div_4; - else - // The subcarrier frequency is fc/128 - adc_clk <= fc_div_8; - end +wire adc_clk = ck_1356megb; // When we're a reader, we just need to do the BPSK demod; but when we're an // eavesdropper, we also need to pick out the commands sent by the reader, // using AM. Do this the same way that we do it for the simulated tag. -reg after_hysteresis, after_hysteresis_prev; +reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev; reg [11:0] has_been_low_for; always @(negedge adc_clk) begin @@ -97,7 +59,6 @@ end // Let us report a correlation every 4 subcarrier cycles, or 4*16 samples, // so we need a 6-bit counter. reg [5:0] corr_i_cnt; -reg [5:0] corr_q_cnt; // And a couple of registers in which to accumulate the correlations. // we would add at most 32 times adc_d, the result can be held in 13 bits. // Need one additional bit because it can be negative as well @@ -105,32 +66,38 @@ reg signed [13:0] corr_i_accum; reg signed [13:0] corr_q_accum; reg signed [7:0] corr_i_out; reg signed [7:0] corr_q_out; +// clock and frame signal for communication to ARM +reg ssp_clk; +reg ssp_frame; + + // ADC data appears on the rising edge, so sample it on the falling edge always @(negedge adc_clk) begin + corr_i_cnt <= corr_i_cnt + 1; + // These are the correlators: we correlate against in-phase and quadrature // versions of our reference signal, and keep the (signed) result to // send out later over the SSP. - if(corr_i_cnt == 7'd63) + if(corr_i_cnt == 7'd0) begin if(snoop) begin - // highest 7 significant bits of tag signal (signed), 1 bit reader signal: - corr_i_out <= {corr_i_accum[13:7], after_hysteresis_prev}; - corr_q_out <= {corr_q_accum[13:7], after_hysteresis}; + // 7 most significant bits of tag signal (signed), 1 bit reader signal: + corr_i_out <= {corr_i_accum[13:7], after_hysteresis_prev_prev}; + corr_q_out <= {corr_q_accum[13:7], after_hysteresis_prev}; + after_hysteresis_prev_prev <= after_hysteresis; end else begin - // highest 8 significant bits of tag signal + // 8 most significant bits of tag signal corr_i_out <= corr_i_accum[13:6]; corr_q_out <= corr_q_accum[13:6]; end corr_i_accum <= adc_d; corr_q_accum <= adc_d; - corr_q_cnt <= 4; - corr_i_cnt <= 0; end else begin @@ -139,13 +106,11 @@ begin else corr_i_accum <= corr_i_accum + adc_d; - if(corr_q_cnt[3]) - corr_q_accum <= corr_q_accum - adc_d; - else + if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2 corr_q_accum <= corr_q_accum + adc_d; + else + corr_q_accum <= corr_q_accum - adc_d; - corr_i_cnt <= corr_i_cnt + 1; - corr_q_cnt <= corr_q_cnt + 1; end // The logic in hi_simulate.v reports 4 samples per bit. We report two @@ -172,7 +137,7 @@ begin end // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35 - // (two frames with 8 Bits each) + // (send two frames with 8 Bits each) if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000) ssp_frame = 1'b1; else @@ -186,5 +151,6 @@ assign dbg = corr_i_cnt[3]; // Unused. assign pwr_lo = 1'b0; +assign pwr_oe2 = 1'b0; endmodule -- 2.39.5