X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fmsp430%2Fadc12%2FMsp430Adc12ImplP.nc;h=e9e7f68e869dd8f07bee73dbd5bb08d86d407252;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=4b5c3ff8ccae1fae06053f497ee40225b528755b;hpb=ec0de8e1ac425b0f6855d46f737c2726cd82df88;p=tinyos-2.x.git diff --git a/tos/chips/msp430/adc12/Msp430Adc12ImplP.nc b/tos/chips/msp430/adc12/Msp430Adc12ImplP.nc index 4b5c3ff8..e9e7f68e 100644 --- a/tos/chips/msp430/adc12/Msp430Adc12ImplP.nc +++ b/tos/chips/msp430/adc12/Msp430Adc12ImplP.nc @@ -34,16 +34,18 @@ */ #include -module Msp430Adc12ImplP +module Msp430Adc12ImplP @safe() { provides { interface Init; interface Msp430Adc12SingleChannel as SingleChannel[uint8_t id]; + interface Msp430Adc12MultiChannel as MultiChannel[uint8_t id]; + interface Msp430Adc12Overflow as Overflow[uint8_t id]; interface AsyncStdControl as DMAExtension[uint8_t id]; - } - uses { + } + uses { interface ArbiterInfo as ADCArbiterInfo; - interface HplAdc12; + interface HplAdc12; interface Msp430Timer as TimerA;; interface Msp430TimerControl as ControlA0; interface Msp430TimerControl as ControlA1; @@ -57,36 +59,50 @@ module Msp430Adc12ImplP interface HplMsp430GeneralIO as Port65; interface HplMsp430GeneralIO as Port66; interface HplMsp430GeneralIO as Port67; - } + } } implementation { + +#ifdef ADC12_TIMERA_ENABLED + #warning Accessing TimerA for ADC12 +#endif + enum { SINGLE_DATA = 1, SINGLE_DATA_REPEAT = 2, MULTIPLE_DATA = 4, MULTIPLE_DATA_REPEAT = 8, - CONVERSION_MODE_MASK = 0x0F, + MULTI_CHANNEL = 16, + CONVERSION_MODE_MASK = 0x1F, - ADC_BUSY = 16, /* request pending */ - USE_TIMERA = 32, /* TimerA used for SAMPCON signal */ + ADC_BUSY = 32, /* request pending */ + USE_TIMERA = 64, /* TimerA used for SAMPCON signal */ + ADC_OVERFLOW = 128, }; uint8_t state; /* see enum above */ - uint16_t *resultBuffer; /* conversion results */ uint16_t resultBufferLength; /* length of buffer */ + uint16_t *COUNT_NOK(resultBufferLength) resultBufferStart; uint16_t resultBufferIndex; /* offset into buffer */ + uint8_t numChannels; /* number of channels (multi-channel conversion) */ uint8_t clientID; /* ID of client that called getData() */ command error_t Init.init() { + adc12ctl0_t ctl0; call HplAdc12.stopConversion(); + ctl0 = call HplAdc12.getCtl0(); + ctl0.adc12tovie = 1; + ctl0.adc12ovie = 1; + call HplAdc12.setCtl0(ctl0); return SUCCESS; } void prepareTimerA(uint16_t interval, uint16_t csSAMPCON, uint16_t cdSAMPCON) { +#ifdef ADC12_TIMERA_ENABLED msp430_compare_control_t ccResetSHI = { ccifg : 0, cov : 0, out : 0, cci : 0, ccie : 0, outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 }; @@ -99,10 +115,12 @@ implementation call ControlA0.setControl(ccResetSHI); call CompareA0.setEvent(interval-1); call CompareA1.setEvent((interval-1)/2); +#endif } void startTimerA() { +#ifdef ADC12_TIMERA_ENABLED msp430_compare_control_t ccSetSHI = { ccifg : 0, cov : 0, out : 1, cci : 0, ccie : 0, outmod : 0, cap : 0, clld : 0, scs : 0, ccis : 0, cm : 0 }; @@ -118,11 +136,12 @@ implementation //call ControlA1.setControl(ccResetSHI); call ControlA1.setControl(ccRSOutmod); call TimerA.setMode(MSP430TIMER_UP_MODE); // go! +#endif } void configureAdcPin( uint8_t inch ) { -#ifdef P6PIN_AUTO_CONFIGURE +#ifdef ADC12_P6PIN_AUTO_CONFIGURE switch (inch) { case 0: call Port60.selectModuleFunc(); call Port60.makeInput(); break; @@ -139,7 +158,7 @@ implementation void resetAdcPin( uint8_t inch ) { -#ifdef P6PIN_AUTO_CONFIGURE +#ifdef ADC12_P6PIN_AUTO_CONFIGURE switch (inch) { case 0: call Port60.selectIOFunc(); break; @@ -158,7 +177,7 @@ implementation const msp430adc12_channel_config_t *config) { error_t result = ERESERVE; -#ifdef CHECK_ARGS +#ifdef ADC12_CHECK_ARGS if (!config) return EINVAL; #endif @@ -202,7 +221,11 @@ implementation uint16_t jiffies) { error_t result = ERESERVE; -#ifdef CHECK_ARGS +#ifdef ADC12_CHECK_ARGS +#ifndef ADC12_TIMERA_ENABLED + if (jiffies>0) + return EINVAL; +#endif if (!config || jiffies == 1 || jiffies == 2) return EINVAL; #endif @@ -250,7 +273,11 @@ implementation uint16_t *buf, uint16_t length, uint16_t jiffies) { error_t result = ERESERVE; -#ifdef CHECK_ARGS +#ifdef ADC12_CHECK_ARGS +#ifndef ADC12_TIMERA_ENABLED + if (jiffies>0) + return EINVAL; +#endif if (!config || !buf || !length || jiffies == 1 || jiffies == 2) return EINVAL; #endif @@ -280,8 +307,9 @@ implementation ctl0.sht1 = config->sht; state = MULTIPLE_DATA; - resultBuffer = buf; + resultBufferStart = NULL; resultBufferLength = length; + resultBufferStart = buf; resultBufferIndex = 0; call HplAdc12.setCtl0(ctl0); call HplAdc12.setCtl1(ctl1); @@ -306,7 +334,11 @@ implementation uint16_t *buf, uint8_t length, uint16_t jiffies) { error_t result = ERESERVE; -#ifdef CHECK_ARGS +#ifdef ADC12_CHECK_ARGS +#ifndef ADC12_TIMERA_ENABLED + if (jiffies>0) + return EINVAL; +#endif if (!config || !buf || !length || length > 16 || jiffies == 1 || jiffies == 2) return EINVAL; #endif @@ -316,7 +348,7 @@ implementation if (call ADCArbiterInfo.userId() == id){ adc12ctl1_t ctl1 = { adc12busy: 0, - ctl1.conseq = 3, + conseq: 3, adc12ssel: config->adc12ssel, adc12div: config->adc12div, issh: 0, @@ -336,8 +368,9 @@ implementation ctl0.sht1 = config->sht; state = MULTIPLE_DATA_REPEAT; - resultBuffer = buf; + resultBufferStart = NULL; resultBufferLength = length; + resultBufferStart = buf; resultBufferIndex = 0; call HplAdc12.setCtl0(ctl0); @@ -362,7 +395,7 @@ implementation { atomic { if (call ADCArbiterInfo.userId() == id){ - if (state & MULTIPLE_DATA_REPEAT && !resultBuffer) + if ((state & MULTIPLE_DATA_REPEAT) && !resultBufferStart) return EINVAL; if (state & ADC_BUSY) return EBUSY; @@ -378,15 +411,112 @@ implementation return FAIL; } + async command error_t MultiChannel.configure[uint8_t id]( + const msp430adc12_channel_config_t *config, + adc12memctl_t *memctl, uint8_t numMemctl, uint16_t *buf, + uint16_t numSamples, uint16_t jiffies) + { + error_t result = ERESERVE; +#ifdef ADC12_CHECK_ARGS +#ifndef ADC12_TIMERA_ENABLED + if (jiffies>0) + return EINVAL; +#endif + if (!config || !memctl || !numMemctl || numMemctl > 15 || !numSamples || + !buf || jiffies == 1 || jiffies == 2 || numSamples % (numMemctl+1) != 0) + return EINVAL; +#endif + atomic { + if (state & ADC_BUSY) + return EBUSY; + if (call ADCArbiterInfo.userId() == id){ + adc12ctl1_t ctl1 = { + adc12busy: 0, + conseq: (numSamples > numMemctl+1) ? 3 : 1, + adc12ssel: config->adc12ssel, + adc12div: config->adc12div, + issh: 0, + shp: 1, + shs: (jiffies == 0) ? 0 : 1, + cstartadd: 0 + }; + adc12memctl_t firstMemctl = { + 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 = MULTI_CHANNEL; + resultBufferStart = NULL; + resultBufferLength = numSamples; + resultBufferStart = buf; + resultBufferIndex = 0; + numChannels = numMemctl+1; + call HplAdc12.setCtl0(ctl0); + call HplAdc12.setCtl1(ctl1); + call HplAdc12.setMCtl(0, firstMemctl); + for (i=0; i<(numMemctl-1) && i < 14; i++){ + memctl[i].eos = 0; + call HplAdc12.setMCtl(i+1, memctl[i]); + } + memctl[i].eos = 1; + call HplAdc12.setMCtl(i+1, memctl[i]); + call HplAdc12.setIEFlags(mask << (i+1)); + + if (jiffies){ + state |= USE_TIMERA; + prepareTimerA(jiffies, config->sampcon_ssel, config->sampcon_id); + } + result = SUCCESS; + } + } + return result; + } + + async command error_t MultiChannel.getData[uint8_t id]() + { + uint8_t i; + atomic { + if (call ADCArbiterInfo.userId() == id){ + if (!resultBufferStart) + return EINVAL; + if (state & ADC_BUSY) + return EBUSY; + state |= ADC_BUSY; + clientID = id; + for (i=0; i 16) length = 16; else @@ -444,35 +601,39 @@ implementation *resultBuffer++ = call HplAdc12.getMem(i); } while (++i < length); resultBufferIndex += length; - - if (resultBufferLength - resultBufferIndex > 15) + if (overflow || resultBufferLength == resultBufferIndex){ + stopConversion(); + resultBuffer -= resultBufferIndex; + k = resultBufferIndex - length; + resultBufferIndex = 0; + signal SingleChannel.multipleDataReady[clientID](resultBuffer, + overflow ? k : resultBufferLength); + } else if (resultBufferLength - resultBufferIndex > 15) return; - else if (resultBufferLength - resultBufferIndex > 0){ + else { + // last sequence < 16 samples 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; + resultBuffer = resultBufferStart; do { *resultBuffer++ = call HplAdc12.getMem(i); } while (++i < resultBufferLength); - resultBuffer = signal SingleChannel.multipleDataReady[clientID]( + resultBufferStart = signal SingleChannel.multipleDataReady[clientID]( resultBuffer-resultBufferLength, - resultBufferLength); - if (!resultBuffer) + overflow ? 0 : resultBufferLength); + if (!resultBufferStart) stopConversion(); break; } +#endif } // switch } @@ -482,13 +643,15 @@ implementation } default async event uint16_t* SingleChannel.multipleDataReady[uint8_t id]( - uint16_t *buf, uint16_t length) + uint16_t *buf, uint16_t numSamples) { return 0; } + + default async event void MultiChannel.dataReady[uint8_t id](uint16_t *buffer, uint16_t numSamples) {}; - async event void HplAdc12.memOverflow(){} - async event void HplAdc12.conversionTimeOverflow(){} + default async event void Overflow.memOverflow[uint8_t id](){} + default async event void Overflow.conversionTimeOverflow[uint8_t id](){} }