diff options
author | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-10-15 20:21:40 +0000 |
---|---|---|
committer | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-10-15 20:21:40 +0000 |
commit | 28eb4a57d93f2cf13d3693ce4dba677f22cbf1cc (patch) | |
tree | 3cc72ad1aeb7c543f91989d4cb055f06d81cd33f /firmware/src/picc | |
parent | b2f42e7acf929490965348e826b5fa86c51515f5 (diff) |
- add svn:ignore property to make 'svn st' output more realistic
- remove old copy+paste+edit port of parts of librfid
- add ability to directly link librfid.a from mainline librfid
- make usb string descriptors optional again (config.h)
- fix TC_CDIV to reset correctly on swtrig (For OpenPICC)
- temporarily re-implement ep0_send_data() in pcd_enumerate.c
- make UDP_PUPv4 switching conditional to PCD
- introduce DEBUG_UNBUFFERED define in dbgu.c
- fix some signed/unsigned/typecast related compiler warnings
- remove dead code from src/os/led.c
- implement a 'mdelay' and 'usleep' stub function (FIXME!)
- rename rc632_... functions into opcd_rc632_... to avoid confusion
- introduce new 'main_librfid' TARGET
- make main_{reqa,analog} work with librfid rather than old code
- introduce mroe debugging options for FIQ handler code in Cstartup_app
- lots of PICC work that doesn't need comments now
git-svn-id: https://svn.openpcd.org:2342/trunk@266 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'firmware/src/picc')
-rw-r--r-- | firmware/src/picc/main_openpicc.c | 29 | ||||
-rw-r--r-- | firmware/src/picc/openpicc.c | 8 | ||||
-rw-r--r-- | firmware/src/picc/pll.c | 4 | ||||
-rw-r--r-- | firmware/src/picc/poti.c | 1 | ||||
-rw-r--r-- | firmware/src/picc/ssc_picc.c | 285 | ||||
-rw-r--r-- | firmware/src/picc/tc_cdiv_sync.c | 10 | ||||
-rw-r--r-- | firmware/src/picc/tc_fdt.c | 85 |
7 files changed, 309 insertions, 113 deletions
diff --git a/firmware/src/picc/main_openpicc.c b/firmware/src/picc/main_openpicc.c index df754de..ff89dc2 100644 --- a/firmware/src/picc/main_openpicc.c +++ b/firmware/src/picc/main_openpicc.c @@ -35,8 +35,8 @@ #include <picc/ssc_picc.h> #include <picc/load_modulation.h> -static const u_int16_t cdivs[] = { 128, 64, 32, 16 }; -static u_int8_t cdiv_idx = 0; +static const u_int16_t cdivs[] = { 8192, 2048, 1024, 512, 128, 64, 32, 16 }; +static u_int8_t cdiv_idx = 6; static u_int16_t duty_percent = 22; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -53,12 +53,12 @@ void _init_func(void) poti_init(); load_mod_init(); tc_cdiv_init(); - //tc_fdt_init(); + tc_fdt_init(); pwm_init(); adc_init(); ssc_rx_init(); - // ssc_tx_init(); - + ssc_tx_init(); + /* high-level protocol */ decoder_init(); opicc_usbapi_init(); @@ -80,7 +80,7 @@ static void help(void) DEBUGPCR("v: decrease load_mod b: increase load_mod\r\n" "B: read button S: toggle nSLAVE_RESET\r\n" "a: SSC stop s: SSC start\r\n" - "d: SSC mode select"); + "d: SSC mode select T: TC_CDIV_HELP enable\r\n"); } int _main_dbgu(char key) @@ -88,6 +88,7 @@ int _main_dbgu(char key) static u_int8_t poti = 64; static u_int8_t pll_inh = 1; static u_int8_t ssc_mode = 1; + static u_int8_t sync_enabled = 0; DEBUGPCRF("main_dbgu"); @@ -218,12 +219,25 @@ int _main_dbgu(char key) ssc_rx_start(); break; case 'd': - ssc_rx_mode_set(++ssc_mode); + ssc_mode++; + if (ssc_mode >= 6) + ssc_mode = 0; + ssc_rx_mode_set(ssc_mode); DEBUGPCRF("SSC MODE %u", ssc_mode); break; + case 'T': + if (sync_enabled) { + tc_cdiv_sync_disable(); + sync_enabled = 0; + } else { + tc_cdiv_sync_enable(); + sync_enabled = 1; + } + break; } tc_cdiv_print(); + //tc_fdt_print(); return -EINVAL; } @@ -236,5 +250,6 @@ void _main_func(void) /* next we deal with incoming reqyests from USB EP1 (OUT) */ usb_in_process(); + udp_unthrottle(); ssc_rx_unthrottle(); } diff --git a/firmware/src/picc/openpicc.c b/firmware/src/picc/openpicc.c index 7b2b5f2..fa1f840 100644 --- a/firmware/src/picc/openpicc.c +++ b/firmware/src/picc/openpicc.c @@ -20,6 +20,7 @@ static u_int16_t opicc_regs[_OPICC_NUM_REGS] = { [OPICC_REG_14443A_FDT0] = 1236, [OPICC_REG_14443A_FDT1] = 1172, [OPICC_REG_14443A_STATE] = ISO14443A_ST_POWEROFF, + [OPICC_REG_14443A_ATQA] = 0x0001, [OPICC_REG_RX_CLK_DIV] = 32, [OPICC_REG_RX_CLK_PHASE] = 0, [OPICC_REG_RX_CONTROL] = 0, @@ -62,9 +63,10 @@ static int opicc_reg_usb_in(struct req_ctx *rctx) break; case OPENPCD_CMD_PICC_REG_WRITE: if (rctx->tot_len < sizeof(*poh) + sizeof(u_int16_t)) { - poh->flags = OPENPCD_FLAG_ERROR; - } - opicc_reg_write(poh->reg, *val16); + /* we only have an 8bit write */ + opicc_reg_write(poh->reg, poh->val); + } else + opicc_reg_write(poh->reg, *val16); break; default: return USB_ERR(USB_ERR_CMD_UNKNOWN); diff --git a/firmware/src/picc/pll.c b/firmware/src/picc/pll.c index 7eb49a4..e48911d 100644 --- a/firmware/src/picc/pll.c +++ b/firmware/src/picc/pll.c @@ -43,9 +43,9 @@ static void pll_lock_change_cb(u_int32_t pio) DEBUGPCRF("PLL LOCK: %d", pll_is_locked()); #if 1 if (pll_is_locked()) - led_switch(1, 1); + led_switch(2, 1); else - led_switch(1, 0); + led_switch(2, 0); #endif } diff --git a/firmware/src/picc/poti.c b/firmware/src/picc/poti.c index 4c94994..e5701dc 100644 --- a/firmware/src/picc/poti.c +++ b/firmware/src/picc/poti.c @@ -31,7 +31,6 @@ void poti_comp_carr(u_int8_t position) while (!(spi->SPI_SR & AT91C_SPI_TDRE)) { } AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SS2_DT_THRESH); - //for (i = 0; i < 0xff; i++) { } /* shift one left, since it is a seven-bit value written as 8 bit xfer */ spi->SPI_TDR = position & 0x7f; while (!(spi->SPI_SR & AT91C_SPI_TDRE)) { } diff --git a/firmware/src/picc/ssc_picc.c b/firmware/src/picc/ssc_picc.c index d4db71a..50dce06 100644 --- a/firmware/src/picc/ssc_picc.c +++ b/firmware/src/picc/ssc_picc.c @@ -22,6 +22,8 @@ * TX side is interconnected with load modulation circuitry */ +//#undef DEBUG + #include <errno.h> #include <string.h> #include <sys/types.h> @@ -31,8 +33,13 @@ #include <os/usb_handler.h> #include <os/dbgu.h> +#include <os/led.h> #include "../openpcd.h" +#include <picc/tc_cdiv_sync.h> + +//#define DEBUG_SSC_REFILL + /* definitions for four-times oversampling */ #define REQA 0x10410441 #define WUPA 0x04041041 @@ -46,6 +53,7 @@ enum ssc_mode { SSC_MODE_14443A_STANDARD, SSC_MODE_14443B, SSC_MODE_EDGE_ONE_SHOT, + SSC_MODE_CONTINUOUS, }; struct ssc_state { @@ -54,23 +62,41 @@ struct ssc_state { }; static struct ssc_state ssc_state; +static const u_int16_t ssc_dmasize[] = { + [SSC_MODE_NONE] = 16, + [SSC_MODE_14443A_SHORT] = 16, /* 64 bytes */ + [SSC_MODE_14443A_STANDARD] = 16, /* 64 bytes */ + [SSC_MODE_14443B] = 16, /* 64 bytes */ + [SSC_MODE_EDGE_ONE_SHOT] = 16, /* 64 bytes */ + [SSC_MODE_CONTINUOUS] = 511, /* 2044 bytes */ +}; + /* This is for four-times oversampling */ -#define ISO14443A_SOF_SAMPLE 0x08 +#define ISO14443A_SOF_SAMPLE 0x01 #define ISO14443A_SOF_LEN 4 +#define SSC_RX_IRQ_MASK (AT91C_SSC_RXRDY | \ + AT91C_SSC_OVRUN | \ + AT91C_SSC_ENDRX | \ + AT91C_SSC_RXBUFF | \ + AT91C_SSC_RXSYN | \ + AT91C_SSC_CP0 | \ + AT91C_SSC_CP1) + +#define SSC_TX_IRQ_MASK (AT91C_SSC_TXRDY | \ + AT91C_SSC_TXEMPTY | \ + AT91C_SSC_ENDTX | \ + AT91C_SSC_TXBUFE | \ + AT91C_SSC_TXSYN) + void ssc_rx_mode_set(enum ssc_mode ssc_mode) { u_int8_t data_len, num_data, sync_len; u_int32_t start_cond; - /* disable Rx */ - ssc->SSC_CR = AT91C_SSC_RXDIS; - - /* disable all Rx related interrupt sources */ - AT91F_SSC_DisableIt(ssc, AT91C_SSC_RXRDY | - AT91C_SSC_OVRUN | AT91C_SSC_ENDRX | - AT91C_SSC_RXBUFF | AT91C_SSC_RXSYN | - AT91C_SSC_CP0 | AT91C_SSC_CP1); + /* disable Rx and all Rx interrupt sources */ + AT91F_SSC_DisableRx(AT91C_BASE_SSC); + AT91F_SSC_DisableIt(ssc, SSC_RX_IRQ_MASK); switch (ssc_mode) { case SSC_MODE_14443A_SHORT: @@ -78,41 +104,48 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode) sync_len = ISO14443A_SOF_LEN; ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; data_len = 32; - num_data = 1; + num_data = 16; break; case SSC_MODE_14443A_STANDARD: start_cond = AT91C_SSC_START_0; sync_len = ISO14443A_SOF_LEN; ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; - data_len = 1; - num_data = 1; /* FIXME */ + data_len = 32; + num_data = 16; /* FIXME */ break; case SSC_MODE_14443B: /* start sampling at first falling data edge */ //start_cond = break; case SSC_MODE_EDGE_ONE_SHOT: + case SSC_MODE_CONTINUOUS: + /* unfortunately we don't have RD and RF interconnected + * (at least not yet in the current hardware) */ //start_cond = AT91C_SSC_START_EDGE_RF; start_cond = AT91C_SSC_START_CONTINOUS; sync_len = 0; - data_len = 8; - num_data = 50; + data_len = 32; + num_data = 16; + break; + case SSC_MODE_NONE: + goto out_set_mode; break; - default: - return; } + //ssc->SSC_RFMR = AT91C_SSC_MSBF | (data_len-1) & 0x1f | ssc->SSC_RFMR = (data_len-1) & 0x1f | (((num_data-1) & 0x0f) << 8) | (((sync_len-1) & 0x0f) << 16); - ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond; + ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | + AT91C_SSC_CKI | start_cond; + /* Enable Rx DMA */ AT91F_PDC_EnableRx(rx_pdc); + /* Enable RX interrupts */ - AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | + AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | AT91C_SSC_CP0 | AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); - +out_set_mode: ssc_state.mode = ssc_mode; - } static void ssc_tx_mode_set(enum ssc_mode ssc_mode) @@ -121,16 +154,15 @@ static void ssc_tx_mode_set(enum ssc_mode ssc_mode) u_int32_t start_cond; /* disable Tx */ - ssc->SSC_CR = AT91C_SSC_TXDIS; + AT91F_SSC_DisableTx(AT91C_BASE_SSC); /* disable all Tx related interrupt sources */ - ssc->SSC_IDR = AT91C_SSC_TXRDY | AT91C_SSC_TXEMPTY | AT91C_SSC_ENDTX | - AT91C_SSC_TXBUFE | AT91C_SSC_TXSYN; + AT91F_SSC_DisableIt(ssc, SSC_TX_IRQ_MASK); switch (ssc_mode) { case SSC_MODE_14443A_SHORT: start_cond = AT91C_SSC_START_RISE_RF; - sync_len = ISO14443A_SOF_LEN; + sync_len = 0; data_len = 32; num_data = 1; break; @@ -138,7 +170,7 @@ static void ssc_tx_mode_set(enum ssc_mode ssc_mode) start_cond = AT91C_SSC_START_0; sync_len = ISO14443A_SOF_LEN; ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE; - data_len = 1; + data_len = 32; num_data = 1; /* FIXME */ break; } @@ -147,11 +179,13 @@ static void ssc_tx_mode_set(enum ssc_mode ssc_mode) (((sync_len-1) & 0x0f) << 16); ssc->SSC_TCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond; + AT91F_SSC_EnableIt(ssc, AT91C_SSC_TXSYN); + AT91F_SSC_EnableTx(AT91C_BASE_SSC); #if 0 /* Enable RX interrupts */ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | - AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); - AT91F_PDC_EnableRx(rx_pdc); + AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE); + AT91F_PDC_EnableTx(tx_pdc); ssc_state.mode = ssc_mode; #endif @@ -167,7 +201,7 @@ static struct openpcd_hdr opcd_ssc_hdr = { static inline void init_opcdhdr(struct req_ctx *rctx) { memcpy(rctx->data, &opcd_ssc_hdr, sizeof(opcd_ssc_hdr)); - rctx->tot_len = MAX_HDRSIZE + MAX_REQSIZE -1; + rctx->tot_len = sizeof(opcd_ssc_hdr); } #ifdef DEBUG_SSC_REFILL @@ -176,6 +210,36 @@ static inline void init_opcdhdr(struct req_ctx *rctx) #define DEBUGR(x, args ...) #endif +static int __ramfunc __ssc_rx_refill(int secondary) +{ + struct req_ctx *rctx; + + rctx = req_ctx_find_get(1, RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY); + if (!rctx) { + DEBUGP("no_rctx_for_refill! "); + return -1; + } + init_opcdhdr(rctx); + DEBUGR("filling SSC RX%u dma ctx: %u (len=%u) ", secondary, + req_ctx_num(rctx), rctx->size); + rctx->tot_len = ssc_dmasize[ssc_state.mode]*4 + + sizeof(struct openpcd_hdr); + if (secondary) { + AT91F_PDC_SetNextRx(rx_pdc, rctx->data+MAX_HDRSIZE, + ssc_dmasize[ssc_state.mode]); + ssc_state.rx_ctx[1] = rctx; + } else { + AT91F_PDC_SetRx(rx_pdc, rctx->data+MAX_HDRSIZE, + ssc_dmasize[ssc_state.mode]); + ssc_state.rx_ctx[0] = rctx; + } + + tc_cdiv_sync_reset(); + + return 0; +} + +#if 0 static char dmabuf1[512]; static char dmabuf2[512]; @@ -188,19 +252,16 @@ static char dmabuf2[512]; */ static int8_t ssc_rx_refill(void) { -#if 1 struct req_ctx *rctx; - + DEBUGR("refill "); +#if 1 rctx = req_ctx_find_get(1, RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY); - if (!rctx) { - DEBUGPCRF("no rctx for refill!"); - return -1; - } - init_opcdhdr(rctx); - + DEBUGP("SSC_SR=0x%08x ", ssc->SSC_SR); if (AT91F_PDC_IsRxEmpty(rx_pdc)) { - DEBUGR("filling primary SSC RX dma ctx"); - AT91F_PDC_SetRx(rx_pdc, &rctx->data[MAX_HDRSIZE], + DEBUGR("filling primary SSC RX dma ctx: %u (len=%u) ", + req_ctx_num(rctx), rctx->size); + rctx->tot_len = rctx->size; + AT91F_PDC_SetRx(rx_pdc, rctx->data+MAX_HDRSIZE, (rctx->size-MAX_HDRSIZE)>>2); ssc_state.rx_ctx[0] = rctx; @@ -215,8 +276,10 @@ static int8_t ssc_rx_refill(void) } if (AT91F_PDC_IsNextRxEmpty(rx_pdc)) { - DEBUGR("filling secondary SSC RX dma ctx"); - AT91F_PDC_SetNextRx(rx_pdc, &rctx->data[MAX_HDRSIZE], + DEBUGR("filling secondary SSC RX dma ctx: %u (len=%u) ", + req_ctx_num(rctx), rctx->size); + rctx->tot_len = rctx->size; + AT91F_PDC_SetNextRx(rx_pdc, rctx->data+MAX_HDRSIZE, (rctx->size-MAX_HDRSIZE)>2); ssc_state.rx_ctx[1] = rctx; return 2; @@ -236,17 +299,74 @@ static int8_t ssc_rx_refill(void) DEBUGPCRF("prim/secnd DMA busy, can't refill"); #endif } +#endif #define ISO14443A_FDT_SHORT_1 1236 #define ISO14443A_FDT_SHORT_0 1172 -static void ssc_irq(void) +static void __ramfunc ssc_irq(void) { u_int32_t ssc_sr = ssc->SSC_SR; DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode); + if (ssc_sr & AT91C_SSC_ENDRX) { +#if 1 + /* in a one-shot sample, we don't want to keep + * sampling further after having received the first + * packet. */ + if (ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT) { + DEBUGP("DISABLE_RX "); + AT91F_SSC_DisableRx(AT91C_BASE_SSC); + } + //AT91F_SSC_DisableIt(AT91C_BASE_SSC, SSC_RX_IRQ_MASK); +#endif + //DEBUGP("Sending primary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len); + /* Mark primary RCTX as ready to send for usb */ + req_ctx_set_state(ssc_state.rx_ctx[0], + RCTX_STATE_UDP_EP2_PENDING); + //RCTX_STATE_FREE); + /* second buffer gets propagated to primary */ + ssc_state.rx_ctx[0] = ssc_state.rx_ctx[1]; + ssc_state.rx_ctx[1] = NULL; + if (ssc_sr & AT91C_SSC_RXBUFF) { + DEBUGP("RXBUFF! "); + if (ssc_state.rx_ctx[0]) { + //DEBUGP("Sending secondary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len); + req_ctx_set_state(ssc_state.rx_ctx[0], + RCTX_STATE_UDP_EP2_PENDING); + //RCTX_STATE_FREE); + } + if (__ssc_rx_refill(0) == -1) + AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX | + AT91C_SSC_RXBUFF | + AT91C_SSC_OVRUN); + } + + if (__ssc_rx_refill(1) == -1) + AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX | + AT91C_SSC_RXBUFF | + AT91C_SSC_OVRUN); + + udp_refill_ep(2); + +#if 0 + if (__ssc_rx_refill(1) == -1) + AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX | + AT91C_SSC_RXBUFF | + AT91C_SSC_OVRUN); +#endif + } + if (ssc_sr & AT91C_SSC_OVRUN) - DEBUGP("RX OVERRUN "); + DEBUGP("RX_OVERRUN "); + + if (ssc_sr & AT91C_SSC_CP0) + DEBUGP("CP0 "); + + if (ssc_sr & AT91C_SSC_TXSYN) + DEBUGP("TXSYN "); +#if 0 + led_toggle(1); switch (ssc_state.mode) { case SSC_MODE_14443A_SHORT: @@ -269,54 +389,39 @@ static void ssc_irq(void) case SSC_MODE_14443A_STANDARD: case SSC_MODE_EDGE_ONE_SHOT: - - if (ssc_sr & (AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF)) { -#if 1 - /* Mark primary RCTX as ready to send for usb */ - req_ctx_set_state(ssc_state.rx_ctx[0], - RCTX_STATE_UDP_EP2_PENDING); - /* second buffer gets propagated to primary */ - ssc_state.rx_ctx[0] = ssc_state.rx_ctx[1]; - ssc_state.rx_ctx[1] = NULL; -#endif - - if (ssc_sr & AT91C_SSC_RXBUFF) { - DEBUGP("RXBUFF, shouldn't happen! "); -#if 0 - req_ctx_set_state(ssc_state.rx_ctx[0], - RCTX_STATE_UDP_EP2_PENDING); -#endif - } - if (ssc_rx_refill() == -1) - AT91F_AIC_DisableIt(ssc, AT91C_SSC_ENDRX | - AT91C_SSC_RXBUFF | - AT91C_SSC_OVRUN); - } + DEBUGP("ONE_SHOT "); + break; + default: + DEBUGP("UNKNOWN_MODE "); break; } - DEBUGPCR(""); + +#endif + DEBUGPCR("I"); AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SSC); } void ssc_rx_unthrottle(void) { - AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | + AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN); } void ssc_rx_start(void) { - DEBUGPCRF("starting SSC RX\n"); + //DEBUGPCRF("starting SSC RX\n"); /* Enable Reception */ - AT91F_SSC_EnableRx(ssc); + AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | + AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN); + AT91F_SSC_EnableRx(AT91C_BASE_SSC); } void ssc_rx_stop(void) { /* Disable reception */ - AT91F_SSC_DisableRx(ssc); + AT91F_SSC_DisableRx(AT91C_BASE_SSC); } void ssc_tx_init(void) @@ -325,8 +430,10 @@ void ssc_tx_init(void) * PA17 !! */ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN_PWM); AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, OPENPCD_PIO_MFIN_SSC_TX | - OPENPCD_PIO_MFOUT_SSC_RX | OPENPCD_PIO_SSP_CKIN, - 0); + OPENPCD_PIO_MFOUT_SSC_RX | OPENPCD_PIO_SSP_CKIN | + AT91C_PIO_PA15, 0); + + ssc_tx_mode_set(SSC_MODE_14443A_SHORT); } static int ssc_usb_in(struct req_ctx *rctx) @@ -338,19 +445,25 @@ static int ssc_usb_in(struct req_ctx *rctx) /* FIXME: allow host to specify mode */ ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT); ssc_rx_start(); + req_ctx_put(rctx); + return 0; break; case OPENPCD_CMD_SSC_WRITE: /* FIXME: implement this */ //ssc_tx_start() break; + default: + return USB_ERR(USB_ERR_CMD_UNKNOWN); + break; } - req_ctx_put(rctx); - return -EINVAL; + return (poh->flags & OPENPCD_FLAG_RESPOND) ? USB_RET_RESPOND : 0; } void ssc_rx_init(void) -{ +{ + tc_cdiv_sync_init(); + rx_pdc = (AT91PS_PDC) &(ssc->SSC_RPR); AT91F_SSC_CfgPMC(); @@ -362,27 +475,37 @@ void ssc_rx_init(void) AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SSC, OPENPCD_IRQ_PRIO_SSC, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &ssc_irq); - /* Reset */ - //ssc->SSC_CR = AT91C_SSC_SWRST; /* don't divide clock inside SSC, we do that in tc_cdiv */ ssc->SSC_CMR = 0; +#if 0 ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | - AT91C_SSC_START_CONTINOUS; - /* Data bits per Data N = 32-1, Data words per Frame = 15-1 (=60 byte)*/ + AT91C_SSC_CKI | AT91C_SSC_START_CONTINOUS; + /* Data bits per Data N = 32-1 + * Data words per Frame = 15-1 (=60 byte)*/ ssc->SSC_RFMR = 31 | AT91C_SSC_MSBF | (14 << 8); +#endif - ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT); + __ssc_rx_refill(0); + __ssc_rx_refill(1); + ssc_rx_mode_set(SSC_MODE_NONE); +#if 0 AT91F_PDC_EnableRx(rx_pdc); /* Enable RX interrupts */ AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); +#endif + /* FIXME: This is hardcoded for REQA 0x26 */ + tc_fdt_set(ISO14443A_FDT_SHORT_0); + AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SSC); - usb_hdlr_register(&ssc_usb_in, OPENPCD_CMD_CLS_SSC); + //usb_hdlr_register(&ssc_usb_in, OPENPCD_CMD_CLS_SSC); + + DEBUGP("\r\n"); } void ssc_fini(void) diff --git a/firmware/src/picc/tc_cdiv_sync.c b/firmware/src/picc/tc_cdiv_sync.c index 5762c2c..b87d9e5 100644 --- a/firmware/src/picc/tc_cdiv_sync.c +++ b/firmware/src/picc/tc_cdiv_sync.c @@ -14,11 +14,6 @@ static u_int8_t enabled; static void pio_data_change(u_int32_t pio) { - DEBUGPCRF("PIO=%d", pio); - - if (pio != 27) - return; - /* FIXME: start ssc if we're in one-shot mode */ //ssc_rx_start(); } @@ -34,7 +29,7 @@ static void __ramfunc cdsync_cb(void) DEBUGP("SWTRG CV=0x%08x ", *AT91C_TC0_CV); #ifdef DISABLE DEBUGP("CDIV_SYNC_FLIP "); - *AT91C_PIOA_IDR = PIO_DATA; + //now in fiq *AT91C_PIOA_IDR = PIO_DATA; #endif //ssc_rx_start(); } @@ -70,6 +65,9 @@ void tc_cdiv_sync_enable(void) DEBUGP("CDIV_SYNC_ENABLE "); tc_cdiv_sync_reset(); +#ifndef DISABLE + *AT91C_PIOA_IER = PIO_DATA; +#endif } extern void (*fiq_handler)(void); diff --git a/firmware/src/picc/tc_fdt.c b/firmware/src/picc/tc_fdt.c index b5e6a27..1651b32 100644 --- a/firmware/src/picc/tc_fdt.c +++ b/firmware/src/picc/tc_fdt.c @@ -21,11 +21,11 @@ /* PICC Simulator Side: * In order to support responding to synchronous frames (REQA/WUPA/ANTICOL), * we need a second Timer/Counter (TC2). This unit is reset by an external - * event (rising edge of modulation pause PCD->PICC) connected to TIOB2, and - * counts up to a configurable number of carrier clock cycles (RA). Once the - * RA value is reached, TIOA2 will see a rising edge. This rising edge will - * be interconnected to TF (Tx Frame) of the SSC to start transmitting our - * synchronous response. + * event (rising edge of modulation pause PCD->PICC, falling edge of + * demodulated data) connected to TIOB2, and counts up to a configurable + * number of carrier clock cycles (RA). Once the RA value is reached, TIOA2 + * will see a rising edge. This rising edge will be interconnected to TF (Tx + * Frame) of the SSC to start transmitting our synchronous response. * */ @@ -37,9 +37,55 @@ #include <os/tc_cdiv.h> #include <picc/tc_fdt.h> +static AT91PS_TC tcfdt = AT91C_BASE_TC2; + void tc_fdt_set(u_int16_t count) { - tcb->TCB_TC2.TC_RA = count; + tcfdt->TC_RA = count; +} + + +/* 'count' number of carrier cycles after the last modulation pause, + * we deem the frame to have ended */ +void tc_frame_end_set(u_int16_t count) +{ + tcfdt->TC_RB = count; +} + +static void tc_fdt_irq(void) +{ + u_int32_t sr = tcfdt->TC_SR; + DEBUGP("tc_fdt_irq: TC2_SR=0x%08x TC2_CV=0x%08x ", + sr, tcfdt->TC_CV); + + if (sr & AT91C_TC_ETRGS) { + DEBUGP("Ext_trigger "); + } + if (sr & AT91C_TC_CPAS) { + DEBUGP("FDT_expired "); + /* FIXME: if we are in anticol / sync mode, + * we could do software triggering of SSC TX, + * but IIRC the hardware does this by TF */ + } + if (sr & AT91C_TC_CPBS) { + DEBUGP("Frame_end "); + /* FIXME: stop ssc (in continuous mode), + * take care of preparing synchronous response if + * we operate in anticol mode.*/ + } + if (sr & AT91C_TC_CPCS) { + DEBUGP("Compare_C "); + } + DEBUGPCR(""); +} + +void tc_fdt_print(void) +{ + DEBUGP("TC2_CV=0x%08x ", tcfdt->TC_CV); + DEBUGP("TC2_CMR=0x%08x ", tcfdt->TC_CMR); + DEBUGP("TC2_SR=0x%08x ", tcfdt->TC_SR); + DEBUGP("TC2_RA=0x%04x, TC2_RB=0x%04x, TC2_RC=0x%04x", + tcfdt->TC_RA, tcfdt->TC_RB, tcfdt->TC_RC); } void tc_fdt_init(void) @@ -49,19 +95,32 @@ void tc_fdt_init(void) AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, ((unsigned int) 1 << AT91C_ID_TC2)); /* Enable Clock for TC2 */ - tcb->TCB_TC2.TC_CCR = AT91C_TC_CLKEN; + tcfdt->TC_CCR = AT91C_TC_CLKEN; + + tcfdt->TC_RC = 0xffff; + tc_frame_end_set(128*2); /* Clock XC1, Wave Mode, No automatic reset on RC comp * TIOA2 in RA comp = set, TIOA2 on RC comp = clear, + * TIOA2 on EEVT = clear * TIOB2 as input, EEVT = TIOB2, Reset/Trigger on EEVT */ - tcb->TCB_TC2.TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE | - AT91C_TC_WAVESEL_UP | - AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR | - AT91C_TC_BEEVT_NONE | AT91C_TC_BCPB_NONE | - AT91C_TC_EEVT_TIOB | AT91C_TC_ETRGEDG_RISING | - AT91C_TC_ENETRG ; + tcfdt->TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE | + AT91C_TC_WAVESEL_UP | + AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR | + AT91C_TC_AEEVT_CLEAR | + AT91C_TC_BEEVT_NONE | AT91C_TC_BCPB_NONE | + AT91C_TC_EEVT_TIOB | AT91C_TC_ETRGEDG_FALLING | + AT91C_TC_ENETRG | AT91C_TC_CPCSTOP ; /* Reset to start timers */ tcb->TCB_BCR = 1; + + AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC2, + OPENPCD_IRQ_PRIO_TC_FDT, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &tc_fdt_irq); + AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC2); + + tcfdt->TC_IER = AT91C_TC_CPAS | AT91C_TC_CPBS | AT91C_TC_CPCS | + AT91C_TC_ETRGS; } |