Updated README.
#define MSP430ADC12_H
#include "Msp430RefVoltGenerator.h"
-#define P6PIN_AUTO_CONFIGURE
+#define ADC12_TIMERA_ENABLED
+#define ADC12_P6PIN_AUTO_CONFIGURE
+#define ADC12_CHECK_ARGS
+//#define ADC12_ONLY_WITH_DMA
+
+// for HIL clients
#define REF_VOLT_AUTO_CONFIGURE
-#define CHECK_ARGS
-
+
typedef struct {
- // see README.txt for a more detailed explanation
+ // see README.txt
unsigned int inch: 4; // input channel
unsigned int sref: 3; // reference voltage
unsigned int ref2_5v: 1; // reference voltage level
typedef struct
{
- // see README.txt for a more detailed explanation
+ // see README.txt
volatile unsigned
inch: 4, // input channel
sref: 3, // reference voltage
void prepareTimerA(uint16_t interval, uint16_t csSAMPCON, uint16_t cdSAMPCON)
{
+#ifdef ADC12_TIMERA_ENABLED
msp430_compare_control_t ccResetSHI = {
ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0,
outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 };
call ControlA0.setControl(ccResetSHI);
call CompareA0.setEvent(interval-1);
call CompareA1.setEvent((interval-1)/2);
+#endif
}
void startTimerA()
{
+#ifdef ADC12_TIMERA_ENABLED
msp430_compare_control_t ccSetSHI = {
ccifg : 0, cov : 0, out : 1, cci : 0, ccie : 0,
outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 };
//call ControlA1.setControl(ccResetSHI);
call ControlA1.setControl(ccRSOutmod);
call TimerA.setMode(MSP430TIMER_UP_MODE); // go!
+#endif
}
void configureAdcPin( uint8_t inch )
{
-#ifdef P6PIN_AUTO_CONFIGURE
+#ifdef ADC12_P6PIN_AUTO_CONFIGURE
switch (inch)
{
case 0: call Port60.selectModuleFunc(); call Port60.makeInput(); break;
void resetAdcPin( uint8_t inch )
{
-#ifdef P6PIN_AUTO_CONFIGURE
+#ifdef ADC12_P6PIN_AUTO_CONFIGURE
switch (inch)
{
case 0: call Port60.selectIOFunc(); break;
const msp430adc12_channel_config_t *config)
{
error_t result = ERESERVE;
-#ifdef CHECK_ARGS
+#ifdef ADC12_CHECK_ARGS
if (!config)
return EINVAL;
#endif
uint16_t jiffies)
{
error_t result = ERESERVE;
-#ifdef CHECK_ARGS
+#ifdef ADC12_CHECK_ARGS
if (!config || jiffies == 1 || jiffies == 2)
return EINVAL;
#endif
uint16_t *buf, uint16_t length, uint16_t jiffies)
{
error_t result = ERESERVE;
-#ifdef CHECK_ARGS
+#ifdef ADC12_CHECK_ARGS
if (!config || !buf || !length || jiffies == 1 || jiffies == 2)
return EINVAL;
#endif
uint16_t *buf, uint8_t length, uint16_t jiffies)
{
error_t result = ERESERVE;
-#ifdef CHECK_ARGS
+#ifdef ADC12_CHECK_ARGS
if (!config || !buf || !length || length > 16 || jiffies == 1 || jiffies == 2)
return EINVAL;
#endif
uint16_t numSamples, uint16_t jiffies)
{
error_t result = ERESERVE;
-#ifdef CHECK_ARGS
+#ifdef ADC12_CHECK_ARGS
if (!config || !memctl || !numMemctl || numMemctl > 15 || !numSamples ||
!buf || jiffies == 1 || jiffies == 2 || numSamples % (numMemctl+1) != 0)
return EINVAL;
void stopConversion()
{
uint8_t i;
+#ifdef ADC12_TIMERA_ENABLED
if (state & USE_TIMERA)
call TimerA.setMode(MSP430TIMER_STOP_MODE);
+#endif
resetAdcPin( (call HplAdc12.getMCtl(0)).inch );
if (state & MULTI_CHANNEL){
ADC12IV = 0; // clear any pending overflow
else
signal Overflow.conversionTimeOverflow[clientID]();
}
-#ifndef MSP430ADC12_ONLY_DMA
switch (state & CONVERSION_MODE_MASK)
{
case SINGLE_DATA:
stopConversion();
break;
}
+#ifndef ADC12_ONLY_WITH_DMA
case MULTI_CHANNEL:
{
uint16_t i = 0;
stopConversion();
break;
}
- } // switch
#endif
+ } // switch
}
default async event error_t SingleChannel.singleDataReady[uint8_t id](uint16_t data)
interface AsyncStdControl as DMAExtension[uint8_t id];
}
} implementation {
- components Msp430Adc12ImplP, HplAdc12P, Msp430TimerC, MainC, HplMsp430GeneralIOC,
+ components Msp430Adc12ImplP, HplAdc12P, MainC,
new SimpleRoundRobinArbiterC(MSP430ADC12_RESOURCE) as Arbiter;
Resource = Arbiter;
Msp430Adc12ImplP.Init <- MainC;
Msp430Adc12ImplP.ADCArbiterInfo -> Arbiter;
Msp430Adc12ImplP.HplAdc12 -> HplAdc12P;
+
+#ifdef ADC12_P6PIN_AUTO_CONFIGURE
+ components HplMsp430GeneralIOC;
Msp430Adc12ImplP.Port60 -> HplMsp430GeneralIOC.Port60;
Msp430Adc12ImplP.Port61 -> HplMsp430GeneralIOC.Port61;
Msp430Adc12ImplP.Port62 -> HplMsp430GeneralIOC.Port62;
Msp430Adc12ImplP.Port65 -> HplMsp430GeneralIOC.Port65;
Msp430Adc12ImplP.Port66 -> HplMsp430GeneralIOC.Port66;
Msp430Adc12ImplP.Port67 -> HplMsp430GeneralIOC.Port67;
+#endif
+#ifdef ADC12_TIMERA_ENABLED
+ components Msp430TimerC;
Msp430Adc12ImplP.TimerA -> Msp430TimerC.TimerA;
Msp430Adc12ImplP.ControlA0 -> Msp430TimerC.ControlA0;
Msp430Adc12ImplP.ControlA1 -> Msp430TimerC.ControlA1;
Msp430Adc12ImplP.CompareA0 -> Msp430TimerC.CompareA0;
Msp430Adc12ImplP.CompareA1 -> Msp430TimerC.CompareA1;
+#endif
}
====================================================================
An application that is written for an MSP430-based platform like 'eyesIFX' or
-'telosb' can access the ADC12 in a more efficient way to, for example, do
-high-frequency sampling through the Msp430Adc12SingleChannel interface. On the
-MSP430 two additional hardware modules may become relevant when the ADC12 is
+'telosb' can access the ADC12 in a more efficient way via two interfaces: (1)
+the Msp430Adc12SingleChannel allows to perform one or more ADC conversions on a
+single channel with a specified sampling frequency and (2) the
+Msp430Adc12MultiChannel allows to sample a group of up to 16 different ADC
+channels "at once" (with minimum latency) and in addition define a sampling
+frequency for the whole group (useful for multi-channel accelerometers, etc.).
+On the MSP430 two additional hardware modules may play a role when the ADC12 is
used: the internal reference voltage generator and the DMA controller.
The voltage generator outputs stabilized voltage of 1.5 V or 2.5 V, which may
clients are present. Second, one must not forget to wire the AdcConfigure
interface to the Msp430Adc12ClientAutoRVGC or Msp430Adc12ClientAutoDMA_RVGC
component in addition to configuring the ADC through the
-Msp430Adc12SingleChannel interface (no nesC warning will be signalled).
+Msp430Adc12SingleChannel interface (a nesC warning will be signalled).
The DMA controller can be used to copy conversion data from the ADC registers
to the application buffer. DMA is only present on MSP430x15x and MSP430x16x
* Msp430Adc12ClientAutoDMAC: DMA, but no automatic reference voltage
* Msp430Adc12ClientAutoDMA_RVGC: DMA and automatic reference voltage
+Currently Msp430Adc12MultiChannel is only provided by the first two components.
I/O PINs
--------------------------------------------------------------------
conversion starts the respective pin is switched to peripheral module function
and input direction and immediately after the conversion has finished it is
switched to I/O function mode. To disable this feature please comment out the
-"P6PIN_AUTO_CONFIGURE" macro in Msp430Adc12.h.
+"ADC12_P6PIN_AUTO_CONFIGURE" macro in Msp430Adc12.h.
Configuration for single channel conversions
// buffer contains conversion results
}
+
+3. Implementation
+====================================================================
+
+The ADC12 stack is located at tinyos-2.x/tos/chips/msp430/adc12. Sensor
+wrappers for the msp430 internal sensors are in
+tinyos-2.x/tos/chips/msp430/sensors, an HAL test app can be found in
+tinyos-2.x/apps/tests/msp430/Adc12.
+
-----
$Date$