summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2007-12-12 01:50:14 +0000
committerhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2007-12-12 01:50:14 +0000
commit202b56a42c5e6a171ee43b469be48525d0e8e350 (patch)
tree84260eadbedd8575f158b95a43c3a481c35362ec
parent3d0e1db9d118f85441a9d559ba2fa7baa7195eee (diff)
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
-rw-r--r--openpicc/Makefile1
-rw-r--r--openpicc/application/iso14443_layer3a.c27
-rw-r--r--openpicc/application/iso14443_layer3a.h30
-rw-r--r--openpicc/application/iso14443a_manchester.c1
-rw-r--r--openpicc/application/iso14443a_miller.c112
-rw-r--r--openpicc/application/iso14443a_miller.h6
-rw-r--r--openpicc/application/tc_fdt.c12
-rw-r--r--openpicc/application/tc_fdt.h2
-rw-r--r--openpicc/os/boot/boot.s31
9 files changed, 187 insertions, 35 deletions
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 <hwelte@hmw-consulting.de>
+ * (C) 2007 by Henryk Plötz <henryk@ploetzli.ch>
*
* 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 <henryk@ploetzli.ch>
+ *
+ * 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 <openpicc.h>
+#include <FreeRTOS.h>
+
+#include <string.h>
+
+#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<sample_buf_len && bit != BIT_ENDMARKER; i++) {
+ for(j=0; j<(signed)(sizeof(sample_buf[0])*8)/OVERSAMPLING_RATE && bit != BIT_ENDMARKER; j++) {
+ int sample = (sample_buf[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 */
personal git repositories of Harald Welte. Your mileage may vary