From 7f0e2816144d21882c65aed8ce78b1e6e15cc144 Mon Sep 17 00:00:00 2001 From: henryk Date: Mon, 10 Mar 2008 09:52:17 +0000 Subject: Further optimisation on the differential miller decoder, is now down to 1750 MCK/2 cycles for the short frame git-svn-id: https://svn.openpcd.org:2342/trunk@448 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- openpicc/application/iso14443a_diffmiller.c | 267 ++++++++++++++-------------- openpicc/application/tc_sniffer.c | 5 + 2 files changed, 137 insertions(+), 135 deletions(-) diff --git a/openpicc/application/iso14443a_diffmiller.c b/openpicc/application/iso14443a_diffmiller.c index 020760f..cc895df 100644 --- a/openpicc/application/iso14443a_diffmiller.c +++ b/openpicc/application/iso14443a_diffmiller.c @@ -36,22 +36,6 @@ #define DEBUGP (void) #define printf usb_print_string -struct diffmiller_state { - int initialized, pauses_count; - iso14443_frame *frame; - u_int32_t counter; - u_int16_t byte,crc; - u_int8_t parity; - struct { - u_int8_t in_frame:1; - u_int8_t frame_finished:1; - u_int8_t overflow:1; - u_int8_t error:1; - } flags; -}; - -struct diffmiller_state _state; - /* * Decoding Methodology: We'll only see the edges for the start of modulation pauses and not * all symbols generate modulation pauses at all. Two phases: @@ -108,26 +92,24 @@ struct diffmiller_state _state; enum symbol {NO_SYM=0, sym_x, sym_y, sym_z}; enum bit { BIT_ERROR, BIT_SOF, BIT_0, BIT_1, BIT_EOF }; -enum bit_length { out_of_range=0, len_3=1, len_5=2, len_7=3, len_9_or_greater=4 }; -const char *bit_length_descriptions[] = { - [out_of_range] = "OOR", - [len_3] = "3/4", - [len_5] = "5/4", - [len_7] = "7/4", - [len_9_or_greater] = ">=9/4", -}; -#define NIENTE {NO_SYM, NO_SYM} - -struct decoder_table_entry { enum symbol first, second; }; -const struct decoder_table_entry decoder_table[][5] = { - /* out_of_range len_3 len_5 len_7 len_9_or_greater*/ - [NO_SYM] = {NIENTE, {sym_z, sym_z}, {sym_z, sym_x}, }, - [sym_x] = {NIENTE, {sym_x, NO_SYM}, {sym_y, sym_z}, {sym_y, sym_x}, {sym_y, sym_y}, }, - [sym_y] = {NIENTE, {sym_z, sym_z}, {sym_z, sym_x}, }, - [sym_z] = {NIENTE, {sym_z, NO_SYM}, {sym_x, NO_SYM}, {sym_y, NO_SYM}, {sym_y, NO_SYM}, }, + +struct diffmiller_state { + int initialized, pauses_count; + enum symbol old_state; + enum bit last_bit; + iso14443_frame *frame; + u_int32_t counter; + u_int16_t byte,crc; + u_int8_t parity; + struct { + u_int8_t in_frame:1; + u_int8_t frame_finished:1; + u_int8_t overflow:1; + u_int8_t error:1; + } flags; }; -int print_bits = 0; +struct diffmiller_state _state; inline void start_frame(struct diffmiller_state * const state) { @@ -141,8 +123,7 @@ inline void start_frame(struct diffmiller_state * const state) state->flags.in_frame = 1; //memset(state->frame, 0, sizeof(*state->frame)); - //memset(state->frame, 0, (u_int32_t)&(((iso14443_frame*)0)->data) ); - memset(state->frame, 0, 26 ); + memset(state->frame, 0, (u_int32_t)&(((iso14443_frame*)0)->data) ); performance_set_checkpoint("start_frame after memset"); } @@ -187,34 +168,8 @@ static inline void end_frame(struct diffmiller_state * const state) } } -static inline void Miller_Bit(struct diffmiller_state * const state, const enum bit bit) +static inline void Miller_Bit(struct diffmiller_state * const state, const int bit_value) { - switch(bit) { - case BIT_SOF: - if(print_bits) printf("SOF"); - start_frame(state); - break; - case BIT_0: - if(print_bits) printf(" 0"); - break; - case BIT_1: - if(print_bits) printf(" 1"); - break; - case BIT_EOF: - if(print_bits) printf(" EOF\n"); - end_frame(state); - break; - default: - if(print_bits) printf(" ERROR\n"); - state->flags.error = 1; - end_frame(state); - break; - } - - int bit_value; - if(bit==BIT_0) bit_value = 0; - else if(bit==BIT_1) bit_value = 1; - else return; if(state->counter<8) { state->byte=state->byte | (bit_value<counter); @@ -239,82 +194,64 @@ static inline void Miller_Bit(struct diffmiller_state * const state, const enum } } -static inline void Miller_Symbol(struct diffmiller_state * const state, const enum symbol symbol) -{ - static enum bit last_bit = BIT_ERROR; - static int in_frame = 0; - enum bit bit = BIT_ERROR; - - //DEBUGP("%c ", 'X'+(symbol-1)); - if(!in_frame) { - if(symbol == sym_z) - bit = BIT_SOF; - else - bit = BIT_ERROR; - } else { - switch(symbol) { - case sym_y: - if(last_bit == BIT_0) - bit = BIT_EOF; - else - bit = BIT_0; - break; - case sym_x: - bit = BIT_1; - break; - case sym_z: - bit = BIT_0; - break; - default: - bit = BIT_ERROR; - break; - } +#define PRINT_BIT(a) if(0){(void)a;} +//#define PRINT_BIT(a) usb_print_string(a) + +#define DO_BIT_0 { \ + Miller_Bit(state, 0); \ + PRINT_BIT(" 0"); \ } - - if(bit != BIT_EOF && last_bit == BIT_0) - Miller_Bit(state, last_bit); - if(bit != BIT_0) Miller_Bit(state, bit); - - last_bit = bit; - if(bit==BIT_SOF) { - in_frame = 1; - last_bit = BIT_ERROR; - } else if(bit==BIT_EOF || bit==BIT_ERROR) { - in_frame = 0; + +#define DO_BIT_1 { \ + Miller_Bit(state, 1); \ + PRINT_BIT(" 1"); \ } - -} -static inline void Miller_Edge(struct diffmiller_state * const state, const unsigned int delta) -{ - static enum symbol old_state = NO_SYM; - enum bit_length length = out_of_range; - - if( ALMOST_EQUAL(delta, BIT_LEN_3) ) { - length = len_3; - } else if( ALMOST_EQUAL(delta, BIT_LEN_5) ) { - length = len_5; - } else if( ALMOST_EQUAL(delta, BIT_LEN_7) ) { - length = len_7; - } else if( ALMOST_GREATER_THAN_OR_EQUAL(delta, BIT_LEN_9)) { - length = len_9_or_greater; +#define DO_SYMBOL_X \ + if(!in_frame) { \ + if(last_bit == BIT_0) DO_BIT_0; \ + error = 1; \ + end_frame(state); \ + PRINT_BIT(" ERROR\n"); \ + last_bit = BIT_ERROR; \ + in_frame = 0; \ + } else { \ + if(last_bit == BIT_0) DO_BIT_0; \ + DO_BIT_1; \ + last_bit = BIT_1; \ } - - const struct decoder_table_entry *entry; - entry = &decoder_table[old_state][length]; - //DEBUGP(" %c{%i}[%s]", 'X'-sym_x+old_state, delta, bit_length_descriptions[length]); - if(entry->first != NO_SYM) { - //DEBUGP("%c ", 'X'-sym_x+entry->first); - Miller_Symbol(state, old_state = entry->first); - } else { - DEBUGP("! "); + +#define DO_SYMBOL_Y \ + if(!in_frame) { \ + if(last_bit == BIT_0) DO_BIT_0; \ + error = 1; \ + end_frame(state); \ + PRINT_BIT(" ERROR\n"); \ + last_bit = BIT_ERROR; \ + in_frame = 0; \ + } else { \ + if(last_bit == BIT_0) { \ + end_frame(state); \ + PRINT_BIT(" EOF\n"); \ + last_bit = BIT_EOF; \ + in_frame = 0; \ + } else { \ + last_bit = BIT_0; \ + } \ } - - if(entry->second != NO_SYM) { - //DEBUGP("%c ", 'X'-sym_x+entry->second); - Miller_Symbol(state, old_state = entry->second); + +#define DO_SYMBOL_Z \ + if(!in_frame) { \ + if(last_bit == BIT_0) DO_BIT_0; \ + start_frame(state); \ + PRINT_BIT("SOF"); \ + in_frame = 1; \ + last_bit = BIT_ERROR; \ + last_bit = BIT_SOF; \ + } else { \ + if(last_bit == BIT_0) DO_BIT_0; \ + last_bit = BIT_0; \ } -} int iso14443a_decode_diffmiller(struct diffmiller_state * const state, iso14443_frame * const frame, @@ -324,19 +261,79 @@ int iso14443a_decode_diffmiller(struct diffmiller_state * const state, iso14443_ if(state->frame != NULL && state->frame != frame) return -EINVAL; state->frame = frame; + enum symbol old_state = state->old_state; + enum bit last_bit = state->last_bit; + int in_frame = state->flags.in_frame; + int error = state->flags.error; + for(; *offset < buflen; ) { + int delta; if(state->pauses_count) - Miller_Edge(state, buffer[(*offset)++] - PAUSE_LEN); + delta = buffer[(*offset)++] - PAUSE_LEN; else - Miller_Edge(state, buffer[(*offset)++]); + delta = buffer[(*offset)++]; + + switch(old_state) { + case sym_x: + if( ALMOST_EQUAL(delta, BIT_LEN_3) ) { + DO_SYMBOL_X; + old_state = sym_x; + } else if( ALMOST_EQUAL(delta, BIT_LEN_5) ) { + DO_SYMBOL_Y; + DO_SYMBOL_Z; + old_state = sym_z; + } else if( ALMOST_EQUAL(delta, BIT_LEN_7) ) { + DO_SYMBOL_Y; + DO_SYMBOL_X; + old_state = sym_x; + } else if( ALMOST_GREATER_THAN_OR_EQUAL(delta, BIT_LEN_9)) { + DO_SYMBOL_Y; + DO_SYMBOL_Y; + old_state = sym_y; + } + break; + case NO_SYM: /* Fall-Through */ + case sym_y: + if( ALMOST_EQUAL(delta, BIT_LEN_3) ) { + DO_SYMBOL_Z; + DO_SYMBOL_Z; + old_state = sym_z; + } else if( ALMOST_EQUAL(delta, BIT_LEN_5) ) { + DO_SYMBOL_Z; + DO_SYMBOL_X; + old_state = sym_x; + } + break; + case sym_z: + if( ALMOST_EQUAL(delta, BIT_LEN_3) ) { + DO_SYMBOL_Z; + old_state = sym_z; + } else if( ALMOST_EQUAL(delta, BIT_LEN_5) ) { + DO_SYMBOL_X; + old_state = sym_x; + } else if( ALMOST_GREATER_THAN_OR_EQUAL(delta, BIT_LEN_7)) { + DO_SYMBOL_Y; + old_state = sym_y; + } + break; + } if(state->flags.frame_finished) { state->flags.frame_finished = 0; + state->old_state = old_state; + state->last_bit = last_bit; + state->flags.in_frame = in_frame; + state->flags.error = error; performance_set_checkpoint("frame finished"); return 0; } } + state->old_state = old_state; + state->last_bit = last_bit; + state->flags.in_frame = in_frame; + state->flags.error = error; + return -EBUSY; } diff --git a/openpicc/application/tc_sniffer.c b/openpicc/application/tc_sniffer.c index cc21a2f..943a2ad 100644 --- a/openpicc/application/tc_sniffer.c +++ b/openpicc/application/tc_sniffer.c @@ -191,6 +191,11 @@ static void timing_loop(void) performance_set_checkpoint("end of first buffer"); handle_buffer(testdata2, sizeof(testdata2)/sizeof(testdata2[0])); performance_stop_report(); + DumpStringToUSB("Produced frame of "); DumpUIntToUSB(rx_frame.numbytes); + DumpStringToUSB(" bytes and "); DumpUIntToUSB(rx_frame.numbits); + DumpStringToUSB(" bits: "); DumpBufferToUSB((char*)rx_frame.data, rx_frame.numbytes + (rx_frame.numbits+7)/8 ); + DumpStringToUSB(" CRC "); if(rx_frame.parameters.a.crc) DumpStringToUSB("OK"); else DumpStringToUSB("ERROR"); + DumpStringToUSB("\n\r"); } } -- cgit v1.2.3