summaryrefslogtreecommitdiff
path: root/openpicc
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc')
-rw-r--r--openpicc/application/iso14443_layer3a.c37
-rw-r--r--openpicc/application/iso14443_layer3a.h13
-rw-r--r--openpicc/application/ssc_picc.c15
-rw-r--r--openpicc/application/ssc_picc.h2
-rw-r--r--openpicc/application/tc_fdt.c4
-rw-r--r--openpicc/config/atmel-rom.ld8
-rw-r--r--openpicc/fdt_timing.diabin0 -> 2147 bytes
-rw-r--r--openpicc/os/boot/Cstartup_SAM7.c4
-rw-r--r--openpicc/os/boot/boot.s43
9 files changed, 92 insertions, 34 deletions
diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c
index c4e02cd..0b5ceaf 100644
--- a/openpicc/application/iso14443_layer3a.c
+++ b/openpicc/application/iso14443_layer3a.c
@@ -74,20 +74,43 @@ const iso14443_frame NULL_FRAME = {
#define INITIAL_FRAME NULL_FRAME
#endif
+#define ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 -1
+#define ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1 -2
+
+/* Transmit a frame in ISO14443A mode from buffer buf at fdt carrier cycles
+ * after the end of the last modulation pause from the PCD with a clock divisor
+ * of div. Set fdt to ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 or _1 to have the
+ * transmission start at the next possible interval. Use _0 when the last bit
+ * from the PCD was a 0 and _1 when it was a 1. */
+void iso14443_transmit(ssc_dma_tx_buffer_t *buf, int fdt, int div)
+{
+ tc_cdiv_set_divider(div);
+ if(fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 ||
+ fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1) {
+ /* FIXME Implement */
+ return;
+ }
+ ssc_tx_fiq_fdt_cdiv = fdt -3*div -1;
+ tc_fdt_set(ssc_tx_fiq_fdt_cdiv -MAX_TF_FIQ_ENTRY_DELAY -MAX_TF_FIQ_OVERHEAD);
+ ssc_tx_fiq_fdt_ssc = fdt -div +1;
+ ssc_tx_start(buf);
+}
+
static int atqa_sent = 0;
/* Running in ISR mode */
void __ramfunc iso14443_layer3a_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode, u_int8_t* samples)
{
(void)ssc_sr;
+ int fdt;
if(ssc_mode == SSC_MODE_14443A_SHORT && samples) {
ISO14443A_SHORT_TYPE sample = *(ISO14443A_SHORT_TYPE*)samples;
portBASE_TYPE send_atqa = 0;
if(sample == REQA) {
- tc_fdt_set(ISO14443A_FDT_SHORT_0);
+ fdt = ISO14443A_FDT_SHORT_0;
if(state == IDLE)
send_atqa = 1;
} else if(sample == WUPA) {
- tc_fdt_set(ISO14443A_FDT_SHORT_1);
+ fdt = ISO14443A_FDT_SHORT_1;
if(state == IDLE || state == HALT)
send_atqa = 1;
}
@@ -97,13 +120,13 @@ void __ramfunc iso14443_layer3a_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode
if(ssc_tx_buffer.state == PREFILLED && ssc_tx_buffer.source == &ATQA_FRAME) {
ssc_tx_buffer.state = PROCESSING;
vLedSetGreen(1);
- tc_cdiv_set_divider(8);
- ssc_tx_start(&ssc_tx_buffer);
+ iso14443_transmit(&ssc_tx_buffer, fdt, 8);
atqa_sent = 1;
vLedSetGreen(0);
}
vLedSetGreen(1);
}
+ vLedSetGreen(0);
}
}
@@ -142,7 +165,7 @@ static int prefill_buffer(ssc_dma_tx_buffer_t *dest, const iso14443_frame *src)
static u_int8_t received_buffer[256];
static void enable_reception(enum ssc_mode mode) {
- tc_fdt_set(ISO14443A_FDT_SHORT_0);
+ tc_fdt_set(0xff00);
ssc_rx_mode_set(mode);
#ifdef FOUR_TIMES_OVERSAMPLING
tc_cdiv_set_divider(32);
@@ -313,9 +336,7 @@ void iso14443_layer3a_state_machine (void *pvParameters)
if(prefill_buffer(&ssc_tx_buffer, &NULL_FRAME)) {
usb_print_string_f("Sending response ...",0);
ssc_tx_buffer.state = PROCESSING;
- tc_cdiv_set_divider(8);
- tc_fdt_set_to_next_slot(1);
- ssc_tx_start(&ssc_tx_buffer);
+ iso14443_transmit(&ssc_tx_buffer, 1, 8);
while( ssc_tx_buffer.state != FREE ) {
vTaskDelay(portTICK_RATE_MS);
}
diff --git a/openpicc/application/iso14443_layer3a.h b/openpicc/application/iso14443_layer3a.h
index 0c2a909..b71c13f 100644
--- a/openpicc/application/iso14443_layer3a.h
+++ b/openpicc/application/iso14443_layer3a.h
@@ -16,17 +16,18 @@ enum ISO14443_STATES {
};
/******************** RX ************************************/
-/* measured TF->FIQ->SSC TX start delay (~3.480us) in carrier cycles */
-#define TF_FIQ_SSC_DELAY 47
-//#define TF_FIQ_SSC_DELAY 40
-#define FALLING_EDGE_DETECTION_DELAY 12
+/* Magic delay, don't know where it comes from */
+#define MAGIC_DELAY -32
+/* See fdt_timinig.dia for these values */
+#define MAX_TF_FIQ_ENTRY_DELAY 16
+#define MAX_TF_FIQ_OVERHEAD 75 /* guesstimate */
extern volatile int fdt_offset;
/* standard derived magic values */
#define ISO14443A_FDT_SLOTLEN 128
#define ISO14443A_FDT_OFFSET_1 84
#define ISO14443A_FDT_OFFSET_0 20
-#define ISO14443A_FDT_SHORT_1 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_1 -FALLING_EDGE_DETECTION_DELAY +fdt_offset -TF_FIQ_SSC_DELAY)
-#define ISO14443A_FDT_SHORT_0 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_0 -FALLING_EDGE_DETECTION_DELAY +fdt_offset -TF_FIQ_SSC_DELAY)
+#define ISO14443A_FDT_SHORT_1 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_1 +fdt_offset +MAGIC_DELAY)
+#define ISO14443A_FDT_SHORT_0 (ISO14443A_FDT_SLOTLEN*9 + ISO14443A_FDT_OFFSET_0 +fdt_offset +MAGIC_DELAY)
#ifdef FOUR_TIMES_OVERSAMPLING
/* definitions for four-times oversampling */
diff --git a/openpicc/application/ssc_picc.c b/openpicc/application/ssc_picc.c
index 10beaab..3da1dbe 100644
--- a/openpicc/application/ssc_picc.c
+++ b/openpicc/application/ssc_picc.c
@@ -302,6 +302,17 @@ out_set_mode:
* by the fiq handler to see whether to start the transmitter. */
#define USE_SSC_TX_TF_WORKAROUND
volatile u_int32_t ssc_tx_pending = 0;
+
+/* This is the time that the TF FIQ should spin until before SWTRG'ing the tc_cdiv.
+ * See fdt_timing.dia. Note: This means transmission is broken without USE_SSC_TX_TF_WORKAROUND */
+volatile u_int32_t ssc_tx_fiq_fdt_cdiv = 0;
+/* This is the time that the TF FIQ should spin until before starting the SSC
+ * There must be enough time between these two! */
+volatile u_int32_t ssc_tx_fiq_fdt_ssc = 0;
+#ifndef USE_SSC_TX_TF_WORKAROUND
+#error Transmission is broken without USE_SSC_TX_TF_WORKAROUND, see comments in code
+#endif
+
void ssc_tf_irq(u_int32_t pio);
void ssc_tx_start(ssc_dma_tx_buffer_t *buf)
{
@@ -613,8 +624,8 @@ void ssc_rx_init(void)
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);
+ /* Will be set to a real value some time later */
+ tc_fdt_set(0xff00);
AT91F_AIC_EnableIt(AT91C_ID_SSC);
diff --git a/openpicc/application/ssc_picc.h b/openpicc/application/ssc_picc.h
index df6da36..5eb1160 100644
--- a/openpicc/application/ssc_picc.h
+++ b/openpicc/application/ssc_picc.h
@@ -84,5 +84,7 @@ typedef struct {
extern ssc_dma_tx_buffer_t ssc_tx_buffer;
extern void ssc_tx_start(ssc_dma_tx_buffer_t *buf);
+extern volatile u_int32_t ssc_tx_fiq_fdt_cdiv;
+extern volatile u_int32_t ssc_tx_fiq_fdt_ssc;
#endif
diff --git a/openpicc/application/tc_fdt.c b/openpicc/application/tc_fdt.c
index 6005125..7413e11 100644
--- a/openpicc/application/tc_fdt.c
+++ b/openpicc/application/tc_fdt.c
@@ -53,8 +53,8 @@ void tc_fdt_set(u_int16_t count)
void __ramfunc tc_fdt_set_to_next_slot(int last_bit)
{
int reference_time;
- if(last_bit == 0) reference_time = ISO14443A_FDT_OFFSET_0-FALLING_EDGE_DETECTION_DELAY;
- else reference_time = ISO14443A_FDT_OFFSET_1-FALLING_EDGE_DETECTION_DELAY;
+ if(last_bit == 0) reference_time = ISO14443A_FDT_OFFSET_0;
+ else reference_time = ISO14443A_FDT_OFFSET_1;
if(tcfdt->TC_SR & AT91C_TC_CLKSTA)
while(tcfdt->TC_CV != 0xFFFF && (tcfdt->TC_CV - reference_time) % 128 != 0);
diff --git a/openpicc/config/atmel-rom.ld b/openpicc/config/atmel-rom.ld
index 9781d0c..447bd07 100644
--- a/openpicc/config/atmel-rom.ld
+++ b/openpicc/config/atmel-rom.ld
@@ -1,9 +1,9 @@
MEMORY
{
- boot : ORIGIN = 0x00100000, LENGTH = 0x100
- flash : ORIGIN = 0x00100100, LENGTH = 256K - 0x100
- vectors : ORIGIN = 0x00200000, LENGTH = 0x100
- ram : ORIGIN = 0x00200100, LENGTH = 64K - 0x100
+ boot : ORIGIN = 0x00100000, LENGTH = 0x200
+ flash : ORIGIN = 0x00100200, LENGTH = 256K - 0x200
+ vectors : ORIGIN = 0x00200000, LENGTH = 0x200
+ ram : ORIGIN = 0x00200200, LENGTH = 64K - 0x200
}
__stack_end__ = 0x00200000 + 64K - 4;
diff --git a/openpicc/fdt_timing.dia b/openpicc/fdt_timing.dia
new file mode 100644
index 0000000..19fad5a
--- /dev/null
+++ b/openpicc/fdt_timing.dia
Binary files differ
diff --git a/openpicc/os/boot/Cstartup_SAM7.c b/openpicc/os/boot/Cstartup_SAM7.c
index 5371794..b308856 100644
--- a/openpicc/os/boot/Cstartup_SAM7.c
+++ b/openpicc/os/boot/Cstartup_SAM7.c
@@ -68,8 +68,8 @@ void AT91F_LowLevelInit (void)
pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
- /* Copy first 0x100 bytes (IRQ vector table and FIQ) to RAM */
- memcpy((void*)0x00200000, (void*)0x00100000, 0x100);
+ /* Copy first 0x200 bytes (IRQ vector table and FIQ) to RAM */
+ memcpy((void*)0x00200000, (void*)0x00100000, 0x200);
/* Perform remap FIXME doesn't work*/
// AT91C_BASE_MC->MC_RCR = AT91C_MC_RCB;
}
diff --git a/openpicc/os/boot/boot.s b/openpicc/os/boot/boot.s
index 95bc130..0000479 100644
--- a/openpicc/os/boot/boot.s
+++ b/openpicc/os/boot/boot.s
@@ -5,6 +5,8 @@
.extern AT91F_LowLevelInit
.extern pio_irq_isr_value
.extern ssc_tx_pending
+ .extern ssc_tx_fiq_fdt_cdiv
+ .extern ssc_tx_fiq_fdt_ssc
.text
.code 32
@@ -60,6 +62,7 @@
.equ PIOA_IDR, 0x44
.equ PIOA_ISR, 0x4c
.equ TC_CCR, 0x00
+.equ TC2_CV, (0x80+0x10)
.equ AIC_EOICR, (304)
.equ PIO_LED1, (1 << 25)
.equ PIO_LED2, (1 << 12)
@@ -68,11 +71,6 @@
.equ PIO_SECONDARY_IRQ, 31
.equ PIO_SECONDARY_IRQ_BIT, (1 << PIO_SECONDARY_IRQ)
-/* FIQ latency is approx 1us. At 13.56 MHz carrier frequency this means that
- * 13.56 cycles of the carrier have passed when the FIQ kicks in and this is
- * the amount that CV0 should be loaded to. (Round up) */
-.equ TC0_FRAME_OFFSET, 9
-
start:
_start:
_mainCRTStartup:
@@ -241,13 +239,38 @@ my_fiq_handler:
ldrne r11, =ssc_tx_pending
ldrne r8, [r11]
tstne r8, #0x01 /* Check whether a TX is pending */
+ beq .no_ssc
+
+ mov r8, #PIO_LED1
+ str r8, [r10, #PIOA_SODR] /* disable LED */
+
+ mov r8, #0x00
+ str r8, [r11] /* Set ssc_tx_pending to 0 */
- movne r8, #0x00
- strne r8, [r11] /* Set ssc_tx_pending to 0 */
+ ldr r11, =ssc_tx_fiq_fdt_cdiv
+ ldr r11, [r11] /* r11 == ssc_tx_fiq_fdt_cdiv */
+
+.wait_for_fdt_cdiv:
+ ldr r8, [r12, #TC2_CV]
+ cmp r8, r11
+ bmi .wait_for_fdt_cdiv /* spin while TC2.CV is less fdt_cdiv */
+
+ str r9, [r12, #TC_CCR] /* SWTRG on TC0 */
+
+ ldr r11, =ssc_tx_fiq_fdt_ssc
+ ldr r11, [r11] /* r11 == ssc_tx_fiq_fdt_ssc */
+
+.wait_for_fdt_ssc:
+ ldr r8, [r12, #TC2_CV]
+ cmp r8, r11
+ bmi .wait_for_fdt_ssc /* spin while TC2.CV is less fdt_ssc */
+
+ mov r11, #PIO_LED1
+ str r11, [r10, #PIOA_CODR] /* enable LED */
- ldrne r11, =AT91C_BASE_SSC
- movne r8, #SSC_CR_TXEN
- strne r8, [r11, #SSC_CR] /* Write TXEN to SSC_CR, enables tx */
+ ldr r11, =AT91C_BASE_SSC
+ mov r8, #SSC_CR_TXEN
+ str r8, [r11, #SSC_CR] /* Write TXEN to SSC_CR, enables tx */
.no_ssc:
/* Trigger PIO_SECONDARY_IRQ */
personal git repositories of Harald Welte. Your mileage may vary