3 #include "lfsampling.h"
7 #define T0_PCF 8 //period for the pcf7931 in us
10 #define abs(x) ( ((x)<0) ? -(x) : (x) )
11 #define max(x,y) ( x<y ? y:x)
13 int DemodPCF7931(uint8_t **outBlocks
) {
15 uint8_t bits
[256] = {0x00};
16 uint8_t blocks
[8][16];
17 uint8_t *dest
= BigBuf_get_addr();
19 int GraphTraceLen
= BigBuf_max_traceLen();
20 if ( GraphTraceLen
> 18000 )
21 GraphTraceLen
= 18000;
24 int i
, j
, lastval
, bitidx
, half_switch
;
26 int tolerance
= clock
/ 8;
30 int lmin
=128, lmax
=128;
33 BigBuf_Clear_keep_EM();
35 LFSetupFPGAForADC(95, true);
36 DoAcquisition_default(0, true);
43 /* Find first local max/min */
44 if(dest
[1] > dest
[0]) {
45 while(i
< GraphTraceLen
) {
46 if( !(dest
[i
] > dest
[i
-1]) && dest
[i
] > lmax
)
53 while(i
< GraphTraceLen
) {
54 if( !(dest
[i
] < dest
[i
-1]) && dest
[i
] < lmin
)
66 for (bitidx
= 0; i
< GraphTraceLen
; i
++)
68 if ( (dest
[i
-1] > dest
[i
] && dir
== 1 && dest
[i
] > lmax
) || (dest
[i
-1] < dest
[i
] && dir
== 0 && dest
[i
] < lmin
))
73 // Switch depending on lc length:
74 // Tolerance is 1/8 of clock rate (arbitrary)
75 if (abs(lc
-clock
/4) < tolerance
) {
77 if((i
- pmc
) == lc
) { /* 16T0 was previous one */
79 i
+= (128+127+16+32+33+16)-1;
87 } else if (abs(lc
-clock
/2) < tolerance
) {
89 if((i
- pmc
) == lc
) { /* 16T0 was previous one */
91 i
+= (128+127+16+32+33)-1;
96 else if(half_switch
== 1) {
102 } else if (abs(lc
-clock
) < tolerance
) {
110 Dbprintf("Error: too many detection errors, aborting.");
115 if(block_done
== 1) {
117 for(j
=0; j
<16; j
++) {
118 blocks
[num_blocks
][j
] = 128*bits
[j
*8+7]+
134 if(i
< GraphTraceLen
)
135 dir
=(dest
[i
-1] > dest
[i
]) ? 0 : 1;
140 if(num_blocks
== 4) break;
142 memcpy(outBlocks
, blocks
, 16*num_blocks
);
146 int IsBlock0PCF7931(uint8_t *Block
) {
147 // Assume RFU means 0 :)
148 if((memcmp(Block
, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block
+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled
150 if((memcmp(Block
+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block
[7] == 0) // PAC disabled, can it *really* happen ?
155 int IsBlock1PCF7931(uint8_t *Block
) {
156 // Assume RFU means 0 :)
157 if(Block
[10] == 0 && Block
[11] == 0 && Block
[12] == 0 && Block
[13] == 0)
158 if((Block
[14] & 0x7f) <= 9 && Block
[15] <= 9)
165 uint8_t Blocks
[8][17];
166 uint8_t tmpBlocks
[4][16];
167 int i
, j
, ind
, ind2
, n
;
174 memset(Blocks
, 0, 8*17*sizeof(uint8_t));
177 memset(tmpBlocks
, 0, 4*16*sizeof(uint8_t));
178 n
= DemodPCF7931((uint8_t**)tmpBlocks
);
181 if(error
==10 && num_blocks
== 0) {
182 Dbprintf("Error, no tag or bad tag");
185 else if (tries
==20 || error
==10) {
186 Dbprintf("Error reading the tag");
187 Dbprintf("Here is the partial content");
192 Dbprintf("(dbg) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
193 tmpBlocks
[i
][0], tmpBlocks
[i
][1], tmpBlocks
[i
][2], tmpBlocks
[i
][3], tmpBlocks
[i
][4], tmpBlocks
[i
][5], tmpBlocks
[i
][6], tmpBlocks
[i
][7],
194 tmpBlocks
[i
][8], tmpBlocks
[i
][9], tmpBlocks
[i
][10], tmpBlocks
[i
][11], tmpBlocks
[i
][12], tmpBlocks
[i
][13], tmpBlocks
[i
][14], tmpBlocks
[i
][15]);
197 if(IsBlock0PCF7931(tmpBlocks
[i
])) {
199 if(i
< n
-1 && IsBlock1PCF7931(tmpBlocks
[i
+1])) {
203 memcpy(Blocks
[0], tmpBlocks
[i
], 16);
204 Blocks
[0][ALLOC
] = 1;
205 memcpy(Blocks
[1], tmpBlocks
[i
+1], 16);
206 Blocks
[1][ALLOC
] = 1;
207 max_blocks
= max((Blocks
[1][14] & 0x7f), Blocks
[1][15]) + 1;
209 Dbprintf("(dbg) Max blocks: %d", max_blocks
);
211 // Handle following blocks
212 for(j
=i
+2, ind2
=2; j
!=i
; j
++, ind2
++, num_blocks
++) {
215 memcpy(Blocks
[ind2
], tmpBlocks
[j
], 16);
216 Blocks
[ind2
][ALLOC
] = 1;
224 for(i
=0; i
<n
; i
++) { // Look for identical block in known blocks
225 if(memcmp(tmpBlocks
[i
], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { // Block is not full of 00
226 for(j
=0; j
<max_blocks
; j
++) {
227 if(Blocks
[j
][ALLOC
] == 1 && !memcmp(tmpBlocks
[i
], Blocks
[j
], 16)) {
228 // Found an identical block
229 for(ind
=i
-1,ind2
=j
-1; ind
>= 0; ind
--,ind2
--) {
232 if(!Blocks
[ind2
][ALLOC
]) { // Block ind2 not already found
233 // Dbprintf("Tmp %d -> Block %d", ind, ind2);
234 memcpy(Blocks
[ind2
], tmpBlocks
[ind
], 16);
235 Blocks
[ind2
][ALLOC
] = 1;
237 if(num_blocks
== max_blocks
) goto end
;
240 for(ind
=i
+1,ind2
=j
+1; ind
< n
; ind
++,ind2
++) {
241 if(ind2
> max_blocks
)
243 if(!Blocks
[ind2
][ALLOC
]) { // Block ind2 not already found
244 // Dbprintf("Tmp %d -> Block %d", ind, ind2);
245 memcpy(Blocks
[ind2
], tmpBlocks
[ind
], 16);
246 Blocks
[ind2
][ALLOC
] = 1;
248 if(num_blocks
== max_blocks
) goto end
;
257 if (BUTTON_PRESS()) return;
258 } while (num_blocks
!= max_blocks
);
260 Dbprintf("-----------------------------------------");
261 Dbprintf("Memory content:");
262 Dbprintf("-----------------------------------------");
263 for(i
=0; i
<max_blocks
; i
++) {
264 if(Blocks
[i
][ALLOC
]==1)
265 Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
266 Blocks
[i
][0], Blocks
[i
][1], Blocks
[i
][2], Blocks
[i
][3], Blocks
[i
][4], Blocks
[i
][5], Blocks
[i
][6], Blocks
[i
][7],
267 Blocks
[i
][8], Blocks
[i
][9], Blocks
[i
][10], Blocks
[i
][11], Blocks
[i
][12], Blocks
[i
][13], Blocks
[i
][14], Blocks
[i
][15]);
269 Dbprintf("<missing block %d>", i
);
271 Dbprintf("-----------------------------------------");
273 cmd_send(CMD_ACK
,0,0,0,0,0);
277 /* Write on a byte of a PCF7931 tag
278 * @param address : address of the block to write
279 @param byte : address of the byte to write
280 @param data : data to write
282 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
)
285 uint32_t tab
[1024]={0}; // data times frame
290 //BUILD OF THE DATA FRAME
292 //alimentation of the tag (time for initializing)
293 AddPatternPCF7931(init_delay
, 0, 8192/2*T0_PCF
, tab
);
296 Dbprintf("Initialization delay : %d us", init_delay
);
297 AddPatternPCF7931(8192/2*T0_PCF
+ 319*T0_PCF
+70, 3*T0_PCF
, 29*T0_PCF
, tab
);
299 Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l
, p
);
301 //password indication bit
302 AddBitPCF7931(1, tab
, l
, p
);
305 //password (on 56 bits)
306 Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1
,pass2
,pass3
,pass4
,pass5
,pass6
,pass7
);
307 AddBytePCF7931(pass1
, tab
, l
, p
);
308 AddBytePCF7931(pass2
, tab
, l
, p
);
309 AddBytePCF7931(pass3
, tab
, l
, p
);
310 AddBytePCF7931(pass4
, tab
, l
, p
);
311 AddBytePCF7931(pass5
, tab
, l
, p
);
312 AddBytePCF7931(pass6
, tab
, l
, p
);
313 AddBytePCF7931(pass7
, tab
, l
, p
);
315 //programming mode (0 or 1)
316 AddBitPCF7931(0, tab
, l
, p
);
318 //block adress on 6 bits
319 Dbprintf("Block address : %02x", address
);
322 if (address
&(1<<u
)) { // bit 1
324 AddBitPCF7931(1, tab
, l
, p
);
326 AddBitPCF7931(0, tab
, l
, p
);
330 //byte address on 4 bits
331 Dbprintf("Byte address : %02x", byte
);
334 if (byte
&(1<<u
)) { // bit 1
336 AddBitPCF7931(1, tab
, l
, p
);
338 AddBitPCF7931(0, tab
, l
, p
);
343 Dbprintf("Data : %02x", data
);
346 if (data
&(1<<u
)) { // bit 1
348 AddBitPCF7931(1, tab
, l
, p
);
350 AddBitPCF7931(0, tab
, l
, p
);
357 AddBitPCF7931(0, tab
, l
, p
); //even parity
359 AddBitPCF7931(1, tab
, l
, p
);//odd parity
363 AddPatternPCF7931(5120+2680, 0, 0, tab
);
365 //conversion of the scale time
367 tab
[u
]=(tab
[u
] * 3)/2;
371 //compennsation of the counter reload
374 for(u
=0;tab
[u
]!=0;u
++){
387 /* Send a trame to a PCF7931 tags
388 * @param tab : array of the data frame
391 void SendCmdPCF7931(uint32_t * tab
){
395 Dbprintf("SENDING DATA FRAME...");
397 FpgaDownloadAndGo(FPGA_BITSTREAM_LF
);
399 FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, 95); //125Khz
401 FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU
);
405 // steal this pin from the SSP and use it to control the modulation
406 AT91C_BASE_PIOA
->PIO_PER
= GPIO_SSC_DOUT
;
407 AT91C_BASE_PIOA
->PIO_OER
= GPIO_SSC_DOUT
;
409 //initialization of the timer
410 AT91C_BASE_PMC
->PMC_PCER
|= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
411 AT91C_BASE_TCB
->TCB_BMR
= AT91C_TCB_TC0XC0S_NONE
| AT91C_TCB_TC1XC1S_TIOA0
| AT91C_TCB_TC2XC2S_NONE
;
412 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKDIS
; // timer disable
413 AT91C_BASE_TC0
->TC_CMR
= AT91C_TC_CLKS_TIMER_DIV3_CLOCK
; //clock at 48/32 MHz
414 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKEN
;
415 AT91C_BASE_TCB
->TCB_BCR
= 1;
418 tempo
= AT91C_BASE_TC0
->TC_CV
;
419 for(u
=0;tab
[u
]!= 0;u
+=3){
424 while(tempo
!= tab
[u
]){
425 tempo
= AT91C_BASE_TC0
->TC_CV
;
428 // stop modulating antenna
430 while(tempo
!= tab
[u
+1]){
431 tempo
= AT91C_BASE_TC0
->TC_CV
;
437 while(tempo
!= tab
[u
+2]){
438 tempo
= AT91C_BASE_TC0
->TC_CV
;
445 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
449 AT91C_BASE_TC0
->TC_CCR
= AT91C_TC_CLKDIS
; // timer disable
450 DbpString("FINISH !");
451 DbpString("(Could be usefull to send the same trame many times)");
456 /* Add a byte for building the data frame of PCF7931 tags
457 * @param b : byte to add
458 * @param tab : array of the data frame
459 * @param l : offset on low pulse width
460 * @param p : offset on low pulse positioning
463 bool AddBytePCF7931(uint8_t byte
, uint32_t * tab
, int32_t l
, int32_t p
){
468 if (byte
&(1<<u
)) { //bit à 1
469 if(AddBitPCF7931(1, tab
, l
, p
)==1)return 1;
471 if(AddBitPCF7931(0, tab
, l
, p
)==1)return 1;
478 /* Add a bits for building the data frame of PCF7931 tags
479 * @param b : bit to add
480 * @param tab : array of the data frame
481 * @param l : offset on low pulse width
482 * @param p : offset on low pulse positioning
484 bool AddBitPCF7931(bool b
, uint32_t * tab
, int32_t l
, int32_t p
){
487 for(u
=0;tab
[u
]!=0;u
+=3){} //we put the cursor at the last value of the array
490 if(b
==1){ //add a bit 1
491 if(u
==0) tab
[u
] = 34*T0_PCF
+p
;
492 else tab
[u
] = 34*T0_PCF
+tab
[u
-1]+p
;
494 tab
[u
+1] = 6*T0_PCF
+tab
[u
]+l
;
495 tab
[u
+2] = 88*T0_PCF
+tab
[u
+1]-l
-p
;
499 if(u
==0) tab
[u
] = 98*T0_PCF
+p
;
500 else tab
[u
] = 98*T0_PCF
+tab
[u
-1]+p
;
502 tab
[u
+1] = 6*T0_PCF
+tab
[u
]+l
;
503 tab
[u
+2] = 24*T0_PCF
+tab
[u
+1]-l
-p
;
511 /* Add a custom pattern in the data frame
512 * @param a : delay of the first high pulse
513 * @param b : delay of the low pulse
514 * @param c : delay of the last high pulse
515 * @param tab : array of the data frame
517 bool AddPatternPCF7931(uint32_t a
, uint32_t b
, uint32_t c
, uint32_t * tab
){
519 for(u
=0;tab
[u
]!=0;u
+=3){} //we put the cursor at the last value of the array
522 else tab
[u
] = a
+ tab
[u
-1];
525 tab
[u
+2] = c
+tab
[u
+1];