+/* 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
+ 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 transmitted data of an EM4x50 tag\r
+ * Format:\r
+ *\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * CCCCCCCC <- column parity bits\r
+ * 0 <- stop bit\r
+ * LW <- Listen Window\r
+ *\r
+ * This pattern repeats for every block of data being transmitted.\r
+ * Transmission starts with two Listen Windows (LW - a modulated\r
+ * pattern of 320 cycles each (32/32/128/64/64)).\r
+ *\r
+ * Note that this data may or may not be the UID. It is whatever data\r
+ * is stored in the blocks defined in the control word First and Last \r
+ * Word Read values. UID is stored in block 32.\r
+ */ \r
+static void CmdEM4x50read(char *str)\r
+{\r
+ int i, j, startblock, clock, skip, block, start, end, low, high;\r
+ BOOL complete= FALSE;\r
+ int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];\r
+ char tmp[6];\r
+\r
+ high= low= 0;\r
+ clock= 64;\r
+\r
+ /* first get high and low values */\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
+ /* populate a buffer with pulse lengths */\r
+ i= 0;\r
+ j= 0;\r
+ while(i < GraphTraceLen)\r
+ {\r
+ // measure from low to low\r
+ while(GraphBuffer[i] > low)\r
+ ++i;\r
+ start= i;\r
+ while(GraphBuffer[i] < high)\r
+ ++i;\r
+ while(GraphBuffer[i] > low)\r
+ ++i;\r
+ tmpbuff[j++]= i - start;\r
+ }\r
+\r
+ \r
+ /* look for data start - should be 2 pairs of LW (pulses of 192,128) */\r
+ start= -1;\r
+ skip= 0;\r
+ for (i= 0; i < j - 4 ; ++i)\r
+ {\r
+ skip += tmpbuff[i];\r
+ if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)\r
+ if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)\r
+ if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)\r
+ if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)\r
+ {\r
+ start= i + 3;\r
+ break;\r
+ }\r
+ }\r
+ startblock= i + 3;\r
+\r
+ /* skip over the remainder of the LW */\r
+ skip += tmpbuff[i+1]+tmpbuff[i+2];\r
+ while(GraphBuffer[skip] > low)\r
+ ++skip;\r
+ skip += 8;\r
+\r
+ /* now do it again to find the end */\r
+ end= start;\r
+ for (i += 3; i < j - 4 ; ++i)\r
+ {\r
+ end += tmpbuff[i];\r
+ if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)\r
+ if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)\r
+ if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)\r
+ if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)\r
+ {\r
+ complete= TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (start >= 0)\r
+ PrintToScrollback("Found data at sample: %i",skip);\r
+ else\r
+ {\r
+ PrintToScrollback("No data found!");\r
+ PrintToScrollback("Try again with more samples.");\r
+ return;\r
+ }\r
+\r
+ if (!complete)\r
+ {\r
+ PrintToScrollback("*** Warning!");\r
+ PrintToScrollback("Partial data - no end found!");\r
+ PrintToScrollback("Try again with more samples.");\r
+ }\r
+\r
+ /* get rid of leading crap */\r
+ sprintf(tmp,"%i",skip);\r
+ CmdLtrim(tmp);\r
+\r
+ /* now work through remaining buffer printing out data blocks */\r
+ block= 0;\r
+ i= startblock;\r
+ while(block < 6)\r
+ {\r
+ PrintToScrollback("Block %i:", block);\r
+ // mandemod routine needs to be split so we can call it for data\r
+ // just print for now for debugging\r
+ Cmdmanchesterdemod("i 64");\r
+ skip= 0;\r
+ /* look for LW before start of next block */\r
+ for ( ; i < j - 4 ; ++i)\r
+ {\r
+ skip += tmpbuff[i];\r
+ if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)\r
+ if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)\r
+ break;\r
+ }\r
+ while(GraphBuffer[skip] > low)\r
+ ++skip;\r
+ skip += 8;\r
+ sprintf(tmp,"%i",skip);\r
+ CmdLtrim(tmp);\r
+ start += skip;\r
+ block++;\r
+ }\r
+}\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 retested = 0;\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
+retest:\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
+ return;\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
+ /* if we've already retested after flipping bits, return */\r
+ if (retested++)\r
+ return;\r
+\r
+ /* if this didn't work, try flipping bits */\r
+ for (i = 0; i < bit2idx; i++)\r
+ BitStream[i] ^= 1;\r
+\r
+ goto retest;\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