summaryrefslogtreecommitdiff
path: root/openpicc/application/ssc_picc.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application/ssc_picc.c')
-rw-r--r--openpicc/application/ssc_picc.c41
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);
personal git repositories of Harald Welte. Your mileage may vary