X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/15c4dc5ace24e6081d1597b011148f156cdd599e..efd193519c5e4613a16b7a13dd69a9962df0b218:/armsrc/iso14443.c diff --git a/armsrc/iso14443.c b/armsrc/iso14443.c index 1543efc9..c7f49f14 100644 --- a/armsrc/iso14443.c +++ b/armsrc/iso14443.c @@ -1,21 +1,29 @@ //----------------------------------------------------------------------------- +// Jonathan Westhues, split Nov 2006 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- // 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. -// Jonathan Westhues, split Nov 2006 //----------------------------------------------------------------------------- -#include + +#include "proxmark3.h" #include "apps.h" -#include "iso14443crc.h" +#include "util.h" +#include "string.h" +#include "iso14443crc.h" -//static void GetSamplesFor14443(BOOL weTx, int n); +//static void GetSamplesFor14443(int weTx, int n); -#define DEMOD_TRACE_SIZE 4096 +/*#define DEMOD_TRACE_SIZE 4096 #define READER_TAG_BUFFER_SIZE 2048 #define TAG_READER_BUFFER_SIZE 2048 -#define DMA_BUFFER_SIZE 1024 - +#define DEMOD_DMA_BUFFER_SIZE 1024 +*/ //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using // a UART kind of thing that's implemented in software. When we get a @@ -29,89 +37,89 @@ // that here) so that they can be transmitted to the reader. Doesn't transmit // them yet, just leaves them ready to send in ToSend[]. //----------------------------------------------------------------------------- -static void CodeIso14443bAsTag(const BYTE *cmd, int len) +static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { - int i; - - ToSendReset(); - - // Transmit a burst of ones, as the initial thing that lets the - // reader get phase sync. This (TR1) must be > 80/fs, per spec, - // but tag that I've tried (a Paypass) exceeds that by a fair bit, - // so I will too. - for(i = 0; i < 20; i++) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } - - // Send SOF. - for(i = 0; i < 10; i++) { - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - } - for(i = 0; i < 2; i++) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } - - for(i = 0; i < len; i++) { - int j; - BYTE b = cmd[i]; - - // Start bit - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - - // Data bits - for(j = 0; j < 8; j++) { - if(b & 1) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } else { - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - } - b >>= 1; - } - - // Stop bit - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } - - // Send SOF. - for(i = 0; i < 10; i++) { - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - } - for(i = 0; i < 10; i++) { - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } - - // Convert from last byte pos to length - ToSendMax++; - - // Add a few more for slop - ToSendMax += 2; + int i; + + ToSendReset(); + + // Transmit a burst of ones, as the initial thing that lets the + // reader get phase sync. This (TR1) must be > 80/fs, per spec, + // but tag that I've tried (a Paypass) exceeds that by a fair bit, + // so I will too. + for(i = 0; i < 20; i++) { + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + } + + // Send SOF. + for(i = 0; i < 10; i++) { + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + } + for(i = 0; i < 2; i++) { + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + } + + for(i = 0; i < len; i++) { + int j; + uint8_t b = cmd[i]; + + // Start bit + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + + // Data bits + for(j = 0; j < 8; j++) { + if(b & 1) { + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + } else { + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + } + b >>= 1; + } + + // Stop bit + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + } + + // Send SOF. + for(i = 0; i < 10; i++) { + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + } + for(i = 0; i < 10; i++) { + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + } + + // Convert from last byte pos to length + ToSendMax++; + + // Add a few more for slop + ToSendMax += 2; } //----------------------------------------------------------------------------- @@ -119,19 +127,19 @@ static void CodeIso14443bAsTag(const BYTE *cmd, int len) // variables. //----------------------------------------------------------------------------- static struct { - enum { - STATE_UNSYNCD, - STATE_GOT_FALLING_EDGE_OF_SOF, - STATE_AWAITING_START_BIT, - STATE_RECEIVING_DATA, - STATE_ERROR_WAIT - } state; - WORD shiftReg; - int bitCnt; - int byteCnt; - int byteCntMax; - int posCnt; - BYTE *output; + enum { + STATE_UNSYNCD, + STATE_GOT_FALLING_EDGE_OF_SOF, + STATE_AWAITING_START_BIT, + STATE_RECEIVING_DATA, + STATE_ERROR_WAIT + } state; + uint16_t shiftReg; + int bitCnt; + int byteCnt; + int byteCntMax; + int posCnt; + uint8_t *output; } Uart; /* Receive & handle a bit coming from the reader. @@ -143,127 +151,128 @@ static struct { * Returns: true if we received a EOF * false if we are still waiting for some more */ -static BOOL Handle14443UartBit(int bit) +static int Handle14443UartBit(int bit) { - switch(Uart.state) { - case STATE_UNSYNCD: - LED_A_OFF(); - if(!bit) { - // we went low, so this could be the beginning - // of an SOF - Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF; - Uart.posCnt = 0; - Uart.bitCnt = 0; - } - break; - - case STATE_GOT_FALLING_EDGE_OF_SOF: - Uart.posCnt++; - if(Uart.posCnt == 2) { - if(bit) { - if(Uart.bitCnt >= 10) { - // we've seen enough consecutive - // zeros that it's a valid SOF - Uart.posCnt = 0; - Uart.byteCnt = 0; - Uart.state = STATE_AWAITING_START_BIT; - LED_A_ON(); // Indicate we got a valid SOF - } else { - // didn't stay down long enough - // before going high, error - Uart.state = STATE_ERROR_WAIT; - } - } else { - // do nothing, keep waiting - } - Uart.bitCnt++; - } - if(Uart.posCnt >= 4) Uart.posCnt = 0; - if(Uart.bitCnt > 14) { - // Give up if we see too many zeros without - // a one, too. - Uart.state = STATE_ERROR_WAIT; - } - break; - - case STATE_AWAITING_START_BIT: - Uart.posCnt++; - if(bit) { - if(Uart.posCnt > 25) { - // stayed high for too long between - // characters, error - Uart.state = STATE_ERROR_WAIT; - } - } else { - // falling edge, this starts the data byte - Uart.posCnt = 0; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - Uart.state = STATE_RECEIVING_DATA; - LED_A_ON(); // Indicate we're receiving - } - break; - - case STATE_RECEIVING_DATA: - Uart.posCnt++; - if(Uart.posCnt == 2) { - // time to sample a bit - Uart.shiftReg >>= 1; - if(bit) { - Uart.shiftReg |= 0x200; - } - Uart.bitCnt++; - } - if(Uart.posCnt >= 4) { - Uart.posCnt = 0; - } - if(Uart.bitCnt == 10) { - if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) - { - // this is a data byte, with correct - // start and stop bits - Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff; - Uart.byteCnt++; - - if(Uart.byteCnt >= Uart.byteCntMax) { - // Buffer overflowed, give up - Uart.posCnt = 0; - Uart.state = STATE_ERROR_WAIT; - } else { - // so get the next byte now - Uart.posCnt = 0; - Uart.state = STATE_AWAITING_START_BIT; - } - } else if(Uart.shiftReg == 0x000) { - // this is an EOF byte - LED_A_OFF(); // Finished receiving - return TRUE; - } else { - // this is an error - Uart.posCnt = 0; - Uart.state = STATE_ERROR_WAIT; - } - } - break; - - case STATE_ERROR_WAIT: - // We're all screwed up, so wait a little while - // for whatever went wrong to finish, and then - // start over. - Uart.posCnt++; - if(Uart.posCnt > 10) { - Uart.state = STATE_UNSYNCD; - } - break; - - default: - Uart.state = STATE_UNSYNCD; - break; - } - - if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error - - return FALSE; + switch(Uart.state) { + case STATE_UNSYNCD: + LED_A_OFF(); + if(!bit) { + // we went low, so this could be the beginning + // of an SOF + Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF; + Uart.posCnt = 0; + Uart.bitCnt = 0; + } + break; + + case STATE_GOT_FALLING_EDGE_OF_SOF: + Uart.posCnt++; + if(Uart.posCnt == 2) { + if(bit) { + if(Uart.bitCnt >= 10) { + // we've seen enough consecutive + // zeros that it's a valid SOF + Uart.posCnt = 0; + Uart.byteCnt = 0; + Uart.state = STATE_AWAITING_START_BIT; + LED_A_ON(); // Indicate we got a valid SOF + } else { + // didn't stay down long enough + // before going high, error + Uart.state = STATE_ERROR_WAIT; + } + } else { + // do nothing, keep waiting + } + Uart.bitCnt++; + } + if(Uart.posCnt >= 4) Uart.posCnt = 0; + if(Uart.bitCnt > 14) { + // Give up if we see too many zeros without + // a one, too. + Uart.state = STATE_ERROR_WAIT; + } + break; + + case STATE_AWAITING_START_BIT: + Uart.posCnt++; + if(bit) { + if(Uart.posCnt > 25) { + // stayed high for too long between + // characters, error + Uart.state = STATE_ERROR_WAIT; + } + } else { + // falling edge, this starts the data byte + Uart.posCnt = 0; + Uart.bitCnt = 0; + Uart.shiftReg = 0; + Uart.state = STATE_RECEIVING_DATA; + LED_A_ON(); // Indicate we're receiving + } + break; + + case STATE_RECEIVING_DATA: + Uart.posCnt++; + if(Uart.posCnt == 2) { + // time to sample a bit + Uart.shiftReg >>= 1; + if(bit) { + Uart.shiftReg |= 0x200; + } + Uart.bitCnt++; + } + if(Uart.posCnt >= 4) { + Uart.posCnt = 0; + } + if(Uart.bitCnt == 10) { + if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) + { + // this is a data byte, with correct + // start and stop bits + Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff; + Uart.byteCnt++; + + if(Uart.byteCnt >= Uart.byteCntMax) { + // Buffer overflowed, give up + Uart.posCnt = 0; + Uart.state = STATE_ERROR_WAIT; + } else { + // so get the next byte now + Uart.posCnt = 0; + Uart.state = STATE_AWAITING_START_BIT; + } + } else if(Uart.shiftReg == 0x000) { + // this is an EOF byte + LED_A_OFF(); // Finished receiving + return TRUE; + } else { + // this is an error + Uart.posCnt = 0; + Uart.state = STATE_ERROR_WAIT; + } + } + break; + + case STATE_ERROR_WAIT: + // We're all screwed up, so wait a little while + // for whatever went wrong to finish, and then + // start over. + Uart.posCnt++; + if(Uart.posCnt > 10) { + Uart.state = STATE_UNSYNCD; + } + break; + + default: + Uart.state = STATE_UNSYNCD; + break; + } + + // This row make the error blew circular buffer in hf 14b snoop + //if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error + + return FALSE; } //----------------------------------------------------------------------------- @@ -275,45 +284,44 @@ static BOOL Handle14443UartBit(int bit) // Assume that we're called with the SSC (to the FPGA) and ADC path set // correctly. //----------------------------------------------------------------------------- -static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen) +static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen) { - BYTE mask; - int i, bit; - - // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); - - - // Now run a `software UART' on the stream of incoming samples. - Uart.output = received; - Uart.byteCntMax = maxLen; - Uart.state = STATE_UNSYNCD; - - for(;;) { - WDT_HIT(); - - if(BUTTON_PRESS()) return FALSE; - - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR; - - mask = 0x80; - for(i = 0; i < 8; i++, mask >>= 1) { - bit = (b & mask); - if(Handle14443UartBit(bit)) { - *len = Uart.byteCnt; - return TRUE; - } - } - } - } + uint8_t mask; + int i, bit; + + // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); + + + // Now run a `software UART' on the stream of incoming samples. + Uart.output = received; + Uart.byteCntMax = maxLen; + Uart.state = STATE_UNSYNCD; + + for(;;) { + WDT_HIT(); + + if(BUTTON_PRESS()) return FALSE; + + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + + mask = 0x80; + for(i = 0; i < 8; i++, mask >>= 1) { + bit = (b & mask); + if(Handle14443UartBit(bit)) { + *len = Uart.byteCnt; + return TRUE; + } + } + } + } } //----------------------------------------------------------------------------- @@ -322,99 +330,99 @@ static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen) //----------------------------------------------------------------------------- void SimulateIso14443Tag(void) { - static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; - static const BYTE response1[] = { - 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22, - 0x00, 0x21, 0x85, 0x5e, 0xd7 - }; + static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + static const uint8_t response1[] = { + 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22, + 0x00, 0x21, 0x85, 0x5e, 0xd7 + }; - BYTE *resp; - int respLen; + uint8_t *resp; + int respLen; - BYTE *resp1 = (((BYTE *)BigBuf) + 800); - int resp1Len; + uint8_t *resp1 = BigBuf_get_addr() + 800; + int resp1Len; - BYTE *receivedCmd = (BYTE *)BigBuf; - int len; + uint8_t *receivedCmd = BigBuf_get_addr(); + int len; - int i; + int i; - int cmdsRecvd = 0; + int cmdsRecvd = 0; - memset(receivedCmd, 0x44, 400); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + memset(receivedCmd, 0x44, 400); - CodeIso14443bAsTag(response1, sizeof(response1)); - memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax; + CodeIso14443bAsTag(response1, sizeof(response1)); + memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax; - // We need to listen to the high-frequency, peak-detected path. - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); + // We need to listen to the high-frequency, peak-detected path. + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); - cmdsRecvd = 0; + cmdsRecvd = 0; - for(;;) { - BYTE b1, b2; + for(;;) { + uint8_t b1, b2; - if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) { + if(!GetIso14443CommandFromReader(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) { - resp = resp1; respLen = resp1Len; - } else { - Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd); - // And print whether the CRC fails, just for good measure - ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); - if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { - // Not so good, try again. - DbpString("+++CRC fail"); - } else { - DbpString("CRC passes"); - } - break; - } - - memset(receivedCmd, 0x44, 32); - - cmdsRecvd++; - - if(cmdsRecvd > 0x30) { - DbpString("many commands later..."); - break; - } - - if(respLen <= 0) continue; - - // Modulate BPSK - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK); - AT91C_BASE_SSC->SSC_THR = 0xff; - FpgaSetupSsc(); - - // Transmit the response. - i = 0; - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - BYTE b = resp[i]; - - AT91C_BASE_SSC->SSC_THR = b; - - i++; - if(i > respLen) { - break; - } - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR; - (void)b; - } - } - } + } + + // Good, look at the command now. + + 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); + // And print whether the CRC fails, just for good measure + ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); + if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { + // Not so good, try again. + DbpString("+++CRC fail"); + } else { + DbpString("CRC passes"); + } + break; + } + + memset(receivedCmd, 0x44, 32); + + cmdsRecvd++; + + if(cmdsRecvd > 0x30) { + DbpString("many commands later..."); + break; + } + + if(respLen <= 0) continue; + + // Modulate BPSK + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK); + AT91C_BASE_SSC->SSC_THR = 0xff; + FpgaSetupSsc(); + + // Transmit the response. + i = 0; + for(;;) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + uint8_t b = resp[i]; + + AT91C_BASE_SSC->SSC_THR = b; + + i++; + if(i > respLen) { + break; + } + } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + (void)b; + } + } + } } //============================================================================= @@ -425,25 +433,25 @@ void SimulateIso14443Tag(void) //============================================================================= static struct { - enum { - DEMOD_UNSYNCD, - DEMOD_PHASE_REF_TRAINING, - DEMOD_AWAITING_FALLING_EDGE_OF_SOF, - DEMOD_GOT_FALLING_EDGE_OF_SOF, - DEMOD_AWAITING_START_BIT, - DEMOD_RECEIVING_DATA, - DEMOD_ERROR_WAIT - } state; - int bitCount; - int posCount; - int thisBit; - int metric; - int metricN; - WORD shiftReg; - BYTE *output; - int len; - int sumI; - int sumQ; + enum { + DEMOD_UNSYNCD, + DEMOD_PHASE_REF_TRAINING, + DEMOD_AWAITING_FALLING_EDGE_OF_SOF, + DEMOD_GOT_FALLING_EDGE_OF_SOF, + DEMOD_AWAITING_START_BIT, + DEMOD_RECEIVING_DATA, + DEMOD_ERROR_WAIT + } state; + int bitCount; + int posCount; + int thisBit; + int metric; + int metricN; + uint16_t shiftReg; + uint8_t *output; + int len; + int sumI; + int sumQ; } Demod; /* @@ -457,239 +465,268 @@ static struct { * false if we are still waiting for some more * */ -static BOOL Handle14443SamplesDemod(int ci, int cq) +static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) { - int v; + 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; \ - } else { \ - v = -ci; \ - } \ - if(Demod.sumQ > 0) { \ - v += cq; \ - } else { \ - v -= cq; \ - } \ - } - - 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; - Demod.state = DEMOD_PHASE_REF_TRAINING; - Demod.sumI = 0; - Demod.sumQ = 0; - } - 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; - } - } - Demod.posCount++; - break; - - case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: - MAKE_SOFT_DECISION(); - if(v < 0) { - Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; - Demod.posCount = 0; - } else { - if(Demod.posCount > 100) { - Demod.state = DEMOD_UNSYNCD; - } - } - Demod.posCount++; - break; - - case DEMOD_GOT_FALLING_EDGE_OF_SOF: - MAKE_SOFT_DECISION(); - if(v > 0) { - if(Demod.posCount < 12) { - Demod.state = DEMOD_UNSYNCD; - } else { - LED_C_ON(); // Got SOF - Demod.state = DEMOD_AWAITING_START_BIT; - Demod.posCount = 0; - Demod.len = 0; - Demod.metricN = 0; - Demod.metric = 0; - } - } else { - if(Demod.posCount > 100) { - Demod.state = DEMOD_UNSYNCD; - } - } - Demod.posCount++; - break; - - case DEMOD_AWAITING_START_BIT: - MAKE_SOFT_DECISION(); - if(v > 0) { - if(Demod.posCount > 10) { - Demod.state = DEMOD_UNSYNCD; - } - } else { - Demod.bitCount = 0; - Demod.posCount = 1; - Demod.thisBit = v; - Demod.shiftReg = 0; - Demod.state = DEMOD_RECEIVING_DATA; - } - break; - - case DEMOD_RECEIVING_DATA: - MAKE_SOFT_DECISION(); - if(Demod.posCount == 0) { - Demod.thisBit = v; - Demod.posCount = 1; - } else { - Demod.thisBit += v; - - if(Demod.thisBit > 0) { - Demod.metric += Demod.thisBit; - } else { - Demod.metric -= Demod.thisBit; - } - (Demod.metricN)++; - - Demod.shiftReg >>= 1; - if(Demod.thisBit > 0) { - Demod.shiftReg |= 0x200; - } - - Demod.bitCount++; - if(Demod.bitCount == 10) { - WORD s = Demod.shiftReg; - if((s & 0x200) && !(s & 0x001)) { - BYTE b = (s >> 1); - Demod.output[Demod.len] = b; - Demod.len++; - Demod.state = DEMOD_AWAITING_START_BIT; - } else if(s == 0x000) { - // This is EOF - LED_C_OFF(); - return TRUE; - Demod.state = DEMOD_UNSYNCD; - } else { - Demod.state = DEMOD_UNSYNCD; - } - } - Demod.posCount = 0; - } - break; - - default: - Demod.state = DEMOD_UNSYNCD; - break; - } - - if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized... - return FALSE; + if(Demod.sumI > 0) { \ + v = ci; \ + } else { \ + v = -ci; \ + } \ + if(Demod.sumQ > 0) { \ + v += cq; \ + } else { \ + v -= cq; \ + } \ + } + + 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; + Demod.state = DEMOD_PHASE_REF_TRAINING; + Demod.sumI = 0; + Demod.sumQ = 0; + } + 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; + } + } + Demod.posCount++; + break; + + case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: + MAKE_SOFT_DECISION(); + if(v < 0) { + Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; + Demod.posCount = 0; + } else { + if(Demod.posCount > 100) { + Demod.state = DEMOD_UNSYNCD; + } + } + Demod.posCount++; + break; + + case DEMOD_GOT_FALLING_EDGE_OF_SOF: + MAKE_SOFT_DECISION(); + if(v > 0) { + if(Demod.posCount < 12) { + Demod.state = DEMOD_UNSYNCD; + } else { + LED_C_ON(); // Got SOF + Demod.state = DEMOD_AWAITING_START_BIT; + Demod.posCount = 0; + Demod.len = 0; + Demod.metricN = 0; + Demod.metric = 0; + } + } else { + if(Demod.posCount > 100) { + Demod.state = DEMOD_UNSYNCD; + } + } + Demod.posCount++; + break; + + case DEMOD_AWAITING_START_BIT: + MAKE_SOFT_DECISION(); + if(v > 0) { + if(Demod.posCount > 10) { + Demod.state = DEMOD_UNSYNCD; + } + } else { + Demod.bitCount = 0; + Demod.posCount = 1; + Demod.thisBit = v; + Demod.shiftReg = 0; + Demod.state = DEMOD_RECEIVING_DATA; + } + break; + + case DEMOD_RECEIVING_DATA: + MAKE_SOFT_DECISION(); + if(Demod.posCount == 0) { + Demod.thisBit = v; + Demod.posCount = 1; + } else { + Demod.thisBit += v; + + if(Demod.thisBit > 0) { + Demod.metric += Demod.thisBit; + } else { + Demod.metric -= Demod.thisBit; + } + (Demod.metricN)++; + + Demod.shiftReg >>= 1; + if(Demod.thisBit > 0) { + Demod.shiftReg |= 0x200; + } + + Demod.bitCount++; + if(Demod.bitCount == 10) { + uint16_t s = Demod.shiftReg; + if((s & 0x200) && !(s & 0x001)) { + uint8_t b = (s >> 1); + Demod.output[Demod.len] = b; + Demod.len++; + Demod.state = DEMOD_AWAITING_START_BIT; + } else if(s == 0x000) { + // This is EOF + LED_C_OFF(); + Demod.state = DEMOD_UNSYNCD; + return TRUE; + } else { + Demod.state = DEMOD_UNSYNCD; + } + } + Demod.posCount = 0; + } + break; + + default: + Demod.state = DEMOD_UNSYNCD; + break; + } + + if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized... + return FALSE; +} +static void DemodReset() +{ + // Clear out the state of the "UART" that receives from the tag. + Demod.len = 0; + Demod.state = DEMOD_UNSYNCD; + memset(Demod.output, 0x00, MAX_FRAME_SIZE); +} +static void DemodInit(uint8_t *data) +{ + Demod.output = data; + DemodReset(); +} + +static void UartReset() +{ + Uart.byteCntMax = MAX_FRAME_SIZE; + Uart.state = STATE_UNSYNCD; + Uart.byteCnt = 0; + Uart.bitCnt = 0; +} +static void UartInit(uint8_t *data) +{ + Uart.output = data; + UartReset(); } /* - * Demodulate the samples we received from the tag + * 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(BOOL weTx, int n, BOOL quiet) +static void GetSamplesFor14443Demod(int weTx, int n, int quiet) { - int max = 0; - BOOL gotFrame = FALSE; + int max = 0; + int gotFrame = FALSE; + int lastRxCounter, ci, cq, samples = 0; + + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); + + // The command (reader -> tag) that we're receiving. + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + + // The response (tag -> reader) that we're receiving. + uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE); + + // The DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); -//# define DMA_BUFFER_SIZE 8 - SBYTE *dmaBuf; + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResponse); + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd); - int lastRxCounter; - SBYTE *upTo; + // Setup and start DMA. + FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE); - int ci, cq; + uint8_t *upTo= dmaBuf; + lastRxCounter = DMA_BUFFER_SIZE; - int samples = 0; + // Signal field is ON with the appropriate LED: + if (weTx) LED_D_ON(); else LED_D_OFF(); + // 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)); + + 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) + { + ci = upTo[0]; + cq = upTo[1]; + upTo += 2; + if(upTo - dmaBuf > DMA_BUFFER_SIZE) { + upTo -= DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } + lastRxCounter -= 2; + if(lastRxCounter <= 0) { + lastRxCounter += DMA_BUFFER_SIZE; + } - // Clear out the state of the "UART" that receives from the tag. - memset(BigBuf, 0x44, 400); - Demod.output = (BYTE *)BigBuf; - Demod.len = 0; - Demod.state = DEMOD_UNSYNCD; + samples += 2; - // And the UART that receives from the reader - Uart.output = (((BYTE *)BigBuf) + 1024); - Uart.byteCntMax = 100; - Uart.state = STATE_UNSYNCD; + Handle14443UartBit(1); + Handle14443UartBit(1); - // Setup for the DMA. - dmaBuf = (SBYTE *)(BigBuf + 32); - upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE); + if(Handle14443SamplesDemod(ci, cq)) { + gotFrame = 1; + } + } - // Signal field is ON with the appropriate LED: - if (weTx) LED_D_ON(); else LED_D_OFF(); - // 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)); - - 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) - { - ci = upTo[0]; - cq = upTo[1]; - upTo += 2; - if(upTo - dmaBuf > DMA_BUFFER_SIZE) { - upTo -= DMA_BUFFER_SIZE; - AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } - lastRxCounter -= 2; - if(lastRxCounter <= 0) { - lastRxCounter += DMA_BUFFER_SIZE; - } - - samples += 2; - - Handle14443UartBit(1); - Handle14443UartBit(1); - - if(Handle14443SamplesDemod(ci, cq)) { - gotFrame = 1; - } - } - - if(samples > 2000) { - break; - } - } - AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; - if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len); + if(samples > 2000) { + break; + } + } + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; + if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len); + //Tracing + if (tracing && Demod.len > 0) { + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(Demod.output , Demod.len, parity); + LogTrace(Demod.output,Demod.len, 0, 0, parity, FALSE); + } } //----------------------------------------------------------------------------- @@ -697,31 +734,31 @@ static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet) // samples from the FPGA, which we will later do some signal processing on, // to get the bits. //----------------------------------------------------------------------------- -/*static void GetSamplesFor14443(BOOL weTx, int n) +/*static void GetSamplesFor14443(int weTx, int n) { - BYTE *dest = (BYTE *)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)) { - SBYTE b; - b = (SBYTE)AT91C_BASE_SSC->SSC_RHR; - - dest[c++] = (BYTE)b; - - if(c >= n) { - break; - } - } - } + 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; + } + } + } }*/ //----------------------------------------------------------------------------- @@ -729,105 +766,105 @@ static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet) //----------------------------------------------------------------------------- static void TransmitFor14443(void) { - int c; + int c; - FpgaSetupSsc(); + FpgaSetupSsc(); - while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xff; - } + 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(); // Signal we are transmitting with the Green LED 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 DWORD 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]; - c++; - if(c >= ToSendMax) { - break; - } - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - volatile DWORD r = AT91C_BASE_SSC->SSC_RHR; - (void)r; - } - WDT_HIT(); - } - LED_B_OFF(); // Finished sending + 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]; + 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 } //----------------------------------------------------------------------------- // Code a layer 2 command (string of octets, including CRC) into ToSend[], // so that it is ready to transmit to the tag using TransmitFor14443(). //----------------------------------------------------------------------------- -void CodeIso14443bAsReader(const BYTE *cmd, int len) +static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { - int i, j; - BYTE b; - - ToSendReset(); - - // Establish initial reference level - for(i = 0; i < 40; i++) { - ToSendStuffBit(1); - } - // Send SOF - for(i = 0; i < 10; i++) { - ToSendStuffBit(0); - } - - for(i = 0; i < len; i++) { - // Stop bits/EGT - ToSendStuffBit(1); - ToSendStuffBit(1); - // Start bit - ToSendStuffBit(0); - // Data bits - b = cmd[i]; - for(j = 0; j < 8; j++) { - if(b & 1) { - ToSendStuffBit(1); - } else { - ToSendStuffBit(0); - } - b >>= 1; - } - } - // Send EOF - ToSendStuffBit(1); - for(i = 0; i < 10; i++) { - ToSendStuffBit(0); - } - for(i = 0; i < 8; i++) { - 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++) { - ToSendStuffBit(1); - } - - // Convert from last character reference to length - ToSendMax++; + int i, j; + uint8_t b; + + ToSendReset(); + + // Establish initial reference level + for(i = 0; i < 40; i++) { + ToSendStuffBit(1); + } + // Send SOF + for(i = 0; i < 10; i++) { + ToSendStuffBit(0); + } + + for(i = 0; i < len; i++) { + // Stop bits/EGT + ToSendStuffBit(1); + ToSendStuffBit(1); + // Start bit + ToSendStuffBit(0); + // Data bits + b = cmd[i]; + for(j = 0; j < 8; j++) { + if(b & 1) { + ToSendStuffBit(1); + } else { + ToSendStuffBit(0); + } + b >>= 1; + } + } + // Send EOF + ToSendStuffBit(1); + for(i = 0; i < 10; i++) { + ToSendStuffBit(0); + } + for(i = 0; i < 8; i++) { + 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++) { + ToSendStuffBit(1); + } + + // Convert from last character reference to length + ToSendMax++; } //----------------------------------------------------------------------------- @@ -835,32 +872,28 @@ void CodeIso14443bAsReader(const BYTE *cmd, int len) // 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(DWORD parameter) +void AcquireRawAdcSamplesIso14443(uint32_t parameter) { - BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; - - // 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); - - 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); - - CodeIso14443bAsReader(cmd1, sizeof(cmd1)); - TransmitFor14443(); -// LED_A_ON(); - GetSamplesFor14443Demod(TRUE, 2000, FALSE); -// LED_A_OFF(); + uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + + SendRawCommand14443B(sizeof(cmd1),1,1,cmd1); +} + +/** + Convenience function to encode, transmit and trace iso 14443b comms + **/ +static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) +{ + CodeIso14443bAsReader(cmd, len); + TransmitFor14443(); + if (tracing) { + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(cmd, len, parity); + LogTrace(cmd,len, 0, 0, parity, TRUE); + } } //----------------------------------------------------------------------------- @@ -872,136 +905,131 @@ void AcquireRawAdcSamplesIso14443(DWORD parameter) // // I tried to be systematic and check every answer of the tag, every CRC, etc... //----------------------------------------------------------------------------- -void ReadSRI512Iso14443(DWORD parameter) -{ - ReadSTMemoryIso14443(parameter,0x0F); -} -void ReadSRIX4KIso14443(DWORD parameter) +void ReadSTMemoryIso14443(uint32_t dwLast) { - ReadSTMemoryIso14443(parameter,0x7F); -} + clear_trace(); + set_tracing(TRUE); -void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast) -{ - BYTE i = 0x00; - - // Make sure that we start from off, since the tags are stateful; - // confusing things will happen if we don't reset them between reads. - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); - - 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); - - // First command: wake up the tag using the INITIATE command - BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b}; - CodeIso14443bAsReader(cmd1, sizeof(cmd1)); - TransmitFor14443(); + uint8_t i = 0x00; + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Make sure that we start from off, since the tags are stateful; + // confusing things will happen if we don't reset them between reads. + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + + 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); + + // First command: wake up the tag using the INITIATE command + uint8_t cmd1[] = { 0x06, 0x00, 0x97, 0x5b}; + + CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, 2000,TRUE); + GetSamplesFor14443Demod(TRUE, 2000,TRUE); // LED_A_OFF(); - if (Demod.len == 0) { + if (Demod.len == 0) { DbpString("No response from tag"); return; - } else { + } else { Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x", Demod.output[0], Demod.output[1],Demod.output[2]); - } - // There is a response, SELECT the uid - DbpString("Now SELECT tag:"); - cmd1[0] = 0x0E; // 0x0E is SELECT - cmd1[1] = Demod.output[0]; - ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); - CodeIso14443bAsReader(cmd1, sizeof(cmd1)); - TransmitFor14443(); + } + // There is a response, SELECT the uid + DbpString("Now SELECT tag:"); + cmd1[0] = 0x0E; // 0x0E is SELECT + cmd1[1] = Demod.output[0]; + ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); + CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); + // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, 2000,TRUE); + GetSamplesFor14443Demod(TRUE, 2000,TRUE); // LED_A_OFF(); - if (Demod.len != 3) { + if (Demod.len != 3) { 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]) { + } + // 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; - } - // Check response from the tag: should be the same UID as the command we just sent: - if (cmd1[1] != Demod.output[0]) { + } + // 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; - } - // Tag is now selected, - // First get the tag's UID: - cmd1[0] = 0x0B; - ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]); - CodeIso14443bAsReader(cmd1, 3); // Only first three bytes for this one - TransmitFor14443(); + } + // Tag is now selected, + // First get the tag's UID: + cmd1[0] = 0x0B; + ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]); + CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one + // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, 2000,TRUE); + GetSamplesFor14443Demod(TRUE, 2000,TRUE); // LED_A_OFF(); - if (Demod.len != 10) { + if (Demod.len != 10) { 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]) { + } + // 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 ?) - } - Dbprintf("Tag UID (64 bits): %08x %08x", + } + 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]); - // Now loop to read all 16 blocks, address from 0 to 15 - DbpString("Tag memory dump, block 0 to 15"); - cmd1[0] = 0x08; - i = 0x00; - dwLast++; - for (;;) { - if (i == dwLast) { - DbpString("System area block (0xff):"); - i = 0xff; - } - cmd1[1] = i; - ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); - CodeIso14443bAsReader(cmd1, sizeof(cmd1)); - TransmitFor14443(); + // Now loop to read all 16 blocks, address from 0 to last block + Dbprintf("Tag memory dump, block 0 to %d",dwLast); + cmd1[0] = 0x08; + i = 0x00; + dwLast++; + for (;;) { + if (i == dwLast) { + DbpString("System area block (0xff):"); + i = 0xff; + } + cmd1[1] = i; + ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); + CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); + // LED_A_ON(); - GetSamplesFor14443Demod(TRUE, 2000,TRUE); + GetSamplesFor14443Demod(TRUE, 2000,TRUE); // LED_A_OFF(); - 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..."); 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]) { + } + // 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 ?) - } - // Now print out the memory location: - Dbprintf("Address=%x, Contents=%x, CRC=%x", i, + } + // 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]); - if (i == 0xff) { + if (i == 0xff) { break; - } - i++; - } + } + i++; + } } @@ -1020,189 +1048,203 @@ void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast) * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE - * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DMA_BUFFER_SIZE + * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DEMOD_DMA_BUFFER_SIZE */ -void SnoopIso14443(void) +void RAMFUNC SnoopIso14443(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. - BOOL triggered = FALSE; - - // The command (reader -> tag) that we're working on receiving. - BYTE *receivedCmd = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE; - // The response (tag -> reader) that we're working on receiving. - BYTE *receivedResponse = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE; - - // As we receive stuff, we copy it from receivedCmd or receivedResponse - // into trace, along with its length and other annotations. - BYTE *trace = (BYTE *)BigBuf; - int traceLen = 0; - - // The DMA buffer, used to stream samples from the FPGA. - SBYTE *dmaBuf = (SBYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE + TAG_READER_BUFFER_SIZE; - int lastRxCounter; - SBYTE *upTo; - int ci, cq; - int maxBehindBy = 0; - - // Count of samples received so far, so that we can include timing - // information in the trace buffer. - int samples = 0; - - // Initialize the trace buffer - memset(trace, 0x44, DEMOD_TRACE_SIZE); - - // Set up the demodulator for tag -> reader responses. - Demod.output = receivedResponse; - Demod.len = 0; - Demod.state = DEMOD_UNSYNCD; - - // And the reader -> tag commands - memset(&Uart, 0, sizeof(Uart)); - Uart.output = receivedCmd; - Uart.byteCntMax = 100; - Uart.state = STATE_UNSYNCD; + // 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; + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + BigBuf_free(); + + clear_trace(); + set_tracing(TRUE); + + // The DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + int lastRxCounter; + uint8_t *upTo; + int ci, cq; + int maxBehindBy = 0; + + // Count of samples received so far, so that we can include timing + // information in the trace buffer. + int samples = 0; + + DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); // Print some debug information about the buffer sizes Dbprintf("Snooping buffers initialized:"); - Dbprintf(" Trace: %i bytes", DEMOD_TRACE_SIZE); - Dbprintf(" Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE); - Dbprintf(" tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE); + 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); - - // Use a counter for blinking the LED - long ledCount=0; - long ledFlashAt=200000; - - // And put the FPGA in the appropriate mode - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - FPGA_HF_READER_RX_XCORR_SNOOP); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Setup for the DMA. - FpgaSetupSsc(); - upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE); - // And now we loop, receiving samples. - for(;;) { - // Blink the LED while Snooping - ledCount++; - if (ledCount == ledFlashAt) { - LED_D_ON(); + + // Signal field is off with the appropriate LED + LED_D_OFF(); + + // 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); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + // Setup for the DMA. + FpgaSetupSsc(); + upTo = dmaBuf; + lastRxCounter = DMA_BUFFER_SIZE; + FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + uint8_t parity[MAX_PARITY_SIZE]; + LED_A_ON(); + + // And now we loop, receiving samples. + for(;;) { + int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & + (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 (ledCount >= 2*ledFlashAt) { - LED_D_OFF(); - ledCount=0; + if(behindBy < 2) continue; + + ci = upTo[0]; + cq = upTo[1]; + upTo += 2; + lastRxCounter -= 2; + if(upTo - dmaBuf > DMA_BUFFER_SIZE) { + upTo -= DMA_BUFFER_SIZE; + lastRxCounter += DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; } - - int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & - (DMA_BUFFER_SIZE-1); - if(behindBy > maxBehindBy) { - maxBehindBy = behindBy; - if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not? - Dbprintf("blew circular buffer! behindBy=%x", behindBy); - goto done; - } - } - if(behindBy < 2) continue; - - ci = upTo[0]; - cq = upTo[1]; - upTo += 2; - lastRxCounter -= 2; - if(upTo - dmaBuf > DMA_BUFFER_SIZE) { - upTo -= DMA_BUFFER_SIZE; - lastRxCounter += DMA_BUFFER_SIZE; - AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } - - samples += 2; - -#define HANDLE_BIT_IF_BODY \ - if(triggered) { \ - ledFlashAt=30000; \ - trace[traceLen++] = ((samples >> 0) & 0xff); \ - trace[traceLen++] = ((samples >> 8) & 0xff); \ - trace[traceLen++] = ((samples >> 16) & 0xff); \ - trace[traceLen++] = ((samples >> 24) & 0xff); \ - trace[traceLen++] = 0; \ - trace[traceLen++] = 0; \ - trace[traceLen++] = 0; \ - trace[traceLen++] = 0; \ - trace[traceLen++] = Uart.byteCnt; \ - memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \ - traceLen += Uart.byteCnt; \ - if(traceLen > 1000) break; \ - } \ - /* And ready to receive another command. */ \ - memset(&Uart, 0, sizeof(Uart)); \ - Uart.output = receivedCmd; \ - Uart.byteCntMax = 100; \ - Uart.state = STATE_UNSYNCD; \ - /* And also reset the demod code, which might have been */ \ - /* false-triggered by the commands from the reader. */ \ - memset(&Demod, 0, sizeof(Demod)); \ - Demod.output = receivedResponse; \ - Demod.state = DEMOD_UNSYNCD; \ - - if(Handle14443UartBit(ci & 1)) { - HANDLE_BIT_IF_BODY - } - if(Handle14443UartBit(cq & 1)) { - HANDLE_BIT_IF_BODY - } - - if(Handle14443SamplesDemod(ci, cq)) { - // timestamp, as a count of samples - trace[traceLen++] = ((samples >> 0) & 0xff); - trace[traceLen++] = ((samples >> 8) & 0xff); - trace[traceLen++] = ((samples >> 16) & 0xff); - trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff); - // correlation metric (~signal strength estimate) - if(Demod.metricN != 0) { - Demod.metric /= Demod.metricN; - } - trace[traceLen++] = ((Demod.metric >> 0) & 0xff); - trace[traceLen++] = ((Demod.metric >> 8) & 0xff); - trace[traceLen++] = ((Demod.metric >> 16) & 0xff); - trace[traceLen++] = ((Demod.metric >> 24) & 0xff); - // length - trace[traceLen++] = Demod.len; - memcpy(trace+traceLen, receivedResponse, Demod.len); - traceLen += Demod.len; - if(traceLen > DEMOD_TRACE_SIZE) { - DbpString("Reached trace limit"); - goto done; + + samples += 2; + + if(Handle14443UartBit(ci & 1)) { + if(triggered && tracing) { + GetParity(Uart.output, Uart.byteCnt, parity); + LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE); } + if(Uart.byteCnt==0) Dbprintf("[1] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt); - triggered = TRUE; + /* 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 & 1)) { + if(triggered && tracing) { + GetParity(Uart.output, Uart.byteCnt, parity); + 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 */ + /* false-triggered by the commands from the reader. */ + DemodReset(); + } + + if(Handle14443SamplesDemod(ci, cq)) { + + //Use samples as a time measurement + if(tracing) + { + uint8_t parity[MAX_PARITY_SIZE]; + GetParity(Demod.output, Demod.len, parity); + LogTrace(Demod.output,Demod.len,samples, samples,parity,FALSE); + } + triggered = TRUE; + LED_A_OFF(); + LED_B_ON(); - // And ready to receive another response. - memset(&Demod, 0, sizeof(Demod)); - Demod.output = receivedResponse; - Demod.state = DEMOD_UNSYNCD; - } + // And ready to receive another response. + DemodReset(); + } WDT_HIT(); - if(BUTTON_PRESS()) { - DbpString("cancelled"); - goto done; - } - } + if(!tracing) { + DbpString("Reached trace limit"); + break; + } -done: - LED_D_OFF(); - AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; + if(BUTTON_PRESS()) { + DbpString("cancelled"); + break; + } + } + FpgaDisableSscDma(); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; DbpString("Snoop statistics:"); - Dbprintf(" Max behind by: %i", maxBehindBy); + Dbprintf(" Max behind by: %i", maxBehindBy); Dbprintf(" Uart State: %x", Uart.state); Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt); Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax); - Dbprintf(" Trace length: %i", traceLen); + Dbprintf(" Trace length: %i", BigBuf_get_traceLen()); } + +/* + * Send raw command to tag ISO14443B + * @Input + * datalen len of buffer data + * recv bool when true wait for data from tag and send to client + * powerfield bool leave the field on when true + * data buffer with byte to send + * + * @Output + * none + * + */ + +void SendRawCommand14443B(uint32_t datalen, uint32_t recv,uint8_t powerfield, uint8_t data[]) +{ + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + 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); + } + + CodeAndTransmit14443bAsReader(data, datalen); + + if(recv) + { + uint16_t iLen = MIN(Demod.len,USB_CMD_DATA_SIZE); + GetSamplesFor14443Demod(TRUE, 2000, TRUE); + cmd_send(CMD_ACK,iLen,0,0,Demod.output,iLen); + } + if(!powerfield) + { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + } +} +