summaryrefslogtreecommitdiff
path: root/openpicc/application
diff options
context:
space:
mode:
authorhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2007-11-26 06:20:17 +0000
committerhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2007-11-26 06:20:17 +0000
commit16d42d5f6b8df076a04a18ffd13d0defc999c7bf (patch)
tree5ea288cc5c509bdc549690877a68bb03679cb447 /openpicc/application
parent29ea5bbf5b9c3b3679aa40e4ee7029284cb424c6 (diff)
Prepare transmission code
Restructure/add some buffer code Reset the watchdog timer (now at 1.5s), add a watchdog pinger thread git-svn-id: https://svn.openpcd.org:2342/trunk@352 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'openpicc/application')
-rw-r--r--openpicc/application/cmd.c24
-rw-r--r--openpicc/application/decoder.h1
-rw-r--r--openpicc/application/iso14443_layer3a.c55
-rw-r--r--openpicc/application/iso14443_layer3a.h53
-rw-r--r--openpicc/application/iso14443a_manchester.c100
-rw-r--r--openpicc/application/main.c28
-rw-r--r--openpicc/application/ssc_picc.c95
-rw-r--r--openpicc/application/ssc_picc.h19
8 files changed, 264 insertions, 111 deletions
diff --git a/openpicc/application/cmd.c b/openpicc/application/cmd.c
index 6e5230e..8c06a3d 100644
--- a/openpicc/application/cmd.c
+++ b/openpicc/application/cmd.c
@@ -26,6 +26,10 @@ xTaskHandle xCmdRecvUsbTask;
xTaskHandle xFieldMeterTask;
xSemaphoreHandle xFieldMeterMutex;
+#if ( configUSE_TRACE_FACILITY == 1 )
+static signed portCHAR pcWriteBuffer[512];
+#endif
+
/* Whether to require a colon (':') be typed before long commands, similar to e.g. vi
* This makes a distinction between long commands and short commands: long commands may be
* longer than one character and/or accept optional parameters, short commands are only one
@@ -262,11 +266,6 @@ void prvExecCommand(u_int32_t cmd, portCHAR *args) {
DumpStringToUSB(" * SSC_RCMR value: ");
DumpUIntToUSB(*AT91C_SSC_RCMR);
DumpStringToUSB("\n\r");
- DumpStringToUSB(" * is remapped?: ");
- DumpStringToUSB( (*(int*)0x00100100 == *(int*)0x00000100) ? "no" :
- ((*(int*)0x00200100 == *(int*)0x00000100) ? "yes" : "foo")
- );
- DumpStringToUSB("\n\r");
DumpStringToUSB(
" *\n\r"
" *****************************************************\n\r"
@@ -300,6 +299,14 @@ void prvExecCommand(u_int32_t cmd, portCHAR *args) {
break;
case 'F':
startstop_field_meter();
+ break;
+#if ( configUSE_TRACE_FACILITY == 1 )
+ case 'T':
+ memset(pcWriteBuffer, 0, sizeof(pcWriteBuffer));
+ vTaskList(pcWriteBuffer);
+ DumpStringToUSB((char*)pcWriteBuffer);
+ break;
+#endif
case 'Q':
ssc_rx_start();
while(0) {
@@ -320,6 +327,9 @@ void prvExecCommand(u_int32_t cmd, portCHAR *args) {
" *\n\r"
" * s - store transmitter settings\n\r"
" * test - test critical sections\n\r"
+#if ( configUSE_TRACE_FACILITY == 1 )
+ " * t - print task list and stack usage\n\r"
+#endif
" * c - print configuration\n\r"
" * 0 - receive only mode\n\r"
" * 1..4 - automatic transmit at selected power levels\n\r"
@@ -479,12 +489,12 @@ portBASE_TYPE vCmdInit(void) {
return 0;
}
- if(xTaskCreate(vCmdRecvUsbCode, (signed portCHAR *)"CMDUSB", TASK_CMD_STACK, NULL,
+ if(xTaskCreate(vCmdRecvUsbCode, (signed portCHAR *)"CMDUSB", 128, NULL,
TASK_CMD_PRIORITY, &xCmdRecvUsbTask) != pdPASS) {
return 0;
}
- if(xTaskCreate(vFieldMeter, (signed portCHAR *)"FIELD METER", TASK_CMD_STACK, NULL,
+ if(xTaskCreate(vFieldMeter, (signed portCHAR *)"FIELD METER", 128, NULL,
TASK_CMD_PRIORITY, &xFieldMeterTask) != pdPASS) {
return 0;
}
diff --git a/openpicc/application/decoder.h b/openpicc/application/decoder.h
index bd25777..7892ea6 100644
--- a/openpicc/application/decoder.h
+++ b/openpicc/application/decoder.h
@@ -21,6 +21,7 @@ struct decoder_state {
extern int decoder_register(int algnum, struct decoder_algo *algo);
extern int decoder_decode(u_int8_t algo, const char *sample_buf,
int sample_buf_size, unsigned char *data_buf);
+extern void decoder_init(void);
#define DECODER_MILLER 0
#define DECODER_NRZL 1
diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c
index 841ad14..2239655 100644
--- a/openpicc/application/iso14443_layer3a.c
+++ b/openpicc/application/iso14443_layer3a.c
@@ -34,20 +34,34 @@
#include "tc_cdiv_sync.h"
#include "usb_print.h"
#include "cmd.h"
+#include "load_modulation.h"
+#include "decoder.h"
+#include "iso14443a_manchester.h"
+#include "led.h"
static enum ISO14443_STATES state = STARTING_UP;
+const iso14443_frame ATQA_FRAME = {
+ TYPE_A,
+ {{STANDARD_FRAME, NO_PARITY}},
+ 2,
+ 0, 0,
+ {4, 0},
+ {}
+};
+
+
#define PLL_LOCK_HYSTERESIS portTICK_RATE_MS*5
#define LAYER3_DEBUG usb_print_string
-extern void main_help_print_buffer(ssc_dma_buffer_t *buffer, int *pktcount);
+extern void main_help_print_buffer(ssc_dma_rx_buffer_t *buffer, int *pktcount);
void iso14443_layer3a_state_machine (void *pvParameters)
{
unsigned long int last_pll_lock = ~0;
int pktcount=0;
(void)pvParameters;
while(1) {
- ssc_dma_buffer_t* buffer = NULL;
+ ssc_dma_rx_buffer_t* buffer = NULL;
portBASE_TYPE need_receive = 0, switch_on = 0;
/* First let's see whether there is a reader */
@@ -97,7 +111,7 @@ void iso14443_layer3a_state_machine (void *pvParameters)
tc_cdiv_set_divider(64);
#endif
tc_fdt_init();
-#if 0
+#if 1
ssc_tx_init();
#else
AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_MOD_PWM);
@@ -107,6 +121,10 @@ void iso14443_layer3a_state_machine (void *pvParameters)
#endif
ssc_rx_init();
+ load_mod_init();
+ load_mod_level(3);
+
+
state = POWERED_OFF;
break;
case POWERED_OFF:
@@ -127,6 +145,7 @@ void iso14443_layer3a_state_machine (void *pvParameters)
if(need_receive) {
if(xQueueReceive(ssc_rx_queue, &buffer, portTICK_RATE_MS)) {
+ vLedSetGreen(0);
portENTER_CRITICAL();
buffer->state = PROCESSING;
portEXIT_CRITICAL();
@@ -145,6 +164,36 @@ void iso14443_layer3a_state_machine (void *pvParameters)
LAYER3_DEBUG("Received ");
LAYER3_DEBUG(first_sample == WUPA ? "WUPA" : "REQA");
LAYER3_DEBUG(" waking up to send ATQA\n\r");
+ portENTER_CRITICAL();
+ if(ssc_tx_buffer.state != FREE) {
+ portEXIT_CRITICAL();
+ /* Wait for another frame */
+ ssc_rx_mode_set(SSC_MODE_14443A_SHORT);
+ ssc_rx_start();
+ } else {
+ ssc_tx_buffer.state = PROCESSING;
+ portEXIT_CRITICAL();
+ ssc_tx_buffer.len = sizeof(ssc_tx_buffer.data);
+ unsigned int ret =
+ manchester_encode(ssc_tx_buffer.data,
+ ssc_tx_buffer.len,
+ &ATQA_FRAME);
+ if(ret>0) {
+ ssc_tx_buffer.len = ret;
+ LAYER3_DEBUG("Buffer ");
+ DumpUIntToUSB(ret);
+ LAYER3_DEBUG(" ");
+ DumpBufferToUSB((char*)ssc_tx_buffer.data, ssc_tx_buffer.len);
+ LAYER3_DEBUG("\n\r");
+ } else {
+ portENTER_CRITICAL();
+ ssc_tx_buffer.state = FREE;
+ portEXIT_CRITICAL();
+ /* Wait for another frame */
+ ssc_rx_mode_set(SSC_MODE_14443A_SHORT);
+ ssc_rx_start();
+ }
+ }
} else {
/* Wait for another frame */
ssc_rx_mode_set(SSC_MODE_14443A_SHORT);
diff --git a/openpicc/application/iso14443_layer3a.h b/openpicc/application/iso14443_layer3a.h
index 6f32dd5..142128e 100644
--- a/openpicc/application/iso14443_layer3a.h
+++ b/openpicc/application/iso14443_layer3a.h
@@ -15,6 +15,7 @@ enum ISO14443_STATES {
ERROR, /* Some unrecoverable error has occured */
};
+/******************** RX ************************************/
/* standard derived magic values */
#define ISO14443A_FDT_SHORT_1 1236
#define ISO14443A_FDT_SHORT_0 1172
@@ -30,6 +31,15 @@ enum ISO14443_STATES {
#define ISO14443A_SOF_LEN 4
/* Length in samples of a short frame */
#define ISO14443A_SHORT_LEN 32
+/* This is wrong: a short frame is 1 start bit, 7 data bits, 1 stop bit
+ * followed by no modulation for one bit period. The start bit is 'eaten' in
+ * SSC Compare 0, but the remaining 7+1+1 bit durations must be sampled and
+ * compared. At four times oversampling this would be 9*4=36 samples, which is
+ * more than one SSC transfer. You'd have to use two transfers of 18 samples
+ * each and modify the comparison code accordingly.
+ * Since four times oversampling doesn't work reliably anyway (every second
+ * sample is near an edge and might sample 0 or 1) this doesn't matter for now.*/
+#error Four times oversampling is broken, see comments in code
#else
/* definitions for two-times oversampling */
@@ -38,8 +48,49 @@ enum ISO14443_STATES {
#define ISO14443A_SOF_SAMPLE 0x01
#define ISO14443A_SOF_LEN 2
-#define ISO14443A_SHORT_LEN 16
+#define ISO14443A_SHORT_LEN 18
#endif
+/* A short frame should be received in one single SSC transfer */
+#if (ISO14443A_SHORT_LEN <= 8)
+/* SSC transfer size in bits */
+#define ISO14443A_SHORT_TRANSFER_SIZE 8
+#define ISO14443A_SHORT_TYPE u_int8_t
+
+#elif (ISO14443A_SHORT_LEN <= 16)
+#define ISO14443A_SHORT_TRANSFER_SIZE 16
+#define ISO14443A_SHORT_TYPE u_int16_t
+
+#elif (ISO14443A_SHORT_LEN <= 32)
+#define ISO14443A_SHORT_TRANSFER_SIZE 32
+#define ISO14443A_SHORT_TYPE u_int32_t
+
+#else
+#error ISO14443A_SHORT_LEN defined too big
+#endif
+
+/******************** TX ************************************/
+/* in bytes, not counting parity */
+#define MAXIMUM_FRAME_SIZE 256
+
+typedef struct {
+ enum { TYPE_A, TYPE_B } type;
+ union {
+ struct {
+ enum { SHORT_FRAME, STANDARD_FRAME, AC_FRAME } format;
+ enum { PARITY, /* Calculate parity on the fly, ignore the parity field below */
+ GIVEN_PARITY, /* Use the parity bits from the parity field below */
+ NO_PARITY, /* Don't send any parity */
+ } parity;
+ } a;
+ } parameters;
+ u_int32_t numbytes;
+ u_int8_t numbits, bit_offset;
+ u_int8_t data[MAXIMUM_FRAME_SIZE];
+ u_int8_t parity[MAXIMUM_FRAME_SIZE]; /* Only the LSB of each byte is used */
+} iso14443_frame;
+
+extern const iso14443_frame ATQA_FRAME;
+
#endif /*ISO14443_LAYER3A_H_*/
diff --git a/openpicc/application/iso14443a_manchester.c b/openpicc/application/iso14443a_manchester.c
index efc4baf..eff5a31 100644
--- a/openpicc/application/iso14443a_manchester.c
+++ b/openpicc/application/iso14443a_manchester.c
@@ -25,7 +25,7 @@
* MSB first LSB first hex LSB first
* Sequence D 1010101000000000 0000000001010101 0x0055
* Sequence E 0000000010101010 0101010100000000 0x5500
- * Sequence F 1010101010101010 0101010101010101 0x5555
+ * Sequence F 0000000000000000 0000000000000000 0x0000
*
* Logic 1 Sequence D
* Logic 0 Sequence E
@@ -44,79 +44,93 @@
#define MANCHESTER_SEQ_D 0x0055
#define MANCHESTER_SEQ_E 0x5500
-#define MANCHESTER_SEQ_F 0x5555
+#define MANCHESTER_SEQ_F 0x0000
#include <errno.h>
#include <string.h>
#include "openpicc.h"
+#include "iso14443_layer3a.h"
+#include "iso14443a_manchester.h"
-static u_int32_t manchester_sample_size(u_int8_t frame_bytelen) __attribute__((unused));
-static u_int32_t manchester_sample_size(u_int8_t frame_bytelen)
-{
- /* 16 bits (2 bytes) per bit => 16 bytes samples per data byte,
- * plus 16bit (2 bytes) parity per data byte
- * plus 16bit (2 bytes) SOF plus 16bit (2 bytes) EOF */
- return (frame_bytelen*18) + 2 + 2;
-
- /* this results in a maximum samples-per-frame size of 4612 bytes
- * for a 256byte frame */
-}
-
-struct manch_enc_state {
- const char *data;
- char *samples;
- u_int16_t *samples16;
+enum parity {
+ PARITY_NONE, /* Don't add a parity bit */
+ ODD_PARITY, EVEN_PARITY, /* Calculate parity */
+ PARITY_0, PARITY_1 /* Set fixed parity */
};
-static void manchester_enc_byte(struct manch_enc_state *mencs, u_int8_t data) __attribute__((unused));
-static void manchester_enc_byte(struct manch_enc_state *mencs, u_int8_t data)
+static void manchester_enc_byte(u_int16_t **s16, u_int8_t data, enum parity parity)
{
int i;
u_int8_t sum_1 = 0;
+ u_int16_t *samples16 = *s16;
/* append 8 sample blobs, one for each bit */
for (i = 0; i < 8; i++) {
if (data & (1 << i)) {
- *(mencs->samples16) = MANCHESTER_SEQ_D;
+ *(samples16) = MANCHESTER_SEQ_D;
sum_1++;
} else {
- *(mencs->samples16) = MANCHESTER_SEQ_E;
+ *(samples16) = MANCHESTER_SEQ_E;
+ }
+ samples16++;
+ }
+ if(parity != PARITY_NONE) {
+ /* Append parity */
+ u_int8_t par=0;
+ switch(parity) {
+ case PARITY_NONE: break;
+ case PARITY_0: par = 0; break;
+ case PARITY_1: par = 1; break;
+ case ODD_PARITY: par = (sum_1 & 0x1) ? 0 : 1; break;
+ case EVEN_PARITY: par = (sum_1 & 0x1) ? 1 : 0; break;
}
- mencs->samples16++;
+ if (par)
+ *(samples16) = MANCHESTER_SEQ_D;
+ else
+ *(samples16) = MANCHESTER_SEQ_E;
+ samples16++;
}
- /* append odd parity */
- if (sum_1 & 0x01)
- *(mencs->samples16) = MANCHESTER_SEQ_E;
- else
- *(mencs->samples16) = MANCHESTER_SEQ_D;
- mencs->samples16++;
+ *s16 = samples16;
}
-#if 0
-/* Broken? */
-int manchester_encode(char *sample_buf, u_int16_t sample_buf_len,
- const char *data, u_int8_t data_len)
+int manchester_encode(u_int8_t *sample_buf, u_int16_t sample_buf_len,
+ const iso14443_frame *frame)
{
- int i, enc_size;
- struct manch_enc_state mencs;
-
- enc_size = manchester_sample_size(data_len);
+ unsigned int i, enc_size;
+ u_int16_t *samples16;
+
+ if(frame->type != TYPE_A) return -EINVAL;
+ if(frame->parameters.a.format != STANDARD_FRAME) return -EINVAL; /* AC not implemented yet */
+
+ /* One bit data is 16 bit/2 byte modulation data */
+ enc_size = 2*2 /* SOF and EOF */
+ + frame->numbytes * 8 * 2
+ + ((frame->parameters.a.parity != NO_PARITY) ? 1 : 0)*8*2;
if (sample_buf_len < enc_size)
return -EINVAL;
+
+ samples16 = (u_int16_t*)sample_buf;
/* SOF */
- *(mencs.samples16++) = MANCHESTER_SEQ_D;
-
- for (i = 0; i < data_len; i++)
- manchester_enc_byte(&mencs, data[i]);
+ *(samples16++) = MANCHESTER_SEQ_D;
+
+ if(frame->parameters.a.parity == NO_PARITY)
+ for (i = 0; i < frame->numbytes; i++)
+ manchester_enc_byte(&samples16, frame->data[i], PARITY_NONE);
+ else if(frame->parameters.a.parity == GIVEN_PARITY)
+ for (i = 0; i < frame->numbytes; i++)
+ manchester_enc_byte(&samples16, frame->data[i], frame->parity[i]?PARITY_1:PARITY_0);
+ else if(frame->parameters.a.parity == PARITY)
+ for (i = 0; i < frame->numbytes; i++)
+ manchester_enc_byte(&samples16, frame->data[i], ODD_PARITY);
/* EOF */
- *(mencs.samples16++) = MANCHESTER_SEQ_F;
+ *(samples16++) = MANCHESTER_SEQ_F;
return enc_size;
}
-#endif
+
#if 0
/* Broken? */
#define BPSK_SPEED_212
diff --git a/openpicc/application/main.c b/openpicc/application/main.c
index 48e9ab2..a093d70 100644
--- a/openpicc/application/main.c
+++ b/openpicc/application/main.c
@@ -48,6 +48,7 @@
#include "tc_fdt.h"
#include "usb_print.h"
#include "iso14443_layer3a.h"
+#include "decoder.h"
/**********************************************************************/
static inline void prvSetupHardware (void)
@@ -76,8 +77,6 @@ void vApplicationIdleHook(void)
{
static char disabled_green = 0;
//static int i=0;
- /* Restart watchdog, has been enabled in Cstartup_SAM7.c */
- AT91F_WDTRestart(AT91C_BASE_WDTC);
//vLedSetGreen(i^=1);
if(!disabled_green) {
//vLedSetGreen(0);
@@ -86,9 +85,9 @@ void vApplicationIdleHook(void)
usb_print_flush();
}
-void main_help_print_buffer(ssc_dma_buffer_t *buffer, int *pktcount)
+void main_help_print_buffer(ssc_dma_rx_buffer_t *buffer, int *pktcount)
{
- u_int16_t *tmp = (u_int16_t*)buffer->data;
+ ISO14443A_SHORT_TYPE *tmp = (ISO14443A_SHORT_TYPE*)buffer->data;
int i, dumped = 0;
unsigned int j;
for(i = buffer->len / sizeof(*tmp); i >= 0 ; i--) {
@@ -102,7 +101,7 @@ void main_help_print_buffer(ssc_dma_buffer_t *buffer, int *pktcount)
DumpStringToUSB(" ");
}
dumped = 1;
- DumpUIntToUSB(i);
+ DumpUIntToUSB(buffer->len / sizeof(*tmp) - i);
DumpStringToUSB(": ");
for(j=0; j<sizeof(*tmp)*8; j++) {
usb_print_char_f( (((*tmp) >> j) & 0x1) ? '1' : '_' , 0);
@@ -120,7 +119,7 @@ void vMainTestSSCRXConsumer (void *pvParameters)
static int pktcount=0;
(void)pvParameters;
while(1) {
- ssc_dma_buffer_t* buffer;
+ ssc_dma_rx_buffer_t* buffer;
if(xQueueReceive(ssc_rx_queue, &buffer, portMAX_DELAY)) {
portENTER_CRITICAL();
buffer->state = PROCESSING;
@@ -142,11 +141,25 @@ void vMainTestSSCRXConsumer (void *pvParameters)
}
}
+/* This task pings the watchdog even when the idle task is not running
+ * It should be started with a very high priority and will delay most of the time */
+void vMainWatchdogPinger (void *pvParameters)
+{
+ (void)pvParameters;
+
+ while(1) {
+ /* Restart watchdog, has been enabled in Cstartup_SAM7.c */
+ AT91F_WDTRestart(AT91C_BASE_WDTC);
+ vTaskDelay(500*portTICK_RATE_MS);
+ }
+}
+
/**********************************************************************/
int main (void)
{
prvSetupHardware ();
usb_print_init();
+ decoder_init();
pio_irq_init();
@@ -165,6 +178,9 @@ int main (void)
vCmdInit();
+ xTaskCreate (vMainWatchdogPinger, (signed portCHAR *) "WDT PINGER", 64,
+ NULL, TASK_ISO_PRIORITY -1, NULL);
+
//vLedSetGreen(1);
/* Remap RAM to addr 0 */
diff --git a/openpicc/application/ssc_picc.c b/openpicc/application/ssc_picc.c
index e9fdbfb..19f028e 100644
--- a/openpicc/application/ssc_picc.c
+++ b/openpicc/application/ssc_picc.c
@@ -52,16 +52,18 @@
static const AT91PS_SSC ssc = AT91C_BASE_SSC;
static AT91PS_PDC rx_pdc;
-static ssc_dma_buffer_t dma_buffers[SSC_DMA_BUFFER_COUNT];
+static ssc_dma_rx_buffer_t dma_buffers[SSC_DMA_BUFFER_COUNT];
xQueueHandle ssc_rx_queue = NULL;
+ssc_dma_tx_buffer_t ssc_tx_buffer;
+
#define TEST_WHETHER_NOT_ENABLING_IT_HELPS
#define TEST_WHETHER_THIS_INTERRUPT_WORKS_AT_ALL
-static ssc_dma_buffer_t* __ramfunc ssc_find_dma_buffer(ssc_dma_buffer_state_t oldstate,
+static ssc_dma_rx_buffer_t* __ramfunc ssc_find_dma_buffer(ssc_dma_buffer_state_t oldstate,
ssc_dma_buffer_state_t newstate)
{
- ssc_dma_buffer_t* result = NULL;
+ ssc_dma_rx_buffer_t* result = NULL;
int i=0;
for(i=0; i<SSC_DMA_BUFFER_COUNT; i++) {
if(dma_buffers[i].state == oldstate) {
@@ -74,18 +76,18 @@ static ssc_dma_buffer_t* __ramfunc ssc_find_dma_buffer(ssc_dma_buffer_state_t ol
}
struct ssc_state {
- ssc_dma_buffer_t* buffer[2];
+ ssc_dma_rx_buffer_t* buffer[2];
enum ssc_mode mode;
};
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 */
+static const struct {u_int16_t bytes; u_int16_t transfers;} ssc_dmasize[] = {
+ [SSC_MODE_NONE] = {0, 0},
+ [SSC_MODE_14443A_SHORT] = {ISO14443A_SHORT_TRANSFER_SIZE/8, 1}, /* 1 transfer of ISO14443A_SHORT_LEN bits */
+ [SSC_MODE_14443A_STANDARD] = {16*4, 16}, /* 64 bytes */
+ [SSC_MODE_14443B] = {16*4, 16}, /* 64 bytes */
+ [SSC_MODE_EDGE_ONE_SHOT] = {16*4, 16}, /* 64 bytes */
+ [SSC_MODE_CONTINUOUS] = {511*4, 511}, /* 2044 bytes */
};
#define SSC_RX_IRQ_MASK (AT91C_SSC_RXRDY | \
@@ -117,7 +119,7 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode)
sync_len = ISO14443A_SOF_LEN;
ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE;
data_len = ISO14443A_SHORT_LEN;
- num_data = 16;
+ num_data = 2;
break;
case SSC_MODE_14443A_STANDARD:
start_cond = AT91C_SSC_START_0;
@@ -159,9 +161,9 @@ void ssc_rx_mode_set(enum ssc_mode ssc_mode)
/* Enable RX interrupts */
#ifdef TEST_WHETHER_NOT_ENABLING_IT_HELPS
-
+/*
AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | AT91C_SSC_CP0 |
- AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);
+ AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);*/
#endif
out_set_mode:
ssc_state.mode = ssc_mode;
@@ -249,7 +251,7 @@ int ssc_count_free(void) {
static int __ramfunc __ssc_rx_refill(int secondary)
{
- ssc_dma_buffer_t *buffer;
+ ssc_dma_rx_buffer_t *buffer;
buffer = ssc_find_dma_buffer(FREE, PENDING);
if (!buffer) {
@@ -260,14 +262,14 @@ static int __ramfunc __ssc_rx_refill(int secondary)
//init_opcdhdr(buffer);
DEBUGR("filling SSC RX%u dma ctx: %u (len=%u) ", secondary,
req_ctx_num(buffer), buffer->size);
- buffer->len = ssc_dmasize[ssc_state.mode]*4;
+ buffer->len = ssc_dmasize[ssc_state.mode].bytes;
if (secondary) {
AT91F_PDC_SetNextRx(rx_pdc, buffer->data,
- ssc_dmasize[ssc_state.mode]);
+ ssc_dmasize[ssc_state.mode].transfers);
ssc_state.buffer[1] = buffer;
} else {
AT91F_PDC_SetRx(rx_pdc, buffer->data,
- ssc_dmasize[ssc_state.mode]);
+ ssc_dmasize[ssc_state.mode].transfers);
ssc_state.buffer[0] = buffer;
}
@@ -360,9 +362,10 @@ static void __ramfunc ssc_irq(void)
/* 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) {
+ if (ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT || ssc_state.mode == SSC_MODE_14443A_SHORT) {
DEBUGP("DISABLE_RX ");
ssc_rx_stop();
+ vLedSetGreen(1);
}
//AT91F_SSC_DisableIt(AT91C_BASE_SSC, SSC_RX_IRQ_MASK);
#endif
@@ -389,12 +392,6 @@ static void __ramfunc ssc_irq(void)
ssc_state.buffer[0]->state = FULL;
//gaportEXIT_CRITICAL();
task_woken = xQueueSendFromISR(ssc_rx_queue, &ssc_state.buffer[0], task_woken);
- /*vLedBlinkRed();
- vLedSetRed(1); for(i=0; i<50; i++) (void)i; vLedSetRed(0);
- for(i=0; i<ssc_state.buffer[0]->len*8; i++) {
- vLedSetRed( ssc_state.buffer[0]->data[i/8] & (1<<(i%8)) );
- }
- vLedBlinkRed();*/
} else {
DEBUGP("EMPTY");
//gaportENTER_CRITICAL();
@@ -405,30 +402,28 @@ static void __ramfunc ssc_irq(void)
/* second buffer gets propagated to primary */
ssc_state.buffer[0] = ssc_state.buffer[1];
ssc_state.buffer[1] = NULL;
- if (ssc_sr & AT91C_SSC_RXBUFF) {
-// FIXME
- DEBUGP("RXBUFF! ");
- if (ssc_state.buffer[0]) {
- //DEBUGP("Sending secondary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len);
- //gaportENTER_CRITICAL();
- ssc_state.buffer[0]->state = FULL;
- //gaportEXIT_CRITICAL();
- task_woken = xQueueSendFromISR(ssc_rx_queue, &ssc_state.buffer[0], task_woken);
+ if(ssc_state.mode != SSC_MODE_14443A_SHORT) {
+ if (ssc_sr & AT91C_SSC_RXBUFF) {
+ // FIXME
+ DEBUGP("RXBUFF! ");
+ if (ssc_state.buffer[0]) {
+ //DEBUGP("Sending secondary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len);
+ //gaportENTER_CRITICAL();
+ ssc_state.buffer[0]->state = FULL;
+ //gaportEXIT_CRITICAL();
+ task_woken = xQueueSendFromISR(ssc_rx_queue, &ssc_state.buffer[0], task_woken);
+ }
+ if (__ssc_rx_refill(0) == -1)
+ AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
+ AT91C_SSC_RXBUFF |
+ AT91C_SSC_OVRUN);
}
- if (__ssc_rx_refill(0) == -1)
+
+ if (__ssc_rx_refill(1) == -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(ssc_state.mode == SSC_MODE_14443A_SHORT) {
+ } else {
// Stop sampling here
ssc_rx_stop();
}
@@ -503,8 +498,11 @@ void ssc_rx_unthrottle(void)
void ssc_rx_start(void)
{
- //DEBUGPCRF("starting SSC RX\n");
-
+ //DEBUGPCRF("starting SSC RX\n");
+
+ __ssc_rx_refill(0);
+ if(ssc_state.mode != SSC_MODE_14443A_SHORT) __ssc_rx_refill(1);
+
/* Enable Reception */
#ifdef TEST_WHETHER_NOT_ENABLING_IT_HELPS
AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 |
@@ -596,9 +594,8 @@ void ssc_rx_init(void)
#endif
ssc_rx_mode_set(SSC_MODE_NONE);
+ ssc_state.buffer[0] = ssc_state.buffer[1] = NULL;
- __ssc_rx_refill(0);
- __ssc_rx_refill(1);
#if 0
AT91F_PDC_EnableRx(rx_pdc);
diff --git a/openpicc/application/ssc_picc.h b/openpicc/application/ssc_picc.h
index 813ef33..db3cc00 100644
--- a/openpicc/application/ssc_picc.h
+++ b/openpicc/application/ssc_picc.h
@@ -2,6 +2,7 @@
#define _SSC_H
#include "queue.h"
+#include "iso14443_layer3a.h"
extern void ssc_rx_start(void);
extern void ssc_rx_stop(void);
@@ -29,7 +30,7 @@ extern portBASE_TYPE ssc_get_overflows(void);
extern int ssc_count_free(void);
#define SSC_DMA_BUFFER_SIZE 2048
-#define SSC_DMA_BUFFER_COUNT 10
+#define SSC_DMA_BUFFER_COUNT 4
typedef enum {
FREE=0, /* Buffer is free */
@@ -43,8 +44,22 @@ typedef struct {
u_int32_t len; /* Length of the content */
enum ssc_mode reception_mode;
u_int8_t data[SSC_DMA_BUFFER_SIZE];
-} ssc_dma_buffer_t;
+} ssc_dma_rx_buffer_t;
extern xQueueHandle ssc_rx_queue;
+/* in bytes, used for the sample buffer that holds the subcarrier modulation data at fc/8 = 1695 MHz */
+#define SSC_TX_BUFFER_SIZE ((MAXIMUM_FRAME_SIZE*( (8+1)*2 ) ) + 2 + 2)
+
+typedef struct {
+ volatile ssc_dma_buffer_state_t state;
+ u_int32_t len; /* Length of the content */
+ u_int8_t data[SSC_TX_BUFFER_SIZE];
+} ssc_dma_tx_buffer_t;
+
+/* Declare one TX buffer. This means that only one buffer can ever be pending for sending. That's because
+ * this buffer must be huge (one frame of 256 bytes of subcarrier modulation data at 1695 MHz sample
+ * rate is approx 4k bytes). */
+extern ssc_dma_tx_buffer_t ssc_tx_buffer;
+
#endif
personal git repositories of Harald Welte. Your mileage may vary