4 #include "lfsampling.h"
8 #include "fpgaloader.h"
10 #define T0_PCF 8 //period for the pcf7931 in us
13 size_t DemodPCF7931(uint8_t **outBlocks
) {
14 uint8_t bits
[256] = {0x00};
15 uint8_t blocks
[8][16];
16 uint8_t *dest
= BigBuf_get_addr();
18 int GraphTraceLen
= BigBuf_max_traceLen();
19 if (GraphTraceLen
> 18000)
20 GraphTraceLen
= 18000;
22 int i
, j
, lastval
, bitidx
, half_switch
;
24 int tolerance
= clock
/ 8;
27 size_t num_blocks
= 0;
28 int lmin
=128, lmax
=128;
31 BigBuf_Clear_keep_EM();
33 LFSetupFPGAForADC(95, true);
34 DoAcquisition_default(0, true);
41 /* Find first local max/min */
42 if(dest
[1] > dest
[0]) {
43 while(i
< GraphTraceLen
) {
44 if( !(dest
[i
] > dest
[i
-1]) && dest
[i
] > lmax
)
50 while(i
< GraphTraceLen
) {
51 if( !(dest
[i
] < dest
[i
-1]) && dest
[i
] < lmin
)
63 for (bitidx
= 0; i
< GraphTraceLen
; i
++) {
64 if ((dest
[i
-1] > dest
[i
] && dir
== 1 && dest
[i
] > lmax
) || (dest
[i
-1] < dest
[i
] && dir
== 0 && dest
[i
] < lmin
)) {
68 // Switch depending on lc length:
69 // Tolerance is 1/8 of clock rate (arbitrary)
70 if (ABS(lc
-clock
/4) < tolerance
) {
72 if((i
- pmc
) == lc
) { /* 16T0 was previous one */
74 i
+= (128+127+16+32+33+16)-1;
81 } else if (ABS(lc
-clock
/2) < tolerance
) {
83 if((i
- pmc
) == lc
) { /* 16T0 was previous one */
85 i
+= (128+127+16+32+33)-1;
89 } else if(half_switch
== 1) {
95 } else if (ABS(lc
-clock
) < tolerance
) {
100 if (++warnings
> 10) {
101 Dbprintf("Error: too many detection errors, aborting.");
106 if(block_done
== 1) {
108 for(j
= 0; j
< 16; ++j
) {
109 blocks
[num_blocks
][j
] =
126 if(i
< GraphTraceLen
)
127 dir
= (dest
[i
-1] > dest
[i
]) ? 0 : 1;
132 if(num_blocks
== 4) break;
134 memcpy(outBlocks
, blocks
, 16 * num_blocks
);
138 bool IsBlock0PCF7931(uint8_t *block
) {
139 // assuming all RFU bits are set to 0
140 // if PAC is enabled password is set to 0
141 if (block
[7] == 0x01)
143 if (!memcmp(block
, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block
+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
146 else if (block
[7] == 0x00)
148 if (!memcmp(block
+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
154 bool IsBlock1PCF7931(uint8_t *block
) {
155 // assuming all RFU bits are set to 0
157 uint8_t rb1
= block
[14] & 0x80;
158 uint8_t rfb
= block
[14] & 0x7f;
159 uint8_t rlb
= block
[15];
161 if (block
[10] == 0 && block
[11] == 0 && block
[12] == 0 && block
[13] == 0)
162 // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled
163 if(rfb
<= rlb
&& rfb
<= 9 && rlb
<= 9 && ((rfb
<= 1 && rlb
>= 1) || rb1
))
170 int found_blocks
= 0; // successfully read blocks
171 int max_blocks
= 8; // readable blocks
172 uint8_t memory_blocks
[8][17]; // PCF content
174 uint8_t single_blocks
[8][17]; // PFC blocks with unknown position
175 int single_blocks_cnt
= 0;
177 size_t n
= 0; // transmitted blocks
178 uint8_t tmp_blocks
[4][16]; // temporary read buffer
180 uint8_t found_0_1
= 0; // flag: blocks 0 and 1 were found
181 int errors
= 0; // error counter
182 int tries
= 0; // tries counter
184 memset(memory_blocks
, 0, 8*17*sizeof(uint8_t));
185 memset(single_blocks
, 0, 8*17*sizeof(uint8_t));
192 memset(tmp_blocks
, 0, 4*16*sizeof(uint8_t));
193 n
= DemodPCF7931((uint8_t**)tmp_blocks
);
197 // exit if no block is received
198 if (errors
>= 10 && found_blocks
== 0 && single_blocks_cnt
== 0) {
199 Dbprintf("Error, no tag or bad tag");
203 // exit if too many errors during reading
204 if (tries
> 50 && (2*errors
> tries
)) {
205 Dbprintf("Error reading the tag");
206 Dbprintf("Here is the partial content");
210 // our logic breaks if we don't get at least two blocks
212 // skip if all 0s block or no blocks
213 if (n
== 0 || !memcmp(tmp_blocks
[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
216 // add block to single blocks list
217 if (single_blocks_cnt
< max_blocks
) {
218 for (i
= 0; i
< single_blocks_cnt
; ++i
) {
219 if (!memcmp(single_blocks
[i
], tmp_blocks
[0], 16)) {
225 memcpy(single_blocks
[single_blocks_cnt
], tmp_blocks
[0], 16);
226 print_result("got single block", single_blocks
[single_blocks_cnt
], 16);
235 Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n
, found_blocks
, (max_blocks
== 0 ? found_blocks
: max_blocks
), tries
, errors
);
236 for (i
= 0; i
< n
; ++i
)
238 print_result("got consecutive blocks", tmp_blocks
[i
], 16);
244 if (IsBlock0PCF7931(tmp_blocks
[i
]) && IsBlock1PCF7931(tmp_blocks
[i
+1])) {
246 memcpy(memory_blocks
[0], tmp_blocks
[i
], 16);
247 memcpy(memory_blocks
[1], tmp_blocks
[i
+1], 16);
248 memory_blocks
[0][ALLOC
] = memory_blocks
[1][ALLOC
] = 1;
249 // block 1 tells how many blocks are going to be sent
250 max_blocks
= MAX((memory_blocks
[1][14] & 0x7f), memory_blocks
[1][15]) + 1;
253 Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks
);
255 // handle the following blocks
256 for (j
= i
+ 2; j
< n
; ++j
) {
257 memcpy(memory_blocks
[found_blocks
], tmp_blocks
[j
], 16);
258 memory_blocks
[found_blocks
][ALLOC
] = 1;
266 // Trying to re-order blocks
267 // Look for identical block in memory blocks
269 // skip all zeroes blocks
270 if (memcmp(tmp_blocks
[i
], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
271 for (j
= 1; j
< max_blocks
- 1; ++j
) {
272 if (!memcmp(tmp_blocks
[i
], memory_blocks
[j
], 16) && !memory_blocks
[j
+1][ALLOC
]) {
273 memcpy(memory_blocks
[j
+1], tmp_blocks
[i
+1], 16);
274 memory_blocks
[j
+1][ALLOC
] = 1;
275 if (++found_blocks
>= max_blocks
) goto end
;
279 if (memcmp(tmp_blocks
[i
+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
280 for (j
= 0; j
< max_blocks
; ++j
) {
281 if (!memcmp(tmp_blocks
[i
+1], memory_blocks
[j
], 16) && !memory_blocks
[(j
== 0 ? max_blocks
: j
) -1][ALLOC
]) {
283 memcpy(memory_blocks
[max_blocks
- 1], tmp_blocks
[i
], 16);
284 memory_blocks
[max_blocks
- 1][ALLOC
] = 1;
286 memcpy(memory_blocks
[j
-1], tmp_blocks
[i
], 16);
287 memory_blocks
[j
-1][ALLOC
] = 1;
289 if (++found_blocks
>= max_blocks
) goto end
;
297 if (BUTTON_PRESS()) {
298 Dbprintf("Button pressed, stopping.");
302 while (found_blocks
< max_blocks
);
305 Dbprintf("-----------------------------------------");
306 Dbprintf("Memory content:");
307 Dbprintf("-----------------------------------------");
308 for (i
= 0; i
< max_blocks
; ++i
) {
309 if (memory_blocks
[i
][ALLOC
])
310 print_result("Block", memory_blocks
[i
], 16);
312 Dbprintf("<missing block %d>", i
);
314 Dbprintf("-----------------------------------------");
316 if (found_blocks
< max_blocks
) {
317 Dbprintf("-----------------------------------------");
318 Dbprintf("Blocks with unknown position:");
319 Dbprintf("-----------------------------------------");
320 for (i
= 0; i
< single_blocks_cnt
; ++i
)
321 print_result("Block", single_blocks
[i
], 16);
323 Dbprintf("-----------------------------------------");
325 cmd_send(CMD_ACK
,0,0,0,0,0);
328 static void RealWritePCF7931(uint8_t *pass
, uint16_t init_delay
, int32_t l
, int32_t p
, uint8_t address
, uint8_t byte
, uint8_t data
) {
329 uint32_t tab
[1024]={0}; // data times frame
334 //BUILD OF THE DATA FRAME
335 //alimentation of the tag (time for initializing)
336 AddPatternPCF7931(init_delay
, 0, 8192/2*T0_PCF
, tab
);
337 AddPatternPCF7931(8192/2*T0_PCF
+ 319*T0_PCF
+70, 3*T0_PCF
, 29*T0_PCF
, tab
);
338 //password indication bit
339 AddBitPCF7931(1, tab
, l
, p
);
340 // password (on 56 bits)
341 AddBytePCF7931(pass
[0], tab
, l
, p
);
342 AddBytePCF7931(pass
[1], tab
, l
, p
);
343 AddBytePCF7931(pass
[2], tab
, l
, p
);
344 AddBytePCF7931(pass
[3], tab
, l
, p
);
345 AddBytePCF7931(pass
[4], tab
, l
, p
);
346 AddBytePCF7931(pass
[5], tab
, l
, p
);
347 AddBytePCF7931(pass
[6], tab
, l
, p
);
348 //programming mode (0 or 1)
349 AddBitPCF7931(0, tab
, l
, p
);
351 //block adress on 6 bits
352 for (u
= 0; u
< 6; ++u
) {
353 if (address
& (1 << u
)) { // bit 1
355 AddBitPCF7931(1, tab
, l
, p
);
357 AddBitPCF7931(0, tab
, l
, p
);
361 //byte address on 4 bits
362 for (u
= 0; u
< 4; ++u
)
364 if (byte
& (1 << u
)) { // bit 1
366 AddBitPCF7931(1, tab
, l
, p
);
369 AddBitPCF7931(0, tab
, l
, p
);
375 if (data
&(1<<u
)) { // bit 1
377 AddBitPCF7931(1, tab
, l
, p
);
380 AddBitPCF7931(0, tab
, l
, p
);
384 if ((parity
% 2) == 0)
385 AddBitPCF7931(0, tab
, l
, p
); //even parity
387 AddBitPCF7931(1, tab
, l
, p
);//odd parity
390 AddPatternPCF7931(5120+2680, 0, 0, tab
);
392 //conversion of the scale time
393 for (u
= 0; u
< 500; ++u
)
394 tab
[u
] = (tab
[u
] * 3) / 2;
396 //compennsation of the counter reload
399 for (u
= 0; tab
[u
] != 0; ++u
)
400 if(tab
[u
] > 0xFFFF) {
409 void BruteForcePCF7931(uint64_t password
, uint8_t tries
, uint16_t init_delay
, int32_t l
, int32_t p
) {
411 uint8_t pass_array
[7];
413 while (password
< 0x00FFFFFFFFFFFFFF) {
414 if (BUTTON_PRESS()) {
415 Dbprintf("Button pressed, stopping bruteforce ...");
419 num_to_bytes(password
, 7, pass_array
);
421 Dbprintf("Trying: %02x %02x %02x %02x %02x %02x %02x ...",
430 for (i
= 0; i
< tries
; ++i
)
446 /* Write on a byte of a PCF7931 tag
447 * @param address : address of the block to write
448 @param byte : address of the byte to write
449 @param data : data to write
451 void WritePCF7931(uint8_t pass1
, uint8_t pass2
, uint8_t pass3
, uint8_t pass4
, uint8_t pass5
, uint8_t pass6
, uint8_t pass7
, uint16_t init_delay
, int32_t l
, int32_t p
, uint8_t address
, uint8_t byte
, uint8_t data
) {
452 Dbprintf("Initialization delay : %d us", init_delay
);
453 Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l
, p
);
454 Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1
, pass2
, pass3
, pass4
, pass5
, pass6
, pass7
);
455 Dbprintf("Block address : %02x", address
);
456 Dbprintf("Byte address : %02x", byte
);
457 Dbprintf("Data : %02x", data
);
459 uint8_t password
[7] = {pass1
, pass2
, pass3
, pass4
, pass5
, pass6
, pass7
};
461 RealWritePCF7931 (password
, init_delay
, l
, p
, address
, byte
, data
);
466 /* Send a trame to a PCF7931 tags
467 * @param tab : array of the data frame
470 void SendCmdPCF7931(uint32_t * tab
) {
474 Dbprintf("Sending data frame ...");
476 FpgaDownloadAndGo(FPGA_BITSTREAM_LF
);
477 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, 95); //125Khz
478 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU
);
482 // steal this pin from the SSP and use it to control the modulation
483 AT91C_BASE_PIOA
->PIO_PER
= GPIO_SSC_DOUT
;
484 AT91C_BASE_PIOA
->PIO_OER
= GPIO_SSC_DOUT
;
486 //initialization of the timer
487 AT91C_BASE_PMC
->PMC_PCER
|= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
488 AT91C_BASE_TCB
->TCB_BMR
= AT91C_TCB_TC0XC0S_NONE
| AT91C_TCB_TC1XC1S_TIOA0
| AT91C_TCB_TC2XC2S_NONE
;
489 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKDIS
; // timer disable
490 AT91C_BASE_TC0
->TC_CMR
= AT91C_TC_CLKS_TIMER_DIV3_CLOCK
; //clock at 48/32 MHz
491 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKEN
;
492 AT91C_BASE_TCB
->TCB_BCR
= 1;
494 tempo
= AT91C_BASE_TC0
->TC_CV
;
495 for (u
= 0; tab
[u
] != 0; u
+= 3) {
498 while(tempo
!= tab
[u
])
499 tempo
= AT91C_BASE_TC0
->TC_CV
;
501 // stop modulating antenna
503 while(tempo
!= tab
[u
+1])
504 tempo
= AT91C_BASE_TC0
->TC_CV
;
508 while(tempo
!= tab
[u
+2])
509 tempo
= AT91C_BASE_TC0
->TC_CV
;
513 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
516 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKDIS
; // timer disable
517 DbpString("Data frame sent (multiple sends may be needed)");
522 /* Add a byte for building the data frame of PCF7931 tags
523 * @param b : byte to add
524 * @param tab : array of the data frame
525 * @param l : offset on low pulse width
526 * @param p : offset on low pulse positioning
528 bool AddBytePCF7931(uint8_t byte
, uint32_t * tab
, int32_t l
, int32_t p
) {
530 for (u
= 0; u
< 8; ++u
) {
531 if (byte
& (1 << u
)) { //bit is 1
532 if(AddBitPCF7931(1, tab
, l
, p
)==1)return 1;
534 if(AddBitPCF7931(0, tab
, l
, p
)==1)return 1;
541 /* Add a bits for building the data frame of PCF7931 tags
542 * @param b : bit to add
543 * @param tab : array of the data frame
544 * @param l : offset on low pulse width
545 * @param p : offset on low pulse positioning
547 bool AddBitPCF7931(bool b
, uint32_t * tab
, int32_t l
, int32_t p
) {
550 for (u
= 0; tab
[u
] != 0; u
+= 3){} //we put the cursor at the last value of the array
552 if (b
== 1) { //add a bit 1
553 if (u
== 0) tab
[u
] = 34 * T0_PCF
+ p
;
554 else tab
[u
] = 34 * T0_PCF
+ tab
[u
-1] + p
;
556 tab
[u
+1] = 6 * T0_PCF
+tab
[u
] + l
;
557 tab
[u
+2] = 88 * T0_PCF
+tab
[u
+ 1] - l
- p
;
559 } else { //add a bit 0
561 if (u
== 0) tab
[u
] = 98 * T0_PCF
+ p
;
562 else tab
[u
] = 98 * T0_PCF
+ tab
[u
-1] + p
;
564 tab
[u
+ 1] = 6 * T0_PCF
+ tab
[u
] + l
;
565 tab
[u
+ 2] = 24 * T0_PCF
+ tab
[u
+ 1] - l
- p
;
572 /* Add a custom pattern in the data frame
573 * @param a : delay of the first high pulse
574 * @param b : delay of the low pulse
575 * @param c : delay of the last high pulse
576 * @param tab : array of the data frame
578 bool AddPatternPCF7931(uint32_t a
, uint32_t b
, uint32_t c
, uint32_t * tab
) {
580 for(u
= 0; tab
[u
] != 0; u
+= 3){} //we put the cursor at the last value of the array
582 if (u
== 0) tab
[u
] = a
;
583 else tab
[u
] = a
+ tab
[u
- 1];
585 tab
[u
+ 1] = b
+ tab
[u
];
586 tab
[u
+ 2] = c
+ tab
[u
+ 1];