]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - winsrc/command.cpp
Added em410xread, em410xsim, em410xread, bitstream, manmod, detectclock commands...
[proxmark3-svn] / winsrc / command.cpp
index a02803db0da870b274571bc0397536cfd7a8d301..1c434ebbd7d2ba317d6344e6b222285b47739e8b 100644 (file)
 #include "../common/iso14443_crc.c"\r
 \r
 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
 #include "../common/iso14443_crc.c"\r
 \r
 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
+#define BIT(x) GraphBuffer[x * clock]\r
+#define BITS (GraphTraceLen / clock)\r
 \r
 \r
+int go = 0;\r
 static int CmdHisamplest(char *str, int nrlow);\r
 \r
 static void GetFromBigBuf(BYTE *dest, int bytes)\r
 static int CmdHisamplest(char *str, int nrlow);\r
 \r
 static void GetFromBigBuf(BYTE *dest, int bytes)\r
@@ -34,7 +37,7 @@ static void GetFromBigBuf(BYTE *dest, int bytes)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return;\r
                }\r
 \r
                        return;\r
                }\r
 \r
@@ -83,19 +86,19 @@ static void CmdHi14read(char *str)
        c.ext1 = atoi(str);\r
        SendCommand(&c, FALSE);\r
 }\r
        c.ext1 = atoi(str);\r
        SendCommand(&c, FALSE);\r
 }\r
-
-
-/* New command to read the contents of a SRI512 tag
- * SRI512 tags are ISO14443-B modulated memory tags,
- * this command just dumps the contents of the memory/
- */
-static void CmdSri512read(char *str)
-{
+\r
+\r
+/* New command to read the contents of a SRI512 tag\r
+ * SRI512 tags are ISO14443-B modulated memory tags,\r
+ * this command just dumps the contents of the memory/\r
+ */\r
+static void CmdSri512read(char *str)\r
+{\r
        UsbCommand c;\r
        c.cmd = CMD_READ_SRI512_TAG;\r
        c.ext1 = atoi(str);\r
        UsbCommand c;\r
        c.cmd = CMD_READ_SRI512_TAG;\r
        c.ext1 = atoi(str);\r
-       SendCommand(&c, FALSE);
-}
+       SendCommand(&c, FALSE);\r
+}\r
 \r
 // ## New command\r
 static void CmdHi14areader(char *str)\r
 \r
 // ## New command\r
 static void CmdHi14areader(char *str)\r
@@ -161,8 +164,6 @@ static void CmdHi14sim(char *str)
        c.cmd = CMD_SIMULATE_TAG_ISO_14443;\r
        SendCommand(&c, FALSE);\r
 }\r
        c.cmd = CMD_SIMULATE_TAG_ISO_14443;\r
        SendCommand(&c, FALSE);\r
 }\r
-
-
 \r
 static void CmdHi14asim(char *str)     // ## simulate iso14443a tag\r
 {                                      // ## greg - added ability to specify tag UID\r
 \r
 static void CmdHi14asim(char *str)     // ## simulate iso14443a tag\r
 {                                      // ## greg - added ability to specify tag UID\r
@@ -205,11 +206,284 @@ static void CmdFPGAOff(char *str)                // ## FPGA Control
        SendCommand(&c, FALSE);\r
 }\r
 \r
        SendCommand(&c, FALSE);\r
 }\r
 \r
-static void CmdLosim(char *str)\r
+/* clear out our graph window */\r
+int CmdClearGraph(int redraw)\r
+{\r
+       int gtl = GraphTraceLen;\r
+       GraphTraceLen = 0;\r
+       \r
+       if (redraw)\r
+               RepaintGraphWindow();\r
+       \r
+       return gtl;\r
+}\r
+\r
+/* write a bit to the graph */\r
+static void CmdAppendGraph(int redraw, int clock, int bit)\r
 {\r
        int i;\r
 \r
 {\r
        int i;\r
 \r
-       for(i = 0; i < GraphTraceLen; i += 48) {\r
+       for (i = 0; i < (int)(clock/2); i++)\r
+               GraphBuffer[GraphTraceLen++] = bit ^ 1;\r
+       \r
+       for (i = (int)(clock/2); i < clock; i++)        \r
+               GraphBuffer[GraphTraceLen++] = bit;\r
+\r
+       if (redraw)\r
+               RepaintGraphWindow();\r
+}\r
+\r
+/* Function is equivalent of loread + losamples + em410xread\r
+ * looped until an EM410x tag is detected */\r
+static void CmdEM410xwatch(char *str)\r
+{\r
+       char *zero = "";\r
+       char *twok = "2000";\r
+       go = 1;\r
+       \r
+       do\r
+       {\r
+               CmdLoread(zero);\r
+               CmdLosamples(twok);\r
+               CmdEM410xread(zero);\r
+       } while (go);\r
+}\r
+\r
+/* Read the ID of an EM410x tag.\r
+ * Format:\r
+ *   1111 1111 1           <-- standard non-repeatable header\r
+ *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID\r
+ *   ....\r
+ *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column\r
+ *   0                     <-- stop bit, end of tag\r
+ */\r
+static void CmdEM410xread(char *str)\r
+{\r
+       int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low;\r
+       int parity[4];\r
+       char id[11];\r
+       int BitStream[MAX_GRAPH_TRACE_LEN];\r
+       high = low = 0;\r
+       \r
+       /* Detect high and lows and clock */\r
+       for (i = 0; i < GraphTraceLen; i++)\r
+       {\r
+               if (GraphBuffer[i] > high)\r
+                       high = GraphBuffer[i];\r
+               else if (GraphBuffer[i] < low)\r
+                       low = GraphBuffer[i];\r
+       }       \r
+       \r
+       /* get clock */\r
+       clock = GetClock(str, high);\r
+       \r
+       /* parity for our 4 columns */\r
+       parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
+       header = rows = 0;\r
+       \r
+       /* manchester demodulate */\r
+       bit = bit2idx = 0;\r
+       for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
+       {\r
+               hithigh = 0;\r
+               hitlow = 0;\r
+               first = 1;\r
+               \r
+               /* Find out if we hit both high and low peaks */\r
+               for (j = 0; j < clock; j++)\r
+               {\r
+                       if (GraphBuffer[(i * clock) + j] == high)\r
+                               hithigh = 1;\r
+                       else if (GraphBuffer[(i * clock) + j] == low)\r
+                               hitlow = 1;\r
+                       \r
+                       /* it doesn't count if it's the first part of our read\r
+                        because it's really just trailing from the last sequence */\r
+                       if (first && (hithigh || hitlow))\r
+                               hithigh = hitlow = 0;\r
+                       else\r
+                               first = 0;\r
+                       \r
+                       if (hithigh && hitlow)\r
+                               break;\r
+               }\r
+               \r
+               /* If we didn't hit both high and low peaks, we had a bit transition */\r
+               if (!hithigh || !hitlow)\r
+                       bit ^= 1;\r
+               \r
+               BitStream[bit2idx++] = bit;\r
+       }\r
+       \r
+       /* We go till 5 before the graph ends because we'll get that far below */\r
+       for (i = 1; i < bit2idx - 5; i++)\r
+       {\r
+               /* Step 2: We have our header but need our tag ID */\r
+               if (header == 9 && rows < 10)\r
+               {\r
+                       /* Confirm parity is correct */\r
+                       if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])\r
+                       {\r
+                               /* Read another byte! */\r
+                               sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));\r
+                               rows++;\r
+                               \r
+                               /* Keep parity info */\r
+                               parity[0] ^= BitStream[i];\r
+                               parity[1] ^= BitStream[i+1];\r
+                               parity[2] ^= BitStream[i+2];\r
+                               parity[3] ^= BitStream[i+3];\r
+                               \r
+                               /* Move 4 bits ahead */\r
+                               i += 4;\r
+                       }\r
+                       \r
+                       /* Damn, something wrong! reset */\r
+                       else\r
+                       {\r
+                               PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);\r
+                               \r
+                               /* Start back rows * 5 + 9 header bits, -1 to not start at same place */\r
+                               i -= 9 + (5 * rows) - 5;\r
+\r
+                               rows = header = 0;\r
+                       }\r
+               }\r
+               \r
+               /* Step 3: Got our 40 bits! confirm column parity */\r
+               else if (rows == 10)\r
+               {\r
+                       /* We need to make sure our 4 bits of parity are correct and we have a stop bit */\r
+                       if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] &&\r
+                               BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] &&\r
+                               BitStream[i+4] == 0)\r
+                       {\r
+                               /* Sweet! */\r
+                               PrintToScrollback("EM410x Tag ID: %s", id);\r
+                               \r
+                               /* Stop any loops */\r
+                               go = 0;\r
+                               break;\r
+                       }\r
+                       \r
+                       /* Crap! Incorrect parity or no stop bit, start all over */\r
+                       else\r
+                       {\r
+                               rows = header = 0;\r
+                               \r
+                               /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */\r
+                               i -= 59;\r
+                       }\r
+               }\r
+                               \r
+               /* Step 1: get our header */\r
+               else if (header < 9)\r
+               {\r
+                       /* Need 9 consecutive 1's */\r
+                       if (BitStream[i] == 1)\r
+                               header++;\r
+                       \r
+                       /* We don't have a header, not enough consecutive 1 bits */\r
+                       else\r
+                               header = 0;\r
+               }\r
+       }\r
+}\r
+\r
+/* emulate an EM410X tag\r
+ * Format:\r
+ *   1111 1111 1           <-- standard non-repeatable header\r
+ *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID\r
+ *   ....\r
+ *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column\r
+ *   0                     <-- stop bit, end of tag\r
+ */\r
+static void CmdEM410xsim(char *str)\r
+{\r
+       int i, n, j, h, binary[4], parity[4];\r
+       char *s = "0";\r
+       \r
+       /* clock is 64 in EM410x tags */\r
+       int clock = 64;\r
+       \r
+       /* clear our graph */\r
+       CmdClearGraph(0);\r
+       \r
+       /* write it out a few times */\r
+       for (h = 0; h < 4; h++)\r
+       {\r
+               /* write 9 start bits */\r
+               for (i = 0; i < 9; i++)\r
+                       CmdAppendGraph(0, clock, 1);\r
+               \r
+               /* for each hex char */\r
+               parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
+               for (i = 0; i < 10; i++)\r
+               {\r
+                       /* read each hex char */\r
+                       sscanf(&str[i], "%1x", &n);\r
+                       for (j = 3; j >= 0; j--, n/= 2)\r
+                               binary[j] = n % 2;\r
+                       \r
+                       /* append each bit */\r
+                       CmdAppendGraph(0, clock, binary[0]);\r
+                       CmdAppendGraph(0, clock, binary[1]);\r
+                       CmdAppendGraph(0, clock, binary[2]);\r
+                       CmdAppendGraph(0, clock, binary[3]);\r
+                       \r
+                       /* append parity bit */\r
+                       CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);\r
+                       \r
+                       /* keep track of column parity */\r
+                       parity[0] ^= binary[0];\r
+                       parity[1] ^= binary[1];\r
+                       parity[2] ^= binary[2];\r
+                       parity[3] ^= binary[3];\r
+               }\r
+               \r
+               /* parity columns */\r
+               CmdAppendGraph(0, clock, parity[0]);\r
+               CmdAppendGraph(0, clock, parity[1]);\r
+               CmdAppendGraph(0, clock, parity[2]);\r
+               CmdAppendGraph(0, clock, parity[3]);\r
+               \r
+               /* stop bit */\r
+               CmdAppendGraph(0, clock, 0);\r
+       }\r
+       \r
+       /* modulate that biatch */\r
+       Cmdmanchestermod(s);\r
+       \r
+       /* booyah! */\r
+       RepaintGraphWindow();\r
+\r
+       CmdLosim(s);\r
+}\r
+\r
+static void ChkBitstream(char *str)\r
+{\r
+       int i;\r
+       \r
+       /* convert to bitstream if necessary */\r
+       for (i = 0; i < (int)(GraphTraceLen / 2); i++)\r
+       {\r
+               if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)\r
+               {\r
+                       Cmdbitstream(str);\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+static void CmdLosim(char *str)\r
+{\r
+       int i;\r
+       char *zero = "0";\r
+       \r
+       /* convert to bitstream if necessary */\r
+       ChkBitstream(str);\r
+       \r
+       for (i = 0; i < GraphTraceLen; i += 48) {\r
                UsbCommand c;\r
                int j;\r
                for(j = 0; j < 48; j++) {\r
                UsbCommand c;\r
                int j;\r
                for(j = 0; j < 48; j++) {\r
@@ -259,7 +533,8 @@ static void CmdLosamples(char *str)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       if (!go)\r
+                               PrintToScrollback("bad resp");\r
                        return;\r
                }\r
                int j;\r
                        return;\r
                }\r
                int j;\r
@@ -285,7 +560,7 @@ static void CmdBitsamples(char *str)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return;\r
                }\r
                int j, k;\r
                        return;\r
                }\r
                int j, k;\r
@@ -316,7 +591,7 @@ static void CmdHisamples(char *str)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return;\r
                }\r
                int j;\r
                        return;\r
                }\r
                int j;\r
@@ -349,7 +624,7 @@ static int CmdHisamplest(char *str, int nrlow)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return 0;\r
                }\r
                int j;\r
                        return 0;\r
                }\r
                int j;\r
@@ -418,7 +693,7 @@ static void CmdHexsamples(char *str)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return;\r
                }\r
                int j;\r
                        return;\r
                }\r
                int j;\r
@@ -457,7 +732,7 @@ static void CmdHisampless(char *str)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return;\r
                }\r
                int j;\r
                        return;\r
                }\r
                int j;\r
@@ -947,7 +1222,7 @@ static void CmdTibits(char *str)
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {\r
                SendCommand(&c, FALSE);\r
                ReceiveCommand(&c);\r
                if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {\r
-                       PrintToScrollback("bad resp\n");\r
+                       PrintToScrollback("bad resp");\r
                        return;\r
                }\r
                int j;\r
                        return;\r
                }\r
                int j;\r
@@ -1545,112 +1820,259 @@ static void CmdFlexdemod(char *str)
 \r
        RepaintGraphWindow();\r
 }\r
 \r
        RepaintGraphWindow();\r
 }\r
-
-/*
- * Generic command to demodulate ASK. bit length in argument.
- * Giving the bit length helps discriminate ripple effects
- * upon zero crossing for noisy traces.
- *
- * Second is convention: positive or negative (High mod means zero
- * or high mod means one)
- *
- * Updates the Graph trace with 0/1 values
- *
- * Arguments:
- * sl : bit length in terms of number of samples per bit
- *      (use yellow/purple markers to compute).
- * c : 0 or 1
- */
-
-static void Cmdaskdemod(char *str) {
-       int i;
-       int sign = 1;
-       int n = 0;
+\r
+/*\r
+ * Generic command to demodulate ASK. bit length in argument.\r
+ * Giving the bit length helps discriminate ripple effects\r
+ * upon zero crossing for noisy traces.\r
+ *\r
+ * Second is convention: positive or negative (High mod means zero\r
+ * or high mod means one)\r
+ *\r
+ * Updates the Graph trace with 0/1 values\r
+ *\r
+ * Arguments:\r
+ * sl : bit length in terms of number of samples per bit\r
+ *      (use yellow/purple markers to compute).\r
+ * c : 0 or 1\r
+ */\r
+\r
+static void Cmdaskdemod(char *str) {\r
+       int i;\r
+       int sign = 1;\r
+       int n = 0;\r
        int c = 0;\r
        int c = 0;\r
-       int t1 = 0;
-
-       // TODO: complain if we do not give 2 arguments here !
-       sscanf(str, "%i %i", &n, &c);
-       if (c == 0) {
-               c = 1 ;
-       } else {
-               c = -1;
-       }
-
-       if (GraphBuffer[0]*c > 0) {
-               GraphBuffer[0] = 1;
-       } else {
-               GraphBuffer[0] = 0;
-       }
-       for(i=1;i<GraphTraceLen;i++) {
-               /* Analyse signal within the symbol length */
-               /* Decide if we crossed a zero */
-               if (GraphBuffer[i]*sign < 0) {
-                        /* Crossed a zero, check if this is a ripple or not */
-                       if ( (i-t1) > n/4 ) {
-                               sign = -sign;
-                               t1=i;
-                               if (GraphBuffer[i]*c > 0){
-                                       GraphBuffer[i]=1;
-                               } else {
-                                       GraphBuffer[i]=0;
-                               }
-                       } else {
-                       /* This is a ripple, set the current sample value
-                          to the same as previous */
-                               GraphBuffer[i] = GraphBuffer[i-1];
-                       }
-               } else {
-                       GraphBuffer[i] = GraphBuffer[i-1];
-               }
-       }
-       RepaintGraphWindow();
-}
-
-
-/*
- * Manchester demodulate a bitstream. The bitstream needs to be already in
- * the GraphBuffer as 0 and 1 values
- *
- * Give the clock rate as argument in order to help the sync - the algorithm
- * resyncs at each pulse anyway.
- *
- * Not optimized by any means, this is the 1st time I'm writing this type of
- * routine, feel free to improve...
- *
- * 1st argument: clock rate (as number of samples per clock rate)
- *               Typical values can be 64, 32, 128...
- */
-static void Cmdmanchesterdemod(char *str) {
+       int t1 = 0;\r
+\r
+       // TODO: complain if we do not give 2 arguments here !\r
+       sscanf(str, "%i %i", &n, &c);\r
+       if (c == 0) {\r
+               c = 1 ;\r
+       } else {\r
+               c = -1;\r
+       }\r
+\r
+       if (GraphBuffer[0]*c > 0) {\r
+               GraphBuffer[0] = 1;\r
+       } else {\r
+               GraphBuffer[0] = 0;\r
+       }\r
+       for(i=1;i<GraphTraceLen;i++) {\r
+               /* Analyse signal within the symbol length */\r
+               /* Decide if we crossed a zero */\r
+               if (GraphBuffer[i]*sign < 0) {\r
+                        /* Crossed a zero, check if this is a ripple or not */\r
+                       if ( (i-t1) > n/4 ) {\r
+                               sign = -sign;\r
+                               t1=i;\r
+                               if (GraphBuffer[i]*c > 0){\r
+                                       GraphBuffer[i]=1;\r
+                               } else {\r
+                                       GraphBuffer[i]=0;\r
+                               }\r
+                       } else {\r
+                       /* This is a ripple, set the current sample value\r
+                          to the same as previous */\r
+                               GraphBuffer[i] = GraphBuffer[i-1];\r
+                       }\r
+               } else {\r
+                       GraphBuffer[i] = GraphBuffer[i-1];\r
+               }\r
+       }\r
+       RepaintGraphWindow();\r
+}\r
+\r
+/* Print our clock rate */\r
+static void Cmddetectclockrate(char *str)\r
+{\r
+       int clock = detectclock(0);\r
+       PrintToScrollback("Auto-detected clock rate: %d", clock);\r
+}\r
+\r
+/*\r
+ * Detect clock rate\r
+ */\r
+int detectclock(int peak)\r
+{\r
+       int i;\r
+       int clock = 0xFFFF;\r
+       int lastpeak = 0;\r
+\r
+       /* Detect peak if we don't have one */\r
+       if (!peak)\r
+               for (i = 0; i < GraphTraceLen; i++)\r
+                       if (GraphBuffer[i] > peak)\r
+                               peak = GraphBuffer[i];\r
+\r
+       for (i = 1; i < GraphTraceLen; i++)\r
+       {\r
+               /* If this is the beginning of a peak */\r
+               if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)\r
+               {\r
+                       /* Find lowest difference between peaks */\r
+                       if (lastpeak && i - lastpeak < clock)\r
+                       {\r
+                               clock = i - lastpeak;\r
+                       }\r
+                       lastpeak = i;\r
+               }\r
+       }\r
+       \r
+       return clock;\r
+}\r
+\r
+/* Get or auto-detect clock rate */\r
+int GetClock(char *str, int peak)\r
+{\r
+       int clock;\r
+       \r
+       sscanf(str, "%i", &clock);\r
+       if (!strcmp(str, ""))\r
+               clock = 0;\r
+\r
+       /* Auto-detect clock */\r
+       if (!clock)\r
+       {\r
+               clock = detectclock(peak);\r
+               \r
+               /* Only print this message if we're not looping something */\r
+               if (!go)\r
+                       PrintToScrollback("Auto-detected clock rate: %d", clock);\r
+       }\r
+       \r
+       return clock;\r
+}\r
+\r
+/*\r
+ * Convert to a bitstream\r
+ */\r
+static void Cmdbitstream(char *str) {\r
        int i, j;\r
        int bit;\r
        int i, j;\r
        int bit;\r
-       int clock;
-       int lastval;
+       int gtl;\r
+       int clock;\r
        int low = 0;\r
        int high = 0;\r
        int hithigh, hitlow, first;\r
        int low = 0;\r
        int high = 0;\r
        int hithigh, hitlow, first;\r
-       int lc = 0;
-       int bitidx = 0;
-       int bit2idx = 0;
-       int warnings = 0;\r
-
-       sscanf(str, "%i", &clock);
-       if (!clock)\r
+\r
+       /* Detect high and lows and clock */\r
+       for (i = 0; i < GraphTraceLen; i++)\r
        {\r
        {\r
-               PrintToScrollback("You must provide a clock rate.");\r
-               return;\r
+               if (GraphBuffer[i] > high)\r
+                       high = GraphBuffer[i];\r
+               else if (GraphBuffer[i] < low)\r
+                       low = GraphBuffer[i];\r
        }\r
        }\r
-
-       int tolerance = clock/4;
-       /* Holds the decoded bitstream: each clock period contains 2 bits       */
-       /* later simplified to 1 bit after manchester decoding.                 */
-       /* Add 10 bits to allow for noisy / uncertain traces without aborting   */
-       /* int BitStream[GraphTraceLen*2/clock+10]; */
-
-       /* But it does not work if compiling on WIndows: therefore we just allocate a */
-       /* large array */
-       int BitStream[MAX_GRAPH_TRACE_LEN];
-
+\r
+       /* Get our clock */\r
+       clock = GetClock(str, high);\r
+       \r
+       gtl = CmdClearGraph(0);\r
+       \r
+       bit = 0;\r
+       for (i = 0; i < (int)(gtl / clock); i++)\r
+       {\r
+               hithigh = 0;\r
+               hitlow = 0;\r
+               first = 1;\r
+               \r
+               /* Find out if we hit both high and low peaks */\r
+               for (j = 0; j < clock; j++)\r
+               {\r
+                       if (GraphBuffer[(i * clock) + j] == high)\r
+                               hithigh = 1;\r
+                       else if (GraphBuffer[(i * clock) + j] == low)\r
+                               hitlow = 1;\r
+                       \r
+                       /* it doesn't count if it's the first part of our read\r
+                        because it's really just trailing from the last sequence */\r
+                       if (first && (hithigh || hitlow))\r
+                               hithigh = hitlow = 0;\r
+                       else\r
+                               first = 0;\r
+                       \r
+                       if (hithigh && hitlow)\r
+                               break;\r
+               }\r
+               \r
+               /* If we didn't hit both high and low peaks, we had a bit transition */\r
+               if (!hithigh || !hitlow)\r
+                       bit ^= 1;\r
+\r
+               CmdAppendGraph(0, clock, bit);\r
+//             for (j = 0; j < (int)(clock/2); j++)\r
+//                     GraphBuffer[(i * clock) + j] = bit ^ 1;\r
+//             for (j = (int)(clock/2); j < clock; j++)\r
+//                     GraphBuffer[(i * clock) + j] = bit;\r
+       }\r
+\r
+       RepaintGraphWindow();\r
+}\r
+\r
+/* Modulate our data into manchester */\r
+static void Cmdmanchestermod(char *str)\r
+{\r
+       int i, j;\r
+       int clock;\r
+       int bit, lastbit, wave;\r
+       \r
+       /* Get our clock */\r
+       clock = GetClock(str, 0);\r
+\r
+       wave = 0;\r
+       lastbit = 1;\r
+       for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
+       {\r
+               bit = GraphBuffer[i * clock] ^ 1;\r
+               \r
+               for (j = 0; j < (int)(clock/2); j++)\r
+                       GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;\r
+               for (j = (int)(clock/2); j < clock; j++)\r
+                       GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;\r
+               \r
+               /* Keep track of how we start our wave and if we changed or not this time */\r
+               wave ^= bit ^ lastbit;\r
+               lastbit = bit;\r
+       }\r
+       \r
+       RepaintGraphWindow();\r
+}\r
+\r
+/*\r
+ * Manchester demodulate a bitstream. The bitstream needs to be already in\r
+ * the GraphBuffer as 0 and 1 values\r
+ *\r
+ * Give the clock rate as argument in order to help the sync - the algorithm\r
+ * resyncs at each pulse anyway.\r
+ *\r
+ * Not optimized by any means, this is the 1st time I'm writing this type of\r
+ * routine, feel free to improve...\r
+ *\r
+ * 1st argument: clock rate (as number of samples per clock rate)\r
+ *               Typical values can be 64, 32, 128...\r
+ */\r
+static void Cmdmanchesterdemod(char *str) {\r
+       int i, j;\r
+       int bit;\r
+       int clock;\r
+       int lastval;\r
+       int low = 0;\r
+       int high = 0;\r
+       int hithigh, hitlow, first;\r
+       int lc = 0;\r
+       int bitidx = 0;\r
+       int bit2idx = 0;\r
+       int warnings = 0;\r
+\r
+       /* Holds the decoded bitstream: each clock period contains 2 bits       */\r
+       /* later simplified to 1 bit after manchester decoding.                 */\r
+       /* Add 10 bits to allow for noisy / uncertain traces without aborting   */\r
+       /* int BitStream[GraphTraceLen*2/clock+10]; */\r
+\r
+       /* But it does not work if compiling on WIndows: therefore we just allocate a */\r
+       /* large array */\r
+       int BitStream[MAX_GRAPH_TRACE_LEN];\r
+\r
        /* Detect high and lows */\r
        for (i = 0; i < GraphTraceLen; i++)\r
        {\r
        /* Detect high and lows */\r
        for (i = 0; i < GraphTraceLen; i++)\r
        {\r
@@ -1660,24 +2082,27 @@ static void Cmdmanchesterdemod(char *str) {
                        low = GraphBuffer[i];\r
        }\r
 \r
                        low = GraphBuffer[i];\r
        }\r
 \r
-       /* Detect first transition */
-       /* Lo-Hi (arbitrary)       */
+       /* Get our clock */\r
+       clock = GetClock(str, high);\r
+       \r
+       int tolerance = clock/4;\r
+       \r
+       /* Detect first transition */\r
+       /* Lo-Hi (arbitrary)       */\r
        for (i = 0; i < GraphTraceLen; i++)\r
        {\r
                if (GraphBuffer[i] == low)\r
                {\r
        for (i = 0; i < GraphTraceLen; i++)\r
        {\r
                if (GraphBuffer[i] == low)\r
                {\r
-//                     BitStream[0]=0; // Previous state = 0;\r
-               lastval = i;
-               break;
-               }
-       }
-//PrintToScrollback("cool %d %d %d %d", low, high, lastval, GraphBuffer[i]);\r
+                       lastval = i;\r
+                       break;\r
+               }\r
+       }\r
 \r
        /* If we're not working with 1/0s, demod based off clock */\r
        if (high != 1)\r
        {\r
                bit = 0;\r
 \r
        /* If we're not working with 1/0s, demod based off clock */\r
        if (high != 1)\r
        {\r
                bit = 0;\r
-               for (i = 0; i < (GraphTraceLen / clock); i++)\r
+               for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
                {\r
                        hithigh = 0;\r
                        hitlow = 0;\r
                {\r
                        hithigh = 0;\r
                        hitlow = 0;\r
@@ -1713,98 +2138,98 @@ static void Cmdmanchesterdemod(char *str) {
        /* standard 1/0 bitstream */\r
        else\r
        {\r
        /* standard 1/0 bitstream */\r
        else\r
        {\r
-
-       /* Then detect duration between 2 successive transitions */
+\r
+       /* Then detect duration between 2 successive transitions */\r
                for (bitidx = 1; i < GraphTraceLen; i++)\r
                {\r
                        if (GraphBuffer[i-1] != GraphBuffer[i])\r
                        {\r
                for (bitidx = 1; i < GraphTraceLen; i++)\r
                {\r
                        if (GraphBuffer[i-1] != GraphBuffer[i])\r
                        {\r
-                       lc = i-lastval;
-                       lastval = i;
-\r
-                       // Error check: if bitidx becomes too large, we do not
-                       // have a Manchester encoded bitstream or the clock is really
-                       // wrong!
-                       if (bitidx > (GraphTraceLen*2/clock+8) ) {
-                               PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
-                               return;
-                       }
-                       // Then switch depending on lc length:
-                       // Tolerance is 1/4 of clock rate (arbitrary)
-                       if (abs(lc-clock/2) < tolerance) {
-                               // Short pulse : either "1" or "0"
-                               BitStream[bitidx++]=GraphBuffer[i-1];
-                       } else if (abs(lc-clock) < tolerance) {
-                               // Long pulse: either "11" or "00"
-                               BitStream[bitidx++]=GraphBuffer[i-1];
-                               BitStream[bitidx++]=GraphBuffer[i-1];
-                       } else {
-                               // Error
+                       lc = i-lastval;\r
+                       lastval = i;\r
+\r
+                       // Error check: if bitidx becomes too large, we do not\r
+                       // have a Manchester encoded bitstream or the clock is really\r
+                       // wrong!\r
+                       if (bitidx > (GraphTraceLen*2/clock+8) ) {\r
+                               PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");\r
+                               return;\r
+                       }\r
+                       // Then switch depending on lc length:\r
+                       // Tolerance is 1/4 of clock rate (arbitrary)\r
+                       if (abs(lc-clock/2) < tolerance) {\r
+                               // Short pulse : either "1" or "0"\r
+                               BitStream[bitidx++]=GraphBuffer[i-1];\r
+                       } else if (abs(lc-clock) < tolerance) {\r
+                               // Long pulse: either "11" or "00"\r
+                               BitStream[bitidx++]=GraphBuffer[i-1];\r
+                               BitStream[bitidx++]=GraphBuffer[i-1];\r
+                       } else {\r
+                               // Error\r
                                        warnings++;\r
                                        warnings++;\r
-                               PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
-                               PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
+                               PrintToScrollback("Warning: Manchester decode error for pulse width detection.");\r
+                               PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");\r
 \r
                                        if (warnings > 100)\r
                                        {\r
                                                PrintToScrollback("Error: too many detection errors, aborting.");\r
                                                return;\r
                                        }\r
 \r
                                        if (warnings > 100)\r
                                        {\r
                                                PrintToScrollback("Error: too many detection errors, aborting.");\r
                                                return;\r
                                        }\r
-                       }
-               }
-       }
-
-       // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
-       // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
-       // to stop output at the final bitidx2 value, not bitidx
-       for (i = 0; i < bitidx; i += 2) {
-               if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
-                       BitStream[bit2idx++] = 1;
-               } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
-                       BitStream[bit2idx++] = 0;
-               } else {
-                       // We cannot end up in this state, this means we are unsynchronized,
-                       // move up 1 bit:
-                       i++;
+                       }\r
+               }\r
+       }\r
+\r
+       // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream\r
+       // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful\r
+       // to stop output at the final bitidx2 value, not bitidx\r
+       for (i = 0; i < bitidx; i += 2) {\r
+               if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {\r
+                       BitStream[bit2idx++] = 1;\r
+               } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {\r
+                       BitStream[bit2idx++] = 0;\r
+               } else {\r
+                       // We cannot end up in this state, this means we are unsynchronized,\r
+                       // move up 1 bit:\r
+                       i++;\r
                                warnings++;\r
                                warnings++;\r
-                       PrintToScrollback("Unsynchronized, resync...");
-                       PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
+                       PrintToScrollback("Unsynchronized, resync...");\r
+                       PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");\r
 \r
                                if (warnings > 100)\r
                                {\r
                                        PrintToScrollback("Error: too many decode errors, aborting.");\r
                                        return;\r
                                }\r
 \r
                                if (warnings > 100)\r
                                {\r
                                        PrintToScrollback("Error: too many decode errors, aborting.");\r
                                        return;\r
                                }\r
-               }
-       }
+               }\r
+       }\r
        }\r
 \r
        PrintToScrollback("Manchester decoded bitstream");\r
        }\r
 \r
        PrintToScrollback("Manchester decoded bitstream");\r
-       // Now output the bitstream to the scrollback by line of 16 bits
-       for (i = 0; i < (bit2idx-16); i+=16) {
-               PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
-                       BitStream[i],
-                       BitStream[i+1],
-                       BitStream[i+2],
-                       BitStream[i+3],
-                       BitStream[i+4],
-                       BitStream[i+5],
-                       BitStream[i+6],
-                       BitStream[i+7],
-                       BitStream[i+8],
-                       BitStream[i+9],
-                       BitStream[i+10],
-                       BitStream[i+11],
-                       BitStream[i+12],
-                       BitStream[i+13],
-                       BitStream[i+14],
-                       BitStream[i+15]);
-       }
-}
-
-
-
-/*
- * Usage ???
+       // Now output the bitstream to the scrollback by line of 16 bits\r
+       for (i = 0; i < (bit2idx-16); i+=16) {\r
+               PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",\r
+                       BitStream[i],\r
+                       BitStream[i+1],\r
+                       BitStream[i+2],\r
+                       BitStream[i+3],\r
+                       BitStream[i+4],\r
+                       BitStream[i+5],\r
+                       BitStream[i+6],\r
+                       BitStream[i+7],\r
+                       BitStream[i+8],\r
+                       BitStream[i+9],\r
+                       BitStream[i+10],\r
+                       BitStream[i+11],\r
+                       BitStream[i+12],\r
+                       BitStream[i+13],\r
+                       BitStream[i+14],\r
+                       BitStream[i+15]);\r
+       }\r
+}\r
+\r
+\r
+\r
+/*\r
+ * Usage ???\r
  */\r
 static void CmdHiddemod(char *str)\r
 {\r
  */\r
 static void CmdHiddemod(char *str)\r
 {\r
@@ -1923,11 +2348,11 @@ static void CmdLcd(char *str)
 static void CmdTest(char *str)\r
 {\r
 }\r
 static void CmdTest(char *str)\r
 {\r
 }\r
-
-/*
- * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
- * 600kHz.
- */
+\r
+/*\r
+ * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below\r
+ * 600kHz.\r
+ */\r
 static void CmdSetDivisor(char *str)\r
 {\r
        UsbCommand c;\r
 static void CmdSetDivisor(char *str)\r
 {\r
        UsbCommand c;\r
@@ -1947,15 +2372,15 @@ static void CmdSweepLF(char *str)
        c.cmd = CMD_SWEEP_LF;\r
        SendCommand(&c, FALSE);\r
 }\r
        c.cmd = CMD_SWEEP_LF;\r
        SendCommand(&c, FALSE);\r
 }\r
-
-
+\r
+\r
 typedef void HandlerFunction(char *cmdline);\r
 \r
 static struct {\r
        char            *name;\r
        HandlerFunction *handler;\r
        int             offline;  // 1 if the command can be used when in offline mode\r
 typedef void HandlerFunction(char *cmdline);\r
 \r
 static struct {\r
        char            *name;\r
        HandlerFunction *handler;\r
        int             offline;  // 1 if the command can be used when in offline mode\r
-       char            *docString;
+       char            *docString;\r
 } CommandTable[] = {\r
        "tune",                         CmdTune,0,              "measure antenna tuning",\r
        "tiread",                       CmdTiread,0,            "read a TI-type 134 kHz tag",\r
 } CommandTable[] = {\r
        "tune",                         CmdTune,0,              "measure antenna tuning",\r
        "tiread",                       CmdTiread,0,            "read a TI-type 134 kHz tag",\r
@@ -1965,6 +2390,9 @@ static struct {
        "plot",                         CmdPlot,1,              "show graph window",\r
        "hide",                         CmdHide,1,              "hide graph window",\r
        "losim",                        CmdLosim,0,             "simulate LF tag",\r
        "plot",                         CmdPlot,1,              "show graph window",\r
        "hide",                         CmdHide,1,              "hide graph window",\r
        "losim",                        CmdLosim,0,             "simulate LF tag",\r
+       "em410xsim",            CmdEM410xsim,1,         "simulate EM410x tag",\r
+       "em410xread",           CmdEM410xread,1,        "extract ID from EM410x tag",\r
+       "em410xwatch",          CmdEM410xwatch,0,       "watches for EM410x tags",\r
        "loread",                       CmdLoread,0,            "read (125/134 kHz) LF ID-only tag",\r
        "losamples",            CmdLosamples,0,         "get raw samples for LF tag",\r
        "hisamples",            CmdHisamples,0,         "get raw samples for HF tag",\r
        "loread",                       CmdLoread,0,            "read (125/134 kHz) LF ID-only tag",\r
        "losamples",            CmdLosamples,0,         "get raw samples for LF tag",\r
        "hisamples",            CmdHisamples,0,         "get raw samples for HF tag",\r
@@ -2002,8 +2430,11 @@ static struct {
        "hidfskdemod",          CmdHIDdemodFSK,0,       "HID FSK demodulator",\r
     "indalademod",             CmdIndalademod,0,         "demod samples for Indala",\r
        "askdemod",                     Cmdaskdemod,1,          "Attempt to demodulate simple ASK tags",\r
        "hidfskdemod",          CmdHIDdemodFSK,0,       "HID FSK demodulator",\r
     "indalademod",             CmdIndalademod,0,         "demod samples for Indala",\r
        "askdemod",                     Cmdaskdemod,1,          "Attempt to demodulate simple ASK tags",\r
+       "bitstream",            Cmdbitstream,1,         "Convert waveform into a bitstream",\r
        "hidsimtag",            CmdHIDsimTAG,0,         "HID tag simulator",\r
        "mandemod",                     Cmdmanchesterdemod,1,   "Try a Manchester demodulation on a binary stream",\r
        "hidsimtag",            CmdHIDsimTAG,0,         "HID tag simulator",\r
        "mandemod",                     Cmdmanchesterdemod,1,   "Try a Manchester demodulation on a binary stream",\r
+       "manmod",                       Cmdmanchestermod,1,     "Manchester modulate a binary stream",\r
+       "detectclock",          Cmddetectclockrate,1, "Detect clock rate",\r
        "fpgaoff",                      CmdFPGAOff,0,           "set FPGA off",                                                 // ## FPGA Control\r
        "lcdreset",                     CmdLcdReset,0,          "Hardware reset LCD",\r
        "lcd",                          CmdLcd,0,                       "Send command/data to LCD",\r
        "fpgaoff",                      CmdFPGAOff,0,           "set FPGA off",                                                 // ## FPGA Control\r
        "lcdreset",                     CmdLcdReset,0,          "Hardware reset LCD",\r
        "lcd",                          CmdLcd,0,                       "Send command/data to LCD",\r
@@ -2076,7 +2507,7 @@ void UsbCommandReceived(UsbCommand *c)
                        memcpy(s, c->d.asBytes, c->ext1);\r
                        s[c->ext1] = '\0';\r
                        PrintToScrollback("#db# %s", s);\r
                        memcpy(s, c->d.asBytes, c->ext1);\r
                        s[c->ext1] = '\0';\r
                        PrintToScrollback("#db# %s", s);\r
-                       break;
+                       break;\r
                }\r
 \r
                case CMD_DEBUG_PRINT_INTEGERS:\r
                }\r
 \r
                case CMD_DEBUG_PRINT_INTEGERS:\r
Impressum, Datenschutz