From dc4300bafb4dd3917a230b27fa2d1efa9ef08dd0 Mon Sep 17 00:00:00 2001 From: Dake Date: Wed, 26 Aug 2015 15:53:49 +0200 Subject: [PATCH] add : writing on PCF7931 tags --- armsrc/appmain.c | 3 + armsrc/apps.h | 6 + armsrc/lfops.c | 283 +++++++++++++++++++++++++++++++++++++++++- client/cmdlfpcf7931.c | 88 ++++++++++++- client/cmdlfpcf7931.h | 13 +- include/usb_cmd.h | 2 + 6 files changed, 388 insertions(+), 7 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 38afd85d..321782da 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -987,6 +987,9 @@ void UsbPacketReceived(uint8_t *packet, int len) ReadPCF7931(); cmd_send(CMD_ACK,0,0,0,0,0); break; + case CMD_PCF7931_WRITE: + WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]); + break; case CMD_EM4X_READ_WORD: EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index b5638ee1..d5c8ba0a 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -61,6 +61,7 @@ void AcquireRawAdcSamples125k(int divisor); void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command); void ReadTItag(void); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); + void AcquireTiType(void); void AcquireRawBitsTI(void); void SimulateTagLowFrequency(int period, int gap, int ledcontrol); @@ -85,6 +86,11 @@ int DemodPCF7931(uint8_t **outBlocks); int IsBlock0PCF7931(uint8_t *Block); int IsBlock1PCF7931(uint8_t *Block); void ReadPCF7931(); +void SendCmdPCF7931(uint32_t * tab); +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p); +bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p); +bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab); +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); void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 733bc953..dc7ffd88 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,12 +311,17 @@ 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); + + +FpgaDownloadAndGo(FPGA_BITSTREAM_LF); if(crc == 0) { crc = update_crc16(crc, (idlo)&0xff); crc = update_crc16(crc, (idlo>>8)&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,21 @@ void ReadPCF7931() { Dbprintf("Memory content:"); Dbprintf("-----------------------------------------"); for(i=0; i", i); } Dbprintf("-----------------------------------------"); + return ; } @@ -2058,3 +2073,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< 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< -// +// 2015 Dake + // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -21,6 +22,8 @@ static int CmdHelp(const char *Cmd); +struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}}; + int CmdLFPCF7931Read(const char *Cmd) { UsbCommand c = {CMD_PCF7931_READ}; @@ -30,10 +33,93 @@ int CmdLFPCF7931Read(const char *Cmd) return 0; } +int CmdLFPCF7931Config(const char *Cmd) +{ + int res = 0; + res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]); + + if (res >= 7 || res < 1){ + if(res == 7) configPcf.init_delay = 17500; //default value + + if(res<=8){ + configPcf.offset[0] = -10; //default value + configPcf.offset[1] = 30; //default value + } + + if(res < 1){ + PrintAndLog("Usage: [...] "); + PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna."); + } + + PrintAndLog("Current configuration :"); + PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]); + PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay); + PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]); + + return 0; + } + + //default values + configPcf.password[0] = 0xFF; + configPcf.password[1] = 0xFF; + configPcf.password[2] = 0xFF; + configPcf.password[3] = 0xFF; + configPcf.password[4] = 0xFF; + configPcf.password[5] = 0xFF; + configPcf.password[6] = 0xFF; + + configPcf.init_delay = 17500; + configPcf.offset[0] = 0; + configPcf.offset[1] = 0; + + PrintAndLog("Incorrect format"); + PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000"); + PrintAndLog(" lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30"); + return 0; +} + + + +int CmdLFPCF7931Write(const char *Cmd) +{ + UsbCommand c = {CMD_PCF7931_WRITE}; + + int res = 0; + res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]); + + if(res < 1) { + PrintAndLog("Please specify the block address in hex"); + return 0; + } + if (res == 1){ + PrintAndLog("Please specify the byte address in hex"); + return 0; + } + if(res == 2) { + PrintAndLog("Please specify the data in hex (1 byte)"); + return 0; + } + if(res == 3) { + uint8_t n=0; + for(n=0;n<7;n++) c.d.asDwords[n] = configPcf.password[n]; + c.d.asDwords[7] = (configPcf.offset[0]+128); + c.d.asDwords[8] = (configPcf.offset[1]+128); + c.d.asDwords[9] = configPcf.init_delay; + SendCommand(&c); + return 0; + } + + PrintAndLog("INCORRECT FORMAT"); + return 0; +} + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"}, + {"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write "}, + {"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h index ed60bc91..78eaff5d 100644 --- a/client/cmdlfpcf7931.h +++ b/client/cmdlfpcf7931.h @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2012 Chalk -// +// 2015 Dake + // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -11,8 +12,18 @@ #ifndef CMDLFPCF7931_H__ #define CMDLFPCF7931_H__ +struct pcf7931_config{ + uint8_t password[7]; + uint16_t init_delay; + int16_t offset[2]; +}; + int CmdLFPCF7931(const char *Cmd); int CmdLFPCF7931Read(const char *Cmd); +int CmdLFPCF7931Write(const char *Cmd); + +int CmdLFPCF7931Config(const char *Cmd); + #endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index f443e970..a58feb38 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -87,6 +87,7 @@ typedef struct{ #define CMD_T55XX_WRITE_BLOCK 0x0215 #define CMD_T55XX_READ_TRACE 0x0216 #define CMD_PCF7931_READ 0x0217 +#define CMD_PCF7931_WRITE 0x0222 #define CMD_EM4X_READ_WORD 0x0218 #define CMD_EM4X_WRITE_WORD 0x0219 #define CMD_IO_DEMOD_FSK 0x021A @@ -99,6 +100,7 @@ typedef struct{ #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 + /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ // For the 13.56 MHz tags -- 2.39.2