summaryrefslogtreecommitdiff
path: root/openpicc/application/ssc_picc.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application/ssc_picc.c')
-rw-r--r--openpicc/application/ssc_picc.c731
1 files changed, 0 insertions, 731 deletions
diff --git a/openpicc/application/ssc_picc.c b/openpicc/application/ssc_picc.c
deleted file mode 100644
index df6d7fa..0000000
--- a/openpicc/application/ssc_picc.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/* AT91SAM7 SSC controller routines for OpenPICC
- * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
- * (C) 2007 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * We use SSC for both TX and RX side.
- *
- * RX side is interconnected with demodulated carrier
- *
- * TX side is interconnected with load modulation circuitry
- */
-
-//#undef DEBUG
-
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <AT91SAM7.h>
-#include <lib_AT91SAM7.h>
-
-#include <FreeRTOS.h>
-#include "queue.h"
-#include "task.h"
-
-#include "dbgu.h"
-#include "led.h"
-#include "cmd.h"
-#include "board.h"
-#include "openpicc.h"
-
-#include "ssc_picc.h"
-#include "tc_cdiv_sync.h"
-#include "tc_fdt.h"
-
-#include "pio_irq.h"
-#include "usb_print.h"
-#include "iso14443_layer3a.h"
-
-#define DEBUG_SSC_REFILL 1
-#ifdef DEBUG_SSC_REFILL
-#define DEBUGR(x, args ...) DEBUGPCRF(x, ## args)
-#else
-#define DEBUGR(x, args ...)
-#endif
-
-#define DEBUG_LOAD_AND_UNLOAD 0
-
-static const AT91PS_SSC ssc = AT91C_BASE_SSC;
-static AT91PS_PDC rx_pdc;
-static AT91PS_PDC tx_pdc;
-
-xQueueHandle ssc_rx_queue = NULL;
-
-struct ssc_state {
- ssc_dma_rx_buffer_t* buffer[2];
- enum ssc_mode mode;
-};
-static struct ssc_state ssc_state;
-
-/* Note: Only use 8, 16 or 32 for the transfersize. (These are the sizes used by the PDC and even though
- * the SSC supports different sizes, all PDC tranfers will be either 8, 16 or 32, rounding up.) */
-static const ssc_mode_def ssc_sizes[] = {
- /* Undefined, no size set */
- [SSC_MODE_NONE] = {SSC_MODE_NONE, 0, 0, 0},
- /* 14443A Short Frame: 1 transfer of ISO14443A_SHORT_LEN bits */
- [SSC_MODE_14443A_SHORT] = {SSC_MODE_14443A_SHORT, ISO14443A_SHORT_LEN, ISO14443A_SHORT_TRANSFER_SIZE, 1},
- /* 14443A Standard Frame: FIXME 16 transfers of 32 bits (maximum number), resulting in 512 samples */
- [SSC_MODE_14443A_STANDARD] = {SSC_MODE_14443A_STANDARD, 32, 32, 16},
- /* 14443A Frame, don't care if standard or short */
- [SSC_MODE_14443A] = {SSC_MODE_14443A,
- 4 * ISO14443A_SAMPLE_LEN, // transfersize_ssc
- 4 * ISO14443A_SAMPLE_LEN <= 8 ? 8 : 16, // transfersize_pdc
- ISO14443A_MAX_RX_FRAME_SIZE_IN_BITS},
- [SSC_MODE_14443B] = {SSC_MODE_14443B, 32, 32, 16}, /* 64 bytes */
- [SSC_MODE_EDGE_ONE_SHOT] = {SSC_MODE_EDGE_ONE_SHOT, 32, 32, 16}, /* 64 bytes */
- [SSC_MODE_CONTINUOUS] = {SSC_MODE_CONTINUOUS, 32, 32, 511}, /* 2044 bytes */
-};
-
-/* ************** SSC BUFFER HANDLING *********************** */
-static ssc_dma_rx_buffer_t dma_buffers[SSC_DMA_BUFFER_COUNT];
-ssc_dma_tx_buffer_t ssc_tx_buffer;
-
-static volatile int overflows;
-static volatile int ssc_buffer_errors;
-static volatile int late_frames = 0;
-
-static int ssc_count_free(void) {
- int i,free = 0;
- for(i=0; i<SSC_DMA_BUFFER_COUNT; i++) {
- if(dma_buffers[i].state == FREE) free++;
- }
- return free;
-}
-
-int ssc_get_metric(ssc_metric metric) {
- switch(metric) {
- case OVERFLOWS:
- return overflows;
- break;
- case BUFFER_ERRORS:
- return ssc_buffer_errors;
- break;
- case FREE_BUFFERS:
- return ssc_count_free();
- break;
- case LATE_FRAMES:
- return late_frames;
- break;
- case SSC_ERRORS:
- return ssc_get_metric(OVERFLOWS) + ssc_get_metric(BUFFER_ERRORS);
- break;
- }
- return 0;
-}
-
-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_rx_buffer_t* result = NULL;
- int i=0;
- for(i=0; i<SSC_DMA_BUFFER_COUNT; i++) {
- if(dma_buffers[i].state == oldstate) {
- result = &dma_buffers[i];
- result->state = newstate;
- break;
- }
- }
- return result;
-}
-
-
-static int __ramfunc __ssc_rx_load(int secondary);
-static ssc_dma_rx_buffer_t* __ramfunc __ssc_rx_unload(int secondary);
-/*
- * Find and load an RX buffer into the DMA controller, using the current SSC mode
- */
-static int __ramfunc __ssc_rx_load(int secondary)
-{
- ssc_dma_rx_buffer_t *buffer;
-
- buffer = ssc_find_dma_buffer(FREE, PENDING);
- if (!buffer) {
- DEBUGP("no_rctx_for_refill! ");
- overflows++;
- return -1;
- }
- DEBUGR("filling SSC RX%u dma ctx: %u (len=%u) ", secondary,
- req_ctx_num(buffer), buffer->size);
- buffer->len_transfers = ssc_sizes[ssc_state.mode].transfers;
- buffer->reception_mode = &ssc_sizes[ssc_state.mode];
-
- if(ssc_state.buffer[secondary] != NULL) {
- /* This condition is not expected to happen and would probably indicate a bug
- * of some sort. However, instead of leaking buffers we'll just pretend it to
- * be free again. */
- ssc_buffer_errors++;
- usb_print_buffer_f("^", 0, 1, 0);
- if(ssc_state.buffer[secondary]->state == PENDING) {
- ssc_state.buffer[secondary]->state = FREE;
- }
- }
-
- if (secondary) {
- AT91F_PDC_SetNextRx(rx_pdc, buffer->data,
- ssc_sizes[ssc_state.mode].transfers);
- ssc_state.buffer[1] = buffer;
- } else {
- AT91F_PDC_SetRx(rx_pdc, buffer->data,
- ssc_sizes[ssc_state.mode].transfers);
- ssc_state.buffer[0] = buffer;
- }
-
- if(DEBUG_LOAD_AND_UNLOAD) {
- if(secondary) {int i=usb_print_set_default_flush(0);
- DumpStringToUSB("{1:");
- DumpUIntToUSB(rx_pdc->PDC_RNCR);
- DumpStringToUSB(" ");
- DumpUIntToUSB(rx_pdc->PDC_RNPR);
- DumpStringToUSB("} ");
- usb_print_set_default_flush(i);}
- else {int i=usb_print_set_default_flush(0);
- DumpStringToUSB("{0:");
- DumpUIntToUSB(rx_pdc->PDC_RCR);
- DumpStringToUSB(" ");
- DumpUIntToUSB(rx_pdc->PDC_RPR);
- DumpStringToUSB("} ");
- usb_print_set_default_flush(i);}
- }
-
- return 0;
-}
-
-/*
- * Take the RX buffer(s) from the DMA controller, e.g. to abort a currently executing receive process and
- * either reclaim the buffer(s) (if no transfer have been done so far) or mark them as used, updating
- * the length fields to match the number of transfers that have actually executed.
- * Warning: When this function executes, the mapping in ssc_state is expected to match the mapping in
- * the PDC (e.g. ssc_state[0] is the RX Buffer and ssc_state[1] is the Next RX Buffer). Do not use this
- * function while the PDC transfer is enabled. Especially do not run it from the SSC RX IRQ.
- */
-static int __ramfunc __ssc_tx_unload_all(ssc_dma_rx_buffer_t** primary, ssc_dma_rx_buffer_t** secondary)
-{
- if(primary != NULL) *primary = __ssc_rx_unload(0); else __ssc_rx_unload(0);
- if(secondary != NULL) *secondary = __ssc_rx_unload(1); else __ssc_rx_unload(1);
- return 1;
-}
-static ssc_dma_rx_buffer_t* __ramfunc __ssc_rx_unload(int secondary)
-{
- ssc_dma_rx_buffer_t *buffer = ssc_state.buffer[secondary];
- if(buffer == NULL) return NULL;
-
- if(DEBUG_LOAD_AND_UNLOAD) {
- if(secondary) {int i=usb_print_set_default_flush(0);
- DumpStringToUSB("(1:");
- DumpUIntToUSB(rx_pdc->PDC_RNCR);
- DumpStringToUSB(" ");
- DumpUIntToUSB(rx_pdc->PDC_RNPR);
- DumpStringToUSB(") ");
- usb_print_set_default_flush(i);}
- else {int i=usb_print_set_default_flush(0);
- DumpStringToUSB("(0:");
- DumpUIntToUSB(rx_pdc->PDC_RCR);
- DumpStringToUSB(" ");
- DumpUIntToUSB(rx_pdc->PDC_RPR);
- DumpStringToUSB(") ");
- usb_print_set_default_flush(i);}
- }
-
- u_int16_t remaining_transfers = (secondary ? rx_pdc->PDC_RNCR : rx_pdc->PDC_RCR);
- u_int8_t* next_transfer_location = (u_int8_t*)(secondary ? rx_pdc->PDC_RNPR : rx_pdc->PDC_RPR);
- u_int16_t elapsed_transfers = buffer->reception_mode->transfers - remaining_transfers;
-
- /* BUG BUG BUG For some reason the RNCR is zero, even though there have been no transfers in the secondary
- * buffer. For now just assume that secondary==1 && remaining_transfers==0 is a bug condition and actually
- * means elapsed_transfers == 0. Of course this will fail should they second buffer really be completely full. */
- if(secondary && remaining_transfers==0) {
- remaining_transfers = buffer->reception_mode->transfers;
- elapsed_transfers = 0;
- }
-
- u_int32_t elapsed_size = buffer->reception_mode->transfersize_pdc/8 * elapsed_transfers;
-
- /* Consistency check */
- if( next_transfer_location - elapsed_size != buffer->data ) {
- int i=usb_print_set_default_flush(0);
- DumpStringToUSB("!!!"); DumpUIntToUSB(secondary); DumpStringToUSB(" ");
- DumpUIntToUSB((int)next_transfer_location); DumpStringToUSB(" ");
- DumpUIntToUSB(elapsed_size); DumpStringToUSB(" "); DumpUIntToUSB((int)buffer->data); DumpStringToUSB(" ");
- usb_print_set_default_flush(i);
- ssc_buffer_errors++;
- usb_print_buffer_f("°", 0, 1, 0);
- if(buffer->state == PENDING) buffer->state = FREE;
- ssc_state.buffer[secondary] = NULL;
- return NULL;
- }
-
- if(secondary) {
- AT91F_PDC_SetNextRx(rx_pdc, 0, 0);
- } else {
- AT91F_PDC_SetRx(rx_pdc, 0, 0);
- }
- if(buffer->state == PENDING || buffer->state==FULL) {
- buffer->len_transfers = elapsed_transfers;
- if(DEBUG_LOAD_AND_UNLOAD)
- {int i=usb_print_set_default_flush(0);
- DumpStringToUSB("<");
- DumpUIntToUSB((unsigned int)buffer);
- DumpStringToUSB(": ");
- DumpUIntToUSB(elapsed_transfers);
- DumpStringToUSB("> ");
- usb_print_set_default_flush(i);}
- if(elapsed_transfers > 0) {
- buffer->state = FULL;
- } else {
- buffer->state = FREE;
- }
- }
- ssc_state.buffer[secondary] = NULL;
-
- return buffer;
-}
-
-#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=0, num_data=0, sync_len=0;
- u_int32_t start_cond=0;
- u_int32_t clock_gating=0;
- u_int8_t stop = 0;
-
- /* 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:
- start_cond = AT91C_SSC_START_0;
- sync_len = ISO14443A_SOF_LEN;
- ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE;
- data_len = ISO14443A_SHORT_LEN;
- num_data = 2;
- clock_gating = (0x2 << 6);
- 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 = 32;
- num_data = 16; /* FIXME */
- clock_gating = (0x2 << 6);
- break;
- case SSC_MODE_14443A:
- start_cond = AT91C_SSC_START_0;
- sync_len = ISO14443A_EOF_LEN;
- ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE << (ISO14443A_EOF_LEN-ISO14443A_SOF_LEN);
- ssc->SSC_RC1R = ISO14443A_EOF_SAMPLE;
- data_len = ssc_sizes[SSC_MODE_14443A].transfersize_ssc;
- num_data = 16; /* Start with 16, then switch to continuous in the IRQ handler */
- stop = 1; /* Actually the documentation indicates that setting STOP makes switching to continuous unnecessary */
- clock_gating = (0x0 << 6);
- 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;
- //AT91C_SSC_START_RISE_RF;
- sync_len = 0;
- data_len = 32;
- num_data = 16;
- clock_gating = (0x2 << 6);
- break;
- case SSC_MODE_NONE:
- goto out_set_mode;
- break;
- }
- //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)
- //| AT91C_SSC_MSBF
- ;
- ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE |
- clock_gating | (0&AT91C_SSC_CKI) | start_cond | (stop << 12);
-
- /* Enable Rx DMA */
- AT91F_PDC_EnableRx(rx_pdc);
-
- /* Enable RX interrupts */
-/*
- AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN | AT91C_SSC_CP0 |
- AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);*/
-out_set_mode:
- ssc_state.mode = ssc_mode;
-}
-
-/* For some reason AT91C_SSC_START_RISE_RF (or AT91C_SSC_START_HIGH_RF or ...) doesn't
- * work as a start condition. Instead we'll configure TF as a PIO input pin, enable
- * a PIO change interrupt, have Fast Forcing enabled for the PIO change interrupt and
- * then activate the SSC TX in the FIQ handler on rising TF. ssc_tx_pending is queried
- * 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)
-{
- u_int8_t data_len, num_data, sync_len;
- u_int32_t start_cond;
-
- /* disable Tx */
- AT91F_PDC_DisableTx(tx_pdc);
- AT91F_SSC_DisableTx(AT91C_BASE_SSC);
-
- /* disable all Tx related interrupt sources */
- AT91F_SSC_DisableIt(ssc, SSC_TX_IRQ_MASK);
-
-#ifdef USE_SSC_TX_TF_WORKAROUND
- start_cond = AT91C_SSC_START_CONTINOUS;
-#else
- start_cond = AT91C_SSC_START_HIGH_RF;
-#endif
- sync_len = 1;
- data_len = 32;
- num_data = buf->len/(data_len/8); /* FIXME This is broken for more than 64 bytes */
-
- ssc->SSC_TFMR = ((data_len-1) & 0x1f) |
- (((num_data-1) & 0x0f) << 8) |
- (((sync_len-1) & 0x0f) << 16);
- ssc->SSC_TCMR = 0x01 | AT91C_SSC_CKO_NONE | AT91C_SSC_CKI | start_cond;
-
- AT91F_PDC_SetTx(tx_pdc, buf->data, num_data);
- AT91F_PDC_SetNextTx(tx_pdc, 0, 0);
- buf->state = PENDING;
-
- AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDTX);
- /* Enable DMA */
- AT91F_PDC_EnableTx(tx_pdc);
- //AT91F_PDC_SetTx(tx_pdc, buf->data, num_data);
-#ifdef OPENPICC_USE_SSC_DATA_GATING
- ssc_set_data_gate(0);
-#endif
- /* Start Transmission */
-#ifndef USE_SSC_TX_TF_WORKAROUND
- AT91F_SSC_EnableTx(AT91C_BASE_SSC);
-#else
- ssc_tx_pending = 1;
- pio_irq_enable(OPENPICC_SSC_TF);
- if(AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_SSC_TF)) {
- /* TF was probably already high when we enabled the PIO change interrupt for it. */
- ssc_tf_irq(OPENPICC_SSC_TF);
- vLedBlinkRed();
- late_frames++;
- usb_print_string_f("Late response\n\r", 0);
- }
-#endif
-}
-
-#ifdef USE_SSC_TX_TF_WORKAROUND
-void ssc_tf_irq(u_int32_t pio) {
- (void)pio;
- if(!AT91F_PIO_IsInputSet(AT91C_BASE_PIOA, OPENPICC_SSC_TF)) return;
- pio_irq_disable(OPENPICC_SSC_TF);
- if(ssc_tx_pending) { /* Transmit has not yet been started by the FIQ */
- AT91F_SSC_EnableTx(AT91C_BASE_SSC);
- ssc_tx_pending = 0;
- }
-}
-#endif
-
-
-static ssc_irq_ext_t irq_extension = NULL;
-ssc_irq_ext_t ssc_set_irq_extension(ssc_irq_ext_t ext_handler) {
- ssc_irq_ext_t old = irq_extension;
- irq_extension = ext_handler;
- return old;
-}
-
-void __ramfunc ssc_rx_stop_frame_ended(void)
-{
-}
-
-static void __ramfunc ssc_irq(void) __attribute__ ((naked));
-static void __ramfunc ssc_irq(void)
-{
- portENTER_SWITCHING_ISR();
- vLedSetRed(1);
- portBASE_TYPE task_woken = pdFALSE;
-
- u_int32_t ssc_sr = ssc->SSC_SR;
- u_int32_t orig_ssc_sr = ssc_sr;
- ssc_dma_rx_buffer_t *inbuf=NULL;
- DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode);
-
- if ((ssc_sr & AT91C_SSC_CP0) && (ssc_state.mode == SSC_MODE_14443A_SHORT || ssc_state.mode == SSC_MODE_14443A)) {
- /* Short frame, busy loop till the frame is received completely to
- * prevent a second irq entrance delay when the actual frame end
- * irq is raised. (The scheduler masks interrupts for about 56us,
- * which is too much for anticollision.) */
- int i = 0;
- //vLedBlinkRed();
- while( ! ((ssc_sr=ssc->SSC_SR) & (AT91C_SSC_ENDRX | AT91C_SSC_CP1)) ) {
- i++;
- if(i > 9600) break; /* Break out, clearly this is not a short frame or a reception error happened */
- }
- ssc_sr |= orig_ssc_sr;
- vLedSetRed(1);
- }
-
- if(orig_ssc_sr & AT91C_SSC_CP1) {usb_print_string_f("oCP1 ", 0); vLedBlinkRed();}
- if(ssc_sr & AT91C_SSC_CP1) usb_print_string_f("CP1 ", 0);
-
- if (ssc_sr & (AT91C_SSC_ENDRX | AT91C_SSC_CP1)) {
- inbuf = ssc_state.buffer[0];
- if(ssc_sr & AT91C_SSC_CP1 && !(ssc_sr & AT91C_SSC_ENDRX)) {
- /* Manually unload buffer 0, since only the SSC has stopped, not the PDC */
- __ssc_rx_unload(0);
- __ssc_rx_load(0);
- }
-
- inbuf->state = FULL;
- task_woken = xQueueSendFromISR(ssc_rx_queue, &inbuf, task_woken);
- vLedSetGreen(1);
-
- if(ssc_sr & AT91C_SSC_ENDRX) {
- /* second buffer got propagated to primary */
- ssc_state.buffer[0] = ssc_state.buffer[1];
- ssc_state.buffer[1] = NULL;
- }
-
- if(ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT || ssc_state.mode == SSC_MODE_14443A_SHORT
- || ssc_state.mode == SSC_MODE_14443A_STANDARD) {
- // Stop sampling here
- ssc_rx_stop();
- } else {
- 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_sr & AT91C_SSC_RXENA) if (__ssc_rx_load(0) == -1)
- AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
- AT91C_SSC_RXBUFF |
- AT91C_SSC_OVRUN);
- }
-
- if(ssc_sr & AT91C_SSC_RXENA && ssc_state.buffer[1] == NULL) if (__ssc_rx_load(1) == -1)
- AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
- AT91C_SSC_RXBUFF |
- AT91C_SSC_OVRUN);
- }
- }
-
- if (ssc_sr & AT91C_SSC_OVRUN)
- DEBUGP("RX_OVERRUN ");
-
- if (ssc_sr & AT91C_SSC_CP0)
- DEBUGP("CP0 ");
-
- if (ssc_sr & AT91C_SSC_TXSYN)
- DEBUGP("TXSYN ");
-
- if(ssc_sr & AT91C_SSC_ENDTX) {
-#ifdef OPENPICC_USE_SSC_DATA_GATING
- ssc_set_data_gate(1);
-#endif
- AT91F_SSC_EnableTx(AT91C_BASE_SSC);
- //usb_print_string_f("ENDTX ", 0);
- if(ssc_tx_buffer.state == PENDING) {
- ssc_tx_buffer.state = FREE;
- AT91F_SSC_DisableIt(ssc, SSC_TX_IRQ_MASK);
- }
- }
-
- if(ssc_sr & AT91C_SSC_TXBUFE)
- DEBUGP("TXBUFE ");
-
- if(irq_extension != NULL)
- irq_extension(ssc_sr, ssc_state.mode, inbuf?inbuf->data:NULL);
-
-
- DEBUGPCR("I");
- AT91F_AIC_ClearIt(AT91C_ID_SSC);
- AT91F_AIC_AcknowledgeIt();
-
- vLedSetRed(0);
- portEXIT_SWITCHING_ISR(task_woken);
-}
-
-void ssc_print(void)
-{
- DEBUGP("PDC_RPR=0x%08x ", rx_pdc->PDC_RPR);
- DEBUGP("PDC_RCR=0x%08x ", rx_pdc->PDC_RCR);
- DEBUGP("PDC_RNPR=0x%08x ", rx_pdc->PDC_RNPR);
- DEBUGP("PDC_RNCR=0x%08x ", rx_pdc->PDC_RNCR);
-}
-
-
-void ssc_rx_unthrottle(void)
-{
- 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");
-
- __ssc_rx_load(0);
- if(ssc_state.mode != SSC_MODE_14443A_SHORT) __ssc_rx_load(1);
-
- /* Enable Reception */
- AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 | AT91C_SSC_CP1 |
- AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN);
- AT91F_PDC_EnableRx(rx_pdc);
- AT91F_SSC_EnableRx(AT91C_BASE_SSC);
-
- /* Clear the flipflop */
- tc_cdiv_sync_reset();
-}
-
-void ssc_rx_stop(void)
-{
- /* Disable reception */
- AT91F_SSC_DisableRx(AT91C_BASE_SSC);
- AT91F_PDC_DisableRx(rx_pdc);
- AT91F_SSC_DisableIt(ssc, SSC_RX_IRQ_MASK);
- __ssc_tx_unload_all(NULL, NULL);
-}
-
-void ssc_tx_init(void)
-{
- /* IMPORTANT: Disable PA23 (PWM0) output, since it is connected to
- * PA17 !! */
- AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_MOD_PWM);
- AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, OPENPICC_MOD_SSC |
- OPENPICC_SSC_CLOCK | OPENPICC_SSC_TF, 0);
-#ifdef USE_SSC_TX_TF_WORKAROUND
- AT91F_PIO_CfgInput(AT91C_BASE_PIOA, OPENPICC_SSC_TF);
- pio_irq_register(OPENPICC_SSC_TF, ssc_tf_irq);
-#endif
-
- tx_pdc = (AT91PS_PDC) &(ssc->SSC_RPR);
-}
-
-void ssc_set_data_gate(int enable)
-{
- if(! OPENPICC->features.clock_gating) return;
- if(enable)
- AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC->DATA_GATE);
- else
- AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC->DATA_GATE);
-}
-
-void ssc_rx_init()
-{
- tc_cdiv_sync_init();
- tc_cdiv_sync_enable();
-
- if(ssc_rx_queue == NULL)
- ssc_rx_queue = xQueueCreate(10, sizeof(ssc_state.buffer[0]));
-
- rx_pdc = (AT91PS_PDC) &(ssc->SSC_RPR);
-
- AT91F_SSC_CfgPMC();
-
- AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA,
- OPENPICC_SSC_DATA | OPENPICC_SSC_CLOCK |
- OPENPICC_PIO_FRAME,
- 0);
-
- AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SSC_DATA_CONTROL);
- AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPICC_PIO_SSC_DATA_CONTROL);
-
- if(OPENPICC->features.clock_gating) {
- AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPICC->DATA_GATE);
- AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPICC->DATA_GATE);
- }
-
- AT91F_AIC_ConfigureIt(AT91C_ID_SSC,
- OPENPICC_IRQ_PRIO_SSC,
- AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (THandler)&ssc_irq);
-
- /* 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_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_NONE);
- ssc_state.buffer[0] = ssc_state.buffer[1] = NULL;
-
-#if 0
- AT91F_PDC_EnableRx(rx_pdc);
-
- /* Enable RX interrupts */
- AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN |
- AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);
-#endif
- /* Will be set to a real value some time later */
- tc_fdt_set(0xff00);
-
- AT91F_AIC_EnableIt(AT91C_ID_SSC);
-
- //usb_hdlr_register(&ssc_usb_in, OPENPCD_CMD_CLS_SSC);
-
- DEBUGP("\r\n");
-}
-
-void ssc_fini(void)
-{
-// usb_hdlr_unregister(OPENPCD_CMD_CLS_SSC);
- AT91F_PDC_DisableRx(rx_pdc);
- AT91F_PDC_DisableTx(tx_pdc);
- AT91F_SSC_DisableTx(ssc);
- AT91F_SSC_DisableRx(ssc);
- AT91F_SSC_DisableIt(ssc, 0xfff);
- AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,
- ((unsigned int) 1 << AT91C_ID_SSC));
-}
personal git repositories of Harald Welte. Your mileage may vary