diff options
author | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-09-12 17:35:30 +0000 |
---|---|---|
committer | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-09-12 17:35:30 +0000 |
commit | d256545b2fd62d78910efcc6273c3b70abd3aa13 (patch) | |
tree | a05e17ec752cfbcc0b79fdbfba81fb949545a112 /firmware/src/picc/adc.c | |
parent | 04e0441914eeb25e042189679b55c9577fc96d2a (diff) |
move to new directory
git-svn-id: https://svn.openpcd.org:2342/trunk@191 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'firmware/src/picc/adc.c')
-rw-r--r-- | firmware/src/picc/adc.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/firmware/src/picc/adc.c b/firmware/src/picc/adc.c new file mode 100644 index 0000000..31b3469 --- /dev/null +++ b/firmware/src/picc/adc.c @@ -0,0 +1,145 @@ +/* AT91SAM7 ADC controller routines for OpenPCD / OpenPICC + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + */ + +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <AT91SAM7.h> +#include <lib_AT91SAM7.h> +#include <openpcd.h> + +#include <os/usb_handler.h> +#include "../openpcd.h" +#include <os/dbgu.h> + +#define OPENPICC_ADC_CH_FIELDSTR AT91C_ADC_CH4 +#define OPENPICC_ADC_CH_PLL_DEM AT91C_ADC_CH5 + +#define DEBUG_ADC + +#ifdef DEBUG_ADC +#define DEBUGADC DEBUGP +#else +#define DEBUGADC do { } while (0) +#endif + +static const AT91PS_ADC adc = AT91C_BASE_ADC; + +enum adc_states { + ADC_NONE, + ADC_READ_CONTINUOUS, + ADC_READ_CONTINUOUS_USB, + ADC_READ_SINGLE, +}; + +struct adc_state { + enum adc_states state; + struct req_ctx *rctx; +}; + +static struct adc_state adc_state; + +static void adc_irq(void) +{ + u_int32_t sr = adc->ADC_SR; + struct req_ctx *rctx = adc_state.rctx; + + DEBUGADC("adc_irq(SR=0x%08x, IMR=0x%08x, state=%u): ", + sr, adc->ADC_IMR, adc_state.state); + + switch (adc_state.state) { + case ADC_NONE: + //break; + case ADC_READ_CONTINUOUS_USB: + if (sr & AT91C_ADC_EOC4) + DEBUGADC("CDR4=0x%4x ", adc->ADC_CDR4); + if (sr & AT91C_ADC_EOC5) + DEBUGADC("CDR5=0x%4x ", adc->ADC_CDR5); + if (sr & AT91C_ADC_ENDRX) { + /* rctx full, get rid of it */ + DEBUGADC("sending rctx (val=%s) ", + hexdump(rctx->tx.data[4], 2)); + + req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING); + adc_state.state = ADC_NONE; + adc_state.rctx = NULL; + + //AT91F_PDC_SetRx(AT91C_BASE_PDC_ADC, NULL, 0); + + /* Disable EOC interrupts since we don't want to + * re-start conversion any further*/ + AT91F_ADC_DisableIt(AT91C_BASE_ADC, AT91C_ADC_ENDRX); + //AT91C_ADC_EOC4|AT91C_ADC_EOC5|AT91C_ADC_ENDRX); + AT91F_PDC_DisableRx(AT91C_BASE_PDC_ADC); + DEBUGADC("disabled IT/RX "); + } else { + if (sr & (AT91C_ADC_EOC4|AT91C_ADC_EOC5)) { + /* re-start conversion, since we need more values */ + AT91F_ADC_StartConversion(adc); + } + } + break; + } + + AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_ADC); + DEBUGADC("cleeared ADC IRQ in AIC\r\n"); +} + +#if 0 +u_int16_t adc_read_fieldstr(void) +{ + return adc->ADC_CDR4; +} + +u_int16_T adc_read_pll_dem(void) +{ + return adc +} +#endif + +static int adc_usb_in(struct req_ctx *rctx) +{ + struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0]; + struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0]; + + switch (poh->cmd) { + case OPENPCD_CMD_ADC_READ: + DEBUGADC("ADC_READ(chan=%u, len=%u) ", poh->reg, poh->val); + //channel = poh->reg; + if (adc_state.rctx) { + /* FIXME: do something */ + req_ctx_put(rctx); + } + + adc_state.state = ADC_READ_CONTINUOUS_USB; + adc_state.rctx = rctx; + memcpy(pih, poh, sizeof(*pih)); + rctx->tx.tot_len = sizeof(*pih) + poh->val * 2; + AT91F_PDC_SetRx(AT91C_BASE_PDC_ADC, rctx->rx.data, poh->val); + AT91F_PDC_EnableRx(AT91C_BASE_PDC_ADC); + AT91F_ADC_EnableChannel(AT91C_BASE_ADC, OPENPICC_ADC_CH_FIELDSTR); + AT91F_ADC_EnableIt(AT91C_BASE_ADC, AT91C_ADC_ENDRX | + OPENPICC_ADC_CH_FIELDSTR); + AT91F_ADC_StartConversion(adc); + break; + } +} + +int adc_init(void) +{ + AT91F_ADC_CfgPMC(); + AT91F_ADC_CfgTimings(AT91C_BASE_ADC, 48 /*MHz*/, 5 /*MHz*/, + 20/*uSec*/, 700/*nSec*/); +#if 0 + AT91F_ADC_EnableChannel(AT91C_BASE_ADC, OPENPICC_ADC_CH_FIELDSTR | + OPENPICC_ADC_CH_PLL_DEM); +#endif + AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_ADC, + AT91C_AIC_PRIOR_LOWEST, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &adc_irq); + AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_ADC); + + usb_hdlr_register(&adc_usb_in, OPENPCD_CMD_CLS_ADC); +} |