-/* $Id$\r
- * "Copyright (c) 2000-2003 The Regents of the University of California. \r
- * All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\r
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT\r
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF\r
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- * \r
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\r
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO\r
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."\r
- *\r
- * Copyright (c) 2002-2005 Intel Corporation\r
- * All rights reserved.\r
- *\r
- * This file is distributed under the terms in the attached INTEL-LICENSE \r
- * file. If you do not find these files, copies can be found by writing to\r
- * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, \r
- * 94704. Attention: Intel License Inquiry.\r
- *\r
- * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose, without fee, and without written agreement is\r
- * hereby granted, provided that the above copyright notice, the following\r
- * two paragraphs and the author appear in all copies of this software.\r
- * \r
- * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO \r
- * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL \r
- * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN\r
- * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH \r
- * DAMAGE. \r
- *\r
- * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,\r
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY \r
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS \r
- * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY \r
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR \r
- * MODIFICATIONS.\r
- */\r
-\r
-#include "Atm128Adc.h"\r
-\r
-/**\r
- * Internal component of the Atmega128 A/D HAL.\r
- *\r
- * @author Jason Hill\r
- * @author David Gay\r
- * @author Philip Levis\r
- * @author Phil Buonadonna\r
- * @author Hu Siquan <husq@xbow.com>\r
- */\r
-\r
-module Atm128AdcP \r
-{\r
- provides {\r
- interface Init;\r
- interface AsyncStdControl;\r
- interface Atm128AdcSingle;\r
- interface Atm128AdcMultiple;\r
- }\r
- uses {\r
- interface HplAtm128Adc;\r
- interface Atm128Calibrate;\r
- }\r
-}\r
-implementation\r
-{ \r
- /* State for the current and next (multiple-sampling only) conversion */\r
- struct {\r
- bool multiple : 1; /* single and multiple-sampling mode */\r
- bool precise : 1; /* is this result going to be precise? */\r
- uint8_t channel : 5; /* what channel did this sample come from? */\r
- } f, nextF;\r
- \r
- command error_t Init.init() {\r
- atomic\r
- {\r
- Atm128Adcsra_t adcsr;\r
-\r
- adcsr.aden = ATM128_ADC_ENABLE_OFF;\r
- adcsr.adsc = ATM128_ADC_START_CONVERSION_OFF; \r
- adcsr.adfr = ATM128_ADC_FREE_RUNNING_OFF; \r
- adcsr.adif = ATM128_ADC_INT_FLAG_OFF; \r
- adcsr.adie = ATM128_ADC_INT_ENABLE_OFF; \r
- adcsr.adps = ATM128_ADC_PRESCALE_2;\r
- call HplAtm128Adc.setAdcsra(adcsr);\r
- }\r
- return SUCCESS;\r
- }\r
-\r
- /* We enable the A/D when start is called, and disable it when stop is\r
- called. This drops A/D conversion latency by a factor of two (but\r
- increases idle mode power consumption a little). \r
- */\r
- async command error_t AsyncStdControl.start() {\r
- atomic call HplAtm128Adc.enableAdc();\r
- return SUCCESS;\r
- }\r
-\r
- async command error_t AsyncStdControl.stop() {\r
- atomic call HplAtm128Adc.disableAdc();\r
-\r
- return SUCCESS;\r
- }\r
-\r
- /* Return TRUE if switching to 'channel' with reference voltage 'refVoltage'\r
- will give a precise result (the first sample after changing reference\r
- voltage or switching to/between a differential channel is imprecise)\r
- */\r
- inline bool isPrecise(Atm128Admux_t admux, uint8_t channel, uint8_t refVoltage) {\r
- return refVoltage == admux.refs &&\r
- (channel <= ATM128_ADC_SNGL_ADC7 || channel >= ATM128_ADC_SNGL_1_23 || channel == admux.mux);\r
- }\r
-\r
- async event void HplAtm128Adc.dataReady(uint16_t data) {\r
- bool precise, multiple;\r
- uint8_t channel;\r
-\r
- atomic \r
- {\r
- channel = f.channel;\r
- precise = f.precise;\r
- multiple = f.multiple;\r
- }\r
-\r
- if (!multiple)\r
- {\r
- /* A single sample. Disable the ADC interrupt to avoid starting\r
- a new sample at the next "sleep" instruction. */\r
- call HplAtm128Adc.disableInterruption();\r
- signal Atm128AdcSingle.dataReady(data, precise);\r
- }\r
- else\r
- {\r
- /* Multiple sampling. The user can:\r
- - tell us to stop sampling\r
- - or, to continue sampling on a new channel, possibly with a\r
- new reference voltage; however this change applies not to\r
- the next sample (the hardware has already started working on\r
- that), but on the one after.\r
- */\r
- bool cont;\r
- uint8_t nextChannel, nextVoltage;\r
- Atm128Admux_t admux;\r
-\r
- atomic \r
- {\r
- admux = call HplAtm128Adc.getAdmux();\r
- nextVoltage = admux.refs;\r
- nextChannel = admux.mux;\r
- }\r
-\r
- cont = signal Atm128AdcMultiple.dataReady(data, precise, channel,\r
- &nextChannel, &nextVoltage);\r
- atomic\r
- if (cont)\r
- {\r
- /* Switch channels and update our internal channel+precision\r
- tracking state (f and nextF). Note that this tracking will\r
- be incorrect if we take too long to get to this point. */\r
- admux.refs = nextVoltage;\r
- admux.mux = nextChannel;\r
- call HplAtm128Adc.setAdmux(admux);\r
-\r
- f = nextF;\r
- nextF.channel = nextChannel;\r
- nextF.precise = isPrecise(admux, nextChannel, nextVoltage);\r
- }\r
- else\r
- call HplAtm128Adc.cancel();\r
- }\r
- }\r
-\r
- /* Start sampling based on request parameters */\r
- void getData(uint8_t channel, uint8_t refVoltage, bool leftJustify, uint8_t prescaler) {\r
- Atm128Admux_t admux;\r
- Atm128Adcsra_t adcsr;\r
-\r
- admux = call HplAtm128Adc.getAdmux();\r
- f.precise = isPrecise(admux, channel, refVoltage);\r
- f.channel = channel;\r
-\r
- admux.refs = refVoltage;\r
- admux.adlar = leftJustify;\r
- admux.mux = channel;\r
- call HplAtm128Adc.setAdmux(admux);\r
-\r
- adcsr.aden = ATM128_ADC_ENABLE_ON;\r
- adcsr.adsc = ATM128_ADC_START_CONVERSION_ON;\r
- adcsr.adfr = f.multiple;\r
- adcsr.adif = ATM128_ADC_INT_FLAG_ON; // clear any stale flag\r
- adcsr.adie = ATM128_ADC_INT_ENABLE_ON;\r
- if (prescaler == ATM128_ADC_PRESCALE)\r
- prescaler = call Atm128Calibrate.adcPrescaler();\r
- adcsr.adps = prescaler;\r
- call HplAtm128Adc.setAdcsra(adcsr);\r
- }\r
-\r
- async command bool Atm128AdcSingle.getData(uint8_t channel, uint8_t refVoltage,\r
- bool leftJustify, uint8_t prescaler) {\r
- atomic\r
- {\r
- f.multiple = FALSE;\r
- getData(channel, refVoltage, leftJustify, prescaler);\r
-\r
- return f.precise;\r
- }\r
- }\r
-\r
- async command bool Atm128AdcSingle.cancel() {\r
- /* There is no Atm128AdcMultiple.cancel, for reasons discussed in that\r
- interface */\r
- return call HplAtm128Adc.cancel();\r
- }\r
-\r
- async command bool Atm128AdcMultiple.getData(uint8_t channel, uint8_t refVoltage,\r
- bool leftJustify, uint8_t prescaler) {\r
- atomic\r
- {\r
- f.multiple = TRUE;\r
- getData(channel, refVoltage, leftJustify, prescaler);\r
- nextF = f;\r
- /* We assume the 2nd sample is precise */\r
- nextF.precise = TRUE;\r
-\r
- return f.precise;\r
- }\r
- }\r
-\r
- default async event void Atm128AdcSingle.dataReady(uint16_t data, bool precise) {\r
- }\r
-\r
- default async event bool Atm128AdcMultiple.dataReady(uint16_t data, bool precise, uint8_t channel,\r
- uint8_t *newChannel, uint8_t *newRefVoltage) {\r
- return FALSE; // stop conversion if we somehow end up here.\r
- }\r
-}\r
+/* $Id$
+ * "Copyright (c) 2000-2003 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2005 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ *
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+#include "Atm128Adc.h"
+
+/**
+ * Internal component of the Atmega128 A/D HAL.
+ *
+ * @author Jason Hill
+ * @author David Gay
+ * @author Philip Levis
+ * @author Phil Buonadonna
+ * @author Hu Siquan <husq@xbow.com>
+ */
+
+module Atm128AdcP
+{
+ provides {
+ interface Init;
+ interface AsyncStdControl;
+ interface Atm128AdcSingle;
+ interface Atm128AdcMultiple;
+ }
+ uses {
+ interface HplAtm128Adc;
+ interface Atm128Calibrate;
+ }
+}
+implementation
+{
+ /* State for the current and next (multiple-sampling only) conversion */
+ struct {
+ bool multiple : 1; /* single and multiple-sampling mode */
+ bool precise : 1; /* is this result going to be precise? */
+ uint8_t channel : 5; /* what channel did this sample come from? */
+ } f, nextF;
+
+ command error_t Init.init() {
+ atomic
+ {
+ Atm128Adcsra_t adcsr;
+
+ adcsr.aden = ATM128_ADC_ENABLE_OFF;
+ adcsr.adsc = ATM128_ADC_START_CONVERSION_OFF;
+ adcsr.adfr = ATM128_ADC_FREE_RUNNING_OFF;
+ adcsr.adif = ATM128_ADC_INT_FLAG_OFF;
+ adcsr.adie = ATM128_ADC_INT_ENABLE_OFF;
+ adcsr.adps = ATM128_ADC_PRESCALE_2;
+ call HplAtm128Adc.setAdcsra(adcsr);
+ }
+ return SUCCESS;
+ }
+
+ /* We enable the A/D when start is called, and disable it when stop is
+ called. This drops A/D conversion latency by a factor of two (but
+ increases idle mode power consumption a little).
+ */
+ async command error_t AsyncStdControl.start() {
+ atomic call HplAtm128Adc.enableAdc();
+ return SUCCESS;
+ }
+
+ async command error_t AsyncStdControl.stop() {
+ atomic call HplAtm128Adc.disableAdc();
+
+ return SUCCESS;
+ }
+
+ /* Return TRUE if switching to 'channel' with reference voltage 'refVoltage'
+ will give a precise result (the first sample after changing reference
+ voltage or switching to/between a differential channel is imprecise)
+ */
+ inline bool isPrecise(Atm128Admux_t admux, uint8_t channel, uint8_t refVoltage) {
+ return refVoltage == admux.refs &&
+ (channel <= ATM128_ADC_SNGL_ADC7 || channel >= ATM128_ADC_SNGL_1_23 || channel == admux.mux);
+ }
+
+ async event void HplAtm128Adc.dataReady(uint16_t data) {
+ bool precise, multiple;
+ uint8_t channel;
+
+ atomic
+ {
+ channel = f.channel;
+ precise = f.precise;
+ multiple = f.multiple;
+ }
+
+ if (!multiple)
+ {
+ /* A single sample. Disable the ADC interrupt to avoid starting
+ a new sample at the next "sleep" instruction. */
+ call HplAtm128Adc.disableInterruption();
+ signal Atm128AdcSingle.dataReady(data, precise);
+ }
+ else
+ {
+ /* Multiple sampling. The user can:
+ - tell us to stop sampling
+ - or, to continue sampling on a new channel, possibly with a
+ new reference voltage; however this change applies not to
+ the next sample (the hardware has already started working on
+ that), but on the one after.
+ */
+ bool cont;
+ uint8_t nextChannel, nextVoltage;
+ Atm128Admux_t admux;
+
+ atomic
+ {
+ admux = call HplAtm128Adc.getAdmux();
+ nextVoltage = admux.refs;
+ nextChannel = admux.mux;
+ }
+
+ cont = signal Atm128AdcMultiple.dataReady(data, precise, channel,
+ &nextChannel, &nextVoltage);
+ atomic
+ if (cont)
+ {
+ /* Switch channels and update our internal channel+precision
+ tracking state (f and nextF). Note that this tracking will
+ be incorrect if we take too long to get to this point. */
+ admux.refs = nextVoltage;
+ admux.mux = nextChannel;
+ call HplAtm128Adc.setAdmux(admux);
+
+ f = nextF;
+ nextF.channel = nextChannel;
+ nextF.precise = isPrecise(admux, nextChannel, nextVoltage);
+ }
+ else
+ call HplAtm128Adc.cancel();
+ }
+ }
+
+ /* Start sampling based on request parameters */
+ void getData(uint8_t channel, uint8_t refVoltage, bool leftJustify, uint8_t prescaler) {
+ Atm128Admux_t admux;
+ Atm128Adcsra_t adcsr;
+
+ admux = call HplAtm128Adc.getAdmux();
+ f.precise = isPrecise(admux, channel, refVoltage);
+ f.channel = channel;
+
+ admux.refs = refVoltage;
+ admux.adlar = leftJustify;
+ admux.mux = channel;
+ call HplAtm128Adc.setAdmux(admux);
+
+ adcsr.aden = ATM128_ADC_ENABLE_ON;
+ adcsr.adsc = ATM128_ADC_START_CONVERSION_ON;
+ adcsr.adfr = f.multiple;
+ adcsr.adif = ATM128_ADC_INT_FLAG_ON; // clear any stale flag
+ adcsr.adie = ATM128_ADC_INT_ENABLE_ON;
+ if (prescaler == ATM128_ADC_PRESCALE)
+ prescaler = call Atm128Calibrate.adcPrescaler();
+ adcsr.adps = prescaler;
+ call HplAtm128Adc.setAdcsra(adcsr);
+ }
+
+ async command bool Atm128AdcSingle.getData(uint8_t channel, uint8_t refVoltage,
+ bool leftJustify, uint8_t prescaler) {
+ atomic
+ {
+ f.multiple = FALSE;
+ getData(channel, refVoltage, leftJustify, prescaler);
+
+ return f.precise;
+ }
+ }
+
+ async command bool Atm128AdcSingle.cancel() {
+ /* There is no Atm128AdcMultiple.cancel, for reasons discussed in that
+ interface */
+ return call HplAtm128Adc.cancel();
+ }
+
+ async command bool Atm128AdcMultiple.getData(uint8_t channel, uint8_t refVoltage,
+ bool leftJustify, uint8_t prescaler) {
+ atomic
+ {
+ f.multiple = TRUE;
+ getData(channel, refVoltage, leftJustify, prescaler);
+ nextF = f;
+ /* We assume the 2nd sample is precise */
+ nextF.precise = TRUE;
+
+ return f.precise;
+ }
+ }
+
+ default async event void Atm128AdcSingle.dataReady(uint16_t data, bool precise) {
+ }
+
+ default async event bool Atm128AdcMultiple.dataReady(uint16_t data, bool precise, uint8_t channel,
+ uint8_t *newChannel, uint8_t *newRefVoltage) {
+ return FALSE; // stop conversion if we somehow end up here.
+ }
+}