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
This commit is contained in:
parent
3d0e1db9d1
commit
202b56a42c
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_*/
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue