]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/m16c62p/adc/M16c62pAdcP.nc
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / tos / chips / m16c62p / adc / M16c62pAdcP.nc
diff --git a/tos/chips/m16c62p/adc/M16c62pAdcP.nc b/tos/chips/m16c62p/adc/M16c62pAdcP.nc
new file mode 100755 (executable)
index 0000000..ed340b9
--- /dev/null
@@ -0,0 +1,220 @@
+/* $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 "M16c62pAdc.h"
+
+/**
+ * Internal component of the M16c62p A/D HAL.
+ *
+ * @author Fan Zhang
+ */
+
+module M16c62pAdcP
+{
+  provides {
+    interface Init;
+    interface AsyncStdControl;
+    interface M16c62pAdcSingle;
+    interface M16c62pAdcMultiple;
+  }
+  uses {
+    interface HplM16c62pAdc;
+    //interface M16c62pCalibrate;
+  }
+}
+implementation
+{  
+  /* type change from uint8_t to M16c62pADCON0_t, this function is defined at m16c62phardware.h */
+  DEFINE_UNION_CAST(int2ADCON0, uint8_t, M16c62pADCON0_t); // 
+  DEFINE_UNION_CAST(int2ADCON1, uint8_t, M16c62pADCON1_t);
+  DEFINE_UNION_CAST(int2ADCON2, uint8_t, M16c62pADCON2_t);
+  command error_t Init.init() {
+    atomic
+    {
+           M16c62pADCON0_t adcon_0;
+           M16c62pADCON1_t adcon_1;
+           M16c62pADCON2_t adcon_2;
+
+           adcon_0 = int2ADCON0(0x00);
+           adcon_0 = int2ADCON0(0x20);
+           adcon_0 = int2ADCON0(0x01); 
+       
+           call HplM16c62pAdc.setADCON0(adcon_0);
+        call HplM16c62pAdc.setADCON1(adcon_1);
+        call HplM16c62pAdc.setADCON2(adcon_2);
+    }
+    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 HplM16c62pAdc.enableAdc();
+    return SUCCESS;
+  }
+
+  async command error_t AsyncStdControl.stop() {
+    atomic call HplM16c62pAdc.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(uint8_t admux, uint8_t channel, uint8_t refVoltage) {
+    return TRUE;
+  }
+  
+  /**
+   * Indicates a sample has been recorded by the ADC as the result
+   * of a ADC interrupt.
+   *
+   * @param data a 2 byte unsigned data value sampled by the ADC.
+   * @param precise if the conversion precise, FALSE if it wasn't. 
+   */  
+  async event void HplM16c62pAdc.dataReady(uint16_t data) {
+    
+    /* A single sample. Disable the ADC interrupt to avoid starting
+          a new sample at the next "sleep" instruction. */
+       call HplM16c62pAdc.disableInterruption();
+       call HplM16c62pAdc.disableAdc(); 
+       signal M16c62pAdcSingle.dataReady(data, TRUE);
+       
+  }
+
+  /* Start sampling based on request parameters 
+   * one-shot mode default
+   * refVoltage default
+   */
+  void getData(uint8_t channel,uint8_t precision, uint8_t prescaler) {
+    M16c62pADCON0_t adcon0_t;
+    M16c62pADCON1_t adcon1_t;
+    M16c62pADCON2_t adcon2_t;
+
+    if(channel < M16c62p_ADC_CHL_AN10)
+    {
+        adcon2_t.adgsel01 = 0;
+    }
+    else if((channel > M16c62p_ADC_CHL_AN7) && (channel <= M16c62p_ADC_CHL_AN17))
+    {
+        adcon2_t.adgsel01 = 2;
+        channel=channel-8;
+    }
+    adcon0_t.ch012 = channel;
+    
+    adcon0_t.md01 = 0;
+    adcon0_t.trg = 0;
+    adcon0_t.adst = M16c62p_ADC_START_CONVERSION_ON;
+    
+    adcon1_t.md2 = 0;
+    if(precision == M16c62p_ADC_PRECISION_10BIT)     // 10-bit mode
+    {
+        adcon1_t.bits = 1;
+    }
+    else
+    {
+        adcon1_t.bits = 0;
+    }
+    adcon1_t.vcut = M16c62p_ADC_ENABLE_ON;
+    adcon1_t.opa01 = 0;
+    
+    adcon2_t.smp = 1; // sample and hold
+    
+    if(prescaler == 0x00){adcon2_t.cks2=0;adcon1_t.cks1=0;adcon0_t.cks0=0;} // fAD/4 prescaler
+    else if(prescaler == 0x01){adcon2_t.cks2=0;adcon1_t.cks1=0;adcon0_t.cks0=1;} // fAD/2 prescaler
+    else if((prescaler == 0x02) || (prescaler == 0x03)){adcon2_t.cks2=0;adcon1_t.cks1=1;adcon0_t.cks0=0;} // fAD prescaler
+    else if(prescaler == 0x04){adcon2_t.cks2=1;adcon1_t.cks1=0;adcon0_t.cks0=0;} // fAD/12 prescaler
+    else if(prescaler == 0x05){adcon2_t.cks2=1;adcon1_t.cks1=0;adcon0_t.cks0=1;} // fAD/6 prescaler
+    else if((prescaler == 0x06) || (prescaler == 0x07)){adcon2_t.cks2=1;adcon1_t.cks1=1;adcon0_t.cks0=0;} // fAD/3 prescaler
+
+    call HplM16c62pAdc.enableInterruption();
+    
+    call HplM16c62pAdc.setADCON2(adcon2_t);
+    call HplM16c62pAdc.setADCON1(adcon1_t);
+    call HplM16c62pAdc.setADCON0(adcon0_t);
+  }
+
+  async command bool M16c62pAdcSingle.getData(uint8_t channel,
+                                            uint8_t precision, uint8_t prescaler) {
+    atomic
+    {
+               getData(channel, precision, prescaler);
+               return TRUE;
+    }
+  }
+
+  async command bool M16c62pAdcSingle.cancel() 
+  {
+    /* There is no M16c62pAdcMultiple.cancel, for reasons discussed in that
+       interface */
+    return call HplM16c62pAdc.cancel();
+  }
+
+  async command bool M16c62pAdcMultiple.getData(uint8_t channel, uint8_t precision, uint8_t prescaler)
+  {
+    atomic
+    {
+               getData(channel, precision, prescaler);
+
+               return TRUE;
+      }
+  }
+
+  default async event void M16c62pAdcSingle.dataReady(uint16_t data, bool precise) {
+  }
+
+  default async event bool M16c62pAdcMultiple.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.
+  }
+}