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
This commit is contained in:
parent
9cde1dd082
commit
7f0e281614
|
@ -36,22 +36,6 @@
|
||||||
#define DEBUGP (void)
|
#define DEBUGP (void)
|
||||||
#define printf usb_print_string
|
#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
|
* 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:
|
* 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 symbol {NO_SYM=0, sym_x, sym_y, sym_z};
|
||||||
enum bit { BIT_ERROR, BIT_SOF, BIT_0, BIT_1, BIT_EOF };
|
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; };
|
struct diffmiller_state {
|
||||||
const struct decoder_table_entry decoder_table[][5] = {
|
int initialized, pauses_count;
|
||||||
/* out_of_range len_3 len_5 len_7 len_9_or_greater*/
|
enum symbol old_state;
|
||||||
[NO_SYM] = {NIENTE, {sym_z, sym_z}, {sym_z, sym_x}, },
|
enum bit last_bit;
|
||||||
[sym_x] = {NIENTE, {sym_x, NO_SYM}, {sym_y, sym_z}, {sym_y, sym_x}, {sym_y, sym_y}, },
|
iso14443_frame *frame;
|
||||||
[sym_y] = {NIENTE, {sym_z, sym_z}, {sym_z, sym_x}, },
|
u_int32_t counter;
|
||||||
[sym_z] = {NIENTE, {sym_z, NO_SYM}, {sym_x, NO_SYM}, {sym_y, NO_SYM}, {sym_y, NO_SYM}, },
|
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)
|
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;
|
state->flags.in_frame = 1;
|
||||||
|
|
||||||
//memset(state->frame, 0, sizeof(*state->frame));
|
//memset(state->frame, 0, sizeof(*state->frame));
|
||||||
//memset(state->frame, 0, (u_int32_t)&(((iso14443_frame*)0)->data) );
|
memset(state->frame, 0, (u_int32_t)&(((iso14443_frame*)0)->data) );
|
||||||
memset(state->frame, 0, 26 );
|
|
||||||
performance_set_checkpoint("start_frame after memset");
|
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) {
|
if(state->counter<8) {
|
||||||
state->byte=state->byte | (bit_value<<state->counter);
|
state->byte=state->byte | (bit_value<<state->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)
|
#define PRINT_BIT(a) if(0){(void)a;}
|
||||||
{
|
//#define PRINT_BIT(a) usb_print_string(a)
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void Miller_Edge(struct diffmiller_state * const state, const unsigned int delta)
|
#define DO_BIT_0 { \
|
||||||
{
|
Miller_Bit(state, 0); \
|
||||||
static enum symbol old_state = NO_SYM;
|
PRINT_BIT(" 0"); \
|
||||||
enum bit_length length = out_of_range;
|
}
|
||||||
|
|
||||||
if( ALMOST_EQUAL(delta, BIT_LEN_3) ) {
|
#define DO_BIT_1 { \
|
||||||
length = len_3;
|
Miller_Bit(state, 1); \
|
||||||
} else if( ALMOST_EQUAL(delta, BIT_LEN_5) ) {
|
PRINT_BIT(" 1"); \
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct decoder_table_entry *entry;
|
#define DO_SYMBOL_X \
|
||||||
entry = &decoder_table[old_state][length];
|
if(!in_frame) { \
|
||||||
//DEBUGP(" %c{%i}[%s]", 'X'-sym_x+old_state, delta, bit_length_descriptions[length]);
|
if(last_bit == BIT_0) DO_BIT_0; \
|
||||||
if(entry->first != NO_SYM) {
|
error = 1; \
|
||||||
//DEBUGP("%c ", 'X'-sym_x+entry->first);
|
end_frame(state); \
|
||||||
Miller_Symbol(state, old_state = entry->first);
|
PRINT_BIT(" ERROR\n"); \
|
||||||
} else {
|
last_bit = BIT_ERROR; \
|
||||||
DEBUGP("! ");
|
in_frame = 0; \
|
||||||
|
} else { \
|
||||||
|
if(last_bit == BIT_0) DO_BIT_0; \
|
||||||
|
DO_BIT_1; \
|
||||||
|
last_bit = BIT_1; \
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entry->second != NO_SYM) {
|
#define DO_SYMBOL_Y \
|
||||||
//DEBUGP("%c ", 'X'-sym_x+entry->second);
|
if(!in_frame) { \
|
||||||
Miller_Symbol(state, old_state = entry->second);
|
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; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#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,
|
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;
|
if(state->frame != NULL && state->frame != frame) return -EINVAL;
|
||||||
state->frame = frame;
|
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; ) {
|
for(; *offset < buflen; ) {
|
||||||
|
int delta;
|
||||||
if(state->pauses_count)
|
if(state->pauses_count)
|
||||||
Miller_Edge(state, buffer[(*offset)++] - PAUSE_LEN);
|
delta = buffer[(*offset)++] - PAUSE_LEN;
|
||||||
else
|
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) {
|
if(state->flags.frame_finished) {
|
||||||
state->flags.frame_finished = 0;
|
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");
|
performance_set_checkpoint("frame finished");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->old_state = old_state;
|
||||||
|
state->last_bit = last_bit;
|
||||||
|
state->flags.in_frame = in_frame;
|
||||||
|
state->flags.error = error;
|
||||||
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,11 @@ static void timing_loop(void)
|
||||||
performance_set_checkpoint("end of first buffer");
|
performance_set_checkpoint("end of first buffer");
|
||||||
handle_buffer(testdata2, sizeof(testdata2)/sizeof(testdata2[0]));
|
handle_buffer(testdata2, sizeof(testdata2)/sizeof(testdata2[0]));
|
||||||
performance_stop_report();
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue