From d7aa3739a95583c1d1dd0305a1a1afeb78f23eb7 Mon Sep 17 00:00:00 2001 From: "micki.held@gmx.de" Date: Sun, 23 Feb 2014 15:46:19 +0000 Subject: [PATCH] More robust iso14443a sniffing/simulation functions by - iso14443a.c: less strict Miller/Manchester decoders - FPGA hi_iso14443a.v: syncing on external readers' clock when simulating and sniffing. --- armsrc/iso14443a.c | 63 ++++++++++++++++++++++++---------------- fpga/fpga.bit | Bin 42172 -> 42172 bytes fpga/hi_iso14443a.v | 68 +++++++++++++++++++++++++++++++------------- 3 files changed, 87 insertions(+), 44 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index ca888295..b105e792 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -236,6 +236,15 @@ bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t timestamp, //----------------------------------------------------------------------------- static tUart Uart; +// Lookup-Table to decide if 4 raw bits are a modulation. +// We accept two or three consecutive "0" in any position with the rest "1" +const bool Mod_Miller_LUT[] = { + TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, + TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE +}; +#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4]) +#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)]) + void UartReset() { Uart.state = STATE_UNSYNCD; @@ -249,7 +258,7 @@ void UartReset() Uart.endTime = 0; } -inline RAMFUNC Modulation_t MillerModulation(uint8_t b) +/* inline RAMFUNC Modulation_t MillerModulation(uint8_t b) { // switch (b & 0x88) { // case 0x00: return MILLER_MOD_BOTH_HALVES; @@ -265,7 +274,7 @@ inline RAMFUNC Modulation_t MillerModulation(uint8_t b) default: return MOD_NOMOD; } } - + */ // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { @@ -293,14 +302,18 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) if (Uart.syncBit != 0xFFFF) { Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); Uart.startTime -= Uart.syncBit; + Uart.endTime = Uart.startTime; Uart.state = STATE_START_OF_COMMUNICATION; } } } else { - switch (MillerModulation(Uart.twoBits >> Uart.syncBit)) { - case MOD_FIRST_HALF: // Sequence Z = 0 + if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) { + if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation in both halves - error + UartReset(); + Uart.highCnt = 6; + } else { // Modulation in first half = Sequence Z = logic "0" if (Uart.state == STATE_MILLER_X) { // error - must not follow after X UartReset(); Uart.highCnt = 6; @@ -317,8 +330,9 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.shiftReg = 0; } } - break; - case MOD_SECOND_HALF: // Sequence X = 1 + } + } else { + if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg Uart.state = STATE_MILLER_X; @@ -330,15 +344,14 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.bitCount = 0; Uart.shiftReg = 0; } - break; - case MOD_NOMOD: // no modulation in both halves - Sequence Y + } else { // no modulation in both halves - Sequence Y if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication Uart.state = STATE_UNSYNCD; if(Uart.len == 0 && Uart.bitCount > 0) { // if we decoded some bits Uart.shiftReg >>= (9 - Uart.bitCount); // add them to the output Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); Uart.parityBits <<= 1; // no parity bit - add "0" - Uart.bitCount--; // last "0" was part of the EOC sequence + Uart.bitCount--; // last "0" was part of the EOC sequence } return TRUE; } @@ -357,11 +370,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.shiftReg = 0; } } - break; - case MOD_BOTH_HALVES: // Error - UartReset(); - Uart.highCnt = 6; - return FALSE; + } } } @@ -388,9 +397,11 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) // Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only) static tDemod Demod; +// Lookup-Table to decide if 4 raw bits are a modulation. +// We accept three or four consecutive "1" in any position const bool Mod_Manchester_LUT[] = { - FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, - FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, + FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE }; #define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4]) @@ -434,7 +445,7 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2; else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1; else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0; - if (Demod.syncBit < 8) { + if (Demod.syncBit != 0xFFFF) { Demod.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); Demod.startTime -= Demod.syncBit; Demod.bitCount = offset; // number of decoded data bits @@ -473,15 +484,17 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non } Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1); } else { // no modulation in both halves - End of communication - if(Demod.bitCount > 0) { // if we decoded bits - Demod.shiftReg >>= (9 - Demod.bitCount); // add the remaining decoded bits to the output - Demod.output[Demod.len++] = Demod.shiftReg & 0xff; - // No parity bit, so just shift a 0 - Demod.parityBits <<= 1; + if (Demod.len > 0 || Demod.bitCount > 0) { // received something + if(Demod.bitCount > 0) { // if we decoded bits + Demod.shiftReg >>= (9 - Demod.bitCount); // add the remaining decoded bits to the output + Demod.output[Demod.len++] = Demod.shiftReg & 0xff; + // No parity bit, so just shift a 0 + Demod.parityBits <<= 1; + } + return TRUE; // we are finished with decoding the raw data sequence + } else { // nothing received. Start over + DemodReset(); } - Demod.state = DEMOD_UNSYNCD; // start from the beginning - Demod.twoBits = 0; - return TRUE; // we are finished with decoding the raw data sequence } } diff --git a/fpga/fpga.bit b/fpga/fpga.bit index 97cdd23362dfe38359dd9066c57ad5b893fb225a..55dbfb8c361b8fcb54e3cdc3991e71cd88d0ff0d 100644 GIT binary patch literal 42172 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 Z_eZIWRNs$ik$;D=6sL2swJen;@^7++cqsq? literal 42172 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

VV{aEfZ%VQ4x0f@d?KHFavJ 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 F@^1r%a~l8v diff --git a/fpga/hi_iso14443a.v b/fpga/hi_iso14443a.v index 0f7325b6..1ad485dd 100644 --- a/fpga/hi_iso14443a.v +++ b/fpga/hi_iso14443a.v @@ -35,7 +35,7 @@ reg ssp_frame; wire adc_clk; assign adc_clk = ck_1356meg; -reg after_hysteresis, after_hysteresis_prev1, after_hysteresis_prev2, after_hysteresis_prev3, after_hysteresis_prev4; +reg after_hysteresis, pre_after_hysteresis, after_hysteresis_prev1, after_hysteresis_prev2, after_hysteresis_prev3, after_hysteresis_prev4; reg [11:0] has_been_low_for; reg [8:0] saw_deep_modulation; reg [2:0] deep_counter; @@ -45,6 +45,8 @@ always @(negedge adc_clk) begin if(& adc_d[7:6]) after_hysteresis <= 1'b1; // adc_d >= 196 (U >= 3,28V) -> after_hysteris = 1 else if(~(| adc_d[7:4])) after_hysteresis <= 1'b0; // if adc_d <= 15 (U <= 1,13V) -> after_hysteresis = 0 + + pre_after_hysteresis <= after_hysteresis; if(~(| adc_d[7:0])) // if adc_d == 0 (U <= 0,94V) begin @@ -122,6 +124,7 @@ reg mod_sig, mod_sig_coil; reg temp_buffer_reset; reg sendbit; reg [3:0] sub_carrier_cnt; +reg[3:0] reader_falling_edge_time; // ADC data appears on the rising edge, so sample it on the falling edge always @(negedge adc_clk) @@ -244,13 +247,42 @@ begin sendbit = 1'b0; end + + + // check timing of a falling edge in reader signal + if (pre_after_hysteresis && ~after_hysteresis) + reader_falling_edge_time[3:0] <= negedge_cnt[3:0]; + else + reader_falling_edge_time[3:0] <= 4'd8; + + + + // sync clock to external reader's clock: + if (negedge_cnt[3:0] == 4'd13 && (mod_type == `SNIFFER || mod_type == `TAGSIM_MOD || mod_type == `TAGSIM_LISTEN)) + begin + // adjust clock if necessary: + if (reader_falling_edge_time < 4'd8 && reader_falling_edge_time > 4'd1) + begin + negedge_cnt <= negedge_cnt; // freeze time + end + else if (reader_falling_edge_time == 4'd8) + begin + negedge_cnt <= negedge_cnt + 1; // the desired state. Advance as usual; + end + else + begin + negedge_cnt[3:0] <= 4'd15; // time warp + end + reader_falling_edge_time <= 4'd8; // only once per detected rising edge + end + + + //------------------------------------------------------------------------------------------------------------------------------------------ // Prepare 8 Bits to communicate to ARM - - // in SNIFFER mode: 4 Bits data sniffed as Tag, 4 Bits data sniffed as Reader - if(mod_type == `SNIFFER) + if (negedge_cnt == 7'd63) begin - if (negedge_cnt == 7'd63) + if (mod_type == `SNIFFER) begin if(deep_modulation) // a reader is sending (or there's no field at all) begin @@ -259,34 +291,32 @@ begin else begin to_arm <= {after_hysteresis_prev1,after_hysteresis_prev2,after_hysteresis_prev3,after_hysteresis_prev4,bit1,bit2,bit3,bit4}; - end + end negedge_cnt <= 0; end else begin negedge_cnt <= negedge_cnt + 1; end - end - else - // other modes: 8 Bits info on queue delay + end + else if(negedge_cnt == 7'd127) begin - if(negedge_cnt == 7'd127) + if (mod_type == `TAGSIM_MOD) begin - if (mod_type == `TAGSIM_MOD) - begin - to_arm[7:0] <= {mod_sig_ptr[4:0], mod_sig_flip[3:1]}; - end - else - begin - to_arm[7:0] <= 8'd0; - end + to_arm[7:0] <= {mod_sig_ptr[4:0], mod_sig_flip[3:1]}; negedge_cnt <= 0; end else begin - negedge_cnt <= negedge_cnt + 1; + to_arm[7:0] <= 8'd0; + negedge_cnt <= negedge_cnt + 1; end end + else + begin + negedge_cnt <= negedge_cnt + 1; + end + if(negedge_cnt == 7'd1) begin -- 2.39.5