summaryrefslogtreecommitdiff
path: root/openpicc
diff options
context:
space:
mode:
authorhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2008-03-14 04:55:15 +0000
committerhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2008-03-14 04:55:15 +0000
commite2e37bea66206adefbb2fc97fcbfb71c1a3cfbe7 (patch)
tree8e1edc0418be46c82e59e5782c9534ebf3d5651c /openpicc
parent9615190a75ab0304d37701e97947ffe36be2d345 (diff)
Add T/C based receiver code with integrated miller decoder
Integrate T/C receiver into iso14443 layer 2a Add state field to iso14443_frame, rename ssc buffer state constants Sniffer seems to work with the new code git-svn-id: https://svn.openpcd.org:2342/trunk@452 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'openpicc')
-rw-r--r--openpicc/Makefile5
-rw-r--r--openpicc/application/cmd.c4
-rw-r--r--openpicc/application/iso14443.h9
-rw-r--r--openpicc/application/iso14443_layer2a.c71
-rw-r--r--openpicc/application/iso14443_layer2a.h17
-rw-r--r--openpicc/application/iso14443_layer3a.c24
-rw-r--r--openpicc/application/iso14443_sniffer.c37
-rw-r--r--openpicc/application/iso14443a_diffmiller.c37
-rw-r--r--openpicc/application/iso14443a_diffmiller.h2
-rw-r--r--openpicc/application/iso14443a_pretender.c4
-rw-r--r--openpicc/application/main.c8
-rw-r--r--openpicc/application/openpicc.h1
-rw-r--r--openpicc/application/performance.c5
-rw-r--r--openpicc/application/ssc.c34
-rw-r--r--openpicc/application/ssc.h22
-rw-r--r--openpicc/application/ssc_buffer.h10
-rw-r--r--openpicc/application/tc_recv.c213
-rw-r--r--openpicc/application/tc_recv.h21
-rw-r--r--openpicc/application/tc_sniffer.c8
19 files changed, 400 insertions, 132 deletions
diff --git a/openpicc/Makefile b/openpicc/Makefile
index e70eab7..b4270ab 100644
--- a/openpicc/Makefile
+++ b/openpicc/Makefile
@@ -88,6 +88,7 @@ ARM_SRC= \
application/tc_cdiv_sync.c \
application/tc_fdt.c \
application/tc_cdiv.c \
+ application/tc_recv.c \
application/usb_print.c \
application/iso14443_layer2a.c \
application/iso14443a_manchester.c \
@@ -109,9 +110,9 @@ ARM_SRC= \
os/core/MemMang/heap_2.c \
os/usb/USB-CDC.c \
os/usb/USBIsr.c \
- application/tc_sniffer.c \
+ application/iso14443_sniffer.c \
+# application/tc_sniffer.c \
# application/iso14443a_pretender.c \
-# application/iso14443_sniffer.c \
# application/iso14443_layer3a.c
#
diff --git a/openpicc/application/cmd.c b/openpicc/application/cmd.c
index 4d7d6b2..412a349 100644
--- a/openpicc/application/cmd.c
+++ b/openpicc/application/cmd.c
@@ -243,9 +243,9 @@ void prvExecCommand(u_int32_t cmd, portCHAR *args) {
case 'P':
print_pio();
break;
- case 'R':
+/* case 'R':
start_stop_sniffing();
- break;
+ break;*/
case 'C':
DumpStringToUSB(
" *****************************************************\n\r"
diff --git a/openpicc/application/iso14443.h b/openpicc/application/iso14443.h
index d3439d1..a2d7458 100644
--- a/openpicc/application/iso14443.h
+++ b/openpicc/application/iso14443.h
@@ -75,8 +75,17 @@
#define MAXIMUM_FRAME_SIZE 256
#define ISO14443A_MAX_RX_FRAME_SIZE_IN_BITS (MAXIMUM_FRAME_SIZE*9 +2)
+typedef enum {
+ FRAME_FREE=0, /* Frame is free */
+ FRAME_PENDING, /* Frame is currently filled by Rx */
+ FRAME_FULL, /* Frame has been filled by Rx */
+ FRAME_PROCESSING,/* The frame is currently processed by the consumer */
+} iso14443_frame_state_t;
+
+
typedef struct {
enum { TYPE_A, TYPE_B } type;
+ iso14443_frame_state_t state;
union {
struct {
enum { SHORT_FRAME, STANDARD_FRAME, AC_FRAME } format;
diff --git a/openpicc/application/iso14443_layer2a.c b/openpicc/application/iso14443_layer2a.c
index 91df6b9..65d5d6a 100644
--- a/openpicc/application/iso14443_layer2a.c
+++ b/openpicc/application/iso14443_layer2a.c
@@ -44,6 +44,7 @@
#include "tc_fdt.h"
#include "tc_cdiv.h"
#include "tc_cdiv_sync.h"
+#include "tc_recv.h"
#include "load_modulation.h"
#include "clock_switch.h"
#include "pio_irq.h"
@@ -58,6 +59,7 @@ static u_int8_t tx_pending=0;
static u_int8_t rx_pending=0;
static iso14443_receive_callback_t callback=NULL;
static ssc_handle_t *ssc;
+static tc_recv_handle_t th;
#ifdef FOUR_TIMES_OVERSAMPLING
#define RX_DIVIDER 32
@@ -65,10 +67,9 @@ static ssc_handle_t *ssc;
#define RX_DIVIDER 64
#endif
-int iso14443_receive(iso14443_receive_callback_t _callback, ssc_dma_rx_buffer_t **buffer, unsigned int timeout)
+int iso14443_receive(iso14443_receive_callback_t _callback, iso14443_frame **frame, unsigned int timeout)
{
- ssc_dma_rx_buffer_t* _buffer = NULL;
- int len;
+ iso14443_frame* _frame = NULL;
if(rx_pending) {
return -EALREADY;
@@ -76,9 +77,9 @@ int iso14443_receive(iso14443_receive_callback_t _callback, ssc_dma_rx_buffer_t
rx_pending=1;
callback=_callback;
- if(ssc_recv(ssc, &_buffer, timeout) == 0) {
+ if(tc_recv_receive(th, &_frame, timeout) == 0) {
- if(_buffer == NULL) {
+ if(_frame == NULL) {
/* Can this happen? */
rx_pending=0;
callback=NULL;
@@ -86,25 +87,23 @@ int iso14443_receive(iso14443_receive_callback_t _callback, ssc_dma_rx_buffer_t
}
portENTER_CRITICAL();
- _buffer->state = PROCESSING;
+ _frame->state = FRAME_PROCESSING;
portEXIT_CRITICAL();
- len = _buffer->len_transfers;
-
if(callback != NULL && !fast_receive) {
- callback(_buffer, 0);
+ callback(NULL, _frame, 0);
}
- if(buffer != NULL) *buffer = _buffer;
+ if(frame != NULL) *frame = _frame;
else {
portENTER_CRITICAL();
- _buffer->state = FREE;
+ _frame->state = FRAME_FREE;
portEXIT_CRITICAL();
}
rx_pending=0;
callback=NULL;
- return len;
+ return 0;
}
/* Note: There is the remote chance of a race condition probability here if
@@ -185,7 +184,7 @@ u_int8_t iso14443_get_fast_receive(void)
static void iso14443_ssc_callback(ssc_callback_reason reason, void *data)
{
- if(reason == CALLBACK_RX_FRAME_BEGIN) {
+ if(reason == SSC_CALLBACK_RX_FRAME_BEGIN) {
/* Busy loop for the frame end */
int *end_asserted = data, i=0;
for(i=0; i<96000; i++)
@@ -197,20 +196,20 @@ static void iso14443_ssc_callback(ssc_callback_reason reason, void *data)
return;
}
- if(reason == CALLBACK_TX_FRAME_ENDED) {
+ if(reason == SSC_CALLBACK_TX_FRAME_ENDED) {
tx_pending = 0;
}
- if( reason == CALLBACK_RX_FRAME_ENDED && fast_receive ) {
+ if( reason == SSC_CALLBACK_RX_FRAME_ENDED && fast_receive ) {
clock_switch(CLOCK_SELECT_CARRIER); /* A Tx might be coming up */
ssc_dma_rx_buffer_t *buffer = data;
if(callback != NULL)
- callback(buffer, 1);
+ callback(buffer, NULL, 1);
}
- if( (reason == CALLBACK_RX_FRAME_ENDED && !tx_pending) || reason == CALLBACK_RX_STARTING
- || reason == CALLBACK_TX_FRAME_ENDED ) {
+ if( (reason == SSC_CALLBACK_RX_FRAME_ENDED && !tx_pending) || reason == SSC_CALLBACK_RX_STARTING
+ || reason == SSC_CALLBACK_TX_FRAME_ENDED ) {
/* For regular SSC Rx we'd set the clock to
// clock_switch(CLOCK_SELECT_PLL);
* however, the SSC Rx code is going to go away (at least for 14443-A)
@@ -226,16 +225,27 @@ static void iso14443_ssc_callback(ssc_callback_reason reason, void *data)
usb_print_set_default_flush(old);
#endif
}
-
}
-static portBASE_TYPE iso14443_rx_FRAME_cb(u_int32_t pio, portBASE_TYPE xTaskWoken)
+static void iso14443_tc_recv_callback(tc_recv_callback_reason reason, void *data)
{
- (void)pio;
- if(PRINT_DEBUG) usb_print_string_f("°", 0); // DEBUG OUTPUT
- if(AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_PIO_FRAME))
- ssc_frame_started();
- return xTaskWoken;
+ if( reason == TC_RECV_CALLBACK_RX_FRAME_ENDED && fast_receive ) {
+ clock_switch(CLOCK_SELECT_CARRIER); /* A Tx might be coming up */
+
+ iso14443_frame *frame = data;
+ if(callback != NULL)
+ callback(NULL, frame, 1);
+ }
+
+ if( (reason == TC_RECV_CALLBACK_RX_FRAME_ENDED && !tx_pending) ||
+ reason == TC_RECV_CALLBACK_SETUP ) {
+ /* For T/C Rx we set the clock to */
+ clock_switch(CLOCK_SELECT_CARRIER);
+ ssc_set_gate(1);
+ tc_fdt_set(0xff00);
+ tc_cdiv_set_divider(RX_DIVIDER);
+ tc_cdiv_sync_reset();
+ }
}
int iso14443_layer2a_init(u_int8_t enable_fast_receive)
@@ -251,14 +261,15 @@ int iso14443_layer2a_init(u_int8_t enable_fast_receive)
iso14443_set_fast_receive(enable_fast_receive);
pio_irq_init_once();
- if(pio_irq_register(OPENPICC_PIO_FRAME, &iso14443_rx_FRAME_cb) >= 0) {
- if(PRINT_DEBUG) usb_print_string("FRAME irq registered\n\r"); // DEBUG OUTPUT
- }
-
- ssc = ssc_open(1, 1, SSC_MODE_14443A, iso14443_ssc_callback);
+ ssc = ssc_open(0, 1, SSC_MODE_14443A, iso14443_ssc_callback);
if(ssc == NULL)
return -EIO;
+ if(tc_recv_init(&th, 0, iso14443_tc_recv_callback) < 0) {
+ ssc_close(ssc);
+ return -EIO;
+ }
+
load_mod_level(3);
return 0;
diff --git a/openpicc/application/iso14443_layer2a.h b/openpicc/application/iso14443_layer2a.h
index 858af81..a8874d0 100644
--- a/openpicc/application/iso14443_layer2a.h
+++ b/openpicc/application/iso14443_layer2a.h
@@ -4,36 +4,37 @@
#include "ssc_buffer.h"
/* Callback type for iso14443_receive().
- * Parameter buffer is being passed a pointer to an SSC Rx buffer structure that this receive happened
- * on. You might want to pass this into iso14443a_decode_miller().
+ * Parameter buffer is either being passed a pointer to an SSC Rx buffer structure that this
+ * receive happened on, or a fully decoded iso14443_frame.
+ * If it's an SSC buffer you might want to pass this into iso14443a_decode_miller().
* Parameter in_irq is true if the callback has been called while still in IRQ mode. It must then *NOT*
* perform any calls that might upset the IRQ processing. Especially it may not call into FreeRTOS or
* any parts of the applications that do.
*/
-typedef void (*iso14443_receive_callback_t)(ssc_dma_rx_buffer_t *buffer, u_int8_t in_irq);
+typedef void (*iso14443_receive_callback_t)(ssc_dma_rx_buffer_t *buffer, iso14443_frame *frame, u_int8_t in_irq);
/* Wait for and receive a frame. Parameters callback and buffer are optional. If you omit them you'll lose
* the received frame, obviously.
* Parameter callback is a callback function that will be called for each received frame and might
* then trigger a response.
- * Parameter buffer is an output pointer to a pointer to an SSC Rx buffer structure containing the
+ * Parameter frame is an output pointer to a pointer to an ISO14443 frame structure containing the
* received frame.
* Parameter timeout gives an optional timeout for the receive operation after which the receive will
* be aborted. When timeout is 0 the receive will not time out.
* This call will block until a frame is received or an exception happens. Obviously it must not be run
* from IRQ context.
*
- * Warning: When you get a buffer from the function then its state is set to PROCESSING and you must
- * FREE it yourself. However, you MUST NOT free a buffer from the callback.
+ * Warning: When you get a frame from the function then its state is set to SSC_PROCESSING and you must
+ * SSC_FREE it yourself. However, you MUST NOT free a buffer or a frame from the callback.
*
* Return values:
- * >= 0 Frame received, return value is buffer length (yes, 0 is a valid buffer length)
+ * = 0 Frame received
* -ENETDOWN PLL is not locked or PLL lock lost
* -ETIMEDOUT Receive timed out without receiving anything (usually not regarded an error condition)
* -EBUSY A Tx is currently running or pending; can't receive
* -EALREADY There's already an iso14443_receive() invocation running
*/
-extern int iso14443_receive(iso14443_receive_callback_t callback, ssc_dma_rx_buffer_t **buffer, unsigned int timeout);
+extern int iso14443_receive(iso14443_receive_callback_t callback, iso14443_frame **frame, unsigned int timeout);
/*
* Transmit a frame. Starts transmitting fdt carrier cycles after the end of the received frame.
diff --git a/openpicc/application/iso14443_layer3a.c b/openpicc/application/iso14443_layer3a.c
index daac8dd..132038e 100644
--- a/openpicc/application/iso14443_layer3a.c
+++ b/openpicc/application/iso14443_layer3a.c
@@ -158,8 +158,8 @@ void __ramfunc iso14443_layer3a_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode
if(send_atqa) {
vLedSetGreen(0);
- if(ssc_tx_buffer.state == PREFILLED && ssc_tx_buffer.source == &ATQA_FRAME) {
- ssc_tx_buffer.state = PROCESSING;
+ if(ssc_tx_buffer.state == SSC_PREFILLED && ssc_tx_buffer.source == &ATQA_FRAME) {
+ ssc_tx_buffer.state = SSC_PROCESSING;
vLedSetGreen(1);
iso14443_transmit(&ssc_tx_buffer, fdt, 8);
atqa_sent = 1;
@@ -174,8 +174,8 @@ void __ramfunc iso14443_layer3a_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode
#define FALSE (0!=0)
static int prefill_buffer(ssc_dma_tx_buffer_t *dest, const iso14443_frame *src) {
portENTER_CRITICAL();
- if(dest->state == FREE) {
- dest->state = PROCESSING;
+ if(dest->state == SSC_FREE) {
+ dest->state = SSC_PROCESSING;
portEXIT_CRITICAL();
dest->source = (void*)src;
dest->len = sizeof(ssc_tx_buffer.data);
@@ -185,15 +185,15 @@ static int prefill_buffer(ssc_dma_tx_buffer_t *dest, const iso14443_frame *src)
if(ret>0) {
dest->len = ret;
portENTER_CRITICAL();
- dest->state = PREFILLED;
+ dest->state = SSC_PREFILLED;
portEXIT_CRITICAL();
} else {
portENTER_CRITICAL();
- dest->state = FREE;
+ dest->state = SSC_FREE;
portEXIT_CRITICAL();
}
return ret > 0;
- } else if(dest->state == PREFILLED) {
+ } else if(dest->state == SSC_PREFILLED) {
portEXIT_CRITICAL();
return dest->source == src;
} else {
@@ -325,7 +325,7 @@ void iso14443_layer3a_state_machine (void *pvParameters)
vLedSetGreen(0);
vLedBlinkGreen();
portENTER_CRITICAL();
- buffer->state = PROCESSING;
+ buffer->state = SSC_PROCESSING;
portEXIT_CRITICAL();
u_int32_t first_sample = *(u_int32_t*)buffer->data;
@@ -392,16 +392,16 @@ void iso14443_layer3a_state_machine (void *pvParameters)
ssc_rx_start();
} else {
//vTaskDelay(portTICK_RATE_MS);
- if(ssc_tx_buffer.source == &ATQA_FRAME) ssc_tx_buffer.state = FREE;
+ if(ssc_tx_buffer.source == &ATQA_FRAME) ssc_tx_buffer.state = SSC_FREE;
if(prefill_buffer(&ssc_tx_buffer, &NULL_FRAME)) {
usb_print_string_f("Sending response ...",0);
- ssc_tx_buffer.state = PROCESSING;
+ ssc_tx_buffer.state = SSC_PROCESSING;
iso14443_transmit(&ssc_tx_buffer,
received_frame.parameters.a.last_bit==ISO14443A_LAST_BIT_0 ?
ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 :
ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1,
8);
- while( ssc_tx_buffer.state != FREE ) {
+ while( ssc_tx_buffer.state != SSC_FREE ) {
vTaskDelay(portTICK_RATE_MS);
}
usb_print_string("done\n\r");
@@ -415,7 +415,7 @@ void iso14443_layer3a_state_machine (void *pvParameters)
}
portENTER_CRITICAL();
- buffer->state = FREE;
+ buffer->state = SSC_FREE;
portEXIT_CRITICAL();
}
} else vTaskDelay(portTICK_RATE_MS);
diff --git a/openpicc/application/iso14443_sniffer.c b/openpicc/application/iso14443_sniffer.c
index bc326b4..6d4a451 100644
--- a/openpicc/application/iso14443_sniffer.c
+++ b/openpicc/application/iso14443_sniffer.c
@@ -26,6 +26,7 @@
#include <board.h>
#include <task.h>
#include <errno.h>
+#include <stdlib.h>
#include "openpicc.h"
#include "ssc_buffer.h"
@@ -37,12 +38,11 @@
#include "cmd.h"
#include "led.h"
-static iso14443_frame rx_frame;
+static iso14443_frame *rx_frame;
void iso14443_sniffer (void *pvParameters)
{
(void)pvParameters;
- (void)rx_frame;
int res;
/* Delay until USB print etc. are ready */
@@ -56,47 +56,30 @@ void iso14443_sniffer (void *pvParameters)
}
} while(res < 0);
+
+ //while(1) { static int i=0; vTaskDelay(10*portTICK_RATE_MS); vLedSetBrightness(LED_RED, abs(1000-i)); i=(i+8)%2000; }
+
usb_print_string("Waiting for carrier. ");
while(iso14443_wait_for_carrier(1000 * portTICK_RATE_MS) != 0) {
}
usb_print_string("Carrier detected.\n\r");
while(true) {
- ssc_dma_rx_buffer_t *buffer = 0;
- res = iso14443_receive(NULL, &buffer, 20000 * portTICK_RATE_MS);
+ res = iso14443_receive(NULL, &rx_frame, 20000 * portTICK_RATE_MS);
if(res >= 0) {
-#if 1
DumpStringToUSB("\n\r");
DumpTimeToUSB(xTaskGetTickCount());
usb_print_string(": Frame received, consists of ");
- DumpUIntToUSB(res);
- usb_print_string(" transfers (");
- DumpUIntToUSB(buffer->reception_mode->transfersize_ssc);
- usb_print_string(" bits from SSC each)\n\r ");
- if(buffer->len_transfers < 200)
- DumpBufferToUSB((char*)buffer->data, (buffer->len_transfers * buffer->reception_mode->transfersize_pdc)/8);
- else {
- DumpBufferToUSB((char*)buffer->data, (200 * buffer->reception_mode->transfersize_pdc)/8);
- usb_print_string("...");
- }
- usb_print_string("\n\r ");
- iso14443a_decode_miller(&rx_frame, buffer);
-
- usb_print_string("Decodes to ");
- DumpUIntToUSB(rx_frame.numbytes);
+ DumpUIntToUSB(rx_frame->numbytes);
usb_print_string(" bytes and ");
- DumpUIntToUSB(rx_frame.numbits);
+ DumpUIntToUSB(rx_frame->numbits);
usb_print_string(" bits: ");
- DumpBufferToUSB((char*)rx_frame.data, rx_frame.numbytes + (rx_frame.numbits+7)/8 );
+ DumpBufferToUSB((char*)rx_frame->data, rx_frame->numbytes + (rx_frame->numbits+7)/8 );
usb_print_string("\n\r");
-#else
- DumpUIntToUSB(buffer->len_transfers);
- DumpStringToUSB("\n\r");
-#endif
portENTER_CRITICAL();
- buffer->state = FREE;
+ rx_frame->state = FRAME_FREE;
portEXIT_CRITICAL();
} else {
if(res != -ETIMEDOUT) {
diff --git a/openpicc/application/iso14443a_diffmiller.c b/openpicc/application/iso14443a_diffmiller.c
index a5acfc8..d73bf95 100644
--- a/openpicc/application/iso14443a_diffmiller.c
+++ b/openpicc/application/iso14443a_diffmiller.c
@@ -124,6 +124,7 @@ inline void start_frame(struct diffmiller_state * const state)
//memset(state->frame, 0, sizeof(*state->frame));
memset(state->frame, 0, (u_int32_t)&(((iso14443_frame*)0)->data) );
performance_set_checkpoint("start_frame after memset");
+ state->frame->state = FRAME_PENDING;
}
static inline void append_to_frame(struct diffmiller_state *const state,
@@ -171,7 +172,7 @@ static inline void end_frame(struct diffmiller_state * const state, const u_int3
}
#define PRINT_BIT(a) if(0){(void)a;}
-//#define PRINT_BIT(a) usb_print_string(a)
+//#define PRINT_BIT(a) usb_print_string_f(a,0)
#define DO_BIT_0 { \
if(++counter==9) { \
@@ -194,10 +195,10 @@ static inline void end_frame(struct diffmiller_state * const state, const u_int3
}
#define DO_SYMBOL_X \
+ PRINT_BIT("(X)"); \
if(!in_frame) { \
if(last_bit == BIT_0) DO_BIT_0; \
error = 1; \
- end_frame(state, counter); \
PRINT_BIT(" ERROR\n"); \
last_bit = BIT_ERROR; \
in_frame = 0; \
@@ -208,10 +209,10 @@ static inline void end_frame(struct diffmiller_state * const state, const u_int3
}
#define DO_SYMBOL_Y \
+ PRINT_BIT("(Y)"); \
if(!in_frame) { \
if(last_bit == BIT_0) DO_BIT_0; \
error = 1; \
- end_frame(state, counter); \
PRINT_BIT(" ERROR\n"); \
last_bit = BIT_ERROR; \
in_frame = 0; \
@@ -227,6 +228,7 @@ static inline void end_frame(struct diffmiller_state * const state, const u_int3
}
#define DO_SYMBOL_Z \
+ PRINT_BIT("(Z)"); \
if(!in_frame) { \
if(last_bit == BIT_0) DO_BIT_0; \
counter = 0; \
@@ -308,11 +310,12 @@ int iso14443a_decode_diffmiller(struct diffmiller_state * const state, iso14443_
if(state->flags.frame_finished) {
state->flags.frame_finished = 0;
- state->old_state = old_state;
+ state->old_state = sym_y;
state->last_bit = last_bit;
state->counter = counter;
state->flags.in_frame = in_frame;
state->flags.error = error;
+ state->frame = NULL;
performance_set_checkpoint("frame finished");
return 0;
}
@@ -327,6 +330,31 @@ int iso14443a_decode_diffmiller(struct diffmiller_state * const state, iso14443_
return -EBUSY;
}
+int iso14443a_diffmiller_assert_frame_ended(struct diffmiller_state * const state,
+ iso14443_frame * const frame)
+{
+ if(state == NULL || !state->initialized) return -EINVAL;
+ if(!state->flags.in_frame) return -EBUSY;
+ if(state->frame != NULL && state->frame != frame) return -EINVAL;
+ state->frame = frame;
+
+ end_frame(state, state->counter);
+ PRINT_BIT(" EOF2\n");
+ state->flags.in_frame = 0;
+
+ if(state->flags.frame_finished) {
+ state->flags.frame_finished = 0;
+ state->old_state = sym_y;
+ state->last_bit = BIT_EOF;
+ state->counter = 0;
+ state->frame = NULL;
+ performance_set_checkpoint("frame finished2");
+ return 0;
+ }
+
+ return -EBUSY;
+}
+
struct diffmiller_state *iso14443a_init_diffmiller(int pauses_count)
{
if(_state.initialized) return NULL;
@@ -334,6 +362,7 @@ struct diffmiller_state *iso14443a_init_diffmiller(int pauses_count)
state->initialized = 1;
state->pauses_count = pauses_count;
state->frame = NULL;
+ state->old_state = sym_y;
state->flags.frame_finished = 0;
return state;
diff --git a/openpicc/application/iso14443a_diffmiller.h b/openpicc/application/iso14443a_diffmiller.h
index f5336d6..7dc9c55 100644
--- a/openpicc/application/iso14443a_diffmiller.h
+++ b/openpicc/application/iso14443a_diffmiller.h
@@ -7,6 +7,8 @@ struct diffmiller_state;
extern int iso14443a_decode_diffmiller(struct diffmiller_state *state, iso14443_frame *frame,
const u_int32_t buffer[], unsigned int *offset, const unsigned int buflen);
+extern int iso14443a_diffmiller_assert_frame_ended(struct diffmiller_state * const state,
+ iso14443_frame * const frame);
extern struct diffmiller_state *iso14443a_init_diffmiller(int pauses_count);
#endif /*ISO14443A_DIFFMILLER_H_*/
diff --git a/openpicc/application/iso14443a_pretender.c b/openpicc/application/iso14443a_pretender.c
index 64112d1..03fb12d 100644
--- a/openpicc/application/iso14443a_pretender.c
+++ b/openpicc/application/iso14443a_pretender.c
@@ -118,7 +118,7 @@ static void fast_receive_callback(ssc_dma_rx_buffer_t *buffer, u_int8_t in_irq)
if(tx_buffer != NULL) {
- tx_buffer->state = FULL;
+ tx_buffer->state = SSC_FULL;
if( iso14443_transmit(tx_buffer, fdt, 1, 0) < 0) {
usb_print_string_f("Tx failed ", 0);
}
@@ -229,7 +229,7 @@ prefill_failed:
}
portENTER_CRITICAL();
- buffer->state = FREE;
+ buffer->state = SSC_FREE;
portEXIT_CRITICAL();
} else {
if(res != -ETIMEDOUT) {
diff --git a/openpicc/application/main.c b/openpicc/application/main.c
index 8babafe..a082933 100644
--- a/openpicc/application/main.c
+++ b/openpicc/application/main.c
@@ -211,12 +211,12 @@ int main (void)
NULL, TASK_USB_PRIORITY, NULL);
/*xTaskCreate (iso14443_layer3a_state_machine, (signed portCHAR *) "ISO14443A-3", TASK_ISO_STACK,
NULL, TASK_ISO_PRIORITY, NULL);*/
- /*xTaskCreate (iso14443_sniffer, (signed portCHAR *) "ISO14443-SNIFF", TASK_ISO_STACK,
- NULL, TASK_ISO_PRIORITY, NULL);*/
+ xTaskCreate (iso14443_sniffer, (signed portCHAR *) "ISO14443-SNIFF", TASK_ISO_STACK,
+ NULL, TASK_ISO_PRIORITY, NULL);
/*xTaskCreate (iso14443a_pretender, (signed portCHAR *) "ISO14443A-PRETEND", TASK_ISO_STACK,
NULL, TASK_ISO_PRIORITY, NULL);*/
- xTaskCreate (tc_sniffer, (signed portCHAR *) "RFID-SNIFFER", TASK_ISO_STACK,
- NULL, TASK_ISO_PRIORITY, NULL);
+ /*xTaskCreate (tc_sniffer, (signed portCHAR *) "RFID-SNIFFER", TASK_ISO_STACK,
+ NULL, TASK_ISO_PRIORITY, NULL);*/
xTaskCreate (vUSBCDCTask, (signed portCHAR *) "USB", TASK_USB_STACK,
diff --git a/openpicc/application/openpicc.h b/openpicc/application/openpicc.h
index b4d2b7a..17cb4ee 100644
--- a/openpicc/application/openpicc.h
+++ b/openpicc/application/openpicc.h
@@ -39,5 +39,6 @@ typedef int s_int32_t;
#define DA_BASELINE 200
#define DIV_ROUND_UP(a,b) ( (a+(b-1)) / b)
+#define MIN(a, b) ((a)>(b)?(b):(a))
#endif/*__OPENPICC_H__*/
diff --git a/openpicc/application/performance.c b/openpicc/application/performance.c
index cffd094..4515f18 100644
--- a/openpicc/application/performance.c
+++ b/openpicc/application/performance.c
@@ -33,6 +33,7 @@ static u_int32_t overruns = 0;
#define NUMBER_OF_CHECKPOINTS 20
static struct performance_checkpoint checkpoints[NUMBER_OF_CHECKPOINTS];
static int current_checkpoint;
+static int running=0;
static void __ramfunc tc_perf_irq(void) __attribute__ ((naked));
static void __ramfunc tc_perf_irq(void)
@@ -66,6 +67,7 @@ inline void performance_start(void)
memset(checkpoints, 0, sizeof(checkpoints));
current_checkpoint = 0;
overruns = 0;
+ running = 1;
tc_perf->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN;
}
@@ -82,6 +84,7 @@ inline perf_time_t performance_get(void)
inline perf_time_t performance_stop(void)
{
perf_time_t result = performance_get();
+ running = 0;
tc_perf->TC_CCR = AT91C_TC_CLKDIS;
return result;
}
@@ -105,6 +108,7 @@ perf_time_t performance_diff(perf_time_t a, perf_time_t b)
void performance_set_checkpoint(const char * const description)
{
+ if(!running) return;
if(current_checkpoint < NUMBER_OF_CHECKPOINTS) {
perf_time_t time = performance_get();
checkpoints[current_checkpoint++] = (struct performance_checkpoint){
@@ -116,6 +120,7 @@ void performance_set_checkpoint(const char * const description)
void performance_stop_report(void)
{
+ if(!running) return;
perf_time_t _now = performance_stop();
struct performance_checkpoint now = {
.time = _now,
diff --git a/openpicc/application/ssc.c b/openpicc/application/ssc.c
index e25d982..4da45ae 100644
--- a/openpicc/application/ssc.c
+++ b/openpicc/application/ssc.c
@@ -125,7 +125,7 @@ static int __ramfunc _ssc_rx_irq(u_int32_t orig_sr, int start_asserted, portBASE
sh->ssc->SSC_RCMR = (orig_rcmr & (~AT91C_SSC_START)) | (AT91C_SSC_START_CONTINOUS);
/* Receiving has started */
if(sh->callback != NULL) {
- sh->callback(CALLBACK_RX_FRAME_BEGIN, &end_asserted);
+ sh->callback(SSC_CALLBACK_RX_FRAME_BEGIN, &end_asserted);
if(end_asserted)
sr = orig_sr | _ssc.ssc->SSC_SR;
}
@@ -147,9 +147,9 @@ static int __ramfunc _ssc_rx_irq(u_int32_t orig_sr, int start_asserted, portBASE
ssc_dma_rx_buffer_t *buffer = _unload_rx(sh);
if(buffer != NULL) {
if(sh->callback != NULL)
- sh->callback(CALLBACK_RX_FRAME_ENDED, buffer);
+ sh->callback(SSC_CALLBACK_RX_FRAME_ENDED, buffer);
- if(buffer->state != FREE) {
+ if(buffer->state != SSC_FREE) {
task_woken = xQueueSendFromISR(sh->rx_queue, &buffer, task_woken);
}
}
@@ -174,7 +174,7 @@ static int __ramfunc _ssc_rx_irq(u_int32_t orig_sr, int start_asserted, portBASE
} else {
sh->ssc->SSC_IDR = SSC_RX_IRQ_MASK;
sh->rx_running = 0;
- sh->callback(CALLBACK_RX_STOPPED, sh);
+ sh->callback(SSC_CALLBACK_RX_STOPPED, sh);
}
}
@@ -202,7 +202,7 @@ static void __ramfunc _ssc_tx_end(ssc_handle_t *sh, int is_an_abort)
AT91F_PDC_SetNextTx(sh->pdc, 0, 0);
if(sh->tx_buffer) {
- sh->tx_buffer->state = FREE;
+ sh->tx_buffer->state = SSC_FREE;
sh->tx_running = 0;
}
@@ -213,9 +213,9 @@ static void __ramfunc _ssc_tx_end(ssc_handle_t *sh, int is_an_abort)
if(sh->callback) {
if(is_an_abort)
- sh->callback(CALLBACK_TX_FRAME_ABORTED, sh->tx_buffer);
+ sh->callback(SSC_CALLBACK_TX_FRAME_ABORTED, sh->tx_buffer);
else
- sh->callback(CALLBACK_TX_FRAME_ENDED, sh->tx_buffer);
+ sh->callback(SSC_CALLBACK_TX_FRAME_ENDED, sh->tx_buffer);
}
sh->tx_buffer = NULL;
@@ -236,7 +236,7 @@ static int __ramfunc _ssc_tx_irq(u_int32_t sr, portBASE_TYPE task_woken)
sh->ssc->SSC_TCMR = (sh->ssc->SSC_TCMR & ~AT91C_SSC_START) | AT91C_SSC_START_CONTINOUS;
if(sh->callback)
- sh->callback(CALLBACK_TX_FRAME_BEGIN, NULL);
+ sh->callback(SSC_CALLBACK_TX_FRAME_BEGIN, NULL);
}
if( sr & AT91C_SSC_TXEMPTY ) {
@@ -297,7 +297,7 @@ static __ramfunc int _reload_rx(ssc_handle_t *sh)
goto out;
}
- ssc_dma_rx_buffer_t *buffer = _get_buffer(FREE, PENDING);
+ ssc_dma_rx_buffer_t *buffer = _get_buffer(SSC_FREE, SSC_PENDING);
if(buffer == NULL) {
ssc_metrics[METRIC_RX_OVERFLOWS].value++;
@@ -328,7 +328,7 @@ static __ramfunc ssc_dma_rx_buffer_t* _unload_rx(ssc_handle_t *sh)
rcr = sh->pdc->PDC_RCR;
AT91F_PDC_SetRx(sh->pdc, 0, 0);
sh->rx_buffer[0] = NULL;
- buffer->state = FULL;
+ buffer->state = SSC_FULL;
if(rcr == 0) {
buffer->flags.overflow = 1;
@@ -357,7 +357,7 @@ static __ramfunc ssc_dma_rx_buffer_t* _unload_rx(ssc_handle_t *sh)
if((buffer->len_transfers - rcr) != (rpr - (unsigned int)buffer->data)*(buffer->reception_mode->transfersize_pdc/8)) {
ssc_metrics[METRIC_MANAGEMENT_ERRORS_3].value++;
- buffer->state = FREE;
+ buffer->state = SSC_FREE;
return NULL;
}
@@ -393,7 +393,7 @@ static void _ssc_start_rx(ssc_handle_t *sh)
AT91C_SSC_CP1 | AT91C_SSC_ENDRX;
sh->rx_running = 1;
if(sh->callback != NULL)
- sh->callback(CALLBACK_RX_STARTING, sh);
+ sh->callback(SSC_CALLBACK_RX_STARTING, sh);
// Actually enable reception
int dummy = sh->ssc->SSC_RHR; (void)dummy;
@@ -411,7 +411,7 @@ static void _ssc_stop_rx(ssc_handle_t *sh)
sh->ssc->SSC_IDR = SSC_RX_IRQ_MASK;
sh->rx_running = 0;
if(sh->callback != NULL)
- sh->callback(CALLBACK_RX_STOPPED, sh);
+ sh->callback(SSC_CALLBACK_RX_STOPPED, sh);
taskEXIT_CRITICAL();
}
@@ -556,7 +556,7 @@ static int _ssc_register_callback(ssc_handle_t *sh, ssc_callback_t _callback)
if(sh->callback != NULL) return -EBUSY;
sh->callback = _callback;
if(sh->callback != NULL)
- sh->callback(CALLBACK_SETUP, sh);
+ sh->callback(SSC_CALLBACK_SETUP, sh);
return 0;
}
@@ -565,7 +565,7 @@ static int _ssc_unregister_callback(ssc_handle_t *sh, ssc_callback_t _callback)
if(!sh) return -EINVAL;
if(_callback == NULL || sh->callback == _callback) {
if(sh->callback != NULL)
- sh->callback(CALLBACK_TEARDOWN, sh);
+ sh->callback(SSC_CALLBACK_TEARDOWN, sh);
sh->callback = NULL;
}
return 0;
@@ -686,7 +686,7 @@ int ssc_send(ssc_handle_t* sh, ssc_dma_tx_buffer_t *buffer)
AT91F_PDC_SetTx(sh->pdc, buffer->data, num_data);
AT91F_PDC_SetNextTx(sh->pdc, 0, 0);
- buffer->state = PENDING;
+ buffer->state = SSC_PENDING;
sh->ssc->SSC_IER = AT91C_SSC_TXEMPTY | AT91C_SSC_TXSYN;
/* Enable DMA */
@@ -795,7 +795,7 @@ int ssc_get_metric(ssc_metric metric, char **description, int *value)
_value = 0;
int i;
for(i=0; i < SSC_DMA_BUFFER_COUNT; i++)
- if(_rx_buffers[i].state == FREE) _value++;
+ if(_rx_buffers[i].state == SSC_FREE) _value++;
break;
case METRIC_MANAGEMENT_ERRORS:
_value = ssc_metrics[METRIC_MANAGEMENT_ERRORS_1].value +
diff --git a/openpicc/application/ssc.h b/openpicc/application/ssc.h
index 9edec64..e99d444 100644
--- a/openpicc/application/ssc.h
+++ b/openpicc/application/ssc.h
@@ -21,17 +21,17 @@ typedef enum {
extern int ssc_get_metric(ssc_metric metric, char **description, int *value);
typedef enum {
- CALLBACK_RX_STARTING, // *data is ssh_handle_t *sh
- CALLBACK_RX_STOPPED, // *data is ssh_handle_t *sh
- CALLBACK_RX_FRAME_BEGIN, // *data is int *end_asserted
- // may set *end_asserted = 1 to force tell the IRQ handler
- // that you have detected the end of reception
- CALLBACK_RX_FRAME_ENDED, // *data is ssc_dma_rx_buffer *buffer
- CALLBACK_TX_FRAME_BEGIN,
- CALLBACK_TX_FRAME_ENDED,
- CALLBACK_TX_FRAME_ABORTED,
- CALLBACK_SETUP, // *data is ssh_handle_t *sh
- CALLBACK_TEARDOWN, // *data is ssh_handle_t *sh
+ SSC_CALLBACK_RX_STARTING, // *data is ssh_handle_t *sh
+ SSC_CALLBACK_RX_STOPPED, // *data is ssh_handle_t *sh
+ SSC_CALLBACK_RX_FRAME_BEGIN, // *data is int *end_asserted
+ // may set *end_asserted = 1 to force tell the IRQ handler
+ // that you have detected the end of reception
+ SSC_CALLBACK_RX_FRAME_ENDED, // *data is ssc_dma_rx_buffer *buffer
+ SSC_CALLBACK_TX_FRAME_BEGIN,
+ SSC_CALLBACK_TX_FRAME_ENDED,
+ SSC_CALLBACK_TX_FRAME_ABORTED,
+ SSC_CALLBACK_SETUP, // *data is ssh_handle_t *sh
+ SSC_CALLBACK_TEARDOWN, // *data is ssh_handle_t *sh
} ssc_callback_reason;
typedef void (*ssc_callback_t)(ssc_callback_reason reason, void *data);
diff --git a/openpicc/application/ssc_buffer.h b/openpicc/application/ssc_buffer.h
index 5365851..527ae46 100644
--- a/openpicc/application/ssc_buffer.h
+++ b/openpicc/application/ssc_buffer.h
@@ -15,11 +15,11 @@
#endif
typedef enum {
- FREE=0, /* Buffer is free */
- PENDING, /* Buffer has been given to the DMA controller and is currently being filled */
- FULL, /* DMA controller signalled that the buffer is full */
- PROCESSING,/* The buffer is currently processed by the consumer (e.g. decoder) */
- PREFILLED, /* The buffer has been prefilled for later usage (only used for TX) */
+ SSC_FREE=0, /* Buffer is free */
+ SSC_PENDING, /* Buffer has been given to the DMA controller and is currently being filled */
+ SSC_FULL, /* DMA controller signalled that the buffer is full */
+ SSC_PROCESSING,/* The buffer is currently processed by the consumer (e.g. decoder) */
+ SSC_PREFILLED, /* The buffer has been prefilled for later usage (only used for TX) */
} ssc_dma_buffer_state_t;
enum ssc_mode {
diff --git a/openpicc/application/tc_recv.c b/openpicc/application/tc_recv.c
new file mode 100644
index 0000000..fa6b510
--- /dev/null
+++ b/openpicc/application/tc_recv.c
@@ -0,0 +1,213 @@
+/***************************************************************
+ *
+ * OpenPICC - ISO 14443 Layer 2 Type A T/C based receiver code
+ * Implements a receiver using FDT Timer/Counter (TC2) and the
+ * FIQ to measure the number of carrier cycles between modulation
+ * pauses.
+ *
+ * The timing measurements are given to the differential miller
+ * decoder on the fly to interleave reception and decoding. This
+ * means two things: a) The CPU will be held in an IRQ handler
+ * with IRQs disabled for the time of reception and b) The frame
+ * will already have been fully decoded to a iso14443_frame
+ * structure when reception ends.
+ *
+ * Copyright 2008 Henryk Plötz <henryk@ploetzli.ch>
+ *
+ ***************************************************************
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+*/
+
+#include <FreeRTOS.h>
+#include <openpicc.h>
+#include <errno.h>
+#include <string.h>
+
+#include <task.h>
+#include <queue.h>
+
+#include "tc_recv.h"
+
+#include "iso14443a_diffmiller.h"
+#include "usb_print.h"
+#include "pio_irq.h"
+#include "led.h"
+#include "cmd.h"
+
+struct tc_recv_handle {
+ u_int8_t initialized;
+ u_int8_t pauses_count;
+ struct diffmiller_state *decoder;
+ int current, next;
+ tc_recv_callback_t callback;
+ iso14443_frame *current_frame;
+ xQueueHandle rx_queue;
+};
+
+static struct tc_recv_handle _tc;
+
+#define BUFSIZE 1024
+typedef struct {
+ u_int32_t count;
+ u_int32_t data[BUFSIZE];
+} fiq_buffer_t;
+fiq_buffer_t fiq_buffers[2];
+
+fiq_buffer_t *tc_sniffer_next_buffer_for_fiq = 0;
+
+iso14443_frame rx_frames[TC_RECV_NUMBER_OF_FRAME_BUFFERS];
+
+#define REAL_FRAME_END 333
+
+static int tc_recv_buffer_overruns = 0;
+
+static inline iso14443_frame *get_frame_buffer(tc_recv_handle_t th)
+{
+ if(th->current_frame) return th->current_frame;
+ unsigned int i; iso14443_frame *result;
+ for(i=0; i<sizeof(rx_frames)/sizeof(rx_frames[0]); i++) {
+ if(rx_frames[i].state == FRAME_FREE) {
+ result = &rx_frames[i];
+ result->state = FRAME_PENDING;
+ th->current_frame = result;
+ return result;
+ }
+ }
+ tc_recv_buffer_overruns++;
+ return NULL;
+}
+
+static portBASE_TYPE handle_frame(iso14443_frame *frame, portBASE_TYPE task_woken)
+{
+ if(_tc.callback) _tc.callback(TC_RECV_CALLBACK_RX_FRAME_ENDED, frame);
+ if(frame->state != FRAME_FREE) {
+ task_woken = xQueueSendFromISR(_tc.rx_queue, &frame, task_woken);
+ }
+ _tc.current_frame = NULL;
+ return task_woken;
+}
+
+static portBASE_TYPE handle_buffer(u_int32_t data[], unsigned int count, portBASE_TYPE task_woken)
+{
+ unsigned int offset = 0;
+ while(offset < count) {
+ iso14443_frame *rx_frame = get_frame_buffer(&_tc);
+ if(rx_frame == NULL) return task_woken;
+ int ret = iso14443a_decode_diffmiller(_tc.decoder, rx_frame, data, &offset, count);
+ if(ret == 0) {
+ task_woken = handle_frame(rx_frame, task_woken);
+ }
+ }
+ return task_woken;
+}
+
+static inline portBASE_TYPE flush_buffer(fiq_buffer_t *buffer, portBASE_TYPE task_woken)
+{
+ if(buffer->count > 0) {
+ if(buffer->count >= BUFSIZE) {
+ usb_print_string_f("Warning: Possible buffer overrun detected\n\r",0);
+ //overruns++;
+ }
+ buffer->count = MIN(buffer->count, BUFSIZE);
+ task_woken = handle_buffer(buffer->data, buffer->count, task_woken);
+ buffer->count = 0;
+ }
+ return task_woken;
+}
+
+#define NEXT_BUFFER(a) ((a+1)%(sizeof(fiq_buffers)/sizeof(fiq_buffers[0])))
+
+static portBASE_TYPE switch_buffers(portBASE_TYPE task_woken)
+{
+ _tc.next = NEXT_BUFFER(_tc.current);
+ task_woken = flush_buffer( &fiq_buffers[_tc.next] , task_woken);
+
+ tc_sniffer_next_buffer_for_fiq = &fiq_buffers[_tc.current=_tc.next];
+ return task_woken;
+}
+
+static portBASE_TYPE tc_recv_irq(u_int32_t pio, portBASE_TYPE task_woken)
+{
+ (void)pio;
+ /* TODO There should be some emergency exit here to prevent the CPU from
+ * spinning in the IRQ for excessive amounts of time. (Maximum transmission
+ * time for 256 Byte frame is something like 21ms.)
+ */
+ while(*AT91C_TC2_CV <= REAL_FRAME_END ||
+ fiq_buffers[NEXT_BUFFER(_tc.current)].count > 0 ||
+ fiq_buffers[_tc.current].count > 0)
+ task_woken = switch_buffers(task_woken);
+
+ if(*AT91C_TC2_CV > REAL_FRAME_END) {
+ iso14443_frame *rx_frame = get_frame_buffer(&_tc);
+ if(rx_frame == NULL) return task_woken;
+ int ret = iso14443a_diffmiller_assert_frame_ended(_tc.decoder, rx_frame);
+ if(ret == 0) {
+ task_woken = handle_frame(rx_frame, task_woken);
+ }
+ }
+ return task_woken;
+}
+
+
+int tc_recv_init(tc_recv_handle_t *_th, int pauses_count, tc_recv_callback_t callback)
+{
+ if(_tc.initialized) return -EBUSY;
+ tc_recv_handle_t th = &_tc;
+
+ memset(fiq_buffers, 0, sizeof(fiq_buffers));
+ th->current = th->next = 0;
+
+ memset(rx_frames, 0, sizeof(rx_frames));
+ th->current_frame = NULL;
+
+ if(th->rx_queue == NULL) {
+ th->rx_queue = xQueueCreate(TC_RECV_NUMBER_OF_FRAME_BUFFERS, sizeof(iso14443_frame*));
+ if(th->rx_queue == NULL)
+ return -ENOMEM;
+ }
+
+ th->pauses_count = pauses_count;
+ th->decoder = iso14443a_init_diffmiller(th->pauses_count);
+ if(!th->decoder) return -EBUSY;
+
+ // The change interrupt is going to be handled by the FIQ and our secondary IRQ handler
+ AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_SSC_DATA);
+ if( pio_irq_register(OPENPICC_SSC_DATA, &tc_recv_irq) < 0)
+ return -EBUSY;
+ pio_irq_enable(OPENPICC_SSC_DATA);
+
+ th->initialized = 1;
+ *_th = th;
+
+ th->callback = callback;
+ if(th->callback) th->callback(TC_RECV_CALLBACK_SETUP, th);
+
+ return 0;
+}
+
+int tc_recv_receive(tc_recv_handle_t th, iso14443_frame* *frame, unsigned int timeout)
+{
+ if(th == NULL) return -EINVAL;
+ if(!th->initialized) return -EINVAL;
+
+ if(xQueueReceive(th->rx_queue, frame, timeout)){
+ if(*frame != NULL) return 0;
+ else return -EINTR;
+ }
+
+ return -ETIMEDOUT;
+}
diff --git a/openpicc/application/tc_recv.h b/openpicc/application/tc_recv.h
new file mode 100644
index 0000000..4f2392b
--- /dev/null
+++ b/openpicc/application/tc_recv.h
@@ -0,0 +1,21 @@
+#ifndef TC_RECV_H_
+#define TC_RECV_H_
+
+#include "iso14443.h"
+
+#define TC_RECV_NUMBER_OF_FRAME_BUFFERS 10
+
+struct tc_recv_handle;
+typedef struct tc_recv_handle *tc_recv_handle_t;
+
+typedef enum {
+ TC_RECV_CALLBACK_RX_FRAME_ENDED, // *data is iso14443_frame *frame
+ TC_RECV_CALLBACK_SETUP, // *data is tc_recv_handle_t th
+ TC_RECV_CALLBACK_TEARDOWN, // *data is tc_recv_handle_t th
+} tc_recv_callback_reason;
+typedef void (*tc_recv_callback_t)(tc_recv_callback_reason reason, void *data);
+
+extern int tc_recv_init(tc_recv_handle_t *th, int pauses_count, tc_recv_callback_t callback);
+extern int tc_recv_receive(tc_recv_handle_t th, iso14443_frame* *frame, unsigned int timeout);
+
+#endif /*TC_RECV_H_*/
diff --git a/openpicc/application/tc_sniffer.c b/openpicc/application/tc_sniffer.c
index 943a2ad..592b5a4 100644
--- a/openpicc/application/tc_sniffer.c
+++ b/openpicc/application/tc_sniffer.c
@@ -56,15 +56,7 @@ static xSemaphoreHandle data_semaphore;
struct diffmiller_state *decoder;
iso14443_frame rx_frame;
-#define BUFSIZE 1024
#define WAIT_TICKS (20*portTICK_RATE_MS)
-typedef struct {
- u_int32_t count;
- u_int32_t data[BUFSIZE];
-} fiq_buffer_t;
-fiq_buffer_t fiq_buffers[2];
-
-fiq_buffer_t *tc_sniffer_next_buffer_for_fiq = 0;
portBASE_TYPE currently_sniffing = 0;
enum { NONE, REQUEST_START, REQUEST_STOP } request_change = REQUEST_START;
personal git repositories of Harald Welte. Your mileage may vary