]> cvs.zerfleddert.de Git - proxmark3-svn/blame - armsrc/lfops.c
added tiwrite command, split LF code from appmain into lfops.c
[proxmark3-svn] / armsrc / lfops.c
CommitLineData
9bea179a 1//-----------------------------------------------------------------------------\r
2// Miscellaneous routines for low frequency tag operations.\r
3// Tags supported here so far are Texas Instruments (TI), HID\r
4// Also routines for raw mode reading/simulating of LF waveform\r
5//\r
6//-----------------------------------------------------------------------------\r
7#include <proxmark3.h>\r
8#include "apps.h"\r
9#include "../common/crc16.c"\r
10\r
11void AcquireRawAdcSamples125k(BOOL at134khz)\r
12{\r
13 if(at134khz) {\r
14 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
15 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
16 } else {\r
17 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
18 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
19 }\r
20\r
21 // Connect the A/D to the peak-detected low-frequency path.\r
22 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
23\r
24 // Give it a bit of time for the resonant antenna to settle.\r
25 SpinDelay(50);\r
26\r
27 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
28 FpgaSetupSsc();\r
29\r
30 // Now call the acquisition routine\r
31 DoAcquisition125k(at134khz);\r
32}\r
33\r
34// split into two routines so we can avoid timing issues after sending commands //\r
35void DoAcquisition125k(BOOL at134khz)\r
36{\r
37 BYTE *dest = (BYTE *)BigBuf;\r
38 int n = sizeof(BigBuf);\r
39 int i;\r
40\r
41 memset(dest,0,n);\r
42 i = 0;\r
43 for(;;) {\r
44 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
45 SSC_TRANSMIT_HOLDING = 0x43;\r
46 LED_D_ON();\r
47 }\r
48 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
49 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
50 i++;\r
51 LED_D_OFF();\r
52 if(i >= n) {\r
53 break;\r
54 }\r
55 }\r
56 }\r
57 DbpIntegers(dest[0], dest[1], at134khz);\r
58}\r
59\r
60void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command)\r
61{\r
62 BOOL at134khz;\r
63\r
64 // see if 'h' was specified\r
65 if(command[strlen((char *) command) - 1] == 'h')\r
66 at134khz= TRUE;\r
67 else\r
68 at134khz= FALSE;\r
69\r
70 if(at134khz) {\r
71 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
72 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
73 } else {\r
74 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
75 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
76 }\r
77\r
78 // Give it a bit of time for the resonant antenna to settle.\r
79 SpinDelay(50);\r
80\r
81 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
82 FpgaSetupSsc();\r
83\r
84 // now modulate the reader field\r
85 while(*command != '\0' && *command != ' ')\r
86 {\r
87 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
88 LED_D_OFF();\r
89 SpinDelayUs(delay_off);\r
90 if(at134khz) {\r
91 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
92 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
93 } else {\r
94 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
95 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
96 }\r
97 LED_D_ON();\r
98 if(*(command++) == '0')\r
99 SpinDelayUs(period_0);\r
100 else\r
101 SpinDelayUs(period_1);\r
102 }\r
103 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
104 LED_D_OFF();\r
105 SpinDelayUs(delay_off);\r
106 if(at134khz) {\r
107 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
108 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
109 } else {\r
110 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
111 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
112 }\r
113\r
114 // now do the read\r
115 DoAcquisition125k(at134khz);\r
116}\r
117\r
118void AcquireTiType(void)\r
119{\r
120 int i;\r
121 // tag transmission is <20ms, sampling at 2M gives us 40K samples max\r
122 // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS\r
123 int n = 1250;\r
124\r
125 // clear buffer\r
126 memset(BigBuf,0,sizeof(BigBuf));\r
127\r
128 // Set up the synchronous serial port\r
129 PIO_DISABLE = (1<<GPIO_SSC_DIN);\r
130 PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN);\r
131\r
132 // steal this pin from the SSP and use it to control the modulation\r
133 PIO_ENABLE = (1<<GPIO_SSC_DOUT);\r
134 PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);\r
135\r
136 SSC_CONTROL = SSC_CONTROL_RESET;\r
137 SSC_CONTROL = SSC_CONTROL_RX_ENABLE | SSC_CONTROL_TX_ENABLE;\r
138\r
139 // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long\r
140 // 48/2 = 24 MHz clock must be divided by 12\r
141 SSC_CLOCK_DIVISOR = 12;\r
142\r
143 SSC_RECEIVE_CLOCK_MODE = SSC_CLOCK_MODE_SELECT(0);\r
144 SSC_RECEIVE_FRAME_MODE = SSC_FRAME_MODE_BITS_IN_WORD(32) | SSC_FRAME_MODE_MSB_FIRST;\r
145 SSC_TRANSMIT_CLOCK_MODE = 0;\r
146 SSC_TRANSMIT_FRAME_MODE = 0;\r
147\r
148 LED_D_ON();\r
149\r
150 // modulate antenna\r
151 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
152\r
153 // Charge TI tag for 50ms.\r
154 SpinDelay(50);\r
155\r
156 // stop modulating antenna and listen\r
157 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
158\r
159 LED_D_OFF();\r
160\r
161 i = 0;\r
162 for(;;) {\r
163 if(SSC_STATUS & SSC_STATUS_RX_READY) {\r
164 BigBuf[i] = SSC_RECEIVE_HOLDING; // store 32 bit values in buffer\r
165 i++; if(i >= n) return;\r
166 }\r
167 WDT_HIT();\r
168 }\r
169\r
170 // return stolen pin to SSP\r
171 PIO_DISABLE = (1<<GPIO_SSC_DOUT);\r
172 PIO_PERIPHERAL_A_SEL = (1<<GPIO_SSC_DIN) | (1<<GPIO_SSC_DOUT);\r
173}\r
174\r
175void ReadTItag()\r
176{\r
177}\r
178\r
179void WriteTIbyte(BYTE b)\r
180{\r
181 int i = 0;\r
182\r
183 // modulate 8 bits out to the antenna\r
184 for (i=0; i<8; i++)\r
185 {\r
186 if (b&(1<<i)) {\r
187 // stop modulating antenna\r
188 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
189 SpinDelayUs(1000);\r
190 // modulate antenna\r
191 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
192 SpinDelayUs(1000);\r
193 } else {\r
194 // stop modulating antenna\r
195 PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_SSC_DOUT);\r
196 SpinDelayUs(300);\r
197 // modulate antenna\r
198 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
199 SpinDelayUs(1700);\r
200 }\r
201 }\r
202}\r
203\r
204void AcquireRawBitsTI(void)\r
205{\r
206 // TI tags charge at 134.2Khz\r
207 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
208\r
209 // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
210 // connects to SSP_DIN and the SSP_DOUT logic level controls\r
211 // whether we're modulating the antenna (high)\r
212 // or listening to the antenna (low)\r
213 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
214\r
215 // get TI tag data into the buffer\r
216 AcquireTiType();\r
217\r
218 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
219}\r
220\r
221// this is a dummy function to get around\r
222// a possible flash bug in the bootloader\r
223// delete once you've added more code.\r
224void DummyDummyDummy(void)\r
225{\r
226 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
227 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
228 AcquireTiType();\r
229 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
230}\r
231\r
232// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc\r
233// if crc provided, it will be written with the data verbatim (even if bogus)\r
234// if not provided a valid crc will be computed from the data and written.\r
235void WriteTItag(DWORD idhi, DWORD idlo, WORD crc)\r
236{\r
237\r
238 // WARNING the order of the bytes in which we calc crc below needs checking\r
239 // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
240 // bytes in reverse or something\r
241\r
242 if(crc == 0) {\r
243 crc = update_crc16(crc, (idlo)&0xff);\r
244 crc = update_crc16(crc, (idlo>>8)&0xff);\r
245 crc = update_crc16(crc, (idlo>>16)&0xff);\r
246 crc = update_crc16(crc, (idlo>>24)&0xff);\r
247 crc = update_crc16(crc, (idhi)&0xff);\r
248 crc = update_crc16(crc, (idhi>>8)&0xff);\r
249 crc = update_crc16(crc, (idhi>>16)&0xff);\r
250 crc = update_crc16(crc, (idhi>>24)&0xff);\r
251 }\r
252 DbpString("Writing the following data to tag:");\r
253 DbpIntegers(idhi, idlo, crc);\r
254\r
255 // TI tags charge at 134.2Khz\r
256 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
257 // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
258 // connects to SSP_DIN and the SSP_DOUT logic level controls\r
259 // whether we're modulating the antenna (high)\r
260 // or listening to the antenna (low)\r
261 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
262 LED_A_ON();\r
263\r
264 // steal this pin from the SSP and use it to control the modulation\r
265 PIO_ENABLE = (1<<GPIO_SSC_DOUT);\r
266 PIO_OUTPUT_ENABLE = (1<<GPIO_SSC_DOUT);\r
267\r
268 // writing algorithm:\r
269 // a high bit consists of a field off for 1ms and field on for 1ms\r
270 // a low bit consists of a field off for 0.3ms and field on for 1.7ms\r
271 // initiate a charge time of 50ms (field on) then immediately start writing bits\r
272 // start by writing 0xBB (keyword) and 0xEB (password)\r
273 // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)\r
274 // finally end with 0x0300 (write frame)\r
275 // all data is sent lsb firts\r
276 // finish with 15ms programming time\r
277\r
278 // modulate antenna\r
279 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
280 SpinDelay(50); // charge time\r
281\r
282 WriteTIbyte(0xbb); // keyword\r
283 WriteTIbyte(0xeb); // password\r
284 WriteTIbyte( (idlo )&0xff );\r
285 WriteTIbyte( (idlo>>8 )&0xff );\r
286 WriteTIbyte( (idlo>>16)&0xff );\r
287 WriteTIbyte( (idlo>>24)&0xff );\r
288 WriteTIbyte( (idhi )&0xff );\r
289 WriteTIbyte( (idhi>>8 )&0xff );\r
290 WriteTIbyte( (idhi>>16)&0xff );\r
291 WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo\r
292 WriteTIbyte( (crc )&0xff ); // crc lo\r
293 WriteTIbyte( (crc>>8 )&0xff ); // crc hi\r
294 WriteTIbyte(0x00); // write frame lo\r
295 WriteTIbyte(0x03); // write frame hi\r
296 PIO_OUTPUT_DATA_SET = (1<<GPIO_SSC_DOUT);\r
297 SpinDelay(50); // programming time\r
298\r
299 LED_A_OFF();\r
300\r
301 // get TI tag data into the buffer\r
302 AcquireTiType();\r
303\r
304 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
305 DbpString("Now use tibits and tidemod");\r
306}\r
307\r
308void SimulateTagLowFrequency(int period, int ledcontrol)\r
309{\r
310 int i;\r
311 BYTE *tab = (BYTE *)BigBuf;\r
312\r
313 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
314\r
315 PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);\r
316\r
317 PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);\r
318 PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);\r
319\r
320#define SHORT_COIL() LOW(GPIO_SSC_DOUT)\r
321#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)\r
322\r
323 i = 0;\r
324 for(;;) {\r
325 while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {\r
326 if(BUTTON_PRESS()) {\r
327 DbpString("Stopped");\r
328 return;\r
329 }\r
330 WDT_HIT();\r
331 }\r
332\r
333 if (ledcontrol)\r
334 LED_D_ON();\r
335\r
336 if(tab[i])\r
337 OPEN_COIL();\r
338 else\r
339 SHORT_COIL();\r
340\r
341 if (ledcontrol)\r
342 LED_D_OFF();\r
343\r
344 while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {\r
345 if(BUTTON_PRESS()) {\r
346 DbpString("Stopped");\r
347 return;\r
348 }\r
349 WDT_HIT();\r
350 }\r
351\r
352 i++;\r
353 if(i == period) i = 0;\r
354 }\r
355}\r
356\r
357// compose fc/8 fc/10 waveform\r
358static void fc(int c, int *n) {\r
359 BYTE *dest = (BYTE *)BigBuf;\r
360 int idx;\r
361\r
362 // for when we want an fc8 pattern every 4 logical bits\r
363 if(c==0) {\r
364 dest[((*n)++)]=1;\r
365 dest[((*n)++)]=1;\r
366 dest[((*n)++)]=0;\r
367 dest[((*n)++)]=0;\r
368 dest[((*n)++)]=0;\r
369 dest[((*n)++)]=0;\r
370 dest[((*n)++)]=0;\r
371 dest[((*n)++)]=0;\r
372 }\r
373 // an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples\r
374 if(c==8) {\r
375 for (idx=0; idx<6; idx++) {\r
376 dest[((*n)++)]=1;\r
377 dest[((*n)++)]=1;\r
378 dest[((*n)++)]=0;\r
379 dest[((*n)++)]=0;\r
380 dest[((*n)++)]=0;\r
381 dest[((*n)++)]=0;\r
382 dest[((*n)++)]=0;\r
383 dest[((*n)++)]=0;\r
384 }\r
385 }\r
386\r
387 // an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
388 if(c==10) {\r
389 for (idx=0; idx<5; idx++) {\r
390 dest[((*n)++)]=1;\r
391 dest[((*n)++)]=1;\r
392 dest[((*n)++)]=1;\r
393 dest[((*n)++)]=0;\r
394 dest[((*n)++)]=0;\r
395 dest[((*n)++)]=0;\r
396 dest[((*n)++)]=0;\r
397 dest[((*n)++)]=0;\r
398 dest[((*n)++)]=0;\r
399 dest[((*n)++)]=0;\r
400 }\r
401 }\r
402}\r
403\r
404// prepare a waveform pattern in the buffer based on the ID given then\r
405// simulate a HID tag until the button is pressed\r
406void CmdHIDsimTAG(int hi, int lo, int ledcontrol)\r
407{\r
408 int n=0, i=0;\r
409 /*\r
410 HID tag bitstream format\r
411 The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
412 A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
413 A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
414 A fc8 is inserted before every 4 bits\r
415 A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
416 nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
417 */\r
418\r
419 if (hi>0xFFF) {\r
420 DbpString("Tags can only have 44 bits.");\r
421 return;\r
422 }\r
423 fc(0,&n);\r
424 // special start of frame marker containing invalid bit sequences\r
425 fc(8, &n); fc(8, &n); // invalid\r
426 fc(8, &n); fc(10, &n); // logical 0\r
427 fc(10, &n); fc(10, &n); // invalid\r
428 fc(8, &n); fc(10, &n); // logical 0\r
429\r
430 WDT_HIT();\r
431 // manchester encode bits 43 to 32\r
432 for (i=11; i>=0; i--) {\r
433 if ((i%4)==3) fc(0,&n);\r
434 if ((hi>>i)&1) {\r
435 fc(10, &n); fc(8, &n); // low-high transition\r
436 } else {\r
437 fc(8, &n); fc(10, &n); // high-low transition\r
438 }\r
439 }\r
440\r
441 WDT_HIT();\r
442 // manchester encode bits 31 to 0\r
443 for (i=31; i>=0; i--) {\r
444 if ((i%4)==3) fc(0,&n);\r
445 if ((lo>>i)&1) {\r
446 fc(10, &n); fc(8, &n); // low-high transition\r
447 } else {\r
448 fc(8, &n); fc(10, &n); // high-low transition\r
449 }\r
450 }\r
451\r
452 if (ledcontrol)\r
453 LED_A_ON();\r
454 SimulateTagLowFrequency(n, ledcontrol);\r
455\r
456 if (ledcontrol)\r
457 LED_A_OFF();\r
458}\r
459\r
460\r
461// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
462void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)\r
463{\r
464 BYTE *dest = (BYTE *)BigBuf;\r
465 int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
466 DWORD hi=0, lo=0;\r
467\r
468 FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
469 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
470\r
471 // Connect the A/D to the peak-detected low-frequency path.\r
472 SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
473\r
474 // Give it a bit of time for the resonant antenna to settle.\r
475 SpinDelay(50);\r
476\r
477 // Now set up the SSC to get the ADC samples that are now streaming at us.\r
478 FpgaSetupSsc();\r
479\r
480 for(;;) {\r
481 WDT_HIT();\r
482 if (ledcontrol)\r
483 LED_A_ON();\r
484 if(BUTTON_PRESS()) {\r
485 DbpString("Stopped");\r
486 if (ledcontrol)\r
487 LED_A_OFF();\r
488 return;\r
489 }\r
490\r
491 i = 0;\r
492 m = sizeof(BigBuf);\r
493 memset(dest,128,m);\r
494 for(;;) {\r
495 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
496 SSC_TRANSMIT_HOLDING = 0x43;\r
497 if (ledcontrol)\r
498 LED_D_ON();\r
499 }\r
500 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
501 dest[i] = (BYTE)SSC_RECEIVE_HOLDING;\r
502 // we don't care about actual value, only if it's more or less than a\r
503 // threshold essentially we capture zero crossings for later analysis\r
504 if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
505 i++;\r
506 if (ledcontrol)\r
507 LED_D_OFF();\r
508 if(i >= m) {\r
509 break;\r
510 }\r
511 }\r
512 }\r
513\r
514 // FSK demodulator\r
515\r
516 // sync to first lo-hi transition\r
517 for( idx=1; idx<m; idx++) {\r
518 if (dest[idx-1]<dest[idx])\r
519 lastval=idx;\r
520 break;\r
521 }\r
522 WDT_HIT();\r
523\r
524 // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
525 // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
526 // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
527 for( i=0; idx<m; idx++) {\r
528 if (dest[idx-1]<dest[idx]) {\r
529 dest[i]=idx-lastval;\r
530 if (dest[i] <= 8) {\r
531 dest[i]=1;\r
532 } else {\r
533 dest[i]=0;\r
534 }\r
535\r
536 lastval=idx;\r
537 i++;\r
538 }\r
539 }\r
540 m=i;\r
541 WDT_HIT();\r
542\r
543 // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
544 lastval=dest[0];\r
545 idx=0;\r
546 i=0;\r
547 n=0;\r
548 for( idx=0; idx<m; idx++) {\r
549 if (dest[idx]==lastval) {\r
550 n++;\r
551 } else {\r
552 // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
553 // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
554 // swallowed up by rounding\r
555 // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
556 // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
557 // like 111000\r
558 if (dest[idx-1]) {\r
559 n=(n+1)/6; // fc/8 in sets of 6\r
560 } else {\r
561 n=(n+1)/5; // fc/10 in sets of 5\r
562 }\r
563 switch (n) { // stuff appropriate bits in buffer\r
564 case 0:\r
565 case 1: // one bit\r
566 dest[i++]=dest[idx-1];\r
567 break;\r
568 case 2: // two bits\r
569 dest[i++]=dest[idx-1];\r
570 dest[i++]=dest[idx-1];\r
571 break;\r
572 case 3: // 3 bit start of frame markers\r
573 dest[i++]=dest[idx-1];\r
574 dest[i++]=dest[idx-1];\r
575 dest[i++]=dest[idx-1];\r
576 break;\r
577 // When a logic 0 is immediately followed by the start of the next transmisson\r
578 // (special pattern) a pattern of 4 bit duration lengths is created.\r
579 case 4:\r
580 dest[i++]=dest[idx-1];\r
581 dest[i++]=dest[idx-1];\r
582 dest[i++]=dest[idx-1];\r
583 dest[i++]=dest[idx-1];\r
584 break;\r
585 default: // this shouldn't happen, don't stuff any bits\r
586 break;\r
587 }\r
588 n=0;\r
589 lastval=dest[idx];\r
590 }\r
591 }\r
592 m=i;\r
593 WDT_HIT();\r
594\r
595 // final loop, go over previously decoded manchester data and decode into usable tag ID\r
596 // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
597 for( idx=0; idx<m-6; idx++) {\r
598 // search for a start of frame marker\r
599 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
600 {\r
601 found=1;\r
602 idx+=6;\r
603 if (found && (hi|lo)) {\r
604 DbpString("TAG ID");\r
605 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
606 /* if we're only looking for one tag */\r
607 if (findone)\r
608 {\r
609 *high = hi;\r
610 *low = lo;\r
611 return;\r
612 }\r
613 hi=0;\r
614 lo=0;\r
615 found=0;\r
616 }\r
617 }\r
618 if (found) {\r
619 if (dest[idx] && (!dest[idx+1]) ) {\r
620 hi=(hi<<1)|(lo>>31);\r
621 lo=(lo<<1)|0;\r
622 } else if ( (!dest[idx]) && dest[idx+1]) {\r
623 hi=(hi<<1)|(lo>>31);\r
624 lo=(lo<<1)|1;\r
625 } else {\r
626 found=0;\r
627 hi=0;\r
628 lo=0;\r
629 }\r
630 idx++;\r
631 }\r
632 if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
633 {\r
634 found=1;\r
635 idx+=6;\r
636 if (found && (hi|lo)) {\r
637 DbpString("TAG ID");\r
638 DbpIntegers(hi, lo, (lo>>1)&0xffff);\r
639 /* if we're only looking for one tag */\r
640 if (findone)\r
641 {\r
642 *high = hi;\r
643 *low = lo;\r
644 return;\r
645 }\r
646 hi=0;\r
647 lo=0;\r
648 found=0;\r
649 }\r
650 }\r
651 }\r
652 WDT_HIT();\r
653 }\r
654}\r
Impressum, Datenschutz