From 202b56a42c5e6a171ee43b469be48525d0e8e350 Mon Sep 17 00:00:00 2001 From: henryk Date: Wed, 12 Dec 2007 01:50:14 +0000 Subject: Add new miller decoder (not working yet) Vastly improve timing through CPU cycle counting. Jitter is now like 40ns (the SSC_DATA edge detection fuzziness) in 2 main clusters 4 CPU cycles (83ns) apart, plus an occasional glitch adding 4 CPU cycles in either direction git-svn-id: https://svn.openpcd.org:2342/trunk@385 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- openpicc/Makefile | 1 + openpicc/application/iso14443_layer3a.c | 27 ++++--- openpicc/application/iso14443_layer3a.h | 30 ++++---- openpicc/application/iso14443a_manchester.c | 1 + openpicc/application/iso14443a_miller.c | 112 ++++++++++++++++++++++++++++ openpicc/application/iso14443a_miller.h | 6 ++ openpicc/application/tc_fdt.c | 12 +-- openpicc/application/tc_fdt.h | 2 +- openpicc/os/boot/boot.s | 31 +++++++- 9 files changed, 187 insertions(+), 35 deletions(-) create mode 100644 openpicc/application/iso14443a_miller.c create mode 100644 openpicc/application/iso14443a_miller.h (limited to 'openpicc') diff --git a/openpicc/Makefile b/openpicc/Makefile index e35dc27..92a7351 100644 --- a/openpicc/Makefile +++ b/openpicc/Makefile @@ -90,6 +90,7 @@ ARM_SRC= \ application/usb_print.c \ application/iso14443_layer3a.c \ application/iso14443a_manchester.c \ + application/iso14443a_miller.c \ application/load_modulation.c \ application/decoder_miller.c \ application/decoder_nrzl.c \ diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c index 0b5ceaf..35152db 100644 --- a/openpicc/application/iso14443_layer3a.c +++ b/openpicc/application/iso14443_layer3a.c @@ -37,13 +37,14 @@ #include "load_modulation.h" #include "decoder.h" #include "iso14443a_manchester.h" +#include "iso14443a_miller.h" #include "led.h" static enum ISO14443_STATES state = STARTING_UP; const iso14443_frame ATQA_FRAME = { TYPE_A, {{STANDARD_FRAME, PARITY}}, - 2, + 2, 0, 0, {4, 0}, {} @@ -85,11 +86,11 @@ const iso14443_frame NULL_FRAME = { void iso14443_transmit(ssc_dma_tx_buffer_t *buf, int fdt, int div) { tc_cdiv_set_divider(div); - if(fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 || - fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1) { - /* FIXME Implement */ - return; - } + if(fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0) { + fdt = tc_fdt_get_next_slot(ISO14443A_FDT_SHORT_0, ISO14443A_FDT_SLOTLEN); + } else if (fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1) { + fdt = tc_fdt_get_next_slot(ISO14443A_FDT_SHORT_1, ISO14443A_FDT_SLOTLEN); + } ssc_tx_fiq_fdt_cdiv = fdt -3*div -1; tc_fdt_set(ssc_tx_fiq_fdt_cdiv -MAX_TF_FIQ_ENTRY_DELAY -MAX_TF_FIQ_OVERHEAD); ssc_tx_fiq_fdt_ssc = fdt -div +1; @@ -162,7 +163,7 @@ static int prefill_buffer(ssc_dma_tx_buffer_t *dest, const iso14443_frame *src) } -static u_int8_t received_buffer[256]; +static iso14443_frame received_frame; static void enable_reception(enum ssc_mode mode) { tc_fdt_set(0xff00); @@ -307,6 +308,12 @@ void iso14443_layer3a_state_machine (void *pvParameters) LAYER3_DEBUG(", woke up to send ATQA\n\r"); atqa_sent = 0; } + if(1) { + DumpStringToUSB("Decoded: "); + iso14443a_decode_miller(&received_frame, buffer->data, buffer->len); + DumpBufferToUSB((char*)received_frame.data, 100); + DumpStringToUSB("\n\r"); + } /* For debugging, wait 1ms, then wait for another frame * Normally we'd go to anticol from here*/ vTaskDelay(portTICK_RATE_MS); @@ -320,12 +327,12 @@ void iso14443_layer3a_state_machine (void *pvParameters) break; case ACTIVE: case ACTIVE_STAR: - if(0) { +#if 0 DumpStringToUSB("Decoded: "); decoder_decode(DECODER_MILLER, (const char*)buffer->data, buffer->len, received_buffer); DumpBufferToUSB((char*)received_buffer, 100); DumpStringToUSB("\n\r"); - } +#endif /* Wait for another frame */ if(0) { ssc_rx_mode_set(SSC_MODE_14443A_STANDARD); @@ -336,7 +343,7 @@ void iso14443_layer3a_state_machine (void *pvParameters) if(prefill_buffer(&ssc_tx_buffer, &NULL_FRAME)) { usb_print_string_f("Sending response ...",0); ssc_tx_buffer.state = PROCESSING; - iso14443_transmit(&ssc_tx_buffer, 1, 8); + iso14443_transmit(&ssc_tx_buffer, ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1, 8); while( ssc_tx_buffer.state != FREE ) { vTaskDelay(portTICK_RATE_MS); } diff --git a/openpicc/application/iso14443_layer3a.h b/openpicc/application/iso14443_layer3a.h index 495ca2e..26a8a2d 100644 --- a/openpicc/application/iso14443_layer3a.h +++ b/openpicc/application/iso14443_layer3a.h @@ -16,21 +16,6 @@ enum ISO14443_STATES { }; /******************** RX ************************************/ -/* Magic delay, don't know where it comes from */ -#define MAGIC_OFFSET -32 -/* Delay from modulation till detection in SSC_DATA */ -#define DETECTION_DELAY 11 -/* See fdt_timinig.dia for these values */ -#define MAX_TF_FIQ_ENTRY_DELAY 16 -#define MAX_TF_FIQ_OVERHEAD 75 /* guesstimate */ -extern volatile int fdt_offset; -/* standard derived magic values */ -#define ISO14443A_FDT_SLOTLEN 128 -#define ISO14443A_FDT_OFFSET_1 84 -#define ISO14443A_FDT_OFFSET_0 20 -#define ISO14443A_FDT_SHORT_1 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_1 +fdt_offset +MAGIC_OFFSET -DETECTION_DELAY) -#define ISO14443A_FDT_SHORT_0 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_0 +fdt_offset +MAGIC_OFFSET -DETECTION_DELAY) - #ifdef FOUR_TIMES_OVERSAMPLING /* definitions for four-times oversampling */ /* Sample values for the REQA and WUPA short frames */ @@ -82,6 +67,21 @@ extern volatile int fdt_offset; #endif /******************** TX ************************************/ +/* Magic delay, don't know where it comes from */ +#define MAGIC_OFFSET -32 +/* Delay from modulation till detection in SSC_DATA */ +#define DETECTION_DELAY 11 +/* See fdt_timinig.dia for these values */ +#define MAX_TF_FIQ_ENTRY_DELAY 16 +#define MAX_TF_FIQ_OVERHEAD 75 /* guesstimate */ +extern volatile int fdt_offset; +/* standard derived magic values */ +#define ISO14443A_FDT_SLOTLEN 128 +#define ISO14443A_FDT_OFFSET_1 84 +#define ISO14443A_FDT_OFFSET_0 20 +#define ISO14443A_FDT_SHORT_1 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_1 +fdt_offset +MAGIC_OFFSET -DETECTION_DELAY) +#define ISO14443A_FDT_SHORT_0 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_0 +fdt_offset +MAGIC_OFFSET -DETECTION_DELAY) + /* in bytes, not counting parity */ #define MAXIMUM_FRAME_SIZE 256 diff --git a/openpicc/application/iso14443a_manchester.c b/openpicc/application/iso14443a_manchester.c index be4de21..4093d57 100644 --- a/openpicc/application/iso14443a_manchester.c +++ b/openpicc/application/iso14443a_manchester.c @@ -1,5 +1,6 @@ /* ISO14443A Manchester encoder for OpenPICC * (C) 2006 by Harald Welte + * (C) 2007 by Henryk Plötz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/openpicc/application/iso14443a_miller.c b/openpicc/application/iso14443a_miller.c new file mode 100644 index 0000000..deb9a8a --- /dev/null +++ b/openpicc/application/iso14443a_miller.c @@ -0,0 +1,112 @@ +/* ISO14443A Manchester encoder for OpenPICC + * (C) 2007 by Henryk Plötz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include + +#include + +#include "iso14443_layer3a.h" +#include "usb_print.h" +#include "cmd.h" + +#ifdef FOUR_TIMES_OVERSAMPLING +#define OVERSAMPLING_RATE 4 + +/* definitions for four-times oversampling */ +#define SEQ_X 0x4 +#define SEQ_Y 0x0 +#define SEQ_Z 0x1 +#else +#define OVERSAMPLING_RATE 2 +#define SEQ_X 0x2 +#define SEQ_Y 0x0 +#define SEQ_Z 0x1 +#endif + +enum miller_sequence { + SEQUENCE_X, + SEQUENCE_Y, + SEQUENCE_Z, +}; + +#define BIT_ENDMARKER -1 + +int iso14443a_decode_miller(iso14443_frame *frame, + const u_int8_t *sample_buf, const u_int16_t sample_buf_len) +{ + signed int i, j, bit = 0, last_bit = 0; + enum miller_sequence current_seq; + unsigned int bitpos = 0; + + memset(frame, 0, sizeof(frame)); + frame->type = TYPE_A; + frame->parameters.a.parity = GIVEN_PARITY; + + for(i=0; i>(j*OVERSAMPLING_RATE)) & ~(~0 << OVERSAMPLING_RATE); + switch(sample) { + case SEQ_X: current_seq = SEQUENCE_X; break; + case SEQ_Y: current_seq = SEQUENCE_Y; break; + case SEQ_Z: current_seq = SEQUENCE_Z; break; + default: current_seq = SEQUENCE_Y; + } + + switch(current_seq) { + case SEQ_X: + DumpStringToUSB("X"); + bit = 1; break; + case SEQ_Y: /* Fall-through to SEQ_Z */ + DumpStringToUSB("Y"); + if(last_bit == 0) { + bit = BIT_ENDMARKER; + break; + } + case SEQ_Z: + DumpStringToUSB("Z"); + bit = 0; break; + } + + switch(bit) { + case BIT_ENDMARKER: + bitpos--; + break; + case 0: /* Fall-through */ + case 1: { + int bytepos = bitpos/9; + if(bitpos % 9 == 8) { /* Parity bit */ + frame->parity[ bytepos/8 ] |= (bit<<(bytepos%8)); + } else { + frame->data[ bytepos ] |= (bit<<(bitpos%9)); + } + } + } + + last_bit = bit; + bitpos++; + } + } + + frame->numbytes = bitpos/9; + frame->numbits = bitpos%9; + DumpStringToUSB("\n\r"); + + return 0; +} diff --git a/openpicc/application/iso14443a_miller.h b/openpicc/application/iso14443a_miller.h new file mode 100644 index 0000000..dbd7f85 --- /dev/null +++ b/openpicc/application/iso14443a_miller.h @@ -0,0 +1,6 @@ +#ifndef ISO14443A_MILLER_H_ +#define ISO14443A_MILLER_H_ + +extern int iso14443a_decode_miller(iso14443_frame *frame, const u_int8_t *sample_buf, const u_int16_t sample_buf_len); + +#endif /*ISO14443A_MILLER_H_*/ diff --git a/openpicc/application/tc_fdt.c b/openpicc/application/tc_fdt.c index 7413e11..2a306ef 100644 --- a/openpicc/application/tc_fdt.c +++ b/openpicc/application/tc_fdt.c @@ -50,16 +50,12 @@ void tc_fdt_set(u_int16_t count) tcfdt->TC_RA = count; } -void __ramfunc tc_fdt_set_to_next_slot(int last_bit) +int tc_fdt_get_next_slot(int reference_time, int slotlen) { - int reference_time; - if(last_bit == 0) reference_time = ISO14443A_FDT_OFFSET_0; - else reference_time = ISO14443A_FDT_OFFSET_1; - - if(tcfdt->TC_SR & AT91C_TC_CLKSTA) + /*if(tcfdt->TC_SR & AT91C_TC_CLKSTA) while(tcfdt->TC_CV != 0xFFFF && (tcfdt->TC_CV - reference_time) % 128 != 0); - tcfdt->TC_CCR = AT91C_TC_SWTRG; - tc_fdt_set(2*128); + tcfdt->TC_CCR = AT91C_TC_SWTRG;*/ + return tcfdt->TC_CV + (slotlen-((tcfdt->TC_CV - reference_time) % slotlen)) + 3*slotlen; } diff --git a/openpicc/application/tc_fdt.h b/openpicc/application/tc_fdt.h index 28e7e7e..6e89f51 100644 --- a/openpicc/application/tc_fdt.h +++ b/openpicc/application/tc_fdt.h @@ -5,6 +5,6 @@ extern void tc_fdt_init(void); extern void tc_fdt_set(u_int16_t count); -extern void __ramfunc tc_fdt_set_to_next_slot(int last_bit); +extern int tc_fdt_get_next_slot(int reference_time, int slotlen); #endif diff --git a/openpicc/os/boot/boot.s b/openpicc/os/boot/boot.s index 0000479..c065a6d 100644 --- a/openpicc/os/boot/boot.s +++ b/openpicc/os/boot/boot.s @@ -250,10 +250,39 @@ my_fiq_handler: ldr r11, =ssc_tx_fiq_fdt_cdiv ldr r11, [r11] /* r11 == ssc_tx_fiq_fdt_cdiv */ +/* Problem: LDR from the timer still takes too long and causes us to miss the exact time. + * Strategy: Spin on TC2 till we are very near the actual time. Then load the timer value, calculate + * the difference to the target, then do a countdown spin without reading the timer. + * + * At 47.923200 MHz 7 processor cycles are 2 carrier cycles of the 13.56MHz carrier + */ + .equ SUB_TIME, 20 /* subtract 20 carrier cycles == 70 processor cycles */ + .equ ADD_TIME, (70-20) /* Add x processor cycles */ + + mov r8, #SUB_TIME + sub r11, r11, r8 + .wait_for_fdt_cdiv: ldr r8, [r12, #TC2_CV] cmp r8, r11 - bmi .wait_for_fdt_cdiv /* spin while TC2.CV is less fdt_cdiv */ + bmi .wait_for_fdt_cdiv /* spin while TC2.CV is less fdt_cdiv-SUB_TIM */ + + ldr r8, [r12, #TC2_CV] + sub r11, r11, r8 /* r11 == fdt_cdiv-SUB_TIME - TC2.CV */ + + mov r8, #0x07 + mul r11, r8, r11 /* r11 = r11 * 7 */ + mov r11, r11, ASR #1 /* r11 = r11 / 2 */ + + mov r8, #ADD_TIME + add r11, r11, r8 /* r11 = r11 + ADD_TIME */ + + mov r11, r11, ASR #2 /* r11 = r11 / 4 (4 is the number of cycles per loop run below) */ + + mov r8, #1 +.wait_for_my_time: + subs r11, r11, r8 + bge .wait_for_my_time str r9, [r12, #TC_CCR] /* SWTRG on TC0 */ -- cgit v1.2.3