From 91d960e6945a1bb8e70e41d62fbb3be93b16f989 Mon Sep 17 00:00:00 2001 From: henryk Date: Sat, 15 Dec 2007 16:31:46 +0000 Subject: Prepare generic ISO 14443A reception mode (no short/standard distinction), prerequisite for proper frame handling and anticol, doesn't work yet git-svn-id: https://svn.openpcd.org:2342/trunk@390 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- openpicc/application/iso14443_layer3a.c | 22 ++++++++++++------ openpicc/application/iso14443_layer3a.h | 7 ++++++ openpicc/application/ssc_picc.c | 41 ++++++++++++++++++--------------- openpicc/application/ssc_picc.h | 6 +++++ 4 files changed, 51 insertions(+), 25 deletions(-) (limited to 'openpicc/application') diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c index b9ee0b9..e3ce769 100644 --- a/openpicc/application/iso14443_layer3a.c +++ b/openpicc/application/iso14443_layer3a.c @@ -75,6 +75,14 @@ const iso14443_frame NULL_FRAME = { #define INITIAL_FRAME NULL_FRAME #endif +#if 1 +#define SHORT_MODE SSC_MODE_14443A_SHORT +#define STANDARD_MODE SSC_MODE_14443A_STANDARD +#else +#define SHORT_MODE SSC_MODE_14443A +#define STANDARD_MODE SSC_MODE_14443A +#endif + #define ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 -1 #define ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1 -2 @@ -104,7 +112,7 @@ void __ramfunc iso14443_layer3a_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode { (void)ssc_sr; int fdt; - if(ssc_mode == SSC_MODE_14443A_SHORT && samples) { + if((ssc_mode == SSC_MODE_14443A_SHORT || ssc_mode == SSC_MODE_14443A) && samples) { ISO14443A_SHORT_TYPE sample = *(ISO14443A_SHORT_TYPE*)samples; portBASE_TYPE send_atqa = 0; if(sample == REQA) { @@ -259,9 +267,9 @@ void iso14443_layer3a_state_machine (void *pvParameters) DumpStringToUSB("\n\r"); state=INITIAL_STATE; if(INITIAL_STATE == IDLE) - enable_reception(SSC_MODE_14443A_SHORT); + enable_reception(SHORT_MODE); else if(INITIAL_STATE == ACTIVE) - enable_reception(SSC_MODE_14443A_STANDARD); + enable_reception(STANDARD_MODE); else enable_reception(SSC_MODE_NONE); } else { LAYER3_DEBUG("SSC TX overflow error, please debug"); @@ -324,18 +332,18 @@ void iso14443_layer3a_state_machine (void *pvParameters) * Normally we'd go to anticol from here*/ vTaskDelay(portTICK_RATE_MS); if(prefill_buffer(&ssc_tx_buffer, &ATQA_FRAME)) { - enable_reception(SSC_MODE_14443A_SHORT); + enable_reception(SHORT_MODE); } } else { /* Wait for another frame */ - enable_reception(SSC_MODE_14443A_SHORT); + enable_reception(SHORT_MODE); } break; case ACTIVE: case ACTIVE_STAR: /* Wait for another frame */ if(0) { - ssc_rx_mode_set(SSC_MODE_14443A_STANDARD); + ssc_rx_mode_set(STANDARD_MODE); ssc_rx_start(); } else { //vTaskDelay(portTICK_RATE_MS); @@ -351,7 +359,7 @@ void iso14443_layer3a_state_machine (void *pvParameters) usb_print_flush(); } /* Wait for another frame */ - enable_reception(SSC_MODE_14443A_STANDARD); + enable_reception(STANDARD_MODE); } default: break; diff --git a/openpicc/application/iso14443_layer3a.h b/openpicc/application/iso14443_layer3a.h index 26a8a2d..9b00ccb 100644 --- a/openpicc/application/iso14443_layer3a.h +++ b/openpicc/application/iso14443_layer3a.h @@ -18,6 +18,7 @@ enum ISO14443_STATES { /******************** RX ************************************/ #ifdef FOUR_TIMES_OVERSAMPLING /* definitions for four-times oversampling */ +#define ISO14443A_SAMPLE_LEN 4 /* Sample values for the REQA and WUPA short frames */ #define REQA 0x10410441 #define WUPA 0x04041041 @@ -39,6 +40,8 @@ enum ISO14443_STATES { #else /* definitions for two-times oversampling */ +#define ISO14443A_SAMPLE_LEN 2 + #define REQA 0x4929 #define WUPA 0x2249 @@ -46,6 +49,9 @@ enum ISO14443_STATES { #define ISO14443A_SOF_LEN 2 #define ISO14443A_SHORT_LEN 18 +#define ISO14443A_EOF_SAMPLE 0x00 +#define ISO14443A_EOF_LEN 4 + #endif /* A short frame should be received in one single SSC transfer */ @@ -66,6 +72,7 @@ enum ISO14443_STATES { #error ISO14443A_SHORT_LEN defined too big #endif +#define ISO14443A_MAX_RX_FRAME_SIZE_IN_BITS (256*9 +2) /******************** TX ************************************/ /* Magic delay, don't know where it comes from */ #define MAGIC_OFFSET -32 diff --git a/openpicc/application/ssc_picc.c b/openpicc/application/ssc_picc.c index 721989f..09be1e5 100644 --- a/openpicc/application/ssc_picc.c +++ b/openpicc/application/ssc_picc.c @@ -76,7 +76,9 @@ static const ssc_mode_def ssc_sizes[] = { /* 14443A Short Frame: 1 transfer of ISO14443A_SHORT_LEN bits */ [SSC_MODE_14443A_SHORT] = {SSC_MODE_14443A_SHORT, ISO14443A_SHORT_TRANSFER_SIZE, 1}, /* 14443A Standard Frame: FIXME 16 transfers of 32 bits (maximum number), resulting in 512 samples */ - [SSC_MODE_14443A_STANDARD] = {SSC_MODE_14443A_STANDARD, 32, 4}, + [SSC_MODE_14443A_STANDARD] = {SSC_MODE_14443A_STANDARD, 32, 16}, + /* 14443A Frame, don't care if standard or short */ + [SSC_MODE_14443A] = {SSC_MODE_14443A, ISO14443A_SAMPLE_LEN, ISO14443A_MAX_RX_FRAME_SIZE_IN_BITS}, [SSC_MODE_14443B] = {SSC_MODE_14443B, 32, 16}, /* 64 bytes */ [SSC_MODE_EDGE_ONE_SHOT] = {SSC_MODE_EDGE_ONE_SHOT, 32, 16}, /* 64 bytes */ [SSC_MODE_CONTINUOUS] = {SSC_MODE_CONTINUOUS, 32, 511}, /* 2044 bytes */ @@ -243,6 +245,7 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode) { u_int8_t data_len=0, num_data=0, sync_len=0; u_int32_t start_cond=0; + u_int8_t stop = 0; /* disable Rx and all Rx interrupt sources */ AT91F_SSC_DisableRx(AT91C_BASE_SSC); @@ -263,6 +266,14 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode) data_len = 32; num_data = 16; /* FIXME */ break; + case SSC_MODE_14443A: + start_cond = AT91C_SSC_START_0; + sync_len = ISO14443A_SOF_LEN; + ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; + data_len = ISO14443A_SAMPLE_LEN; + num_data = 16; /* Start with 16, then switch to continuous in the IRQ handler */ + stop = 1; /* Actually the documentation indicates that setting STOP makes switching to continuous unnecessary */ + break; case SSC_MODE_14443B: /* start sampling at first falling data edge */ //start_cond = @@ -289,7 +300,7 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode) //| AT91C_SSC_MSBF ; ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | - (0x2 << 6) | AT91C_SSC_CKI | start_cond; + (0x2 << 6) | AT91C_SSC_CKI | start_cond | (stop << 12); /* Enable Rx DMA */ AT91F_PDC_EnableRx(rx_pdc); @@ -384,16 +395,6 @@ void ssc_tf_irq(u_int32_t pio) { #endif -//static struct openpcd_hdr opcd_ssc_hdr = { -// .cmd = OPENPCD_CMD_SSC_READ, -//}; - -//static inline void init_opcdhdr(struct req_ctx *rctx) -//{ -// memcpy(rctx->data, &opcd_ssc_hdr, sizeof(opcd_ssc_hdr)); -// rctx->tot_len = sizeof(opcd_ssc_hdr); -//} - static ssc_irq_ext_t irq_extension = NULL; ssc_irq_ext_t ssc_set_irq_extension(ssc_irq_ext_t ext_handler) { ssc_irq_ext_t old = irq_extension; @@ -419,22 +420,26 @@ static void __ramfunc ssc_irq(void) ssc_dma_rx_buffer_t *inbuf=NULL; DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode); - if (ssc_sr & AT91C_SSC_CP0 && ssc_state.mode == SSC_MODE_14443A_SHORT) { + if ((ssc_sr & AT91C_SSC_CP0) && (ssc_state.mode == SSC_MODE_14443A_SHORT || ssc_state.mode == SSC_MODE_14443A)) { + if(ssc_state.mode == SSC_MODE_14443A && ISO14443A_SOF_LEN != ISO14443A_EOF_LEN) { + /* Need to reprogram FSLEN */ + ssc->SSC_RFMR = (ssc->SSC_RFMR & ~(0xf << 16)) | ( ((ISO14443A_EOF_LEN-1)&0xf) << 16 ); + } /* Short frame, busy loop till the frame is received completely to * prevent a second irq entrance delay when the actual frame end * irq is raised. (The scheduler masks interrupts for about 56us, * which is too much for anticollision.) */ int i = 0; vLedBlinkRed(); - while( ! ((ssc_sr=ssc->SSC_SR) & AT91C_SSC_ENDRX) ) { + while( ! ((ssc_sr=ssc->SSC_SR) & (AT91C_SSC_ENDRX | AT91C_SSC_CP1)) ) { i++; - if(i > 9600) break; + if(i > 9600) break; /* Break out, clearly this is not a short frame or a reception error happened */ } ssc_sr |= orig_ssc_sr; vLedSetRed(1); } - if (ssc_sr & AT91C_SSC_ENDRX) { + if (ssc_sr & (AT91C_SSC_ENDRX | AT91C_SSC_CP1)) { /* Ignore empty frames */ if (ssc_state.mode == SSC_MODE_CONTINUOUS) { /* This code section is probably bitrotten by now. */ @@ -472,7 +477,7 @@ static void __ramfunc ssc_irq(void) ssc_state.buffer[0] = ssc_state.buffer[1]; ssc_state.buffer[1] = NULL; if(ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT || ssc_state.mode == SSC_MODE_14443A_SHORT - || ssc_state.mode == SSC_MODE_14443A_STANDARD) { + || ssc_state.mode == SSC_MODE_14443A_STANDARD || (ssc_state.mode == SSC_MODE_14443A && ssc_sr & AT91C_SSC_CP1)) { // Stop sampling here ssc_rx_stop(); } else { @@ -554,7 +559,7 @@ void ssc_rx_start(void) if(ssc_state.mode != SSC_MODE_14443A_SHORT) __ssc_rx_load(1); /* Enable Reception */ - AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | + AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | AT91C_SSC_CP1 | AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN); AT91F_PDC_EnableRx(rx_pdc); AT91F_SSC_EnableRx(AT91C_BASE_SSC); diff --git a/openpicc/application/ssc_picc.h b/openpicc/application/ssc_picc.h index a01b16d..9600bab 100644 --- a/openpicc/application/ssc_picc.h +++ b/openpicc/application/ssc_picc.h @@ -21,6 +21,7 @@ enum ssc_mode { SSC_MODE_NONE, SSC_MODE_14443A_SHORT, SSC_MODE_14443A_STANDARD, + SSC_MODE_14443A, SSC_MODE_14443B, SSC_MODE_EDGE_ONE_SHOT, SSC_MODE_CONTINUOUS, @@ -51,6 +52,11 @@ extern int ssc_get_metric(ssc_metric metric); #define SSC_RX_BUFFER_SIZE 2048 #define SSC_DMA_BUFFER_COUNT 4 +#if SSC_RX_BUFFER_SIZE < ISO14443A_MAX_RX_FRAME_SIZE_IN_BITS +#undef SSC_RX_BUFFER_SIZE +#define SSC_RX_BUFFER_SIZE ISO14443A_MAX_RX_FRAME_SIZE_IN_BITS +#endif + typedef enum { FREE=0, /* Buffer is free */ PENDING, /* Buffer has been given to the DMA controller and is currently being filled */ -- cgit v1.2.3