[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/shockfish/tos/lib/OscopeUART OscopeM.nc, NONE, 1.1

rogmeier rogmeier at users.sourceforge.net
Wed Sep 20 05:47:11 PDT 2006


Update of /cvsroot/tinyos/tinyos-1.x/contrib/shockfish/tos/lib/OscopeUART
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv14971

Added Files:
	OscopeM.nc 
Log Message:
Initial Import. This file is used for the TinyNode demonstrator. Packets are sent on the UART instead of the radio.-


--- NEW FILE: OscopeM.nc ---
//$Id: OscopeM.nc,v 1.1 2006/09/20 12:47:09 rogmeier Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

// @author Cory Sharp <cssharp at eecs.berkeley.edu>

includes Oscope;

module OscopeM
{
  provides interface StdControl;
  provides interface Oscope[uint8_t channel];
  uses interface SendMsg as DataMsg;
  uses interface ReceiveMsg as ResetCounterMsg;
}
implementation
{
  enum
  {
    MAX_CHANNELS = OSCOPE_MAX_CHANNELS,
    BUFFER_SIZE = OSCOPE_BUFFER_SIZE,
  };

  typedef struct
  {
    uint8_t index;
    bool send_data_ready;
    uint16_t lastCount;
    uint16_t count;
    uint16_t data[BUFFER_SIZE];
    uint16_t send_data[BUFFER_SIZE];
  } OscopeData_t;

  TOS_Msg m_msg;
  int m_is_sending;
  int m_send_next;

  OscopeData_t m_data[ MAX_CHANNELS ];

  // reset invoked on any one channel resets all channels.  The oscilloscope
  // visualization is really only useful when all channels are synchronized.

  command void Oscope.reset[uint8_t channel]()
  {
    OscopeData_t* ch = m_data+0;
    OscopeData_t* chend = m_data+MAX_CHANNELS;

    atomic
    {
      for( ; ch != chend; ch++ )
      {
	ch->index = 0;
	ch->send_data_ready = FALSE;
	ch->count = 0;
      }
    }

    m_send_next = 0;
    m_is_sending = FALSE;
  }

  command result_t StdControl.init()
  {
    call Oscope.reset[MAX_CHANNELS]();
    return SUCCESS;
  }

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

  command result_t StdControl.stop()
  {
    return SUCCESS;
  }

  // sendHelper and sendHelperTask post tasks to retry sending a packet until
  // DataMsg.send returns SUCCESS.  It's guarded by m_is_sending so that a call
  // to Oscope.reset() also flushes any pending sendHelperTask.

  void sendHelper();
  task void sendHelperTask()
  {
    sendHelper();
  }

  void sendHelper()
  {
    if( m_is_sending == TRUE )
    {
#ifdef SEND_TO_UART
      if( call DataMsg.send( TOS_UART_ADDR, sizeof(OscopeMsg_t), &m_msg ) == FAIL )
#else
      if( call DataMsg.send( TOS_BCAST_ADDR, sizeof(OscopeMsg_t), &m_msg ) == FAIL )
#endif
      {
	  //	if( post sendHelperTask() == FALSE )
	  m_is_sending = FALSE; //the task didn't post, nothing to do but drop the msg
      }
    }
  }

  int channel_inc( int ch, int inc )
  {
    ch += inc;
    if( ch >= MAX_CHANNELS )
      ch -= MAX_CHANNELS;
    return ch;
  }

  // send tries to be a little fair by transmitting pending channels round
  // robin instead of possibly letting one channel starve another.  Also, as
  // soon as a pending channel is found, its data is stuffed into the local
  // TOS_Msg.  The channel is then allowed to aggregate new, additional data,
  // possibly before the message is sent.

  task void send()
  {
    if( m_is_sending == FALSE )
    {
      int i;
      OscopeData_t* chbegin = m_data + 0;
      OscopeData_t* chend = m_data + MAX_CHANNELS;
      OscopeData_t* ch = m_data + m_send_next;

      for( i=0; i<MAX_CHANNELS; i++ )
      {
	if( ch->send_data_ready == TRUE )
	{
	  OscopeMsg_t* body = (OscopeMsg_t*)m_msg.data;
	  int n = channel_inc( i, m_send_next );

	  body->sourceMoteID = TOS_LOCAL_ADDRESS;
	  body->lastSampleNumber = ch->lastCount;
	  body->channel = n;
	  memcpy( body->data, ch->send_data, sizeof(uint16_t)*BUFFER_SIZE );

	  ch->send_data_ready = FALSE;

	  m_is_sending = TRUE;
	  m_send_next = channel_inc( n, 1 );

	  sendHelper();
	  return; // a channel has been queued for send, get out of here
	}

	if( ++ch == chend )
	  ch = chbegin;
      }
    }
  }

  // When a message is done sending, mark the local TOS_Msg as free to use.
  // Post send again here in case another channel is pending to send, as well.

  event result_t DataMsg.sendDone( TOS_MsgPtr msg, result_t success )
  {
    m_is_sending = FALSE;
    post send();
    return SUCCESS;
  }

  // put increments the reading count regardless if the value is ultimately
  // dropped or not -- this is appropriate.  Because of this, we have to save
  // the count as lastCount so that Oscilloscope can properly visualze in time
  // the aggregated data versus the dropped data.

  task void prepare_send_data()
  {
    OscopeData_t* ch = m_data + 0;
    OscopeData_t* chend = m_data + MAX_CHANNELS;

    for( ; ch != chend; ch++ )
    {
      atomic
      {
	if( ch->index >= BUFFER_SIZE )
	{
	  ch->lastCount = ch->count;
	  memcpy( ch->send_data, ch->data, sizeof(uint16_t)*BUFFER_SIZE );
	  ch->send_data_ready = TRUE;
	  ch->index = 0;
	  post send();
	}
      }
    }
  }

  async command result_t Oscope.put[uint8_t channel]( uint16_t value )
  {
    result_t rv = FAIL;
    atomic
    {
      if( channel < MAX_CHANNELS )
      {
	OscopeData_t* ch = &m_data[channel];
	ch->count++;
	if( ch->index < BUFFER_SIZE )
	{
	  ch->data[ ch->index++ ] = value;
	  if( ch->index >= BUFFER_SIZE )
	    post prepare_send_data();
	  rv = SUCCESS;
	}
      }
    }
    return rv;
  }

  event TOS_MsgPtr ResetCounterMsg.receive( TOS_MsgPtr msg )
  {
    call Oscope.reset[MAX_CHANNELS]();
    return msg;
  }
}




More information about the Tinyos-contrib-commits mailing list