[Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/msp430/adc12 AdcP.nc,
NONE, 1.1.2.1 Msp430Adc12ClientAutoDMAC.nc, NONE,
1.1.2.1 Msp430Adc12ClientAutoDMA_RVGC.nc, NONE,
1.1.2.1 Msp430Adc12ClientAutoRVGC.nc, NONE,
1.1.2.1 Msp430Adc12DMAP.nc, NONE, 1.1.2.1 Msp430Adc12ImplP.nc,
NONE, 1.1.2.1 Msp430RefVoltArbiterImplP.nc, NONE,
1.1.2.1 README.txt, NONE, 1.1.2.1 AdcReadClientC.nc, 1.1.2.5,
1.1.2.6 AdcReadNowClientC.nc, 1.1.2.5,
1.1.2.6 AdcReadStreamClientC.nc, 1.1.2.4, 1.1.2.5 HplAdc12.nc,
1.1.2.4, 1.1.2.5 HplAdc12P.nc, 1.1.2.2, 1.1.2.3 Msp430Adc12.h,
1.1.2.6, 1.1.2.7 Msp430Adc12ClientC.nc, 1.1.2.5,
1.1.2.6 Msp430Adc12P.nc, 1.1.2.9,
1.1.2.10 Msp430Adc12SingleChannel.nc, 1.1.2.6,
1.1.2.7 Msp430RefVoltArbiterP.nc, 1.1.2.7,
1.1.2.8 Msp430RefVoltGeneratorP.nc, 1.1.2.2, 1.1.2.3 AdcC.nc,
1.1.2.16, NONE Msp430Adc12C.nc, 1.1.2.10,
NONE Msp430Adc12Config.nc, 1.1.2.4,
NONE Msp430Adc12FastClientC.nc, 1.1.2.1,
NONE Msp430Adc12FastSingleChannel.nc, 1.1.2.1,
NONE Msp430Adc12RefVoltAutoClientC.nc, 1.1.2.3,
NONE Msp430RefVoltArbiterC.nc, 1.1.2.3, NONE
Jan-Hinrich Hauer
janhauer at users.sourceforge.net
Mon Oct 9 06:24:46 PDT 2006
- Previous message: [Tinyos-2-commits] CVS: tinyos-2.x/doc/txt tep101.txt, 1.1.2.7,
1.1.2.8
- Next message: [Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/msp430/sensors
Msp430InternalTemperatureC.nc, 1.1.2.3,
1.1.2.4 Msp430InternalTemperatureP.nc, 1.1.2.3,
1.1.2.4 Msp430InternalVoltageC.nc, 1.1.2.4,
1.1.2.5 Msp430InternalVoltageP.nc, 1.1.2.4, 1.1.2.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv18537/tos/chips/msp430/adc12
Modified Files:
Tag: tinyos-2_0_devel-BRANCH
AdcReadClientC.nc AdcReadNowClientC.nc AdcReadStreamClientC.nc
HplAdc12.nc HplAdc12P.nc Msp430Adc12.h Msp430Adc12ClientC.nc
Msp430Adc12P.nc Msp430Adc12SingleChannel.nc
Msp430RefVoltArbiterP.nc Msp430RefVoltGeneratorP.nc
Added Files:
Tag: tinyos-2_0_devel-BRANCH
AdcP.nc Msp430Adc12ClientAutoDMAC.nc
Msp430Adc12ClientAutoDMA_RVGC.nc Msp430Adc12ClientAutoRVGC.nc
Msp430Adc12DMAP.nc Msp430Adc12ImplP.nc
Msp430RefVoltArbiterImplP.nc README.txt
Removed Files:
Tag: tinyos-2_0_devel-BRANCH
AdcC.nc Msp430Adc12C.nc Msp430Adc12Config.nc
Msp430Adc12FastClientC.nc Msp430Adc12FastSingleChannel.nc
Msp430Adc12RefVoltAutoClientC.nc Msp430RefVoltArbiterC.nc
Log Message:
Did some major changes that will break existing components:
1) changed HIL configuration interface to AdcConfigure (in tos/interfaces) as described in TEP 101
2) changed HAL interface Msp430Adc12SingleChannel.nc to have separate commands for configuration and getting the data (especially with DMA setup the time between getData(config) and the start of the actual sampling became too long).
3) improved HAL implementation (less code)
4) wrote new components for automatic DMA support (see README.txt)
The implications for existing applications should be small (very few lines of code changes), e.g. replacing "getData(config);" with "configureX(config); getData();".
Please have a look at the README.txt.
--- NEW FILE: AdcP.nc ---
/*
* Copyright (c) 2006, 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.2.1 $
* $Date: 2006/10/09 13:24:42 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
module AdcP {
provides {
interface Read<uint16_t> as Read[uint8_t client];
interface ReadNow<uint16_t> as ReadNow[uint8_t client];
interface Resource as ResourceReadNow[uint8_t client];
interface ReadStream<uint16_t> as ReadStream[uint8_t streamClient];
}
uses {
// for Read only:
interface Resource as ResourceRead[uint8_t client];
// for ReadNow only:
interface Resource as SubResourceReadNow[uint8_t client];
// for Read and ReadNow:
interface AdcConfigure<const msp430adc12_channel_config_t*> as Config[uint8_t client];
interface Msp430Adc12SingleChannel as SingleChannel[uint8_t client];
// for ReadStream only:
interface AdcConfigure<const msp430adc12_channel_config_t*> as ConfigReadStream[uint8_t streamClient];
interface Msp430Adc12SingleChannel as SingleChannelReadStream[uint8_t streamClient];
interface Resource as ResourceReadStream[uint8_t streamClient];
}
}
implementation
{
enum {
STATE_READ,
STATE_READNOW,
STATE_READNOW_INVALID_CONFIG,
STATE_READSTREAM,
};
struct stream_entry_t {
uint16_t count;
struct stream_entry_t *next;
};
// Resource interface / arbiter makes norace declaration safe
norace uint8_t state;
norace uint8_t owner;
norace uint16_t value;
norace uint16_t *resultBuf;
// atomic section in postBuffer() makes norace safe
norace struct stream_entry_t *streamBuf[uniqueCount(ADCC_READ_STREAM_SERVICE)];
norace uint32_t usPeriod[uniqueCount(ADCC_READ_STREAM_SERVICE)];
msp430adc12_channel_config_t streamConfig;
void task finishStreamRequest();
void task signalBufferDone();
void nextReadStreamRequest(uint8_t streamClient);
error_t configure(uint8_t client)
{
error_t result = EINVAL;
const msp430adc12_channel_config_t *config;
config = call Config.getConfiguration[client]();
if (config->inch != INPUT_CHANNEL_NONE)
result = call SingleChannel.configureSingle[client](config);
return result;
}
command error_t Read.read[uint8_t client]()
{
return call ResourceRead.request[client]();
}
event void ResourceRead.granted[uint8_t client]()
{
// signalled only for Read.read()
error_t result = configure(client);
if (result == SUCCESS){
state = STATE_READ;
result = call SingleChannel.getData[client]();
}
if (result != SUCCESS){
call ResourceRead.release[client]();
signal Read.readDone[client](result, 0);
}
}
async command error_t ResourceReadNow.request[uint8_t nowClient]()
{
return call SubResourceReadNow.request[nowClient]();
}
event void SubResourceReadNow.granted[uint8_t nowClient]()
{
if (configure(nowClient) == SUCCESS)
state = STATE_READNOW;
else
state = STATE_READNOW_INVALID_CONFIG;
signal ResourceReadNow.granted[nowClient]();
}
async command error_t ResourceReadNow.immediateRequest[uint8_t nowClient]()
{
error_t result = call SubResourceReadNow.immediateRequest[nowClient]();
if (result == SUCCESS){
result = configure(nowClient);
if (result == SUCCESS)
state = STATE_READNOW;
}
return result;
}
async command error_t ResourceReadNow.release[uint8_t nowClient]()
{
return call SubResourceReadNow.release[nowClient]();
}
async command bool ResourceReadNow.isOwner[uint8_t nowClient]()
{
return call SubResourceReadNow.isOwner[nowClient]();
}
async command error_t ReadNow.read[uint8_t nowClient]()
{
if (state == STATE_READNOW_INVALID_CONFIG)
return EINVAL;
else
return call SingleChannel.getData[nowClient]();
}
void task readDone()
{
call ResourceRead.release[owner]();
signal Read.readDone[owner](SUCCESS, value);
}
async event error_t SingleChannel.singleDataReady[uint8_t client](uint16_t data)
{
switch (state)
{
case STATE_READ:
owner = client;
value = data;
post readDone();
break;
case STATE_READNOW:
signal ReadNow.readDone[client](SUCCESS, data);
break;
default:
// error !
break;
}
return SUCCESS;
}
async event uint16_t* SingleChannel.multipleDataReady[uint8_t client](
uint16_t *buf, uint16_t length)
{
// error !
return 0;
}
command error_t ReadStream.postBuffer[uint8_t streamClient]( uint16_t* buf, uint16_t count )
{
struct stream_entry_t *newEntry = (struct stream_entry_t *) buf;
newEntry->count = count;
newEntry->next = 0;
atomic {
if (!streamBuf[streamClient])
streamBuf[streamClient] = newEntry;
else {
struct stream_entry_t *tmp = streamBuf[streamClient];
while (tmp->next)
tmp = tmp->next;
tmp->next = newEntry;
}
}
return SUCCESS;
}
command error_t ReadStream.read[uint8_t streamClient]( uint32_t _usPeriod )
{
if (!streamBuf[streamClient])
return EINVAL;
usPeriod[streamClient] = _usPeriod;
return call ResourceReadStream.request[streamClient]();
}
void task finishStreamRequest()
{
call ResourceReadStream.release[owner]();
if (!streamBuf[owner])
// all posted buffers were filled
signal ReadStream.readDone[owner]( SUCCESS, usPeriod[owner] );
else {
// the commented code below makes gcc throw
// "internal error: unsupported relocation error" !?!
/*
do {
signal ReadStream.bufferDone[owner]( FAIL, (uint16_t *) streamBuf[owner], 0);
streamBuf[owner] = streamBuf[owner]->next;
} while (streamBuf[owner]);
*/
signal ReadStream.readDone[owner]( FAIL, 0 );
}
}
event void ResourceReadStream.granted[uint8_t streamClient]()
{
error_t result;
const msp430adc12_channel_config_t *config;
struct stream_entry_t *entry = streamBuf[streamClient];
if (!entry)
result = EINVAL;
else {
config = call ConfigReadStream.getConfiguration[streamClient]();
if (config->inch == INPUT_CHANNEL_NONE)
result = EINVAL;
else {
owner = streamClient;
streamConfig = *config;
streamConfig.sampcon_ssel = SAMPCON_SOURCE_SMCLK; // assumption: SMCLK runs at 1 MHz
streamConfig.sampcon_id = SAMPCON_CLOCK_DIV_1;
streamBuf[streamClient] = entry->next;
result = call SingleChannelReadStream.configureMultiple[streamClient](
&streamConfig, (uint16_t *) entry, entry->count, usPeriod[streamClient]);
if (result == SUCCESS)
result = call SingleChannelReadStream.getData[streamClient]();
else {
streamBuf[streamClient] = entry;
post finishStreamRequest();
return;
}
}
}
if (result != SUCCESS){
call ResourceReadStream.release[streamClient]();
signal ReadStream.readDone[streamClient]( FAIL, 0 );
}
return;
}
async event uint16_t* SingleChannelReadStream.multipleDataReady[uint8_t streamClient](
uint16_t *buf, uint16_t length)
{
error_t nextRequest;
if (!resultBuf){
value = length;
resultBuf = buf;
post signalBufferDone();
if (!streamBuf[streamClient])
post finishStreamRequest();
else {
// fill next buffer (this is the only async code dealing with buffers)
struct stream_entry_t *entry = streamBuf[streamClient];
streamBuf[streamClient] = streamBuf[streamClient]->next;
nextRequest = call SingleChannelReadStream.configureMultiple[streamClient](
&streamConfig, (uint16_t *) entry, entry->count, usPeriod[streamClient]);
if (nextRequest == SUCCESS)
nextRequest = call SingleChannelReadStream.getData[streamClient]();
if (nextRequest != SUCCESS){
streamBuf[owner] = entry;
post finishStreamRequest();
}
}
} else {
// overflow: can't signal data fast enough
struct stream_entry_t *entry = (struct stream_entry_t *) buf;
entry->next = streamBuf[streamClient];
streamBuf[streamClient] = entry; // what a waste
post finishStreamRequest();
}
return 0;
}
void task signalBufferDone()
{
signal ReadStream.bufferDone[owner]( SUCCESS, resultBuf, value);
resultBuf = 0;
}
async event error_t SingleChannelReadStream.singleDataReady[uint8_t streamClient](uint16_t data)
{
// won't happen
return SUCCESS;
}
default async command error_t ResourceRead.request[uint8_t client]() { return FAIL; }
default async command error_t ResourceRead.immediateRequest[uint8_t client]() { return FAIL; }
default async command error_t ResourceRead.release[uint8_t client]() { return FAIL; }
default event void Read.readDone[uint8_t client]( error_t result, uint16_t val ){}
default async command error_t SubResourceReadNow.release[uint8_t nowClient](){ return FAIL;}
default async command error_t SubResourceReadNow.request[uint8_t nowClient](){ return FAIL; }
default event void ResourceReadNow.granted[uint8_t nowClient](){}
default async event void ReadNow.readDone[uint8_t client]( error_t result, uint16_t val ){}
default async command error_t SubResourceReadNow.immediateRequest[uint8_t nowClient]()
{
return FAIL;
}
default async command error_t ResourceReadStream.request[uint8_t streamClient]() { return FAIL; }
default async command error_t ResourceReadStream.release[uint8_t streamClient]() { return FAIL; }
default event void ReadStream.bufferDone[uint8_t streamClient]( error_t result,
uint16_t* buf, uint16_t count ){}
default event void ReadStream.readDone[uint8_t streamClient]( error_t result, uint32_t actualPeriod ){ }
default async command error_t SingleChannel.getData[uint8_t client]()
{
return EINVAL;
}
// will be placed in flash
const msp430adc12_channel_config_t defaultConfig = {INPUT_CHANNEL_NONE,0,0,0,0,0,0,0};
default async command const msp430adc12_channel_config_t*
Config.getConfiguration[uint8_t client]()
{
return &defaultConfig;
}
default async command const msp430adc12_channel_config_t*
ConfigReadStream.getConfiguration[uint8_t client]()
{
return &defaultConfig;
}
default async command error_t SingleChannelReadStream.configureMultiple[uint8_t client](
const msp430adc12_channel_config_t *config, uint16_t buffer[],
uint16_t numSamples, uint16_t jiffies)
{
return FAIL;
}
default async command error_t SingleChannelReadStream.getData[uint8_t client]()
{
return FAIL;
}
default async command error_t SingleChannel.configureSingle[uint8_t client](
const msp430adc12_channel_config_t *config){ return FAIL; }
}
--- NEW FILE: Msp430Adc12ClientAutoDMAC.nc ---
/*
* Copyright (c) 2006, 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.2.1 $
* $Date: 2006/10/09 13:24:42 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/**
* This component virtualizes access to the HAL of the MSP430 ADC12. ADC
* conversion results are copied using DMA.
*
* @author Jan Hauer
*
* @see Please refer to the README.txt and TEP 101 for more information about
* this component and its intended use.
*/
generic configuration Msp430Adc12ClientAutoDMAC()
{
provides {
interface Resource;
interface Msp430Adc12SingleChannel;
}
} implementation {
components Msp430DmaC, Msp430Adc12DMAP, Msp430Adc12P;
enum {
ID = unique(MSP430ADC12_RESOURCE),
};
Resource = Msp430Adc12P.Resource[ID];
Msp430Adc12SingleChannel = Msp430Adc12DMAP.SingleChannel[ID];
Msp430Adc12DMAP.SubSingleChannel[ID] -> Msp430Adc12P.SingleChannel[ID];
Msp430Adc12DMAP.AsyncAdcControl[ID] -> Msp430Adc12P.DMAExtension[ID];
Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;
Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel0;
}
--- NEW FILE: Msp430Adc12ClientAutoDMA_RVGC.nc ---
/*
* Copyright (c) 2006, 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.2.1 $ $Date: 2006/10/09 13:24:42 $ @author: Jan Hauer
* <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/**
* This component virtualizes access to the HAL of the MSP430 ADC12. ADC
* conversion results are copied using DMA and reference voltage is enabled as
* required by the configuration.
*
* @author Jan Hauer
*
* @see Please refer to the README.txt and TEP 101 for more information about
* this component and its intended use.
*/
generic configuration Msp430Adc12ClientAutoDMA_RVGC()
{
provides {
interface Resource;
interface Msp430Adc12SingleChannel;
}
uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
} implementation {
components Msp430Adc12P, Msp430RefVoltArbiterP;
enum {
ID = unique(MSP430ADC12_RESOURCE),
};
Resource = Msp430RefVoltArbiterP.ClientResource[ID];
Msp430RefVoltArbiterP.AdcResource[ID] -> Msp430Adc12P.Resource[ID];
AdcConfigure = Msp430RefVoltArbiterP.Config[ID];
components Msp430DmaC, Msp430Adc12DMAP;
Msp430Adc12SingleChannel = Msp430Adc12DMAP.SingleChannel[ID];
Msp430Adc12DMAP.SubSingleChannel[ID] -> Msp430Adc12P.SingleChannel[ID];
Msp430Adc12DMAP.AsyncAdcControl[ID] -> Msp430Adc12P.DMAExtension[ID];
Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;
Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel0;
}
--- NEW FILE: Msp430Adc12ClientAutoRVGC.nc ---
/*
* Copyright (c) 2006, 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.2.1 $ $Date: 2006/10/09 13:24:42 $ @author: Jan Hauer
* <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/**
* This component virtualizes access to the HAL of the MSP430 ADC12.
* Reference voltage is enabled automatically as required by the configuration.
*
* @author Jan Hauer
*
* @see Please refer to the README.txt and TEP 101 for more information about
* this component and its intended use.
*/
generic configuration Msp430Adc12ClientAutoRVGC()
{
provides {
interface Resource;
interface Msp430Adc12SingleChannel;
}
uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
} implementation {
components Msp430Adc12P, Msp430RefVoltArbiterP;
enum {
ID = unique(MSP430ADC12_RESOURCE),
};
Resource = Msp430RefVoltArbiterP.ClientResource[ID];
Msp430Adc12SingleChannel = Msp430Adc12P.SingleChannel[ID];
Msp430RefVoltArbiterP.AdcResource[ID] -> Msp430Adc12P.Resource[ID];
AdcConfigure = Msp430RefVoltArbiterP.Config[ID];
}
--- NEW FILE: Msp430Adc12DMAP.nc ---
/*
* Copyright (c) 2006, 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.2.1 $
* $Date: 2006/10/09 13:24:43 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include <Msp430Adc12.h>
#include <Msp430Dma.h>
module Msp430Adc12DMAP
{
provides {
interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
}
uses {
interface Msp430DmaControl as DMAControl;
interface Msp430DmaChannel as DMAChannel;
interface Msp430Adc12SingleChannel as SubSingleChannel[uint8_t id];
interface AsyncStdControl as AsyncAdcControl[uint8_t id];
}
}
implementation
{
enum {
MULTIPLE_SINGLE,
MULTIPLE_REPEAT,
MULTIPLE_SINGLE_AGAIN,
};
// norace declarations are safe here, because Msp430Adc12P.nc implements
// a lock mechanism which guarantees that no two clients can access the ADC
// and the module variables below are only changed after the lock was acquired
norace uint8_t client;
norace uint8_t mode;
norace uint16_t *buffer;
norace uint16_t numSamples;
async command error_t SingleChannel.configureSingle[uint8_t id](
const msp430adc12_channel_config_t *config)
{
// don't use DMA for single conversions
return call SubSingleChannel.configureSingle[id](config);
}
async command error_t SingleChannel.configureSingleRepeat[uint8_t id](
const msp430adc12_channel_config_t *config,
uint16_t jiffies)
{
// don't use DMA for single conversions
return call SubSingleChannel.configureSingleRepeat[id](config, jiffies);
}
error_t configure(uint8_t id, const msp430adc12_channel_config_t *config,
uint16_t *buf, uint16_t length, uint16_t jiffies, uint8_t _mode)
{
// for multiple samples single-channel repat-conversion mode
// is used, because then there is only one interrupt at the
// the end of the whole sequence and DMA has done all the copying
error_t result = call SubSingleChannel.configureSingleRepeat[id](config, jiffies);
if (result == SUCCESS){
call DMAControl.init();
call DMAControl.setFlags(ENABLE_NMI, NOT_ROUND_ROBIN, ON_FETCH);
call DMAChannel.setupTransfer(
DMA_REPEATED_SINGLE_TRANSFER,
DMA_TRIGGER_ADC12IFGx,
DMA_EDGE_SENSITIVE,
ADC12MEM,
buf,
length,
DMA_WORD,
DMA_WORD,
DMA_ADDRESS_UNCHANGED,
DMA_ADDRESS_INCREMENTED
);
call DMAChannel.startTransfer();
client = id;
mode = _mode;
buffer = buf;
numSamples = length;
call AsyncAdcControl.start[id]();
}
return result;
}
async command error_t SingleChannel.configureMultiple[uint8_t id](
const msp430adc12_channel_config_t *config,
uint16_t *buf, uint16_t length, uint16_t jiffies)
{
return configure(id, config, buf, length, jiffies, MULTIPLE_SINGLE);
}
async command error_t SingleChannel.configureMultipleRepeat[uint8_t id](
const msp430adc12_channel_config_t *config,
uint16_t *buf, uint8_t length, uint16_t jiffies)
{
return configure(id, config, buf, length, jiffies, MULTIPLE_REPEAT);
}
async command error_t SingleChannel.getData[uint8_t id]()
{
if (mode == MULTIPLE_SINGLE_AGAIN)
call DMAChannel.repeatTransfer(ADC12MEM, buffer, numSamples);
return call SubSingleChannel.getData[id]();
}
async event error_t SubSingleChannel.singleDataReady[uint8_t id](uint16_t data)
{
// forward (only signalled if not in DMA mode)
return signal SingleChannel.singleDataReady[id](data);
}
async event uint16_t* SubSingleChannel.multipleDataReady[uint8_t id](uint16_t buf[], uint16_t num)
{
// will never get here
return 0;
}
async event void DMAChannel.transferDone(error_t success)
{
uint16_t* next;
uint8_t oldMode = mode;
if (oldMode != MULTIPLE_REPEAT){
call AsyncAdcControl.stop[client]();
mode = MULTIPLE_SINGLE_AGAIN;
}
next = signal SingleChannel.multipleDataReady[client](buffer, numSamples);
if (oldMode == MULTIPLE_REPEAT)
if (next){
call DMAChannel.repeatTransfer(ADC12MEM, next, numSamples);
call AsyncAdcControl.start[client]();
} else
call AsyncAdcControl.stop[client]();
}
default async command error_t SubSingleChannel.configureSingle[uint8_t id](
const msp430adc12_channel_config_t *config)
{ return FAIL; }
default async command error_t SubSingleChannel.configureSingleRepeat[uint8_t id](
const msp430adc12_channel_config_t *config, uint16_t jiffies)
{ return FAIL; }
default async command error_t SubSingleChannel.configureMultiple[uint8_t id](
const msp430adc12_channel_config_t
*config, uint16_t buf[], uint16_t num, uint16_t jiffies)
{ return FAIL; }
default async command error_t SubSingleChannel.configureMultipleRepeat[uint8_t id](
const msp430adc12_channel_config_t *config, uint16_t buf[], uint8_t
num, uint16_t jiffies)
{ return FAIL; }
default async command error_t SubSingleChannel.getData[uint8_t id]()
{ return FAIL;}
default async event error_t SingleChannel.singleDataReady[uint8_t id](
uint16_t data)
{ return FAIL; }
default async event uint16_t* SingleChannel.multipleDataReady[uint8_t id](
uint16_t buf[], uint16_t num)
{ return 0;}
default async command error_t AsyncAdcControl.stop[uint8_t id]()
{ return FAIL; }
default async command error_t AsyncAdcControl.start[uint8_t id]()
{ return FAIL; }
}
--- NEW FILE: Msp430Adc12ImplP.nc ---
/*
* Copyright (c) 2006, 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.2.1 $
* $Date: 2006/10/09 13:24:43 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include <Msp430Adc12.h>
module Msp430Adc12ImplP
{
provides {
interface Init;
interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
interface AsyncStdControl as DMAExtension[uint8_t id];
}
uses {
interface ArbiterInfo as ADCArbiterInfo;
interface HplAdc12;
interface Msp430Timer as TimerA;;
interface Msp430TimerControl as ControlA0;
interface Msp430TimerControl as ControlA1;
interface Msp430Compare as CompareA0;
interface Msp430Compare as CompareA1;
interface HplMsp430GeneralIO as Port60;
interface HplMsp430GeneralIO as Port61;
interface HplMsp430GeneralIO as Port62;
interface HplMsp430GeneralIO as Port63;
interface HplMsp430GeneralIO as Port64;
interface HplMsp430GeneralIO as Port65;
interface HplMsp430GeneralIO as Port66;
interface HplMsp430GeneralIO as Port67;
}
}
implementation
{
enum {
SINGLE_DATA = 1,
SINGLE_DATA_REPEAT = 2,
MULTIPLE_DATA = 4,
MULTIPLE_DATA_REPEAT = 8,
CONVERSION_MODE_MASK = 0x0F,
ADC_BUSY = 16, /* request pending */
USE_TIMERA = 32, /* TimerA used for SAMPCON signal */
};
uint8_t state; /* see enum above */
uint16_t *resultBuffer; /* conversion results */
uint16_t resultBufferLength; /* length of buffer */
uint16_t resultBufferIndex; /* offset into buffer */
uint8_t clientID; /* ID of client that called getData() */
command error_t Init.init()
{
call HplAdc12.stopConversion();
return SUCCESS;
}
void prepareTimerA(uint16_t interval, uint16_t csSAMPCON, uint16_t cdSAMPCON)
{
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 TimerA.setMode(MSP430TIMER_STOP_MODE);
call TimerA.clear();
call TimerA.disableEvents();
call TimerA.setClockSource(csSAMPCON);
call TimerA.setInputDivider(cdSAMPCON);
call ControlA0.setControl(ccResetSHI);
call CompareA0.setEvent(interval-1);
call CompareA1.setEvent((interval-1)/2);
}
void startTimerA()
{
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 };
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 };
msp430_compare_control_t ccRSOutmod = {
ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0,
outmod : 7, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 };
// manually trigger first conversion, then switch to Reset/set conversionMode
call ControlA1.setControl(ccResetSHI);
call ControlA1.setControl(ccSetSHI);
//call ControlA1.setControl(ccResetSHI);
call ControlA1.setControl(ccRSOutmod);
call TimerA.setMode(MSP430TIMER_UP_MODE); // go!
}
void configureAdcPin( uint8_t inch )
{
#ifdef P6PIN_AUTO_CONFIGURE
switch (inch)
{
case 0: call Port60.selectModuleFunc(); call Port60.makeInput(); break;
case 1: call Port61.selectModuleFunc(); call Port61.makeInput(); break;
case 2: call Port62.selectModuleFunc(); call Port62.makeInput(); break;
case 3: call Port63.selectModuleFunc(); call Port63.makeInput(); break;
case 4: call Port64.selectModuleFunc(); call Port64.makeInput(); break;
case 5: call Port65.selectModuleFunc(); call Port65.makeInput(); break;
case 6: call Port66.selectModuleFunc(); call Port66.makeInput(); break;
case 7: call Port67.selectModuleFunc(); call Port67.makeInput(); break;
}
#endif
}
void resetAdcPin( uint8_t inch )
{
#ifdef P6PIN_AUTO_CONFIGURE
switch (inch)
{
case 0: call Port60.selectIOFunc(); break;
case 1: call Port61.selectIOFunc(); break;
case 2: call Port62.selectIOFunc(); break;
case 3: call Port63.selectIOFunc(); break;
case 4: call Port64.selectIOFunc(); break;
case 5: call Port65.selectIOFunc(); break;
case 6: call Port66.selectIOFunc(); break;
case 7: call Port67.selectIOFunc(); break;
}
#endif
}
async command error_t SingleChannel.configureSingle[uint8_t id](
const msp430adc12_channel_config_t *config)
{
error_t result = ERESERVE;
#ifdef CHECK_ARGS
if (!config)
return EINVAL;
#endif
atomic {
if (state & ADC_BUSY)
return EBUSY;
if (call ADCArbiterInfo.userId() == id){
adc12ctl1_t ctl1 = {
adc12busy: 0,
conseq: 0,
adc12ssel: config->adc12ssel,
adc12div: config->adc12div,
issh: 0,
shp: 1,
shs: 0,
cstartadd: 0
};
adc12memctl_t memctl = {
inch: config->inch,
sref: config->sref,
eos: 1
};
adc12ctl0_t ctl0 = call HplAdc12.getCtl0();
ctl0.msc = 1;
ctl0.sht0 = config->sht;
ctl0.sht1 = config->sht;
state = SINGLE_DATA;
call HplAdc12.setCtl0(ctl0);
call HplAdc12.setCtl1(ctl1);
call HplAdc12.setMCtl(0, memctl);
call HplAdc12.setIEFlags(0x01);
result = SUCCESS;
}
}
return result;
}
async command error_t SingleChannel.configureSingleRepeat[uint8_t id](
const msp430adc12_channel_config_t *config,
uint16_t jiffies)
{
error_t result = ERESERVE;
#ifdef CHECK_ARGS
if (!config || jiffies == 1 || jiffies == 2)
return EINVAL;
#endif
atomic {
if (state & ADC_BUSY)
return EBUSY;
if (call ADCArbiterInfo.userId() == id) {
adc12ctl1_t ctl1 = {
adc12busy: 0,
conseq: 2,
adc12ssel: config->adc12ssel,
adc12div: config->adc12div,
issh: 0,
shp: 1,
shs: (jiffies == 0) ? 0 : 1,
cstartadd: 0
};
adc12memctl_t memctl = {
inch: config->inch,
sref: config->sref,
eos: 1
};
adc12ctl0_t ctl0 = call HplAdc12.getCtl0();
ctl0.msc = (jiffies == 0) ? 1 : 0;
ctl0.sht0 = config->sht;
ctl0.sht1 = config->sht;
state = SINGLE_DATA_REPEAT;
call HplAdc12.setCtl0(ctl0);
call HplAdc12.setCtl1(ctl1);
call HplAdc12.setMCtl(0, memctl);
call HplAdc12.setIEFlags(0x01);
if (jiffies){
state |= USE_TIMERA;
prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id);
}
result = SUCCESS;
}
}
return result;
}
async command error_t SingleChannel.configureMultiple[uint8_t id](
const msp430adc12_channel_config_t *config,
uint16_t *buf, uint16_t length, uint16_t jiffies)
{
error_t result = ERESERVE;
#ifdef CHECK_ARGS
if (!config || !buf || !length || jiffies == 1 || jiffies == 2)
return EINVAL;
#endif
atomic {
if (state & ADC_BUSY)
return EBUSY;
if (call ADCArbiterInfo.userId() == id){
adc12ctl1_t ctl1 = {
adc12busy: 0,
conseq: (length > 16) ? 3 : 1,
adc12ssel: config->adc12ssel,
adc12div: config->adc12div,
issh: 0,
shp: 1,
shs: (jiffies == 0) ? 0 : 1,
cstartadd: 0
};
adc12memctl_t memctl = {
inch: config->inch,
sref: config->sref,
eos: 0
};
uint16_t i, mask = 1;
adc12ctl0_t ctl0 = call HplAdc12.getCtl0();
ctl0.msc = (jiffies == 0) ? 1 : 0;
ctl0.sht0 = config->sht;
ctl0.sht1 = config->sht;
state = MULTIPLE_DATA;
resultBuffer = buf;
resultBufferLength = length;
resultBufferIndex = 0;
call HplAdc12.setCtl0(ctl0);
call HplAdc12.setCtl1(ctl1);
for (i=0; i<(length-1) && i < 15; i++)
call HplAdc12.setMCtl(i, memctl);
memctl.eos = 1;
call HplAdc12.setMCtl(i, memctl);
call HplAdc12.setIEFlags(mask << i);
if (jiffies){
state |= USE_TIMERA;
prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id);
}
result = SUCCESS;
}
}
return result;
}
async command error_t SingleChannel.configureMultipleRepeat[uint8_t id](
const msp430adc12_channel_config_t *config,
uint16_t *buf, uint8_t length, uint16_t jiffies)
{
error_t result = ERESERVE;
#ifdef CHECK_ARGS
if (!config || !buf || !length || length > 16 || jiffies == 1 || jiffies == 2)
return EINVAL;
#endif
atomic {
if (state & ADC_BUSY)
return EBUSY;
if (call ADCArbiterInfo.userId() == id){
adc12ctl1_t ctl1 = {
adc12busy: 0,
ctl1.conseq = 3,
adc12ssel: config->adc12ssel,
adc12div: config->adc12div,
issh: 0,
shp: 1,
shs: (jiffies == 0) ? 0 : 1,
cstartadd: 0
};
adc12memctl_t memctl = {
inch: config->inch,
sref: config->sref,
eos: 0
};
uint16_t i, mask = 1;
adc12ctl0_t ctl0 = call HplAdc12.getCtl0();
ctl0.msc = (jiffies == 0) ? 1 : 0;
ctl0.sht0 = config->sht;
ctl0.sht1 = config->sht;
state = MULTIPLE_DATA_REPEAT;
resultBuffer = buf;
resultBufferLength = length;
resultBufferIndex = 0;
call HplAdc12.setCtl0(ctl0);
call HplAdc12.setCtl1(ctl1);
for (i=0; i<(length-1) && i < 15; i++)
call HplAdc12.setMCtl(i, memctl);
memctl.eos = 1;
call HplAdc12.setMCtl(i, memctl);
call HplAdc12.setIEFlags(mask << i);
if (jiffies){
state |= USE_TIMERA;
prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id);
}
result = SUCCESS;
}
}
return result;
}
async command error_t SingleChannel.getData[uint8_t id]()
{
atomic {
if (call ADCArbiterInfo.userId() == id){
if (state & MULTIPLE_DATA_REPEAT && !resultBuffer)
return EINVAL;
if (state & ADC_BUSY)
return EBUSY;
state |= ADC_BUSY;
clientID = id;
configureAdcPin((call HplAdc12.getMCtl(0)).inch);
call HplAdc12.startConversion();
if (state & USE_TIMERA)
startTimerA();
return SUCCESS;
}
}
return FAIL;
}
void stopConversion()
{
adc12memctl_t memctl = call HplAdc12.getMCtl(0);
if (state & USE_TIMERA)
call TimerA.setMode(MSP430TIMER_STOP_MODE);
resetAdcPin( memctl.inch );
call HplAdc12.stopConversion();
call HplAdc12.resetIFGs();
state &= ~ADC_BUSY;
}
async command error_t DMAExtension.start[uint8_t id]()
{
atomic {
if (call ADCArbiterInfo.userId() == id){
call HplAdc12.setIEFlags(0);
call HplAdc12.resetIFGs();
return SUCCESS;
}
}
return FAIL;
}
async command error_t DMAExtension.stop[uint8_t id]()
{
atomic {
if (call ADCArbiterInfo.userId() == id){
stopConversion();
return SUCCESS;
}
}
return FAIL;
}
async event void TimerA.overflow(){}
async event void CompareA0.fired(){}
async event void CompareA1.fired(){}
async event void HplAdc12.conversionDone(uint16_t iv)
{
switch (state & CONVERSION_MODE_MASK)
{
case SINGLE_DATA:
stopConversion();
signal SingleChannel.singleDataReady[clientID](call HplAdc12.getMem(0));
break;
case SINGLE_DATA_REPEAT:
{
error_t repeatContinue;
repeatContinue = signal SingleChannel.singleDataReady[clientID](
call HplAdc12.getMem(0));
if (repeatContinue == FAIL)
stopConversion();
break;
}
case MULTIPLE_DATA:
{
uint16_t i = 0, length;
if (resultBufferLength - resultBufferIndex > 16)
length = 16;
else
length = resultBufferLength - resultBufferIndex;
do {
*resultBuffer++ = call HplAdc12.getMem(i);
} while (++i < length);
resultBufferIndex += length;
if (resultBufferLength - resultBufferIndex > 15)
return;
else if (resultBufferLength - resultBufferIndex > 0){
adc12memctl_t memctl = call HplAdc12.getMCtl(0);
memctl.eos = 1;
call HplAdc12.setMCtl(resultBufferLength - resultBufferIndex, memctl);
} else {
stopConversion();
resultBuffer -= resultBufferLength;
resultBufferIndex = 0;
signal SingleChannel.multipleDataReady[clientID](resultBuffer, resultBufferLength);
}
}
break;
case MULTIPLE_DATA_REPEAT:
{
uint8_t i = 0;
do {
*resultBuffer++ = call HplAdc12.getMem(i);
} while (++i < resultBufferLength);
resultBuffer = signal SingleChannel.multipleDataReady[clientID](
resultBuffer-resultBufferLength,
resultBufferLength);
if (!resultBuffer)
stopConversion();
break;
}
} // switch
}
default async event error_t SingleChannel.singleDataReady[uint8_t id](uint16_t data)
{
return FAIL;
}
default async event uint16_t* SingleChannel.multipleDataReady[uint8_t id](
uint16_t *buf, uint16_t length)
{
return 0;
}
async event void HplAdc12.memOverflow(){}
async event void HplAdc12.conversionTimeOverflow(){}
}
--- NEW FILE: Msp430RefVoltArbiterImplP.nc ---
/*
* Copyright (c) 2006, Technische Universität 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 Universität 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.2.1 $
* $Date: 2006/10/09 13:24:43 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
module Msp430RefVoltArbiterImplP
{
provides interface Resource as ClientResource[uint8_t client];
uses {
interface Resource as AdcResource[uint8_t client];
interface SplitControl as RefVolt_1_5V;
interface SplitControl as RefVolt_2_5V;
interface AdcConfigure<const msp430adc12_channel_config_t*> as Config[uint8_t client];
}
} implementation {
enum {
NO_OWNER = 0xFF,
};
norace uint8_t owner = NO_OWNER;
task void switchOff();
async command error_t ClientResource.request[uint8_t client]()
{
return call AdcResource.request[client]();
}
async command error_t ClientResource.immediateRequest[uint8_t client]()
{
const msp430adc12_channel_config_t* settings = call Config.getConfiguration[client]();
if (settings->sref == REFERENCE_VREFplus_AVss ||
settings->sref == REFERENCE_VREFplus_VREFnegterm)
// always fails, because of the possible start-up delay (and async-sync transition)
return FAIL;
else {
error_t request = call AdcResource.immediateRequest[client]();
if (request == SUCCESS)
owner = client;
return request;
}
}
event void AdcResource.granted[uint8_t client]()
{
const msp430adc12_channel_config_t* settings = call Config.getConfiguration[client]();
owner = client;
if (settings->sref == REFERENCE_VREFplus_AVss ||
settings->sref == REFERENCE_VREFplus_VREFnegterm){
error_t started;
if (settings->ref2_5v == REFVOLT_LEVEL_1_5)
started = call RefVolt_1_5V.start();
else
started = call RefVolt_2_5V.start();
if (started != SUCCESS){
owner = NO_OWNER;
call AdcResource.release[client]();
call AdcResource.request[client]();
}
} else
signal ClientResource.granted[client]();
}
event void RefVolt_1_5V.startDone(error_t error)
{
if (owner != NO_OWNER){
// Note that it can still not be guaranteed that ClientResource.granted()
// is not signalled after ClientResource.release() has been called.
signal ClientResource.granted[owner]();
}
}
event void RefVolt_2_5V.startDone(error_t error)
{
if (owner != NO_OWNER){
// Note that it can still not be guaranteed that ClientResource.granted()
// is not signalled after ClientResource.release() has been called.
signal ClientResource.granted[owner]();
}
}
async command error_t ClientResource.release[uint8_t client]()
{
atomic {
if (owner == client){
owner = NO_OWNER;
post switchOff();
}
}
return call AdcResource.release[client]();
}
task void switchOff()
{
if (owner == NO_OWNER)
if (call RefVolt_1_5V.stop() != SUCCESS)
post switchOff();
}
event void RefVolt_1_5V.stopDone(error_t error)
{
}
event void RefVolt_2_5V.stopDone(error_t error)
{
}
async command uint8_t ClientResource.isOwner[uint8_t client]()
{
return call AdcResource.isOwner[client]();
}
default event void ClientResource.granted[uint8_t client](){}
default async command error_t AdcResource.request[uint8_t client]()
{
return FAIL;
}
default async command error_t AdcResource.immediateRequest[uint8_t client]()
{
return FAIL;
}
default async command error_t AdcResource.release[uint8_t client](){return FAIL;}
const msp430adc12_channel_config_t defaultConfig = {INPUT_CHANNEL_NONE,0,0,0,0,0,0,0};
default async command const msp430adc12_channel_config_t*
Config.getConfiguration[uint8_t client]()
{
return &defaultConfig;
}
}
--- NEW FILE: README.txt ---
The implementation of the 12-bit ADC stack on the MSP430 is in compliance with
TEP 101 (tinyos-2.x/doc/txt/tep101.txt) and provides virtualized access to the
ADC12 by seven different components: AdcReadClientC, AdcReadNowClientC,
AdcReadStreamClientC, Msp430Adc12ClientC, Msp430Adc12ClientAutoDMAC,
Msp430Adc12ClientAutoRVGC and Msp430Adc12ClientAutoDMA_RVGC. A client
component may wire to any of these components and it SHOULD NOT wire to any
other components in 'tinyos-2.x/tos/chips/msp430/adc12'. This document
explains the difference between the seven components.
A platform-independent application (an application like 'Oscilloscope' that is
supposed to run on, for example, the 'telosb' and 'micaz' platform at the same
time) cannot wire to an MSP430-specific interface like Msp430Adc12SingleChannel
(there is no MSP430 on micaz). Instead such an application may access the
MSP430 ADC through any of the three following components:
* AdcReadClientC: to read single ADC values
* AdcReadNowClientC: to read single ADC values asynchronously (fast)
* AdcReadStreamClientC: to read multiple ADC values
These components are less efficient than the MSP430-specific ADC components
(described below), but they provide standard TinyOS interfaces for reading ADC
values. Thus, if a client component does not care so much about efficiency but
rather about portability it should wire to any of these components.
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
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 be
used as reference voltage in the conversion process. Whether the internal
reference voltage generator should be enabled during the conversion is
platform-specific (e.g. the light sensor on the 'eyesIFX' requires a stable
reference voltage). When an application requires a stable reference voltage
during the sampling process it should wire to the Msp430Adc12ClientAutoRVGC
component. This assures that when the app is signalled the Resource.granted()
event the reference voltage generator outputs a stable voltage (the level is
defined in the configuration data supplied by the application). The DMA
controller can be used to efficiently copy conversion data from ADC data
registers to the application buffer. DMA is only present on MSP430x15x and
MSP430x16x devices. When an application wants to use the DMA it can wire to
the Msp430Adc12ClientAutoDMAC component and then conversion results are
transferred using DMA. Both, enabling the reference generator and using the
DMA, therefore happens transparent to the app. There are four possible
combinations reflected by the following components that an MSP430-based
application may wire to:
* Msp430Adc12ClientC: no DMA, no automatic reference voltage
* Msp430Adc12ClientAutoRVGC: automatic reference voltage, but no DMA
* Msp430Adc12ClientAutoDMAC: DMA, but no automatic reference voltage
* Msp430Adc12ClientAutoDMA_RVGC: DMA and automatic reference voltage
During a conversion the respective ADC port pin (ports 6.0 - 6.7) must be
configured such that the peripheral module function is selected and the port
pin is switched to input direction. By default, for every client this is done
**automatically** in the ADC stack (Msp430Adc12ImplP), i.e. just before the
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.
-----
$Date: 2006/10/09 13:24:43 $
@author: Jan Hauer <hauer at tkn.tu-berlin.de>
Index: AdcReadClientC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/AdcReadClientC.nc,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -C2 -d -r1.1.2.5 -r1.1.2.6
*** AdcReadClientC.nc 19 Jun 2006 11:12:23 -0000 1.1.2.5
--- AdcReadClientC.nc 9 Oct 2006 13:24:42 -0000 1.1.2.6
***************
*** 35,49 ****
/**
! * This component allows a client to access the MSP430 ADC12
! * (12-bit analog-to-digital converter) via the <code>Read</code> interface. A
! * client must wire the <code>Msp430Adc12Config</code> interface to a component
! * that returns its ADC12 configuration data. Depending on the
! * REF_VOLT_AUTO_CONFIGURE switch (defined in Msp430Adc12.h) the internal
! * reference voltage generator is automatically enabled if and only if the
! * configuration data includes VREF as reference voltage.
*
! * @author Jan Hauer
! * @see Please refer to TEP 101 for more information about this component and its
! * intended use.
*/
--- 35,45 ----
/**
! * This component virtualizes the HIL of ADC12 on MSP430. A client must wire
! * <code>AdcConfigure</code> to a component that returns the client's adc
! * configuration data.
*
! * @author Jan Hauer
! * @see Please refer to the README.txt and TEP 101 for more information about
! * this component and its intended use.
*/
***************
*** 51,59 ****
generic configuration AdcReadClientC() {
provides interface Read<uint16_t>;
! uses interface Msp430Adc12Config;
} implementation {
! components AdcC,
#ifdef REF_VOLT_AUTO_CONFIGURE
! new Msp430Adc12RefVoltAutoClientC() as Msp430AdcClient;
#else
new Msp430Adc12ClientC() as Msp430AdcClient;
--- 47,58 ----
generic configuration AdcReadClientC() {
provides interface Read<uint16_t>;
! uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
} implementation {
! components AdcP,
#ifdef REF_VOLT_AUTO_CONFIGURE
! // if the client configuration requires a stable
! // reference voltage, the reference voltage generator
! // is automatically enabled
! new Msp430Adc12ClientAutoRVGC() as Msp430AdcClient;
#else
new Msp430Adc12ClientC() as Msp430AdcClient;
***************
*** 64,73 ****
};
! Read = AdcC.Read[CLIENT];
! Msp430Adc12Config = AdcC.Config[CLIENT];
! AdcC.SingleChannel[CLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
! AdcC.Resource[CLIENT] -> Msp430AdcClient.Resource;
#ifdef REF_VOLT_AUTO_CONFIGURE
! Msp430Adc12Config = Msp430AdcClient.Msp430Adc12Config;
#endif
}
--- 63,72 ----
};
! Read = AdcP.Read[CLIENT];
! AdcConfigure = AdcP.Config[CLIENT];
! AdcP.SingleChannel[CLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
! AdcP.ResourceRead[CLIENT] -> Msp430AdcClient.Resource;
#ifdef REF_VOLT_AUTO_CONFIGURE
! AdcConfigure = Msp430AdcClient.AdcConfigure;
#endif
}
Index: AdcReadNowClientC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/AdcReadNowClientC.nc,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -C2 -d -r1.1.2.5 -r1.1.2.6
*** AdcReadNowClientC.nc 19 Jun 2006 11:12:23 -0000 1.1.2.5
--- AdcReadNowClientC.nc 9 Oct 2006 13:24:42 -0000 1.1.2.6
***************
*** 35,53 ****
/**
! * This component allows a client to access the MSP430 ADC12
! * (12-bit analog-to-digital converter) via the <code>ReadNow</code> and
! * <code>Resource</code> interface. According to TEP 108 a client must reserve
! * the ADC before using it via the <code>Resource</code> interface (otherwise
! * the request will fail). A client must wire the
! * <code>Msp430Adc12Config</code> interface to a component that returns its
! * ADC12 configuration data. Depending on the REF_VOLT_AUTO_CONFIGURE switch
! * (defined in Msp430Adc12.h) the internal reference voltage generator is
! * automatically enabled if and only if the configuration data includes VREF as
! * reference voltage. Then the <code>Resource.granted()</code> event implies
! * that the reference voltage is stable.
*
! * @author Jan Hauer
! * @see Please refer to TEP 101 for more information about this component and its
! * intended use.
*/
--- 35,45 ----
/**
! * This component virtualizes the HIL of ADC12 on MSP430. A client must wire
! * <code>AdcConfigure</code> to a component that returns the client's adc
! * configuration data.
*
! * @author Jan Hauer
! * @see Please refer to the README.txt and TEP 101 for more information about
! * this component and its intended use.
*/
***************
*** 58,66 ****
interface ReadNow<uint16_t>;
}
! uses interface Msp430Adc12Config;
} implementation {
! components AdcC,
#ifdef REF_VOLT_AUTO_CONFIGURE
! new Msp430Adc12RefVoltAutoClientC() as Msp430AdcClient;
#else
new Msp430Adc12ClientC() as Msp430AdcClient;
--- 50,61 ----
interface ReadNow<uint16_t>;
}
! uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
} implementation {
! components AdcP,
#ifdef REF_VOLT_AUTO_CONFIGURE
! // if the client configuration requires a stable
! // reference voltage, the reference voltage generator
! // is automatically enabled
! new Msp430Adc12ClientAutoRVGC() as Msp430AdcClient;
#else
new Msp430Adc12ClientC() as Msp430AdcClient;
***************
*** 71,80 ****
};
! ReadNow = AdcC.ReadNow[CLIENT];
! Msp430Adc12Config = AdcC.Config[CLIENT];
! AdcC.SingleChannel[CLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
! Resource = Msp430AdcClient.Resource;
#ifdef REF_VOLT_AUTO_CONFIGURE
! Msp430Adc12Config = Msp430AdcClient.Msp430Adc12Config;
#endif
}
--- 66,77 ----
};
! ReadNow = AdcP.ReadNow[CLIENT];
! AdcConfigure = AdcP.Config[CLIENT];
! AdcP.SingleChannel[CLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
! Resource = AdcP.ResourceReadNow[CLIENT];
!
! AdcP.SubResourceReadNow[CLIENT] -> Msp430AdcClient.Resource;
#ifdef REF_VOLT_AUTO_CONFIGURE
! AdcConfigure = Msp430AdcClient.AdcConfigure;
#endif
}
Index: AdcReadStreamClientC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/AdcReadStreamClientC.nc,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -C2 -d -r1.1.2.4 -r1.1.2.5
*** AdcReadStreamClientC.nc 19 Jun 2006 11:12:23 -0000 1.1.2.4
--- AdcReadStreamClientC.nc 9 Oct 2006 13:24:42 -0000 1.1.2.5
***************
*** 35,49 ****
/**
! * This component allows a client to access the MSP430 ADC12
! * (12-bit analog-to-digital converter) via the <code>ReadStream</code>
! * interface. A client must wire the <code>Msp430Adc12Config</code> interface
! * to a component that returns its ADC12 configuration data. Depending on the
! * REF_VOLT_AUTO_CONFIGURE switch (defined in Msp430Adc12.h) the internal
! * reference voltage generator is automatically enabled if and only if the
! * configuration data includes VREF as reference voltage.
*
! * @author Jan Hauer
! * @see Please refer to TEP 101 for more information about this component and its
! * intended use.
*/
--- 35,45 ----
/**
! * This component virtualizes the HIL of ADC12 on MSP430. A client must wire
! * <code>AdcConfigure</code> to a component that returns the client's adc
! * configuration data.
*
! * @author Jan Hauer
! * @see Please refer to the README.txt and TEP 101 for more information about
! * this component and its intended use.
*/
***************
*** 51,61 ****
generic configuration AdcReadStreamClientC() {
provides interface ReadStream<uint16_t>;
! uses interface Msp430Adc12Config;
} implementation {
! components AdcC,
#ifdef REF_VOLT_AUTO_CONFIGURE
! new Msp430Adc12RefVoltAutoClientC() as Msp430AdcClient;
#else
! new Msp430Adc12ClientC() as Msp430AdcClient;
#endif
--- 47,60 ----
generic configuration AdcReadStreamClientC() {
provides interface ReadStream<uint16_t>;
! uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
} implementation {
! components AdcP,
#ifdef REF_VOLT_AUTO_CONFIGURE
! // if the client configuration requires a stable
! // reference voltage, the reference voltage generator
! // is automatically enabled
! new Msp430Adc12ClientAutoRVGC() as Msp430AdcPlient;
#else
! new Msp430Adc12ClientC() as Msp430AdcPlient;
#endif
***************
*** 64,73 ****
};
! ReadStream = AdcC.ReadStream[RSCLIENT];
! Msp430Adc12Config = AdcC.ConfigReadStream[RSCLIENT];
! AdcC.SingleChannelReadStream[RSCLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
! AdcC.ResourceReadStream[RSCLIENT] -> Msp430AdcClient.Resource;
#ifdef REF_VOLT_AUTO_CONFIGURE
! Msp430Adc12Config = Msp430AdcClient.Msp430Adc12Config;
#endif
}
--- 63,72 ----
};
! ReadStream = AdcP.ReadStream[RSCLIENT];
! AdcConfigure = AdcP.ConfigReadStream[RSCLIENT];
! AdcP.SingleChannelReadStream[RSCLIENT] -> Msp430AdcPlient.Msp430Adc12SingleChannel;
! AdcP.ResourceReadStream[RSCLIENT] -> Msp430AdcPlient.Resource;
#ifdef REF_VOLT_AUTO_CONFIGURE
! AdcConfigure = Msp430AdcPlient.AdcConfigure;
#endif
}
Index: HplAdc12.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/HplAdc12.nc,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -C2 -d -r1.1.2.4 -r1.1.2.5
*** HplAdc12.nc 19 Jun 2006 11:12:23 -0000 1.1.2.4
--- HplAdc12.nc 9 Oct 2006 13:24:42 -0000 1.1.2.5
***************
*** 107,116 ****
/**
- * Returns the ADC12 interrupt flag register, ADC12IFG.
- * @return ADC12IFG
- */
- async command uint16_t getIFGs();
-
- /**
* Signals an ADC12MEMx overflow.
*/
--- 107,110 ----
***************
*** 134,202 ****
async command bool isBusy();
- /**
- * Sets the Sample-and-hold time flags, SHT0x and SHT1x.
- * Requires ENC-flag to be reset (disableConversion) !
- * @param sht Sample-and-hold, top 4 bits = SHT1x, lower 4 bits = SHT0x
- */
- async command void setSHT(uint8_t sht);
-
- /**
- * Sets the multiple sample and conversion flag, MSC in ADC12CTL0.
- * Requires ENC-flag to be reset (disableConversion) !
- */
- async command void setMSC();
-
- /**
- * Resets the multiple sample and conversion flag, MSC in ADC12CTL0.
- * Requires ENC-flag to be reset (disableConversion) !
- */
- async command void resetMSC();
-
- /**
- * Sets the REFON in ADC12CTL0.
- * Requires ENC-flag to be reset (disableConversion) !
- */
- async command void setRefOn();
-
- /**
- * Resets the REFON in ADC12CTL0.
- * Requires ENC-flag to be reset (disableConversion) !
- */
- async command void resetRefOn();
-
- /**
- * Returns the REFON flag in ADC12CTL0.
- * @return REFON
- */
- async command uint8_t getRefon();
-
- /**
- * Sets the reference generator voltage to 1.5V.
- * Requires ENC-flag to be reset (disableConversion) !
- */
- async command void setRef1_5V();
-
- /**
- * Sets the reference generator voltage to 2.5V.
- * Requires ENC-flag to be reset (disableConversion) !
- */
- async command void setRef2_5V();
-
- /**
- * Returns reference voltage level (REF2_5V flag).
- * @return 0 if reference generator voltage is 1.5V,
- * 1 if reference generator voltage is 2.5V
- */
- async command uint8_t isRef2_5V();
-
- /**
- * Enables a conversion (sets the ENC flag).
- */
- async command void enableConversion();
-
/**
! * Disables a conversion (resets the ENC flag).
*/
! async command void disableConversion();
/**
--- 128,135 ----
async command bool isBusy();
/**
! * Stops a conversion.
*/
! async command void stopConversion();
/**
***************
*** 205,222 ****
async command void startConversion();
- /**
- * Stops a conversion.
- */
- async command void stopConversion();
-
- /**
- * Switches the ADC12 off (ADC12ON flag).
- */
- async command void adcOff();
-
- /**
- * Switches the ADC12 off (ADC12ON flag).
- */
- async command void adcOn();
}
--- 138,141 ----
Index: HplAdc12P.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/HplAdc12P.nc,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -C2 -d -r1.1.2.2 -r1.1.2.3
*** HplAdc12P.nc 19 Jun 2006 11:12:23 -0000 1.1.2.2
--- HplAdc12P.nc 9 Oct 2006 13:24:42 -0000 1.1.2.3
***************
*** 104,140 ****
}
! 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.setRefOn(){ ADC12CTL0 |= REFON;}
! async command void HplAdc12.resetRefOn(){ ADC12CTL0 &= ~REFON;}
! async command uint8_t HplAdc12.getRefon(){ return (ADC12CTL0 & REFON) >> 5;}
! async command void HplAdc12.setRef1_5V(){ ADC12CTL0 &= ~REF2_5V;}
! async command void HplAdc12.setRef2_5V(){ ADC12CTL0 |= REF2_5V;}
! async command uint8_t HplAdc12.isRef2_5V(){ return (ADC12CTL0 & REF2_5V) >> 6;}
!
! 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 void HplAdc12.adcOff(){ ADC12CTL0 &= ~ADC12ON; }
! async command void HplAdc12.adcOn(){ ADC12CTL0 |= ADC12ON; }
TOSH_SIGNAL(ADC_VECTOR) {
--- 104,118 ----
}
! async command void HplAdc12.startConversion(){
! ADC12CTL0 |= ADC12ON;
! ADC12CTL0 |= (ADC12SC + ENC);
}
! async command void HplAdc12.stopConversion(){
! ADC12CTL0 &= ~(ADC12SC + ENC);
! ADC12CTL0 &= ~(ADC12ON);
}
! async command bool HplAdc12.isBusy(){ return ADC12CTL1 & ADC12BUSY; }
TOSH_SIGNAL(ADC_VECTOR) {
Index: Msp430Adc12.h
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12.h,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -C2 -d -r1.1.2.6 -r1.1.2.7
*** Msp430Adc12.h 31 Jan 2006 18:43:40 -0000 1.1.2.6
--- Msp430Adc12.h 9 Oct 2006 13:24:42 -0000 1.1.2.7
***************
*** 1,4 ****
/*
! * Copyright (c) 2004, Technische Universitaet Berlin
* All rights reserved.
*
--- 1,4 ----
/*
! * Copyright (c) 2006, Technische Universitaet Berlin
* All rights reserved.
*
***************
*** 43,73 ****
/*
! * The msp430adc12_channel_config_t encapsulates all relevant flags for
! * sampling a single ADC12 channel on a per-client basis. They are taken from
! * the following MSP430 registers: ADC12CTL0, ADC12CTL1, ADC12MCTLx and TACTL
! * of TimerA (if applicable) and named according to section "17.3 ADC12
! * Registers" of the "MSP430x1xx Family User's Guide",
! * http://focus.ti.com/lit/ug/slau049e/slau049e.pdf).
! *
! * .inch: ADC12 input channel (ADC12MCTLx register). An (external) input channel
! * maps to one of msp430's A0-A7 pins (see device specific data sheet).
*
! * .sref: reference voltage (ADC12MCTLx register). If
! * REFERENCE_VREFplus_AVss or REFERENCE_VREFplus_VREFnegterm is chosen
! * AND the client wires to Msp430Adc12RefVoltAutoClientC (or
! * REF_VOLT_AUTO_CONFIGURE is defined and the client wires to
! * AdcReadClientC, AdcReadNowClientC or AdcReadStreamClientC) then the
! * reference voltage generator is automatically switched on to the
! * voltage level defined by the "ref2_5v" flag (see below) whenever the
! * client accesses the ADC12. Otherwise both flags are ignored.
*
! * .ref2_5v: Reference generator voltage level (ADC12CTL0 register). See
! * explanation to "sref" flag.
*
! * .adc12ssel: ADC12 clock source select for the sample-hold-time
! * (ADC12CTL1 register). In combination the "adc12ssel", "adc12div" and
! * "sht" define the sample-hold-time: "adc12ssel" defines the clock
! * source, "adc12div" defines the ADC12 clock divider and "sht" define
! * the time expressed in jiffies.
*
* .adc12div: ADC12 clock divider (ADC12CTL1 register). See "adc12ssel".
--- 43,74 ----
/*
! * The msp430adc12_channel_config_t includes all relevant flags to configure
! * the ADC12 for single channel conversions. They are contained in the following
! * MSP430 registers: ADC12CTL0, ADC12CTL1, ADC12MCTLx and TACTL of TimerA (if
! * applicable) and named according to section "17.3 ADC12 Registers" of the
! * "MSP430x1xx Family User's Guide".
! *
! * **********************************
! *
! * .inch: ADC12 input channel (ADC12MCTLx register). An (external) input
! * channel maps to one of msp430's A0-A7 pins (see device specific data sheet).
*
! * .sref: reference voltage (ADC12MCTLx register). If REFERENCE_VREFplus_AVss
! * or REFERENCE_VREFplus_VREFnegterm is chosen AND the client wires to the
! * Msp430Adc12ClientAutoRVGC or Msp430Adc12ClientAutoDMA_RVGC component then
! * the reference voltage generator has automatically been enabled to the
! * voltage level defined by the "ref2_5v" flag (see below) when the
! * Resource.granted() event is signalled to the client. Otherwise this flag is
! * ignored.
*
! * .ref2_5v: Reference generator voltage level (ADC12CTL0 register). See "sref"
! * flag.
*
! * .adc12ssel: ADC12 clock source select for the sample-hold-time (ADC12CTL1
! * register). In combination the "adc12ssel", "adc12div" and "sht" define the
! * sample-hold-time: "adc12ssel" defines the clock source, "adc12div" defines
! * the ADC12 clock divider and "sht" define the time expressed in jiffies.
! * (the sample-hold-time depends on the resistence of the attached sensor, and
! * is calculated using to the formula in section 17.2.4 of the user guide)
*
* .adc12div: ADC12 clock divider (ADC12CTL1 register). See "adc12ssel".
***************
*** 75,119 ****
* .sht: Sample-and-hold time (ADC12CTL1 register). See "adc12ssel".
*
! * .sampcon_ssel: In combination with "sampcon_id" and the "jiffies"
! * parameter in the Msp430Adc12SingleChannel interface commands the
! * "sampcon_ssel" defines the sampling rate (TASSEL in TACTL register,
! * TimerA). It is the clock source for the SAMPCON signal, which
! * triggers the actual sampling. It is ignored when
! * Msp430Adc12SingleChannel.getSingleData() is used or the "jiffies"
! * parameter is zero; otherwise the SAMPCON signal is sourced from
! * TimerA, so that the multiple conversion mode can be made with the
! * user defined sampling rate.
*
! * .sampcon_id: Input divider for "sampcon_ssel" (IDx in TACTL
! * register, TimerA). See "sampcon_ssel".
*
*
* **********************************
*
! * EXAMPLE: Assuming that SMCLK runs at 1 MHz the following command fills the
! * user buffer with 2000 conversion results sampled on channel A2 with a
! * sampling rate of 4000 Hz, i.e. the multipleDataReady() event is signalled
! * after 500 ms. Note that the sampling rate is defined by the combination of
! * SAMPCON_SOURCE_SMCLK, SAMPCON_CLOCK_DIV_1 and the "jiffies" parameter of
! * 250.
! *
! *
! * uint16_t buffer[2000];
! * msp430adc12_channel_config_t config = {
! * INPUT_CHANNEL_A2, REFERENCE_VREFplus_AVss, REFVOLT_LEVEL_1_5,
! * SHT_SOURCE_SMCLK, SHT_CLOCK_DIV_1, SAMPLE_HOLD_64_CYCLES,
! * SAMPCON_SOURCE_SMCLK, SAMPCON_CLOCK_DIV_1
! * };
! *
! * event void Resource.granted()
! * {
! * if (call SingleChannel.getMultipleData(&config, buffer, 2000, 250)
! * == SUCCESS)
! * {
! * // .. multipleDataReady() event will be signalled in 500ms
! * } else {
! * // check error
! * }
! * }
*/
--- 76,124 ----
* .sht: Sample-and-hold time (ADC12CTL1 register). See "adc12ssel".
*
! * .sampcon_ssel: Clock source for the sampling period (TASSEL for TimerA).
! * When an ADC client specifies a non-zero "jiffies" parameter (passed in the
! * relevant Msp430Adc12SingleChannel interface commands), the ADC
! * implementation will automatically configure TimerA to be sourced from
! * "sampcon_ssel" with an input divider of "sampcon_id". During the sampling
! * process TimerA will then be used to trigger a conversion every "jiffies"
! * clock ticks.
*
! * .sampcon_id: Input divider for "sampcon_ssel" (IDx in TACTL register,
! * TimerA). See "sampcon_ssel".
*
*
* **********************************
*
! * EXAMPLE: Assuming that SMCLK runs at 1 MHz the following code snippet
! * performs 2000 ADC conversions on channel A2 with a sampling period of 4000 Hz.
! * The sampling period is defined by the combination of SAMPCON_SOURCE_SMCLK,
! * SAMPCON_CLOCK_DIV_1 and a "jiffies" parameter of (1000000 / 4000) = 250.
!
! #define NUM_SAMPLES 2000
! uint16_t buffer[NUM_SAMPLES];
!
! msp430adc12_channel_config_t config = {
! INPUT_CHANNEL_A2, REFERENCE_VREFplus_AVss, REFVOLT_LEVEL_NONE,
! SHT_SOURCE_SMCLK, SHT_CLOCK_DIV_1, SAMPLE_HOLD_64_CYCLES,
! SAMPCON_SOURCE_SMCLK, SAMPCON_CLOCK_DIV_1
! };
!
! event void Boot.booted()
! {
! call Resource.request();
! }
!
! event void Resource.granted()
! {
! error_t result;
! result = call SingleChannel.configureMultiple(&config, buffer, BUFFER_SIZE, 250);
! if (result == SUCCESS)
! call SingleChannel.getData();
! }
!
! async event uint16_t* SingleChannel.multipleDataReady(uint16_t *buf, uint16_t length)
! {
! // buffer contains conversion results
! }
*/
***************
*** 228,232 ****
#define ADCC_READ_STREAM_SERVICE "AdcC.ReadStream.Client"
-
typedef struct
{
--- 233,236 ----
Index: Msp430Adc12ClientC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12ClientC.nc,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -C2 -d -r1.1.2.5 -r1.1.2.6
*** Msp430Adc12ClientC.nc 19 Jun 2006 11:12:23 -0000 1.1.2.5
--- Msp430Adc12ClientC.nc 9 Oct 2006 13:24:42 -0000 1.1.2.6
***************
*** 1,4 ****
/*
! * Copyright (c) 2004, Technische Universitaet Berlin
* All rights reserved.
*
--- 1,4 ----
/*
! * Copyright (c) 2006, Technische Universitaet Berlin
* All rights reserved.
*
***************
*** 35,64 ****
/**
! * This component realizes the HAL1 representation and allows an
! * MSP430-specific client to access the MSP430 ADC12 (12-bit analog-to-digital
! * converter) via the <code>Msp430Adc12SingleChannel</code> and
! * <code>Resource</code> interface. According to TEP 108 a client must reserve
! * the ADC before using it via the <code>Resource</code> interface (otherwise
! * the request will fail). In contrast to the
! * <code>Msp430Adc12RefVoltAutoClientC</code> the
! * <code>Msp430Adc12ClientC</code> does not enable internal reference voltage
! * generator.
*
! * @author Jan Hauer
! * @see Please refer to TEP 101 for more information about this component and its
! * intended use.
*/
generic configuration Msp430Adc12ClientC()
{
! provides interface Resource;
! provides interface Msp430Adc12SingleChannel;
} implementation {
! components Msp430Adc12C;
enum {
ID = unique(MSP430ADC12_RESOURCE),
};
! Resource = Msp430Adc12C.Resource[ID];
! Msp430Adc12SingleChannel = Msp430Adc12C.SingleChannel[ID];
}
--- 35,59 ----
/**
! * This component virtualizes access to the HAL of the MSP430 ADC12.
*
! * @author Jan Hauer
! *
! * @see Please refer to the README.txt and TEP 101 for more information about
! * this component and its intended use.
*/
generic configuration Msp430Adc12ClientC()
{
! provides {
! interface Resource;
! interface Msp430Adc12SingleChannel;
! }
} implementation {
! components Msp430Adc12P;
enum {
ID = unique(MSP430ADC12_RESOURCE),
};
! Resource = Msp430Adc12P.Resource[ID];
! Msp430Adc12SingleChannel = Msp430Adc12P.SingleChannel[ID];
}
Index: Msp430Adc12P.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12P.nc,v
retrieving revision 1.1.2.9
retrieving revision 1.1.2.10
diff -C2 -d -r1.1.2.9 -r1.1.2.10
*** Msp430Adc12P.nc 7 Jul 2006 15:17:54 -0000 1.1.2.9
--- Msp430Adc12P.nc 9 Oct 2006 13:24:43 -0000 1.1.2.10
***************
*** 1,28 ****
/*
! * 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.
*
--- 1,28 ----
/*
! * Copyright (c) 2006, 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.
*
***************
*** 34,545 ****
*/
! #include <Msp430Adc12.h>
! module Msp430Adc12P
! {
! provides {
! interface Init;
! interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
! interface Msp430Adc12FastSingleChannel as FastSingleChannel[uint8_t id];
! }
! uses {
! interface ArbiterInfo as ADCArbiterInfo;
! interface HplAdc12;
! interface Msp430Timer as TimerA;
! interface Msp430TimerControl as ControlA0;
! interface Msp430TimerControl as ControlA1;
! interface Msp430Compare as CompareA0;
! interface Msp430Compare as CompareA1;
! interface HplMsp430GeneralIO as Port60;
! interface HplMsp430GeneralIO as Port61;
! interface HplMsp430GeneralIO as Port62;
! interface HplMsp430GeneralIO as Port63;
! interface HplMsp430GeneralIO as Port64;
! interface HplMsp430GeneralIO as Port65;
! interface HplMsp430GeneralIO as Port66;
! interface HplMsp430GeneralIO as Port67;
!
! }
! }
! implementation
{
! enum { // conversionMode
! SINGLE_DATA,
! SINGLE_DATA_REPEAT,
! MULTIPLE_DATA,
! MULTIPLE_DATA_REPEAT,
! };
! enum { // flags
! ADC_BUSY = 1, /* request pending */
! TIMERA_USED = 2, /* TimerA used for SAMPCON signal */
! FAST_MODE = 4,
! };
!
! uint16_t *resultBuffer; /* result buffer */
! uint16_t resultBufferLength; /* length of buffer */
! uint16_t resultBufferIndex; /* offset into buffer */
! norace uint8_t clientID; /* ID of interface that issued current request */
! norace uint8_t flags; /* current state, see above */
!
! // norace is safe, because Resource interface resolves conflicts
! norace uint8_t conversionMode; /* current conversion conversionMode, see above */
!
! command error_t Init.init()
! {
! call HplAdc12.disableConversion();
! call HplAdc12.adcOff();
! return SUCCESS;
! }
!
! error_t clientAccessRequest(uint8_t id)
! {
! atomic {
! if (call ADCArbiterInfo.userId() == id){
! if (flags & ADC_BUSY)
! return EBUSY;
! flags = ADC_BUSY;
! clientID = id;
! return SUCCESS;
! }
! }
! return ERESERVE;
! }
!
! inline void clientAccessFinished()
! {
! atomic flags = 0;
! }
!
! void prepareTimerA(uint16_t interval, uint16_t csSAMPCON, uint16_t cdSAMPCON)
! {
! 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 TimerA.setMode(MSP430TIMER_STOP_MODE);
! call TimerA.clear();
! call TimerA.disableEvents();
! call TimerA.setClockSource(csSAMPCON);
! call TimerA.setInputDivider(cdSAMPCON);
! call ControlA0.setControl(ccResetSHI);
! call CompareA0.setEvent(interval-1);
! call CompareA1.setEvent((interval-1)/2);
! }
!
! void startTimerA()
! {
! 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 };
! 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 };
! msp430_compare_control_t ccRSOutmod = {
! ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0,
! outmod : 7, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 };
! // manually trigger first conversion, then switch to Reset/set conversionMode
! call ControlA1.setControl(ccResetSHI);
! call ControlA1.setControl(ccSetSHI);
! //call ControlA1.setControl(ccResetSHI);
! call ControlA1.setControl(ccRSOutmod);
! call TimerA.setMode(MSP430TIMER_UP_MODE); // go!
! }
!
! void configureAdcPin( uint8_t inch )
! {
! #ifdef P6PIN_AUTO_CONFIGURE
! switch (inch)
! {
! case 0: call Port60.selectModuleFunc(); call Port60.makeInput(); break;
! case 1: call Port61.selectModuleFunc(); call Port61.makeInput(); break;
! case 2: call Port62.selectModuleFunc(); call Port62.makeInput(); break;
! case 3: call Port63.selectModuleFunc(); call Port63.makeInput(); break;
! case 4: call Port64.selectModuleFunc(); call Port64.makeInput(); break;
! case 5: call Port65.selectModuleFunc(); call Port65.makeInput(); break;
! case 6: call Port66.selectModuleFunc(); call Port66.makeInput(); break;
! case 7: call Port67.selectModuleFunc(); call Port67.makeInput(); break;
! }
! #endif
! }
!
! void resetAdcPin( uint8_t inch )
! {
! #ifdef P6PIN_AUTO_CONFIGURE
! switch (inch)
! {
! case 0: call Port60.selectIOFunc(); break;
! case 1: call Port61.selectIOFunc(); break;
! case 2: call Port62.selectIOFunc(); break;
! case 3: call Port63.selectIOFunc(); break;
! case 4: call Port64.selectIOFunc(); break;
! case 5: call Port65.selectIOFunc(); break;
! case 6: call Port66.selectIOFunc(); break;
! case 7: call Port67.selectIOFunc(); break;
! }
! #endif
! }
!
! void stopConversionSingleChannel()
! {
! adc12memctl_t memctl = call HplAdc12.getMCtl(0);
! if (flags & TIMERA_USED){
! call TimerA.setMode(MSP430TIMER_STOP_MODE);
! }
! resetAdcPin( memctl.inch );
! call HplAdc12.stopConversion();
! call HplAdc12.adcOff();
! call HplAdc12.setIEFlags(0);
! call HplAdc12.resetIFGs();
! clientAccessFinished();
! }
!
! error_t configureSingleData(uint8_t id, const msp430adc12_channel_config_t *config)
! {
! error_t result;
! #ifdef CHECK_ARGS
! if (!config)
! return EINVAL;
! #endif
! if ((result = clientAccessRequest(id)) == SUCCESS)
! {
! adc12ctl0_t ctl0 = {
! adc12sc: 0,
! enc: 0,
! adc12tovie: 0,
! adc12ovie: 0,
! adc12on: 1,
! refon: call HplAdc12.getRefon(),
! r2_5v: call HplAdc12.isRef2_5V(),
! msc: 1,
! sht0: config->sht,
! sht1: config->sht
! };
! adc12ctl1_t ctl1 = {
! adc12busy: 0,
! conseq: 0,
! adc12ssel: config->adc12ssel,
! adc12div: config->adc12div,
! issh: 0,
! shp: 1,
! shs: 0,
! cstartadd: 0
! };
! adc12memctl_t memctl = {
! inch: config->inch,
! sref: config->sref,
! eos: 1
! };
! conversionMode = SINGLE_DATA;
! configureAdcPin( config->inch );
! call HplAdc12.setCtl0(ctl0);
! call HplAdc12.setCtl1(ctl1);
! call HplAdc12.setMCtl(0, memctl);
! call HplAdc12.setIEFlags(0x01);
! //call HplAdc12.startConversion();
! }
! return result;
! }
!
! async command error_t SingleChannel.getSingleData[uint8_t id](
! const msp430adc12_channel_config_t *config)
! {
! error_t result = configureSingleData(id, config);
! if (result == SUCCESS)
! call HplAdc12.startConversion();
! return result;
! }
!
! async command error_t FastSingleChannel.configure[uint8_t id](const msp430adc12_channel_config_t *config)
! {
! return configureSingleData(id, config);
! }
!
! async command error_t FastSingleChannel.getSingleData[uint8_t id]()
! {
! if (clientID == id){
! flags |= FAST_MODE;
! call HplAdc12.startConversion();
! return SUCCESS;
! }
! return FAIL;
! }
!
! async command error_t SingleChannel.getSingleDataRepeat[uint8_t id](
! const msp430adc12_channel_config_t *config,
! uint16_t jiffies)
! {
! error_t result;
! #ifdef CHECK_ARGS
! if (!config || jiffies == 1 || jiffies == 2)
! return EINVAL;
! #endif
! if ((result = clientAccessRequest(id)) == SUCCESS)
! {
! adc12ctl0_t ctl0 = {
! adc12sc: 0,
! enc: 0,
! adc12tovie: 0,
! adc12ovie: 0,
! adc12on: 1,
! refon: call HplAdc12.getRefon(),
! r2_5v: call HplAdc12.isRef2_5V(),
! msc: (jiffies == 0) ? 1 : 0,
! sht0: config->sht,
! sht1: config->sht
! };
! adc12ctl1_t ctl1 = {
! adc12busy: 0,
! conseq: 2,
! adc12ssel: config->adc12ssel,
! adc12div: config->adc12div,
! issh: 0,
! shp: 1,
! shs: (jiffies == 0) ? 0 : 1,
! cstartadd: 0
! };
! adc12memctl_t memctl = {
! inch: config->inch,
! sref: config->sref,
! eos: 1
! };
! conversionMode = SINGLE_DATA_REPEAT;
! configureAdcPin( config->inch );
! call HplAdc12.setCtl0(ctl0);
! call HplAdc12.setCtl1(ctl1);
! call HplAdc12.setMCtl(0, memctl);
! call HplAdc12.setIEFlags(0x01);
! if (jiffies){
! atomic flags |= TIMERA_USED;
! prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id);
! }
! call HplAdc12.startConversion();
! if (jiffies)
! startTimerA(); // go!
! }
! return result;
! }
!
! async command error_t SingleChannel.getMultipleData[uint8_t id](
! const msp430adc12_channel_config_t *config,
! uint16_t *buf, uint16_t length, uint16_t jiffies)
! {
! error_t result;
! #ifdef CHECK_ARGS
! if (!config || !buf || !length || jiffies == 1 || jiffies == 2)
! return EINVAL;
! #endif
! if ((result = clientAccessRequest(id)) == SUCCESS)
! {
! adc12ctl0_t ctl0 = {
! adc12sc: 0,
! enc: 0,
! adc12tovie: 0,
! adc12ovie: 0,
! adc12on: 1,
! refon: call HplAdc12.getRefon(),
! r2_5v: call HplAdc12.isRef2_5V(),
! msc: (jiffies == 0) ? 1 : 0,
! sht0: config->sht,
! sht1: config->sht
! };
! adc12ctl1_t ctl1 = {
! adc12busy: 0,
! conseq: (length > 16) ? 3 : 1,
! adc12ssel: config->adc12ssel,
! adc12div: config->adc12div,
! issh: 0,
! shp: 1,
! shs: (jiffies == 0) ? 0 : 1,
! cstartadd: 0
! };
! adc12memctl_t memctl = {
! inch: config->inch,
! sref: config->sref,
! eos: 0
! };
! uint16_t i, mask = 1;
! conversionMode = MULTIPLE_DATA;
! atomic {
! resultBuffer = buf;
! resultBufferLength = length;
! resultBufferIndex = 0;
! }
! configureAdcPin( config->inch );
! call HplAdc12.setCtl0(ctl0);
! call HplAdc12.setCtl1(ctl1);
! for (i=0; i<(length-1) && i < 15; i++)
! call HplAdc12.setMCtl(i, memctl);
! memctl.eos = 1;
! call HplAdc12.setMCtl(i, memctl);
! call HplAdc12.setIEFlags(mask << i);
!
! if (jiffies){
! atomic flags |= TIMERA_USED;
! prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id);
! }
! call HplAdc12.startConversion();
! if (jiffies)
! startTimerA(); // go!
! }
! return result;
! }
!
! async command error_t SingleChannel.getMultipleDataRepeat[uint8_t id](
! const msp430adc12_channel_config_t *config,
! uint16_t *buf, uint8_t length, uint16_t jiffies)
! {
! error_t result;
! #ifdef CHECK_ARGS
! if (!config || !buf || !length || length > 16 || jiffies == 1 || jiffies == 2)
! return EINVAL;
! #endif
! if ((result = clientAccessRequest(id)) == SUCCESS)
! {
! adc12ctl0_t ctl0 = {
! adc12sc: 0,
! enc: 0,
! adc12tovie: 0,
! adc12ovie: 0,
! adc12on: 1,
! refon: call HplAdc12.getRefon(),
! r2_5v: call HplAdc12.isRef2_5V(),
! msc: (jiffies == 0) ? 1 : 0,
! sht0: config->sht,
! sht1: config->sht
! };
! adc12ctl1_t ctl1 = {
! adc12busy: 0,
! ctl1.conseq = 3,
! adc12ssel: config->adc12ssel,
! adc12div: config->adc12div,
! issh: 0,
! shp: 1,
! shs: (jiffies == 0) ? 0 : 1,
! cstartadd: 0
! };
! adc12memctl_t memctl = {
! inch: config->inch,
! sref: config->sref,
! eos: 0
! };
! uint16_t i, mask = 1;
! conversionMode = MULTIPLE_DATA_REPEAT;
! atomic {
! resultBuffer = buf;
! resultBufferLength = length;
! resultBufferIndex = 0;
! }
! configureAdcPin( config->inch );
! call HplAdc12.setCtl0(ctl0);
! call HplAdc12.setCtl1(ctl1);
! for (i=0; i<(length-1) && i < 15; i++)
! call HplAdc12.setMCtl(i, memctl);
! memctl.eos = 1;
! call HplAdc12.setMCtl(i, memctl);
! call HplAdc12.setIEFlags(mask << i);
!
! if (jiffies){
! atomic flags |= TIMERA_USED;
! prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id);
! }
! call HplAdc12.startConversion();
! if (jiffies)
! startTimerA(); // go!
! }
! return result;
! }
!
! async event void TimerA.overflow(){}
! async event void CompareA0.fired(){}
! async event void CompareA1.fired(){}
!
!
! async event void HplAdc12.conversionDone(uint16_t iv)
! {
! switch (conversionMode)
! {
! case SINGLE_DATA:
! if (flags & FAST_MODE){
! #ifdef P6PIN_AUTO_CONFIGURE
! adc12memctl_t memctl = call HplAdc12.getMCtl(0);
! resetAdcPin( memctl.inch );
! #endif
! clientAccessFinished();
! // stopConversionSingleChannel()
! signal FastSingleChannel.singleDataReady[clientID](call HplAdc12.getMem(0));
! } else {
! stopConversionSingleChannel();
! signal SingleChannel.singleDataReady[clientID](call HplAdc12.getMem(0));
! }
! break;
! case SINGLE_DATA_REPEAT:
! {
! error_t repeatContinue;
! repeatContinue = signal SingleChannel.singleDataReady[clientID](
! call HplAdc12.getMem(0));
! if (repeatContinue == FAIL)
! stopConversionSingleChannel();
! break;
! }
! case MULTIPLE_DATA:
! {
! uint16_t i = 0, length;
! if (resultBufferLength - resultBufferIndex > 16)
! length = 16;
! else
! length = resultBufferLength - resultBufferIndex;
! do {
! *resultBuffer++ = call HplAdc12.getMem(i);
! } while (++i < length);
! resultBufferIndex += length;
!
! if (resultBufferLength - resultBufferIndex > 15)
! return;
! else if (resultBufferLength - resultBufferIndex > 0){
! adc12memctl_t memctl = call HplAdc12.getMCtl(0);
! memctl.eos = 1;
! call HplAdc12.setMCtl(resultBufferLength - resultBufferIndex, memctl);
! } else {
! stopConversionSingleChannel();
! signal SingleChannel.multipleDataReady[clientID](
! resultBuffer - resultBufferLength, resultBufferLength);
! }
! }
! break;
! case MULTIPLE_DATA_REPEAT:
! {
! uint8_t i = 0;
! do {
! *resultBuffer++ = call HplAdc12.getMem(i);
! } while (++i < resultBufferLength);
!
! resultBuffer = signal SingleChannel.multipleDataReady[clientID](
! resultBuffer-resultBufferLength,
! resultBufferLength);
! if (!resultBuffer)
! stopConversionSingleChannel();
! break;
! }
! } // switch
}
! default async event error_t SingleChannel.singleDataReady[uint8_t id](uint16_t data)
! {
! return FAIL;
! }
!
! default async event void FastSingleChannel.singleDataReady[uint8_t id](uint16_t data)
! {
! return;
! }
!
! default async event uint16_t* SingleChannel.multipleDataReady[uint8_t id](
! uint16_t *buf, uint16_t length)
! {
! return 0;
! }
! async event void HplAdc12.memOverflow(){}
! async event void HplAdc12.conversionTimeOverflow(){}
}
--- 34,70 ----
*/
! #include <Msp430Adc12.h>
! configuration Msp430Adc12P
{
! provides {
! interface Resource[uint8_t id];
! interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id];
! interface AsyncStdControl as DMAExtension[uint8_t id];
}
+ } implementation {
+ components Msp430Adc12ImplP, HplAdc12P, Msp430TimerC, MainC, HplMsp430GeneralIOC,
+ new SimpleRoundRobinArbiterC(MSP430ADC12_RESOURCE) as Arbiter;
! Resource = Arbiter;
! SingleChannel = Msp430Adc12ImplP.SingleChannel;
! DMAExtension = Msp430Adc12ImplP.DMAExtension;
! Msp430Adc12ImplP.Init <- MainC;
! Msp430Adc12ImplP.ADCArbiterInfo -> Arbiter;
! Msp430Adc12ImplP.HplAdc12 -> HplAdc12P;
! Msp430Adc12ImplP.Port60 -> HplMsp430GeneralIOC.Port60;
! Msp430Adc12ImplP.Port61 -> HplMsp430GeneralIOC.Port61;
! Msp430Adc12ImplP.Port62 -> HplMsp430GeneralIOC.Port62;
! Msp430Adc12ImplP.Port63 -> HplMsp430GeneralIOC.Port63;
! Msp430Adc12ImplP.Port64 -> HplMsp430GeneralIOC.Port64;
! Msp430Adc12ImplP.Port65 -> HplMsp430GeneralIOC.Port65;
! Msp430Adc12ImplP.Port66 -> HplMsp430GeneralIOC.Port66;
! Msp430Adc12ImplP.Port67 -> HplMsp430GeneralIOC.Port67;
+ Msp430Adc12ImplP.TimerA -> Msp430TimerC.TimerA;
+ Msp430Adc12ImplP.ControlA0 -> Msp430TimerC.ControlA0;
+ Msp430Adc12ImplP.ControlA1 -> Msp430TimerC.ControlA1;
+ Msp430Adc12ImplP.CompareA0 -> Msp430TimerC.CompareA0;
+ Msp430Adc12ImplP.CompareA1 -> Msp430TimerC.CompareA1;
}
Index: Msp430Adc12SingleChannel.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12SingleChannel.nc,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -C2 -d -r1.1.2.6 -r1.1.2.7
*** Msp430Adc12SingleChannel.nc 7 Jul 2006 15:17:54 -0000 1.1.2.6
--- Msp430Adc12SingleChannel.nc 9 Oct 2006 13:24:43 -0000 1.1.2.7
***************
*** 1,4 ****
/*
! * Copyright (c) 2004, Technische Universitaet Berlin
* All rights reserved.
*
--- 1,4 ----
/*
! * Copyright (c) 2006, Technische Universitaet Berlin
* All rights reserved.
*
***************
*** 35,148 ****
/**
! * This interface exports access to the ADC12 on the level of
! * HAL1 on a per-channel basis. It allows to sample a channel once or
! * repeatedly (and signal an event per conversion result) or perform multiple
! * conversions for the same channel once or repeatedly (and signal an event per
! * multiple conversion results). It does not allow to sample different channels
! * with the same command.
*
! * @author Jan Hauer
! * @see Please refer to TEP 101 for more information about this component and its
! * intended use.
*/
! #include <Msp430Adc12.h>
interface Msp430Adc12SingleChannel
{
/**
! * Samples an ADC channel once. If SUCCESS is returned, an event
! * <code>singleDataReady()</code> will be signalled with the conversion
! * result. Otherwise <code>singleDataReady()</code> will not be signalled.
*
* @param config ADC12 configuration data.
! * @return SUCCESS means conversion data will be signalled in
! * <code>singleDataReady()</code>.
*/
! async command error_t getSingleData(const msp430adc12_channel_config_t *config);
! /** Samples an ADC channel repeatedly and signals an event
! * <code>singleDataReady()</code> after every single conversion. Conversion
! * result are signalled, until the client returns <code>FAIL</code> in the
! * <code>singleDataReady()</code> event handler. If this command does not
! * return SUCCESS then <code>singleDataReady()</code> will not be
! * signalled.<br><br> 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 "sampcon_ssel" and input divider "sampcon_id" as
! * specified in the <code>config</code> parameter.
*
* @param config ADC12 configuration data.
! * @param jiffies Sampling rate in terms of clock ticks of
! * "sampcon_ssel" and input divider "sampcon_id".
! * @return SUCCESS means conversion data will be signalled in
! * <code>singleDataReady()</code> until the client returns <code>FAIL</code>.
*/
! async command error_t getSingleDataRepeat(const msp430adc12_channel_config_t *config,
! uint16_t jiffies);
! /**
! *
! * Samples an ADC channel multiple times and signals one event
! * <code>multipleDataReady()</code> with all conversion results. If SUCCESS
! * is returned, the event <code>multipleDataReady</code> is signalled after
! * the buffer is filled with conversion results, otherwise
! * <code>multipleDataReady()</code> will not be signalled. <br><br>
! * 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
! * "sampcon_ssel" and input divider "sampcon_id" as specified in the
! * <code>config</code> parameter.
! *
! * @param config ADC12 configuration data.
! * @param jiffies Sampling rate in terms of clock ticks of
! * "sampcon_ssel" and input divider "sampcon_id".
! * @param buffer The buffer to store the conversion results. It must have a
! * minimum size of <code>numSamples * 2</code> byte !
! * @param numSamples Number of samples to take, buffer size must be greater or
! * equal than <code>numSamples * 2</code> byte !
! * @return SUCCESS means conversion data will be signalled in
! * <code>singleDataReady()</code>.
! */
! async command error_t getMultipleData( const msp430adc12_channel_config_t *config,
! uint16_t *buffer, uint16_t numSamples, uint16_t jiffies);
- /**
- *
- * Samples an ADC channel up to 16 times and signals an event
- * <code>multipleDataReady()</code> with all conversion results repeatedly.
- * If SUCCESS is returned, the event <code>multipleDataReady</code> is
- * signalled after the buffer is filled with the first (up to 16) conversion
- * results, otherwise <code>multipleDataReady()</code> will not be signalled.
- * The conversion result are signalled repeatedly, until the client returns
- * <code>FAIL</code> in the <code>multipleDataReady()</code> event handler.
- * <br><br> 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
- * "sampcon_ssel" and input divider "sampcon_id" as specified in the
- * <code>config</code> parameter.
- *
- * @param config ADC12 configuration data. @param jiffies Jiffies in terms of
- * clock ticks of "sampcon_ssel" and input divider "sampcon_id". @param
- * buffer The buffer to store the conversion results. It must have a minimum
- * size of <code>numSamples * 2</code> byte !
- * @param jiffies Sampling rate in terms of clock ticks of
- * "sampcon_ssel" and input divider "sampcon_id".
- * @param numSamples Number of samples to take, 1 <= numSamples <= 16, buffer
- * size must be greater or equal than <code>numSamples * 2</code> byte !
- * @return SUCCESS means conversion data will be signalled in
- * <code>singleDataReady()</code> until the client returns <code>FAIL</code>.
- */
- async command error_t getMultipleDataRepeat(const msp430adc12_channel_config_t *config,
- uint16_t *buffer, uint8_t numSamples, uint16_t jiffies);
/**
! * Data from a call to <code>getSingleData()</code> or
! * <code>getSingleDataRepeat()</code> is ready. In the first case the return
! * value is ignored, in the second it defines whether another conversion
! * takes place (<code>SUCCESS()</code>) or not (<code>FAIL</code>).
*
* @param data Conversion result (lower 12 bit).
* @return If this event is signalled as response to a call to
! * <code>getSingleDataRepeat()</code> then <code>SUCCESS</code> results in
* another sampling and <code>FAIL</code> stops the repeated sampling.
* Otherwise the return value is ignored.
--- 35,205 ----
/**
! *
! * This interface provides access to the ADC12 on the level of HAL. It can be
! * used to sample an adc channel once or repeatedly (one event is signalled per
! * conversion result) or perform multiple conversions for a channel once or
! * repeatedly (one event is signalled per multiple conversion results). It
! * cannot be used to sample different adc channels with a single command.
! * Sampling a channel requires calling a sequence of two commands, configureX()
! * and getData(), where X is either 'Single', 'SingleRepeat', 'Multiple' or
! * 'MultipleRepeat'. Conversion results will be signalled by the
! * dataReadySingle() or dataReadyMultiple() event, depending on the previous
! * configuration, i.e. there are four possible sequences:
! *
! * configureSingle() -> [ getData() -> singleDataReady() ]*
! * or configureSingleRepeat() -> [ getData() -> singleDataReady() ]*
! * or configureMultiple() -> [ getData() -> multipleDataReady() ]*
! * or configureMultipleRepeat() -> getData() -> multipleDataReady()
*
! * where configureX() and getData() are commands called by the client and
! * singleDataReady() and multipleDataReady() are events signalled back to the
! * client by the adc subsystem. Note that a configuration is valid until
! * the client reconfigures or releases the ADC (using the Resource
! * interface), except for configureMultipleRepeat(), which is only valid
! * for a single call to getData(). This means that after a successful
! * configuration with, for example, configureSingle() the client may call
! * getData() more than once without reconfiguring the ADC in between
! * (if the client has not released the ADC via the Resource interface).
! *
! * @author Jan Hauer
*/
! #include "Msp430Adc12.h"
interface Msp430Adc12SingleChannel
{
+
/**
! * Configures the ADC to perform a single conversion. Any previous
! * configuration will be overwritten. If SUCCESS is returned calling
! * <code>getData()</code> will start the conversion immediately and a
! * <code>singleDataReady()</code> event will be signalled with the conversion
! * result when the conversion has finished.
*
* @param config ADC12 configuration data.
! *
! * @return SUCCESS means that the ADC was configured successfully and
! * <code>getData()</code> can be called to start the conversion.
*/
! async command error_t configureSingle(const msp430adc12_channel_config_t *config);
! /**
! * Configures the ADC for repeated single channel conversion mode. Any
! * previous configuration will be overwritten. If SUCCESS is returned calling
! * <code>getData()</code> will start sampling the adc channel periodically
! * (the first conversion is started immediately). The sampling period is
! * specified by the <code>jiffies</code> parameter, which defines the time
! * between successive conversions in terms of clock ticks of clock source
! * "sampcon_ssel" and clock input divider "sampcon_id" as specified in the
! * <code>config</code> parameter. If jiffies is zero successive conversions
! * are performed as quickly as possible. Conversion result are signalled
! * until the client returns <code>FAIL</code> in the
! * <code>singleDataReady()</code> event handler.
*
* @param config ADC12 configuration data.
! * @param jiffies Sampling period in terms of clock ticks of "sampcon_ssel" and
! * input divider "sampcon_id".
! *
! * @return SUCCESS means that the ADC was configured successfully and
! * <code>getData()</code> can be called to start with the first conversion.
*/
! async command error_t configureSingleRepeat(const msp430adc12_channel_config_t *config, uint16_t jiffies);
!
! /**
! * Configures the ADC for sampling a channel <code>numSamples</code> times
! * with a given sampling period. Any previous configuration will be
! * overwritten. In contrast to the <code>configureSingleRepeat()</code>
! * command, this configuration means that only one event will be signalled
! * after all samples have been taken (which is useful for high-frequency
! * sampling). If SUCCESS is returned calling <code>getData()</code> will
! * start sampling the adc channel <code>numSamples</code> times and the first
! * conversion is started immediately. Conversion results are stored in a
! * buffer allocated by the client (the <code>buffer</code>
! * parameter). The sampling period is specified by the <code>jiffies</code>
! * parameter, which defines the time between successive conversions in terms
! * of clock ticks of clock source "sampcon_ssel" and clock input divider
! * "sampcon_id" as specified in the <code>config</code> parameter. If jiffies
! * is zero successive conversions are performed as quickly as possible. After
! * <code>numSamples</code> conversions an event
! * <code>multipleDataReady()</code> is signalled with the conversion results.
! *
! * @param config ADC12 configuration data.
! * @param jiffies Sampling period in terms of clock ticks of "sampcon_ssel"
! * and input divider "sampcon_id".
! * @param buffer The user-allocated buffer in which the conversion results
! * will be stored. It must have at least <code>numSamples</code> entries,
! * i.e. it must have a size of at least <code>numSamples</code> * 2 byte.
! * @param numSamples Number of adc samples
! *
! * @return SUCCESS means that the ADC was configured successfully and
! * <code>getData()</code> can be called to start with the first conversion.
! */
! async command error_t configureMultiple( const msp430adc12_channel_config_t *config, uint16_t buffer[], uint16_t numSamples, uint16_t jiffies);
!
! /**
! *
! * Configures the ADC for sampling a channel multiple times repeatedly. Any
! * previous configuration will be overwritten. In contrast to the
! * <code>configureSingleRepeat()</code> command this configuration means that
! * an event with <code>numSamples</code> conversion results will be
! * signalled, where 0 < <code>numSamples</code> <= 16. In contrast to the
! * <code>configureMultiple()</code> command, this configuration means that
! * <code>numSamples</code> conversion results will be signalled repeatedly
! * until the client returns <code>FAIL</code> in the
! * <code>multipleDataReady()</code> event handler.
! *
! * If <code>configureMultipleRepeat()</code> returns SUCCESS calling
! * <code>getData()</code> will start the the first conversion immediately.
! * The sampling period is specified by the <code>jiffies</code> parameter,
! * which defines the time between successive conversions in terms of clock
! * ticks of clock source "sampcon_ssel" and clock input divider "sampcon_id"
! * as specified in the <code>config</code> parameter. If jiffies is zero
! * successive conversions are performed as quickly as possible. After
! * <code>numSamples</code> conversions an event
! * <code>multipleDataReady()</code> is signalled with <code>numSamples</code>
! * conversion results. If the client returns <code>SUCCESS</code> in the
! * <code>multipleDataReady()</code> event handler, <code>numSamples</code>
! * new conversions will be performed, otherwise not.
! *
! * @param config ADC12 configuration data.
! * @param jiffies Sampling period in terms of clock ticks of "sampcon_ssel"
! * and input divider "sampcon_id".
! * @param buffer The user-allocated buffer in which the conversion results
! * will be stored. It must have at least <code>numSamples</code> entries,
! * i.e. it must have a size of at least <code>numSamples</code> * 2 byte.
! * @param numSamples Number of adc samples to take, 0 <
! * <code>numSamples</code> <= 16
! *
! * @return SUCCESS means that the ADC was configured successfully and
! * <code>getData()</code> can be called to start with the first conversion.
! */
! async command error_t configureMultipleRepeat(const msp430adc12_channel_config_t *config, uint16_t buffer[], uint8_t numSamples, uint16_t jiffies);
/**
! * Starts sampling an adc channel using the configuration as specified by
! * the last call to any of the four available configuration commands.
! *
! * @return SUCCESS means that the conversion was started successfully and an
! * event singleDataReady() or multipleDataReady() will be signalled
! * (depending on the previous configuration). Otherwise no such event will be
! * signalled.
! */
! async command error_t getData();
!
! /**
! * A single ADC conversion result is ready. If the ADC was configured with
! * the <code>configureSingle()</code> command, then the return value is
! * ignored. If the ADC was configured with the
! * <code>configureSingleRepeat()</code> command then the return value tells
! * whether another conversion should be performed (<code>SUCCESS()</code>) or
! * not (<code>FAIL</code>). If <code>SUCCESS()</code> is returned then the
! * sampling period will be as specified in the
! * <code>configureSingleRepeat()</code> command.
*
* @param data Conversion result (lower 12 bit).
+ *
* @return If this event is signalled as response to a call to
! * <code>configureSingleRepeat()</code> then <code>SUCCESS</code> results in
* another sampling and <code>FAIL</code> stops the repeated sampling.
* Otherwise the return value is ignored.
***************
*** 151,169 ****
/**
! * Data from a call to <code>getMultipleData()</code> or
! * <code>getMultipleDataRepeat()</code> is ready. In the first case the
! * return value is ignored, in the second a non-zero pointer defines where to
! * store the next <code>numSamples</code> conversion results and a null
! * pointer stops the repeated conversion mode.
*
! * @param buffer Conversion results (lower 12 bit are valid).
* @param numSamples Number of samples stored in <code>buffer</code>
! * @return A null pointer stops a repeated conversion mode. Any non-zero
! * value is interpreted as the next buffer, which must have size
! * <code>numSamples 2</code> byte!). Ignored if this event is a response to
! * <code>getMultipleData()</code>.
*/
! async event uint16_t* multipleDataReady(uint16_t *bu