[Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/msp430/adc12 AdcStreamP.nc, NONE, 1.1 Msp430Adc12DMAWireC.nc, NONE, 1.1 WireAdcStreamP.nc, NONE, 1.1 AdcP.nc, 1.4, 1.5 AdcReadStreamClientC.nc, 1.4, 1.5 HplAdc12P.nc, 1.4, 1.5 Msp430Adc12ClientAutoDMAC.nc, 1.5, 1.6 Msp430Adc12ClientAutoDMA_RVGC.nc, 1.6, 1.7 Msp430Adc12ClientAutoRVGC.nc, 1.6, 1.7 Msp430Adc12ImplP.nc, 1.5, 1.6 Msp430Adc12MultiChannel.nc, 1.2, 1.3 README.txt, 1.6, 1.7

Jan-Hinrich Hauer janhauer at users.sourceforge.net
Mon Apr 7 02:41:58 PDT 2008


Update of /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv23244/tos/chips/msp430/adc12

Modified Files:
	AdcP.nc AdcReadStreamClientC.nc HplAdc12P.nc 
	Msp430Adc12ClientAutoDMAC.nc Msp430Adc12ClientAutoDMA_RVGC.nc 
	Msp430Adc12ClientAutoRVGC.nc Msp430Adc12ImplP.nc 
	Msp430Adc12MultiChannel.nc README.txt 
Added Files:
	AdcStreamP.nc Msp430Adc12DMAWireC.nc WireAdcStreamP.nc 
Log Message:
- bugfix: ReadStream did not work with a "usPeriod" parameter > 0xFFFF (the fix uses/adapts the atmel ReadStream code)
- bugfix: overflow interrupts were not handled/signalled correctly from the HAL
- fixed the wiring for DMA, which was not correct when used by more than one client
- polished the HPL and added some comments
- introduced a compile time warning when DMA/TimerA is accessed (will be removed once we decide how these components are arbitrated)


--- NEW FILE: AdcStreamP.nc ---
/* $Id: AdcStreamP.nc,v 1.1 2008/04/07 09:41:55 janhauer Exp $
 * Copyright (c) 2005 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 *
 * 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.
 *
 */

/**
 * Convert MSP430 HAL A/D interface to the HIL interfaces (adapted atmega code).
 * @author David Gay
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 */
#include "Timer.h"

module AdcStreamP {
  provides {
    interface Init @atleastonce();
    interface ReadStream<uint16_t>[uint8_t client];
  }
  uses {
    interface Msp430Adc12SingleChannel as SingleChannel[uint8_t client];
    interface AdcConfigure<const msp430adc12_channel_config_t*>[uint8_t client];
    interface Alarm<TMilli, uint32_t>;
  }
}
implementation {
  enum {
    NSTREAM = uniqueCount(ADCC_READ_STREAM_SERVICE)
  };

  /* Resource reservation is required, and it's incorrect to call getData
     again before dataReady is signaled, so there are no races in correct
     programs */
  norace uint8_t client = NSTREAM;

  /* Stream data */
  struct list_entry_t {
    uint16_t count;
    struct list_entry_t *next;
  };
  struct list_entry_t *bufferQueue[NSTREAM];
  struct list_entry_t **bufferQueueEnd[NSTREAM];
  uint16_t *lastBuffer, lastCount;

  norace uint16_t *buffer, *pos, count;
  norace uint32_t now, period;
  norace bool periodModified;


  command error_t Init.init() {
    uint8_t i;

    for (i = 0; i != NSTREAM; i++)
      bufferQueueEnd[i] = &bufferQueue[i];

    return SUCCESS;
  }

  void sampleSingle() {
    call SingleChannel.getData[client]();
  }

  command error_t ReadStream.postBuffer[uint8_t c](uint16_t *buf, uint16_t n) {
    if (n < sizeof(struct list_entry_t))
      return ESIZE;
    atomic
    {
      struct list_entry_t *newEntry = (struct list_entry_t *)buf;

      if (!bufferQueueEnd[c]) // Can't post right now.
        return FAIL;

      newEntry->count = n;
      newEntry->next = NULL;
      *bufferQueueEnd[c] = newEntry;
      bufferQueueEnd[c] = &newEntry->next;
    }
    return SUCCESS;
  }

  task void readStreamDone() {
    uint8_t c = client;
    uint32_t actualPeriod = period;
    if (periodModified)
      actualPeriod = period - (period % 1000);

    atomic
    {
      bufferQueue[c] = NULL;
      bufferQueueEnd[c] = &bufferQueue[c];
    }

    client = NSTREAM;
    signal ReadStream.readDone[c](SUCCESS, actualPeriod);
  }

  task void readStreamFail() {
    /* By now, the pending bufferDone has been signaled (see readStream). */
    struct list_entry_t *entry;
    uint8_t c = client;

    atomic entry = bufferQueue[c];
    for (; entry; entry = entry->next)
      signal ReadStream.bufferDone[c](FAIL, (uint16_t *)entry, entry->count);

    atomic
    {
      bufferQueue[c] = NULL;
      bufferQueueEnd[c] = &bufferQueue[c];
    }

    client = NSTREAM;
    signal ReadStream.readDone[c](FAIL, 0);
  }

  task void bufferDone() {
    uint16_t *b, c;
    atomic
    {
      b = lastBuffer;
      c = lastCount;
      lastBuffer = NULL;
    }

    signal ReadStream.bufferDone[client](SUCCESS, b, c);
  }

  void nextAlarm() {
    call Alarm.startAt(now, period);
    now += period;
  }

  async event void Alarm.fired() {
    sampleSingle();
  }

  error_t nextBuffer(bool startNextAlarm) {
    atomic
    {
      struct list_entry_t *entry = bufferQueue[client];

      if (!entry)
      {
        // all done
        bufferQueueEnd[client] = NULL; // prevent post
        post readStreamDone();
        return FAIL;
      }
      else
      {
        bufferQueue[client] = entry->next;
        if (!bufferQueue[client])
          bufferQueueEnd[client] = &bufferQueue[client];
        pos = buffer = (uint16_t *)entry;
        count = entry->count;
        if (startNextAlarm)
          nextAlarm();
        return SUCCESS;
      }
    }
  }

  void nextMultiple(uint8_t c)
  {
    if (nextBuffer(FALSE) == SUCCESS){
      msp430adc12_channel_config_t config = *call AdcConfigure.getConfiguration[c]();
      config.sampcon_ssel = SAMPCON_SOURCE_SMCLK; // assumption: SMCLK runs at 1 MHz
      config.sampcon_id = SAMPCON_CLOCK_DIV_1; 
      call SingleChannel.configureMultiple[c]( &config, pos, count, period);
      call SingleChannel.getData[c]();
    }
  }

  command error_t ReadStream.read[uint8_t c](uint32_t usPeriod)
  {
    if (usPeriod & 0xFFFF0000){
      // "manual" sampling
      period = usPeriod / 1000;
      periodModified = TRUE;
      client = c;
      now = call Alarm.getNow();
      call SingleChannel.configureSingle[c](call AdcConfigure.getConfiguration[c]());
      if (nextBuffer(FALSE) == SUCCESS)
        sampleSingle();
    } else {
      period = usPeriod;
      periodModified = FALSE;
      client = c;
      nextMultiple(c);
    }
    return SUCCESS;
  }


  async event error_t SingleChannel.singleDataReady[uint8_t streamClient](uint16_t data)
  {
    if (client == NSTREAM)
      return FAIL;

    if (count == 0)
    {
      now = call Alarm.getNow();
      nextBuffer(TRUE);
    }
    else
    {
      *pos++ = data;
      if (!--count)
      {
        atomic
        {
          if (lastBuffer)
          {
            /* We failed to signal bufferDone in time. Fail. */
            bufferQueueEnd[client] = NULL; // prevent post
            post readStreamFail();
            return FAIL;
          }
          else
          {
            lastBuffer = buffer;
            lastCount = pos - buffer;
          }
        }
        post bufferDone();
        nextBuffer(TRUE);
      }
      else
        nextAlarm();
    }
    return FAIL;
  }
  
  async event uint16_t* SingleChannel.multipleDataReady[uint8_t streamClient](
      uint16_t *buf, uint16_t length)
  {
    atomic
    {
      if (lastBuffer)
      {
        /* We failed to signal bufferDone in time. Fail. */
        bufferQueueEnd[client] = NULL; // prevent post
        post readStreamFail();
        return 0;
      }
      else
      {
        lastBuffer = buffer;
        lastCount = pos - buffer;
      }
    }
    post bufferDone();
    nextMultiple(streamClient);
    return 0;
  }

  const msp430adc12_channel_config_t defaultConfig = {
      inch: SUPPLY_VOLTAGE_HALF_CHANNEL,
      sref: REFERENCE_VREFplus_AVss,
      ref2_5v: REFVOLT_LEVEL_1_5,
      adc12ssel: SHT_SOURCE_ACLK,
      adc12div: SHT_CLOCK_DIV_1,
      sht: SAMPLE_HOLD_4_CYCLES,
      sampcon_ssel: SAMPCON_SOURCE_SMCLK,
      sampcon_id: SAMPCON_CLOCK_DIV_1
  };
  default async command const msp430adc12_channel_config_t* AdcConfigure.getConfiguration[uint8_t c]()
  { 
    return &defaultConfig;
  }
  default async command error_t SingleChannel.configureMultiple[uint8_t c](
      const msp430adc12_channel_config_t *config, uint16_t b[], 
      uint16_t numSamples, uint16_t jiffies)
  {
    return FAIL;
  }
  default async command error_t SingleChannel.getData[uint8_t c]()
  {
    return FAIL;
  }  
  default async command error_t SingleChannel.configureSingle[uint8_t c](
      const msp430adc12_channel_config_t *config){ return FAIL; }
}

--- NEW FILE: Msp430Adc12DMAWireC.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 $
 * $Date: 2008/04/07 09:41:55 $
 * @author: Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */

configuration Msp430Adc12DMAWireC
{ 
} implementation { 
  components Msp430DmaC, Msp430Adc12DMAP;
  Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;
  Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel2;
#warning Accessing DMA.channel2 for ADC12
}

--- NEW FILE: WireAdcStreamP.nc ---
/* $Id: WireAdcStreamP.nc,v 1.1 2008/04/07 09:41:55 janhauer Exp $
 * Copyright (c) 2005 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */
/**
 * Support component for AdcReadStreamClientC.
 *
 * @author David Gay
 * @author Jan Hauer 
 */

#include "Msp430Adc12.h"

configuration WireAdcStreamP {
  provides interface ReadStream<uint16_t>[uint8_t client];
  uses {
    interface AdcConfigure<const msp430adc12_channel_config_t*>[uint8_t client];
    interface Msp430Adc12SingleChannel[uint8_t client];
    interface Resource[uint8_t client];
  }
}
implementation {
  components AdcStreamP, MainC, new AlarmMilli32C() as Alarm, 
    new ArbitratedReadStreamC(uniqueCount(ADCC_READ_STREAM_SERVICE), uint16_t) as ArbitrateReadStream;

  ReadStream = ArbitrateReadStream;
  AdcConfigure = AdcStreamP;
  Resource = ArbitrateReadStream;

  ArbitrateReadStream.Service -> AdcStreamP;

  AdcStreamP.Init <- MainC;
  Msp430Adc12SingleChannel = AdcStreamP.SingleChannel;
  AdcStreamP.Alarm -> Alarm;
}

Index: AdcP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/AdcP.nc,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** AdcP.nc	12 Dec 2006 18:23:06 -0000	1.4
--- AdcP.nc	7 Apr 2008 09:41:55 -0000	1.5
***************
*** 39,43 ****
      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 {
--- 39,42 ----
***************
*** 49,57 ****
      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];
- 
    }
  }
--- 48,51 ----
***************
*** 62,71 ****
      STATE_READNOW,
      STATE_READNOW_INVALID_CONFIG,
-     STATE_READSTREAM,
-   };
-   
-   struct stream_entry_t {
-     uint16_t count;
-     struct stream_entry_t *next;
    };
    
--- 56,59 ----
***************
*** 74,87 ****
    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)
--- 62,65 ----
***************
*** 97,102 ****
    command error_t Read.read[uint8_t client]()
    {
-     if (call ResourceRead.isOwner[client]())
-       return EBUSY;
      return call ResourceRead.request[client]();
    }
--- 75,78 ----
***************
*** 109,114 ****
        state = STATE_READ;
        result = call SingleChannel.getData[client]();
!     }
!     if (result != SUCCESS){
        call ResourceRead.release[client]();
        signal Read.readDone[client](result, 0);
--- 85,89 ----
        state = STATE_READ;
        result = call SingleChannel.getData[client]();
!     } else {
        call ResourceRead.release[client]();
        signal Read.readDone[client](result, 0);
***************
*** 190,324 ****
      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;
-     if (call ResourceReadStream.isOwner[streamClient]())
-       return EBUSY;
-     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; }
--- 165,168 ----
***************
*** 333,348 ****
    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 async command bool ResourceReadStream.isOwner[uint8_t streamClient]() { return FALSE; }
!   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]()
    {
--- 177,181 ----
    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 SingleChannel.getData[uint8_t client]()
    {
***************
*** 350,354 ****
    }
  
-   // 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*
--- 183,186 ----
***************
*** 356,383 ****
    { 
      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; }
! 
! 
! }
! 
--- 188,194 ----
    { 
      return &defaultConfig;
!   }  
    default async command error_t SingleChannel.configureSingle[uint8_t client](
        const msp430adc12_channel_config_t *config){ return FAIL; }
!   
! } 

Index: AdcReadStreamClientC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/AdcReadStreamClientC.nc,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** AdcReadStreamClientC.nc	12 Dec 2006 18:23:07 -0000	1.4
--- AdcReadStreamClientC.nc	7 Apr 2008 09:41:55 -0000	1.5
***************
*** 49,60 ****
    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
  
--- 49,61 ----
    uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
  } implementation {
!   components WireAdcStreamP, 
  #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;
!   AdcConfigure = Msp430AdcClient.AdcConfigure;
  #else
!              new Msp430Adc12ClientC() as Msp430AdcClient;
  #endif
  
***************
*** 63,73 ****
    };
  
!   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
  }
    
--- 64,71 ----
    };
  
!   ReadStream = WireAdcStreamP.ReadStream[RSCLIENT];
!   AdcConfigure = WireAdcStreamP.AdcConfigure[RSCLIENT];
!   WireAdcStreamP.Resource[RSCLIENT] -> Msp430AdcClient.Resource;
!   WireAdcStreamP.Msp430Adc12SingleChannel[RSCLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
  }
    

Index: HplAdc12P.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/HplAdc12P.nc,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** HplAdc12P.nc	12 Dec 2006 18:23:07 -0000	1.4
--- HplAdc12P.nc	7 Apr 2008 09:41:55 -0000	1.5
***************
*** 54,72 ****
    MSP430REG_NORACE(ADC12IE);
    MSP430REG_NORACE(ADC12IV);
    
    async command void HplAdc12.setCtl0(adc12ctl0_t control0){
!     ADC12CTL0 = *(uint16_t*)&control0; 
    }
    
    async command void HplAdc12.setCtl1(adc12ctl1_t control1){
!     ADC12CTL1 = *(uint16_t*)&control1; 
    }
    
    async command adc12ctl0_t HplAdc12.getCtl0(){ 
!     return *(adc12ctl0_t*) &ADC12CTL0; 
    }
    
    async command adc12ctl1_t HplAdc12.getCtl1(){
!     return *(adc12ctl1_t*) &ADC12CTL1; 
    }
    
--- 54,76 ----
    MSP430REG_NORACE(ADC12IE);
    MSP430REG_NORACE(ADC12IV);
+ 
+   // SFRs are accessed directly or cast to a pointer, both works fine
+   // (we don't access all SFRs directly, because that would result in
+   // much higher memory footprint)
    
    async command void HplAdc12.setCtl0(adc12ctl0_t control0){
!     ADC12CTL0 = *((uint16_t*) &control0); 
    }
    
    async command void HplAdc12.setCtl1(adc12ctl1_t control1){
!     ADC12CTL1 = *((uint16_t*) &control1); 
    }
    
    async command adc12ctl0_t HplAdc12.getCtl0(){ 
!     return *((adc12ctl0_t*) &ADC12CTL0); 
    }
    
    async command adc12ctl1_t HplAdc12.getCtl1(){
!     return *((adc12ctl1_t*) &ADC12CTL1); 
    }
    
***************
*** 93,105 ****
    
    async command void HplAdc12.resetIFGs(){ 
!     if (!ADC12IFG)
!       return;
!     else {
!       // workaround, because ADC12IFG is not writable 
!       uint8_t i;
!       volatile uint16_t tmp;
!       for (i=0; i<16; i++)
!         tmp = call HplAdc12.getMem(i);
!     }
    } 
    
--- 97,102 ----
    
    async command void HplAdc12.resetIFGs(){ 
!     ADC12IV = 0; 
!     ADC12IFG = 0;
    } 
    
***************
*** 109,113 ****
    }
    
!   async command void HplAdc12.stopConversion(){ 
      ADC12CTL0 &= ~(ADC12SC + ENC); 
      ADC12CTL0 &= ~(ADC12ON); 
--- 106,112 ----
    }
    
!   async command void HplAdc12.stopConversion(){
!     // stop conversion mode immediately, conversion data is unreliable
!     ADC12CTL1 &= ~(CONSEQ0 | CONSEQ1);
      ADC12CTL0 &= ~(ADC12SC + ENC); 
      ADC12CTL0 &= ~(ADC12ON); 

Index: Msp430Adc12ClientAutoDMAC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12ClientAutoDMAC.nc,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** Msp430Adc12ClientAutoDMAC.nc	29 May 2007 16:19:20 -0000	1.5
--- Msp430Adc12ClientAutoDMAC.nc	7 Apr 2008 09:41:55 -0000	1.6
***************
*** 49,55 ****
      interface Resource;
      interface Msp430Adc12SingleChannel;
    }
  } implementation {
!   components Msp430DmaC, Msp430Adc12DMAP, Msp430Adc12P;
     
    enum {
--- 49,56 ----
      interface Resource;
      interface Msp430Adc12SingleChannel;
+     interface Msp430Adc12Overflow;
    }
  } implementation {
!   components Msp430DmaC, Msp430Adc12DMAP, Msp430Adc12P, Msp430Adc12DMAWireC;
     
    enum {
***************
*** 58,66 ****
    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;
  }
--- 59,66 ----
    Resource = Msp430Adc12P.Resource[ID];
    Msp430Adc12SingleChannel = Msp430Adc12DMAP.SingleChannel[ID];
+   Msp430Adc12Overflow = Msp430Adc12P.Overflow[ID];
    
    Msp430Adc12DMAP.SubSingleChannel[ID] -> Msp430Adc12P.SingleChannel[ID];
    Msp430Adc12DMAP.AsyncAdcControl[ID] -> Msp430Adc12P.DMAExtension[ID];
  
  }

Index: Msp430Adc12ClientAutoDMA_RVGC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12ClientAutoDMA_RVGC.nc,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** Msp430Adc12ClientAutoDMA_RVGC.nc	25 Jun 2007 13:44:49 -0000	1.6
--- Msp430Adc12ClientAutoDMA_RVGC.nc	7 Apr 2008 09:41:55 -0000	1.7
***************
*** 48,55 ****
      interface Resource;
      interface Msp430Adc12SingleChannel;
    }
    uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
  } implementation {
!   components Msp430Adc12P, Msp430RefVoltArbiterP;
  
    enum {
--- 48,56 ----
      interface Resource;
      interface Msp430Adc12SingleChannel;
+     interface Msp430Adc12Overflow;
    }
    uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
  } implementation {
!   components Msp430Adc12P, Msp430RefVoltArbiterP, Msp430Adc12DMAWireC;
  
    enum {
***************
*** 57,60 ****
--- 58,62 ----
    };
    Resource = Msp430RefVoltArbiterP.ClientResource[ID];
+   Msp430Adc12Overflow = Msp430Adc12P.Overflow[ID];
    
    Msp430RefVoltArbiterP.AdcResource[ID] -> Msp430Adc12P.Resource[ID];
***************
*** 70,76 ****
    Msp430Adc12DMAP.SubSingleChannel[ID] -> Msp430Adc12P.SingleChannel[ID];
    Msp430Adc12DMAP.AsyncAdcControl[ID] -> Msp430Adc12P.DMAExtension[ID];
- 
-   Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;
-   Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel0;
-   
  }
--- 72,74 ----

Index: Msp430Adc12ClientAutoRVGC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12ClientAutoRVGC.nc,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** Msp430Adc12ClientAutoRVGC.nc	25 Jun 2007 13:44:49 -0000	1.6
--- Msp430Adc12ClientAutoRVGC.nc	7 Apr 2008 09:41:55 -0000	1.7
***************
*** 47,50 ****
--- 47,51 ----
      interface Msp430Adc12SingleChannel;
      interface Msp430Adc12MultiChannel;
+     interface Msp430Adc12Overflow;
    }
    uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
***************
*** 58,61 ****
--- 59,63 ----
    Msp430Adc12SingleChannel = Msp430Adc12P.SingleChannel[ID];
    Msp430Adc12MultiChannel = Msp430Adc12P.MultiChannel[ID];
+   Msp430Adc12Overflow = Msp430Adc12P.Overflow[ID];
    
    Msp430RefVoltArbiterP.AdcResource[ID] -> Msp430Adc12P.Resource[ID];

Index: Msp430Adc12ImplP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12ImplP.nc,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** Msp430Adc12ImplP.nc	25 Jun 2007 15:47:15 -0000	1.5
--- Msp430Adc12ImplP.nc	7 Apr 2008 09:41:55 -0000	1.6
***************
*** 64,67 ****
--- 64,68 ----
  implementation
  { 
+ #warning Accessing TimerA for ADC12 
    enum {
      SINGLE_DATA = 1,
***************
*** 87,91 ****
--- 88,97 ----
    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;
    }
***************
*** 326,330 ****
          adc12ctl1_t ctl1 = {
            adc12busy: 0,
!           ctl1.conseq = 3,
            adc12ssel: config->adc12ssel,
            adc12div: config->adc12div,
--- 332,336 ----
          adc12ctl1_t ctl1 = {
            adc12busy: 0,
!           conseq: 3,
            adc12ssel: config->adc12ssel,
            adc12div: config->adc12div,
***************
*** 405,410 ****
          adc12ctl1_t ctl1 = {
            adc12busy: 0,
!           // use seq. of channels (rep.seq. channel does not work with TimerA + MSC ?)
!           conseq: (jiffies == 0) ? 3 : 1, 
            adc12ssel: config->adc12ssel,
            adc12div: config->adc12div,
--- 411,415 ----
          adc12ctl1_t ctl1 = {
            adc12busy: 0,
!           conseq: (numSamples > numMemctl+1) ? 3 : 1, 
            adc12ssel: config->adc12ssel,
            adc12div: config->adc12div,
***************
*** 421,425 ****
          uint16_t i, mask = 1;
          adc12ctl0_t ctl0 = call HplAdc12.getCtl0();
!         ctl0.msc = 1;
          ctl0.sht0 = config->sht;
          ctl0.sht1 = config->sht;
--- 426,430 ----
          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;
***************
*** 482,492 ****
      resetAdcPin( (call HplAdc12.getMCtl(0)).inch );
      if (state & MULTI_CHANNEL){
-       ADC12IV = 0; // clear any pending overflow
        for (i=1; i<numChannels; i++)
          resetAdcPin( (call HplAdc12.getMCtl(i)).inch );
      }
!     call HplAdc12.stopConversion();
!     call HplAdc12.resetIFGs(); 
!     state &= ~ADC_BUSY;
    }
  
--- 487,498 ----
      resetAdcPin( (call HplAdc12.getMCtl(0)).inch );
      if (state & MULTI_CHANNEL){
        for (i=1; i<numChannels; i++)
          resetAdcPin( (call HplAdc12.getMCtl(i)).inch );
      }
!     atomic {
!       call HplAdc12.stopConversion();
!       call HplAdc12.resetIFGs(); 
!       state &= ~ADC_BUSY;
!     }
    }
  
***************
*** 505,515 ****
    async command error_t DMAExtension.stop[uint8_t id]()
    {
!     atomic {
!       if (call ADCArbiterInfo.userId() == id){
!         stopConversion();
!         return SUCCESS;
!       }
!     }
!     return FAIL;
    }
    
--- 511,516 ----
    async command error_t DMAExtension.stop[uint8_t id]()
    {
!     stopConversion();
!     return SUCCESS;
    }
    
***************
*** 520,523 ****
--- 521,525 ----
    async event void HplAdc12.conversionDone(uint16_t iv)
    {
+     bool overflow = FALSE;
      if (iv <= 4){ // check for overflow
        if (iv == 2)
***************
*** 525,528 ****
--- 527,533 ----
        else
          signal Overflow.conversionTimeOverflow[clientID]();
+       // only if the client didn't ask for data as fast as possible (jiffies was not zero)
+       if (!(call HplAdc12.getCtl0()).msc)
+         overflow = TRUE;
      }
      switch (state & CONVERSION_MODE_MASK) 
***************
*** 537,541 ****
            repeatContinue = signal SingleChannel.singleDataReady[clientID](
                  call HplAdc12.getMem(0));
!           if (repeatContinue == FAIL)
              stopConversion();
            break;
--- 542,546 ----
            repeatContinue = signal SingleChannel.singleDataReady[clientID](
                  call HplAdc12.getMem(0));
!           if (repeatContinue != SUCCESS)
              stopConversion();
            break;
***************
*** 544,557 ****
        case MULTI_CHANNEL:
          {
!           uint16_t i = 0;
            do {
              *resultBuffer++ = call HplAdc12.getMem(i);
            } while (++i < numChannels);
            resultBufferIndex += numChannels;
!           if (resultBufferLength == resultBufferIndex){
              stopConversion();
!             resultBuffer -= resultBufferLength;
              resultBufferIndex = 0;
!             signal MultiChannel.dataReady[clientID](resultBuffer, resultBufferLength);
            } else call HplAdc12.enableConversion();
          }
--- 549,564 ----
        case MULTI_CHANNEL:
          {
!           uint16_t i = 0, k;
            do {
              *resultBuffer++ = call HplAdc12.getMem(i);
            } while (++i < numChannels);
            resultBufferIndex += numChannels;
!           if (overflow || resultBufferLength == resultBufferIndex){
              stopConversion();
!             resultBuffer -= resultBufferIndex;
!             k = resultBufferIndex - numChannels;
              resultBufferIndex = 0;
!             signal MultiChannel.dataReady[clientID](resultBuffer, 
!                 overflow ? k : resultBufferLength);
            } else call HplAdc12.enableConversion();
          }
***************
*** 559,563 ****
        case MULTIPLE_DATA:
          {
!           uint16_t i = 0, length;
            if (resultBufferLength - resultBufferIndex > 16) 
              length = 16;
--- 566,570 ----
        case MULTIPLE_DATA:
          {
!           uint16_t i = 0, length, k;
            if (resultBufferLength - resultBufferIndex > 16) 
              length = 16;
***************
*** 568,583 ****
            } 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);
            }
          }
--- 575,592 ----
            } while (++i < length);
            resultBufferIndex += length;
!           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 {
!             // last sequence < 16 samples
              adc12memctl_t memctl = call HplAdc12.getMCtl(0);
              memctl.eos = 1;
              call HplAdc12.setMCtl(resultBufferLength - resultBufferIndex, memctl);
            }
          }
***************
*** 592,596 ****
            resultBuffer = signal SingleChannel.multipleDataReady[clientID](
                resultBuffer-resultBufferLength,
!                     resultBufferLength);
            if (!resultBuffer)  
              stopConversion();
--- 601,605 ----
            resultBuffer = signal SingleChannel.multipleDataReady[clientID](
                resultBuffer-resultBufferLength,
!               overflow ? 0 : resultBufferLength);
            if (!resultBuffer)  
              stopConversion();

Index: Msp430Adc12MultiChannel.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/Msp430Adc12MultiChannel.nc,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** Msp430Adc12MultiChannel.nc	12 Dec 2006 18:23:07 -0000	1.2
--- Msp430Adc12MultiChannel.nc	7 Apr 2008 09:41:55 -0000	1.3
***************
*** 75,85 ****
     * numSamples = (numMemctl+1) * 2
     *
!    * @param jiffies Sampling period per sequence in terms of clock ticks of
!    * "sampcon_ssel" and input divider "sampcon_id". A sequence of (numMemctl+1)
!    * is always sampled as fast as possible and <code>jiffies</code> specifies
!    * the time between those sequences. For example, if numSamples =
!    * (numMemctl+1) * 5, then dataReady() will be signalled after (approx.)
!    * 5*jiffies clock ticks after the call to getData() and each set of
!    * numMemctl+1 channels was sampled at (almost) the same time.
     *
     * @return SUCCESS means that the ADC was configured successfully and
--- 75,80 ----
     * numSamples = (numMemctl+1) * 2
     *
!    * @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

Index: README.txt
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/chips/msp430/adc12/README.txt,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** README.txt	25 Jun 2007 15:47:15 -0000	1.6
--- README.txt	7 Apr 2008 09:41:55 -0000	1.7
***************
*** 37,42 ****
  single channel with a specified sampling frequency and (2) the
  Msp430Adc12MultiChannel allows to sample a group of up to 16 different ADC
! channels "at once" (with minimum latency) and in addition define a sampling
! frequency for the whole group (useful for multi-channel accelerometers, etc.).
  On the MSP430 two additional hardware modules may play a role when the ADC12 is
  used: the internal reference voltage generator and the DMA controller. 
--- 37,42 ----
  single channel with a specified sampling frequency and (2) the
  Msp430Adc12MultiChannel allows to sample a group of up to 16 different ADC
! channels.
! 
  On the MSP430 two additional hardware modules may play a role when the ADC12 is
  used: the internal reference voltage generator and the DMA controller. 



More information about the Tinyos-2-commits mailing list