3 #include "lfsampling.h" 
   8 #define T0_PCF 8 //period for the pcf7931 in us 
  11 int DemodPCF7931(uint8_t **outBlocks
) { 
  13     uint8_t bits
[256] = {0x00}; 
  14         uint8_t blocks
[8][16]; 
  15     uint8_t *dest 
= BigBuf_get_addr(); 
  17         int GraphTraceLen 
= BigBuf_max_traceLen(); 
  18         if (  GraphTraceLen 
> 18000 ) 
  19                 GraphTraceLen 
= 18000; 
  22         int i
, j
, lastval
, bitidx
, half_switch
; 
  24         int tolerance 
= clock 
/ 8; 
  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
) 
  51                 while(i 
< GraphTraceLen
) { 
  52             if( !(dest
[i
] < dest
[i
-1]) && dest
[i
] < lmin
) 
  64         for (bitidx 
= 0; i 
< GraphTraceLen
; i
++) 
  66         if ( (dest
[i
-1] > dest
[i
] && dir 
== 1 && dest
[i
] > lmax
) || (dest
[i
-1] < dest
[i
] && dir 
== 0 && dest
[i
] < lmin
)) 
  71                         // Switch depending on lc length: 
  72                         // Tolerance is 1/8 of clock rate (arbitrary) 
  73                         if (ABS(lc
-clock
/4) < tolerance
) { 
  75                                 if((i 
- pmc
) == lc
) { /* 16T0 was previous one */ 
  77                                         i 
+= (128+127+16+32+33+16)-1; 
  85                         } else if (ABS(lc
-clock
/2) < tolerance
) { 
  87                                 if((i 
- pmc
) == lc
) { /* 16T0 was previous one */ 
  89                                         i 
+= (128+127+16+32+33)-1; 
  94                                 else if(half_switch 
== 1) { 
 100                         } else if (ABS(lc
-clock
) < tolerance
) { 
 108                                         Dbprintf("Error: too many detection errors, aborting."); 
 113                         if(block_done 
== 1) { 
 115                                         for(j
=0; j
<16; j
++) { 
 116                         blocks
[num_blocks
][j
] = 128*bits
[j
*8+7]+ 
 132                         if(i 
< GraphTraceLen
) 
 133                 dir 
=(dest
[i
-1] > dest
[i
]) ? 0 : 1; 
 138                 if(num_blocks 
== 4) break; 
 140     memcpy(outBlocks
, blocks
, 16*num_blocks
); 
 144 int IsBlock0PCF7931(uint8_t *Block
) { 
 145         // Assume RFU means 0 :) 
 146         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 
 148         if((memcmp(Block
+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block
[7] == 0) // PAC disabled, can it *really* happen ? 
 153 int IsBlock1PCF7931(uint8_t *Block
) { 
 154         // Assume RFU means 0 :) 
 155         if(Block
[10] == 0 && Block
[11] == 0 && Block
[12] == 0 && Block
[13] == 0) 
 156                 if((Block
[14] & 0x7f) <= 9 && Block
[15] <= 9) 
 163         uint8_t Blocks
[8][17]; 
 164         uint8_t tmpBlocks
[4][16]; 
 165         int i
, j
, ind
, ind2
, n
; 
 172         memset(Blocks
, 0, 8*17*sizeof(uint8_t)); 
 175                 memset(tmpBlocks
, 0, 4*16*sizeof(uint8_t)); 
 176                 n 
= DemodPCF7931((uint8_t**)tmpBlocks
); 
 179                 if(error
==10 && num_blocks 
== 0) { 
 180                         Dbprintf("Error, no tag or bad tag"); 
 183                 else if (tries
==20 || error
==10) { 
 184                         Dbprintf("Error reading the tag"); 
 185                         Dbprintf("Here is the partial content"); 
 190                         Dbprintf("(dbg) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", 
 191                                          tmpBlocks
[i
][0], tmpBlocks
[i
][1], tmpBlocks
[i
][2], tmpBlocks
[i
][3], tmpBlocks
[i
][4], tmpBlocks
[i
][5], tmpBlocks
[i
][6], tmpBlocks
[i
][7], 
 192                                         tmpBlocks
[i
][8], tmpBlocks
[i
][9], tmpBlocks
[i
][10], tmpBlocks
[i
][11], tmpBlocks
[i
][12], tmpBlocks
[i
][13], tmpBlocks
[i
][14], tmpBlocks
[i
][15]); 
 195                                 if(IsBlock0PCF7931(tmpBlocks
[i
])) { 
 197                                         if(i 
< n
-1 && IsBlock1PCF7931(tmpBlocks
[i
+1])) { 
 201                                                 memcpy(Blocks
[0], tmpBlocks
[i
], 16); 
 202                                                 Blocks
[0][ALLOC
] = 1; 
 203                                                 memcpy(Blocks
[1], tmpBlocks
[i
+1], 16); 
 204                                                 Blocks
[1][ALLOC
] = 1; 
 205                                                 max_blocks 
= MAX((Blocks
[1][14] & 0x7f), Blocks
[1][15]) + 1; 
 207                                                 Dbprintf("(dbg) Max blocks: %d", max_blocks
); 
 209                                                 // Handle following blocks 
 210                                                 for(j
=i
+2, ind2
=2; j
!=i
; j
++, ind2
++, num_blocks
++) { 
 213                                                         memcpy(Blocks
[ind2
], tmpBlocks
[j
], 16); 
 214                                                         Blocks
[ind2
][ALLOC
] = 1; 
 222                         for(i
=0; i
<n
; i
++) { // Look for identical block in known blocks 
 223                                 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 
 224                                         for(j
=0; j
<max_blocks
; j
++) { 
 225                                                 if(Blocks
[j
][ALLOC
] == 1 && !memcmp(tmpBlocks
[i
], Blocks
[j
], 16)) { 
 226                                                         // Found an identical block 
 227                                                         for(ind
=i
-1,ind2
=j
-1; ind 
>= 0; ind
--,ind2
--) { 
 230                                                                 if(!Blocks
[ind2
][ALLOC
]) { // Block ind2 not already found 
 231                                                                         // Dbprintf("Tmp %d -> Block %d", ind, ind2); 
 232                                                                         memcpy(Blocks
[ind2
], tmpBlocks
[ind
], 16); 
 233                                                                         Blocks
[ind2
][ALLOC
] = 1; 
 235                                                                         if(num_blocks 
== max_blocks
) goto end
; 
 238                                                         for(ind
=i
+1,ind2
=j
+1; ind 
< n
; ind
++,ind2
++) { 
 239                                                                 if(ind2 
> max_blocks
) 
 241                                                                 if(!Blocks
[ind2
][ALLOC
]) { // Block ind2 not already found 
 242                                                                         // Dbprintf("Tmp %d -> Block %d", ind, ind2); 
 243                                                                         memcpy(Blocks
[ind2
], tmpBlocks
[ind
], 16); 
 244                                                                         Blocks
[ind2
][ALLOC
] = 1; 
 246                                                                         if(num_blocks 
== max_blocks
) goto end
; 
 255                 if (BUTTON_PRESS()) return; 
 256         } while (num_blocks 
!= max_blocks
); 
 258         Dbprintf("-----------------------------------------"); 
 259         Dbprintf("Memory content:"); 
 260         Dbprintf("-----------------------------------------"); 
 261         for(i
=0; i
<max_blocks
; i
++) { 
 262                 if(Blocks
[i
][ALLOC
]==1) 
 263                         Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", 
 264                                          Blocks
[i
][0], Blocks
[i
][1], Blocks
[i
][2], Blocks
[i
][3], Blocks
[i
][4], Blocks
[i
][5], Blocks
[i
][6], Blocks
[i
][7], 
 265                                         Blocks
[i
][8], Blocks
[i
][9], Blocks
[i
][10], Blocks
[i
][11], Blocks
[i
][12], Blocks
[i
][13], Blocks
[i
][14], Blocks
[i
][15]); 
 267                         Dbprintf("<missing block %d>", i
); 
 269         Dbprintf("-----------------------------------------"); 
 271         cmd_send(CMD_ACK
,0,0,0,0,0); 
 275 /* Write on a byte of a PCF7931 tag 
 276  * @param address : address of the block to write 
 277    @param byte : address of the byte to write 
 278     @param data : data to write 
 280 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
) 
 283         uint32_t tab
[1024]={0}; // data times frame 
 288         //BUILD OF THE DATA FRAME 
 290         //alimentation of the tag (time for initializing) 
 291         AddPatternPCF7931(init_delay
, 0, 8192/2*T0_PCF
, tab
); 
 294         Dbprintf("Initialization delay : %d us", init_delay
); 
 295         AddPatternPCF7931(8192/2*T0_PCF 
+ 319*T0_PCF
+70, 3*T0_PCF
, 29*T0_PCF
, tab
); 
 297         Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l
, p
); 
 299         //password indication bit 
 300         AddBitPCF7931(1, tab
, l
, p
); 
 303         //password (on 56 bits) 
 304         Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1
,pass2
,pass3
,pass4
,pass5
,pass6
,pass7
); 
 305         AddBytePCF7931(pass1
, tab
, l
, p
); 
 306         AddBytePCF7931(pass2
, tab
, l
, p
); 
 307         AddBytePCF7931(pass3
, tab
, l
, p
); 
 308         AddBytePCF7931(pass4
, tab
, l
, p
); 
 309         AddBytePCF7931(pass5
, tab
, l
, p
); 
 310         AddBytePCF7931(pass6
, tab
, l
, p
); 
 311         AddBytePCF7931(pass7
, tab
, l
, p
); 
 313         //programming mode (0 or 1) 
 314         AddBitPCF7931(0, tab
, l
, p
); 
 316         //block adress on 6 bits 
 317         Dbprintf("Block address : %02x", address
); 
 320                 if (address
&(1<<u
)) {   // bit 1 
 322                          AddBitPCF7931(1, tab
, l
, p
); 
 324                          AddBitPCF7931(0, tab
, l
, p
); 
 328         //byte address on 4 bits 
 329         Dbprintf("Byte address : %02x", byte
); 
 332                 if (byte
&(1<<u
)) {      // bit 1 
 334                          AddBitPCF7931(1, tab
, l
, p
); 
 336                          AddBitPCF7931(0, tab
, l
, p
); 
 341         Dbprintf("Data : %02x", data
); 
 344                 if (data
&(1<<u
)) {      // bit 1 
 346                          AddBitPCF7931(1, tab
, l
, p
); 
 348                          AddBitPCF7931(0, tab
, l
, p
); 
 355                 AddBitPCF7931(0, tab
, l
, p
); //even parity 
 357                 AddBitPCF7931(1, tab
, l
, p
);//odd parity 
 361         AddPatternPCF7931(5120+2680, 0, 0, tab
); 
 363         //conversion of the scale time 
 365                 tab
[u
]=(tab
[u
] * 3)/2; 
 369         //compennsation of the counter reload 
 372                 for(u
=0;tab
[u
]!=0;u
++){ 
 385 /* Send a trame to a PCF7931 tags 
 386  * @param tab : array of the data frame 
 389 void SendCmdPCF7931(uint32_t * tab
){ 
 393         Dbprintf("SENDING DATA FRAME..."); 
 395         FpgaDownloadAndGo(FPGA_BITSTREAM_LF
); 
 397         FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, 95); //125Khz 
 399         FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU 
); 
 403         // steal this pin from the SSP and use it to control the modulation 
 404         AT91C_BASE_PIOA
->PIO_PER 
= GPIO_SSC_DOUT
; 
 405         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_SSC_DOUT
; 
 407         //initialization of the timer 
 408         AT91C_BASE_PMC
->PMC_PCER 
|= (0x1 << 12) | (0x1 << 13) | (0x1 << 14); 
 409         AT91C_BASE_TCB
->TCB_BMR 
= AT91C_TCB_TC0XC0S_NONE 
| AT91C_TCB_TC1XC1S_TIOA0 
| AT91C_TCB_TC2XC2S_NONE
; 
 410         AT91C_BASE_TC0
->TC_CCR 
= AT91C_TC_CLKDIS
; // timer disable 
 411         AT91C_BASE_TC0
->TC_CMR 
= AT91C_TC_CLKS_TIMER_DIV3_CLOCK
;  //clock at 48/32 MHz 
 412         AT91C_BASE_TC0
->TC_CCR 
= AT91C_TC_CLKEN
; 
 413         AT91C_BASE_TCB
->TCB_BCR 
= 1; 
 416         tempo 
= AT91C_BASE_TC0
->TC_CV
; 
 417         for(u
=0;tab
[u
]!= 0;u
+=3){ 
 422                 while(tempo 
!=  tab
[u
]){ 
 423                         tempo 
= AT91C_BASE_TC0
->TC_CV
; 
 426                 // stop modulating antenna 
 428                 while(tempo 
!=  tab
[u
+1]){ 
 429                         tempo 
= AT91C_BASE_TC0
->TC_CV
; 
 435                 while(tempo 
!=  tab
[u
+2]){ 
 436                         tempo 
= AT91C_BASE_TC0
->TC_CV
; 
 443         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 447         AT91C_BASE_TC0
->TC_CCR 
= AT91C_TC_CLKDIS
; // timer disable 
 448         DbpString("FINISH !"); 
 449         DbpString("(Could be usefull to send the same trame many times)"); 
 454 /* Add a byte for building the data frame of PCF7931 tags  
 455  * @param b : byte to add 
 456  * @param tab : array of the data frame 
 457  * @param l : offset on low pulse width 
 458  * @param p : offset on low pulse positioning 
 461 bool AddBytePCF7931(uint8_t byte
, uint32_t * tab
, int32_t l
, int32_t p
){ 
 466                 if (byte
&(1<<u
)) {      //bit à 1 
 467                         if(AddBitPCF7931(1, tab
, l
, p
)==1)return 1; 
 469                         if(AddBitPCF7931(0, tab
, l
, p
)==1)return 1; 
 476 /* Add a bits for building the data frame of PCF7931 tags  
 477  * @param b : bit to add 
 478  * @param tab : array of the data frame 
 479  * @param l : offset on low pulse width 
 480  * @param p : offset on low pulse positioning 
 482 bool AddBitPCF7931(bool b
, uint32_t * tab
, int32_t l
, int32_t p
){ 
 485         for(u
=0;tab
[u
]!=0;u
+=3){} //we put the cursor at the last value of the array 
 488         if(b
==1){       //add a bit 1 
 489                 if(u
==0) tab
[u
] = 34*T0_PCF
+p
; 
 490                 else     tab
[u
] = 34*T0_PCF
+tab
[u
-1]+p
; 
 492                 tab
[u
+1] = 6*T0_PCF
+tab
[u
]+l
; 
 493                 tab
[u
+2] = 88*T0_PCF
+tab
[u
+1]-l
-p
; 
 497                 if(u
==0) tab
[u
] = 98*T0_PCF
+p
; 
 498                 else     tab
[u
] = 98*T0_PCF
+tab
[u
-1]+p
; 
 500                 tab
[u
+1] = 6*T0_PCF
+tab
[u
]+l
; 
 501                 tab
[u
+2] = 24*T0_PCF
+tab
[u
+1]-l
-p
; 
 509 /* Add a custom pattern in the data frame 
 510  * @param a : delay of the first high pulse 
 511  * @param b : delay of the low pulse 
 512  * @param c : delay of the last high pulse 
 513  * @param tab : array of the data frame 
 515 bool AddPatternPCF7931(uint32_t a
, uint32_t b
, uint32_t c
, uint32_t * tab
){ 
 517         for(u
=0;tab
[u
]!=0;u
+=3){} //we put the cursor at the last value of the array 
 520         else tab
[u
] = a 
+ tab
[u
-1]; 
 523         tab
[u
+2] = c
+tab
[u
+1];