X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/8e21541e77dd0909a99a1ed1106a6df87d34a247..fa0503b03f06bc917b5dcb00d08334cc9c3c68dc:/armsrc/lfops.c diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 733bc953..d7f91c53 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -16,8 +16,7 @@ #include "string.h" #include "lfdemod.h" #include "lfsampling.h" -#include "usb_cdc.h" - +#include "usb_cdc.h" //test /** * Function to do a modulation and then get samples. @@ -214,6 +213,8 @@ void ReadTItag(void) } } + + void WriteTIbyte(uint8_t b) { int i = 0; @@ -310,11 +311,16 @@ void AcquireTiType(void) } } + + + // arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc // if crc provided, it will be written with the data verbatim (even if bogus) // if not provided a valid crc will be computed from the data and written. void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) { + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); if(crc == 0) { crc = update_crc16(crc, (idlo)&0xff); @@ -1705,6 +1711,8 @@ int DemodPCF7931(uint8_t **outBlocks) { if(num_blocks == 4) break; } memcpy(outBlocks, Blocks, 16*num_blocks); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return num_blocks; } @@ -1828,14 +1836,15 @@ void ReadPCF7931() { Dbprintf("Memory content:"); Dbprintf("-----------------------------------------"); for(i=0; i<max_blocks; i++) { - if(Blocks[i][ALLOC]==1) + if(Blocks[i][ALLOC]==1){ Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7], Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]); - else + }else Dbprintf("<missing block %d>", i); } Dbprintf("-----------------------------------------"); + return ; } @@ -2058,3 +2067,261 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } + + +#define T0_PCF 8 //period for the pcf7931 in us + +/* Write on a byte of a PCF7931 tag + * @param address : address of the block to write + @param byte : address of the byte to write + @param data : data to write + */ +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) +{ + + uint32_t tab[1024]={0}; // data times frame + uint32_t u = 0; + uint8_t parity = 0; + bool comp = 0; + + + //BUILD OF THE DATA FRAME + + //alimentation of the tag (time for initializing) + AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); + + //PMC + Dbprintf("Initialization delay : %d us", init_delay); + AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); + + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + + //password indication bit + AddBitPCF7931(1, tab, l, p); + + + //password (on 56 bits) + Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); + AddBytePCF7931(pass1, tab, l, p); + AddBytePCF7931(pass2, tab, l, p); + AddBytePCF7931(pass3, tab, l, p); + AddBytePCF7931(pass4, tab, l, p); + AddBytePCF7931(pass5, tab, l, p); + AddBytePCF7931(pass6, tab, l, p); + AddBytePCF7931(pass7, tab, l, p); + + + //programming mode (0 or 1) + AddBitPCF7931(0, tab, l, p); + + //block adress on 6 bits + Dbprintf("Block address : %02x", address); + for (u=0; u<6; u++) + { + if (address&(1<<u)) { // bit 1 + parity++; + AddBitPCF7931(1, tab, l, p); + } else{ // bit 0 + AddBitPCF7931(0, tab, l, p); + } + } + + //byte address on 4 bits + Dbprintf("Byte address : %02x", byte); + for (u=0; u<4; u++) + { + if (byte&(1<<u)) { // bit 1 + parity++; + AddBitPCF7931(1, tab, l, p); + } else{ // bit 0 + AddBitPCF7931(0, tab, l, p); + } + } + + //data on 8 bits + Dbprintf("Data : %02x", data); + for (u=0; u<8; u++) + { + if (data&(1<<u)) { // bit 1 + parity++; + AddBitPCF7931(1, tab, l, p); + } else{ //bit 0 + AddBitPCF7931(0, tab, l, p); + } + } + + + //parity bit + if((parity%2)==0){ + AddBitPCF7931(0, tab, l, p); //even parity + }else{ + AddBitPCF7931(1, tab, l, p);//odd parity + } + + //time access memory + AddPatternPCF7931(5120+2680, 0, 0, tab); + + //conversion of the scale time + for(u=0;u<500;u++){ + tab[u]=(tab[u] * 3)/2; + } + + + //compennsation of the counter reload + while (!comp){ + comp = 1; + for(u=0;tab[u]!=0;u++){ + if(tab[u] > 0xFFFF){ + tab[u] -= 0xFFFF; + comp = 0; + } + } + } + + SendCmdPCF7931(tab); +} + + + +/* Send a trame to a PCF7931 tags + * @param tab : array of the data frame + */ + +void SendCmdPCF7931(uint32_t * tab){ + uint16_t u=0; + uint16_t tempo=0; + + Dbprintf("SENDING DATA FRAME..."); + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); + + LED_A_ON(); + + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + + //initialization of the timer + AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; + AT91C_BASE_TCB->TCB_BCR = 1; + + + tempo = AT91C_BASE_TC0->TC_CV; + for(u=0;tab[u]!= 0;u+=3){ + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + // stop modulating antenna + LOW(GPIO_SSC_DOUT); + while(tempo != tab[u+1]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u+2]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + } + + LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + + + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + DbpString("FINISH !"); + DbpString("(Could be usefull to send the same trame many times)"); + LED(0xFFFF, 1000); +} + + +/* Add a byte for building the data frame of PCF7931 tags + * @param b : byte to add + * @param tab : array of the data frame + * @param l : offset on low pulse width + * @param p : offset on low pulse positioning + */ + +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ + + uint32_t u; + for (u=0; u<8; u++) + { + if (byte&(1<<u)) { //bit à 1 + if(AddBitPCF7931(1, tab, l, p)==1)return 1; + } else { //bit à 0 + if(AddBitPCF7931(0, tab, l, p)==1)return 1; + } + } + + return 0; +} + +/* Add a bits for building the data frame of PCF7931 tags + * @param b : bit to add + * @param tab : array of the data frame + * @param l : offset on low pulse width + * @param p : offset on low pulse positioning + */ +bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){ + uint8_t u = 0; + + for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array + + + if(b==1){ //add a bit 1 + if(u==0) tab[u] = 34*T0_PCF+p; + else tab[u] = 34*T0_PCF+tab[u-1]+p; + + tab[u+1] = 6*T0_PCF+tab[u]+l; + tab[u+2] = 88*T0_PCF+tab[u+1]-l-p; + return 0; + }else{ //add a bit 0 + + if(u==0) tab[u] = 98*T0_PCF+p; + else tab[u] = 98*T0_PCF+tab[u-1]+p; + + tab[u+1] = 6*T0_PCF+tab[u]+l; + tab[u+2] = 24*T0_PCF+tab[u+1]-l-p; + return 0; + } + + + return 1; +} + +/* Add a custom pattern in the data frame + * @param a : delay of the first high pulse + * @param b : delay of the low pulse + * @param c : delay of the last high pulse + * @param tab : array of the data frame + */ +bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){ + uint32_t u = 0; + for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array + + if(u==0) tab[u] = a; + else tab[u] = a + tab[u-1]; + + tab[u+1] = b+tab[u]; + tab[u+2] = c+tab[u+1]; + + return 0; +} \ No newline at end of file