summaryrefslogtreecommitdiff
path: root/firmware/src/picc
diff options
context:
space:
mode:
authorlaforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-10-15 20:21:40 +0000
committerlaforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2006-10-15 20:21:40 +0000
commit28eb4a57d93f2cf13d3693ce4dba677f22cbf1cc (patch)
tree3cc72ad1aeb7c543f91989d4cb055f06d81cd33f /firmware/src/picc
parentb2f42e7acf929490965348e826b5fa86c51515f5 (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.c29
-rw-r--r--firmware/src/picc/openpicc.c8
-rw-r--r--firmware/src/picc/pll.c4
-rw-r--r--firmware/src/picc/poti.c1
-rw-r--r--firmware/src/picc/ssc_picc.c285
-rw-r--r--firmware/src/picc/tc_cdiv_sync.c10
-rw-r--r--firmware/src/picc/tc_fdt.c85
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;
}
personal git repositories of Harald Welte. Your mileage may vary