diff options
Diffstat (limited to 'openpicc/application/ssc_picc.c')
-rw-r--r-- | openpicc/application/ssc_picc.c | 41 |
1 files changed, 23 insertions, 18 deletions
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); |