1 /* AT91SAM7 ADC controller routines for OpenPICC
2 * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <sys/types.h>
24 #include <lib_AT91SAM7.h>
27 #include <os/usb_handler.h>
28 #include "../openpcd.h"
31 #define OPENPICC_ADC_CH_FIELDSTR AT91C_ADC_CH4
32 #define OPENPICC_ADC_CH_PLL_DEM AT91C_ADC_CH5
37 #define DEBUGADC DEBUGP
39 #define DEBUGADC do { } while (0)
42 static const AT91PS_ADC adc
= AT91C_BASE_ADC
;
47 ADC_READ_CONTINUOUS_USB
,
52 enum adc_states state
;
56 static struct adc_state adc_state
;
58 static void adc_irq(void)
60 u_int32_t sr
= adc
->ADC_SR
;
61 struct req_ctx
*rctx
= adc_state
.rctx
;
63 DEBUGADC("adc_irq(SR=0x%08x, IMR=0x%08x, state=%u): ",
64 sr
, adc
->ADC_IMR
, adc_state
.state
);
66 switch (adc_state
.state
) {
69 case ADC_READ_CONTINUOUS_USB
:
70 if (sr
& AT91C_ADC_EOC4
)
71 DEBUGADC("CDR4=0x%4x ", adc
->ADC_CDR4
);
72 if (sr
& AT91C_ADC_EOC5
)
73 DEBUGADC("CDR5=0x%4x ", adc
->ADC_CDR5
);
74 if (sr
& AT91C_ADC_ENDRX
) {
75 /* rctx full, get rid of it */
76 DEBUGADC("sending rctx (val=%s) ",
77 hexdump(rctx
->data
[4], 2));
79 req_ctx_set_state(rctx
, RCTX_STATE_UDP_EP2_PENDING
);
80 adc_state
.state
= ADC_NONE
;
81 adc_state
.rctx
= NULL
;
83 //AT91F_PDC_SetRx(AT91C_BASE_PDC_ADC, NULL, 0);
85 /* Disable EOC interrupts since we don't want to
86 * re-start conversion any further*/
87 AT91F_ADC_DisableIt(AT91C_BASE_ADC
, AT91C_ADC_ENDRX
);
88 //AT91C_ADC_EOC4|AT91C_ADC_EOC5|AT91C_ADC_ENDRX);
89 AT91F_PDC_DisableRx(AT91C_BASE_PDC_ADC
);
90 DEBUGADC("disabled IT/RX ");
92 if (sr
& (AT91C_ADC_EOC4
|AT91C_ADC_EOC5
)) {
93 /* re-start conversion, since we need more values */
94 AT91F_ADC_StartConversion(adc
);
100 AT91F_AIC_ClearIt(AT91C_BASE_AIC
, AT91C_ID_ADC
);
101 DEBUGADC("cleeared ADC IRQ in AIC\r\n");
105 u_int16_t
adc_read_fieldstr(void)
107 return adc
->ADC_CDR4
;
110 u_int16_T
adc_read_pll_dem(void)
116 static int adc_usb_in(struct req_ctx
*rctx
)
118 struct openpcd_hdr
*poh
= (struct openpcd_hdr
*) &rctx
->data
[0];
121 case OPENPCD_CMD_ADC_READ
:
122 DEBUGADC("ADC_READ(chan=%u, len=%u) ", poh
->reg
, poh
->val
);
123 //channel = poh->reg;
124 if (adc_state
.rctx
) {
125 /* FIXME: do something */
129 adc_state
.state
= ADC_READ_CONTINUOUS_USB
;
130 adc_state
.rctx
= rctx
;
131 rctx
->tot_len
= sizeof(*poh
) + poh
->val
* 2;
132 AT91F_PDC_SetRx(AT91C_BASE_PDC_ADC
, rctx
->data
, poh
->val
);
133 AT91F_PDC_EnableRx(AT91C_BASE_PDC_ADC
);
134 AT91F_ADC_EnableChannel(AT91C_BASE_ADC
, OPENPICC_ADC_CH_FIELDSTR
);
135 AT91F_ADC_EnableIt(AT91C_BASE_ADC
, AT91C_ADC_ENDRX
|
136 OPENPICC_ADC_CH_FIELDSTR
);
137 AT91F_ADC_StartConversion(adc
);
145 AT91F_ADC_CfgTimings(AT91C_BASE_ADC
, 48 /*MHz*/, 5 /*MHz*/,
146 20/*uSec*/, 700/*nSec*/);
148 AT91F_ADC_EnableChannel(AT91C_BASE_ADC
, OPENPICC_ADC_CH_FIELDSTR
|
149 OPENPICC_ADC_CH_PLL_DEM
);
151 AT91F_AIC_ConfigureIt(AT91C_BASE_AIC
, AT91C_ID_ADC
,
152 AT91C_AIC_PRIOR_LOWEST
,
153 AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
, &adc_irq
);
154 AT91F_AIC_EnableIt(AT91C_BASE_AIC
, AT91C_ID_ADC
);
156 usb_hdlr_register(&adc_usb_in
, OPENPCD_CMD_CLS_ADC
);