]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/msp430/adc12/AdcP.nc
Updated files.
[tinyos-2.x.git] / tos / chips / msp430 / adc12 / AdcP.nc
diff --git a/tos/chips/msp430/adc12/AdcP.nc b/tos/chips/msp430/adc12/AdcP.nc
new file mode 100644 (file)
index 0000000..654807a
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * 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$
+ * $Date$
+ * @author: Jan Hauer <hauer@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]()
+  {
+    if (call ResourceRead.isOwner[client]())
+      return EBUSY;
+    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;
+    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; }
+  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 async command bool ResourceRead.isOwner[uint8_t client]() { return FALSE; }
+  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 async command bool SubResourceReadNow.isOwner[uint8_t client]() { return FALSE; }
+  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]()
+  {
+    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; }
+
+
+}
+