mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-06 16:27:22 +08:00
em4x70: Clean up conversion of RF periods to ticks
This commit is contained in:
parent
70a70a91bc
commit
40654b8ac6
1 changed files with 47 additions and 43 deletions
|
@ -21,28 +21,32 @@ static em4x70_tag_t tag = { 0 };
|
|||
// EM4170 requires a parity bit on commands, other variants do not.
|
||||
static bool command_parity = true;
|
||||
|
||||
#define EM4X70_T_TAG_QUARTER_PERIOD 8
|
||||
#define EM4X70_T_TAG_HALF_PERIOD 16
|
||||
#define EM4X70_T_TAG_THREE_QUARTER_PERIOD 24
|
||||
#define EM4X70_T_TAG_FULL_PERIOD 32
|
||||
#define EM4X70_T_TAG_TWA 128 // Write Access Time
|
||||
#define EM4X70_T_TAG_DIV 224 // Divergency Time
|
||||
#define EM4X70_T_TAG_AUTH 4224 // Authentication Time
|
||||
#define EM4X70_T_TAG_WEE 3072 // EEPROM write Time
|
||||
#define EM4X70_T_TAG_TWALB 672 // Write Access Time of Lock Bits
|
||||
// Conversion from Ticks to RF periods
|
||||
// 1 us = 1.5 ticks
|
||||
// 1RF Period = 8us = 12 Ticks
|
||||
#define TICKS_PER_FC 12
|
||||
|
||||
#define EM4X70_T_WAITING_FOR_SNGLLIW 160 // Unsure
|
||||
// Chip timing from datasheet
|
||||
// Converted into Ticks for timing functions
|
||||
#define EM4X70_T_TAG_QUARTER_PERIOD (8 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_HALF_PERIOD (16 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_THREE_QUARTER_PERIOD (24 * TICKS_PER_FC)
|
||||
#define EM4X70_T_TAG_FULL_PERIOD (32 * TICKS_PER_FC) // 1 Bit Period
|
||||
#define EM4X70_T_TAG_TWA (128 * TICKS_PER_FC) // Write Access Time
|
||||
#define EM4X70_T_TAG_DIV (224 * TICKS_PER_FC) // Divergency Time
|
||||
#define EM4X70_T_TAG_AUTH (4224 * TICKS_PER_FC) // Authentication Time
|
||||
#define EM4X70_T_TAG_WEE (3072 * TICKS_PER_FC) // EEPROM write Time
|
||||
#define EM4X70_T_TAG_TWALB (672 * TICKS_PER_FC) // Write Access Time of Lock Bits
|
||||
#define EM4X70_T_TAG_BITMOD (4 * TICKS_PER_FC) // Initial time to stop modulation when sending 0
|
||||
#define EM4X70_T_TAG_TOLERANCE (8 * TICKS_PER_FC) // Tolerance in RF periods for receive/LIW
|
||||
|
||||
#define TICKS_PER_FC 12 // 1 fc = 8us, 1.5us per tick = 12 ticks
|
||||
#define EM4X70_MIN_AMPLITUDE 10 // Minimum difference between a high and low signal
|
||||
#define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this
|
||||
#define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window
|
||||
|
||||
#define EM4X70_TAG_TOLERANCE 8
|
||||
#define EM4X70_TAG_WORD 48
|
||||
|
||||
#define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command
|
||||
#define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command
|
||||
|
||||
|
||||
/**
|
||||
* These IDs are from the EM4170 datasheet
|
||||
* Some versions of the chip require a
|
||||
|
@ -133,7 +137,7 @@ static bool get_signalproperties(void) {
|
|||
static uint32_t get_pulse_length(void) {
|
||||
|
||||
uint8_t sample;
|
||||
uint32_t timeout = GetTicks() + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
uint32_t timeout = GetTicks() + EM4X70_T_TAG_TIMEOUT;
|
||||
|
||||
do {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -143,7 +147,7 @@ static uint32_t get_pulse_length(void) {
|
|||
return 0;
|
||||
|
||||
uint32_t start_ticks = GetTicks();
|
||||
timeout = start_ticks + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
timeout = start_ticks + EM4X70_T_TAG_TIMEOUT;
|
||||
|
||||
do {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -152,7 +156,7 @@ static uint32_t get_pulse_length(void) {
|
|||
if (IS_TIMEOUT(timeout))
|
||||
return 0;
|
||||
|
||||
timeout = (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD) + GetTicks();
|
||||
timeout = GetTicks() + EM4X70_T_TAG_TIMEOUT;
|
||||
do {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
} while (IS_HIGH(sample) && !IS_TIMEOUT(timeout));
|
||||
|
@ -172,7 +176,7 @@ static uint32_t get_pulse_length(void) {
|
|||
static uint32_t get_pulse_invert_length(void) {
|
||||
|
||||
uint8_t sample;
|
||||
uint32_t timeout = GetTicks() + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
uint32_t timeout = GetTicks() + EM4X70_T_TAG_TIMEOUT;
|
||||
|
||||
do {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -182,7 +186,7 @@ static uint32_t get_pulse_invert_length(void) {
|
|||
return 0;
|
||||
|
||||
uint32_t start_ticks = GetTicks();
|
||||
timeout = start_ticks + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
timeout = start_ticks + EM4X70_T_TAG_TIMEOUT;
|
||||
|
||||
do {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
@ -191,7 +195,7 @@ static uint32_t get_pulse_invert_length(void) {
|
|||
if (IS_TIMEOUT(timeout))
|
||||
return 0;
|
||||
|
||||
timeout = GetTicks() + (TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
timeout = GetTicks() + EM4X70_T_TAG_TIMEOUT;
|
||||
do {
|
||||
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
} while (IS_LOW(sample) && !IS_TIMEOUT(timeout));
|
||||
|
@ -203,9 +207,9 @@ static uint32_t get_pulse_invert_length(void) {
|
|||
|
||||
}
|
||||
|
||||
static bool check_pulse_length(uint32_t pl, int length) {
|
||||
static bool check_pulse_length(uint32_t pl, uint32_t length) {
|
||||
// check if pulse length <pl> corresponds to given length <length>
|
||||
return ((pl >= TICKS_PER_FC * (length - EM4X70_TAG_TOLERANCE)) & (pl <= TICKS_PER_FC * (length + EM4X70_TAG_TOLERANCE)));
|
||||
return ((pl >= (length - EM4X70_T_TAG_TOLERANCE)) & (pl <= (length + EM4X70_T_TAG_TOLERANCE)));
|
||||
}
|
||||
|
||||
static void em4x70_send_bit(bool bit) {
|
||||
|
@ -215,24 +219,24 @@ static void em4x70_send_bit(bool bit) {
|
|||
|
||||
if (bit == 0) {
|
||||
|
||||
// disable modulation (drop the field) for 4 cycles of carrier
|
||||
// disable modulation (drop the field) n cycles of carrier
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
while (TICKS_ELAPSED(start_ticks) <= TICKS_PER_FC * 4);
|
||||
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_BITMOD);
|
||||
|
||||
// enable modulation (activates the field) for remaining first
|
||||
// half of bit period
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
while (TICKS_ELAPSED(start_ticks) <= TICKS_PER_FC * EM4X70_T_TAG_HALF_PERIOD);
|
||||
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_HALF_PERIOD);
|
||||
|
||||
// disable modulation for second half of bit period
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
while (TICKS_ELAPSED(start_ticks) <= TICKS_PER_FC * EM4X70_T_TAG_FULL_PERIOD);
|
||||
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_FULL_PERIOD);
|
||||
|
||||
} else {
|
||||
|
||||
// bit = "1" means disable modulation for full bit period
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
while (TICKS_ELAPSED(start_ticks) <= TICKS_PER_FC * EM4X70_T_TAG_FULL_PERIOD);
|
||||
while (TICKS_ELAPSED(start_ticks) <= EM4X70_T_TAG_FULL_PERIOD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,7 +300,7 @@ static bool check_ack(void) {
|
|||
// returns true if signal structue corresponds to ACK, anything else is
|
||||
// counted as NAK (-> false)
|
||||
uint32_t start_ticks = GetTicks();
|
||||
while (TICKS_ELAPSED(start_ticks) < TICKS_PER_FC * 4 * EM4X70_T_TAG_FULL_PERIOD) {
|
||||
while (TICKS_ELAPSED(start_ticks) < (4 * EM4X70_T_TAG_FULL_PERIOD)) {
|
||||
/*
|
||||
ACK
|
||||
64 (48+16)
|
||||
|
@ -378,13 +382,13 @@ static int send_pin(const uint32_t pin) {
|
|||
}
|
||||
|
||||
// Wait TWALB (write access lock bits)
|
||||
WaitTicks(TICKS_PER_FC * EM4X70_T_TAG_TWALB);
|
||||
WaitTicks(EM4X70_T_TAG_TWALB);
|
||||
|
||||
// <-- Receive ACK
|
||||
if (check_ack()) {
|
||||
|
||||
// <w> Writes Lock Bits
|
||||
WaitTicks(TICKS_PER_FC * EM4X70_T_TAG_WEE);
|
||||
WaitTicks(EM4X70_T_TAG_WEE);
|
||||
// <-- Receive header + ID
|
||||
uint8_t tag_id[EM4X70_MAX_RECEIVE_LENGTH];
|
||||
int num = em4x70_receive(tag_id);
|
||||
|
@ -415,14 +419,14 @@ static int write(const uint16_t word, const uint8_t address) {
|
|||
em4x70_send_word(word);
|
||||
|
||||
// Wait TWA
|
||||
WaitTicks(TICKS_PER_FC * EM4X70_T_TAG_TWA);
|
||||
WaitTicks(EM4X70_T_TAG_TWA);
|
||||
|
||||
// look for ACK sequence
|
||||
if (check_ack()) {
|
||||
|
||||
// now EM4x70 needs T0 * EM4X70_T_TAG_TWEE (EEPROM write time)
|
||||
// for saving data and should return with ACK
|
||||
WaitTicks(TICKS_PER_FC * EM4X70_T_TAG_WEE);
|
||||
WaitTicks(EM4X70_T_TAG_WEE);
|
||||
if (check_ack()) {
|
||||
|
||||
return PM3_SUCCESS;
|
||||
|
@ -436,7 +440,7 @@ static int write(const uint16_t word, const uint8_t address) {
|
|||
static bool find_listen_window(bool command) {
|
||||
|
||||
int cnt = 0;
|
||||
while (cnt < EM4X70_T_WAITING_FOR_SNGLLIW) {
|
||||
while (cnt < EM4X70_T_WAITING_FOR_LIW) {
|
||||
/*
|
||||
80 ( 64 + 16 )
|
||||
80 ( 64 + 16 )
|
||||
|
@ -444,10 +448,10 @@ static bool find_listen_window(bool command) {
|
|||
96 ( 64 + 32 )
|
||||
64 ( 32 + 16 +16 )*/
|
||||
|
||||
if (check_pulse_length(get_pulse_invert_length(), 80) &&
|
||||
check_pulse_length(get_pulse_invert_length(), 80) &&
|
||||
check_pulse_length(get_pulse_length(), 96) &&
|
||||
check_pulse_length(get_pulse_length(), 64)) {
|
||||
if (check_pulse_length(get_pulse_invert_length(), (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||
check_pulse_length(get_pulse_invert_length(), (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(), (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD) &&
|
||||
check_pulse_length(get_pulse_length(), EM4X70_T_TAG_FULL_PERIOD + (2*EM4X70_T_TAG_HALF_PERIOD))) {
|
||||
|
||||
if (command) {
|
||||
/* Here we are after the 64 duration edge.
|
||||
|
@ -456,7 +460,7 @@ static bool find_listen_window(bool command) {
|
|||
*
|
||||
* I've found between 4-5 quarter periods (32-40) works best
|
||||
*/
|
||||
WaitTicks(TICKS_PER_FC * 4 * EM4X70_T_TAG_QUARTER_PERIOD);
|
||||
WaitTicks( 4 * EM4X70_T_TAG_QUARTER_PERIOD );
|
||||
// Send RM Command
|
||||
em4x70_send_bit(0);
|
||||
em4x70_send_bit(0);
|
||||
|
@ -573,7 +577,7 @@ static int em4x70_receive(uint8_t *bits) {
|
|||
// 4 Manchester 0's
|
||||
|
||||
// Skip a few leading 1's as it could be noisy
|
||||
WaitTicks(TICKS_PER_FC * 3 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
WaitTicks(6 * EM4X70_T_TAG_FULL_PERIOD);
|
||||
|
||||
// wait until we get the transition from 1's to 0's which is 1.5 full windows
|
||||
int pulse_count = 0;
|
||||
|
@ -597,7 +601,7 @@ static int em4x70_receive(uint8_t *bits) {
|
|||
}
|
||||
|
||||
// identify remaining bits based on pulse lengths
|
||||
// between two listen windows only pulse lengths of 1, 1.5 and 2 are possible
|
||||
// between listen windows only pulse lengths of 1, 1.5 and 2 are possible
|
||||
while (bit_pos < EM4X70_MAX_RECEIVE_LENGTH) {
|
||||
|
||||
if (edge)
|
||||
|
@ -634,8 +638,8 @@ static int em4x70_receive(uint8_t *bits) {
|
|||
bits[bit_pos++] = 0;
|
||||
}
|
||||
|
||||
} else if ((edge && check_pulse_length(pl, 3 * EM4X70_T_TAG_FULL_PERIOD)) ||
|
||||
(!edge && check_pulse_length(pl, 80))) {
|
||||
} else if ((edge && check_pulse_length(pl, (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD)) ||
|
||||
(!edge && check_pulse_length(pl, (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD))) {
|
||||
|
||||
// LIW detected (either invert or normal)
|
||||
return --bit_pos;
|
||||
|
|
Loading…
Reference in a new issue