3 #include "lfsampling.h" 
   7 #define T0_PCF 8 //period for the pcf7931 in us 
  10 int DemodPCF7931(uint8_t **outBlocks
) { 
  12     uint8_t bits
[256] = {0x00}; 
  13         uint8_t blocks
[8][16]; 
  14     uint8_t *dest 
= BigBuf_get_addr(); 
  16         int GraphTraceLen 
= BigBuf_max_traceLen(); 
  17         if (  GraphTraceLen 
> 18000 ) 
  18                 GraphTraceLen 
= 18000; 
  20         int i
, j
, lastval
, bitidx
, half_switch
; 
  22         int tolerance 
= clock 
/ 8; 
  26         int lmin
=128, lmax
=128; 
  29         BigBuf_Clear_keep_EM(); 
  31         LFSetupFPGAForADC(95, true); 
  32         DoAcquisition_default(0, true); 
  39         /* Find first local max/min */ 
  40     if(dest
[1] > dest
[0]) { 
  41                 while(i 
< GraphTraceLen
) { 
  42             if( !(dest
[i
] > dest
[i
-1]) && dest
[i
] > lmax
) 
  49                 while(i 
< GraphTraceLen
) { 
  50             if( !(dest
[i
] < dest
[i
-1]) && dest
[i
] < lmin
) 
  62         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
)) 
  69                         // Switch depending on lc length: 
  70                         // Tolerance is 1/8 of clock rate (arbitrary) 
  71                         if (ABS(lc
-clock
/4) < tolerance
) { 
  73                                 if((i 
- pmc
) == lc
) { /* 16T0 was previous one */ 
  75                                         i 
+= (128+127+16+32+33+16)-1; 
  83                         } else if (ABS(lc
-clock
/2) < tolerance
) { 
  85                                 if((i 
- pmc
) == lc
) { /* 16T0 was previous one */ 
  87                                         i 
+= (128+127+16+32+33)-1; 
  92                                 else if(half_switch 
== 1) { 
  98                         } else if (ABS(lc
-clock
) < tolerance
) { 
 106                                         Dbprintf("Error: too many detection errors, aborting."); 
 111                         if(block_done 
== 1) { 
 113                                         for(j
=0; j
<16; j
++) { 
 114                         blocks
[num_blocks
][j
] = 128*bits
[j
*8+7]+ 
 130                         if(i 
< GraphTraceLen
) 
 131                 dir 
=(dest
[i
-1] > dest
[i
]) ? 0 : 1; 
 136                 if(num_blocks 
== 4) break; 
 138     memcpy(outBlocks
, blocks
, 16*num_blocks
); 
 142 int IsBlock0PCF7931(uint8_t *Block
) { 
 143         // Assume RFU means 0 :) 
 144         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 
 146         if((memcmp(Block
+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block
[7] == 0) // PAC disabled, can it *really* happen ? 
 151 int IsBlock1PCF7931(uint8_t *Block
) { 
 152         // Assume RFU means 0 :) 
 153         if( Block
[10] == 0 &&  
 157                  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
) 
 282         uint32_t tab
[1024] = {0}; // data times frame 
 287         //BUILD OF THE DATA FRAME 
 289         //alimentation of the tag (time for initializing) 
 290         AddPatternPCF7931(init_delay
, 0, 8192/2*T0_PCF
, tab
); 
 293         Dbprintf("Initialization delay : %d us", init_delay
); 
 294         AddPatternPCF7931(8192/2*T0_PCF 
+ 319*T0_PCF
+70, 3*T0_PCF
, 29*T0_PCF
, tab
); 
 296         Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l
, p
); 
 298         //password indication bit 
 299         AddBitPCF7931(1, tab
, l
, p
); 
 301         //password (on 56 bits) 
 302         Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1
,pass2
,pass3
,pass4
,pass5
,pass6
,pass7
); 
 303         AddBytePCF7931(pass1
, tab
, l
, p
); 
 304         AddBytePCF7931(pass2
, tab
, l
, p
); 
 305         AddBytePCF7931(pass3
, tab
, l
, p
); 
 306         AddBytePCF7931(pass4
, tab
, l
, p
); 
 307         AddBytePCF7931(pass5
, tab
, l
, p
); 
 308         AddBytePCF7931(pass6
, tab
, l
, p
); 
 309         AddBytePCF7931(pass7
, tab
, l
, p
); 
 312         //programming mode (0 or 1) 
 313         AddBitPCF7931(0, tab
, l
, p
); 
 315         //block adress on 6 bits 
 316         Dbprintf("Block address : %02x", address
); 
 319                 if (address
&(1<<u
)) {   // bit 1 
 321                          AddBitPCF7931(1, tab
, l
, p
); 
 323                          AddBitPCF7931(0, tab
, l
, p
); 
 327         //byte address on 4 bits 
 328         Dbprintf("Byte address : %02x", byte
); 
 331                 if (byte
&(1<<u
)) {      // bit 1 
 333                          AddBitPCF7931(1, tab
, l
, p
); 
 335                          AddBitPCF7931(0, tab
, l
, p
); 
 340         Dbprintf("Data : %02x", data
); 
 343                 if (data
&(1<<u
)) {      // bit 1 
 345                          AddBitPCF7931(1, tab
, l
, p
); 
 347                          AddBitPCF7931(0, tab
, l
, p
); 
 354                 AddBitPCF7931(0, tab
, l
, p
); //even parity 
 356                 AddBitPCF7931(1, tab
, l
, p
);//odd parity 
 360         AddPatternPCF7931(5120+2680, 0, 0, tab
); 
 362         //conversion of the scale time 
 364                 tab
[u
]=(tab
[u
] * 3)/2; 
 367         //compensation of the counter reload 
 370                 for(u
=0;tab
[u
]!=0;u
++){ 
 383 /* Send a trame to a PCF7931 tags 
 384  * @param tab : array of the data frame 
 387 void SendCmdPCF7931(uint32_t * tab
){ 
 388         uint16_t u
=0, tempo
=0; 
 390         Dbprintf("Sending data frame..."); 
 392         FpgaDownloadAndGo(FPGA_BITSTREAM_LF
); 
 394         FpgaSendCommand(FPGA_CMD_SET_DIVISOR
, 95); //125Khz 
 396         FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU 
); 
 400         // steal this pin from the SSP and use it to control the modulation 
 401         AT91C_BASE_PIOA
->PIO_PER 
= GPIO_SSC_DOUT
; 
 402         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_SSC_DOUT
; 
 404         //initialization of the timer 
 405         AT91C_BASE_PMC
->PMC_PCER 
|= (0x1 << AT91C_ID_TC0
); 
 406         AT91C_BASE_TCB
->TCB_BMR 
= AT91C_TCB_TC0XC0S_NONE 
| AT91C_TCB_TC1XC1S_TIOA0 
| AT91C_TCB_TC2XC2S_NONE
; 
 407         AT91C_BASE_TC0
->TC_CCR 
= AT91C_TC_CLKDIS
; // timer disable 
 408         AT91C_BASE_TC0
->TC_CMR 
= AT91C_TC_CLKS_TIMER_DIV3_CLOCK
;  //clock at 48/32 MHz 
 409         AT91C_BASE_TC0
->TC_CCR 
= AT91C_TC_CLKEN
; 
 410         AT91C_BASE_TCB
->TCB_BCR 
= 1; 
 413         tempo 
= AT91C_BASE_TC0
->TC_CV
; 
 414         for( u 
= 0; tab
[u
] != 0; u 
+= 3){ 
 418                 while(tempo 
!= tab
[u
]) tempo 
= AT91C_BASE_TC0
->TC_CV
;            
 420                 // stop modulating antenna 
 422                 while(tempo 
!= tab
[u
+1]) tempo 
= AT91C_BASE_TC0
->TC_CV
; 
 426                 while(tempo 
!= tab
[u
+2]) tempo 
= AT91C_BASE_TC0
->TC_CV
;          
 430         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 433         AT91C_BASE_TC0
->TC_CCR 
= AT91C_TC_CLKDIS
; // timer disable 
 438 /* Add a byte for building the data frame of PCF7931 tags  
 439  * @param b : byte to add 
 440  * @param tab : array of the data frame 
 441  * @param l : offset on low pulse width 
 442  * @param p : offset on low pulse positioning 
 445 bool AddBytePCF7931(uint8_t byte
, uint32_t * tab
, int32_t l
, int32_t p
){ 
 450                 if (byte
&(1<<u
)) {      //bit à 1 
 451                         if( AddBitPCF7931(1, tab
, l
, p
)==1) return 1; 
 453                         if (AddBitPCF7931(0, tab
, l
, p
)==1) return 1; 
 459 /* Add a bits for building the data frame of PCF7931 tags  
 460  * @param b : bit to add 
 461  * @param tab : array of the data frame 
 462  * @param l : offset on low pulse width 
 463  * @param p : offset on low pulse positioning 
 465 bool AddBitPCF7931(bool b
, uint32_t * tab
, int32_t l
, int32_t p
){ 
 468         //we put the cursor at the last value of the array 
 469         for ( u 
= 0; tab
[u
] != 0; u 
+= 3 ) { }  
 471         if ( b 
== 1 ) { //add a bit 1 
 473                         tab
[u
] = 34 * T0_PCF 
+ p
; 
 475                         tab
[u
] = 34 * T0_PCF 
+ tab
[u
-1] + p
; 
 477                 tab
[u
+1] =  6 * T0_PCF 
+ tab
[u
] + l
; 
 478                 tab
[u
+2] = 88 * T0_PCF 
+ tab
[u
+1] - l 
- p
; 
 480         } else {                //add a bit 0 
 483                         tab
[u
] = 98 * T0_PCF 
+ p
; 
 485                         tab
[u
] = 98 * T0_PCF 
+ tab
[u
-1] + p
; 
 487                 tab
[u
+1] =  6 * T0_PCF 
+ tab
[u
] + l
; 
 488                 tab
[u
+2] = 24 * T0_PCF 
+ tab
[u
+1] - l 
- p
; 
 494 /* Add a custom pattern in the data frame 
 495  * @param a : delay of the first high pulse 
 496  * @param b : delay of the low pulse 
 497  * @param c : delay of the last high pulse 
 498  * @param tab : array of the data frame 
 500 bool AddPatternPCF7931(uint32_t a
, uint32_t b
, uint32_t c
, uint32_t * tab
){ 
 502         for(u 
= 0; tab
[u
] != 0; u 
+= 3){} //we put the cursor at the last value of the array 
 504         tab
[u
]   = (u 
== 0) ? a 
: a 
+ tab
[u
-1]; 
 505         tab
[u
+1] = b 
+ tab
[u
]; 
 506         tab
[u
+2] = c 
+ tab
[u
+1];