-//-----------------------------------------------------------------------------\r
-// Routines to support ISO 14443. This includes both the reader software and\r
-// the `fake tag' modes. At the moment only the Type B modulation is\r
-// supported.\r
-// Jonathan Westhues, split Nov 2006\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-#include "../common/iso14443_crc.c"\r
-\r
-\r
-//static void GetSamplesFor14443(BOOL weTx, int n);\r
-\r
-#define DMA_BUFFER_SIZE 256\r
-\r
-//=============================================================================\r
-// An ISO 14443 Type B tag. We listen for commands from the reader, using\r
-// a UART kind of thing that's implemented in software. When we get a\r
-// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.\r
-// If it's good, then we can do something appropriate with it, and send\r
-// a response.\r
-//=============================================================================\r
-\r
-//-----------------------------------------------------------------------------\r
-// Code up a string of octets at layer 2 (including CRC, we don't generate\r
-// that here) so that they can be transmitted to the reader. Doesn't transmit\r
-// them yet, just leaves them ready to send in ToSend[].\r
-//-----------------------------------------------------------------------------\r
-static void CodeIso14443bAsTag(const BYTE *cmd, int len)\r
-{\r
- int i;\r
-\r
- ToSendReset();\r
-\r
- // Transmit a burst of ones, as the initial thing that lets the\r
- // reader get phase sync. This (TR1) must be > 80/fs, per spec,\r
- // but tag that I've tried (a Paypass) exceeds that by a fair bit,\r
- // so I will too.\r
- for(i = 0; i < 20; i++) {\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- }\r
-\r
- // Send SOF.\r
- for(i = 0; i < 10; i++) {\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- }\r
- for(i = 0; i < 2; i++) {\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- }\r
-\r
- for(i = 0; i < len; i++) {\r
- int j;\r
- BYTE b = cmd[i];\r
-\r
- // Start bit\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
-\r
- // Data bits\r
- for(j = 0; j < 8; j++) {\r
- if(b & 1) {\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- } else {\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- }\r
- b >>= 1;\r
- }\r
-\r
- // Stop bit\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- }\r
-\r
- // Send SOF.\r
- for(i = 0; i < 10; i++) {\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- ToSendStuffBit(0);\r
- }\r
- for(i = 0; i < 10; i++) {\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- ToSendStuffBit(1);\r
- }\r
-\r
- // Convert from last byte pos to length\r
- ToSendMax++;\r
-\r
- // Add a few more for slop\r
- ToSendMax += 2;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// The software UART that receives commands from the reader, and its state\r
-// variables.\r
-//-----------------------------------------------------------------------------\r
-static struct {\r
- enum {\r
- STATE_UNSYNCD,\r
- STATE_GOT_FALLING_EDGE_OF_SOF,\r
- STATE_AWAITING_START_BIT,\r
- STATE_RECEIVING_DATA,\r
- STATE_ERROR_WAIT\r
- } state;\r
- WORD shiftReg;\r
- int bitCnt;\r
- int byteCnt;\r
- int byteCntMax;\r
- int posCnt;\r
- BYTE *output;\r
-} Uart;\r
-\r
-/* Receive & handle a bit coming from the reader.\r
- *\r
- * LED handling:\r
- * LED A -> ON once we have received the SOF and are expecting the rest.\r
- * LED A -> OFF once we have received EOF or are in error state or unsynced\r
- *\r
- * Returns: true if we received a EOF\r
- * false if we are still waiting for some more\r
- */\r
-static BOOL Handle14443UartBit(int bit)\r
-{\r
- switch(Uart.state) {\r
- case STATE_UNSYNCD:\r
- LED_A_OFF();\r
- if(!bit) {\r
- // we went low, so this could be the beginning\r
- // of an SOF\r
- Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;\r
- Uart.posCnt = 0;\r
- Uart.bitCnt = 0;\r
- }\r
- break;\r
-\r
- case STATE_GOT_FALLING_EDGE_OF_SOF:\r
- Uart.posCnt++;\r
- if(Uart.posCnt == 2) {\r
- if(bit) {\r
- if(Uart.bitCnt >= 10) {\r
- // we've seen enough consecutive\r
- // zeros that it's a valid SOF\r
- Uart.posCnt = 0;\r
- Uart.byteCnt = 0;\r
- Uart.state = STATE_AWAITING_START_BIT;\r
- LED_A_ON(); // Indicate we got a valid SOF\r
- } else {\r
- // didn't stay down long enough\r
- // before going high, error\r
- Uart.state = STATE_ERROR_WAIT;\r
- }\r
- } else {\r
- // do nothing, keep waiting\r
- }\r
- Uart.bitCnt++;\r
- }\r
- if(Uart.posCnt >= 4) Uart.posCnt = 0;\r
- if(Uart.bitCnt > 14) {\r
- // Give up if we see too many zeros without\r
- // a one, too.\r
- Uart.state = STATE_ERROR_WAIT;\r
- }\r
- break;\r
-\r
- case STATE_AWAITING_START_BIT:\r
- Uart.posCnt++;\r
- if(bit) {\r
- if(Uart.posCnt > 25) {\r
- // stayed high for too long between\r
- // characters, error\r
- Uart.state = STATE_ERROR_WAIT;\r
- }\r
- } else {\r
- // falling edge, this starts the data byte\r
- Uart.posCnt = 0;\r
- Uart.bitCnt = 0;\r
- Uart.shiftReg = 0;\r
- Uart.state = STATE_RECEIVING_DATA;\r
- LED_A_ON(); // Indicate we're receiving\r
- }\r
- break;\r
-\r
- case STATE_RECEIVING_DATA:\r
- Uart.posCnt++;\r
- if(Uart.posCnt == 2) {\r
- // time to sample a bit\r
- Uart.shiftReg >>= 1;\r
- if(bit) {\r
- Uart.shiftReg |= 0x200;\r
- }\r
- Uart.bitCnt++;\r
- }\r
- if(Uart.posCnt >= 4) {\r
- Uart.posCnt = 0;\r
- }\r
- if(Uart.bitCnt == 10) {\r
- if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))\r
- {\r
- // this is a data byte, with correct\r
- // start and stop bits\r
- Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;\r
- Uart.byteCnt++;\r
-\r
- if(Uart.byteCnt >= Uart.byteCntMax) {\r
- // Buffer overflowed, give up\r
- Uart.posCnt = 0;\r
- Uart.state = STATE_ERROR_WAIT;\r
- } else {\r
- // so get the next byte now\r
- Uart.posCnt = 0;\r
- Uart.state = STATE_AWAITING_START_BIT;\r
- }\r
- } else if(Uart.shiftReg == 0x000) {\r
- // this is an EOF byte\r
- LED_A_OFF(); // Finished receiving\r
- return TRUE;\r
- } else {\r
- // this is an error\r
- Uart.posCnt = 0;\r
- Uart.state = STATE_ERROR_WAIT;\r
- }\r
- }\r
- break;\r
-\r
- case STATE_ERROR_WAIT:\r
- // We're all screwed up, so wait a little while\r
- // for whatever went wrong to finish, and then\r
- // start over.\r
- Uart.posCnt++;\r
- if(Uart.posCnt > 10) {\r
- Uart.state = STATE_UNSYNCD;\r
- }\r
- break;\r
-\r
- default:\r
- Uart.state = STATE_UNSYNCD;\r
- break;\r
- }\r
-\r
- if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error\r
-\r
- return FALSE;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Receive a command (from the reader to us, where we are the simulated tag),\r
-// and store it in the given buffer, up to the given maximum length. Keeps\r
-// spinning, waiting for a well-framed command, until either we get one\r
-// (returns TRUE) or someone presses the pushbutton on the board (FALSE).\r
-//\r
-// Assume that we're called with the SSC (to the FPGA) and ADC path set\r
-// correctly.\r
-//-----------------------------------------------------------------------------\r
-static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)\r
-{\r
- BYTE mask;\r
- int i, bit;\r
-\r
- // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen\r
- // only, since we are receiving, not transmitting).\r
- // Signal field is off with the appropriate LED\r
- LED_D_OFF();\r
- FpgaWriteConfWord(\r
- FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);\r
-\r
-\r
- // Now run a `software UART' on the stream of incoming samples.\r
- Uart.output = received;\r
- Uart.byteCntMax = maxLen;\r
- Uart.state = STATE_UNSYNCD;\r
-\r
- for(;;) {\r
- WDT_HIT();\r
-\r
- if(BUTTON_PRESS()) return FALSE;\r
-\r
- if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
- SSC_TRANSMIT_HOLDING = 0x00;\r
- }\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
- BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
-\r
- mask = 0x80;\r
- for(i = 0; i < 8; i++, mask >>= 1) {\r
- bit = (b & mask);\r
- if(Handle14443UartBit(bit)) {\r
- *len = Uart.byteCnt;\r
- return TRUE;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Main loop of simulated tag: receive commands from reader, decide what\r
-// response to send, and send it.\r
-//-----------------------------------------------------------------------------\r
-void SimulateIso14443Tag(void)\r
-{\r
- static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
- static const BYTE response1[] = {\r
- 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,\r
- 0x00, 0x21, 0x85, 0x5e, 0xd7\r
- };\r
-\r
- BYTE *resp;\r
- int respLen;\r
-\r
- BYTE *resp1 = (((BYTE *)BigBuf) + 800);\r
- int resp1Len;\r
-\r
- BYTE *receivedCmd = (BYTE *)BigBuf;\r
- int len;\r
-\r
- int i;\r
-\r
- int cmdsRecvd = 0;\r
-\r
- memset(receivedCmd, 0x44, 400);\r
-\r
- CodeIso14443bAsTag(response1, sizeof(response1));\r
- memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;\r
-\r
- // We need to listen to the high-frequency, peak-detected path.\r
- SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
- FpgaSetupSsc();\r
-\r
- cmdsRecvd = 0;\r
-\r
- for(;;) {\r
- BYTE b1, b2;\r
-\r
- if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {\r
- DbpIntegers(cmdsRecvd, 0, 0);\r
- DbpString("button press");\r
- break;\r
- }\r
-\r
- // Good, look at the command now.\r
-\r
- if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {\r
- resp = resp1; respLen = resp1Len;\r
- } else {\r
- DbpString("new cmd from reader:");\r
- DbpIntegers(len, 0x1234, cmdsRecvd);\r
- // And print whether the CRC fails, just for good measure\r
- ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);\r
- if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {\r
- // Not so good, try again.\r
- DbpString("+++CRC fail");\r
- } else {\r
- DbpString("CRC passes");\r
- }\r
- break;\r
- }\r
-\r
- memset(receivedCmd, 0x44, 32);\r
-\r
- cmdsRecvd++;\r
-\r
- if(cmdsRecvd > 0x30) {\r
- DbpString("many commands later...");\r
- break;\r
- }\r
-\r
- if(respLen <= 0) continue;\r
-\r
- // Modulate BPSK\r
- // Signal field is off with the appropriate LED\r
- LED_D_OFF();\r
- FpgaWriteConfWord(\r
- FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);\r
- SSC_TRANSMIT_HOLDING = 0xff;\r
- FpgaSetupSsc();\r
-\r
- // Transmit the response.\r
- i = 0;\r
- for(;;) {\r
- if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
- BYTE b = resp[i];\r
-\r
- SSC_TRANSMIT_HOLDING = b;\r
-\r
- i++;\r
- if(i > respLen) {\r
- break;\r
- }\r
- }\r
- if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
- volatile BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
- (void)b;\r
- }\r
- }\r
- }\r
-}\r
-\r
-//=============================================================================\r
-// An ISO 14443 Type B reader. We take layer two commands, code them\r
-// appropriately, and then send them to the tag. We then listen for the\r
-// tag's response, which we leave in the buffer to be demodulated on the\r
-// PC side.\r
-//=============================================================================\r
-\r
-static struct {\r
- enum {\r
- DEMOD_UNSYNCD,\r
- DEMOD_PHASE_REF_TRAINING,\r
- DEMOD_AWAITING_FALLING_EDGE_OF_SOF,\r
- DEMOD_GOT_FALLING_EDGE_OF_SOF,\r
- DEMOD_AWAITING_START_BIT,\r
- DEMOD_RECEIVING_DATA,\r
- DEMOD_ERROR_WAIT\r
- } state;\r
- int bitCount;\r
- int posCount;\r
- int thisBit;\r
- int metric;\r
- int metricN;\r
- WORD shiftReg;\r
- BYTE *output;\r
- int len;\r
- int sumI;\r
- int sumQ;\r
-} Demod;\r
-\r
-/*\r
- * Handles reception of a bit from the tag\r
- *\r
- * LED handling:\r
- * LED C -> ON once we have received the SOF and are expecting the rest.\r
- * LED C -> OFF once we have received EOF or are unsynced\r
- *\r
- * Returns: true if we received a EOF\r
- * false if we are still waiting for some more\r
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#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 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
+// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
+// If it's good, then we can do something appropriate with it, and send
+// a response.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Code up a string of octets at layer 2 (including CRC, we don't generate
+// 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 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;
+ 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;
+}
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+ 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.
+ *
+ * LED handling:
+ * LED A -> ON once we have received the SOF and are expecting the rest.
+ * LED A -> OFF once we have received EOF or are in error state or unsynced
+ *
+ * Returns: true if we received a EOF
+ * false if we are still waiting for some more
+ */
+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;
+}
+
+//-----------------------------------------------------------------------------
+// Receive a command (from the reader to us, where we are the simulated tag),
+// and store it in the given buffer, up to the given maximum length. Keeps
+// spinning, waiting for a well-framed command, until either we get one
+// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
+//
+// 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)
+{
+ 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;
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Main loop of simulated tag: receive commands from reader, decide what
+// response to send, and send it.
+//-----------------------------------------------------------------------------
+void SimulateIso14443Tag(void)
+{
+ 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
+ };
+
+ uint8_t *resp;
+ int respLen;
+
+ uint8_t *resp1 = (((uint8_t *)BigBuf) + 800);
+ int resp1Len;
+
+ uint8_t *receivedCmd = (uint8_t *)BigBuf;
+ int len;
+
+ int i;
+
+ int cmdsRecvd = 0;
+
+ memset(receivedCmd, 0x44, 400);
+
+ 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();
+
+ cmdsRecvd = 0;
+
+ for(;;) {
+ uint8_t b1, b2;
+
+ 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)) {
+ 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;
+ }
+ }
+ }
+}
+
+//=============================================================================
+// An ISO 14443 Type B reader. We take layer two commands, code them
+// appropriately, and then send them to the tag. We then listen for the
+// tag's response, which we leave in the buffer to be demodulated on the
+// PC side.
+//=============================================================================
+
+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;
+ uint16_t shiftReg;
+ uint8_t *output;
+ int len;
+ int sumI;
+ int sumQ;
+} Demod;
+
+/*
+ * Handles reception of a bit from the tag
+ *
+ * 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