+//-----------------------------------------------------------------------------\r
+// Miscellaneous routines for low frequency tag operations.\r
+// Tags supported here so far are Texas Instruments (TI), HID\r
+// Also routines for raw mode reading/simulating of LF waveform\r
+//\r
+//-----------------------------------------------------------------------------\r
+#include <proxmark3.h>\r
+#include "apps.h"\r
+#include "../common/crc16.c"\r
+\r
+void AcquireRawAdcSamples125k(BOOL at134khz)\r
+{\r
+ if(at134khz) {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ } else {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ }\r
+\r
+ // Connect the A/D to the peak-detected low-frequency path.\r
+ SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
+\r
+ // Give it a bit of time for the resonant antenna to settle.\r
+ SpinDelay(50);\r
+\r
+ // Now set up the SSC to get the ADC samples that are now streaming at us.\r
+ FpgaSetupSsc();\r
+\r
+ // Now call the acquisition routine\r
+ DoAcquisition125k(at134khz);\r
+}\r
+\r
+// split into two routines so we can avoid timing issues after sending commands //\r
+void DoAcquisition125k(BOOL at134khz)\r
+{\r
+ BYTE *dest = (BYTE *)BigBuf;\r
+ int n = sizeof(BigBuf);\r
+ int i;\r
+\r
+ memset(dest,0,n);\r
+ i = 0;\r
+ for(;;) {\r
+ if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
+ SSC_TRANSMIT_HOLDING = 0x43;\r
+ LED_D_ON();\r
+ }\r
+ if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
+ dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
+ i++;\r
+ LED_D_OFF();\r
+ if(i >= n) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ DbpIntegers(dest[0], dest[1], at134khz);\r
+}\r
+\r
+void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command)\r
+{\r
+ BOOL at134khz;\r
+\r
+ // see if 'h' was specified\r
+ if(command[strlen((char *) command) - 1] == 'h')\r
+ at134khz= TRUE;\r
+ else\r
+ at134khz= FALSE;\r
+\r
+ if(at134khz) {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ } else {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ }\r
+\r
+ // Give it a bit of time for the resonant antenna to settle.\r
+ SpinDelay(50);\r
+\r
+ // Now set up the SSC to get the ADC samples that are now streaming at us.\r
+ FpgaSetupSsc();\r
+\r
+ // now modulate the reader field\r
+ while(*command != '\0' && *command != ' ')\r
+ {\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LED_D_OFF();\r
+ SpinDelayUs(delay_off);\r
+ if(at134khz) {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ } else {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ }\r
+ LED_D_ON();\r
+ if(*(command++) == '0')\r
+ SpinDelayUs(period_0);\r
+ else\r
+ SpinDelayUs(period_1);\r
+ }\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LED_D_OFF();\r
+ SpinDelayUs(delay_off);\r
+ if(at134khz) {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ } else {\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+ }\r
+\r
+ // now do the read\r
+ DoAcquisition125k(at134khz);\r
+}\r
+\r
+void AcquireTiType(void)\r
+{\r
+ int i;\r
+ // tag transmission is <20ms, sampling at 2M gives us 40K samples max\r
+ // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS\r
+ int n = 1250;\r
+\r
+ // clear buffer\r
+ memset(BigBuf,0,sizeof(BigBuf));\r
+\r
+ // Set up the synchronous serial port\r
+ PIO_DISABLE = (1<<GPIO_SSC_DIN);\r
+ PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN);\r
+\r
+ // steal this pin from the SSP and use it to control the modulation\r
+ PIO_ENABLE = (1<<GPIO_SSC_DOUT);\r
+ PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);\r
+\r
+ SSC_CONTROL = SSC_CONTROL_RESET;\r
+ SSC_CONTROL = SSC_CONTROL_RX_ENABLE | SSC_CONTROL_TX_ENABLE;\r
+\r
+ // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long\r
+ // 48/2 = 24 MHz clock must be divided by 12\r
+ SSC_CLOCK_DIVISOR = 12;\r
+\r
+ SSC_RECEIVE_CLOCK_MODE = SSC_CLOCK_MODE_SELECT(0);\r
+ SSC_RECEIVE_FRAME_MODE = SSC_FRAME_MODE_BITS_IN_WORD(32) | SSC_FRAME_MODE_MSB_FIRST;\r
+ SSC_TRANSMIT_CLOCK_MODE = 0;\r
+ SSC_TRANSMIT_FRAME_MODE = 0;\r
+\r
+ LED_D_ON();\r
+\r
+ // modulate antenna\r
+ PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
+\r
+ // Charge TI tag for 50ms.\r
+ SpinDelay(50);\r
+\r
+ // stop modulating antenna and listen\r
+ PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
+\r
+ LED_D_OFF();\r
+\r
+ i = 0;\r
+ for(;;) {\r
+ if(SSC_STATUS & SSC_STATUS_RX_READY) {\r
+ BigBuf[i] = SSC_RECEIVE_HOLDING; // store 32 bit values in buffer\r
+ i++; if(i >= n) return;\r
+ }\r
+ WDT_HIT();\r
+ }\r
+\r
+ // return stolen pin to SSP\r
+ PIO_DISABLE = (1<<GPIO_SSC_DOUT);\r
+ PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN) | (1<<GPIO_SSC_DOUT);\r
+}\r
+\r
+void ReadTItag()\r
+{\r
+}\r
+\r
+void WriteTIbyte(BYTE b)\r
+{\r
+ int i = 0;\r
+\r
+ // modulate 8 bits out to the antenna\r
+ for (i=0; i<8; i++)\r
+ {\r
+ if (b&(1<<i)) {\r
+ // stop modulating antenna\r
+ PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
+ SpinDelayUs(1000);\r
+ // modulate antenna\r
+ PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
+ SpinDelayUs(1000);\r
+ } else {\r
+ // stop modulating antenna\r
+ PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
+ SpinDelayUs(300);\r
+ // modulate antenna\r
+ PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
+ SpinDelayUs(1700);\r
+ }\r
+ }\r
+}\r
+\r
+void AcquireRawBitsTI(void)\r
+{\r
+ // TI tags charge at 134.2Khz\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+\r
+ // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
+ // connects to SSP_DIN and the SSP_DOUT logic level controls\r
+ // whether we're modulating the antenna (high)\r
+ // or listening to the antenna (low)\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
+\r
+ // get TI tag data into the buffer\r
+ AcquireTiType();\r
+\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+}\r
+\r
+// this is a dummy function to get around\r
+// a possible flash bug in the bootloader\r
+// delete once you've added more code.\r
+void DummyDummyDummy(void)\r
+{\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
+ AcquireTiType();\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+}\r
+\r
+// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc\r
+// if crc provided, it will be written with the data verbatim (even if bogus)\r
+// if not provided a valid crc will be computed from the data and written.\r
+void WriteTItag(DWORD idhi, DWORD idlo, WORD crc)\r
+{\r
+\r
+ // WARNING the order of the bytes in which we calc crc below needs checking\r
+ // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
+ // bytes in reverse or something\r
+\r
+ if(crc == 0) {\r
+ crc = update_crc16(crc, (idlo)&0xff);\r
+ crc = update_crc16(crc, (idlo>>8)&0xff);\r
+ crc = update_crc16(crc, (idlo>>16)&0xff);\r
+ crc = update_crc16(crc, (idlo>>24)&0xff);\r
+ crc = update_crc16(crc, (idhi)&0xff);\r
+ crc = update_crc16(crc, (idhi>>8)&0xff);\r
+ crc = update_crc16(crc, (idhi>>16)&0xff);\r
+ crc = update_crc16(crc, (idhi>>24)&0xff);\r
+ }\r
+ DbpString("Writing the following data to tag:");\r
+ DbpIntegers(idhi, idlo, crc);\r
+\r
+ // TI tags charge at 134.2Khz\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
+ // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
+ // connects to SSP_DIN and the SSP_DOUT logic level controls\r
+ // whether we're modulating the antenna (high)\r
+ // or listening to the antenna (low)\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
+ LED_A_ON();\r
+\r
+ // steal this pin from the SSP and use it to control the modulation\r
+ PIO_ENABLE = (1<<GPIO_SSC_DOUT);\r
+ PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);\r
+\r
+ // writing algorithm:\r
+ // a high bit consists of a field off for 1ms and field on for 1ms\r
+ // a low bit consists of a field off for 0.3ms and field on for 1.7ms\r
+ // initiate a charge time of 50ms (field on) then immediately start writing bits\r
+ // start by writing 0xBB (keyword) and 0xEB (password)\r
+ // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)\r
+ // finally end with 0x0300 (write frame)\r
+ // all data is sent lsb firts\r
+ // finish with 15ms programming time\r
+\r
+ // modulate antenna\r
+ PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
+ SpinDelay(50); // charge time\r
+\r
+ WriteTIbyte(0xbb); // keyword\r
+ WriteTIbyte(0xeb); // password\r
+ WriteTIbyte( (idlo )&0xff );\r
+ WriteTIbyte( (idlo>>8 )&0xff );\r
+ WriteTIbyte( (idlo>>16)&0xff );\r
+ WriteTIbyte( (idlo>>24)&0xff );\r
+ WriteTIbyte( (idhi )&0xff );\r
+ WriteTIbyte( (idhi>>8 )&0xff );\r
+ WriteTIbyte( (idhi>>16)&0xff );\r
+ WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo\r
+ WriteTIbyte( (crc )&0xff ); // crc lo\r
+ WriteTIbyte( (crc>>8 )&0xff ); // crc hi\r
+ WriteTIbyte(0x00); // write frame lo\r
+ WriteTIbyte(0x03); // write frame hi\r
+ PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
+ SpinDelay(50); // programming time\r
+\r
+ LED_A_OFF();\r
+\r
+ // get TI tag data into the buffer\r
+ AcquireTiType();\r
+\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ DbpString("Now use tibits and tidemod");\r
+}\r
+\r
+void SimulateTagLowFrequency(int period, int ledcontrol)\r
+{\r
+ int i;\r
+ BYTE *tab = (BYTE *)BigBuf;\r
+\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
+\r
+ PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);\r
+\r
+ PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);\r
+ PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);\r
+\r
+#define SHORT_COIL() LOW(GPIO_SSC_DOUT)\r
+#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)\r
+\r
+ i = 0;\r
+ for(;;) {\r
+ while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {\r
+ if(BUTTON_PRESS()) {\r
+ DbpString("Stopped");\r
+ return;\r
+ }\r
+ WDT_HIT();\r
+ }\r
+\r
+ if (ledcontrol)\r
+ LED_D_ON();\r
+\r
+ if(tab[i])\r
+ OPEN_COIL();\r
+ else\r
+ SHORT_COIL();\r
+\r
+ if (ledcontrol)\r
+ LED_D_OFF();\r
+\r
+ while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {\r
+ if(BUTTON_PRESS()) {\r
+ DbpString("Stopped");\r
+ return;\r
+ }\r
+ WDT_HIT();\r
+ }\r
+\r
+ i++;\r
+ if(i == period) i = 0;\r
+ }\r
+}\r
+\r
+// compose fc/8 fc/10 waveform\r
+static void fc(int c, int *n) {\r
+ BYTE *dest = (BYTE *)BigBuf;\r
+ int idx;\r
+\r
+ // for when we want an fc8 pattern every 4 logical bits\r
+ if(c==0) {\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ }\r
+ // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples\r
+ if(c==8) {\r
+ for (idx=0; idx<6; idx++) {\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ }\r
+ }\r
+\r
+ // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
+ if(c==10) {\r
+ for (idx=0; idx<5; idx++) {\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=1;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ dest[((*n)++)]=0;\r
+ }\r
+ }\r
+}\r
+\r
+// prepare a waveform pattern in the buffer based on the ID given then\r
+// simulate a HID tag until the button is pressed\r
+void CmdHIDsimTAG(int hi, int lo, int ledcontrol)\r
+{\r
+ int n=0, i=0;\r
+ /*\r
+ HID tag bitstream format\r
+ The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
+ A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
+ A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
+ A fc8 is inserted before every 4 bits\r
+ A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
+ nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
+ */\r
+\r
+ if (hi>0xFFF) {\r
+ DbpString("Tags can only have 44 bits.");\r
+ return;\r
+ }\r
+ fc(0,&n);\r
+ // special start of frame marker containing invalid bit sequences\r
+ fc(8, &n); fc(8, &n); // invalid\r
+ fc(8, &n); fc(10, &n); // logical 0\r
+ fc(10, &n); fc(10, &n); // invalid\r
+ fc(8, &n); fc(10, &n); // logical 0\r
+\r
+ WDT_HIT();\r
+ // manchester encode bits 43 to 32\r
+ for (i=11; i>=0; i--) {\r
+ if ((i%4)==3) fc(0,&n);\r
+ if ((hi>>i)&1) {\r
+ fc(10, &n); fc(8, &n); // low-high transition\r
+ } else {\r
+ fc(8, &n); fc(10, &n); // high-low transition\r
+ }\r
+ }\r
+\r
+ WDT_HIT();\r
+ // manchester encode bits 31 to 0\r
+ for (i=31; i>=0; i--) {\r
+ if ((i%4)==3) fc(0,&n);\r
+ if ((lo>>i)&1) {\r
+ fc(10, &n); fc(8, &n); // low-high transition\r
+ } else {\r
+ fc(8, &n); fc(10, &n); // high-low transition\r
+ }\r
+ }\r
+\r
+ if (ledcontrol)\r
+ LED_A_ON();\r
+ SimulateTagLowFrequency(n, ledcontrol);\r
+\r
+ if (ledcontrol)\r
+ LED_A_OFF();\r
+}\r
+\r
+\r
+// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
+void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)\r
+{\r
+ BYTE *dest = (BYTE *)BigBuf;\r
+ int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
+ DWORD hi=0, lo=0;\r
+\r
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
+\r
+ // Connect the A/D to the peak-detected low-frequency path.\r
+ SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
+\r
+ // Give it a bit of time for the resonant antenna to settle.\r
+ SpinDelay(50);\r
+\r
+ // Now set up the SSC to get the ADC samples that are now streaming at us.\r
+ FpgaSetupSsc();\r
+\r
+ for(;;) {\r
+ WDT_HIT();\r
+ if (ledcontrol)\r
+ LED_A_ON();\r
+ if(BUTTON_PRESS()) {\r
+ DbpString("Stopped");\r
+ if (ledcontrol)\r
+ LED_A_OFF();\r
+ return;\r
+ }\r
+\r
+ i = 0;\r
+ m = sizeof(BigBuf);\r
+ memset(dest,128,m);\r
+ for(;;) {\r
+ if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
+ SSC_TRANSMIT_HOLDING = 0x43;\r
+ if (ledcontrol)\r
+ LED_D_ON();\r
+ }\r
+ if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
+ dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
+ // we don't care about actual value, only if it's more or less than a\r
+ // threshold essentially we capture zero crossings for later analysis\r
+ if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
+ i++;\r
+ if (ledcontrol)\r
+ LED_D_OFF();\r
+ if(i >= m) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ // FSK demodulator\r
+\r
+ // sync to first lo-hi transition\r
+ for( idx=1; idx<m; idx++) {\r
+ if (dest[idx-1]<dest[idx])\r
+ lastval=idx;\r
+ break;\r
+ }\r
+ WDT_HIT();\r
+\r
+ // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
+ // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
+ // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
+ for( i=0; idx<m; idx++) {\r
+ if (dest[idx-1]<dest[idx]) {\r
+ dest[i]=idx-lastval;\r
+ if (dest[i] <= 8) {\r
+ dest[i]=1;\r
+ } else {\r
+ dest[i]=0;\r
+ }\r
+\r
+ lastval=idx;\r
+ i++;\r
+ }\r
+ }\r
+ m=i;\r
+ WDT_HIT();\r
+\r
+ // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
+ lastval=dest[0];\r
+ idx=0;\r
+ i=0;\r
+ n=0;\r
+ for( idx=0; idx<m; idx++) {\r
+ if (dest[idx]==lastval) {\r
+ n++;\r
+ } else {\r
+ // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
+ // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
+ // swallowed up by rounding\r
+ // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
+ // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
+ // like 111000\r
+ if (dest[idx-1]) {\r
+ n=(n+1)/6; // fc/8 in sets of 6\r
+ } else {\r
+ n=(n+1)/5; // fc/10 in sets of 5\r
+ }\r
+ switch (n) { // stuff appropriate bits in buffer\r
+ case 0:\r
+ case 1: // one bit\r
+ dest[i++]=dest[idx-1];\r
+ break;\r
+ case 2: // two bits\r
+ dest[i++]=dest[idx-1];\r
+ dest[i++]=dest[idx-1];\r
+ break;\r
+ case 3: // 3 bit start of frame markers\r
+ dest[i++]=dest[idx-1];\r
+ dest[i++]=dest[idx-1];\r
+ dest[i++]=dest[idx-1];\r
+ break;\r
+ // When a logic 0 is immediately followed by the start of the next transmisson\r
+ // (special pattern) a pattern of 4 bit duration lengths is created.\r
+ case 4:\r
+ dest[i++]=dest[idx-1];\r
+ dest[i++]=dest[idx-1];\r
+ dest[i++]=dest[idx-1];\r
+ dest[i++]=dest[idx-1];\r
+ break;\r
+ default: // this shouldn't happen, don't stuff any bits\r
+ break;\r
+ }\r
+ n=0;\r
+ lastval=dest[idx];\r
+ }\r
+ }\r
+ m=i;\r
+ WDT_HIT();\r
+\r
+ // final loop, go over previously decoded manchester data and decode into usable tag ID\r
+ // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
+ for( idx=0; idx<m-6; idx++) {\r
+ // search for a start of frame marker\r
+ if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
+ {\r
+ found=1;\r
+ idx+=6;\r
+ if (found && (hi|lo)) {\r
+ DbpString("TAG ID");\r
+ DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
+ /* if we're only looking for one tag */\r
+ if (findone)\r
+ {\r
+ *high = hi;\r
+ *low = lo;\r
+ return;\r
+ }\r
+ hi=0;\r
+ lo=0;\r
+ found=0;\r
+ }\r
+ }\r
+ if (found) {\r
+ if (dest[idx] && (!dest[idx+1]) ) {\r
+ hi=(hi<<1)|(lo>>31);\r
+ lo=(lo<<1)|0;\r
+ } else if ( (!dest[idx]) && dest[idx+1]) {\r
+ hi=(hi<<1)|(lo>>31);\r
+ lo=(lo<<1)|1;\r
+ } else {\r
+ found=0;\r
+ hi=0;\r
+ lo=0;\r
+ }\r
+ idx++;\r
+ }\r
+ if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
+ {\r
+ found=1;\r
+ idx+=6;\r
+ if (found && (hi|lo)) {\r
+ DbpString("TAG ID");\r
+ DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
+ /* if we're only looking for one tag */\r
+ if (findone)\r
+ {\r
+ *high = hi;\r
+ *low = lo;\r
+ return;\r
+ }\r
+ hi=0;\r
+ lo=0;\r
+ found=0;\r
+ }\r
+ }\r
+ }\r
+ WDT_HIT();\r
+ }\r
+}\r