mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-20 13:23:25 -07:00
Merge branch 'master' into topaz. Update Changelog.
This commit is contained in:
commit
d9cc4e1ae2
10 changed files with 490 additions and 29 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -2055,19 +2055,20 @@ void ReaderMifare(bool first_try)
|
|||
byte_t par_list[8] = {0x00};
|
||||
byte_t ks_list[8] = {0x00};
|
||||
|
||||
#define PRNG_SEQUENCE_LENGTH (1 << 16);
|
||||
static uint32_t sync_time;
|
||||
static uint32_t sync_cycles;
|
||||
static int32_t sync_cycles;
|
||||
int catch_up_cycles = 0;
|
||||
int last_catch_up = 0;
|
||||
uint16_t elapsed_prng_sequences;
|
||||
uint16_t consecutive_resyncs = 0;
|
||||
int isOK = 0;
|
||||
|
||||
if (first_try) {
|
||||
mf_nr_ar3 = 0;
|
||||
sync_time = GetCountSspClk() & 0xfffffff8;
|
||||
sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
|
||||
sync_cycles = PRNG_SEQUENCE_LENGTH; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces).
|
||||
nt_attacked = 0;
|
||||
nt = 0;
|
||||
par[0] = 0;
|
||||
}
|
||||
else {
|
||||
|
@ -2082,8 +2083,17 @@ void ReaderMifare(bool first_try)
|
|||
LED_C_OFF();
|
||||
|
||||
|
||||
#define DARKSIDE_MAX_TRIES 32 // number of tries to sync on PRNG cycle. Then give up.
|
||||
uint16_t unsuccessfull_tries = 0;
|
||||
#define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
|
||||
#define MAX_SYNC_TRIES 32
|
||||
#define NUM_DEBUG_INFOS 8 // per strategy
|
||||
#define MAX_STRATEGY 3
|
||||
uint16_t unexpected_random = 0;
|
||||
uint16_t sync_tries = 0;
|
||||
int16_t debug_info_nr = -1;
|
||||
uint16_t strategy = 0;
|
||||
int32_t debug_info[MAX_STRATEGY][NUM_DEBUG_INFOS];
|
||||
uint32_t select_time;
|
||||
uint32_t halt_time;
|
||||
|
||||
for(uint16_t i = 0; TRUE; i++) {
|
||||
|
||||
|
@ -2096,21 +2106,60 @@ void ReaderMifare(bool first_try)
|
|||
break;
|
||||
}
|
||||
|
||||
if (strategy == 2) {
|
||||
// test with additional hlt command
|
||||
halt_time = 0;
|
||||
int len = mifare_sendcmd_short(NULL, false, 0x50, 0x00, receivedAnswer, receivedAnswerPar, &halt_time);
|
||||
if (len && MF_DBGLEVEL >= 3) {
|
||||
Dbprintf("Unexpected response of %d bytes to hlt command (additional debugging).", len);
|
||||
}
|
||||
}
|
||||
|
||||
if (strategy == 3) {
|
||||
// test with FPGA power off/on
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
|
||||
SpinDelay(100);
|
||||
}
|
||||
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card");
|
||||
continue;
|
||||
}
|
||||
select_time = GetCountSspClk();
|
||||
|
||||
sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
|
||||
catch_up_cycles = 0;
|
||||
elapsed_prng_sequences = 1;
|
||||
if (debug_info_nr == -1) {
|
||||
sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
|
||||
catch_up_cycles = 0;
|
||||
|
||||
// if we missed the sync time already, advance to the next nonce repeat
|
||||
while(GetCountSspClk() > sync_time) {
|
||||
sync_time = (sync_time & 0xfffffff8) + sync_cycles;
|
||||
}
|
||||
// if we missed the sync time already, advance to the next nonce repeat
|
||||
while(GetCountSspClk() > sync_time) {
|
||||
elapsed_prng_sequences++;
|
||||
sync_time = (sync_time & 0xfffffff8) + sync_cycles;
|
||||
}
|
||||
|
||||
// Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked)
|
||||
ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
|
||||
// Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked)
|
||||
ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
|
||||
} else {
|
||||
// collect some information on tag nonces for debugging:
|
||||
#define DEBUG_FIXED_SYNC_CYCLES PRNG_SEQUENCE_LENGTH
|
||||
if (strategy == 0) {
|
||||
// nonce distances at fixed time after card select:
|
||||
sync_time = select_time + DEBUG_FIXED_SYNC_CYCLES;
|
||||
} else if (strategy == 1) {
|
||||
// nonce distances at fixed time between authentications:
|
||||
sync_time = sync_time + DEBUG_FIXED_SYNC_CYCLES;
|
||||
} else if (strategy == 2) {
|
||||
// nonce distances at fixed time after halt:
|
||||
sync_time = halt_time + DEBUG_FIXED_SYNC_CYCLES;
|
||||
} else {
|
||||
// nonce_distances at fixed time after power on
|
||||
sync_time = DEBUG_FIXED_SYNC_CYCLES;
|
||||
}
|
||||
ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
|
||||
}
|
||||
|
||||
// Receive the (4 Byte) "random" nonce
|
||||
if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) {
|
||||
|
@ -2128,19 +2177,37 @@ void ReaderMifare(bool first_try)
|
|||
int nt_distance = dist_nt(previous_nt, nt);
|
||||
if (nt_distance == 0) {
|
||||
nt_attacked = nt;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (nt_distance == -99999) { // invalid nonce received
|
||||
unsuccessfull_tries++;
|
||||
if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) {
|
||||
unexpected_random++;
|
||||
if (unexpected_random > MAX_UNEXPECTED_RANDOM) {
|
||||
isOK = -3; // Card has an unpredictable PRNG. Give up
|
||||
break;
|
||||
} else {
|
||||
continue; // continue trying...
|
||||
}
|
||||
}
|
||||
sync_cycles = (sync_cycles - nt_distance);
|
||||
if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
|
||||
if (++sync_tries > MAX_SYNC_TRIES) {
|
||||
if (strategy > MAX_STRATEGY || MF_DBGLEVEL < 3) {
|
||||
isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly
|
||||
break;
|
||||
} else { // continue for a while, just to collect some debug info
|
||||
debug_info[strategy][debug_info_nr] = nt_distance;
|
||||
debug_info_nr++;
|
||||
if (debug_info_nr == NUM_DEBUG_INFOS) {
|
||||
strategy++;
|
||||
debug_info_nr = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
sync_cycles = (sync_cycles - nt_distance/elapsed_prng_sequences);
|
||||
if (sync_cycles <= 0) {
|
||||
sync_cycles += PRNG_SEQUENCE_LENGTH;
|
||||
}
|
||||
if (MF_DBGLEVEL >= 3) {
|
||||
Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -2151,6 +2218,7 @@ void ReaderMifare(bool first_try)
|
|||
catch_up_cycles = 0;
|
||||
continue;
|
||||
}
|
||||
catch_up_cycles /= elapsed_prng_sequences;
|
||||
if (catch_up_cycles == last_catch_up) {
|
||||
consecutive_resyncs++;
|
||||
}
|
||||
|
@ -2164,6 +2232,9 @@ void ReaderMifare(bool first_try)
|
|||
else {
|
||||
sync_cycles = sync_cycles + catch_up_cycles;
|
||||
if (MF_DBGLEVEL >= 3) Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, -catch_up_cycles, sync_cycles);
|
||||
last_catch_up = 0;
|
||||
catch_up_cycles = 0;
|
||||
consecutive_resyncs = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -2171,12 +2242,10 @@ void ReaderMifare(bool first_try)
|
|||
consecutive_resyncs = 0;
|
||||
|
||||
// Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding
|
||||
if (ReaderReceive(receivedAnswer, receivedAnswerPar))
|
||||
{
|
||||
if (ReaderReceive(receivedAnswer, receivedAnswerPar)) {
|
||||
catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer
|
||||
|
||||
if (nt_diff == 0)
|
||||
{
|
||||
if (nt_diff == 0) {
|
||||
par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change
|
||||
}
|
||||
|
||||
|
@ -2211,6 +2280,16 @@ void ReaderMifare(bool first_try)
|
|||
|
||||
|
||||
mf_nr_ar[3] &= 0x1F;
|
||||
|
||||
if (isOK == -4) {
|
||||
if (MF_DBGLEVEL >= 3) {
|
||||
for (uint16_t i = 0; i <= MAX_STRATEGY; i++) {
|
||||
for(uint16_t j = 0; j < NUM_DEBUG_INFOS; j++) {
|
||||
Dbprintf("collected debug info[%d][%d] = %d", i, j, debug_info[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte_t buf[28];
|
||||
memcpy(buf + 0, uid, 4);
|
||||
|
|
275
armsrc/lfops.c
275
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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue