[Tinyos-commits] CVS: tinyos-1.x/tos/platform/msp430/adc ADCC.nc, NONE, 1.1 ADCHIL.h, NONE, 1.1 ADCM.nc, NONE, 1.1 ADCMultiple.nc, NONE, 1.1 ADCSingle.nc, NONE, 1.1 ADC_README, NONE, 1.1 DemoSensorC.nc, NONE, 1.1 HPLADC12.nc, NONE, 1.1 HPLADC12M.nc, NONE, 1.1 InternalTemp.h, NONE, 1.1 InternalTempC.nc, NONE, 1.1 InternalTempM.nc, NONE, 1.1 InternalVoltage.h, NONE, 1.1 InternalVoltageC.nc, NONE, 1.1 InternalVoltageM.nc, NONE, 1.1 MSP430ADC12.h, NONE, 1.1 MSP430ADC12C.nc, NONE, 1.1 MSP430ADC12M.nc, NONE, 1.1 MSP430ADC12Multiple.nc, NONE, 1.1 MSP430ADC12Single.nc, NONE, 1.1 Voltage.h, NONE, 1.1 VoltageM.nc, NONE, 1.1

Joe Polastre jpolastre at users.sourceforge.net
Wed Sep 28 03:41:14 PDT 2005


Update of /cvsroot/tinyos/tinyos-1.x/tos/platform/msp430/adc
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30738/msp430/adc

Added Files:
	ADCC.nc ADCHIL.h ADCM.nc ADCMultiple.nc ADCSingle.nc 
	ADC_README DemoSensorC.nc HPLADC12.nc HPLADC12M.nc 
	InternalTemp.h InternalTempC.nc InternalTempM.nc 
	InternalVoltage.h InternalVoltageC.nc InternalVoltageM.nc 
	MSP430ADC12.h MSP430ADC12C.nc MSP430ADC12M.nc 
	MSP430ADC12Multiple.nc MSP430ADC12Single.nc Voltage.h 
	VoltageM.nc 
Log Message:
complete reorganization of ADC to support DMA and DAC modules   

Changes to the ADC include:

The ADC no longer directly accesses TimerA.  Instead it uses
the TimerExclusive interface in MSP430TimerAExclusive to gain
exclusive lock on TimerA.  It releases TimerA when it is done.
This is necessary for other components that would like to use
TimerA to do so, such as the DAC.

Commands for the DMA have been added to the MSP430Single and
MSP430Multiple ADC interfaces.  These include startSampling,
stopSampling, pauseSampling, and resumeSampling.  They should only
be used in conjunction with the DMA and never as standalone functions.

A TinyOS driver for the DAC is being committed that uses the
newly created TimerExclusive interface to get access to TimerA.
It also supports DMA use.

The DMA has been rearchitected to follow the namespace of the other
components with minor bug fixes.  

The ADC, DAC, and DMA have been moved to their own subdirectories to
make life easier when viewing the msp430 platform.  Platforms that
rely on these components must now include the following lines in the
@opts section of their .platform file:
-I%T/platform/msp430/adc
-I%T/platform/msp430/dac
-I%T/platform/msp430/dma

A sample application is being checked in to 
apps/TestMSP430DMA/
that includes TestADC12DMAC for reading multiple samples from the ADC
and also TestDAC12DMAC for sending multiple readings via the DAC

Although I spearheaded much of the DAC efforts, credit goes to
Ben Greenstein for fixes to the ADC and much of the DMA code that I based
this new implementation on.



--- NEW FILE: ADCC.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Description ----------------------------------------------------------
 * Obsolete, use ADCHILC/M instead.
 * Read ADC_README about how to use the provided interfaces, e.g.
 * ADCControl.bind has a slightly different meaning than before.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Vlado Handziski <handzisk at tkn.tu-berlin.de>
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * @author: Kevin Klues <klues at tkn.tu-berlin.de>
 * ========================================================================
 */
 
configuration ADCC
{
  provides {
    interface ADC[uint8_t port];
    interface ADCControl;
    interface StdControl;
  }
}
implementation
{
  components ADCM
#ifdef __msp430_have_adc12
    , MSP430ADC12C
#else
// need support for ADC10 msp430 devices, etc
#error ADCC: Compiling for an msp430 device that does not have ADC12
#endif
    ;
  
  ADC = ADCM.ADC;
  ADCControl = ADCM;
  StdControl = ADCM;
#ifdef __msp430_have_adc12
  StdControl = MSP430ADC12C;
  ADCM.MSP430ADC12Single -> MSP430ADC12C.MSP430ADC12Single[unique("MSP430ADC12")];
#endif
}

--- NEW FILE: ADCHIL.h ---
//$Id: ADCHIL.h,v 1.1 2005/09/28 10:41:11 jpolastre Exp $

#ifndef ADCHIL_H
#define ADCHIL_H

typedef enum
{
   ADC_SUCCESS = 0,
   ADC_FAIL = 1,
   // further errorcodes can be added here
} adcresult_t;

#endif

--- NEW FILE: ADCM.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Description ----------------------------------------------------------
 * Obsolete, use HIL interface (wrappers) instead.
 * nesC will issue a warning about bind() being called asynchronously,
 * which can be ignored.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Vlado Handziski <handzisk at tkn.tu-berlin.de>
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * @author: Kevin Klues <klues at tkn.tu-berlin.de>
 * ========================================================================
 */
includes MSP430ADC12;

module ADCM
{
  provides {
    interface ADC[uint8_t port];
    interface ADCControl;
    interface StdControl;
  }
  uses {
    interface MSP430ADC12Single;
  }
}

implementation
{

  enum
  {
    TOSH_ADC_PORTMAPSIZE = uniqueCount("ADCPort")
  };

  // member of TOSH_adc_portmap:
  // bit 0-3: inputChannel
  // bit 4-6: refVolt
  // bit 7: refVoltLevel
  norace uint8_t TOSH_adc_portmap[TOSH_ADC_PORTMAPSIZE];
  norace uint8_t samplingRate;
  norace bool continuousData;
  norace uint8_t owner;
  bool initialized;
  volatile bool busy;
  
  command result_t StdControl.init()
  { 
    call ADCControl.init();
    return SUCCESS;
  }
  
  command result_t StdControl.start()
  {
    return SUCCESS; 
  }
  
  command result_t StdControl.stop()
  {
    continuousData = FALSE;
    atomic busy = FALSE;
    return SUCCESS;
  }
  
  command result_t ADCControl.init() 
  {
    if (!initialized){
      samplingRate = 0xFF;  // max. sampling time (1024 ticks ADC12CLK)
      initialized = 1;
    } 
    return SUCCESS;
  }

  command result_t ADCControl.setSamplingRate(uint8_t rate) 
  {
    // Assumption: SMCLK runs at 1 MHz
    switch (rate){
      case (TOS_ADCSample3750ns): samplingRate = 0x00; break;
      case (TOS_ADCSample7500ns): samplingRate = 0x01; break;
      case (TOS_ADCSample15us):   samplingRate = 0x02; break;
      case (TOS_ADCSample30us):   samplingRate = 0x03; break;
      case (TOS_ADCSample60us):   samplingRate = 0x04; break;
      case (TOS_ADCSample120us):  samplingRate = 0x06; break;
      case (TOS_ADCSample240us):  samplingRate = 0x08; break;
      case (TOS_ADCSample480us):  samplingRate = 0x0A; break;
    }
    return SUCCESS;
  }

  command result_t ADCControl.bindPort(uint8_t port, uint8_t adcPort) 
  {  
    if (port < TOSH_ADC_PORTMAPSIZE){
      TOSH_adc_portmap[port] = adcPort;
      return SUCCESS;
    } else
      return FAIL;
  }

  result_t triggerConversion(uint8_t port){
    MSP430ADC12Settings_t settings;  
    settings.refVolt2_5 = (TOSH_adc_portmap[port] & 0x80) >> 7;
    settings.clockSourceSHT = SHT_SOURCE_SMCLK;
    settings.clockSourceSAMPCON = SAMPCON_SOURCE_SMCLK;
    settings.referenceVoltage = (TOSH_adc_portmap[port] & 0x70) >> 4;
    settings.clockDivSAMPCON = SAMPCON_CLOCK_DIV_1;
    settings.clockDivSHT = SHT_CLOCK_DIV_1;
    settings.inputChannel = TOSH_adc_portmap[port] & 0x0F;
    settings.sampleHoldTime = samplingRate;

    // this will create a nesC warning (async call), which
    // can be ignored. 
    if (call MSP430ADC12Single.bind(settings) == SUCCESS){
      if ((!continuousData && call MSP430ADC12Single.getData() != MSP430ADC12_FAIL)
          || (continuousData && call MSP430ADC12Single.getDataRepeat(0) != MSP430ADC12_FAIL)) {
        owner = port;
        return SUCCESS;
      }
    }
    atomic busy = FALSE;
    return FAIL;
  }
    
  async command result_t ADC.getData[uint8_t port]()
  {  
    bool oldBusy;
    if (port >= TOSH_ADC_PORTMAPSIZE)
      return FAIL;
    atomic {
      oldBusy = busy;
      busy = TRUE;
    } 
    if (!oldBusy){
      continuousData = FALSE;
      return triggerConversion(port);
    }
    return FAIL;  
  }


  async command result_t ADC.getContinuousData[uint8_t port]()
  {  
    bool oldBusy;
    if (port >= TOSH_ADC_PORTMAPSIZE)
      return FAIL;
    atomic {
      oldBusy = busy;
      busy = TRUE;
    }      
    if (!oldBusy){
      continuousData = TRUE;
      return triggerConversion(port);
    } else
      return FAIL;
  }

  default async event result_t ADC.dataReady[uint8_t num](uint16_t d){return SUCCESS;}

  async event result_t MSP430ADC12Single.dataReady(uint16_t d)
  {
    if (!continuousData){
      atomic busy = FALSE;
      return signal ADC.dataReady[owner](d);
    } else if (signal ADC.dataReady[owner](d) == FAIL){
        atomic busy = FALSE;
        return FAIL;
      }
    return SUCCESS;
  }
}


--- NEW FILE: ADCMultiple.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
includes ADCHIL;
interface ADCMultiple
{
  /**
    * Initiates a series of, i.e. multiple successive conversions. 
    * The length of a series must match and is only bounded by the 
    * size of the buffer. An event <code>dataReady</code> is signalled
    * when the buffer is filled with conversion results. 
    * Successive conversions are performed as quickly as possible.
    *
    * @param buf Buffer to store the conversion results. Ignored
    * if <code>reserve</code> was called successfully before,
    * because then those settings are applicable.
    *
    * @param length The size of the buffer and number of conversions.
    * Ignored if <code>reserve</code> was called successfully before,
    * because then those settings are applicable.
    *
    * @return ADC_SUCCESS if the ADC is free and available 
    * to accept the request, error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t getData(uint16_t *buf, uint16_t length);

  /**
    * Initiates a series of, i.e. multiple successive conversions,
    * in repeat mode, i.e. continuously.
    * After each series of conversions is performed an event 
    * <code>dataReady</code> is signalled with the conversion results.
    * This continues until the eventhandler returns <code>FAIL</code>.
    *
    * @param buf Buffer to store the conversion results. Ignored
    * if <code>reserveContinuous</code> was called successfully before,
    * because then those settings are applicable.
    *
    * @param length The size of the buffer and number of conversions.
    * Ignored if <code>reserveContinuous</code> was called successfully before,
    * because then those settings are applicable.
    *
    * @return ADC_SUCCESS if the ADC is free and available 
    * to accept the request, error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t getDataContinuous(uint16_t *buf, uint16_t length);
    
  /**
    * Reserves the ADC for a series of conversions.  If this call  
    * succeeds the next call to <code>getData</code> will also succeed 
    * and the first corresponding conversion will then be started with a
    * minimum latency.
    *
    * @return ADC_SUCCESS if reservation was successful,
    * error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t reserve(uint16_t *buf, uint16_t length);
  
  /**
    * Reserves the ADC for a series of conversions in repeat mode. If this call  
    * succeeds the next call to <code>getDataRepeat</code> will also succeed 
    * and the first corresponding conversion will then be started with a
    * minimum latency.
    *
    * @return ADC_SUCCESS if reservation was successful,
    * error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t reserveContinuous(uint16_t *buf, uint16_t length);

  /**
    * Cancels a reservation made by <code>reserve</code> or
    * <code>reserveRepeat</code>.
    *
    * @return ADC_SUCCESS if reservation was cancelled successfully,
    * error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t unreserve();
  
  /**
    * Conversion results from call to <code>getData</code> or 
    * <code>getDataContinuous</code> are ready. In the first case
    * the returned value is ignored, in the second it defines
    * whether any further conversions will be made or not.
    *
    * @param result ADC_SUCCESS if the conversions were performed
    * successfully and the results are valid, error code 
    * otherwise (see ADCHIL.h).
    * @param buf The address of the conversion results, identical 
    * to buf passed to <code>getData</code> or 
    * <code>reserveContinuous</code> .
    * @param length Size of the buffer, identical to length passed to
    * <code>getData</code> or <code>reserveContinuous</code> .
    *
    * @return 0 (nullpointer) stops further conversions in continuous mode,
    * otherwise the pointer points to a buffer of the same length 
    * where the next conversion results are to be stored in continuous mode
    * (ignored if not in continuous mode).
    */
  async event uint16_t* dataReady(adcresult_t result, uint16_t *buf, uint16_t length); 
}


--- NEW FILE: ADCSingle.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
includes ADCHIL;
interface ADCSingle
{
  /**
    * Initiates one single conversion. The conversion result
    * is signalled in the event <code>dataReady</code>.
    *
    * @return ADC_SUCCESS if the ADC is free and available 
    * to accept the request, error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t getData();

  /**
    * Initiates conversions in repeat mode, ie. continuously.
    * After each conversion an event <code>dataReady</code>
    * is signalled with the conversion result until 
    * the eventhandler returns <code>FAIL</code>.
    *
    * @return ADC_SUCCESS if the ADC is free and available 
    * to accept the request, error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t getDataContinuous();
    
  /**
    * Reserves the ADC for one single conversion.  If this call  
    * succeeds the next call to <code>getData</code> will also succeed 
    * and the corresponding conversion will then be started with a
    * minimum latency.
    *
    * @return ADC_SUCCESS if reservation was successful,
    * to accept the request, error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t reserve();
  
  /**
    * Reserves the ADC for continuous conversions. If this call  
    * succeeds the next call to <code>getDataContinuous/code> will also succeed 
    * and the corresponding conversion will then be started with a
    * minimum latency.
    *
    * @return ADC_SUCCESS if reservation was successful,
    * error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t reserveContinuous();

  /**
    * Cancels a reservation made by <code>reserve</code> or
    * <code>reserveRepeat</code>.
    *
    * @return ADC_SUCCESS if reservation was cancelled successfully,
    * error code otherwise (see ADCHIL.h).
    */
  async command adcresult_t unreserve();
  
  /**
    * Conversion result from call to <code>getData</code> or 
    * <code>getDataRepeat</code> is ready. In the first case
    * the returned value is ignored, in the second it defines
    * whether any further conversions will be made or not.
    *
    * @param result ADC_SUCCESS if the conversion was performed
    * successfully and <code>data</code> is valid, error 
    * code otherwise (see ADCHIL.h).
    * @param data The conversion result, an uninterpreted 
    * 16-bit value.
    *
    * @return SUCCESS continues conversions in continuous mode,
    * FAIL stops further conversions in continuous mode
    * (ignored if not in continuous mode).
    */
  async event result_t dataReady(adcresult_t result, uint16_t data); 
}


--- NEW FILE: ADC_README ---
              Documentation on ADC12 Components for the MSP430    
 
$Revision: 1.1 $
$Date: 2005/09/28 10:41:11 $
@author Jan Hauer <hauer at tkn.tu-berlin.de>
             
       
There are three ways to access MSP430's ADC12: 

1) Platform independent applications should use
   tos/interfaces/ADCSingle.nc and tos/interfaces/ADCMultiple.nc.
2) Applications written only for the msp430 platform can use
   tos/platform/msp430/MSP430ADC12Single or tos/platform/msp430/MSP430ADC12Multiple.
3) The tos/interfaces/ADC and tos/interfaces/ADCControl
   interfaces are still supported but obsolete, do not use them, because
   they might not be supported in future. 

The use of 1) and 2) is explained TEP101 in beta/teps/, additional
information can be found below. The use of 3) (although obsolete) is also
explained below.
Generell information about the ADC12 can be found in "MSP430 User's Guide" 
Chapter 17. 

1) HIL
Read the section "Hardware Interface Layer (HIL)" in TEP101 in beta/teps/.

2) MSP430ADC12Single and MSP430ADC12Multiple
In a configuration the MSP430ADC12Single and MSP430ADC12Multiple
need to be instantiated with unique("MSP430ADC12").
Read the section "Hardware Adaptation Layer (HAL)" subsection c) in TEP101 
in beta/teps/.
Read the explanation in MSP430ADC12.h for how to use bind().
Look at tinyos-1.x/contrib/eyes/apps/TestADC for an example.

3) ADCC - obsolete -
ADC and ADCControl are used almost the same way as specified in the 
interface definitions, there is only a difference in the meaning of the 
parameters passed to ADCControl.bindPort(). 
"ADCControl.bindPort(uint8_t port, uint8_t adcPort)" needs to be called once for
each port that is to be sampled through the ADCC. This binds the interface
instance number (="port") to the actual input-channel and some other settings
coded in "adcPort". The reason for this is that any subsequent calls to
"ADC.getData()" will only require the port-number to identify the corresponding
settings. The port-number is not passed as a parameter of "ADC.getData()", but
it is the number of the ADC-interface instance (ADC is a parameterized
interface). That's why it is necessary to always have the "port"-parameter in
"ADCControl.bindPort(uint8_t port, uint8_t adcPort)" be the same as the
interface parameter of the ADC interface through which your component is wired
to ADCC. Actually this is how the interface ADCControl was intended anyway.

a) The "port" Parameter of ADCControl.bindPort 

Since the "port" parameters reflect the interface instance they must all be
different starting from 0 (to keep RAM usage to minimum as the interface IDs are
used to index and allocate an array).  This is achieved by having a separate
header file for each sensor component and having a unique constant created for
each sensor with unique("ADCPort"), see below for an example.

b) The "adcPort" Parameter of ADCControl.bindPort 

The parameter "adcPort" encodes the input channel and the reference voltage. If
reference voltage VREF+ is used it additionally holds information about the
required value of VREF+ (1.5V or 2.5V). In detail:

 bit 0-3: input channel
 bit 4-6: reference voltage
 bit 7: voltage level (ignored if reference voltage != VREF+)

There is a macro ASSOCIATE_ADC_CHANNEL in MSP430ADC12.h that can be used to
encode this information. In the header file for a sensor component there should
be a constant that reflects the actual settings for this sensor. An example for
the "port" and "adcPort" parameters (see InternalVoltage.h):

enum
{
  // the "port" parameter and interface id
  TOS_ADC_INTERNAL_VOLTAGE_PORT = unique("ADCPort"),

  // the actual settings, "adcPort" parameter
  TOSH_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT = ASSOCIATE_ADC_CHANNEL( 
           INTERNAL_VOLTAGE, 
           REFERENCE_VREFplus_AVss, 
           REFVOLT_LEVEL_1_5), 
};


WIRING EXAMPLE:

first wire ADCC to your configuration:

    MyApp.ADC -> ADCC.ADC[TOS_ADC_INTERNAL_VOLTAGE_PORT];
    MyApp.ADCControl -> ADCC.ADCControl;

then bind and do the conversion in you module.

    call ADCControl.init();
    call ADCControl.bindPort(TOS_ADC_INTERNAL_VOLTAGE_PORT, 
                                   TOSH_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT);
    call ADC.getData();

    


--- NEW FILE: DemoSensorC.nc ---
// $Id: DemoSensorC.nc,v 1.1 2005/09/28 10:41:11 jpolastre Exp $

/*                  tab:4
 * "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-2003 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.
 */
/*
 *
 * Authors:   Jason Hill, David Gay, Philip Levis
 * Date last modified:  6/25/02
 *
 */

/**
 * @author Jason Hill
 * @author David Gay
 * @author Philip Levis
 * @author Kevin Klues (adaptation for the EYES nodes)
 */


configuration DemoSensorC
{
  provides interface ADC;
  provides interface StdControl;
}
implementation
{
  components InternalTempC as DemoSensor;
  
  StdControl = DemoSensor;
  ADC = DemoSensor;
}

--- NEW FILE: HPLADC12.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Description ----------------------------------------------------------
 * Interface for controlling ADC12-functionality of MSP430.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer (hauer at tkn.tu-berlin.de)
 * ========================================================================
 */
        
includes  MSP430ADC12;

interface HPLADC12
{
  async command void setControl0(adc12ctl0_t control0); 
  async command void setControl1(adc12ctl1_t control1);
  async command adc12ctl0_t getControl0(); 
  async command adc12ctl1_t getControl1(); 
  
  /* Sets ADC12CTL0 to control0 except it leaves REFON, REF2_5V unchanged */
  async command void setControl0_IgnoreRef(adc12ctl0_t control0); 
  
  async command void setMemControl(uint8_t index, adc12memctl_t memControl); 
  async command adc12memctl_t getMemControl(uint8_t i); 
  async command uint16_t getMem(uint8_t i); 

  
  async command void setIEFlags(uint16_t mask); 
  async command uint16_t getIEFlags(); 
  
  async command void resetIFGs(); 
  async command uint16_t getIFGs(); 

  async event void memOverflow();
  async event void timeOverflow();
  async event void converted(uint8_t number);

  async command bool isBusy();
  /* ATTENTION: setConversionMode and setSHT etc. require ENC-flag to be reset! 
     (disableConversion) */
  async command void setConversionMode(uint8_t mode);
  async command void setSHT(uint8_t sht);
  async command void setMSC();
  async command void resetMSC();
  async command void setRefOn();
  async command void setRefOff();
  async command uint8_t getRefon();     // off if 0, else on
  async command void setRef1_5V();
  async command void setRef2_5V();
  async command uint8_t getRef2_5V();   // 1.5 V if 0, else 2.5 V
    
  async command void enableConversion();
  async command void disableConversion();
  async command void startConversion();
  async command void stopConversion();
  
  async command bool isInterruptPending();
  async command void off();
  async command void on();
}


--- NEW FILE: HPLADC12M.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Description ----------------------------------------------------------
 * ADC lowlevel functions.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer
 * ========================================================================
 */

module HPLADC12M {
  provides interface HPLADC12;
}
implementation
{
 
  MSP430REG_NORACE(ADC12CTL0);
  MSP430REG_NORACE(ADC12CTL1);
  MSP430REG_NORACE(ADC12IFG);
  MSP430REG_NORACE(ADC12IE);
  MSP430REG_NORACE(ADC12IV);
  
  async command void HPLADC12.setControl0(adc12ctl0_t control0){
    ADC12CTL0 = *(uint16_t*)&control0; 
  }
  
  async command void HPLADC12.setControl1(adc12ctl1_t control1){
    ADC12CTL1 = *(uint16_t*)&control1; 
  }
  
  async command void HPLADC12.setControl0_IgnoreRef(adc12ctl0_t control0){
    adc12ctl0_t oldControl0 = (*(adc12ctl0_t*) &ADC12CTL0);
    control0.refon = oldControl0.refon;
    control0.r2_5v = oldControl0.r2_5v;
    ADC12CTL0 = (*(uint16_t*)&control0); 
  }
     
  async command adc12ctl0_t HPLADC12.getControl0(){ 
    return *(adc12ctl0_t*) &ADC12CTL0; 
  }
  
  async command adc12ctl1_t HPLADC12.getControl1(){
    return *(adc12ctl1_t*) &ADC12CTL1; 
  }
  
  async command void HPLADC12.setMemControl(uint8_t i, adc12memctl_t memControl){
    uint8_t *memCtlPtr = (uint8_t*) ADC12MCTL;
    if (i<16){
      memCtlPtr += i;
      *memCtlPtr = *(uint8_t*)&memControl; 
    }
  }
   
  async command adc12memctl_t HPLADC12.getMemControl(uint8_t i){
    adc12memctl_t x = {inch: 0, sref: 0, eos: 0 };    
    uint8_t *memCtlPtr = (uint8_t*) ADC12MCTL;
    if (i<16){
      memCtlPtr += i;
      x = *(adc12memctl_t*) memCtlPtr;
    }
    return x;
  }  
  
  async command uint16_t HPLADC12.getMem(uint8_t i){
    return *((uint16_t*) ADC12MEM + i);
  }

  async command void HPLADC12.setIEFlags(uint16_t mask){ ADC12IE = mask; } 
  async command uint16_t HPLADC12.getIEFlags(){ return (uint16_t) ADC12IE; } 
  
  async command void HPLADC12.resetIFGs(){ 
    // workaround, because ADC12IFG = 0x0000 has no effect !
    if (!ADC12IFG)
      return;
    else {
      uint8_t i;
      volatile uint16_t mud;
      for (i=0; i<16; i++)
        mud = call HPLADC12.getMem(i);
    }
  } 
  
  async command uint16_t HPLADC12.getIFGs(){ return (uint16_t) ADC12IFG; } 

  async command bool HPLADC12.isBusy(){ return ADC12CTL1 & ADC12BUSY; }
  
  async command void HPLADC12.enableConversion(){ ADC12CTL0 |= ENC;}
  async command void HPLADC12.disableConversion(){ ADC12CTL0 &= ~ENC; }
  async command void HPLADC12.startConversion(){ ADC12CTL0 |= ADC12SC + ENC; }
  async command void HPLADC12.stopConversion(){ 
    ADC12CTL1 &= ~(CONSEQ_1 | CONSEQ_3); 
    ADC12CTL0 &= ~ENC; 
  }
  
  async command void HPLADC12.setMSC(){ ADC12CTL0 |= MSC; }
  async command void HPLADC12.resetMSC(){ ADC12CTL0 &= ~MSC; }
  
  async command void HPLADC12.setConversionMode(uint8_t mode){
    uint16_t ctl1 = ADC12CTL1 & 0xFFF9;
    switch(mode){
      case SINGLE_CHANNEL: ADC12CTL0 &= ~MSC; break;
      case SEQUENCE_OF_CHANNELS: ctl1 |= 0x0002; ADC12CTL0 |= MSC; break;
      case REPEAT_SINGLE_CHANNEL: ctl1 |= 0x0004; ADC12CTL0 |= MSC; break;
      case REPEAT_SEQUENCE_OF_CHANNELS: ctl1 |= 0x0006; ADC12CTL0 |= MSC; break;
    }
    ADC12CTL1 = ctl1;
    return;
  }
    
  async command void HPLADC12.setRefOn(){ ADC12CTL0 |= REFON;}
  async command void HPLADC12.setRefOff(){ ADC12CTL0 &= ~REFON;}
  async command uint8_t HPLADC12.getRefon(){ return ADC12CTL0 & REFON;}
  async command void HPLADC12.setRef1_5V(){ ADC12CTL0 &= ~REF2_5V;}
  async command void HPLADC12.setRef2_5V(){ ADC12CTL0 |= REF2_5V;}
  async command uint8_t HPLADC12.getRef2_5V(){ return ADC12CTL0 & REF2_5V;}
  
  async command void HPLADC12.setSHT(uint8_t sht){
    uint16_t ctl0 = ADC12CTL0;
    uint16_t shttemp = sht & 0x0F;    
    ctl0 &= 0x00FF;
    ctl0 |= (shttemp << 8);
    ctl0 |= (shttemp << 12);
    ADC12CTL0 = ctl0; 
  }
  
  async command bool HPLADC12.isInterruptPending(){ 
    if (ADC12IFG)
      return TRUE;
    else
      return FALSE;
  }
  
  async command void HPLADC12.off(){ ADC12CTL0 &= ~ADC12ON; }
  async command void HPLADC12.on(){ ADC12CTL0 |= ADC12ON; }

  TOSH_SIGNAL(ADC_VECTOR) {
    uint16_t iv = ADC12IV;
    switch(iv)
    {
      case  2: signal HPLADC12.memOverflow(); return;
      case  4: signal HPLADC12.timeOverflow(); return;
    }
    iv >>= 1;
    if (iv && iv < 19)
      signal HPLADC12.converted(iv-3);
  }
}

--- NEW FILE: InternalTemp.h ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */


#ifndef INTERNAL_TEMP_H 
#define INTERNAL_TEMP_H

#include "MSP430ADC12.h"

enum
{
  TOS_ADC_INTERNAL_TEMP_PORT = unique("ADCPort"),
  TOSH_ACTUAL_ADC_INTERNAL_TEMPERATURE_PORT = ASSOCIATE_ADC_CHANNEL( 
           INTERNAL_TEMPERATURE, 
           REFERENCE_VREFplus_AVss, 
           REFVOLT_LEVEL_1_5), 
};

#define MSP430ADC12_INTERNAL_TEMPERATURE ADC12_SETTINGS( \
           INTERNAL_TEMPERATURE, REFERENCE_VREFplus_AVss, SAMPLE_HOLD_4_CYCLES, \
           SHT_SOURCE_ACLK, SHT_CLOCK_DIV_1, SAMPCON_SOURCE_SMCLK, \
           SAMPCON_CLOCK_DIV_1, REFVOLT_LEVEL_1_5) 


#endif


--- NEW FILE: InternalTempC.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */

includes InternalTemp;
configuration InternalTempC
{
  provides interface ADC as InternalTempADC;
  provides interface ADCSingle;
  provides interface ADCMultiple;
  provides interface StdControl;
}
implementation
{
  components InternalTempM
    , ADCC
#ifdef __msp430_have_adc12
    , MSP430ADC12C
#endif
    ;
  
  StdControl = InternalTempM;
  StdControl = ADCC;
  ADCSingle = InternalTempM;
  ADCMultiple = InternalTempM;
  InternalTempADC = ADCC.ADC[TOS_ADC_INTERNAL_TEMP_PORT];
  
  InternalTempM.ADCControl -> ADCC;

#ifdef __msp430_have_adc12
  StdControl = MSP430ADC12C;
  InternalTempM.MSP430ADC12Single -> MSP430ADC12C.MSP430ADC12Single[unique("MSP430ADC12")];
  InternalTempM.MSP430ADC12Multiple -> MSP430ADC12C.MSP430ADC12Multiple[unique("MSP430ADC12")];
#endif
}

--- NEW FILE: InternalTempM.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
includes ADCHIL;
module InternalTempM {
  provides {
    interface StdControl;
    interface ADCSingle;
    interface ADCMultiple;
  }
  uses {
    interface ADCControl;
    interface MSP430ADC12Single;
    interface MSP430ADC12Multiple;
  }
}
implementation {
  norace bool contMode;

  command result_t StdControl.init() {
    contMode = FALSE;
    return SUCCESS;
  }
  
  command result_t StdControl.start() {
   result_t ok1, ok2;
   
   ok1 = call ADCControl.init();
   ok2 = call ADCControl.bindPort(TOS_ADC_INTERNAL_TEMP_PORT, 
                                  TOSH_ACTUAL_ADC_INTERNAL_TEMPERATURE_PORT);
   call MSP430ADC12Single.bind(MSP430ADC12_INTERNAL_TEMPERATURE);
   call MSP430ADC12Multiple.bind(MSP430ADC12_INTERNAL_TEMPERATURE);
   return SUCCESS;
  }
   
  command result_t StdControl.stop() {
    return SUCCESS;
  }
 
  async command adcresult_t ADCSingle.getData()
  {
    if (call MSP430ADC12Single.getData() != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCSingle.getDataContinuous()
  {
    if (call MSP430ADC12Single.getDataRepeat(0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }
  
  async command adcresult_t ADCSingle.reserve()
  {
    if (call MSP430ADC12Single.reserve() == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }
  
  async command adcresult_t ADCSingle.reserveContinuous()
  {
    if (call MSP430ADC12Single.reserveRepeat(0) == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCSingle.unreserve()
  {
    if (call MSP430ADC12Single.unreserve() == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async event result_t MSP430ADC12Single.dataReady(uint16_t data)
  {
    return signal ADCSingle.dataReady(ADC_SUCCESS, data); 
  }

  default async event result_t ADCSingle.dataReady(adcresult_t result, uint16_t data)
  { 
    return FAIL;
  }


  async command adcresult_t ADCMultiple.getData(uint16_t *buf, uint16_t length)
  {
    if (call MSP430ADC12Multiple.getData(buf, length, 0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCMultiple.getDataContinuous(uint16_t *buf, uint16_t length)
  {
    if (length <= 16) {
      if (call MSP430ADC12Multiple.getDataRepeat(buf, length, 0) != MSP430ADC12_FAIL)
        return ADC_SUCCESS;
      return ADC_FAIL;
    } else {
      if (call MSP430ADC12Multiple.getData(buf, length, 0) != MSP430ADC12_FAIL){
        contMode = TRUE;
        return ADC_SUCCESS;
      } else
        return ADC_FAIL;
    }
  }

  async command adcresult_t ADCMultiple.reserve(uint16_t *buf, uint16_t length)
  {
    if (call MSP430ADC12Multiple.reserve(buf, length, 0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCMultiple.reserveContinuous(uint16_t *buf, uint16_t length)
  {
    if (call MSP430ADC12Multiple.reserveRepeat(buf, length, 0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCMultiple.unreserve()
  {
    if (call MSP430ADC12Multiple.unreserve() == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }
  
  async event uint16_t* MSP430ADC12Multiple.dataReady(uint16_t *buf, uint16_t length)
  {
    uint16_t *nextbuf;
    if (!contMode)
      nextbuf = signal ADCMultiple.dataReady(SUCCESS, buf, length);
    else
      if ((nextbuf = signal ADCMultiple.dataReady(SUCCESS, buf, length)))
        call MSP430ADC12Multiple.getData(nextbuf, length, 0);
      else
        contMode = FALSE;
    return nextbuf;
  } 

  default async event uint16_t* ADCMultiple.dataReady(adcresult_t result, uint16_t *buf, uint16_t length)
  {
    return 0;
  }
  
}


--- NEW FILE: InternalVoltage.h ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */


#ifndef INTERNAL_VOLTAGE_H 
#define INTERNAL_VOLTAGE_H

#include "MSP430ADC12.h"

enum
{
  TOS_ADC_INTERNAL_VOLTAGE_PORT = unique("ADCPort"),
  TOSH_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT = ASSOCIATE_ADC_CHANNEL( 
           INTERNAL_VOLTAGE, 
           REFERENCE_VREFplus_AVss, 
           REFVOLT_LEVEL_1_5), 
}; 

#define MSP430ADC12_INTERNAL_VOLTAGE ADC12_SETTINGS( \
           INTERNAL_VOLTAGE, REFERENCE_VREFplus_AVss, SAMPLE_HOLD_4_CYCLES, \
           SHT_SOURCE_ACLK, SHT_CLOCK_DIV_1, SAMPCON_SOURCE_SMCLK, \
           SAMPCON_CLOCK_DIV_1, REFVOLT_LEVEL_1_5) 

#endif



--- NEW FILE: InternalVoltageC.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
includes InternalVoltage;
configuration InternalVoltageC
{
  provides interface ADC as InternalVoltageADC;
  provides interface ADCSingle;
  provides interface ADCMultiple;
  provides interface StdControl;
}
implementation
{
  components InternalVoltageM
    , ADCC
#ifdef __msp430_have_adc12
    , MSP430ADC12C
#endif
    ;
  
  StdControl = InternalVoltageM;
  StdControl = ADCC;
  ADCSingle = InternalVoltageM;
  ADCMultiple = InternalVoltageM;
  InternalVoltageADC = ADCC.ADC[TOS_ADC_INTERNAL_VOLTAGE_PORT];
  
  InternalVoltageM.ADCControl -> ADCC;

#ifdef __msp430_have_adc12
  StdControl = MSP430ADC12C;
  InternalVoltageM.MSP430ADC12Single -> MSP430ADC12C.MSP430ADC12Single[unique("MSP430ADC12")];
  InternalVoltageM.MSP430ADC12Multiple -> MSP430ADC12C.MSP430ADC12Multiple[unique("MSP430ADC12")];
#endif
}


--- NEW FILE: InternalVoltageM.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
includes ADCHIL;
module InternalVoltageM {
  provides {
    interface StdControl;
    interface ADCSingle;
    interface ADCMultiple;
  }
  uses {
    interface ADCControl;
    interface MSP430ADC12Single;
    interface MSP430ADC12Multiple;
  }
}
implementation {
  norace bool contMode;

  command result_t StdControl.init() {
    contMode = FALSE;
    return SUCCESS;
  }
  
  command result_t StdControl.start() {
   result_t ok1, ok2;
   
   ok1 = call ADCControl.init();
   ok2 = call ADCControl.bindPort(TOS_ADC_INTERNAL_VOLTAGE_PORT, 
                                  TOSH_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT);
   call MSP430ADC12Single.bind(MSP430ADC12_INTERNAL_VOLTAGE);
   call MSP430ADC12Multiple.bind(MSP430ADC12_INTERNAL_VOLTAGE);
   return SUCCESS;
  }
   
  command result_t StdControl.stop() {
    return SUCCESS;
  }
 
  async command adcresult_t ADCSingle.getData()
  {
    if (call MSP430ADC12Single.getData() != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCSingle.getDataContinuous()
  {
    if (call MSP430ADC12Single.getDataRepeat(0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }
  
  async command adcresult_t ADCSingle.reserve()
  {
    if (call MSP430ADC12Single.reserve() == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }
  
  async command adcresult_t ADCSingle.reserveContinuous()
  {
    if (call MSP430ADC12Single.reserveRepeat(0) == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCSingle.unreserve()
  {
    if (call MSP430ADC12Single.unreserve() == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async event result_t MSP430ADC12Single.dataReady(uint16_t data)
  {
    return signal ADCSingle.dataReady(ADC_SUCCESS, data); 
  }

  
  default async event result_t ADCSingle.dataReady(adcresult_t result, uint16_t data)
  { 
    return FAIL;
  }

  async command adcresult_t ADCMultiple.getData(uint16_t *buf, uint16_t length)
  {
    if (call MSP430ADC12Multiple.getData(buf, length, 0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCMultiple.getDataContinuous(uint16_t *buf, uint16_t length)
  {
    if (length <= 16) {
      if (call MSP430ADC12Multiple.getDataRepeat(buf, length, 0) != MSP430ADC12_FAIL)
        return ADC_SUCCESS;
      return ADC_FAIL;
    } else {
      if (call MSP430ADC12Multiple.getData(buf, length, 0) != MSP430ADC12_FAIL){
        contMode = TRUE;
        return ADC_SUCCESS;
      } else
        return ADC_FAIL;
    }
  }

  async command adcresult_t ADCMultiple.reserve(uint16_t *buf, uint16_t length)
  {
    if (call MSP430ADC12Multiple.reserve(buf, length, 0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCMultiple.reserveContinuous(uint16_t *buf, uint16_t length)
  {
    if (call MSP430ADC12Multiple.reserveRepeat(buf, length, 0) != MSP430ADC12_FAIL)
      return ADC_SUCCESS;
    return ADC_FAIL;
  }

  async command adcresult_t ADCMultiple.unreserve()
  {
    if (call MSP430ADC12Multiple.unreserve() == SUCCESS) 
      return ADC_SUCCESS;
    return ADC_FAIL;
  }
  
  async event uint16_t* MSP430ADC12Multiple.dataReady(uint16_t *buf, uint16_t length)
  {
    uint16_t *nextbuf;
    if (!contMode)
      nextbuf = signal ADCMultiple.dataReady(SUCCESS, buf, length);
    else
      if ((nextbuf = signal ADCMultiple.dataReady(SUCCESS, buf, length)))
        call MSP430ADC12Multiple.getData(nextbuf, length, 0);
      else
        contMode = FALSE;
    return nextbuf;
  } 

  default async event uint16_t* ADCMultiple.dataReady(adcresult_t result, uint16_t *buf, uint16_t length)
  {
    return 0;
  }
}


--- NEW FILE: MSP430ADC12.h ---
//$Id: MSP430ADC12.h,v 1.1 2005/09/28 10:41:11 jpolastre Exp $

#ifndef MSP430ADC12_H
#define MSP430ADC12_H

/*
 * An application using the MSP430ADC12Single or MSP430ADC12Multiple interface 
 * needs to call bind() to bind the interface instance to certain settings which 
 * will be used for all subsequent conversions. In the following a macro,
 * ADC12_SETTINGS(), is provided to conveniently create the parameter for bind.
 * The macro takes 8 arguments:
 * 
 * ADC12_SETTINGS(IC, RV, SHT, CS_SHT, CD_SHT, CS_SAMPCON, CD_SAMPCON, RVL)
 *   
 * The arguments have the following meaning:
 * 
 * IC: Input channel to be sampled. An (external) input channel maps to one of
 * msp430's pins (see device specific data sheet which pin it is mapped to, A0-A7).
 * Make sure this pin is set to module function and input when sampling the
 * channel. Use inputChannel_enum in MSP430ADC12.h for IC.
 * 
 * RV: Reference voltage for the conversion(s). The MSP430 allows conversions with
 * VREF+ as a stable reference voltage (see RefVolt component). Therefore the
 * HAL module checks each request for the reference voltage and if necessary
 * switches on VREF+ automatically (via RefVolt component).  However, because there
 * is a startup delay of max. 17ms for the reference voltage generator to become
 * stable, a call getData() might result in an event dataReady() delayed by 17ms.
 * To avoid this, the application can start the reference voltage generator itself
 * by calling RefVolt.get() 17ms prior to the first conversion (and call
 * RefVolt.release() after the last conversion). Use referenceVoltage_enum in
 * MSP430ADC12.h for RV.
 * 
 * SHT: Sample-hold-time. This defines the time a channel is actually sampled for.  It
 * is measured in clock cycles of the sample-hold clock source (CS_SHT) and depends
 * on the external source resistance, see section ADC12, subsection "Sample Timing
 * Considerations" in msp430 User Guide. Use sampleHold_enum for SHT.
 *      
 * CS_SHT: Clock source for sample-hold-time. Use clockSourceSHT_enum for CS_SHT.
 * 
 * CD_SHT: Clock divider for clock source of sample-hold-time. Use
 * clockDivSHT_enum for CD_SHT.
 *
 * CS_SAMPCON: Clock source for the SAMPCON signal.
 * One characteristic of the MSP430 ADC12 is the ability to define the time 
 * interval between subsequent conversions and let multiple conversions
 * be performed completely in hardware. This is reflected by an additional 
 * parameter (jiffies) in the relevant commands of the HAL interfaces.
 * CS_SAMPCON defines the clock source for and jiffies defines the
 * period in cycles of CS_SAMPCON (see example below). Use
 * clockSourceSAMPCON_enum for CS_SAMPCON.
 *             
 * CD_SAMPCON: Clock divider for clock source of SAMPCON signal.  Together with
 * CS_SAMPCON and the *jiffies* parameter in a getData() command the CD_SAMPCON
 * defines the period a channel is sampled. Use clockSourceSAMPCON_enum for
 * CS_SAMPCON.
 * 
 * RVL: Reference voltage level. This is only valid it for RV either
 * REFERENCE_VREFplus_AVss or REFERENCE_VREFplus_VREFnegterm was chosen, otherwise
 * it is ignored. It specifies the level of VREF+. Use refVolt2_5_enum for RVL.
 * 
 * EXAMPLE:
 * Binding to settings for a sensor on channel A1, using 
 * reference voltage VR+ = VREF+ and VR­ = AVSS, a sample hold-time
 * of 4 * (1/5000000) * 2 = 1.6us, a sampcon source of SMCLK and
 * reference voltage generator level of 1.5 Volt:
 *
 * call MSP430ADC12Multiple.bind(ADC12_SETTINGS(INPUT_CHANNEL_A1, 
 *                                              REFERENCE_VREFplus_AVss,
 *                                              SAMPLE_HOLD_4_CYCLES,
 *                                              SHT_SOURCE_ADC12OSC,
 *                                              SHT_CLOCK_DIV_2,
 *                                              SAMPCON_SOURCE_SMCLK,
 *                                              SAMPCON_CLOCK_DIV_1,
 *                                              REFVOLT_LEVEL_1_5));
 * 
 * Now the following command takes 100 samples, each separated by 1ms 
 * (assuming SMCLK runs at 1MHz):
 *
 * call MSP430ADC12Multiple.getData(buf, 100, 1000);
 *
 * After 17ms (initial start of reference voltage generator) + 100 * 1 ms
 * = 117 ms the corresponding event is signalled.
 * Note that the SAMPCON signal is concurrent to the sampling process,
 * i.e. sample-hold-time is not relevant for the calculation of the 117ms.
 *
 * In the configuration the MSP430ADC12Single and MSP430ADC12Multiple
 * need to be instantiated with unique("MSP430ADC12").
 */
#define ADC12_SETTINGS(IC, RV, SHT, CS_SHT, CD_SHT, CS_SAMPCON, CD_SAMPCON, RVL) \
        (int2adcSettings(((((((((((((((((uint32_t) SHT) << 4) + IC) << 3) \
        + CD_SHT) << 3) + RV) << 2) + CD_SAMPCON) << 2) + CS_SAMPCON) << 2) \
        + CS_SHT) << 1) + RVL)))

/*
 * Defining the 'adcPort' variable in
 * ADCControl.bindPort(uint8_t port, uint8_t adcPort).
 *
 * IC:  member of inputChannel_enum
 * RV:  member of referenceVoltage_enum
 * RVL: member of refVolt2_5_enum
 */
#define ASSOCIATE_ADC_CHANNEL(IC, RV, RVL) \
        ((((RVL << 3) + RV) << 4) + IC)
        
typedef struct 
{
  unsigned int refVolt2_5: 1;         // reference voltage level
  unsigned int clockSourceSHT: 2;     // clock source sample-hold-time
  unsigned int clockSourceSAMPCON: 2; // clock source sampcon signal
  unsigned int clockDivSAMPCON: 2;    // clock divider sampcon
  unsigned int referenceVoltage: 3;   // reference voltage
  unsigned int clockDivSHT: 3;        // clock divider sample-hold-time
  unsigned int inputChannel: 4;       // input channel
  unsigned int sampleHoldTime: 4;     // sample-hold-time
  unsigned int : 0;                   // aligned to a word boundary 
} MSP430ADC12Settings_t;
 
typedef enum
{
  MSP430ADC12_FAIL = 0,               // request failed
  MSP430ADC12_SUCCESS = 1,            // request was successful
  MSP430ADC12_DELAYED = 2,            // request was successful but delayed
} msp430ADCresult_t;

enum refVolt2_5_enum
{
  REFVOLT_LEVEL_1_5 = 0,                    // reference voltage of 1.5 V
  REFVOLT_LEVEL_2_5 = 1,                    // reference voltage of 2.5 V
};

enum clockDivSHT_enum
{
   SHT_CLOCK_DIV_1 = 0,                         // ADC12 clock divider of 1
   SHT_CLOCK_DIV_2 = 1,                         // ADC12 clock divider of 2
   SHT_CLOCK_DIV_3 = 2,                         // ADC12 clock divider of 3
   SHT_CLOCK_DIV_4 = 3,                         // ADC12 clock divider of 4
   SHT_CLOCK_DIV_5 = 4,                         // ADC12 clock divider of 5
   SHT_CLOCK_DIV_6 = 5,                         // ADC12 clock divider of 6
   SHT_CLOCK_DIV_7 = 6,                         // ADC12 clock divider of 7
   SHT_CLOCK_DIV_8 = 7,                         // ADC12 clock divider of 8
};

enum clockDivSAMPCON_enum
{
   SAMPCON_CLOCK_DIV_1 = 0,             // SAMPCON clock divider of 1
   SAMPCON_CLOCK_DIV_2 = 1,             // SAMPCON clock divider of 2
   SAMPCON_CLOCK_DIV_3 = 2,             // SAMPCON clock divider of 3
   SAMPCON_CLOCK_DIV_4 = 3,             // SAMPCON clock divider of 4
};

enum clockSourceSAMPCON_enum
{
   SAMPCON_SOURCE_TACLK = 0,        // Timer A clock source is (external) TACLK
   SAMPCON_SOURCE_ACLK = 1,         // Timer A clock source ACLK
   SAMPCON_SOURCE_SMCLK = 2,        // Timer A clock source SMCLK
   SAMPCON_SOURCE_INCLK = 3,        // Timer A clock source is (external) INCLK
};

enum inputChannel_enum
{  
   // see device specific data sheet which pin Ax is mapped to
   INPUT_CHANNEL_A0 = 0,                    // input channel A0 
   INPUT_CHANNEL_A1 = 1,                    // input channel A1
   INPUT_CHANNEL_A2 = 2,                    // input channel A2
   INPUT_CHANNEL_A3 = 3,                    // input channel A3
   INPUT_CHANNEL_A4 = 4,                    // input channel A4
   INPUT_CHANNEL_A5 = 5,                    // input channel A5
   INPUT_CHANNEL_A6 = 6,                    // input channel A6
   INPUT_CHANNEL_A7 = 7,                    // input channel A7
   EXTERNAL_REFERENCE_VOLTAGE = 8,          // VeREF+ (input channel 8)
   REFERENCE_VOLTAGE_NEGATIVE_TERMINAL = 9, // VREF-/VeREF- (input channel 9)
   INTERNAL_TEMPERATURE = 10,               // Temperature diode (input channel 10)
   INTERNAL_VOLTAGE = 11                    // (AVcc-AVss)/2 (input channel 11-15)
};

enum referenceVoltage_enum
{
   REFERENCE_AVcc_AVss = 0,                 // VR+ = AVcc   and VR-= AVss
   REFERENCE_VREFplus_AVss = 1,             // VR+ = VREF+  and VR-= AVss
   REFERENCE_VeREFplus_AVss = 2,            // VR+ = VeREF+ and VR-= AVss
   REFERENCE_AVcc_VREFnegterm = 4,          // VR+ = AVcc   and VR-= VREF-/VeREF- 
   REFERENCE_VREFplus_VREFnegterm = 5,      // VR+ = VREF+  and VR-= VREF-/VeREF-   
   REFERENCE_VeREFplus_VREFnegterm = 6      // VR+ = VeREF+ and VR-= VREF-/VeREF-
};

enum clockSourceSHT_enum
{
   SHT_SOURCE_ADC12OSC = 0,                // ADC12OSC
   SHT_SOURCE_ACLK = 1,                    // ACLK
   SHT_SOURCE_MCLK = 2,                    // MCLK
   SHT_SOURCE_SMCLK = 3                    // SMCLK
};

enum sampleHold_enum
{
   SAMPLE_HOLD_4_CYCLES = 0,         // sampling duration is 4 clock cycles
   SAMPLE_HOLD_8_CYCLES = 1,         // ...
   SAMPLE_HOLD_16_CYCLES = 2,         
   SAMPLE_HOLD_32_CYCLES = 3,         
   SAMPLE_HOLD_64_CYCLES = 4,         
   SAMPLE_HOLD_96_CYCLES = 5,        
   SAMPLE_HOLD_123_CYCLES = 6,        
   SAMPLE_HOLD_192_CYCLES = 7,        
   SAMPLE_HOLD_256_CYCLES = 8,        
   SAMPLE_HOLD_384_CYCLES = 9,        
   SAMPLE_HOLD_512_CYCLES = 10,        
   SAMPLE_HOLD_768_CYCLES = 11,        
   SAMPLE_HOLD_1024_CYCLES = 12       
};



                             /* private */


typedef union {
   uint32_t i;
   MSP430ADC12Settings_t s;
} MSP430ADC12Settings_ut;


inline MSP430ADC12Settings_t int2adcSettings(uint32_t i){
  MSP430ADC12Settings_ut u;
  u.i = i;
  return u.s;
}

enum
{
  ADC_IDLE = 0x00,
  SINGLE_CHANNEL = 0x01,
  REPEAT_SINGLE_CHANNEL = 0x02,
  SEQUENCE_OF_CHANNELS = 0x04,
  REPEAT_SEQUENCE_OF_CHANNELS = 0x08,
  TIMER_USED = 0x10,
  RESERVED = 0x20,
  VREF_WAIT = 0x40,
  ADC_INTERRUPT_DISABLED =0x80,
};
  
/* Test for GCC bug (bitfield access) - only version 3.2.3 is known to be stable */
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION == 332
#error "Your gcc version (3.3.2) contains a bug which results in false accessing \
of bitfields in structs and makes MSP430ADC12M.nc fail ! Install version 3.2.3 instead."
#elif GCC_VERSION != 323
#warning "This version of gcc might contain a bug which results in false accessing \
of bitfields in structs (MSP430ADC12M.nc would fail). Version 3.2.3 is known to be safe."
#endif  

#define ADC12CTL0_DEFAULT 0x0000
#define ADC12CTL0_TIMER_TRIGGERED ((ADC12CTL0_DEFAULT | ADC12ON) & ~(MSC))
#define ADC12CTL0_AUTO_TRIGGERED ((ADC12CTL0_DEFAULT | ADC12ON) | MSC)


typedef struct 
{
  volatile unsigned
  inch: 4,                                     // input channel
  sref: 3,                                     // reference voltage
  eos: 1;                                      // end of sequence flag
} __attribute__ ((packed)) adc12memctl_t;

typedef struct 
{
  unsigned int refVolt2_5: 1;
  unsigned int gotRefVolt: 1;
  unsigned int result_16bit: 1;
  unsigned int clockSourceSHT: 2;
  unsigned int clockSourceSAMPCON: 2;
  unsigned int clockDivSAMPCON: 2;  
  unsigned int clockDivSHT: 3;            
  unsigned int sampleHoldTime: 4; 
  adc12memctl_t memctl;
} __attribute__ ((packed)) adc12settings_t;


#endif

--- NEW FILE: MSP430ADC12C.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */

configuration MSP430ADC12C
{
  provides interface StdControl;
  provides interface MSP430ADC12Single[uint8_t id];
  provides interface MSP430ADC12Multiple[uint8_t id];
}

implementation
{
// ALL MSP430 devices with ADC12 have PORT6 too
// the converse is not true--msp430x14x1 does not have ADC12 but has PORT6
// keeps users with ADC10 or slope devices from accidentally using ADC12
#ifndef __msp430_have_adc12  // this could be ADC12MEM instead
#error MSP430ADC12C: Target msp430 device does not have ADC12 module
#endif

  components MSP430ADC12M, HPLADC12M, MSP430TimerAExclusiveC as TAC, RefVoltC;

  StdControl = TAC;
  StdControl = MSP430ADC12M;
  MSP430ADC12Single = MSP430ADC12M.ADCSingle;
  MSP430ADC12Multiple = MSP430ADC12M.ADCMultiple;
    
  MSP430ADC12M.HPLADC12 -> HPLADC12M;
  MSP430ADC12M.RefVolt -> RefVoltC;

  MSP430ADC12M.TimerExclusive -> TAC.TimerExclusive[unique("TimerA")];

}


--- NEW FILE: MSP430ADC12M.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
includes MSP430ADC12;

module MSP430ADC12M 
{
  provides {
    interface StdControl;
    interface MSP430ADC12Single as ADCSingle[uint8_t id];
    interface MSP430ADC12Multiple as ADCMultiple[uint8_t id];
  }
  uses {
    interface HPLADC12;
    interface RefVolt;
    interface TimerExclusive;
  }
}
implementation
{  
  #define CHECKARGS 1
  
  norace uint8_t cmode;             /* current conversion mode */
  norace uint16_t *bufPtr;          /* result buffer */
  norace uint16_t bufLength;        /* length of buffer */
  norace uint16_t bufOffset;        /* offset into buffer */
  norace uint8_t owner;             /* interface instance for current conversion */
  norace uint8_t reserved;          /* reserve() called successfully */
  norace uint8_t vrefWait;          /* waiting for voltage generator to become stable */
  norace adc12settings_t adc12settings[uniqueCount("MSP430ADC12")]; /* bind settings */
  
  void stopConversion();

  command result_t StdControl.init()
  { 
    cmode = ADC_IDLE;
    reserved = ADC_IDLE;
    vrefWait = FALSE;
    call HPLADC12.disableConversion();
    call HPLADC12.setIEFlags(0x0000);       
    return SUCCESS;
  }
  
  command result_t StdControl.start()
  {
    return SUCCESS; 
  }
  
  command result_t StdControl.stop()
  {
    call HPLADC12.disableConversion();
    call HPLADC12.setIEFlags(0x0000);
    return SUCCESS;
  }
  
  void configureAdcPin( uint8_t inputChannel )
  {
    if( inputChannel <= 7 ){
      P6SEL |= (1 << inputChannel); //adc function (instead of general IO)
      P6DIR &= ~(1 << inputChannel); //input (instead of output)
    }
  }

  command result_t ADCSingle.bind[uint8_t num](MSP430ADC12Settings_t settings)
  {
    result_t res = FAIL;
    adc12memctl_t memctl = {  inch: settings.inputChannel,
                              sref: settings.referenceVoltage,
                              eos: 0 };
    #if CHECKARGS
    if (num >= uniqueCount("MSP430ADC12"))
      return FAIL;
    #endif
    atomic 
    {
      if (cmode == ADC_IDLE || owner != num){
	configureAdcPin( settings.inputChannel );
        adc12settings[num].refVolt2_5 = settings.refVolt2_5;
        adc12settings[num].gotRefVolt = 0;
        adc12settings[num].clockSourceSHT = settings.clockSourceSHT;
        adc12settings[num].clockSourceSAMPCON = settings.clockSourceSAMPCON;   
        adc12settings[num].clockDivSAMPCON = settings.clockDivSAMPCON;
        adc12settings[num].clockDivSHT = settings.clockDivSHT;
        adc12settings[num].sampleHoldTime = settings.sampleHoldTime;
        adc12settings[num].memctl = memctl;
        res = SUCCESS;
      }
    }
    return res;
  }

  command result_t ADCMultiple.bind[uint8_t num](MSP430ADC12Settings_t settings)
  {
    return (call ADCSingle.bind[num](settings));
  }

  msp430ADCresult_t getRefVolt(uint8_t num)
  {
    msp430ADCresult_t adcResult = MSP430ADC12_SUCCESS;
    result_t vrefResult;
    adc12memctl_t memctl = adc12settings[num].memctl;
    
    if (memctl.sref == REFERENCE_VREFplus_AVss ||
        memctl.sref == REFERENCE_VREFplus_VREFnegterm)
    {
      if(adc12settings[num].gotRefVolt == 0) {
        if (adc12settings[num].refVolt2_5)
          vrefResult = call RefVolt.get(REFERENCE_2_5V);
        else
          vrefResult = call RefVolt.get(REFERENCE_1_5V);
      } else 
        vrefResult = SUCCESS;
      if (vrefResult != SUCCESS)
      {
        adcResult = MSP430ADC12_FAIL;
      } else {
        adc12settings[num].gotRefVolt = 1;
        if (call RefVolt.getState() == REFERENCE_UNSTABLE)
          adcResult = MSP430ADC12_DELAYED;
      }
    }
    return adcResult;
  }
    
  result_t releaseRefVolt(uint8_t num)
  {
    if (adc12settings[num].gotRefVolt == 1){
      call RefVolt.release();
      adc12settings[num].gotRefVolt = 0;
      return SUCCESS;
    }
    return FAIL;
  }

  result_t prepareTimerA(uint16_t interval, uint16_t csSAMPCON, uint16_t cdSAMPCON)
  {
    if (call TimerExclusive.get() == SUCCESS) {
      return call TimerExclusive.prepareTimer(interval, csSAMPCON, cdSAMPCON);
    }
    return FAIL;
  }
    
  result_t startTimerA()
  {
    return call TimerExclusive.startTimer();
  }    
 
  msp430ADCresult_t newRequest(uint8_t req, uint8_t num, void *dataDest, uint16_t length, uint16_t jiffies)
  {
    bool access = FALSE;
    msp430ADCresult_t res = MSP430ADC12_FAIL;
    // Workaround by Cory Sharp
    // since msp430 is a 16-bit platform, make num a signed
    // 16-bit integer to avoid "warning: comparison is always true due to
    // limited range of data type" if it happens that (num >= 0) is tested.
    const int16_t num16 = num;
    
    // 2005/Aug: Ben Greenstein:
    // needed interrupts enabled flag for no interrupt mode for DMA
    bool interrupts_enabled = (req & ADC_INTERRUPT_DISABLED ? 0: 1);
    req &= ~ADC_INTERRUPT_DISABLED; // hack -- clear bit so rest of code isn't confused

    #if CHECKARGS
    if ( num16 >= uniqueCount("MSP430ADC12") || (!reserved &&
        (!length || (req == REPEAT_SEQUENCE_OF_CHANNELS && length > 16)) ) )
      return MSP430ADC12_FAIL;
    
    // since timerA is used in upmode with OUTMOD=7, i.e. reset/set,
    // jiffies cannot be 1 (otherwise reset and set is performed simultanously).
    // it cannot be 2 either - TAR rollover with TACCR1=0 
    // does reset OUT0 signal. But with timerA running at
    // 1MHz jiffies < 10 will probably (depending on ADC12CLK) not work 
    // anyway because of too long sample-hold-time. 
    if (jiffies == 1 || jiffies == 2)
      return MSP430ADC12_FAIL;
    #endif
     
    if (reserved & RESERVED)
      if (!(reserved & VREF_WAIT) && owner == num16 && cmode == req){
        call HPLADC12.startConversion();
        if (reserved & TIMER_USED)
          startTimerA(); // go!
        reserved = ADC_IDLE;
        return MSP430ADC12_SUCCESS;
      } else
        return MSP430ADC12_FAIL;
   
    atomic {
      if (cmode == ADC_IDLE){
        owner = num16;
        cmode = SEQUENCE_OF_CHANNELS;
        access = TRUE;
      }
    }

    if (access){
      res = MSP430ADC12_SUCCESS;
      switch (getRefVolt(num16))
      {
        case MSP430ADC12_FAIL: 
          cmode = ADC_IDLE;
          res = MSP430ADC12_FAIL;
          break;
        case MSP430ADC12_DELAYED:
          // VREF is unstable, simulate reserve call and
          // start conversion in RefVolt.isStable later
          req |= (RESERVED | VREF_WAIT);
          res = MSP430ADC12_DELAYED;               
          vrefWait = TRUE;
          // fall through
        case MSP430ADC12_SUCCESS: 
          {
            int8_t i, memctlsUsed = length;
            uint16_t mask = 1;
            adc12memctl_t lastMemctl = adc12settings[num16].memctl;
            uint16_t ctl0 = ADC12CTL0_TIMER_TRIGGERED;
            adc12ctl1_t ctl1 = {adc12busy:0, conseq:1, 
                                adc12ssel:adc12settings[num16].clockSourceSHT, 
                                adc12div:adc12settings[num16].clockDivSHT, issh:0, shp:1, 
                                shs:1, cstartadd:0};
            if (length > 16){
              ctl1.conseq = 3; // repeat sequence mode
              memctlsUsed = 16;
            }
            bufPtr = dataDest;
            bufLength = length;
            bufOffset = 0;     
            
            // initialize ADC registers
            call HPLADC12.disableConversion();            
            if (jiffies == 0){
              ctl0 = ADC12CTL0_AUTO_TRIGGERED;
              ctl1.shs = 0;  // ADC12SC starts the conversion
            }
            for (i=0; i<memctlsUsed-1; i++)
              call HPLADC12.setMemControl(i, adc12settings[num16].memctl);
            lastMemctl.eos = 1;  
            call HPLADC12.setMemControl(i, lastMemctl);
            call HPLADC12.setSHT(adc12settings[num16].sampleHoldTime);
            if (interrupts_enabled)
	      call HPLADC12.setIEFlags(mask << i);
            call HPLADC12.setControl0_IgnoreRef(*(adc12ctl0_t*) &ctl0);
            
            if (req & SINGLE_CHANNEL){
                ctl1.conseq = 0; // single channel single conversion
                cmode = SINGLE_CHANNEL;
            } else if (req & REPEAT_SINGLE_CHANNEL){
                ctl1.conseq = 2; // repeat single channel
                cmode = REPEAT_SINGLE_CHANNEL;
            } else if (req & REPEAT_SEQUENCE_OF_CHANNELS){
                ctl1.conseq = 3; // repeat sequence of channels
                cmode = REPEAT_SEQUENCE_OF_CHANNELS;
            }
            call HPLADC12.setControl1(ctl1);
            
            if (req & RESERVED){
              // reserve ADC now
              reserved = req;
              if (jiffies != 0){
		if (prepareTimerA(jiffies, adc12settings[num16].clockSourceSAMPCON, adc12settings[num16].clockDivSAMPCON) == SUCCESS) {
		  reserved |= TIMER_USED;
		}
		else {
		  // couldn't get the timer, so return fail
		  cmode = ADC_IDLE;
		  res = MSP430ADC12_FAIL;
		  break;
		}
              }
            } else {
               // trigger first conversion now
               call HPLADC12.startConversion();
               if (jiffies != 0){
                 if (prepareTimerA(jiffies, adc12settings[num16].clockSourceSAMPCON, adc12settings[num16].clockDivSAMPCON) == SUCCESS) {
		   startTimerA(); // go!
		 }
		 else {
		   // couldn't get the timer, so return fail
		   cmode = ADC_IDLE;
		   res = MSP430ADC12_FAIL;
		   break;
		 }
               }
            }
            res = MSP430ADC12_SUCCESS;
            break;
          }
      } // of switch
    }
    return res;
  }

  
  result_t unreserve(uint8_t num)
  {
    if (reserved & RESERVED && owner == num){
      cmode = reserved = ADC_IDLE;
      return SUCCESS;
    }
    return FAIL;
  }
  
  async command msp430ADCresult_t ADCSingle.getData[uint8_t num]()
  {
    return newRequest(SINGLE_CHANNEL, num, 0, 1, 0);
  }

  async command msp430ADCresult_t ADCSingle.getDataRepeat[uint8_t num](uint16_t jiffies)
  {
    return newRequest(REPEAT_SINGLE_CHANNEL, num, 0, 1, jiffies);
  }

  async command result_t ADCSingle.reserve[uint8_t num]()
  {
    if (newRequest(RESERVED | SINGLE_CHANNEL, num, 0, 1, 0) == MSP430ADC12_SUCCESS)
      return SUCCESS;
    return FAIL;
  }

  async command result_t ADCSingle.reserveRepeat[uint8_t num](uint16_t jiffies)
  {
    if (newRequest(RESERVED | REPEAT_SINGLE_CHANNEL, num, 0, 1, jiffies) == 
        MSP430ADC12_SUCCESS)
      return SUCCESS;
    return FAIL;
  }

  async command result_t ADCSingle.unreserve[uint8_t num]()
  {
    return unreserve(num);
  }
  
  async command msp430ADCresult_t ADCSingle.startSampling[uint8_t num](uint16_t jiffies){
    return newRequest(REPEAT_SINGLE_CHANNEL | ADC_INTERRUPT_DISABLED, num, 0, 1, jiffies);
  }

  async command void ADCSingle.pauseSampling[uint8_t num](){
    call HPLADC12.stopConversion();
  }
  async command void ADCSingle.resumeSampling[uint8_t num](){
    /* setConversion mode also asserts MSC. ADC12CTL0 |= MSC might
       not be necessary.
    */
    call HPLADC12.setConversionMode(REPEAT_SINGLE_CHANNEL);
    call HPLADC12.resetMSC();
    call HPLADC12.enableConversion();
  }
  
  async command void ADCSingle.stopSampling[uint8_t num](){
    stopConversion();
  }

  async command msp430ADCresult_t ADCMultiple.startSampling[uint8_t num](uint16_t jiffies){
    return newRequest(REPEAT_SEQUENCE_OF_CHANNELS | ADC_INTERRUPT_DISABLED, num, 0, 16, jiffies);
  }

  async command void ADCMultiple.pauseSampling[uint8_t num](){
    call ADCSingle.pauseSampling[num]();
  }
  async command void ADCMultiple.resumeSampling[uint8_t num](){
    call ADCSingle.resumeSampling[num]();
  }

  async command void ADCMultiple.stopSampling[uint8_t num](){
    stopConversion();
  }

  async command msp430ADCresult_t ADCMultiple.getData[uint8_t num](uint16_t *buf, 
                                             uint16_t length, uint16_t jiffies)
  {
    return newRequest(SEQUENCE_OF_CHANNELS, num, buf, length, jiffies);
  }
  
  async command msp430ADCresult_t ADCMultiple.getDataRepeat[uint8_t num](uint16_t *buf, 
                                             uint8_t length, uint16_t jiffies) 
  {
    return newRequest(REPEAT_SEQUENCE_OF_CHANNELS, num, buf, length, jiffies);
  }

  async command result_t ADCMultiple.reserve[uint8_t num](uint16_t *buf, 
                                      uint16_t length, uint16_t jiffies)
  {
    if (newRequest(SEQUENCE_OF_CHANNELS | RESERVED, num, buf, length, jiffies)
        == MSP430ADC12_SUCCESS)
      return SUCCESS;
    return FAIL;
  }
  
  async command result_t ADCMultiple.reserveRepeat[uint8_t num](uint16_t *buf,
                                            uint16_t length, uint16_t jiffies)
  {
    if (newRequest(REPEAT_SEQUENCE_OF_CHANNELS | RESERVED, num, buf, length, jiffies)
        == MSP430ADC12_SUCCESS)
      return SUCCESS;
    return FAIL;
  }
  
  async command result_t  ADCMultiple.unreserve[uint8_t num]()
  {
    return unreserve(num);
  }
     
  default async event result_t ADCSingle.dataReady[uint8_t num](uint16_t data)
  {
    return FAIL;
  }
  default async event uint16_t* ADCMultiple.dataReady[uint8_t num](uint16_t *buf,
                                                          uint16_t length)
  {
    return (uint16_t*) 0;
  }

  event void RefVolt.isStable(RefVolt_t vref)
  {
    if (vrefWait){
      call HPLADC12.startConversion();
      if (reserved & TIMER_USED)
        startTimerA(); // go!
      reserved = ADC_IDLE;
      vrefWait = FALSE;
    }
  }
    
  void stopConversion()
  {
    call TimerExclusive.stopTimer();
    call TimerExclusive.release();
    call HPLADC12.stopConversion();
    call HPLADC12.setIEFlags(0);
    call HPLADC12.resetIFGs();
    if (adc12settings[owner].gotRefVolt)
      releaseRefVolt(owner);
    cmode = ADC_IDLE;  // enable access to ADC, owner now invalid
  }
  
  async event void HPLADC12.converted(uint8_t number){
    switch (cmode) 
    { 
       case SINGLE_CHANNEL:
            {
              volatile uint8_t ownerTmp = owner;
              stopConversion();
              signal ADCSingle.dataReady[ownerTmp](call HPLADC12.getMem(0));
            }
            break;
       case REPEAT_SINGLE_CHANNEL:
            if (signal ADCSingle.dataReady[owner](call HPLADC12.getMem(0)) == FAIL)
              stopConversion();
            break;
        case SEQUENCE_OF_CHANNELS:
            {
              uint16_t i = 0, length = (bufLength - bufOffset > 16) ? 16 : bufLength - bufOffset;
              do {
                *bufPtr++ = call HPLADC12.getMem(i);
              } while (++i < length);
               
              bufOffset += length;
              
              if (bufLength - bufOffset > 15)
                return;
              else if (bufLength - bufOffset > 0){
                adc12memctl_t memctl = call HPLADC12.getMemControl(0);
                memctl.eos = 1;
                call HPLADC12.setMemControl(bufLength - bufOffset, memctl);
              } else {
                stopConversion();
                signal ADCMultiple.dataReady[owner](bufPtr - bufLength, bufLength);
              }
            }
            break;
        case REPEAT_SEQUENCE_OF_CHANNELS:
            {
              uint8_t i = 0;
              do {
                *bufPtr++ = call HPLADC12.getMem(i);
              } while (++i < bufLength);
              if ((bufPtr = signal ADCMultiple.dataReady[owner](bufPtr-bufLength, bufLength)) == 0)
                stopConversion();
              break;
            }
        default:
            {
              //volatile uint16_t data = call HPLADC12.getMem(number);
              call HPLADC12.resetIFGs();
            }
            break;
      } // switch
  }
  
  async event void HPLADC12.memOverflow(){}
  async event void HPLADC12.timeOverflow(){}

  event void TimerExclusive.free() { 
    // currently doesn't do a delay on waiting for the timer
    // if someone else has it, we have to wait until another time
  }

}


--- NEW FILE: MSP430ADC12Multiple.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */

interface MSP430ADC12Multiple
{    
  /**
    * Binds the interface instance to the values specified in
    * <code>settings</code>. This command must be called once 
    * before the first call to <code>getData</code> or 
    * <code>getDataRepeat</code> is made (a good spot is  
    * StdControl.init). 
    * It can also be used to change settings later on.
    *
    * @return FAIL if interface parameter is out of bounds or
    * conversion in progress for this interface, SUCCESS otherwise
    */
  //command result_t bind(MSP430ADC12Settings_t settings, MSP430ADC12PinSettings_t pinSetting);
  command result_t bind(MSP430ADC12Settings_t settings);

  /**
    * Initiates a series of, i.e. multiple successive conversions. 
    * The size of a series must match and is only bounded by the 
    * size of the buffer. There is one event <code>dataReady</code>
    * after the buffer is filled with conversion results. 
    * Successive conversions are performed as quickly as possible if
    * <code>jiffies</code> equals zero. Otherwise <code>jiffies</code> 
    * define the time between successive conversions in terms of 
    * clock ticks of settings.clockSourceSAMPCON and input divider 
    * settings.clockDivSAMPCON specified in <code>bind()</code>.  
    * If VREF was chosen as reference voltage in <code>bind</code> 
    * and the voltage generator has not yet reached a stable level,
    * <code>ADC_QUEUED</code> is returned and the conversion process 
    * starts as soon as VREF becomes stable (max. 17ms).
    *
    * @param buf Buffer to store the conversion results. Ignored
    * if <code>reserve</code> was called successfully before,
    * because then those settings are applicable.
    *
    * @param length The size of the buffer and number of conversions.
    * Ignored if <code>reserve</code> was called successfully before,
    * because then those settings are applicable.
    *
    * @param jiffies TimerA clock ticks between the single conversions
    * of the series. Ignored if <code>reserve</code> was called successfully 
    * before, because then those settings are applicable.
    *
    * @return MSP430ADC12_FAIL the adc is busy 
    * MSP430ADC12_SUCCESS successfully triggered conversion
    * MSP430ADC12_DELAYED conversion starts as soon as VREF becomes stable.
    */
  async command msp430ADCresult_t getData(uint16_t *buf, uint16_t length, uint16_t jiffies);

  /**
    * Initiates a sequence of conversions in repeat mode. The size
    * of a sequence is less or equal 16. The event 
    * <code>dataReadyRepeat</code> will be signalled after each 
    * sequence of conversions has finished. 
    * Successive conversions within the sequence are performed as quickly 
    * as possible if <code>jiffies</code> equals zero. Otherwise <code>jiffies</code> 
    * define the time between successive conversions in terms of 
    * clock ticks of settings.clockSourceSAMPCON and input divider 
    * settings.clockDivSAMPCON specified in <code>bind()</code>.  
    * If VREF was chosen as reference voltage in <code>bind</code> 
    * and the voltage generator has not yet reached a stable level,
    * <code>ADC_QUEUED</code> is returned and the conversion process 
    * starts as soon as VREF becomes stable (max. 17ms).
    * Repeat mode is stopped when the eventhandler 
    * <code>dataReadyRepeat</code> returns a nullpointer. 
    *
    * @param buf Buffer to store the conversion results.  
    * @param length The size of the buffer and number of conversions,
    * must be <= 16
    *
    * @return MSP430ADC12_FAIL the adc is busy  
    * MSP430ADC12_SUCCESS successfully triggered conversion
    * MSP430ADC12_DELAYED conversion starts as soon as VREF becomes stable.
    */
  async command msp430ADCresult_t getDataRepeat(uint16_t *buf, uint8_t length, uint16_t jiffies);

  /**
    * Reserves the ADC for one single conversion.  If this call  
    * succeeds the next call to <code>getData</code> will also succeed 
    * and the corresponding conversion will then be started with a
    * minimum latency. Until then all other commands will fail.
    *
    * @return SUCCESS reservation successful
    * FAIL otherwise 
    */
  async command result_t reserve(uint16_t *buf, uint16_t length, uint16_t jiffies);

  /**
    * Reserves the ADC for repeated conversions.  If this call  
    * succeeds the next call to <code>getDataRepeat/code> will also succeed 
    * and the corresponding conversion will then be started with a
    * minimum latency. Until then all other commands will fail.
    *
    * @return SUCCESS reservation successful
    * FAIL otherwise 
    */
  async command result_t reserveRepeat(uint16_t *buf, uint16_t length, uint16_t jiffies);

  /**
    * Cancels the reservation made by <code>reserve</code> or
    * <code>reserveRepeat</code>.
    *
    * @return SUCCESS un-reservation successful
    * FAIL no reservation active 
    */
  async command result_t unreserve();

  /**
    * Conversion results from call to <code>getData</code> or 
    * <code>getDataRepeat</code> are ready. In the first case
    * the returned value is ignored, in the second it points
    * to the buffer where the next sequence of conversions is 
    * to be stored.
    *
    * @param buf Buffer address of conversion results, it is
    * identical to the <code>buf</code> passed to
    * <code>getData</code> or <code>getDataRepeat</code>. 
    * In each word the lower 12 bits are the actual 
    * result and the upper 4 bits are zero.
    *
    * @param length The size of the buffer and number of conversions,
    * it is identical to the <code>length</code> passed to
    * <code>getData</code> or <code>getDataRepeat</code>.
    *
    * @return Points to the buffer where to store the next
    * sequence of conversions. The buffer must be of size
    * <code>length</code>, it can, of course, be identical to 
    * <code>buf</code> (then the previous results will be
    * overwritten).
    * A return value of 0 (nullpointer) will stop repeat mode, so
    * that no further conversions are performed. 
    */
  async event uint16_t* dataReady(uint16_t *buf, uint16_t length);

  /**
   * Start sampling the ADC.  SMCLK is used for the sampling,
   * so 1 jiffy = 1 us on msp430 platforms
   *
   * startSampling() should be used INSTEAD of getData() when
   * the msp430 ADC is used in conjunction with the DMA (ie, no need
   * for the ADC dataReady() events because the DMA will handle them
   * instead)
   *
   * Do NOT use startSampling() without the DMA
   *
   * @ return MSP430ADC12_SUCCESS if sampling commences
   */
  async command msp430ADCresult_t startSampling(uint16_t jiffies);

  /**
   * Stop current sampling.
   *
   * If sampling is in process, it is halted.  To be used in conjunction
   * with startSampling and the DMA controller
   *
   * Do NOT use stopSampling() without the DMA
   */
  async command void stopSampling();

  /**
   * Pause current sampling. If sampling is in process, it is halted.
   * To be used in conjunction with resumeSampling and the DMA
   * controller. Does NOT release timer resource, so it should be used
   * only when you expect to resume very soon.
   *
   * This command should be used to pause the ADC's current operation
   * while the DMA is loaded with new settings.
   *
   * Do NOT use pauseSampling() without the DMA
   *
   */
  async command void pauseSampling();

  /**
   * Resume current sampling after it has been paused. Pause and resume
   * are designed to be as lightweight as possible so that as few adc
   * samples as possible (if any) are lost between a pause and resume.
   * 
   * This command should resume sampling after giving the DMA controller
   * a new buffer to store the results.
   *
   * Do NOT use resumeSampling() without the DMA
   *
   */
  async command void resumeSampling();
}


--- NEW FILE: MSP430ADC12Single.nc ---
/*
 * Copyright (c) 2004, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/09/28 10:41:11 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
        
includes  MSP430ADC12;
interface MSP430ADC12Single
{     
  /**
    * Binds the interface instance to the values specified in
    * <code>settings</code>. This command must be called once 
    * before the first call to <code>getData</code> or 
    * <code>getDataRepeat</code> is made (a good spot is  
    * StdControl.init). 
    * It can also be used to change settings later on.
    *
    * @return FAIL if interface parameter is out of bounds or
    * conversion in progress for this interface, SUCCESS otherwise
    */
 // command result_t bind(MSP430ADC12Settings_t settings, MSP430ADC12PinSettings_t pinSetting);
  command result_t bind(MSP430ADC12Settings_t settings);

  /**
    * Initiates one single conversion. After the conversion is 
    * performed the event <code>dataReady</code> is signalled 
    * with the conversion result.
    * If VREF was chosen as reference voltage in <code>bind</code> 
    * and the voltage generator has not yet reached a stable level,
    * <code>MSP430ADC12_DELAYED</code> is returned and the conversion  
    * process starts as soon as VREF becomes stable (max. 17ms).
    *
    * @return MSP430ADC12_FAIL the adc is busy  
    * MSP430ADC12_SUCCESS successfully triggered conversion
    * MSP430ADC12_DELAYED conversion starts as soon as VREF becomes stable.
    */
  async command msp430ADCresult_t getData();

  /**
    * Initiates conversions in repeat mode, ie. continuously.
    * After each conversion is performed an event <code>dataReady</code>
    * is signalled with the conversion result until the eventhandler 
    * returns <code>FAIL</code>.
    * Successive conversions are performed as quickly as possible if
    * <code>jiffies</code> equals zero. Otherwise <code>jiffies</code> 
    * define the time between successive conversions in terms of 
    * clock ticks of settings.clockSourceSAMPCON and input divider 
    * settings.clockDivSAMPCON specified in <code>bind()</code>.  
    * If VREF was chosen as reference voltage in <code>bind</code> 
    * and the voltage generator has not yet reached a stable level,
    * <code>MSP430ADC12_DELAYED</code> is returned and the conversion  
    * process starts as soon as VREF becomes stable (max. 17ms).
    *
    * @return MSP430ADC12_FAIL the adc is busy  
    * MSP430ADC12_SUCCESS successfully triggered first conversion
    * MSP430ADC12_DELAYED conversion starts as soon as VREF becomes stable.
    */
  async command msp430ADCresult_t getDataRepeat(uint16_t jiffies);   
  
  /**
    * Reserves the ADC for one single conversion.  If this call  
    * succeeds the next call to <code>getData</code> will also succeed 
    * and the corresponding conversion will then be started with a
    * minimum latency. Until then all other commands will fail.
    *
    * @return SUCCESS reservation successful
    * FAIL otherwise 
    */
  async command result_t reserve();

  /**
    * Reserves the ADC for repeated conversions.  If this call  
    * succeeds the next call to <code>getDataRepeat/code> will also succeed 
    * and the corresponding conversion will then be started with a
    * minimum latency. Until then all other commands will fail.
    *
    * @return SUCCESS reservation successful
    * FAIL otherwise 
    */
  async command result_t reserveRepeat(uint16_t jiffies);

  /**
    * Cancels the reservation made by <code>reserve</code> or
    * <code>reserveRepeat</code>.
    *
    * @return SUCCESS un-reservation successful
    * FAIL no reservation active 
    */
  async command result_t unreserve();

  /**
    * Conversion result from call to <code>getData</code> or 
    * <code>getDataRepeat</code> is ready. In the first case
    * the returned value is ignored, in the second it defines
    * whether any further conversions will be made or not.
    *
    * @param data The conversion result. The lower 12 bits
    * are the actual result and the upper 4 bits are zero.
    *
    * @return SUCCESS continues sampling in repeat mode
    * FAIL stops further conversions in repeat mode 
    */
  async event result_t dataReady(uint16_t data);

  /**
   * Start sampling the ADC.  SMCLK is used for the sampling,
   * so 1 jiffy = 1 us on msp430 platforms
   *
   * startSampling() should be used INSTEAD of getData() when
   * the msp430 ADC is used in conjunction with the DMA (ie, no need
   * for the ADC dataReady() events because the DMA will handle them
   * instead)
   *
   * Do NOT use startSampling() without the DMA
   *
   * @ return MSP430ADC12_SUCCESS if sampling commences
   */
  async command msp430ADCresult_t startSampling(uint16_t jiffies);

  /**
   * Stop current sampling.
   *
   * If sampling is in process, it is halted.  To be used in conjunction
   * with startSampling and the DMA controller
   *
   * Do NOT use stopSampling() without the DMA
   */
  async command void stopSampling();

  /**
   * Pause current sampling. If sampling is in process, it is halted.
   * To be used in conjunction with resumeSampling and the DMA
   * controller. Does NOT release timer resource, so it should be used
   * only when you expect to resume very soon.
   *
   * This command should be used to pause the ADC's current operation
   * while the DMA is loaded with new settings.
   *
   * Do NOT use pauseSampling() without the DMA
   *
   */
  async command void pauseSampling();

  /**
   * Resume current sampling after it has been paused. Pause and resume
   * are designed to be as lightweight as possible so that as few adc
   * samples as possible (if any) are lost between a pause and resume.
   * 
   * This command should resume sampling after giving the DMA controller
   * a new buffer to store the results.
   *
   * Do NOT use resumeSampling() without the DMA
   *
   */
  async command void resumeSampling();

}


--- NEW FILE: Voltage.h ---
// $Id: Voltage.h,v 1.1 2005/09/28 10:41:11 jpolastre Exp $

/*									tab:2
 *
 *
 * "Copyright (c) 2000-2005 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."
 *
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

#ifndef __VOLTAGE_H__
#define __VOLTAGE_H__

enum {
  TOS_ADC_VOLTAGE_PORT = unique("ADCPort"),
};

#endif

--- NEW FILE: VoltageM.nc ---
// $Id: VoltageM.nc,v 1.1 2005/09/28 10:41:11 jpolastre Exp $

/*									tab:2
 *
 *
 * "Copyright (c) 2000-2005 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."
 *
 */

/**
 * Module for measuring supply voltage (Vcc) on telos. Value returned
 * by dataReady() is in millivolts.
 *
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

module VoltageM {
  provides {
    interface ADC as Voltage;
    interface StdControl;
  }
  uses {
    interface ADC;
    interface ADCControl;
  }
}

implementation {

  enum {
    ERROR_VOLTAGE = 0xffff,
  };

  enum {
    VOLTAGE_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT_1_5 = ASSOCIATE_ADC_CHANNEL(
      INTERNAL_VOLTAGE,
      REFERENCE_VREFplus_AVss,
      REFVOLT_LEVEL_1_5),
    VOLTAGE_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT_2_5 = ASSOCIATE_ADC_CHANNEL(
      INTERNAL_VOLTAGE,
      REFERENCE_VREFplus_AVss,
      REFVOLT_LEVEL_2_5),
  };

  uint8_t state;
  uint16_t voltage;

  enum {
    S_IDLE,
    S_GET_DATA_1_5,
    S_GET_DATA_2_5,
  };

  command result_t StdControl.init() {
    atomic state = S_IDLE;
    return SUCCESS;
  }

  command result_t StdControl.start() {
    return call ADCControl.init();
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }

  void signalReady(uint16_t v) {
    atomic state = S_IDLE;
    signal Voltage.dataReady(v);
  }

  task void signalReadyTask() {
    uint32_t tmpVoltage;
    // DVcc = (ADCCounts/4096)*Vref*2
    atomic {
      tmpVoltage = voltage;
      switch(state) {
      case S_GET_DATA_1_5: tmpVoltage *= 3000; break;
      case S_GET_DATA_2_5: tmpVoltage *= 5000; break;
      }
      tmpVoltage >>= 12;
    }
    signalReady(tmpVoltage);
  }

  task void sample() {

    result_t result;
    uint8_t tmpState;
    uint16_t port;

    atomic tmpState = state;

    port = (tmpState == S_GET_DATA_1_5) ?
      VOLTAGE_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT_1_5 :
      VOLTAGE_ACTUAL_ADC_INTERNAL_VOLTAGE_PORT_2_5;
    
    result = call ADCControl.bindPort(TOS_ADC_VOLTAGE_PORT, port);
    result = rcombine(call ADC.getData(), result);
    
    if (result == FAIL)
      signalReady(ERROR_VOLTAGE);

  }

  async command result_t Voltage.getData() {

    uint8_t tmpState;

    atomic tmpState = state;

    if (tmpState != S_IDLE)
      return FAIL;

    atomic state = S_GET_DATA_1_5;

    if (post sample() == FAIL)
      return FAIL;

    return SUCCESS;

  }
  
  /*
   * Not supported.
   */
  async command result_t Voltage.getContinuousData() {
    return FAIL;
  }

  async event result_t ADC.dataReady(uint16_t data) {

    result_t result;

    if (data == 0xfff) {
      atomic state = S_GET_DATA_2_5;
      result = post sample();
    }
    else {
      atomic voltage = data;
      result = post signalReadyTask();
    }

    if (result == FAIL)
      signalReady(ERROR_VOLTAGE);
      
    return SUCCESS;

  }

}



More information about the Tinyos-commits mailing list