Add code modules for tc_fdt, tc_cdiv_sync, tc_cdiv, ssc_picc
Almost all of these have not been checked yet, I just copied them over and hot-fixed compile time errors F.e. all ssc usb code has been removed git-svn-id: https://svn.openpcd.org:2342/trunk@323 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
This commit is contained in:
parent
9d397dfbbe
commit
1dfa375abb
|
@ -77,6 +77,9 @@ ARM_SRC= \
|
|||
application/da.c \
|
||||
application/pll.c \
|
||||
application/pio_irq.c \
|
||||
application/ssc_picc.c \
|
||||
application/tc_cdiv_sync.c \
|
||||
application/tc_fdt.c \
|
||||
os/boot/Cstartup_SAM7.c \
|
||||
os/core/list.c \
|
||||
os/core/queue.c \
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef DBGU_H_
|
||||
#define DBGU_H_
|
||||
|
||||
#define DEBUGPCRF(...) ;
|
||||
#define DEBUGPCRF(...) while(0);
|
||||
#define DEBUGPCR(...) while(0);
|
||||
#define DEBUGP(...) while(0);
|
||||
|
||||
#endif /*DBGU_H_*/
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "da.h"
|
||||
#include "pll.h"
|
||||
#include "pio_irq.h"
|
||||
#include "ssc_picc.h"
|
||||
|
||||
/**********************************************************************/
|
||||
static inline void prvSetupHardware (void)
|
||||
|
@ -82,6 +83,8 @@ int main (void)
|
|||
prvSetupHardware ();
|
||||
|
||||
pio_irq_init();
|
||||
|
||||
ssc_tx_init();
|
||||
|
||||
vLedInit();
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef __OPENPICC_H__
|
||||
#define __OPENPICC_H__
|
||||
|
||||
#include "board.h"
|
||||
|
||||
typedef unsigned char bool_t;
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
|
@ -32,6 +34,8 @@ typedef signed char s_int8_t;
|
|||
typedef signed short s_int16_t;
|
||||
typedef int s_int32_t;
|
||||
|
||||
#define int16_t s_int16_t
|
||||
|
||||
#define DA_BASELINE 200
|
||||
|
||||
#endif/*__OPENPICC_H__*/
|
||||
|
|
|
@ -0,0 +1,589 @@
|
|||
/* AT91SAM7 SSC controller routines for OpenPICC
|
||||
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
|
||||
*
|
||||
* 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 <os/usb_handler.h>
|
||||
#include "dbgu.h"
|
||||
#include "led.h"
|
||||
#include "board.h"
|
||||
#include "openpicc.h"
|
||||
|
||||
#include "ssc_picc.h"
|
||||
#include "tc_cdiv_sync.h"
|
||||
#include "tc_fdt.h"
|
||||
|
||||
//#define DEBUG_SSC_REFILL
|
||||
|
||||
/* definitions for four-times oversampling */
|
||||
#define REQA 0x10410441
|
||||
#define WUPA 0x04041041
|
||||
|
||||
static const AT91PS_SSC ssc = AT91C_BASE_SSC;
|
||||
static AT91PS_PDC rx_pdc;
|
||||
|
||||
enum ssc_mode {
|
||||
SSC_MODE_NONE,
|
||||
SSC_MODE_14443A_SHORT,
|
||||
SSC_MODE_14443A_STANDARD,
|
||||
SSC_MODE_14443B,
|
||||
SSC_MODE_EDGE_ONE_SHOT,
|
||||
SSC_MODE_CONTINUOUS,
|
||||
};
|
||||
|
||||
struct ssc_state {
|
||||
struct req_ctx *rx_ctx[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 */
|
||||
};
|
||||
|
||||
/* This is for four-times oversampling */
|
||||
#define ISO14443A_SOF_SAMPLE 0x01
|
||||
#define ISO14443A_SOF_LEN 4
|
||||
|
||||
#define SSC_RX_IRQ_MASK (AT91C_SSC_RXRDY | \
|
||||
AT91C_SSC_OVRUN | \
|
||||
AT91C_SSC_ENDRX | \
|
||||
AT91C_SSC_RXBUFF | \
|
||||
AT91C_SSC_RXSYN | \
|
||||
AT91C_SSC_CP0 | \
|
||||
AT91C_SSC_CP1)
|
||||
|
||||
#define SSC_TX_IRQ_MASK (AT91C_SSC_TXRDY | \
|
||||
AT91C_SSC_TXEMPTY | \
|
||||
AT91C_SSC_ENDTX | \
|
||||
AT91C_SSC_TXBUFE | \
|
||||
AT91C_SSC_TXSYN)
|
||||
|
||||
void ssc_rx_mode_set(enum ssc_mode ssc_mode)
|
||||
{
|
||||
u_int8_t data_len=0, num_data=0, sync_len=0;
|
||||
u_int32_t start_cond=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 = 32;
|
||||
num_data = 16;
|
||||
break;
|
||||
case SSC_MODE_14443A_STANDARD:
|
||||
start_cond = AT91C_SSC_START_0;
|
||||
sync_len = ISO14443A_SOF_LEN;
|
||||
ssc->SSC_RC0R = ISO14443A_SOF_SAMPLE;
|
||||
data_len = 32;
|
||||
num_data = 16; /* FIXME */
|
||||
break;
|
||||
case SSC_MODE_14443B:
|
||||
/* start sampling at first falling data edge */
|
||||
//start_cond =
|
||||
break;
|
||||
case SSC_MODE_EDGE_ONE_SHOT:
|
||||
case SSC_MODE_CONTINUOUS:
|
||||
/* unfortunately we don't have RD and RF interconnected
|
||||
* (at least not yet in the current hardware) */
|
||||
//start_cond = AT91C_SSC_START_EDGE_RF;
|
||||
start_cond = AT91C_SSC_START_CONTINOUS;
|
||||
//AT91C_SSC_START_RISE_RF;
|
||||
sync_len = 0;
|
||||
data_len = 32;
|
||||
num_data = 16;
|
||||
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);
|
||||
ssc->SSC_RCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE |
|
||||
(0x2 << 6) | AT91C_SSC_CKI | start_cond;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void ssc_tx_mode_set(enum ssc_mode ssc_mode)
|
||||
{
|
||||
u_int8_t data_len, num_data, sync_len;
|
||||
u_int32_t start_cond;
|
||||
|
||||
/* disable Tx */
|
||||
AT91F_SSC_DisableTx(AT91C_BASE_SSC);
|
||||
|
||||
/* disable all Tx related interrupt sources */
|
||||
AT91F_SSC_DisableIt(ssc, SSC_TX_IRQ_MASK);
|
||||
|
||||
switch (ssc_mode) {
|
||||
case SSC_MODE_14443A_SHORT:
|
||||
start_cond = AT91C_SSC_START_RISE_RF;
|
||||
sync_len = 0;
|
||||
data_len = 32;
|
||||
num_data = 1;
|
||||
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 = 1; /* FIXME */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ssc->SSC_TFMR = ((data_len-1) & 0x1f) |
|
||||
(((num_data-1) & 0x0f) << 8) |
|
||||
(((sync_len-1) & 0x0f) << 16);
|
||||
ssc->SSC_TCMR = AT91C_SSC_CKS_RK | AT91C_SSC_CKO_NONE | start_cond;
|
||||
|
||||
AT91F_SSC_EnableIt(ssc, AT91C_SSC_TXSYN);
|
||||
AT91F_SSC_EnableTx(AT91C_BASE_SSC);
|
||||
#if 0
|
||||
/* Enable RX interrupts */
|
||||
AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN |
|
||||
AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE);
|
||||
AT91F_PDC_EnableTx(tx_pdc);
|
||||
|
||||
ssc_state.mode = ssc_mode;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//static struct openpcd_hdr opcd_ssc_hdr = {
|
||||
// .cmd = OPENPCD_CMD_SSC_READ,
|
||||
//};
|
||||
|
||||
//static inline void init_opcdhdr(struct req_ctx *rctx)
|
||||
//{
|
||||
// memcpy(rctx->data, &opcd_ssc_hdr, sizeof(opcd_ssc_hdr));
|
||||
// rctx->tot_len = sizeof(opcd_ssc_hdr);
|
||||
//}
|
||||
|
||||
#define DEBUG_SSC_REFILL 1
|
||||
#ifdef DEBUG_SSC_REFILL
|
||||
#define DEBUGR(x, args ...) DEBUGPCRF(x, ## args)
|
||||
#else
|
||||
#define DEBUGR(x, args ...)
|
||||
#endif
|
||||
|
||||
static int __ramfunc __ssc_rx_refill(int secondary)
|
||||
{
|
||||
(void)secondary;
|
||||
// FIXME
|
||||
/* struct req_ctx *rctx;
|
||||
|
||||
rctx = req_ctx_find_get(1, RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY);
|
||||
if (!rctx) {
|
||||
DEBUGP("no_rctx_for_refill! ");
|
||||
return -1;
|
||||
}
|
||||
init_opcdhdr(rctx);
|
||||
DEBUGR("filling SSC RX%u dma ctx: %u (len=%u) ", secondary,
|
||||
req_ctx_num(rctx), rctx->size);
|
||||
rctx->tot_len = ssc_dmasize[ssc_state.mode]*4 +
|
||||
sizeof(struct openpcd_hdr);
|
||||
if (secondary) {
|
||||
AT91F_PDC_SetNextRx(rx_pdc, rctx->data+MAX_HDRSIZE,
|
||||
ssc_dmasize[ssc_state.mode]);
|
||||
ssc_state.rx_ctx[1] = rctx;
|
||||
} else {
|
||||
AT91F_PDC_SetRx(rx_pdc, rctx->data+MAX_HDRSIZE,
|
||||
ssc_dmasize[ssc_state.mode]);
|
||||
ssc_state.rx_ctx[0] = rctx;
|
||||
}
|
||||
*/
|
||||
tc_cdiv_sync_reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char dmabuf1[512];
|
||||
static char dmabuf2[512];
|
||||
|
||||
/* Try to refill RX dma descriptors. Return values:
|
||||
* 0) no dma descriptors empty
|
||||
* 1) filled next/secondary descriptor
|
||||
* 2) filled both primary and secondary descriptor
|
||||
* -1) no free request contexts to use
|
||||
* -2) only one free request context, but two free descriptors
|
||||
*/
|
||||
static int8_t ssc_rx_refill(void)
|
||||
{
|
||||
struct req_ctx *rctx;
|
||||
DEBUGR("refill ");
|
||||
#if 1
|
||||
rctx = req_ctx_find_get(1, RCTX_STATE_FREE, RCTX_STATE_SSC_RX_BUSY);
|
||||
DEBUGP("SSC_SR=0x%08x ", ssc->SSC_SR);
|
||||
if (AT91F_PDC_IsRxEmpty(rx_pdc)) {
|
||||
DEBUGR("filling primary SSC RX dma ctx: %u (len=%u) ",
|
||||
req_ctx_num(rctx), rctx->size);
|
||||
rctx->tot_len = rctx->size;
|
||||
AT91F_PDC_SetRx(rx_pdc, rctx->data+MAX_HDRSIZE,
|
||||
(rctx->size-MAX_HDRSIZE)>>2);
|
||||
ssc_state.rx_ctx[0] = rctx;
|
||||
|
||||
/* If primary is empty, secondary must be empty, too */
|
||||
rctx = req_ctx_find_get(1, RCTX_STATE_FREE,
|
||||
RCTX_STATE_SSC_RX_BUSY);
|
||||
if (!rctx) {
|
||||
DEBUGPCRF("no rctx for secondary refill!");
|
||||
return -2;
|
||||
}
|
||||
init_opcdhdr(rctx);
|
||||
}
|
||||
|
||||
if (AT91F_PDC_IsNextRxEmpty(rx_pdc)) {
|
||||
DEBUGR("filling secondary SSC RX dma ctx: %u (len=%u) ",
|
||||
req_ctx_num(rctx), rctx->size);
|
||||
rctx->tot_len = rctx->size;
|
||||
AT91F_PDC_SetNextRx(rx_pdc, rctx->data+MAX_HDRSIZE,
|
||||
(rctx->size-MAX_HDRSIZE)>2);
|
||||
ssc_state.rx_ctx[1] = rctx;
|
||||
return 2;
|
||||
} else {
|
||||
/* we were unable to fill*/
|
||||
DEBUGPCRF("prim/secnd DMA busy, can't refill");
|
||||
req_ctx_put(rctx);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (AT91F_PDC_IsRxEmpty(rx_pdc))
|
||||
AT91F_PDC_SetRx(rx_pdc, dmabuf1, sizeof(dmabuf1)>>2);
|
||||
|
||||
if (AT91F_PDC_IsNextRxEmpty(rx_pdc))
|
||||
AT91F_PDC_SetNextRx(rx_pdc, dmabuf2, sizeof(dmabuf2)>>2);
|
||||
else
|
||||
DEBUGPCRF("prim/secnd DMA busy, can't refill");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ISO14443A_FDT_SHORT_1 1236
|
||||
#define ISO14443A_FDT_SHORT_0 1172
|
||||
|
||||
static void __ramfunc ssc_irq(void)
|
||||
{
|
||||
u_int32_t ssc_sr = ssc->SSC_SR;
|
||||
// int i, *tmp, emptyframe = 0;
|
||||
DEBUGP("ssc_sr=0x%08x, mode=%u: ", ssc_sr, ssc_state.mode);
|
||||
|
||||
if (ssc_sr & AT91C_SSC_ENDRX) {
|
||||
#if 1
|
||||
/* in a one-shot sample, we don't want to keep
|
||||
* sampling further after having received the first
|
||||
* packet. */
|
||||
if (ssc_state.mode == SSC_MODE_EDGE_ONE_SHOT) {
|
||||
DEBUGP("DISABLE_RX ");
|
||||
ssc_rx_stop();
|
||||
}
|
||||
//AT91F_SSC_DisableIt(AT91C_BASE_SSC, SSC_RX_IRQ_MASK);
|
||||
#endif
|
||||
#if 0
|
||||
/* Experimental start SSC on frame, stop on FFFFFFFF */
|
||||
if (ssc_state.mode == SSC_MODE_CONTINUOUS) {
|
||||
//ssc->SSC_RCMR = (ssc->SSC_RCMR & ~AT91C_SSC_START) | AT91C_SSC_START_CONTINOUS;
|
||||
tmp = (u_int32_t*)ssc_state.rx_ctx[0]->data;
|
||||
for(i = ssc_state.rx_ctx[0]->size / 4; i >= 0 ; i--) {
|
||||
if( *tmp++ == 0xFFFFFFFF ) {
|
||||
*(tmp-1) = 0xAAAAAAAA; // debug marker
|
||||
/* No modulation for a long time, stop sampling
|
||||
* and prepare for next frame */
|
||||
DEBUGP("RESTART RX ");
|
||||
ssc_rx_stop();
|
||||
ssc_rx_mode_set(ssc_state.mode);
|
||||
ssc_rx_start();
|
||||
led_toggle(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Ignore empty frames */
|
||||
if (ssc_state.mode == SSC_MODE_CONTINUOUS) {
|
||||
// FIXME
|
||||
// tmp = (u_int32_t*)ssc_state.rx_ctx[0]->data + MAX_HDRSIZE;
|
||||
// emptyframe = 1;
|
||||
// for(i = (ssc_state.rx_ctx[0]->size-MAX_HDRSIZE) / 4 - 8/*WTF?*/; i > 0; i--) {
|
||||
// if( *tmp++ != 0xFFFFFFFF ) {
|
||||
// DEBUGPCR("NONEMPTY(%08x, %i): %08x", tmp, i, *(tmp-1));
|
||||
// emptyframe = 0;
|
||||
// break;
|
||||
// } else {
|
||||
// //DEBUGPCR("DUNNO(%08x, %i): %08x", tmp, i, tmp[i]);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
//DEBUGP("Sending primary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len);
|
||||
/* Mark primary RCTX as ready to send for usb */
|
||||
// if(!emptyframe) {
|
||||
// FIXME
|
||||
// DEBUGP("NONEMPTY");
|
||||
// req_ctx_set_state(ssc_state.rx_ctx[0],
|
||||
// RCTX_STATE_UDP_EP2_PENDING);
|
||||
// //RCTX_STATE_FREE);
|
||||
// } else {
|
||||
// DEBUGP("EMPTY");
|
||||
// req_ctx_put(ssc_state.rx_ctx[0]);
|
||||
// }
|
||||
|
||||
/* second buffer gets propagated to primary */
|
||||
ssc_state.rx_ctx[0] = ssc_state.rx_ctx[1];
|
||||
ssc_state.rx_ctx[1] = NULL;
|
||||
if (ssc_sr & AT91C_SSC_RXBUFF) {
|
||||
// DEBUGP("RXBUFF! ");
|
||||
// if (ssc_state.rx_ctx[0]) {
|
||||
// //DEBUGP("Sending secondary RCTX(%u, len=%u) ", req_ctx_num(ssc_state.rx_ctx[0]), ssc_state.rx_ctx[0]->tot_len);
|
||||
// req_ctx_set_state(ssc_state.rx_ctx[0],
|
||||
// RCTX_STATE_UDP_EP2_PENDING);
|
||||
// //RCTX_STATE_FREE);
|
||||
// }
|
||||
if (__ssc_rx_refill(0) == -1)
|
||||
AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
|
||||
AT91C_SSC_RXBUFF |
|
||||
AT91C_SSC_OVRUN);
|
||||
}
|
||||
|
||||
if (__ssc_rx_refill(1) == -1)
|
||||
AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
|
||||
AT91C_SSC_RXBUFF |
|
||||
AT91C_SSC_OVRUN);
|
||||
|
||||
// udp_refill_ep(2);
|
||||
|
||||
#if 0
|
||||
if (__ssc_rx_refill(1) == -1)
|
||||
AT91F_SSC_DisableIt(ssc, AT91C_SSC_ENDRX |
|
||||
AT91C_SSC_RXBUFF |
|
||||
AT91C_SSC_OVRUN);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ssc_sr & AT91C_SSC_OVRUN)
|
||||
DEBUGP("RX_OVERRUN ");
|
||||
|
||||
if (ssc_sr & AT91C_SSC_CP0)
|
||||
DEBUGP("CP0 ");
|
||||
|
||||
if (ssc_sr & AT91C_SSC_TXSYN)
|
||||
DEBUGP("TXSYN ");
|
||||
#if 0
|
||||
led_toggle(1);
|
||||
|
||||
switch (ssc_state.mode) {
|
||||
case SSC_MODE_14443A_SHORT:
|
||||
if (ssc_sr & AT91C_SSC_RXSYN)
|
||||
DEBUGP("RXSYN ");
|
||||
if (ssc_sr & AT91C_SSC_RXRDY) {
|
||||
u_int32_t sample = ssc->SSC_RHR;
|
||||
DEBUGP("RXRDY=0x%08x ", sample);
|
||||
/* Try to set FDT compare register ASAP */
|
||||
if (sample == REQA) {
|
||||
tc_fdt_set(ISO14443A_FDT_SHORT_0);
|
||||
/* FIXME: prepare and configure ATQA response */
|
||||
} else if (sample == WUPA) {
|
||||
tc_fdt_set(ISO14443A_FDT_SHORT_1);
|
||||
/* FIXME: prepare and configure ATQA response */
|
||||
} else
|
||||
DEBUGP("<== unknown ");
|
||||
}
|
||||
break;
|
||||
|
||||
case SSC_MODE_14443A_STANDARD:
|
||||
case SSC_MODE_EDGE_ONE_SHOT:
|
||||
DEBUGP("ONE_SHOT ");
|
||||
break;
|
||||
default:
|
||||
DEBUGP("UNKNOWN_MODE ");
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
DEBUGPCR("I");
|
||||
AT91F_AIC_ClearIt(AT91C_ID_SSC);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
/* Enable Reception */
|
||||
AT91F_SSC_EnableIt(ssc, AT91C_SSC_ENDRX | AT91C_SSC_CP0 |
|
||||
AT91C_SSC_RXBUFF | AT91C_SSC_OVRUN);
|
||||
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);
|
||||
}
|
||||
|
||||
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_DATA | OPENPICC_SSC_DATA |
|
||||
AT91C_PIO_PA15, 0);
|
||||
|
||||
ssc_tx_mode_set(SSC_MODE_14443A_SHORT);
|
||||
}
|
||||
|
||||
//static int ssc_usb_in(struct req_ctx *rctx)
|
||||
//{
|
||||
// FIXME
|
||||
// struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data;
|
||||
//
|
||||
// switch (poh->cmd) {
|
||||
// case OPENPCD_CMD_SSC_READ:
|
||||
// /* FIXME: allow host to specify mode */
|
||||
// ssc_rx_mode_set(SSC_MODE_EDGE_ONE_SHOT);
|
||||
// ssc_rx_start();
|
||||
// req_ctx_put(rctx);
|
||||
// return 0;
|
||||
// break;
|
||||
// case OPENPCD_CMD_SSC_WRITE:
|
||||
// /* FIXME: implement this */
|
||||
// //ssc_tx_start()
|
||||
// break;
|
||||
// default:
|
||||
// return USB_ERR(USB_ERR_CMD_UNKNOWN);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return (poh->flags & OPENPCD_FLAG_RESPOND) ? USB_RET_RESPOND : 0;
|
||||
//}
|
||||
|
||||
void ssc_rx_init(void)
|
||||
{
|
||||
tc_cdiv_sync_init();
|
||||
tc_cdiv_sync_enable();
|
||||
|
||||
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);
|
||||
|
||||
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_refill(0);
|
||||
__ssc_rx_refill(1);
|
||||
|
||||
ssc_rx_mode_set(SSC_MODE_NONE);
|
||||
#if 0
|
||||
AT91F_PDC_EnableRx(rx_pdc);
|
||||
|
||||
/* Enable RX interrupts */
|
||||
AT91F_SSC_EnableIt(ssc, AT91C_SSC_OVRUN |
|
||||
AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);
|
||||
#endif
|
||||
/* FIXME: This is hardcoded for REQA 0x26 */
|
||||
tc_fdt_set(ISO14443A_FDT_SHORT_0);
|
||||
|
||||
AT91F_AIC_EnableIt(AT91C_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_SSC_DisableTx(ssc);
|
||||
AT91F_SSC_DisableRx(ssc);
|
||||
AT91F_SSC_DisableIt(ssc, 0xfff);
|
||||
AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,
|
||||
((unsigned int) 1 << AT91C_ID_SSC));
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _SSC_H
|
||||
#define _SSC_H
|
||||
|
||||
extern void ssc_rx_start(void);
|
||||
extern void ssc_rx_stop(void);
|
||||
|
||||
/* Rx/Tx initialization separate, since Tx disables PWM output ! */
|
||||
extern void ssc_tx_init(void);
|
||||
extern void ssc_rx_init(void);
|
||||
|
||||
extern void ssc_fini(void);
|
||||
extern void ssc_rx_stop(void);
|
||||
extern void ssc_rx_unthrottle(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
/* OpenPC TC (Timer / Clock) support code
|
||||
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This idea of this code is to feed the 13.56MHz carrier clock of RC632
|
||||
* into TCLK1, which is routed to XC1. Then configure TC0 to divide this
|
||||
* clock by a configurable divider.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <lib_AT91SAM7.h>
|
||||
#include <AT91SAM7.h>
|
||||
#include <os/dbgu.h>
|
||||
|
||||
#include "../openpcd.h"
|
||||
#include <os/tc_cdiv.h>
|
||||
|
||||
static AT91PS_TCB tcb = AT91C_BASE_TCB;
|
||||
|
||||
/* set carrier divider to a specific */
|
||||
void tc_cdiv_set_divider(u_int16_t div)
|
||||
{
|
||||
tcb->TCB_TC0.TC_RC = div;
|
||||
|
||||
/* set to 50% duty cycle */
|
||||
tcb->TCB_TC0.TC_RA = 1;
|
||||
tcb->TCB_TC0.TC_RB = 1 + (div >> 1);
|
||||
}
|
||||
|
||||
void tc_cdiv_phase_add(int16_t inc)
|
||||
{
|
||||
tcb->TCB_TC0.TC_RA = (tcb->TCB_TC0.TC_RA + inc) % tcb->TCB_TC0.TC_RC;
|
||||
tcb->TCB_TC0.TC_RB = (tcb->TCB_TC0.TC_RB + inc) % tcb->TCB_TC0.TC_RC;
|
||||
|
||||
/* FIXME: can this be done more elegantly? */
|
||||
if (tcb->TCB_TC0.TC_RA == 0) {
|
||||
tcb->TCB_TC0.TC_RA += 1;
|
||||
tcb->TCB_TC0.TC_RB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void tc_cdiv_init(void)
|
||||
{
|
||||
/* Cfg PA28(TCLK1), PA0(TIOA0), PA1(TIOB0), PA20(TCLK2) as Periph B */
|
||||
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0,
|
||||
OPENPCD_PIO_CARRIER_IN |
|
||||
OPENPCD_PIO_CARRIER_DIV_OUT |
|
||||
OPENPCD_PIO_CDIV_HELP_OUT |
|
||||
OPENPCD_PIO_CDIV_HELP_IN);
|
||||
|
||||
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,
|
||||
((unsigned int) 1 << AT91C_ID_TC0));
|
||||
|
||||
/* Enable Clock for TC0 */
|
||||
tcb->TCB_TC0.TC_CCR = AT91C_TC_CLKEN;
|
||||
|
||||
/* Connect TCLK1 to XC1, TCLK2 to XC2 */
|
||||
tcb->TCB_BMR &= ~(AT91C_TCB_TC1XC1S | AT91C_TCB_TC2XC2S);
|
||||
tcb->TCB_BMR |= (AT91C_TCB_TC1XC1S_TCLK1 | AT91C_TCB_TC2XC2S_TCLK2);
|
||||
|
||||
/* Clock XC1, Wave mode, Reset on RC comp
|
||||
* TIOA0 on RA comp = set, * TIOA0 on RC comp = clear,
|
||||
* TIOB0 on EEVT = set, TIOB0 on RB comp = clear,
|
||||
* EEVT = XC2 (TIOA0) */
|
||||
tcb->TCB_TC0.TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE |
|
||||
AT91C_TC_WAVESEL_UP_AUTO |
|
||||
AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR |
|
||||
AT91C_TC_BEEVT_SET | AT91C_TC_BCPB_CLEAR |
|
||||
AT91C_TC_EEVT_XC2 | AT91C_TC_ETRGEDG_RISING |
|
||||
AT91C_TC_BSWTRG_CLEAR | AT91C_TC_ASWTRG_CLEAR;
|
||||
|
||||
tc_cdiv_set_divider(128);
|
||||
|
||||
/* Reset to start timers */
|
||||
tcb->TCB_BCR = 1;
|
||||
}
|
||||
|
||||
void tc_cdiv_print(void)
|
||||
{
|
||||
DEBUGP("TCB_BMR=0x%08x ", tcb->TCB_BMR);
|
||||
DEBUGP("TC0_CV=0x%08x ", tcb->TCB_TC0.TC_CV);
|
||||
DEBUGP("TC0_CMR=0x%08x ", tcb->TCB_TC0.TC_CMR);
|
||||
DEBUGPCR("TC0_SR=0x%08x", tcb->TCB_TC0.TC_SR);
|
||||
|
||||
DEBUGPCR("TC0_RA=0x%04x, TC0_RB=0x%04x, TC0_RC=0x%04x",
|
||||
tcb->TCB_TC0.TC_RA, tcb->TCB_TC0.TC_RB, tcb->TCB_TC0.TC_RC);
|
||||
}
|
||||
|
||||
void tc_cdiv_fini(void)
|
||||
{
|
||||
tcb->TCB_TC0.TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC,
|
||||
((unsigned int) 1 << AT91C_ID_TC0));
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef _TC_CDIV_H
|
||||
#define _TC_CDIV_H
|
||||
|
||||
#include "openpicc.h"
|
||||
#include <sys/types.h>
|
||||
#include <lib_AT91SAM7.h>
|
||||
|
||||
static AT91PS_TCB tcb;
|
||||
|
||||
extern void tc_cdiv_phase_add(int16_t inc);
|
||||
extern void tc_cdiv_set_divider(u_int16_t div);
|
||||
|
||||
static inline void tc_cdiv_phase_inc(void)
|
||||
{
|
||||
tc_cdiv_phase_add(1);
|
||||
}
|
||||
|
||||
static inline void tc_cdiv_phase_dec(void)
|
||||
{
|
||||
tc_cdiv_phase_add(-1);
|
||||
}
|
||||
|
||||
extern void tc_cdiv_print(void);
|
||||
extern void tc_cdiv_init(void);
|
||||
extern void tc_cdiv_fini(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,110 @@
|
|||
/* Synchronize TC_CDIV divided sample clock with the SOF of the packet */
|
||||
|
||||
#include <lib_AT91SAM7.h>
|
||||
#include <AT91SAM7.h>
|
||||
#include "dbgu.h"
|
||||
#include "pio_irq.h"
|
||||
#include "openpicc.h"
|
||||
|
||||
#define USE_IRQ
|
||||
|
||||
static u_int8_t enabled;
|
||||
|
||||
#if 0
|
||||
static void pio_data_change(u_int32_t pio)
|
||||
{
|
||||
(void)pio;
|
||||
DEBUGP("PIO_FRAME_IRQ: ");
|
||||
/* we get one interrupt for each change. If now, after the
|
||||
* change the level is high, then it must have been a rising
|
||||
* edge */
|
||||
if (*AT91C_PIOA_PDSR & OPENPICC_PIO_FRAME) {
|
||||
*AT91C_TC0_CCR = AT91C_TC_SWTRG;
|
||||
DEBUGPCR("CDIV_SYNC_FLIP SWTRG CV=0x%08x",
|
||||
*AT91C_TC0_CV);
|
||||
} else
|
||||
DEBUGPCR("");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void __ramfunc cdsync_cb(void)
|
||||
{
|
||||
DEBUGP("PIO_IRQ: ");
|
||||
if (*AT91C_PIOA_ISR & OPENPICC_PIO_FRAME) {
|
||||
DEBUGP("PIO_FRAME_IRQ: ");
|
||||
/* we get one interrupt for each change. If now, after the
|
||||
* change the level is high, then it must have been a rising
|
||||
* edge */
|
||||
if (*AT91C_PIOA_PDSR & OPENPICC_PIO_FRAME) {
|
||||
*AT91C_TC0_CCR = AT91C_TC_SWTRG;
|
||||
DEBUGPCR("CDIV_SYNC_FLIP SWTRG CV=0x%08x",
|
||||
*AT91C_TC0_CV);
|
||||
} else
|
||||
DEBUGPCR("");
|
||||
} else
|
||||
DEBUGPCR("");
|
||||
}
|
||||
#endif
|
||||
|
||||
void tc_cdiv_sync_reset(void)
|
||||
{
|
||||
if (enabled) {
|
||||
u_int32_t tmp = *AT91C_PIOA_ISR;
|
||||
(void)tmp;
|
||||
volatile int i;
|
||||
DEBUGPCRF("CDIV_SYNC_FLOP");
|
||||
|
||||
/* reset the hardware flipflop */
|
||||
AT91F_PIO_ClearOutput(AT91C_BASE_PIOA,
|
||||
OPENPICC_PIO_SSC_DATA_CONTROL);
|
||||
for (i = 0; i < 0xff; i++) ;
|
||||
AT91F_PIO_SetOutput(AT91C_BASE_PIOA,
|
||||
OPENPICC_PIO_SSC_DATA_CONTROL);
|
||||
}
|
||||
}
|
||||
|
||||
void tc_cdiv_sync_disable(void)
|
||||
{
|
||||
enabled = 0;
|
||||
*AT91C_PIOA_IDR = OPENPICC_PIO_FRAME;
|
||||
}
|
||||
|
||||
void tc_cdiv_sync_enable(void)
|
||||
{
|
||||
enabled = 1;
|
||||
|
||||
DEBUGPCRF("CDIV_SYNC_ENABLE ");
|
||||
tc_cdiv_sync_reset();
|
||||
*AT91C_PIOA_IER = OPENPICC_PIO_FRAME;
|
||||
}
|
||||
|
||||
extern void (*fiq_handler)(void);
|
||||
void tc_cdiv_sync_init(void)
|
||||
{
|
||||
DEBUGPCRF("initializing");
|
||||
|
||||
enabled = 0;
|
||||
|
||||
AT91F_PIOA_CfgPMC();
|
||||
|
||||
#ifdef USE_IRQ
|
||||
/* Configure IRQ */
|
||||
AT91F_AIC_ConfigureIt(AT91C_ID_PIOA,
|
||||
AT91C_AIC_PRIOR_HIGHEST,
|
||||
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (THandler)&cdsync_cb);
|
||||
#else
|
||||
/* Configure FIQ */
|
||||
AT91F_AIC_ConfigureIt(AT91C_ID_FIQ,
|
||||
//0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &cdsync_cb);
|
||||
0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (THandler)&fiq_handler);
|
||||
/* enable fast forcing for PIOA interrupt */
|
||||
*AT91C_AIC_FFER = (1 << AT91C_ID_PIOA);
|
||||
|
||||
/* register pio irq handler */
|
||||
pio_irq_register(OPENPICC_PIO_FRAME, &pio_data_change);
|
||||
#endif
|
||||
AT91F_AIC_EnableIt(AT91C_ID_PIOA);
|
||||
|
||||
tc_cdiv_sync_disable();
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _TC_CDIV_SYNC_H
|
||||
#define _TC_CDIV_SYNC_H
|
||||
extern void tc_cdiv_sync_enable(void);
|
||||
extern void tc_cdiv_sync_init(void);
|
||||
extern void tc_cdiv_sync_reset(void);
|
||||
#endif
|
|
@ -0,0 +1,126 @@
|
|||
/* OpenPICC TC (Timer / Clock) support code
|
||||
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* PICC Simulator Side:
|
||||
* In order to support responding to synchronous frames (REQA/WUPA/ANTICOL),
|
||||
* we need a second Timer/Counter (TC2). This unit is reset by an external
|
||||
* event (rising edge of modulation pause PCD->PICC, falling edge of
|
||||
* demodulated data) connected to TIOB2, and counts up to a configurable
|
||||
* number of carrier clock cycles (RA). Once the RA value is reached, TIOA2
|
||||
* will see a rising edge. This rising edge will be interconnected to TF (Tx
|
||||
* Frame) of the SSC to start transmitting our synchronous response.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <lib_AT91SAM7.h>
|
||||
#include <AT91SAM7.h>
|
||||
#include "dbgu.h"
|
||||
|
||||
#include "openpicc.h"
|
||||
#include "tc_cdiv.h"
|
||||
#include "tc_fdt.h"
|
||||
|
||||
static AT91PS_TC tcfdt = AT91C_BASE_TC2;
|
||||
|
||||
void tc_fdt_set(u_int16_t count)
|
||||
{
|
||||
tcfdt->TC_RA = count;
|
||||
}
|
||||
|
||||
|
||||
/* 'count' number of carrier cycles after the last modulation pause,
|
||||
* we deem the frame to have ended */
|
||||
void tc_frame_end_set(u_int16_t count)
|
||||
{
|
||||
tcfdt->TC_RB = count;
|
||||
}
|
||||
|
||||
static void tc_fdt_irq(void)
|
||||
{
|
||||
u_int32_t sr = tcfdt->TC_SR;
|
||||
DEBUGP("tc_fdt_irq: TC2_SR=0x%08x TC2_CV=0x%08x ",
|
||||
sr, tcfdt->TC_CV);
|
||||
|
||||
if (sr & AT91C_TC_ETRGS) {
|
||||
DEBUGP("Ext_trigger ");
|
||||
}
|
||||
if (sr & AT91C_TC_CPAS) {
|
||||
DEBUGP("FDT_expired ");
|
||||
/* FIXME: if we are in anticol / sync mode,
|
||||
* we could do software triggering of SSC TX,
|
||||
* but IIRC the hardware does this by TF */
|
||||
}
|
||||
if (sr & AT91C_TC_CPBS) {
|
||||
DEBUGP("Frame_end ");
|
||||
/* FIXME: stop ssc (in continuous mode),
|
||||
* take care of preparing synchronous response if
|
||||
* we operate in anticol mode.*/
|
||||
}
|
||||
if (sr & AT91C_TC_CPCS) {
|
||||
DEBUGP("Compare_C ");
|
||||
}
|
||||
DEBUGPCR("");
|
||||
}
|
||||
|
||||
void tc_fdt_print(void)
|
||||
{
|
||||
DEBUGP("TC2_CV=0x%08x ", tcfdt->TC_CV);
|
||||
DEBUGP("TC2_CMR=0x%08x ", tcfdt->TC_CMR);
|
||||
DEBUGP("TC2_SR=0x%08x ", tcfdt->TC_SR);
|
||||
DEBUGP("TC2_RA=0x%04x, TC2_RB=0x%04x, TC2_RC=0x%04x",
|
||||
tcfdt->TC_RA, tcfdt->TC_RB, tcfdt->TC_RC);
|
||||
}
|
||||
|
||||
void tc_fdt_init(void)
|
||||
{
|
||||
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, AT91C_PA15_TF,
|
||||
AT91C_PA26_TIOA2 | AT91C_PA27_TIOB2);
|
||||
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC,
|
||||
((unsigned int) 1 << AT91C_ID_TC2));
|
||||
/* Enable Clock for TC2 */
|
||||
tcfdt->TC_CCR = AT91C_TC_CLKEN;
|
||||
|
||||
tcfdt->TC_RC = 0xffff;
|
||||
tc_frame_end_set(128*2);
|
||||
|
||||
/* Clock XC1, Wave Mode, No automatic reset on RC comp
|
||||
* TIOA2 in RA comp = set, TIOA2 on RC comp = clear,
|
||||
* TIOA2 on EEVT = clear
|
||||
* TIOB2 as input, EEVT = TIOB2, Reset/Trigger on EEVT */
|
||||
tcfdt->TC_CMR = AT91C_TC_CLKS_XC1 | AT91C_TC_WAVE |
|
||||
AT91C_TC_WAVESEL_UP |
|
||||
AT91C_TC_ACPA_SET | AT91C_TC_ACPC_CLEAR |
|
||||
AT91C_TC_AEEVT_CLEAR |
|
||||
AT91C_TC_BEEVT_NONE | AT91C_TC_BCPB_NONE |
|
||||
AT91C_TC_EEVT_TIOB | AT91C_TC_ETRGEDG_FALLING |
|
||||
AT91C_TC_ENETRG | AT91C_TC_CPCSTOP ;
|
||||
|
||||
/* Reset to start timers */
|
||||
tcb->TCB_BCR = 1;
|
||||
|
||||
AT91F_AIC_ConfigureIt(AT91C_ID_TC2,
|
||||
OPENPCD_IRQ_PRIO_TC_FDT,
|
||||
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &tc_fdt_irq);
|
||||
AT91F_AIC_EnableIt(AT91C_ID_TC2);
|
||||
|
||||
tcfdt->TC_IER = AT91C_TC_CPAS | AT91C_TC_CPBS | AT91C_TC_CPCS |
|
||||
AT91C_TC_ETRGS;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _TC_FDT_H
|
||||
#define _TC_FDT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
extern void tc_fdt_init(void);
|
||||
extern void tc_fdt_set(u_int16_t count);
|
||||
|
||||
#endif
|
|
@ -61,6 +61,19 @@
|
|||
#define OPENPICC_PIO_PLL_INHIBIT AT91C_PIO_PA24
|
||||
#define OPENPICC_PIO_PLL_LOCK AT91C_PIO_PA4
|
||||
|
||||
#define OPENPICC_MOD_PWM AT91C_PA23_PWM0
|
||||
#define OPENPICC_MOD_SSC AT91C_PA17_TD
|
||||
#define OPENPICC_SSC_DATA AT91C_PA18_RD
|
||||
#define OPENPICC_SSC_CLOCK AT91C_PA19_RK
|
||||
|
||||
#define OPENPICC_PIO_FRAME AT91C_PIO_PA20
|
||||
#define OPENPICC_PIO_SSC_DATA_CONTROL AT91C_PIO_PA21
|
||||
#define OPENPICC_PIO_AB_DETECT AT91C_PIO_PA22
|
||||
#define OPENPICC_PIO_PLL_INHIBIT AT91C_PIO_PA24
|
||||
|
||||
#define OPENPICC_IRQ_PRIO_SSC (AT91C_AIC_PRIOR_HIGHEST-1)
|
||||
#define OPENPCD_IRQ_PRIO_TC_FDT (AT91C_AIC_PRIOR_LOWEST+3)
|
||||
|
||||
/*-----------------*/
|
||||
/* task priorities */
|
||||
/*-----------------*/
|
||||
|
|
Loading…
Reference in New Issue