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.
This commit is contained in:
micki.held@gmx.de 2014-02-23 15:46:19 +00:00
parent 7bc95e2e43
commit d7aa3739a9
3 changed files with 87 additions and 44 deletions

View file

@ -236,6 +236,15 @@ bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t timestamp,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static tUart Uart; 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() void UartReset()
{ {
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
@ -249,7 +258,7 @@ void UartReset()
Uart.endTime = 0; Uart.endTime = 0;
} }
inline RAMFUNC Modulation_t MillerModulation(uint8_t b) /* inline RAMFUNC Modulation_t MillerModulation(uint8_t b)
{ {
// switch (b & 0x88) { // switch (b & 0x88) {
// case 0x00: return MILLER_MOD_BOTH_HALVES; // case 0x00: return MILLER_MOD_BOTH_HALVES;
@ -265,7 +274,7 @@ inline RAMFUNC Modulation_t MillerModulation(uint8_t b)
default: return MOD_NOMOD; default: return MOD_NOMOD;
} }
} }
*/
// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time // 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) 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) { if (Uart.syncBit != 0xFFFF) {
Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
Uart.startTime -= Uart.syncBit; Uart.startTime -= Uart.syncBit;
Uart.endTime = Uart.startTime;
Uart.state = STATE_START_OF_COMMUNICATION; Uart.state = STATE_START_OF_COMMUNICATION;
} }
} }
} else { } else {
switch (MillerModulation(Uart.twoBits >> Uart.syncBit)) { if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {
case MOD_FIRST_HALF: // Sequence Z = 0 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 if (Uart.state == STATE_MILLER_X) { // error - must not follow after X
UartReset(); UartReset();
Uart.highCnt = 6; Uart.highCnt = 6;
@ -317,8 +330,9 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
Uart.shiftReg = 0; 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.bitCount++;
Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
Uart.state = STATE_MILLER_X; 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.bitCount = 0;
Uart.shiftReg = 0; Uart.shiftReg = 0;
} }
break; } else { // no modulation in both halves - Sequence Y
case MOD_NOMOD: // 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 if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
if(Uart.len == 0 && Uart.bitCount > 0) { // if we decoded some bits if(Uart.len == 0 && Uart.bitCount > 0) { // if we decoded some bits
Uart.shiftReg >>= (9 - Uart.bitCount); // add them to the output Uart.shiftReg >>= (9 - Uart.bitCount); // add them to the output
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); Uart.output[Uart.len++] = (Uart.shiftReg & 0xff);
Uart.parityBits <<= 1; // no parity bit - add "0" 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; return TRUE;
} }
@ -357,11 +370,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
Uart.shiftReg = 0; 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) // Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only)
static tDemod Demod; 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[] = { const bool Mod_Manchester_LUT[] = {
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE,
FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE
}; };
#define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4]) #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 & 0x03B8) == 0x0380) Demod.syncBit = 2;
else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1; else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1;
else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0; 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 = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
Demod.startTime -= Demod.syncBit; Demod.startTime -= Demod.syncBit;
Demod.bitCount = offset; // number of decoded data bits 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); Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1);
} else { // no modulation in both halves - End of communication } else { // no modulation in both halves - End of communication
if(Demod.bitCount > 0) { // if we decoded bits if (Demod.len > 0 || Demod.bitCount > 0) { // received something
Demod.shiftReg >>= (9 - Demod.bitCount); // add the remaining decoded bits to the output if(Demod.bitCount > 0) { // if we decoded bits
Demod.output[Demod.len++] = Demod.shiftReg & 0xff; Demod.shiftReg >>= (9 - Demod.bitCount); // add the remaining decoded bits to the output
// No parity bit, so just shift a 0 Demod.output[Demod.len++] = Demod.shiftReg & 0xff;
Demod.parityBits <<= 1; // 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
} }
} }

Binary file not shown.

View file

@ -35,7 +35,7 @@ reg ssp_frame;
wire adc_clk; wire adc_clk;
assign adc_clk = ck_1356meg; 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 [11:0] has_been_low_for;
reg [8:0] saw_deep_modulation; reg [8:0] saw_deep_modulation;
reg [2:0] deep_counter; reg [2:0] deep_counter;
@ -45,6 +45,8 @@ always @(negedge adc_clk)
begin begin
if(& adc_d[7:6]) after_hysteresis <= 1'b1; // adc_d >= 196 (U >= 3,28V) -> after_hysteris = 1 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 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) if(~(| adc_d[7:0])) // if adc_d == 0 (U <= 0,94V)
begin begin
@ -122,6 +124,7 @@ reg mod_sig, mod_sig_coil;
reg temp_buffer_reset; reg temp_buffer_reset;
reg sendbit; reg sendbit;
reg [3:0] sub_carrier_cnt; 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 // ADC data appears on the rising edge, so sample it on the falling edge
always @(negedge adc_clk) always @(negedge adc_clk)
@ -244,13 +247,42 @@ begin
sendbit = 1'b0; sendbit = 1'b0;
end 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 // Prepare 8 Bits to communicate to ARM
if (negedge_cnt == 7'd63)
// in SNIFFER mode: 4 Bits data sniffed as Tag, 4 Bits data sniffed as Reader
if(mod_type == `SNIFFER)
begin begin
if (negedge_cnt == 7'd63) if (mod_type == `SNIFFER)
begin begin
if(deep_modulation) // a reader is sending (or there's no field at all) if(deep_modulation) // a reader is sending (or there's no field at all)
begin begin
@ -259,34 +291,32 @@ begin
else else
begin begin
to_arm <= {after_hysteresis_prev1,after_hysteresis_prev2,after_hysteresis_prev3,after_hysteresis_prev4,bit1,bit2,bit3,bit4}; to_arm <= {after_hysteresis_prev1,after_hysteresis_prev2,after_hysteresis_prev3,after_hysteresis_prev4,bit1,bit2,bit3,bit4};
end end
negedge_cnt <= 0; negedge_cnt <= 0;
end end
else else
begin begin
negedge_cnt <= negedge_cnt + 1; negedge_cnt <= negedge_cnt + 1;
end end
end end
else else if(negedge_cnt == 7'd127)
// other modes: 8 Bits info on queue delay
begin begin
if(negedge_cnt == 7'd127) if (mod_type == `TAGSIM_MOD)
begin begin
if (mod_type == `TAGSIM_MOD) to_arm[7:0] <= {mod_sig_ptr[4:0], mod_sig_flip[3:1]};
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
negedge_cnt <= 0; negedge_cnt <= 0;
end end
else else
begin begin
negedge_cnt <= negedge_cnt + 1; to_arm[7:0] <= 8'd0;
negedge_cnt <= negedge_cnt + 1;
end end
end end
else
begin
negedge_cnt <= negedge_cnt + 1;
end
if(negedge_cnt == 7'd1) if(negedge_cnt == 7'd1)
begin begin