[Tinyos-commits] CVS: tinyos-1.x/tos/platform/msp430/dac
HPLDAC12.nc, NONE, 1.1 HPLDAC12M.nc, NONE, 1.1 MSP430DAC.nc,
NONE, 1.1 MSP430DAC12.h, NONE, 1.1 MSP430DAC12C.nc, NONE,
1.1 MSP430DAC12M.nc, NONE, 1.1
Joe Polastre
jpolastre at users.sourceforge.net
Wed Sep 28 03:41:13 PDT 2005
Update of /cvsroot/tinyos/tinyos-1.x/tos/platform/msp430/dac
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30738/msp430/dac
Added Files:
HPLDAC12.nc HPLDAC12M.nc MSP430DAC.nc MSP430DAC12.h
MSP430DAC12C.nc MSP430DAC12M.nc
Log Message:
complete reorganization of ADC to support DMA and DAC modules
Changes to the ADC include:
The ADC no longer directly accesses TimerA. Instead it uses
the TimerExclusive interface in MSP430TimerAExclusive to gain
exclusive lock on TimerA. It releases TimerA when it is done.
This is necessary for other components that would like to use
TimerA to do so, such as the DAC.
Commands for the DMA have been added to the MSP430Single and
MSP430Multiple ADC interfaces. These include startSampling,
stopSampling, pauseSampling, and resumeSampling. They should only
be used in conjunction with the DMA and never as standalone functions.
A TinyOS driver for the DAC is being committed that uses the
newly created TimerExclusive interface to get access to TimerA.
It also supports DMA use.
The DMA has been rearchitected to follow the namespace of the other
components with minor bug fixes.
The ADC, DAC, and DMA have been moved to their own subdirectories to
make life easier when viewing the msp430 platform. Platforms that
rely on these components must now include the following lines in the
@opts section of their .platform file:
-I%T/platform/msp430/adc
-I%T/platform/msp430/dac
-I%T/platform/msp430/dma
A sample application is being checked in to
apps/TestMSP430DMA/
that includes TestADC12DMAC for reading multiple samples from the ADC
and also TestDAC12DMAC for sending multiple readings via the DAC
Although I spearheaded much of the DAC efforts, credit goes to
Ben Greenstein for fixes to the ADC and much of the DMA code that I based
this new implementation on.
--- NEW FILE: HPLDAC12.nc ---
// $Id: HPLDAC12.nc,v 1.1 2005/09/28 10:41:11 jpolastre Exp $
/*
* Copyright (c) 2005 Moteiv Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached MOTEIV-LICENSE
* file. If you do not find these files, copies can be found at
* http://www.moteiv.com/MOTEIV-LICENSE.txt and by emailing info at moteiv.com.
*/
includes MSP430DAC12;
/**
* Interface to the DAC on the MSP430 platform
*
* @author Joe Polastre <info at moteiv.com>
*/
interface HPLDAC12
{
async command void setControl(dac12ctl_t control);
async command dac12ctl_t getControl();
async command void setRef(dac12ref_t refSelect);
async command dac12ref_t getRef();
/**
* Set the resolution of the DAC
*
* @param res FALSE for 12-bit, TRUE for 8-bit
*/
async command void setRes(bool res);
/**
* Get the resolution of the DAC
*
* @return FALSE for 12-bit, TRUE for 8-bit
*/
async command bool getRes();
async command void setLoadSelect(dac12load_t loadSelect);
async command dac12load_t getLoadSelect();
async command void startCalibration();
async command bool getCalibration();
/**
* Sets the input range of the DAC
*
* @param range FALSE for a full-scale output = 3x reference voltage
* TRUE for a full-scale output = 1x reference voltage
*/
async command void setInputRange(bool range);
async command bool getInputRange();
async command void setAmplifier(dac12amp_t ampsetting);
async command dac12amp_t getAmplifier();
async command void setFormat(bool format);
async command bool getFormat();
async command void enableInterrupts();
async command void disableInterrupts();
async command bool isInterruptPending();
async command void on();
async command void off();
async command void group();
async command void ungroup();
async command void setData(uint16_t data);
async command uint16_t getData();
}
--- NEW FILE: HPLDAC12M.nc ---
// $Id: HPLDAC12M.nc,v 1.1 2005/09/28 10:41:11 jpolastre Exp $
/*
* Copyright (c) 2005 Moteiv Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached MOTEIV-LICENSE
* file. If you do not find these files, copies can be found at
* http://www.moteiv.com/MOTEIV-LICENSE.txt and by emailing info at moteiv.com.
*/
includes MSP430DAC12;
/**
* HPL layer for the DAC12 module on the MSP430 platform
*
* @author Joe Polastre <info at moteiv.com>
*/
module HPLDAC12M {
provides interface HPLDAC12 as DAC0;
provides interface HPLDAC12 as DAC1;
}
implementation
{
MSP430REG_NORACE(DAC12_0CTL);
MSP430REG_NORACE(DAC12_0DAT);
MSP430REG_NORACE(DAC12_1CTL);
MSP430REG_NORACE(DAC12_1DAT);
/***************** DAC 0 ***************/
async command void DAC0.setControl(dac12ctl_t control) {
DAC12_0CTL = *(uint16_t*)&control;
}
async command dac12ctl_t DAC0.getControl() {
return *(dac12ctl_t*) &DAC12_0CTL;
}
async command void DAC0.setRef(dac12ref_t refSelect) {
dac12ctl_t ctl;
atomic {
ctl = *(dac12ctl_t*) &DAC12_0CTL;
ctl.reference = refSelect;
DAC12_0CTL = *(uint16_t*)&ctl;
}
}
async command dac12ref_t DAC0.getRef() {
return (dac12ref_t)((DAC12_0CTL & DAC12SREF_3) >> 13);
}
async command void DAC0.setRes(bool res) {
if (res)
DAC12_0CTL |= DAC12RES;
else
DAC12_0CTL &= ~DAC12RES;
}
async command bool DAC0.getRes() {
return (DAC12_0CTL & DAC12RES) ? TRUE : FALSE;
}
async command void DAC0.setLoadSelect(dac12load_t loadSelect) {
dac12ctl_t ctl;
atomic {
ctl = *(dac12ctl_t*) &DAC12_0CTL;
ctl.load = loadSelect;
DAC12_0CTL = *(uint16_t*)&ctl;
}
}
async command dac12load_t DAC0.getLoadSelect() {
return (dac12load_t)((DAC12_0CTL & DAC12LSEL_3) >> 10);
}
async command void DAC0.startCalibration() {
DAC12_0CTL |= DAC12CALON;
}
async command bool DAC0.getCalibration() {
return (DAC12_0CTL & DAC12CALON) >> 9;
}
async command void DAC0.setInputRange(bool range) {
if (range)
DAC12_0CTL |= DAC12IR;
else
DAC12_0CTL &= ~DAC12IR;
}
async command bool DAC0.getInputRange() {
return (DAC12_0CTL & DAC12IR) ? TRUE : FALSE;
}
async command void DAC0.setAmplifier(dac12amp_t ampsetting) {
dac12ctl_t ctl;
atomic {
ctl = *(dac12ctl_t*) &DAC12_0CTL;
ctl.dacamp = ampsetting;
DAC12_0CTL = *(uint16_t*)&ctl;
}
}
async command dac12amp_t DAC0.getAmplifier() {
return (dac12amp_t)((DAC12_0CTL & DAC12AMP_7) >> 5);
}
async command void DAC0.setFormat(bool format) {
if (format)
DAC12_0CTL |= DAC12DF;
else
DAC12_0CTL &= ~DAC12DF;
}
async command bool DAC0.getFormat() {
return (DAC12_0CTL & DAC12DF) ? TRUE : FALSE;
}
async command void DAC0.enableInterrupts() {
DAC12_0CTL |= DAC12IE;
}
async command void DAC0.disableInterrupts() {
DAC12_0CTL &= ~DAC12IE;
}
async command bool DAC0.isInterruptPending() {
return (DAC12_0CTL & DAC12IFG) ? TRUE : FALSE;
}
async command void DAC0.on() {
DAC12_0CTL |= DAC12ENC;
}
async command void DAC0.off() {
DAC12_0CTL &= ~DAC12ENC;
}
async command void DAC0.group() {
DAC12_0CTL |= DAC12GRP;
}
async command void DAC0.ungroup() {
DAC12_0CTL &= ~DAC12GRP;
}
async command void DAC0.setData(uint16_t data) {
DAC12_0DAT = data;
}
async command uint16_t DAC0.getData() {
uint16_t temp = DAC12_0DAT;
return temp;
}
/***************** DAC 1 ***************/
async command void DAC1.setControl(dac12ctl_t control) {
DAC12_1CTL = *(uint16_t*)&control;
}
async command dac12ctl_t DAC1.getControl() {
return *(dac12ctl_t*) &DAC12_1CTL;
}
async command void DAC1.setRef(dac12ref_t refSelect) {
dac12ctl_t ctl;
atomic {
ctl = *(dac12ctl_t*) &DAC12_1CTL;
ctl.reference = refSelect;
DAC12_1CTL = *(uint16_t*)&ctl;
}
}
async command dac12ref_t DAC1.getRef() {
return (dac12ref_t)((DAC12_1CTL & DAC12SREF_3) >> 13);
}
async command void DAC1.setRes(bool res) {
if (res)
DAC12_1CTL |= DAC12RES;
else
DAC12_1CTL &= ~DAC12RES;
}
async command bool DAC1.getRes() {
return (DAC12_1CTL & DAC12RES) ? TRUE : FALSE;
}
async command void DAC1.setLoadSelect(dac12load_t loadSelect) {
dac12ctl_t ctl;
atomic {
ctl = *(dac12ctl_t*) &DAC12_1CTL;
ctl.load = loadSelect;
DAC12_1CTL = *(uint16_t*)&ctl;
}
}
async command dac12load_t DAC1.getLoadSelect() {
return (dac12load_t)((DAC12_1CTL & DAC12LSEL_3) >> 10);
}
async command void DAC1.startCalibration() {
DAC12_1CTL |= DAC12CALON;
}
async command bool DAC1.getCalibration() {
return (DAC12_1CTL & DAC12CALON) >> 9;
}
async command void DAC1.setInputRange(bool range) {
if (range)
DAC12_1CTL |= DAC12IR;
else
DAC12_1CTL &= ~DAC12IR;
}
async command bool DAC1.getInputRange() {
return (DAC12_1CTL & DAC12IR) ? TRUE : FALSE;
}
async command void DAC1.setAmplifier(dac12amp_t ampsetting) {
dac12ctl_t ctl;
atomic {
ctl = *(dac12ctl_t*) &DAC12_1CTL;
ctl.dacamp = ampsetting;
DAC12_1CTL = *(uint16_t*)&ctl;
}
}
async command dac12amp_t DAC1.getAmplifier() {
return (dac12amp_t)((DAC12_1CTL & DAC12AMP_7) >> 5);
}
async command void DAC1.setFormat(bool format) {
if (format)
DAC12_1CTL |= DAC12DF;
else
DAC12_1CTL &= ~DAC12DF;
}
async command bool DAC1.getFormat() {
return (DAC12_1CTL & DAC12DF) ? TRUE : FALSE;
}
async command void DAC1.enableInterrupts() {
DAC12_1CTL |= DAC12IE;
}
async command void DAC1.disableInterrupts() {
DAC12_1CTL &= ~DAC12IE;
}
async command bool DAC1.isInterruptPending() {
return (DAC12_1CTL & DAC12IFG) ? TRUE : FALSE;
}
async command void DAC1.on() {
DAC12_1CTL |= DAC12ENC;
}
async command void DAC1.off() {
DAC12_1CTL &= ~DAC12ENC;
}
async command void DAC1.group() {
DAC12_1CTL |= DAC12GRP;
}
async command void DAC1.ungroup() {
DAC12_1CTL &= ~DAC12GRP;
}
async command void DAC1.setData(uint16_t data) {
DAC12_1DAT = data;
}
async command uint16_t DAC1.getData() {
uint16_t temp = DAC12_1DAT;
return temp;
}
}
--- NEW FILE: MSP430DAC.nc ---
includes MSP430DAC12;
interface MSP430DAC {
// intended process for single output
// - bind, specifically ref volt
// - enable
// - wait for enableDone
// - enableOutput
// - set
// - do whatever
// - disable
// intended process for multiple outputs
// - bind, specifically ref volt
// load select bits ignored (reset later)
// - enable
// - wait for enableDone
// - enableOutput
// - setSequence / Repeat
// the DMA and TimerA are set for the user
// - do whatever
// - disable
command result_t bind(dac12ref_t reference,
dac12res_t resolution,
dac12load_t loadselect,
dac12fsout_t fsout,
dac12amp_t amp,
dac12df_t dataformat,
dac12group_t group);
// turn the dac on or off
// includes a calibration step and turning refvolt on
async command result_t enable();
event void enableDone(result_t success);
// turn the dac off
// release dependence on refvolt
async command result_t disable();
event void disableDone(result_t success);
async command result_t enableOutput();
async command result_t disableOutput();
// set the value, fails if sequence or repeat in progress
async command result_t set(uint16_t dacunits);
}
--- NEW FILE: MSP430DAC12.h ---
// $Id: MSP430DAC12.h,v 1.1 2005/09/28 10:41:11 jpolastre Exp $
/*
* Copyright (c) 2005 Moteiv Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached MOTEIV-LICENSE
* file. If you do not find these files, copies can be found at
* http://www.moteiv.com/MOTEIV-LICENSE.txt and by emailing info at moteiv.com.
*/
#ifndef MSP430DAC12_H
#define MSP430DAC12_H
#include "msp430hardware.h"
typedef enum {
DAC12_AMP_OFFZ = 0,
DAC12_AMP_OFF0 = 1,
DAC12_AMP_LOW_LOW = 2,
DAC12_AMP_LOW_MED = 3,
DAC12_AMP_LOW_HIGH = 4,
DAC12_AMP_MED_MED = 5,
DAC12_AMP_MED_HIGH = 6,
DAC12_AMP_HIGH_HIGH = 7
} dac12amp_t;
typedef enum {
DAC12_LOAD_WRITE = 0,
DAC12_LOAD_WRITEGROUP = 1,
DAC12_LOAD_TAOUT1 = 2,
DAC12_LOAD_TBOUT2 = 3
} dac12load_t;
typedef enum {
DAC12_REF_VREF = 0,
DAC12_REF_VEREF = 2
} dac12ref_t;
typedef enum {
DAC12_RES_8BIT = 1,
DAC12_RES_12BIT = 0
} dac12res_t;
typedef enum {
DAC12_FSOUT_1X = 1,
DAC12_FSOUT_3X = 2,
} dac12fsout_t;
typedef enum {
DAC12_DF_STRAIGHT = 0,
DAC12_DF_2COMP = 1
} dac12df_t;
typedef enum {
DAC12_GROUP_OFF = 0,
DAC12_GROUP_ON = 1
} dac12group_t;
typedef struct
{
unsigned int group : 1;
unsigned int enc : 1;
unsigned int ifg : 1;
unsigned int ie : 1;
unsigned int format : 1;
unsigned int dacamp : 3;
unsigned int range : 1;
unsigned int cal: 1;
unsigned int load : 2;
unsigned int resolution : 1;
unsigned int reference : 2;
unsigned int reserved : 1;
} __attribute__ ((packed)) dac12ctl_t;
#endif
--- NEW FILE: MSP430DAC12C.nc ---
// $Id: MSP430DAC12C.nc,v 1.1 2005/09/28 10:41:11 jpolastre Exp $
/*
* Copyright (c) 2005 Moteiv Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached MOTEIV-LICENSE
* file. If you do not find these files, copies can be found at
* http://www.moteiv.com/MOTEIV-LICENSE.txt and by emailing info at moteiv.com.
*/
configuration MSP430DAC12C {
provides {
interface StdControl;
interface MSP430DAC as DAC0;
interface MSP430DAC as DAC1;
}
}
implementation {
components HPLDAC12M, RefVoltC, MSP430DAC12M as Impl, MSP430TimerAExclusiveC as TAC;
StdControl = TAC;
StdControl = Impl;
DAC0 = Impl.DAC0;
DAC1 = Impl.DAC1;
Impl.HPLDAC0 -> HPLDAC12M.DAC0;
Impl.HPLDAC1 -> HPLDAC12M.DAC1;
Impl.RefVolt -> RefVoltC;
Impl.TimerExclusive -> TAC.TimerExclusive[unique("TimerA")];
}
--- NEW FILE: MSP430DAC12M.nc ---
// $Id: MSP430DAC12M.nc,v 1.1 2005/09/28 10:41:11 jpolastre Exp $
/*
* Copyright (c) 2005 Moteiv Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached MOTEIV-LICENSE
* file. If you do not find these files, copies can be found at
* http://www.moteiv.com/MOTEIV-LICENSE.txt and by emailing info at moteiv.com.
*/
module MSP430DAC12M {
provides {
interface StdControl;
interface MSP430DAC as DAC0;
interface MSP430DAC as DAC1;
}
uses {
interface HPLDAC12 as HPLDAC0;
interface HPLDAC12 as HPLDAC1;
interface RefVolt;
interface TimerExclusive;
}
}
implementation {
MSP430REG_NORACE(P6SEL);
uint8_t state;
enum {
IDLE,
PROC_DAC0,
PROC_DAC1,
RV_DAC0,
RV_DAC1,
};
command result_t StdControl.init() {
atomic {
state = IDLE;
}
return SUCCESS;
}
command result_t StdControl.start() {
return SUCCESS;
}
command result_t StdControl.stop() {
return SUCCESS;
}
// calibrate the output on DAC0
task void calibDAC0() {
call HPLDAC0.startCalibration();
// wait for the calibration to finish
while (call HPLDAC0.getCalibration() != 0) ;
atomic state = IDLE;
signal DAC0.enableDone(SUCCESS);
}
// calibrate the output on DAC1
task void calibDAC1() {
call HPLDAC1.startCalibration();
// wait for the calibration to finish
while (call HPLDAC1.getCalibration() != 0) ;
atomic state = IDLE;
signal DAC1.enableDone(SUCCESS);
}
/**************************** DAC 0 ************************/
// to enable the DAC, the following steps must be taken:
// 0) switch DAC0 to be MODFUNC
// 1) turn on the reference voltage to 2.5V
// 2) calibrate the output amplifier
// 3) set DAC settings
// 4) enable output
async command result_t DAC0.enable() {
result_t result = SUCCESS;
atomic {
if (state != IDLE) {
result = FAIL;
}
else {
state = PROC_DAC0;
}
}
if (result == SUCCESS) {
// set dac0 on port 6 to mod func
P6SEL |= (1 << 6);
// set the 2.5V reference
result = call RefVolt.get(REFERENCE_2_5V);
if (result == SUCCESS) {
if (call RefVolt.getState() == REFERENCE_2_5V){
return post calibDAC0();
} else {
// wait for the stable event
atomic state = RV_DAC0;
return SUCCESS;
}
}
}
return FAIL;
}
command result_t DAC0.bind(dac12ref_t reference,
dac12res_t resolution,
dac12load_t loadselect,
dac12fsout_t fsout,
dac12amp_t amp,
dac12df_t dataformat,
dac12group_t group) {
dac12ctl_t control;
call HPLDAC0.off();
control = call HPLDAC0.getControl();
control.group = group;
control.format = dataformat;
control.dacamp = amp;
control.range = fsout;
control.load = loadselect;
control.resolution = resolution;
control.reference = reference;
call HPLDAC0.setControl(control);
return SUCCESS;
}
default event void DAC0.enableDone(result_t success) { }
async command result_t DAC0.enableOutput() {
call HPLDAC0.on();
return SUCCESS;
}
async command result_t DAC0.disableOutput() {
call HPLDAC0.off();
return SUCCESS;
}
task void disableDone0() {
signal DAC0.disableDone(SUCCESS);
}
async command result_t DAC0.disable() {
// release the reference voltage
call HPLDAC0.off();
if (call RefVolt.release() == SUCCESS) {
return post disableDone0();
}
return FAIL;
}
default event void DAC0.disableDone(result_t success) { }
async command result_t DAC0.set(uint16_t dacunits) {
call HPLDAC0.setData(dacunits);
return SUCCESS;
}
/**************************** DAC 1 ************************/
// to enable the DAC, the following steps must be taken:
// 0) switch DAC1 to be MODFUNC
// 1) turn on the reference voltage to 2.5V
// 2) calibrate the output amplifier
// 3) set DAC settings
// 4) enable output
async command result_t DAC1.enable() {
result_t result = SUCCESS;
atomic {
if (state != IDLE) {
result = FAIL;
}
else {
state = PROC_DAC1;
}
}
if (result) {
// set dac1 on port 6 to mod func
P6SEL |= (1 << 7);
// set the 2.5V reference
result = call RefVolt.get(REFERENCE_2_5V);
if (result == SUCCESS) {
if (call RefVolt.getState() == REFERENCE_2_5V){
return post calibDAC1();
} else {
// wait for the stable event
atomic state = RV_DAC1;
return SUCCESS;
}
}
}
return FAIL;
}
command result_t DAC1.bind(dac12ref_t reference,
dac12res_t resolution,
dac12load_t loadselect,
dac12fsout_t fsout,
dac12amp_t amp,
dac12df_t dataformat,
dac12group_t group) {
dac12ctl_t control;
call HPLDAC1.off();
control = call HPLDAC1.getControl();
control.group = group;
control.format = dataformat;
control.dacamp = amp;
control.range = fsout;
control.load = loadselect;
control.resolution = resolution;
control.reference = reference;
call HPLDAC1.setControl(control);
return SUCCESS;
}
default event void DAC1.enableDone(result_t success) { }
async command result_t DAC1.enableOutput() {
call HPLDAC1.on();
return SUCCESS;
}
async command result_t DAC1.disableOutput() {
call HPLDAC1.off();
return SUCCESS;
}
task void disableDone1() {
signal DAC1.disableDone(SUCCESS);
}
async command result_t DAC1.disable() {
// release the reference voltage
call HPLDAC1.off();
if (call RefVolt.release() == SUCCESS) {
return post disableDone1();
}
return FAIL;
}
default event void DAC1.disableDone(result_t success) { }
async command result_t DAC1.set(uint16_t dacunits) {
call HPLDAC1.setData(dacunits);
return SUCCESS;
}
event void TimerExclusive.free() { }
event void RefVolt.isStable(RefVolt_t vref) {
uint8_t _state = IDLE;
atomic {
if (state == RV_DAC0) {
_state = state;
state = PROC_DAC0;
}
else if (state == RV_DAC1) {
_state = state;
state = PROC_DAC1;
}
}
switch(_state) {
case RV_DAC0:
post calibDAC0();
case RV_DAC1:
post calibDAC1();
}
}
}
More information about the Tinyos-commits
mailing list