[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/imote2/tos/sensorboards/Framework BoardManager.nc, NONE, 1.1 BufferManagementDispatchM.nc, NONE, 1.1 ChannelManager.nc, NONE, 1.1 ChannelManagerM.nc, NONE, 1.1 channelParams.h, NONE, 1.1 ChannelParamsManager.nc, NONE, 1.1 ChannelParamsManagerM.nc, NONE, 1.1 DSPManager.nc, NONE, 1.1 frameworkconfig.h, NONE, 1.1 postprocessingFunctions.h, NONE, 1.1 SensorboardC.nc, NONE, 1.1 SensorboardM.nc, NONE, 1.1 SensorData.nc, NONE, 1.1 SensorDataInfo.nc, NONE, 1.1 sensorTypes.h, NONE, 1.1 triggerFunctions.h, NONE, 1.1 TriggerManager.nc, NONE, 1.1 TriggerManagerM.nc, NONE, 1.1 triggerOps.h, NONE, 1.1

Robbie Adler radler at users.sourceforge.net
Wed Oct 25 08:03:55 PDT 2006


Update of /cvsroot/tinyos/tinyos-1.x/contrib/imote2/tos/sensorboards/Framework
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv27317/sensorboards/Framework

Added Files:
	BoardManager.nc BufferManagementDispatchM.nc ChannelManager.nc 
	ChannelManagerM.nc channelParams.h ChannelParamsManager.nc 
	ChannelParamsManagerM.nc DSPManager.nc frameworkconfig.h 
	postprocessingFunctions.h SensorboardC.nc SensorboardM.nc 
	SensorData.nc SensorDataInfo.nc sensorTypes.h 
	triggerFunctions.h TriggerManager.nc TriggerManagerM.nc 
	triggerOps.h 
Log Message:
initial release of driver framework and basicsensorboard driver

--- NEW FILE: BoardManager.nc ---
/***
 *
 * @author Robbie Adler
 *
 * This interface provides board specific channel enabling commands for use with the GenericSampling Sensorboard architecture
 *
 */
interface BoardManager{
  
  //operates on a list of exposed channels
  command result_t enableChannelsToBeSampled(uint8_t numChannels, uint8_t *channelList);
  
  //operates on a list of dataChannels
  command result_t startDataChannels(uint8_t numChannels, uint8_t *channelList);
}

--- NEW FILE: BufferManagementDispatchM.nc ---



module BufferManagementDispatchM{
  provides{
    interface BufferManagement as InsideBufferManagement;
  }
  uses{
    interface BufferManagement as OutsideBufferManagement;
  }
}
implementation{
  command uint8_t *InsideBufferManagement.AllocBuffer(uint32_t numBytes){
    return call OutsideBufferManagement.AllocBuffer(numBytes);
  }		
  
  /**
   * Release Buffer
   * @param buffer Previously allocated buffer
   * @return SUCCESS/FAIL 
   */
  command result_t InsideBufferManagement.ReleaseBuffer(uint8_t *buffer){
    return call OutsideBufferManagement.ReleaseBuffer(buffer);
  }		
}

--- NEW FILE: ChannelManager.nc ---
/**
 * @author Robbie Adler
 **/


interface ChannelManager{
  
  /**
   *command to "start" a list of channels.  In the context of the channel manager, the
   *start function is used to actually start the sampling process on a channel
   *
   *
   *
   **/
  
  command result_t startChannels(uint8_t numChannels, 
			 uint8_t *channelList);
  
  /**
   * command to "warmup" a bunch of channels.  When the warmup time has elapsed,
   * warmupDone will be signalled
   *
   *
   *
   *
   **/
  command result_t warmupChannels(uint8_t numChannels, 
				  uint8_t *channelList);
  
  event result_t warmupChannelsDone(uint8_t numChannels, 
				    uint8_t *channelList);
  
  
  /**
   * Wait for data on a list of channels
   * @param numChannels:  Number of channels that we're waiting on
   * @param targetChannels:  array of channels that we're waiting on
   * @param timeout:  timeout to keep while waiting for the current set of trigger conditions
   * 
   * @return FAIL if this is not possible; SUCCESS otherwise
   *
   **/
  command result_t waitForData(uint8_t numChannels, uint8_t *targetChannels);

  
  /**
   * all the channel mananger to prepare a channel to be sampled.
   * 
   *
   *
   *
   *
   *
   * @param memoryRequested: pointer to a variable that the ChannelManager may store information about the
   * amount of memory that it thinks is requested for this transaction
   *
   * @param memoryRequired: pointer to a variable that the ChannelManager may store information about the
   * amount of memory that it thinks is required for this transaction
   *
   * @return: SUCCESS if all of the parameters are valid options, FAIL otherwise
   **/

  command result_t prepareChannel(uint8_t channel, 
				  uint32_t samplingRate, 
				  uint32_t numSamples, 
				  uint8_t sampleWidth, 
				  bool streaming, 
				  uint32_t warmup, 
				  uint32_t type, 
				  uint32_t function, 
				  TypeValItem *other);
							  
  event result_t DataReady(uint8_t channel, uint16_t numBytes, bool done);

  command result_t addTrigger(uint8_t boolOp, 
			      uint32_t triggerFunction,
			      float triggerValue, 
			      uint32_t triggerWindowSamples,
			      uint8_t triggerChannel,
			      uint8_t targetChannel);

  command void clearTrigger(uint8_t targetChannel);

  
}

--- NEW FILE: ChannelManagerM.nc ---
/**
 * @author Robbie Adler
 **/

includes queue;

module ChannelManagerM{
  provides {
    interface ChannelManager;
    interface StdControl;
  }
  uses {
    interface ChannelParamsManager[uint8_t instance];
    interface DSPManager[uint8_t instance];
    interface BufferManagement;
    interface BoardManager;
    interface TriggerManager;
    interface Timer as ADCWarmupTimer;
    interface WriteData;
    interface WallClock;
  }
}
implementation {

#include "frameworkconfig.h"
#include "sensorboard.h"
  
#define WRAPPERHEADER_FIRSTOFFSET (12)
  
  typedef struct{
    uint32_t warmupTime;
    uint32_t requiredSize;
    uint32_t requestedSize;
    uint32_t samplingRate;
    uint32_t numSamples;
    uint8_t sampleWidth;
  }sampleInfo_t __attribute__((packed));

  typedef struct{
    uint32_t warmup;
    uint8_t *channelList;
    uint8_t numChannels;
  }channelList_t;
  
  sampleInfo_t gSampleInfo[TOTAL_DATA_CHANNELS];
  bool gPreparedChannelState[TOTAL_CHANNELS];
  bool bWarmupTimerRunning = FALSE;
  bool channelInProgress[TOTAL_DATA_CHANNELS];
  uint8_t gDataChannelPreparedChannel[TOTAL_DATA_CHANNELS];
  queue_t warmupTimeQueue;
  
  uint32_t gSequenceID;

  command result_t StdControl.init(){
    int i;
    
    //make sure that all of these ID's are initialized to FALSE
    for(i=0; i<TOTAL_DATA_CHANNELS; i++){
      channelInProgress[i] = FALSE;
      gDataChannelPreparedChannel[i] = INVALID_CHANNEL_ID;
    }
    
    initqueue(&warmupTimeQueue, defaultQueueSize);
    gSequenceID = 0; //initialize just to make sure
    return SUCCESS;
  }
  
  command result_t StdControl.start(){
    
    return SUCCESS;
  }

  command result_t StdControl.stop(){
    
    return SUCCESS;
  }
  
  /***********************************
this module is intended to manage the current set of channels.  It contains state information
that indicates whether a channel is ready to be run.
   
other purposes of this module:
-manage the sample header for the sensorboard.  It provide functions for a using module to determine
 the size of the sampleheader as well as function to write the sampleheader into a provided buffer
 the intent here is for the using module to never be aware of the implementation of the of the sampleheader
 so that we can minimize the dependence on the specific structure to allow for future modifications

  ***************/  
  
  bool isSamplingInProgress(uint8_t channel);
  result_t getDataChannelFromChannel(uint8_t channel, uint8_t *dataChannel);
  result_t getChannelFromDataChannel(uint8_t dataChannel, uint8_t *channel);
  result_t isSupportedSamplingRate(uint8_t channel, uint32_t samplingRate);  
  result_t isSupportedNumSamples(uint8_t channel, uint32_t numSamples);
  result_t isSupportedSampleWidth(uint8_t channel, uint8_t sampleWidth);
  result_t isSupportedStreaming(uint8_t channel, bool streaming);
  result_t isSupportedSensorType(uint8_t channel, uint32_t type);
  result_t isSupportedFunction(uint8_t channel, uint32_t function);


  command result_t ChannelManager.startChannels(uint8_t numChannels, 
					uint8_t *channelList){
    
    
    uint32_t i,j;
    
    if(numChannels == 0){
      //this is an error
      trace(DBG_USR1,"FAIL:  GenericSamplng.start requires numChannels > 0\r\n");
      return FAIL;
    }
    
    if(channelList == NULL){
      trace(DBG_USR1,"ASSERT:  GenericSamplng.start passed NULL channelList\r\n");
    }
    
    //check to make sure that all of the channels listed are a part of the same simultaneous sampling group
    //if our board's capabilities table is configured correctly and this function is used correctly, the
    //simulChannelGroup for all of the channels in our list should be the same
    for(i=1; i<numChannels; i++){
      if(dataChannelCapabilitiesTable[channelList[0]].simulChannelGroup != dataChannelCapabilitiesTable[channelList[i]].simulChannelGroup){
	trace(DBG_USR1,"FAIL:  GenericSampling.start requires that all started channels be a member of the same simultaneous sampling group\r\n");
	return FAIL;
      }
    }
    //all of the channels are part of the same simultaneous sampling group.
    
    //Now, make sure that all of the channels have been prepared and that we're only starting a channel once
    for(i=0;i<numChannels; i++){
      uint8_t dataChannel;
      if(getDataChannelFromChannel(channelList[i], &dataChannel) == FAIL){
	trace(DBG_USR1,"FAIL:  GenericSampling.start unable to lookup dataChannel from sensor channel\r\n");
	return FAIL;
      }
      if(gDataChannelPreparedChannel[dataChannel] != channelList[i]){
	//this channel was not actually prepared
	trace(DBG_USR1,"FAIL:  GenericSampling.start attempted to start unprepared channel %d\r\n",channelList[i]);
      }
      //make sure that we're only starting a channel once..should only have to look forward in the array
      for(j=i+1; j<numChannels; j++){
	if(channelList[i] == channelList[j]){
	  //we have a duplicate!
	  trace(DBG_USR1,"FAIL:  GenericSamplng.start attempting to start channel %d more than once\r\n", channelList[i]);
	  return FAIL;
	}
      }
    }
    
    //turn on the channels that we need to turn on...
    if(call BoardManager.enableChannelsToBeSampled(numChannels, channelList) == FAIL){
      trace(DBG_USR1,"FAIL:  GenericSamplng.start unable to enable channel list to be sampled\r\n");
      return FAIL;
    }

    gSequenceID++;
    
    return SUCCESS;
  }
  
  task void warmupTimerExpiredTask(){
    
    channelList_t *list;

    //get the entry at the top of queue
    if(popqueue(&warmupTimeQueue,(uint32_t *)&list)){
      //found something in the queue
    }
    else{
      trace(DBG_USR1,"FATAL ERROR...warmupTimerExpiredTask did not find a queue entry\r\n");
      return;
    }
    
    signal ChannelManager.warmupChannelsDone(list->numChannels, list->channelList);
    
    free(list->channelList);
    free(list);
    
    if(peekqueue(&warmupTimeQueue,(uint32_t *)&list)){
      trace(DBG_USR1,"Info:  warmupTimerExpiredTask found a concurrent warmup request\r\n");
      call ADCWarmupTimer.start(TIMER_ONE_SHOT,list->warmup/1000);
    }
  }
  
  event result_t ADCWarmupTimer.fired(){
    
    trace(DBG_USR1,"ADC Warmup timer expired...\r\n");
    bWarmupTimerRunning= FALSE;
    
    //not sure what happens if we request another one shot in the event for the previous 1
    post warmupTimerExpiredTask();
    
    return SUCCESS;
  }
  
  
  
  command result_t ChannelManager.warmupChannels(uint8_t numChannels, 
						 uint8_t *channelList){
    
    /********
     *This function needs to take the list of channels, calculate the
     * max warmup time required across all channels, start a timer 
     * for this warmup, and signal the warmupChannelsDone event when 
     * the timer has expired.
     *
     *********/
    int i;
    uint8_t dataChannel;
    uint32_t time, totalTime=0;
    channelList_t *newList;
    
    if(channelList == NULL){
      return FAIL;
    }
    
    for (i=0; i<numChannels; i++){
      if(getDataChannelFromChannel(channelList[i], &dataChannel) == FAIL){
	return FAIL;
      }
      time = gSampleInfo[dataChannel].warmupTime;
      if(time > totalTime){
	// this implies that we have a new max...store it
	totalTime = time;
      } 
      else{
	//ignore it...we already found our max
      }
    }
    trace(DBG_USR1,"INFO:  Total warmup time requested = %dms\r\n",totalTime/1000);
    
    
    
    if((newList = malloc(sizeof(channelList_t)))==NULL){
      trace(DBG_USR1,"FATAL ERROR:  unable to allocate enough memory in warmupChannels\r\n");
      return FAIL;
    }
    
    //got enough memory, now allocate the internal array so that we can copy state
    if( (newList->channelList = malloc(numChannels)) == NULL){
      //we didn't get the memory we need...deallocate and FAIL
      free(newList);
      trace(DBG_USR1,"FATAL ERROR:  unable to allocate enough memory in warmupChannels\r\n");
      return FAIL;
    }
    //got our memory
    newList->warmup = time;
    memcpy(newList->channelList,channelList,numChannels);
    newList->numChannels = numChannels;
    pushqueue(&warmupTimeQueue,(uint32_t)newList);
    
    if(totalTime > 0){
      if(bWarmupTimerRunning){
	//already have a warmupTimer running...don't do anything.  We'll pull out the next
	//time request from the queue once the time hits
      }
      else{
	bWarmupTimerRunning = TRUE;
	call ADCWarmupTimer.start(TIMER_ONE_SHOT,totalTime/1000);
      } 
    }
    else{
      //no warmup time is requested:
      post warmupTimerExpiredTask();
    }
    return SUCCESS;
  }
  
  command result_t ChannelManager.prepareChannel(uint8_t channel, 
						 uint32_t samplingRate, 
						 uint32_t numSamples, 
						 uint8_t sampleWidth, 
						 bool streaming, 
						 uint32_t warmup, 
						 uint32_t type, 
						 uint32_t function, 
						 TypeValItem *other){
    
    
    uint32_t requiredSize, requestedSize, numRecords;
    size_t headerSize;
    uint8_t dataChannel;
    sampleInfo_t *pSi;

    if(isSamplingInProgress(channel)){
      trace(DBG_USR1,"FAIL:  GenericSampling.prepare called while sampling in progress for channel %d channel group\r\n",
	    channel);
      return FAIL;
    }
    
    //check out the supported sampling rates if we need to
    if(isSupportedSamplingRate(channel, samplingRate) == FAIL){
      trace(DBG_USR1,"Unsupported Sampling rate %d passed in\r\n",samplingRate);
      return FAIL;
    }
       
    if(isSupportedNumSamples(channel, numSamples) == FAIL){
      trace(DBG_USR1,"Unsupported Number of Samples %d passed in\r\n",numSamples);
      return FAIL;
    }
    
    if(isSupportedSampleWidth(channel, sampleWidth) == FAIL){
      trace(DBG_USR1,"Unsupported Sample Width %d passed in\r\n",sampleWidth);
      return FAIL;
    }
    
    //HACK!!  need to properly differentiate between the bit width of the sample and the bit width of the sample's storage
    sampleWidth = sampleWidth/8;
    
    if(isSupportedStreaming(channel, streaming)== FAIL){
      trace(DBG_USR1,"Streaming is not currently supported\r\n");
      return FAIL;
    }
    
    if(isSupportedSensorType(channel, type)== FAIL){
      trace(DBG_USR1,"Unsupported Sensor Type %d passed in\r\n",type);
      //print an error meesage here saying that we failed the sampling rate test
      return FAIL;
    }       
    
    if(isSupportedFunction(channel, function)==FAIL){
      trace(DBG_USR1,"Unsupported Post Processing Function %#x passed in\r\n",function);
      return FAIL;
    }
    
    if(getDataChannelFromChannel(channel, &dataChannel) == FAIL){
      return FAIL;
    }
    
    pSi = &gSampleInfo[dataChannel];

#ifdef DOCHUNKING
    if(DOCHUNKING){
      uint16_t numBuffers;
      
      numBuffers = numSamples/CHUNKSIZE;
      
      if((numBuffers*CHUNKSIZE) != numSamples){
	numBuffers++;
      }
      numSamples = numBuffers * CHUNKSIZE;
    }
#endif

    if(call ChannelParamsManager.storeParams[dataChannel](channel,
							  samplingRate, 
							  numSamples, 
							  sampleWidth, 
							  streaming, 
							  type, 
							  function, 
							  other) == FAIL){
      return FAIL;
    }
    
    if(call DSPManager.initPostProcessing[dataChannel](samplingRate, 
						       numSamples, 
						       sampleWidth, 
						       streaming, 
						       warmup, 
						       type, 
						       function, 
						       other) == FAIL){
      return FAIL;
    }
    //store warmuptime and get a buffer
    pSi->warmupTime = warmup;
    //now, get a dataBuffer for this acquisition
    headerSize = call ChannelParamsManager.getHeaderSize[dataChannel]();
    if(call DSPManager.getDataStorageSize[dataChannel](&requestedSize, &requiredSize, &numRecords) == SUCCESS){
       //DSPManager is alive and can give us some idea of how many bytes we need.
      //Now, we can adjust this paramater based on what our needs are 
      
      requestedSize += (numRecords * headerSize) + WRAPPERHEADER_FIRSTOFFSET; 
      requiredSize += (numRecords * headerSize) + WRAPPERHEADER_FIRSTOFFSET;  
    }
    else{
      //DSPManager for this channel doesn't do anything.  We need to estimate how much storage we need:
      
      //this is the size that we'd like the allocator to give us
      requestedSize = headerSize + WRAPPERHEADER_FIRSTOFFSET  + sampleWidth*numSamples;
      //this is the minimum size that the allocator can return to us
      requiredSize = headerSize + WRAPPERHEADER_FIRSTOFFSET  + sampleWidth;  
    }
    
    pSi->requestedSize = requestedSize;
    pSi->requiredSize = requiredSize;

    pSi->samplingRate = samplingRate;
    pSi->numSamples = numSamples;
    pSi->sampleWidth = sampleWidth;
    
    //mark the data channel as having been prepared with this external channel Id.
    //Note:  this is redundant information as the same exact piece of info should be
    //stored in the ChannelParamsManager.  However, we want to store this piece of
    //information here because it helps keep the line drawn between the "generic"
    //ChannelManager and the "sampleHeader specific ChannelParamsManager
    gDataChannelPreparedChannel[dataChannel] = channel;
    
    return SUCCESS;
  }

  command result_t ChannelManager.addTrigger(uint8_t boolOp, 
					     uint32_t triggerFunction,
					     float triggerValue, 
					     uint32_t triggerWindowSamples,
					     uint8_t triggerChannel,
					     uint8_t targetChannel){
    //translate channel id's...call TriggerManager
    uint8_t translatedTriggerChannel, translatedTargetChannel;

    getDataChannelFromChannel(targetChannel,&translatedTargetChannel);
    getDataChannelFromChannel(triggerChannel,&translatedTriggerChannel);
    
    return call TriggerManager.addTrigger(boolOp, 
					  triggerFunction, 
					  triggerValue,
					  triggerWindowSamples,
					  translatedTriggerChannel, 
					  translatedTargetChannel);
  }
  
  command void ChannelManager.clearTrigger(uint8_t targetChannel){
    //translate id..call TriggerManager
    uint8_t translatedTargetChannel;
    getDataChannelFromChannel(targetChannel,&translatedTargetChannel);
    
    return call TriggerManager.clearTrigger(translatedTargetChannel);
  }
    
  bool isSamplingInProgress(uint8_t channel){
    return (channelInProgress[channel]);
  }
      
  result_t getDataChannelFromChannel(uint8_t channel,uint8_t *dataChannel){
    const supportedCommonFeatureList32_t *feature;
    
    if(channel >= TOTAL_CHANNELS){
      return FAIL;
    }
               
    feature = channelCapabilitiesTable[channel].supportedSensorTypes;
    if((feature != NULL) && (dataChannel != NULL)){
      *dataChannel=feature->commonFeature;
      return SUCCESS;
    }
    else{
      return FAIL;
    }
  }
  
  result_t getChannelFromDataChannel(uint8_t dataChannel, uint8_t *channel){
    if(channel){
      *channel = gDataChannelPreparedChannel[dataChannel];
      return SUCCESS;
    }
    else{
      return FAIL;
    }
  }

  result_t isSupportedSamplingRate(uint8_t channel, uint32_t samplingRate){
    
    const supportedFeatureList32_t *feature;
    uint32_t i;
    
    feature = channelCapabilitiesTable[channel].supportedSamplingRates;
    if(feature != NULL){
      //channel only has has specific sampling rates that it supports
      //find if the support sampling rate is there
      for(i=0; i<feature->numElements; i++){
	if(feature->elements[i] == samplingRate){
	  return SUCCESS;
	}
      }
    }
    else{
      //we support all sampling rates
      return SUCCESS;
    }
    return FAIL;
  }
  
  result_t isSupportedNumSamples(uint8_t channel, uint32_t numSamples){
     return SUCCESS;
  }
      
  result_t isSupportedSampleWidth(uint8_t channel, uint8_t sampleWidth){
    const supportedFeatureList8_t *feature;
    uint32_t i;
    
    feature = channelCapabilitiesTable[channel].supportedSampleWidths;
    if(feature != NULL){
      //channel only has has specific sampling rates that it supports
      //find if the supported sampling width
      for(i=0; i<feature->numElements; i++){
	if(feature->elements[i] == sampleWidth){
	  return SUCCESS;
	}
      }
    }
    else{
      //we support all sampling widths
      return SUCCESS;
    }
    return FAIL;
  }
  
  result_t isSupportedStreaming(uint8_t channel, bool streaming){
    if(streaming == FALSE){
      return SUCCESS;
    }
    return FAIL;
  }
    
  result_t isSupportedSensorType(uint8_t channel, uint32_t type)  {
    const supportedCommonFeatureList32_t *feature;
    uint32_t i,element;
    
    
    feature = channelCapabilitiesTable[channel].supportedSensorTypes;
    if(feature != NULL){
      if(feature->numElements == 0){
	//special case to indicate that anything is supported
	return SUCCESS;
      }
      
      for(i=0; i<feature->numElements; i++){
	element = feature->elements[i];
	switch(GET_SENSOR_TYPE(element)){
	case SENSOR_ANALOG:
	  { 

	    uint32_t coupling, phytype, inputtype, range;
	    coupling = GET_ANALOG_COUPLING(type) & GET_ANALOG_COUPLING(element);
	    phytype = GET_ANALOG_PHYSICAL_TYPE(type) & GET_ANALOG_PHYSICAL_TYPE(element);
	    inputtype = GET_ANALOG_INPUT_TYPE(type) & GET_ANALOG_INPUT_TYPE(element);
	    range = GET_ANALOG_INPUT_RANGE(type) & GET_ANALOG_INPUT_RANGE(element);
	    if(coupling && phytype && inputtype && range){
	      return SUCCESS;
	    }
	  }
	  break;
	case SENSOR_DIGITAL:
	  {
	    uint32_t dtype;
	    dtype = GET_DIGITAL_TYPE(type) & GET_DIGITAL_TYPE(element);
	    if(dtype){
	      return SUCCESS;
	    }
	  }
	  return SUCCESS;
	  
	  break;
	default:
	  //unknown type:
	  break;
	}
      }
    }
    else{
      //FATAL ERROR!!
      return FAIL;
    }

    return FAIL;
  }  
  
  result_t isSupportedFunction(uint8_t channel, uint32_t function){
    uint8_t dataChannel;
    getDataChannelFromChannel(channel, &dataChannel);
    return call DSPManager.isSupportedFunction[dataChannel](function);
  }
    
  
  
#if 0
  void combineChannelMaps(channelMap_t *output, uint8_t mapindex){
    uint8_t temp;
    //selects just get or'd together
    output->selects = output->selects | channelIdMapOnTable[mapindex].selects;
    
    //enables get or'd togher except for VCC3_SENSOR_EN which is active low and needs to be and'd 
    temp = eGET(output->enables, VCC3_SENSOR_EN); 
    temp &= eGET(channelIdMapOnTable[mapindex].enables, VCC3_SENSOR_EN);   
    temp |= ~(1<<VCC3_SENSOR_EN);  //temp now has it's low bit the and of the two signals and all other bits 1's
    output->enables |= (channelIdMapOnTable[mapindex].enables & ~(1<<VCC3_SENSOR_EN));
    output->enables &= temp;
    
    return;
  }
  
  void copyChannelMap(channelMap_t *output, uint8_t mapindex){
    output->selects = channelIdMapOnTable[mapindex].selects; 
    output->enables = channelIdMapOnTable[mapindex].enables; 
  }
#endif 

  
  default command result_t DSPManager.initPostProcessing[uint8_t instance](uint32_t samplingRate, 
									   uint32_t numSamples, 
									   uint8_t sampleWidth, 
									   bool streaming, 
									   uint32_t warmup, 
									   uint32_t type, 
									   uint32_t function, 
									   TypeValItem *other){
    trace(DBG_USR1,"WARNING:  No DSPManager instance installed on datachannel %d\r\n",instance);
    return SUCCESS;
  }

  default command result_t DSPManager.isSupportedFunction[uint8_t instance](uint32_t function){
    if(function){
      return FAIL;
    }
    else{
      return SUCCESS;
    }
  }
  
  default command result_t DSPManager.getDataStorageSize[uint8_t instance](uint32_t *requestedSize, 
									   uint32_t *requiredSize,
									   uint32_t *numRecords){
    *requestedSize = 0;
    *requiredSize = 0;
    return FAIL;
  }

  event result_t TriggerManager.TriggeredData(uint8_t dataChannel,
					      uint8_t *buffer, 
					      float ADCScale,
					      float ADCOffset,
					      uint16_t numBytesWrite, 
					      uint16_t numBytesTotal, 
					      uint16_t numSamples,
					      uint64_t timestamp,
					      bool done){
    
    
    uint8_t channel;
    sampleInfo_t *pSi;
    
    
    call ChannelParamsManager.setNumSamples[dataChannel](numSamples);
    call ChannelParamsManager.setMicroTimestamp[dataChannel](timestamp);
    call ChannelParamsManager.setWallTimestamp[dataChannel](call WallClock.getWallClock());
    call ChannelParamsManager.setADCScale[dataChannel](ADCScale);
    call ChannelParamsManager.setADCOffset[dataChannel](ADCOffset);
    call ChannelParamsManager.setSequenceID[dataChannel](gSequenceID);
    
    call ChannelParamsManager.writeSampleHeader[dataChannel](buffer);
    call ChannelParamsManager.incrementSampleOffset[dataChannel](numSamples);
        
    getChannelFromDataChannel(dataChannel,&channel);
    pSi = &gSampleInfo[dataChannel];
    
    call WriteData.write(0, 
			 buffer, 
			 numBytesWrite);
        
    if(done){
      signal ChannelManager.DataReady(channel, pSi->numSamples, done);
    }
    
    return SUCCESS;
  }

  command result_t ChannelManager.waitForData(uint8_t numChannels, uint8_t *targetChannels){
    //translate this list of channels to a list of data channels for the triggermanager!!!
    uint8_t *translatedChannelList;
    int i;
    
    if(targetChannels == NULL){
      trace(DBG_USR1,"ChannelManager.waitForData passed NULL targetChannels pointer\r\n");
    }
    
    if((translatedChannelList = malloc(numChannels*sizeof(*translatedChannelList))) == NULL){
      trace(DBG_USR1,"ChannelManager.waitForData unable to allocate translated channel array\r\n");
      return FAIL;
    }
    
    for(i=0; i<numChannels; i++){
      sampleInfo_t *pSi;
      uint8_t UOM;
      
      getDataChannelFromChannel(targetChannels[i], &(translatedChannelList[i]));
      pSi = &gSampleInfo[translatedChannelList[i]];
      call ChannelParamsManager.setSampleOffset[translatedChannelList[i]](0);
      if(call TriggerManager.setCollectionInfo(translatedChannelList[i], 
					    pSi->samplingRate, 
					    pSi->numSamples,
					    pSi->sampleWidth,
					    call ChannelParamsManager.getHeaderSize[translatedChannelList[i]](), 
						0) == FAIL){
	return FAIL;
      }
      
      if(call TriggerManager.getOutputUOM(translatedChannelList[i], &UOM) == SUCCESS){
	call ChannelParamsManager.setOutputUOM[translatedChannelList[i]](UOM);
      }
      else{
	return FAIL;
      }
    }
    
    if(call TriggerManager.waitForTrigger(numChannels, translatedChannelList,0) == FAIL){
      trace(DBG_USR1,"FATAL ERROR:  TriggerManger.waitForTrigger failed\r\n");
      return FAIL;
    }
    
    if(call BoardManager.startDataChannels(numChannels, translatedChannelList) == FAIL){
      trace(DBG_USR1,"FATAL ERROR:  TriggerManger.startDataChannels failed\r\n");
      return FAIL;
    }    
    
    free(translatedChannelList);
    return SUCCESS;
    
  }
  
  event result_t TriggerManager.waitForTriggerDone(uint8_t numChannels, 
						   uint8_t *targetChannels, 
						   result_t status){
    
    return SUCCESS;
  }

  event result_t WriteData.writeDone(uint8_t *data, uint32_t numBytesWrote, result_t status){
    
    //writedata completed
    //trace(DBG_USR1,"WriteData.write completed successfully..returning buffer!\r\n");
    call BufferManagement.ReleaseBuffer(data);
    //we are now officially done with our sampling activity...need to clean up state...
    
    return SUCCESS;
  }

}

--- NEW FILE: channelParams.h ---
#ifndef __CHANNNEL_PARAMS_H__
#define __CHANNNEL_PARAMS_H__

//structure that records the capabilities of our various channels

typedef struct{
  uint32_t numElements;
  uint32_t elements[];
} supportedFeatureList32_t;

typedef struct{
  uint32_t commonFeature;
  uint32_t numElements;
  uint32_t elements[];
} supportedCommonFeatureList32_t;


typedef struct{
  uint32_t numElements;
  uint8_t elements[];
} supportedFeatureList8_t;


typedef struct{
  uint32_t element;
  supportedFeatureList32_t featureList;
}supportedCompoundFeatures32_t;

typedef struct{
  uint32_t numElements;
  supportedCompoundFeatures32_t elements[];
} supportedFeatureMap_t;

/*************************************
 * Structure that defines the capabilities of each sampling channel
 * 
 * @element maxSamplingRate should contain the maximum support sampling rate on this channel
 * @element supportedSensorTypes must contain a pointer to a supportedCommonFeatureList structure that contains the
 *          supported sensortypes.  The common element of each FeatureList entry should contain the physical channel that this set 
 *          of sensors is connected to
 * @element supportedSamplingRates may contain a pointer to a supportedFeatureList structure that contains the
 *          supported samplingRates.  If this pointer is NULL, it implies that any arbitrary integer sampling
 *          rate is supported by this channel
 ************************************/

typedef struct{
  uint32_t maxSamplingRate;
  const supportedCommonFeatureList32_t *supportedSensorTypes;
  const supportedFeatureList32_t *supportedSamplingRates;
  const supportedFeatureList8_t *supportedSampleWidths;
} channelParam_t;

typedef struct{
  const supportedFeatureList8_t *simulChannelGroup;
} dataChannelParam_t;



#endif // __CHANNNEL_PARAMS_H__

--- NEW FILE: ChannelParamsManager.nc ---
/**
 * @author Robbie Adler
 **/

interface ChannelParamsManager{
  
  command result_t storeParams(uint8_t channel, 
			       uint32_t samplingRate, 
			       uint32_t numSamples, 
			       uint8_t sampleWidth, 
			       bool streaming, 
			       uint32_t type, 
			       uint32_t function, 
			       TypeValItem *other);
  
  command result_t writeSampleHeader(uint8_t *buffer);
  command size_t getHeaderSize();
  command result_t setNumSamples(uint16_t numSamples);
  command result_t setSampleOffset(uint32_t numSamples);
  command result_t incrementSampleOffset(uint16_t numSamples);
  command result_t setMicroTimestamp(uint64_t timestamp);
  command result_t setWallTimestamp(uint32_t timestamp);
  command result_t setADCScale(float ADCScale);
  command result_t setADCOffset(float ADCOffset);
  command result_t setSequenceID(uint32_t ID);
  command result_t setOutputUOM(uint8_t UOM);
  
}

--- NEW FILE: ChannelParamsManagerM.nc ---
/**
 *@author Robbie Adler
 **/
#include "frameworkconfig.h"

module ChannelParamsManagerM {
  provides{
    
    interface StdControl;
    interface ChannelParamsManager[uint8_t instance];
  }
}

implementation{
  
#include "postprocessingFunctions.h"
#include "sampleHeader.h"

#define SAMPLEHEADER_UNUSED(sampleheader) (sampleheader->channelId == INVALID_CHANNEL_ID)
  
  /********
   *this module is completely dependent on the SampleHeader_t structure.  If it changes, all  
   *code-level changes should be isolated to this module
   *
   **********/
  sampleHeader_t gSampleHeaders[TOTAL_DATA_CHANNELS];
   
  result_t parseTypeValItem(sampleHeader_t *psh,TypeValItem* paramList, uint16_t whichFunction);
  result_t parsePostProcessingFunction(sampleHeader_t *sh,TypeValItem *paramList,uint32_t function);

  command result_t StdControl.init(){
    int i;

    for(i=0; i<TOTAL_DATA_CHANNELS; i++){
      //initialize our sampleInfo_t structures so that their channelId's are invalid
      gSampleHeaders[i].channelId = INVALID_CHANNEL_ID;
    }
    return SUCCESS;
  }
  
  command result_t StdControl.start(){
  
    return SUCCESS;
  }

  command result_t StdControl.stop(){
  
    return SUCCESS;
  }
  
  result_t getDataChannelFromSensorType(uint8_t channel, uint32_t type, uint8_t *phyChannel)  {
    const supportedCommonFeatureList32_t *feature;
        
    feature = channelCapabilitiesTable[channel].supportedSensorTypes;
    if((feature != NULL) && (phyChannel != NULL)){
      *phyChannel=feature->commonFeature;
      return SUCCESS;
    }
    return FAIL;
  }  
  
  result_t getParameterStorage(uint8_t channel, sampleHeader_t **ppSh, uint8_t dataChannel){
    
    if(channel >= TOTAL_CHANNELS){
      return FAIL;
    }
    if(ppSh == NULL){
      return FAIL;
    }
    
    *ppSh = &(gSampleHeaders[dataChannel]);
    if(SAMPLEHEADER_UNUSED((*ppSh))){
      //found one that is unused!!
      return SUCCESS;
    }
    else{
      if((*ppSh)->channelId == channel){
	//we've already prepared this channel set...print a warning message...but allow the prepare to be overwritten
	trace(DBG_USR1,"Warning:  GenericSampling.prepare used on existing prepared channel...overwriting config\r\n");
	return SUCCESS;
      }
    }
    trace(DBG_USR1,"FAIL:  GenericSampling.prepare has exceeded its simultaneous channel limit\r\n");
    *ppSh = NULL;
    return FAIL;
  }
  
  command size_t ChannelParamsManager.getHeaderSize[uint8_t instance](){
    return sizeof(sampleHeader_t);
  }
  
  command result_t ChannelParamsManager.storeParams[uint8_t instance](uint8_t channel,
								      uint32_t samplingRate, 
								      uint32_t numSamples, 
								      uint8_t sampleWidth, 
								      bool streaming, 
								      uint32_t type, 
								      uint32_t function, 
								      TypeValItem *other){
    sampleHeader_t *sh;
    
    if(instance >= TOTAL_DATA_CHANNELS){
      return FAIL;
    }
    
    if(getParameterStorage(channel, &sh, instance) == FAIL){
      return FAIL;
    }
    trace(DBG_USR1,"Info:  StoringParameters for data channel %d\r\n",instance);

    //we should have previous done all of our error checking..start filling in fields

    sh->channelId = channel; 		/* channelId generating the sample.  This is VirtualChannel */
    sh->samplingRate = samplingRate;	/* Rate at which samples are taken */
    sh->totalSamples = numSamples; 	        /* Time: numSamples, FFT on mote: numOfLines */
    sh->sampleWidth = sampleWidth;        /* bit width of sample data used for parsing sample body */
    //sh->samplePadding = need to fill out based on a table of values;
    sh->sensorType = type;	        /* sensorType */
    sh->function = function;		/* post processing function applied to data. */  
        
    //fill out the misc fields of the sampleheader
    if(parseTypeValItem(sh,other,FI_FUNCTION_BOARD) != SUCCESS){
      return FAIL;
    }
    if(parsePostProcessingFunction(sh,other,function) != SUCCESS){
      return FAIL;
    }
        
    return SUCCESS;
    
  }
    
  //sadly, this module needs to be aware of the postProcessingFunction because some parts of our sampleHeader are
  //determined from the postProcessingFunction.  Since this module is responsible for maintaining the sampleHeader,
  //it is responsible for parsing the postProcessingFunction and the TypeValItem list to pull out fields required
  //by the sampleHeader
  result_t parsePostProcessingFunction(sampleHeader_t *sh, TypeValItem *paramList,uint32_t function){
    sh->gSEFilterType = 0; //initialize
        
    switch(GET_SPECTRUM_CALC(function)){
    case SPECTRUM_NONE:
      break;
    case SPECTRUM_FFT:
          //get FFT parameters...this will fill in NumOutputPoints
      parseTypeValItem(sh,paramList,FI_FUNCTION_FFT);
      parseTypeValItem(sh,paramList,FI_FUNCTION_AVG);
      break;
    case SPECTRUM_GSE:
      parseTypeValItem(sh,paramList,FI_FUNCTION_GSE);
      //this will fil in the number of averages
      parseTypeValItem(sh,paramList,FI_FUNCTION_AVG);
      break;
    default:
      trace(DBG_USR1,"WARNING:  GenericSampling.prepare postprocessing function contains invalid SpectrumCalc %d\r\n",
	    GET_SPECTRUM_CALC(function));
    } 
    return SUCCESS;
  }
  
  result_t parseTypeValItem(sampleHeader_t *sh,TypeValItem* paramList, uint16_t whichFunction){
    
    int i;

    if(sh==NULL){
      trace(DBG_USR1,"ASSERT:  GenericSampling.parseTypeValItem passed NULL SamplingHeader pointer\r\n");
      return FAIL;
    }
    
    for(i=0; i<paramList->count;i++){
      switch(paramList->functionInfo[i].function){
      case FI_FUNCTION_BOARD:
	if(whichFunction == FI_FUNCTION_BOARD){
	  switch(paramList->functionInfo[i].paramname) {
	  case FIF_BOARD_LOGICALNODEID:	/* Intel logical nodeId, mote generating sample*/
	    sh->logicalNodeId = paramList->functionInfo[i].paramval;
	    break;
	  case FIF_BOARD_QUERYGROUPID:  	/* UniqueId of the query group being satisfied by this sample record */
	    sh->queryGroupId=paramList->functionInfo[i].paramval;
	    break;	    
	  case FIF_BOARD_ACQUISITIONNUM:/* Ordinal # of the acquisition for the query: e.g.1st, 2nd, 3rd */	
	    sh->acquisitionNum=paramList->functionInfo[i].paramval;	
	    break;	    
	  case FIF_BOARD_ACQUISITIONCOUNT:	/* Total # of acquisitions needed to satisfy the query group */
	    sh->acquisitionCount=paramList->functionInfo[i].paramval;
	    break;	
	  case FIF_BOARD_DESIREDUOM:/* Unit of Measure the user wants. See EngineeringUnits.h */
	    sh->desiredUOM=paramList->functionInfo[i].paramval; 	        
	    break;	
	  case FIF_BOARD_ENGINEERINGUOM:/* Native UOM the sensor takes its readings in. See EngineeringUnits.h */
	    sh->engineeringUOM=paramList->functionInfo[i].paramval;	
	    break;	
	  case FIF_BOARD_OUTPUTUOM:/* Unit of Measure of the data on this sample record. See EngineeringUnits.h   */
	    //sh->outputUOM=paramList->functionInfo[i].paramval; 		
	    break;
	  case FIF_BOARD_CONVERSIONVAL:/* Conversion of volts/EU to convert voltage reading the EU for the sensor */
	    memcpy(&(sh->conversionVal),&(paramList->functionInfo[i].paramval),4);
	    break;	
	  case FIF_BOARD_SENSORZERO:/* Zero stop of the sensor.  */
	    memcpy(&(sh->sensorZero),&(paramList->functionInfo[i].paramval),4);
	    break;
	  default:
	  }
	}
	break;
      case FI_FUNCTION_FFT:
	if(whichFunction == FI_FUNCTION_FFT){
	  switch(paramList->functionInfo[i].paramname) {
	  case FIF_FFT_NUMOUTPUTSAMPLES:
	    sh->numSamples = paramList->functionInfo[i].paramval;
	    trace(DBG_USR1,"FFT will have %d outputpoints\r\n",sh->numSamples);
	    break;
	  default:
	  }
	}
	break;
      case FI_FUNCTION_GSE:
	if(whichFunction == FI_FUNCTION_GSE){
	  switch(paramList->functionInfo[i].paramname) {
	  case FIF_GSE_FILTERFREQ:
	    trace(DBG_USR1,"WARNING:  GenericSampling.prepare unable to utilize filterfreq %d for gSE measurement\r\n",
		  paramList->functionInfo[i].paramval);
	    sh->gSEFilterType = paramList->functionInfo[i].paramval;
	    break;
	  default:
	  }
	}
	break;
      case FI_FUNCTION_AVG:
	break;
      default:
	trace(DBG_USR1,"WARNING:  GenericSampling.prepare passed unknown TypeValItem.functionInfo[i].function");
      }
    }
    return SUCCESS;
  }

  command result_t ChannelParamsManager.writeSampleHeader[uint8_t instance](uint8_t *buffer){
    
    memcpy(buffer,&gSampleHeaders[instance],sizeof(sampleHeader_t));
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setNumSamples[uint8_t instance](uint16_t numSamples){
    
    gSampleHeaders[instance].numSamples= numSamples;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.incrementSampleOffset[uint8_t instance](uint16_t numSamples){
    
    gSampleHeaders[instance].sampleOffset += numSamples;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setSampleOffset[uint8_t instance](uint32_t numSamples){
    
    gSampleHeaders[instance].sampleOffset = numSamples;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setMicroTimestamp[uint8_t instance](uint64_t timeStamp){
    
    gSampleHeaders[instance].microSecTimeStamp = timeStamp;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setWallTimestamp[uint8_t instance](uint32_t timeStamp){
    
    gSampleHeaders[instance].wallClockTimeStamp = timeStamp;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setADCScale[uint8_t instance](float ADCScale){
    
    gSampleHeaders[instance].ADCScale = ADCScale;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setADCOffset[uint8_t instance](float ADCOffset){
    
    gSampleHeaders[instance].ADCOffset = ADCOffset;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setSequenceID[uint8_t instance](uint32_t ID){
    
    gSampleHeaders[instance].sequenceID = ID;
    return SUCCESS;
  }

  command result_t ChannelParamsManager.setOutputUOM[uint8_t instance](uint8_t UOM){
    
    gSampleHeaders[instance].outputUOM = UOM;
    return SUCCESS;
  }

}

--- NEW FILE: DSPManager.nc ---
/**
 * @author Robbie Adler
 **/

interface DSPManager{
  
  command result_t initPostProcessing(uint32_t samplingRate, 
				      uint32_t numSamples, 
				      uint8_t sampleWidth, 
				      bool streaming, 
				      uint32_t warmup, 
				      uint32_t type, 
				      uint32_t function, 
				      TypeValItem *other);

  command result_t isSupportedFunction(uint32_t function);
  
  /*
   *return the amount of storage required for the required post-processing routing to function properly
   *
   *
   */
  command result_t getDataStorageSize(uint32_t *requestedSize, uint32_t *requiredSize, uint32_t *numRecords);
  
}

--- NEW FILE: frameworkconfig.h ---
#ifndef __FRAMEWORK_CONFIG_H__
#define __FRAMEWORK_CONFIG_H__


#include "config.h"

#define LAST_CHANNEL (TOTAL_CHANNELS -1)
#define INVALID_CHANNEL_ID (0xFF)

#endif // __FRAMEWORK_CONFIG_H__

--- NEW FILE: postprocessingFunctions.h ---
#ifndef __POSTPROCESSINGFUNCTION_H__
#define __POSTPROCESSINGFUNCTION_H__

//constants in this file are based on the Collection Variables.xls generated by Mick Flanigan.  Otherwise, the assignments are arbitrary

//NONE is just a placeholder

#define NONE (0) 

#define SPECTRUM_CALC(_x) ((_x & 0x3)<<1)
#define GET_SPECTRUM_CALC(_x) ((_x >>1) & 0x3)
#define SPECTRUM_NONE    (0)
#define SPECTRUM_FFT     (1)
#define SPECTRUM_GSE     (2)

#define MAG_CALC         (1 << 3)
#define GET_MAG_CALC(_x) ((_x>>3) & 0x1)

#define AVG_CALC(_x) ((_x & 0x7)<<4)
#define GET_AVG_CALC(_x) ((_x >>4) & 0x7)
#define AVG_NONE         (0)
#define AVG_LINEAR       (1)
#define AVG_TIMESYNC     (2)
#define AVG_EXPONENTIAL  (3)
#define AVG_PEAKHOLD     (4)


#define WINDOW_CALC(_x)     ((_x & 0x7)<<7)
#define GET_WINDOW_CALC(_x) ((_x >>7) & 0x7)
#define WIN_NONE         (0)
#define WIN_RECTANGULAR  (1)
#define WIN_HANNING      (2)
#define WIN_FLATTOP      (3)
#define WIN_HAMMING      (4)
#define WIN_KAISERBESSEL (5)
#define WIN_COS4         (6)

#define SIGNAL_DETECTION_CALC(_x) ((_x & 0x3) <<10)
#define GET_SIGNAL_DETECTION_CALC(_x) ((_x >> 10) & 0x3)
#define SIGNAL_DETECTION_INVALID (0) //note, SIGNAL_DETECTION MUST be a value!
#define SIGNAL_DETECTION_RMS  (1)
#define SIGNAL_DETECTION_PEAK (2)
#define SIGNAL_DETECTION_PKPK (3)


#define TACHOMETER_CALC(_x)         ((_x & 0x3) <<12)
#define GET_TACHOMETER_CALC(_x)     ((_x >> 12) & 0x3)

#define TACHOMETER_NONE      (0)
#define TACHOMETER_RPM       (1)
#define TACHOMETER_PHASE     (2)


//total number of bits currently used = 1 + 2 + 1 + 3 + 3 + 2 + 2 = 14 bits
#endif

--- NEW FILE: SensorboardC.nc ---
/**
*
*@author Robbie Adler
*
**/

configuration SensorboardC{
    provides {
      interface StdControl;
      interface GenericSampling;
    }
    uses{
      interface BufferManagement;
      interface WriteData;
      interface SensorData[uint8_t dataChannel];
      interface DSPManager[uint8_t dataChannel];
      interface BoardManager;
    }
}

implementation {
#include "frameworkconfig.h"

  components SensorboardM,
    Main,
    PXA27XWallClockM,
    TimerC,
    TriggerManagerM,
    ChannelManagerM,
    BufferManagementDispatchM,
#ifdef BLUSH_TRIGGER
    BluSHC,
#endif
    ChannelParamsManagerM;
    
    
  StdControl = SensorboardM.StdControl;
  GenericSampling = SensorboardM;
  
  SensorboardM.DependentControl -> ChannelManagerM.StdControl;
  SensorboardM.DependentControl -> ChannelParamsManagerM.StdControl;
  SensorboardM.DependentControl -> TriggerManagerM.StdControl;

  SensorboardM.ChannelManager -> ChannelManagerM;
  ChannelManagerM.TriggerManager -> TriggerManagerM;  
  ChannelManagerM.ChannelParamsManager -> ChannelParamsManagerM;
  
  
  BoardManager  = ChannelManagerM.BoardManager;
  DSPManager = ChannelManagerM.DSPManager;
  SensorData = TriggerManagerM.SensorData;
  BufferManagement =  BufferManagementDispatchM.OutsideBufferManagement;
  TriggerManagerM.BufferManagement-> BufferManagementDispatchM.InsideBufferManagement;
  ChannelManagerM.BufferManagement-> BufferManagementDispatchM.InsideBufferManagement;
  WriteData = ChannelManagerM;
      
  ChannelManagerM.ADCWarmupTimer -> TimerC.Timer[unique("Timer")];
  SensorboardM.AcquisitionTimeout -> TimerC.Timer[unique("Timer")];
  
  ChannelManagerM.WallClock -> PXA27XWallClockM;
  Main.StdControl -> PXA27XWallClockM.StdControl;
  
  //-----------
  //BluSH commands
  
#ifdef BLUSH_TRIGGER
  BluSHC.BluSH_AppI[unique("BluSH")] -> TriggerManagerM.ForceTrigger;
#endif
}

--- NEW FILE: SensorboardM.nc ---
includes downsample;
includes sensorboard;
includes processVibration;
includes gSE;
includes gSEIIR;

module SensorboardM{
  provides {
    interface StdControl;
    interface GenericSampling;
  }
  uses {
    interface SSP;
    interface Timer as AcquisitionTimeout;
    interface ChannelManager;
    
    interface StdControl as DependentControl;
  }
}
implementation {

#include "frameworkconfig.h"
#include "paramtask.h"

  result_t acquisitionDone(float scale);
  result_t triggerADCAcquisition();
  result_t doADCAcquisition();
  result_t cleanupSamplingState();
  result_t cleanupTimers();
 
  // paramaterized tasks
  
  void postPrepareDone(uint32_t arg);
  DEFINE_PARAMTASK(postPrepareDone);

  void postPrepareDoneFail(uint32_t arg);
  DEFINE_PARAMTASK(postPrepareDoneFail);

  void printList(char *header, uint8_t numItems, uint8_t* list) __attribute__ ((C,spontaneous));
  
  void printList(char *header, uint8_t numItems, uint8_t* list){
    char *buffer, tempBuf[8];
    buffer = malloc(256);
    
    if(buffer){
      int i, currentPos, currentCount;
      if(strlen(header) < 256){
	memcpy(buffer, header, strlen(header));
      }
      else{
	return;
      }
      currentPos = strlen(header);
      for(i=0; i<numItems; i++){
	currentCount = snprintf(tempBuf,8,"%d ",list[i]);
	if((currentCount > 0) && ((currentCount + currentPos) < 255)){
	  memcpy(buffer+currentPos,tempBuf, currentCount);
	  currentPos += currentCount;
	}
      }
      buffer[currentPos] = 0;
      trace(DBG_USR1,"%s\r\n",buffer);
      free(buffer);
    }
  }
  

#if 0   
  uint8_t *getNextBuffer(){
    int i;
    uint8_t *ret = NULL;
    atomic{
      for(i=0;i<NUMBUFFERS; i++){
	if(tempBuffers[i].inuse == FALSE){
	  tempBuffers[i].inuse = TRUE;
	  ret = (uint8_t *)tempBuffers[i].buf;
	  break;
	}
      }
    }
    return ret;
  }

  void returnBuffer(short *buf){
    int i;
    atomic{
      for(i=0;i<NUMBUFFERS; i++){
	if(tempBuffers[i].buf == buf){
	  tempBuffers[i].inuse = FALSE;
	}
      }
    }
  }
  
  void initBuffer(){
    int i;
    atomic{
      for(i=0;i<NUMBUFFERS; i++){
	tempBuffers[i].inuse = FALSE;
      }
    }
  }
#endif
    
  command result_t StdControl.init(){
      
    //    int i;

    trace(DBG_USR1,"\r\nInitializing %s\r\n", mySensorboardName);

#if 0
    initBuffer();
    atomic{
      //init global state that needs to be init'd
      gTotalTachTime=0;
      gTotalTachSamples=0;
      gLastTachValue=0;
      gSamplingInProgress = FALSE;
      for(i=0;i<MAX_SIMUL_CHANNELS;i++){
	gSampleInfo[i].sampleHeader.channelId = INVALID_CHANNEL_ID;
      }
      for(i=0;i<TOTAL_CHANNELS;i++){
	call GenericSampling.ClearTrigger(i);
      }
      
    }

    //SSP must be told whether it's Master or Slave to SCLK or SFRM and then
    //it can be inited.  All other parameters must be set after init is
    // called
    
    //read in our calibration values
#if EEPROM_PRESENT
    //read gVREFCal and gACCELCal out of the EEPROM
    //    call EEPROM.read(  );
    gVREFCal = 2.5;
    gACCELCal = 10.025;
#else
    gVREFCal = 2.5;
    gACCELCal = 10.025;
#endif
    
    //currently, this means that the board is not present
      
    gADCOffsetInt =0;
    gADCOffset = 0;
    gADCScale = 7.8920e-5;
    gADCAccelScale = 1.9e-4;
    gADCAccelDCScale = 5.024;
#endif

    call DependentControl.init();
    
    return SUCCESS;
  }
  
  command result_t StdControl.start(){
    
    call DependentControl.start();
    return SUCCESS;
  };

  command result_t StdControl.stop(){
    
    call DependentControl.stop();
    return SUCCESS;
  };
  
  event result_t AcquisitionTimeout.fired(){
    
    //we've timed out....
#if 0
    int i;
    bool samplingInProgress;
    
    atomic{
      samplingInProgress = gSamplingInProgress;
    }
    if(samplingInProgress == TRUE){
      
      //stop timers ASAP!!!
      cleanupTimers();
      
      trace(DBG_USR1,"ERROR:  GenericSampling Acquisition Timeout\r\n");
      
      //if we're still sampling....need to cleanup and notify
      for(i=0; i<MAX_SIMUL_CHANNELS; i++){
	if(gSampleInfo[i].sampleHeader.channelId!= INVALID_CHANNEL_ID){
	  //write the wrapperHeader and the sampleheader for this acquisitions
	  WRITEHEADER(gSampleInfo[i].dataBuffer,0,1);
	  WRITEHEADER(gSampleInfo[i].dataBuffer,4,WRAPPERHEADER_FIRSTOFFSET);
	  //set numSamples to 0 so that the sampleHeader is consistent with sampleBody.
	  gSampleInfo[i].sampleHeader.numSamples = 0;
	  memcpy(gSampleInfo[i].dataBuffer+WRAPPERHEADER_FIRSTOFFSET,
		 &(gSampleInfo[i].sampleHeader),
		 sizeof(sampleHeader_t));
	  	  
	  //do not support partial acquisitions because we have extremely
	  //limited insight into where we are at in the acquisition
	  
	  /*call WriteData.write(0, 
			       gSampleInfo[i].dataBuffer, 
			       sizeof(sampleHeader_t)+WRAPPERHEADER_FIRSTOFFSET);	
	  */
	  signal GenericSampling.samplingDone(gSampleInfo[i].sampleHeader.channelId,FAIL,0);  
	}
      }
      
      cleanupSamplingState();
      
    }
#endif
    return SUCCESS;
  }
  
  result_t cleanupTimers(){
    //this should work regardless of whether we have a timeout or not
    call AcquisitionTimeout.stop();
    return SUCCESS;
  }
  
  result_t cleanupSamplingState(){
    //sampling has now been officially concluded...need to clean up state
    int i;
    
#if 0
    atomic{
      gSamplingInProgress=FALSE;
      gGse=FALSE;
      gGseCal=FALSE;
    }
    
    cleanupTimers();
    for(i=0; i<MAX_SIMUL_CHANNELS; i++){
      gSampleInfo[i].sampleHeader.channelId = INVALID_CHANNEL_ID;
    } 
      
    //turn off the board...select channel 0
#endif
    return SUCCESS;
  }

  
  void postPrepareDone(uint32_t arg){
    uint8_t channelID = (uint32_t)arg;
    //TODO:  do some checking here based on the arguments
    signal GenericSampling.prepareDone(channelID,SUCCESS);
  }

  void postPrepareDoneFail(uint32_t arg){
    uint8_t channelID = (uint32_t)arg;
    //TODO:  do some checking here based on the arguments
    signal GenericSampling.prepareDone(channelID,FAIL);
  }
  

  /**
   * Prepare to peform sampling. 
   * @param channel The sensor channel id
   * @param samplingRate The sampling rate specified in Hz
   * @param numSamples The number of samples to collect
   * @param sampleWidth The number of bits per sample 
   * @param streaming TRUE for streaming (sampling will only
   *   end when stop is called.
   * @param warmup The sensor warmup time in microseconds, this will imply
   *   that once the start function is called, the sensor will turn on and 
   *   the samples will be dropped for at least warmup microseconds
   * @param type The sensor type to be sampled.  Some boards might expose 
   *   multiple type sensors on one channel.  The value is an enum that is 
   *   sensor board specific
   * @param function The sensor driver can support some form of post 
   *   processing capability (e.g. average, FFT, etc).  This supported values
   *   in this field will be sensor board specfic. Note that the meaning 
   *   of the numSamples parameter will be dependent on the post processing 
   *   function.
   * @param other this is an array of type value pairs that will capture
   *   board specific parameters that don't need to be applied to all boards
   *   The last item in the array will have a type 0 to indidate end of list
   * @return If the result is SUCCESS, <code>ready</code> will be signaled
   *   If the result is FAIL, no sampling will happen.
   */  

  command result_t GenericSampling.prepare(uint8_t channel, 
					     uint32_t samplingRate, 
					     uint32_t numSamples, 
					     uint8_t sampleWidth, 
					     bool streaming, 
					     uint32_t warmup, 
					     uint32_t type, 
					     uint32_t function, 
					     TypeValItem *other){
    
    /***************
cases that need to be watched out for:
    
1.) preparing the same channel multiple times....error or override?
2.) We currently allow at most 2 simul channels of which 1 can be a data channel and 1 can be a tach
3.) Must check that we have at most 1 data channel
4.) Must check that we have at most 1 tach channel

    *************/
    if(channel > LAST_CHANNEL){
      trace(DBG_USR1,"FAIL:  GenericSampling.prepare called with invalid channelId\r\n");
      return FAIL;
    }
    
    if(call ChannelManager.prepareChannel(channel, 
					  samplingRate, 
					  numSamples, 
					  sampleWidth,
					  streaming, 
					  warmup, 
					  type, 
					  function, 
					  other) == SUCCESS){
      
      POST_PARAMTASK(postPrepareDone,channel);
      return SUCCESS;
    }
    else{
      return FAIL;
    }
  }
  
  
  /**
   * Prepare a trigger channel
   * @param channel The sensor channel id
   * @param samplingRate The sampling rate specified in Hz
   * @param numSamples The number of samples to collect
   * @param sampleWidth The number of bits per sample 
   * @param streaming TRUE for streaming (sampling will only
   *   end when stop is called.
   * @param warmup The sensor warmup time in microseconds, this will imply
   *   that once the start function is called, the sensor will turn on and 
   *   the samples will be dropped for at least warmup microseconds
   * @param type The sensor type to be sampled.  Some boards might expose 
   *   multiple type sensors on one channel.  The value is an enum that is 
   *   sensor board specific
   * @param function The sensor driver can support some form of post 
   *   processing capability (e.g. average, FFT, etc).  This supported values
   *   in this field will be sensor board specfic. Note that the meaning 
   *   of the numSamples parameter will be dependent on the post processing 
   *   function.
   * @param other this is an array of type value pairs that will capture
   *   board specific parameters that don't need to be applied to all boards
   *   The last item in the array will have a type 0 to indidate end of list
   * @param storeData if TRUE the trigger channel is sampled like a regular
   *   channel and the data is stored in the same way.  If FALSE, the trigger
   *   channel data is just used for the purpose of triggering another channel
   * @return If the result is SUCCESS, <code>ready</code> will be signaled
   *   If the result is FAIL, no sampling will happen.
   */
  command result_t GenericSampling.prepareTrigger(uint8_t channel, 
						  uint32_t samplingRate, 
						  uint32_t numSamples, 
						  uint8_t sampleWidth, 
						  bool streaming, 
						  uint32_t warmup, 
						  uint32_t type, 
						  uint32_t function, 
						  TypeValItem *other, 
						  bool storeData){
    
    trace(DBG_USR1,"ERROR:  GenericSampling.prepareTrigger called.  This should not happen!\r\n");
    return FAIL;
  }


  /**
   * Report if sampling can be started
   * @param channel The sensor channel id
   * @param ok SUCCESS if sampling can be started by calling 
   *   <code>start</code>, FAIL otherwise
   * @return Ignored
   */
  default event result_t GenericSampling.prepareDone(uint8_t channel, result_t ok){
    return SUCCESS;
  }
     
  /** 
   * Start sampling requested by previous <code>prepare</code>
   *   If multiple channels are being passed in a list, then the sensor
   *   board will start all the channel simultaneously if supported.  However
   *   if individual start calls are executed, these channels are assumed to
   *   be independent. 
   *   If a trigger is setup and linked to a target channel, when the target 
   *   channel is started, the trigger channel will be started instead and 
   *   the target channel will only be started if the trigger is invoked.
   * @param numChannels The number of channels listed in the channelList
   * @param channelList An array of channel id values to be started
   * @param timeout if the complete collection is not done within timeout
   *   msec, the board will stop the capture and signal the samplingDone
   *   with a timeout error condition
   * @return SUCCESS if sampling started (<code>done</code> will be signaled
   *   when it complates), FAIL if it didn't.
   */
  command result_t GenericSampling.start(uint8_t numChannels, 
					 uint8_t *channelList, 
					 uint32_t timeout){
    
    //need to figure out whether we have info about the channels that are being requested
    //gSampleHeaders contains the information about the channels that we're currently aware of
    //
    
    //start channels will actuall start the channels and do some error checking.
    //in this module's model, channels will get started, warmed up, and then tested for trigger
    //conditions before getting written
    printList("GenericSampling.start() called with channel #'s: ", numChannels, channelList);
    
    if(call ChannelManager.startChannels(numChannels, channelList) == FAIL){
      return FAIL;
    }
    
    //start the overall acquisition timeout timer
    if(timeout){
      call AcquisitionTimeout.start(TIMER_ONE_SHOT,timeout);
    }
    
    call ChannelManager.warmupChannels(numChannels, channelList);
    return SUCCESS;
  }
  
  #define MAX_TRIGGER_TIMEOUT (1000)

  event result_t ChannelManager.warmupChannelsDone(uint8_t numChannels, 
						   uint8_t *channelList){
    
    trace(DBG_USR1,"Channel warmup completed\r\n");
    call ChannelManager.waitForData(numChannels, channelList);
    return SUCCESS;
  }
  
  /** 
   * Stop sampling started by earlier <code>start</code>
   * @param numChannels The number of channels listed in the channelList
   * @param channelList An array of channel id values to be started
   * @return SUCCESS if sampling can be stopped (<code>done</code> will 
   *   be signaled shortly), FAIL if it can't.
   */
  command result_t GenericSampling.stop(uint8_t numChannels, 
					uint8_t *channelList){

    return FAIL;
  }

  /**
   * Report sampling completion
   * @param channel The sensor channel id
   * @param status SUCCESS if sampling was succesful, FAIL if it failed. Failure
   *   may be due to the sampling interval being too short or to a data
   *   logging poblem.
   * @param numSamples Number of samples of data collected
   * @return Ignored
   */
  default event result_t GenericSampling.samplingDone(uint8_t channel, 
						      result_t status, 
						      uint32_t numSamples){

    return SUCCESS;
  }

  /**
   * This function supports triggering channel sampling from one or many
   *   channels based on the behavior of a trigger channel.
   * 
   * @param boolOp Boolean operation to combine different triggers.  
   *   Supported enum is board specific
   * @param triggerFunction The supported functions are board specific
   *   examples are rising edge, falling edge, max, min, average
   * @param triggerValue The tigger function evaluates the function and 
   *   compares to the value to evaulate the trigger
   * @param triggerChannel the channel id of the trigger
   * @param targetChannel the channel id of the triggered channel 
   * 
   * @return SUCCESS indicates the trigger was setup
   **/
    

  command result_t GenericSampling.AddTrigger(uint8_t boolOp, 
					      uint32_t triggerFunction,
					      float triggerValue, 
					      uint32_t triggerWindowSamples,
					      uint8_t triggerChannel,
					      uint8_t targetChannel){

    return call ChannelManager.addTrigger(boolOp, 
					  triggerFunction, 
					  triggerValue, 
					  triggerWindowSamples,
					  triggerChannel, 
					  targetChannel);
  }

  /**
   * This function clears the preset trigger functionality
   * 
   * @param targetChannel the channel id of the target channel
   */
  command void GenericSampling.ClearTrigger(uint8_t targetChannel){
    
    return call ChannelManager.clearTrigger(targetChannel);
  }

  /**
   * Report that a target channel has been triggered (trigger invoked)
   * @param channel The target channel id 
   * @return Ignored
   */
  default event result_t GenericSampling.TargetChannelTriggered(uint8_t channel){
    return SUCCESS;
  }

  /**
   * Retrieve information about a supported board feature
   * @param feature supported list of features to be interogated is board
   *   specific.  This will be an enumerated list that is defined across
   *   sensor boards, and each sensor board will support a subset of the
   *   range.  There is a special feature (type 0), which will return the
   *   list of supported features by this board rather than the infromation
   *   about a specific feature.
   * @param options This is an array options relating to the passed feature
   *   The driver will allocate the array.  The caller shouldn't modify 
   *   the contents of the array, nor can it assume that the array will
   *   persist after the function returns.
   * @return The function returns the number of entries in the array
   *   0 means that the feature is not supported
   */
  command uint32_t GenericSampling.GetSupportedFeature(uint32_t feature, 
						       uint32_t *options){
    return 0;
  }

  /**
   * Returns the actual data width of the sample returned by the board
   *   given a desired sample width.  e.g. the caller can request 14 bit
   *   samples and the board can pack it into 16 bit samples. It also
   *   indicates the endianess of the samples
   * @param sampleWidth desired number of bits per sample
   * @param dataWidth driver will return the data width in bits used to
   *   pack these samples
   * @param littleEndian driver will return the endianess of the data.  
   *   FALSE for little endian, FALSE for big endian
   *   
   */ 

  command void GenericSampling.getSampleInfo(uint8_t sampleWidth, 
					     uint8_t *dataWidth, 
					     bool *littleEndian){

    return;
  }

  /**********************
WriteData interface
  *******************/
  

  event result_t ChannelManager.DataReady(uint8_t channel, uint16_t numSamples, bool done){
    if(done){
      return signal GenericSampling.samplingDone(channel, SUCCESS, numSamples); 
    }
    return SUCCESS;
  }
}

--- NEW FILE: SensorData.nc ---

/***
 *SensorData interface the describes a data being returned in Task context from a sensor board
 *
 *
 *@author Robbie Adler
 ***/

interface SensorData{
  
   /**
   * getOutputUOM
   *
   * Function to get the outputUOM for the data returned by a call to SensorData.getSensorData under the current configuration
   * @param uint8_t* UOM.  Pointer to a uint8_t where the UOM will be returned
   *
   * @returns FAIL if there is not enough information to return a valid UOM, SUCCESS otherwise
   **/
  command result_t getOutputUOM(uint8_t *UOM);
  
  /**
   *
   * setSensorType 
   *
   * Function to allow the sensortype that should be associated with the current collection to be set
   *
   *@return FAIL if this is not called on a valid DataChannel, SUCCES otherwise.
   **/

  command result_t setSensorType(uint32_t sensorType);
  
  /**
   *
   * setSamplingRate 
   *
   * Function to allow the sampling rate associated with the current collection to be set
   *
   * @param requestedSamplingRate is the rate requested of the data providing component
   * @param actualSamplingRate is the rate that the data providing component will actually return for the given request
   *
   *@return FAIL if this is not called on a valid DataChannel, SUCCESS otherwise.
   **/
  command result_t setSamplingRate(uint32_t requestedSamplingRate, uint32_t *actualSamplingRate);

  /**
   *
   * setSampleWidth 
   *
   * Function to allow the sampling width associated with the current collection to be set
   *
   * @param requestedSampleWidth is the sample width requested in bytes
   * 
   *@return FAIL if this is not called on a valid DataChannel or if the requestedSampleWidth is not supported, SUCCESS otherwise.
   **/
  command result_t setSampleWidth(uint8_t requestedSampleWidth);
  

  command result_t getSensorData(uint8_t *buffer, uint32_t numSamples);
  
  /**
   *
   *buffer = pointer to buffer that returns data
   *numSamples = number of samples requested
   *timestamp = timestap that this buffer was received at
   *
   *@return pointer to new buffer to fill with samples, or NULL if done
   **/

  event uint8_t *getSensorDataDone(uint8_t *buffer, uint32_t numSamples, uint64_t timestamp, float ADCScale, float ADCOffset);
}

--- NEW FILE: SensorDataInfo.nc ---

/***
 *SensorDataInfo interface that allows for a sideband channel of setting and getting parameters/information about the current collection
 *
 *
 *@author Robbie Adler
 ***/

interface SensorDataInfo{
  
  /**
   * getOutputUOM
   *
   * Function to get the outputUOM for the data returned by a call to SensorData.getSensorData under the current configuration
   * @param uint8_t* UOM.  Pointer to a uint8_t where the UOM will be returned
   *
   * @returns FAIL if there is not enough information to return a valid UOM, SUCCESS otherwise
   **/
  command result_t getOutputUOM(uint8_t *UOM);
  
  /**
   *
   * setSensorType 
   *
   * Function to allow the sensortype that should be associated with the current collection to be set
   *
   *@return FAIL if this is not called on a valid DataChannel, SUCCES otherwise.
   **/

  command result_t setSensorType(uint32_t sensorType);
}

--- NEW FILE: sensorTypes.h ---
/**
 *@author Robbie Adler
 **/

#ifndef __SENSOR_TYPES_H__
#define __SENSOR_TYPES_H__

//#define CREATE_MASK(numberofbits, shift) (((1<<(numberofbits)) - 1)<<(shift))
#define CREATE_MASK(numberofbits, shift) (((1<<(numberofbits)) - 1))

#define SENSOR_TYPE_BITS (1)
#define SENSOR_TYPE_POS (0)
#define SENSOR_TYPE_MASK CREATE_MASK(SENSOR_TYPE_BITS, SENSOR_TYPE_POS)
#define SET_SENSOR_TYPE(type) ((type & SENSOR_TYPE_MASK) << SENSOR_TYPE_POS)
#define GET_SENSOR_TYPE(val)  ((val >> SENSOR_TYPE_POS) & SENSOR_TYPE_MASK)
enum {
  SENSOR_ANALOG = 0,
  SENSOR_DIGITAL = 1
};

#define SENSOR_ANALOG_COUPLING_BITS (2)
#define SENSOR_ANALOG_COUPLING_POS (SENSOR_TYPE_POS + SENSOR_TYPE_BITS)
#define SENSOR_ANALOG_COUPLING_MASK CREATE_MASK(SENSOR_ANALOG_COUPLING_BITS, SENSOR_ANALOG_COUPLING_POS)
#define SET_ANALOG_COUPLING(type) ((type & SENSOR_ANALOG_COUPLING_MASK) << SENSOR_ANALOG_COUPLING_POS)
#define GET_ANALOG_COUPLING(val)  ((val >> SENSOR_ANALOG_COUPLING_POS) & SENSOR_ANALOG_COUPLING_MASK)
enum {
  SENSOR_ANALOG_ACCOUPLED = 1,
  SENSOR_ANALOG_DCCOUPLED = 2
};

#define SENSOR_ANALOG_PHYSICAL_TYPE_BITS (2)
#define SENSOR_ANALOG_PHYSICAL_TYPE_POS (SENSOR_ANALOG_COUPLING_POS + SENSOR_ANALOG_COUPLING_BITS)
#define SENSOR_ANALOG_PHYSICAL_TYPE_MASK CREATE_MASK(SENSOR_ANALOG_PHYSICAL_TYPE_BITS, SENSOR_ANALOG_PHYSICAL_TYPE_POS)
#define SET_ANALOG_PHYSICAL_TYPE(type) ((type & SENSOR_ANALOG_PHYSICAL_TYPE_MASK) << SENSOR_ANALOG_PHYSICAL_TYPE_POS)
#define GET_ANALOG_PHYSICAL_TYPE(val)  ((val >> SENSOR_ANALOG_PHYSICAL_TYPE_POS) & SENSOR_ANALOG_PHYSICAL_TYPE_MASK)
enum { 
  SENSOR_ANALOG_VOLTAGE = 1,
  SENSOR_ANALOG_CURRENT = 2
};

#define SENSOR_ANALOG_INPUT_TYPE_BITS (2)
#define SENSOR_ANALOG_INPUT_TYPE_POS (SENSOR_ANALOG_PHYSICAL_TYPE_POS + SENSOR_ANALOG_PHYSICAL_TYPE_BITS)
#define SENSOR_ANALOG_INPUT_TYPE_MASK CREATE_MASK(SENSOR_ANALOG_INPUT_TYPE_BITS, SENSOR_ANALOG_INPUT_TYPE_POS)
#define SET_ANALOG_INPUT_TYPE(type) ((type & SENSOR_ANALOG_INPUT_TYPE_MASK) << SENSOR_ANALOG_INPUT_TYPE_POS)
#define GET_ANALOG_INPUT_TYPE(val)  ((val >> SENSOR_ANALOG_INPUT_TYPE_POS) & SENSOR_ANALOG_INPUT_TYPE_MASK)
enum { 
  SENSOR_ANALOG_SINGLEENDED = 1,
  SENSOR_ANALOG_DIFFERENTIAL = 2
};

#define SENSOR_ANALOG_INPUT_RANGE_BITS (4)
#define SENSOR_ANALOG_INPUT_RANGE_POS (SENSOR_ANALOG_INPUT_TYPE_POS + SENSOR_ANALOG_INPUT_TYPE_BITS)
#define SENSOR_ANALOG_INPUT_RANGE_MASK CREATE_MASK(SENSOR_ANALOG_INPUT_RANGE_BITS, SENSOR_ANALOG_INPUT_RANGE_POS)
#define SET_ANALOG_INPUT_RANGE(type) ((type & SENSOR_ANALOG_INPUT_RANGE_MASK) << SENSOR_ANALOG_INPUT_RANGE_POS)
#define GET_ANALOG_INPUT_RANGE(val)  ((val >> SENSOR_ANALOG_INPUT_RANGE_POS) & SENSOR_ANALOG_INPUT_RANGE_MASK)
enum {
  SENSOR_ANALOG_RANGE_PLUS5V = 1,
  SENSOR_ANALOG_RANGE_PLUSMINUS5V = 2,
  SENSOR_ANALOG_RANGE_PLUS10V = 3,
  SENSOR_ANALOG_RANGE_PLUSMINUS10V = 4
};  
  
#define SENSOR_DIGITAL_TYPE_BITS (3)
#define SENSOR_DIGITAL_TYPE_POS (SENSOR_TYPE_POS + SENSOR_TYPE_BITS)
#define SENSOR_DIGITAL_TYPE_MASK CREATE_MASK(SENSOR_DIGITAL_TYPE_BITS, SENSOR_DIGITAL_TYPE_POS)
#define SET_DIGITAL_TYPE(type) ((type & SENSOR_DIGITAL_TYPE_MASK) << SENSOR_DIGITAL_TYPE_POS)
#define GET_DIGITAL_TYPE(val)  ((val >> SENSOR_DIGITAL_TYPE_POS) & SENSOR_DIGITAL_TYPE_MASK)
enum { 
  SENSOR_DIGITAL_PWMACCELEROMETER = 1,
  SENSOR_DIGITAL_3AXISACCEL = 2,
  SENSOR_DIGITAL_GENERIC = 3
};

#define ANALOG_SENSOR(coupling,phytype,inputtype,inputrange)  \
(SET_SENSOR_TYPE(SENSOR_ANALOG) | SET_ANALOG_COUPLING((coupling)) | \
SET_ANALOG_PHYSICAL_TYPE((phytype)) | SET_ANALOG_INPUT_TYPE((inputtype)) | \
SET_ANALOG_INPUT_RANGE((inputrange)))    

#define DIGITAL_SENSOR(type) \
(SET_SENSOR_TYPE(SENSOR_DIGITAL) | SET_DIGITAL_TYPE((type)))    

#endif //__SENSOR_TYPES_H__

--- NEW FILE: triggerFunctions.h ---
#ifndef __TRIGGERFUNCTIONS_H__
#define __TRIGGERFUNCTIONS_H__

enum
  {
    TRIGGER_GT=0,
    TRIGGER_LT,
    TRIGGER_RMS_GT,
    TRIGGER_RMS_LT,
    TRIGGER_ABSOLUTE_GT,
    TRIGGER_ABSOLUTE_LT,
    TRIGGER_POSEDGE,
    TRIGGER_NEGEDGE
  };

#endif

--- NEW FILE: TriggerManager.nc ---
/**
 * @author Robbie Adler
 **/


interface TriggerManager{



  command result_t addTrigger(uint8_t boolOp, 
			      uint32_t triggerFunction,
			      float triggerValue, 
			      uint32_t triggerWindowSamples,
			      uint8_t triggerChannel,
			      uint8_t targetChannel);

  command void clearTrigger(uint8_t targetChannel);
  
  command result_t getOutputUOM(uint8_t channel, uint8_t *pUOM);
  
  /**
   * set the collection specification for a channel that the TriggerManager will collect data from.
   * 
   * @param channel: that this specification applies to.  Channel may either be a target channel 
   *                or a trigger channel
   * @param samplingRate:  the sampling rate that the data should be captured at
   * @param numSamples:  total number of samples that should be collected
   * @param sampleWidth: Width of each sample rounded up to the nearest number of bytes
   * @param headerSize:  additional space that should be allocated by the TriggerManager for header info.
                         Data will start being written at this offset
   * @param footerSize:  additional space that should be allocated by the TriggerManager for footer info.
   * 
   * @return FAIL if this is not possible; SUCCESS otherwise
   *
   **/
  command result_t setCollectionInfo(uint8_t channel, 
				     uint32_t samplingRate, 
				     uint32_t numSamples,
				     uint8_t  sampleWidth,
				     uint16_t headerSize, 
				     uint16_t footerSize);
  
  /**
   * Wait for the trigger condition on a list of channels
   * @param numChannels:  Number of channels that we're waiting on
   * @param targetChannels:  array of channels that we're waiting on
   * @param timeout:  timeout to keep while waiting for the current set of trigger conditions
   * 
   * @return FAIL if this is not possible; SUCCESS otherwise
   *
   **/
  command result_t waitForTrigger(uint8_t numChannels, uint8_t *targetChannels, uint32_t timeout);
  
  /**
   * cancle Waiting for the trigger condition on a list of channels
   * @param numChannels:  Number of channels that we're waiting on
   * @param targetChannels:  array of channels that we're waiting on
   * @param timeout:  timeout to keep while waiting for the current set of trigger conditions
   * 
   * @return FAIL if this is not possible; SUCCESS otherwise
   *
   **/
  command result_t cancelWaitForTrigger(uint8_t numChannels, uint8_t *targetChannels);
  
   /**
   * Trigger condition has either hit or failed for a list of channels
   * @param numChannels:  Number of channels that we're waiting on
   * @param targetChannels:  array of channels that we're waiting on
   * @param status:  SUCCESS if it is ok to start acquiring data, FAIL otherwise
   *
   * @return SUCCESS if handles, FAIL otherwise
   *
   **/
  event result_t waitForTriggerDone(uint8_t numChannels, uint8_t *targetChannels, result_t status);
  
  /**
   * a triggered data buffer that should be committed to memory.  
   * @param buffer:  data buffer
   * @param numBytes: amount of data to write
   * @param done:  TRUE if all data requested by the capture is in the buffer, FALSE if this is a data Fragment that needs to be committed beforehand.
   *
   * @return SUCCESS if handles, FAIL otherwise
   *
   **/
  event result_t TriggeredData(uint8_t channel, 
			       uint8_t *buffer, 
			       float ADCScale, 
			       float ADCOffset,
			       uint16_t numBytesWrite, 
			       uint16_t numBytesTotal, 
			       uint16_t numSamples,
			       uint64_t timestamp,
			       bool done);
  
}

--- NEW FILE: TriggerManagerM.nc ---
/**	
 * @author Robbie Adler	
 **/	
//includes profile;
includes queue;

module TriggerManagerM{
  provides{
    interface TriggerManager;
    interface StdControl;
#ifdef BLUSH_TRIGGER
    interface BluSH_AppI as ForceTrigger;
#endif
  
  }
  uses{
    interface SensorData as SensorData[uint8_t dataChannel];
    interface BufferManagement;
  }
[...1517 lines suppressed...]
      if(channel < TOTAL_DATA_CHANNELS){
	if(gTriggerWaitInfo[channel]){
	  gTriggerWaitInfo[channel]->bTriggered = TRUE;
	}
	else{
	  trace(DBG_USR1,"Error: ForceTrigger encounted unstarted data channel \r\n");
	}
      }
      else{
	trace(DBG_USR1,"ForceTrigger received invalid target data channel = %d\r\n",channel);
      } 
    }
    else{
      trace(DBG_USR1,"ForceTrigger targetDataChannel\r\n");
    }
    return BLUSH_SUCCESS_DONE;
  }
  
#endif
}

--- NEW FILE: triggerOps.h ---
#ifndef __TRIGGER_OPS_H__
#define __TRIGGER_OPS_H__

enum
  {
    TRIGGER_OP_NONE=0,
    TRIGGER_OP_AND,
    TRIGGER_OP_OR
  };


#endif // __TRIGGER_OPS_H__



More information about the Tinyos-contrib-commits mailing list