[Tinyos-beta-commits] CVS: tinyos-1.x/beta/platform/imote ADXLM.nc, NONE, 1.1 AlphaDisp.nc, NONE, 1.1 AlphaDispM.nc, NONE, 1.1 BluSH.h, NONE, 1.1 BluSHC.nc, NONE, 1.1 BluSHM.nc, NONE, 1.1 BluSH_AppI.nc, NONE, 1.1 BluSH_types.h, NONE, 1.1 Clock.nc, NONE, 1.1 DebugC.nc, NONE, 1.1 DebugM.nc, NONE, 1.1 DebugUART.nc, NONE, 1.1 DebugUARTBufferC.nc, NONE, 1.1 DebugUARTBufferM.nc, NONE, 1.1 DebugUARTM.nc, NONE, 1.1 FileSystem.nc, NONE, 1.1 FileSystemM.nc, NONE, 1.1 FileSystemTypes.h, NONE, 1.1 Flash.h, NONE, 1.1 Flash.nc, NONE, 1.1 FlashAccessM.nc, NONE, 1.1 FlashFS.h, NONE, 1.1 FlashFS.nc, NONE, 1.1 FlashFSC.nc, NONE, 1.1 FlashFSM.nc, NONE, 1.1 GPIO.nc, NONE, 1.1 HPLByteDMAM.nc, NONE, 1.1 HPLDMA.nc, NONE, 1.1 HPLDebugUartC.nc, NONE, 1.1 HPLDebugUartM.nc, NONE, 1.1 HPLFlashM.nc, NONE, 1.1 HPLMainUartC.nc, NONE, 1.1 HPLMainUartM.nc, NONE, 1.1 HPLUART.nc, NONE, 1.1 LoggerRead.nc, NONE, 1.1 LoggerWrite.nc, NONE, 1.1 NewTimer.h, NONE, 1.1 ReliablePacket.nc, NONE, 1.1 ReliablePacketC.nc, NONE, 1.1 ReliablePacketM.nc, NONE, 1.1 ReliableTransportC.nc, NONE, 1.1 ReliableTransportM.nc, NONE, 1.1 ReliableTransportParams.h, NONE, 1.1 StatsLogger.nc, NONE, 1.1 StatsLoggerM.nc, NONE, 1.1 StatsTypes.h, NONE, 1.1 SystemTime.nc, NONE, 1.1 TimerC.nc, NONE, 1.1 UtilitiesM.nc, NONE, 1.1 WSN.h, NONE, 1.1 WSN_Messages.h, NONE, 1.1 cmdlinetools.c, NONE, 1.1 BTLowerLayersM.nc, 1.1, 1.2 DebugLedM.nc, 1.1, 1.2 FindRootScatternetFormationC.nc, 1.1, 1.2 FindRootScatternetFormationM.nc, 1.1, 1.2 GenericPacketM.nc, 1.1, 1.2 HPLClock.nc, 1.2, 1.3 HPLDMAUart.nc, 1.1, 1.2 HPLDMAUartC.nc, 1.1, 1.2 HPLDMAUartM.nc, 1.1, 1.2 HPLPowerManagementM.nc, 1.1, 1.2 HPLUARTC.nc, 1.1, 1.2 LowPowerM.nc, 1.1, 1.2 NetworkC.nc, 1.1, 1.2 NetworkCommand.h, 1.1, 1.2 NetworkDataM.nc, 1.1, 1.2 NetworkHardwiredC.nc, 1.1, 1.2 NetworkLinkQueuesM.nc, 1.2, 1.3 NetworkManagerM.nc, 1.1, 1.2 NetworkMonitorC.nc, 1.2, 1.3 NetworkMonitorM.nc, 1.2, 1.3 NetworkPageM.nc, 1.1, 1.2 NetworkPropertiesM.nc, 1.1, 1.2 NetworkRelayM.nc, 1.2, 1.3 NetworkTopologyM.nc, 1.1, 1.2 SensorC.nc, 1.1, 1.2 SensorM.nc, 1.1, 1.2 SignalStrengthM.nc, 1.1, 1.2 TempHum.nc, 1.1, 1.2 TempHumM.nc, 1.1, 1.2 TimerM.nc, 1.1, 1.2 TreeRoutingM.nc, 1.2, 1.3 UARTBufferM.nc, 1.2, 1.3 WDTControlM.nc, 1.1, 1.2

Lama Nachman lnachman at users.sourceforge.net
Tue Sep 6 01:28:03 PDT 2005


Update of /cvsroot/tinyos/tinyos-1.x/beta/platform/imote
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27772

Modified Files:
	BTLowerLayersM.nc DebugLedM.nc FindRootScatternetFormationC.nc 
	FindRootScatternetFormationM.nc GenericPacketM.nc HPLClock.nc 
	HPLDMAUart.nc HPLDMAUartC.nc HPLDMAUartM.nc 
	HPLPowerManagementM.nc HPLUARTC.nc LowPowerM.nc NetworkC.nc 
	NetworkCommand.h NetworkDataM.nc NetworkHardwiredC.nc 
	NetworkLinkQueuesM.nc NetworkManagerM.nc NetworkMonitorC.nc 
	NetworkMonitorM.nc NetworkPageM.nc NetworkPropertiesM.nc 
	NetworkRelayM.nc NetworkTopologyM.nc SensorC.nc SensorM.nc 
	SignalStrengthM.nc TempHum.nc TempHumM.nc TimerM.nc 
	TreeRoutingM.nc UARTBufferM.nc WDTControlM.nc 
Added Files:
	ADXLM.nc AlphaDisp.nc AlphaDispM.nc BluSH.h BluSHC.nc 
	BluSHM.nc BluSH_AppI.nc BluSH_types.h Clock.nc DebugC.nc 
	DebugM.nc DebugUART.nc DebugUARTBufferC.nc DebugUARTBufferM.nc 
	DebugUARTM.nc FileSystem.nc FileSystemM.nc FileSystemTypes.h 
	Flash.h Flash.nc FlashAccessM.nc FlashFS.h FlashFS.nc 
	FlashFSC.nc FlashFSM.nc GPIO.nc HPLByteDMAM.nc HPLDMA.nc 
	HPLDebugUartC.nc HPLDebugUartM.nc HPLFlashM.nc HPLMainUartC.nc 
	HPLMainUartM.nc HPLUART.nc LoggerRead.nc LoggerWrite.nc 
	NewTimer.h ReliablePacket.nc ReliablePacketC.nc 
	ReliablePacketM.nc ReliableTransportC.nc ReliableTransportM.nc 
	ReliableTransportParams.h StatsLogger.nc StatsLoggerM.nc 
	StatsTypes.h SystemTime.nc TimerC.nc UtilitiesM.nc WSN.h 
	WSN_Messages.h cmdlinetools.c 
Log Message:
New Imote release, v2.0


--- NEW FILE: ADXLM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */
/*
 * This module provides an interface for a pulse width modulated (PWM) signal.
 * After starting, the module triggers an event on the rising edge of the
 * clock, returning the duty cycle of the most recent pulse.  Two values are
 * returned, the duration of the period and the duration of the high phase.
 */

module ADXLM
{
  provides {
    interface StdControl;
    interface ADXL;
  }
}

implementation
{
    
    // This should move to HPLInterrupt
    extern void TM_PIOIsr_ISR() __attribute__ ((C, spontaneous));
    
    // time stamps for the most recent rise and fall of the signal
        
    signed short Ta, Tb, Tc, Td, tempX, tempY;
    unsigned short T1x,T1y,Time;
    enum eState{getTa, getTb, getTc, done}state;
    
    command result_t StdControl.init() {
        TM_RegisterInterrupt(eTM_PIO, (tIntFunc) TM_PIOIsr_ISR, eTM_ProLow);
        TM_SetPioAsOutput(0);
        TM_SetPioAsOutput(1);
        TM_SetPioAsInput(2);
        //TM_SetPioAsInput(3);
        TM_SetPioAsOutput(3);
        TM_SetPioAsOutput(4);
        TM_SetPioAsOutput(5);
        TM_SetPioAsOutput(6);
        TM_SetPioAsOutput(7);
        
        state = getTa;
        return SUCCESS;
    }
    
    command result_t StdControl.start() {
        TM_LOAD_SVR(0x7FFFFFFF);  
        TM_SET_SVR_CTRL(TM_TMR_ENABLE | TM_TMR_FREERUN_MODE);
        // TM_LOAD_RTOS(0x7FFFFFFF);  
        //TM_SET_RTOS_CTRL(TM_TMR_ENABLE | TM_TMR_FREERUN_MODE);
        TM_Dis_WDTmrClk();
        TM_EnablePIOInt();
        return SUCCESS;
    }
    
    command result_t StdControl.stop() {
        TM_DisablePIOInt();
        return SUCCESS;
    }
    
    default event result_t ADXL.Pulse(unsigned short x, unsigned short y, unsigned short period){ 
        //default event result_t ADXL.Pulse(signed short a, signed short b, signed short c, signed short d){ 
        return SUCCESS;
    }
    
    
  /*
   * Detect any changes on PWM input.  This routine is called when any of the
   * GPIO states change.
   *
   * GPIO2 = PWMx, GPIO3 = PWMy
   */
  void TM_PIO_InterruptHdl() __attribute__ ((C, spontaneous)) {
           
      TM_DisablePIOInt();
      Time = TM_GetSvrTmrCnter();
      //Time = TM_GetRtosTmrCnter();
     
      switch(state)
          {
              //Note:  Apparently our timer is based on the 32k crystal and is only 16 bits
              //       For some terrible reason, it also seems to count down instead of up.
          case getTa:
              if(TM_ReadPio(2))
              {//need to make sure that we align to the rising edge of GPIO2
                  Ta = Time;
                  state = getTb;
              }
              break;
          case getTb:
              //should be the falling edge of GPIO2
              if(TM_ReadPio(2) == 0)
                  {
                      Tb = Time;
                      tempX = Ta-Tb;
                      T1x = (unsigned short)tempX;
                      TM_SetPioAsOutput(2);
                      TM_SetPioAsInput(3);
                      state = getTc;
                  }
              break;
          case getTc:
              //should be the rising edge of GPIO3
              if(TM_ReadPio(3))
                  {
                  Tc = Time;
                  state = done;
              }
              break;
          case done:
              //should be the falling edge of GPIO3
              if(TM_ReadPio(3) == 0)
              {
                  Td = Time;
                  tempY = Tc-Td;
                  T1y = (unsigned short)(tempY);
                  //signal ADXL.Pulse(T1x, T1y, (unsigned)( (Ta- (((signed)T1x)>>2))   - (((signed)T1y)>>2)));
                  TM_SetPioAsInput(2);
                  TM_SetPioAsOutput(3);
                  TM_LOAD_SVR(0x7FFFFFFF);  
                  //TM_LOAD_RTOS(0x7FFFFFFF);  //for some reason, I occasionally miss a Pio interrupt when the timer underflows
                  state = getTa;
                  signal ADXL.Pulse(T1x, T1y, (unsigned short)((Ta - (((signed short)T1x)>>2))  - (Tc - (((signed short)T1y)>>2))));
                  //                 signal ADXL.Pulse(Ta, Tb, Tc, Td);

                  
              }
              break;
          }
      
      TM_ClearPioInterrupt();
      TM_EnablePIOInt();
  }                                 
}

  

--- NEW FILE: AlphaDisp.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

interface AlphaDisp

{
  // initializes AlphaDisp
  // numStatusChars = number of characters used to display link status
  //                  each character can display up to 2 status
  //                  values range 0 to 2
  command result_t init(uint8 numStatusChars);
  
  // puts display to power-saving sleep mode
  command result_t sleep();
  
  // Display up to 4 static characters
  // c = pointer to the character array
  // count = number of characters to display (up to 4-numStatusChars)
  // bright = brightness of display (1 to 15)
  command result_t staticDisp(char *c, uint8 count, uint8 bright);
  
  // Scroll an array of characters in an infinite loop
  // c = pointer to the character array
  // count = number of characters to display (up to 40 characters)
  // bright = brightness of display (1 to 15)
  command result_t scrollInit(char *c, uint8 count, uint8 bright);
  
  // Sets the refresh rate of scroll
  // refresh = refresh interval (in msec)
  command result_t setRefresh(int refresh);
  
  // Update the link quality status indicator
  // dispID = ID of the link quality indicator.  The indicators use
  //          the right 2 (or 1) characters of the display in according
  //          to the following placement:
  //          | 2 | 0 |
  //          | 3 | 1 |
  // linkQuality = link quality in the range 0:15.  The number of dots
  //           showing up on the display indicates this value
  command result_t linkStatusDisp(uint8 dispID, uint8 linkQuality);
}


--- NEW FILE: AlphaDispM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

#define TIC TOSH_SET_LED7_PIN();TOSH_CLR_LED7_PIN()
#define RS_LOW TOSH_CLR_LED2_PIN()
#define RS_HI  TOSH_SET_LED2_PIN()
#define CE_LOW TOSH_CLR_LED5_PIN()
#define CE_HI  TOSH_SET_LED5_PIN()
#define SEND0  TOSH_CLR_LED6_PIN()
#define SEND1  TOSH_SET_LED6_PIN()

#define TABLE_SZ 96*5
#define REMOVED 32
#define NUM_DISP_CHAR 4
#define MAX_NUM_STAT_CHAR 2
#define MAX_SCROLL_CHAR 40
#define COLUMNS_PER_CHAR 5
#define BITS_PER_COLUMN 8

module AlphaDispM {
  provides {
    interface AlphaDisp;
  }
  uses {
    interface Timer;
  }
}
implementation
{
  char buf[TABLE_SZ]; // buffer where the Display bitmaps are stored
                      // format is 5 bytes per ASCII character
                      // each byte corresponds to a column in the bitmap

  char outbuf[NUM_DISP_CHAR*COLUMNS_PER_CHAR];

  uint8 num_active; // number of characters available to staticDisp() and scrollInit()
  uint8 num_status; // number of characters used to display status
  char status_bitmap[COLUMNS_PER_CHAR*MAX_NUM_STAT_CHAR]; // status can use up to 10 columns of display

  int s_len, s_i;
  char s_bitmap[MAX_SCROLL_CHAR*COLUMNS_PER_CHAR+NUM_DISP_CHAR*COLUMNS_PER_CHAR];
  int refresh_rate; // number of msec

  void blankDisp();
  void setBright(uint8 bright);
  void updateDisp (char *buffer);
  char* copyBitmap (char *dest, char *src);

  command result_t AlphaDisp.init(uint8 numStatus) {
    int i;
    //uint8 c;
    char buf_i[TABLE_SZ] = {
    // The first 32 characters of the ASCII table are control characters which are not
    // used in the display.  Therefor the corresponding bitmap is commented out to save
    // memory.
    /*0x3f,0x3f,0x3f,0x3f,0x0,0x8,0x1c,0x3e,0x1c,0x8,0x2a,0x15,0x2a,0x15,0x0,0xf,0x12,0x7f,0x10,0x0,
    0xf,0x5,0x78,0x28,0x0,0x7,0x7d,0x28,0x50,0x0,0x7,0x4,0x78,0x28,0x0,0x0,0x2,0x5,0x2,0x0,
    0x0,0x12,0x17,0x12,0x0,0xf,0x2,0x74,0x4f,0x0,0x7,0x18,0x77,0x10,0x0,0x8,0x8,0xf,0x0,0x0,
    0x8,0x8,0x78,0x0,0x0,0x0,0x0,0x78,0x8,0x8,0x0,0x0,0xf,0x8,0x8,0x8,0x8,0x7f,0x8,0x8,
    0x2,0x2,0x2,0x2,0x2,0x4,0x4,0x4,0x4,0x4,0x8,0x8,0x8,0x8,0x8,0x10,0x10,0x10,0x10,0x10,
    0x20,0x20,0x20,0x20,0x20,0x0,0x0,0x7f,0x8,0x8,0x8,0x8,0x7f,0x0,0x0,0x8,0x8,0xf,0x8,0x8,
    0x8,0x8,0x78,0x8,0x8,0x0,0x0,0x7f,0x0,0x0,0x0,0x24,0x2a,0x31,0x0,0x0,0x31,0x2a,0x24,0x0,
    0x0,0x3c,0x4,0x3c,0x0,0x0,0x34,0x1c,0x16,0x0,0x28,0x1c,0x2a,0x22,0x0,0x0,0x0,0x8,0x0,0x0,*/
    0x0,0x0,0x0,0x0,0x0,0xa,0x0,0x75,0x0,0xa,0x0,0x7,0x0,0x7,0x0,0x14,0x3e,0x14,0x3e,0x14,
    0x4,0x2a,0x3e,0x2a,0x10,0x13,0x8,0x4,0x32,0x0,0x14,0x2a,0x14,0x20,0x0,0x4,0x3,0x1,0x0,0x0,
    0x0,0x1e,0x21,0x0,0x0,0x0,0x21,0x1e,0x0,0x0,0x2a,0x1c,0x2a,0x0,0x0,0x8,0x8,0x3e,0x8,0x8,
    0x40,0x30,0x10,0x0,0x0,0x8,0x8,0x8,0x8,0x0,0x0,0x30,0x30,0x0,0x0,0x10,0x8,0x4,0x2,0x0,
    0x1e,0x21,0x1e,0x0,0x0,0x22,0x3f,0x20,0x0,0x0,0x22,0x31,0x29,0x26,0x0,0x11,0x25,0x25,0x1b,0x0,
    0xc,0xa,0x3f,0x8,0x0,0x17,0x25,0x25,0x19,0x0,0x1e,0x25,0x25,0x18,0x0,0x1,0x31,0xd,0x3,0x0,
    0x1a,0x25,0x25,0x1a,0x0,0x6,0x29,0x29,0x1e,0x0,0x0,0x36,0x36,0x0,0x0,0x40,0x36,0x16,0x0,0x0,
    0x8,0x14,0x22,0x0,0x0,0x14,0x14,0x14,0x14,0x0,0x22,0x14,0x8,0x0,0x0,0x2,0x29,0x6,0x0,0x0,
    0x1e,0x21,0x2d,0xe,0x0,0x3e,0x9,0x9,0x3e,0x0,0x3f,0x25,0x25,0x1a,0x0,0x1e,0x21,0x21,0x12,0x0,
    0x3f,0x21,0x21,0x1e,0x0,0x3f,0x25,0x25,0x21,0x0,0x3f,0x5,0x5,0x1,0x0,0x1e,0x21,0x29,0x3a,0x0,
    0x3f,0x4,0x4,0x3f,0x0,0x21,0x3f,0x21,0x0,0x0,0x10,0x20,0x20,0x1f,0x0,0x3f,0xc,0x12,0x21,0x0,
    0x3f,0x20,0x20,0x20,0x0,0x3f,0x6,0x6,0x3f,0x0,0x3f,0x6,0x18,0x3f,0x0,0x1e,0x21,0x21,0x1e,0x0,
    0x3f,0x9,0x9,0x6,0x0,0x1e,0x31,0x21,0x5e,0x0,0x3f,0x9,0x19,0x26,0x0,0x12,0x25,0x29,0x12,0x0,
    0x1,0x3f,0x1,0x0,0x0,0x1f,0x20,0x20,0x1f,0x0,0xf,0x30,0x30,0xf,0x0,0x3f,0x18,0x18,0x3f,0x0,
    0x33,0xc,0xc,0x33,0x0,0x7,0x38,0x7,0x0,0x0,0x31,0x29,0x25,0x23,0x0,0x3f,0x21,0x21,0x0,0x0,
    0x2,0x4,0x8,0x10,0x0,0x21,0x21,0x3f,0x0,0x0,0x2,0x1,0x2,0x0,0x0,0x20,0x20,0x20,0x20,0x0,
    0x1,0x3,0x4,0x0,0x0,0x18,0x24,0x14,0x3c,0x0,0x3f,0x24,0x24,0x18,0x0,0x18,0x24,0x24,0x0,0x0,
    0x18,0x24,0x24,0x3f,0x0,0x18,0x34,0x2c,0x8,0x0,0x8,0x3e,0x9,0x2,0x0,0x28,0x54,0x54,0x4c,0x0,
    0x3f,0x4,0x4,0x38,0x0,0x24,0x3d,0x20,0x0,0x0,0x20,0x40,0x3d,0x0,0x0,0x3f,0x8,0x14,0x20,0x0,
    0x21,0x3f,0x20,0x0,0x0,0x3c,0x8,0xc,0x38,0x0,0x3c,0x4,0x4,0x38,0x0,0x18,0x24,0x24,0x18,0x0,
    0x7c,0x24,0x24,0x18,0x0,0x18,0x24,0x24,0x7c,0x0,0x3c,0x4,0x4,0x8,0x0,0x28,0x2c,0x34,0x14,0x0,
    0x4,0x1f,0x24,0x20,0x0,0x1c,0x20,0x20,0x3c,0x0,0x1c,0x20,0x1c,0x0,0x0,0x3c,0x30,0x30,0x3c,0x0,
    0x24,0x18,0x18,0x24,0x0,0xc,0x50,0x20,0x1c,0x0,0x24,0x34,0x2c,0x24,0x0,0x4,0x1e,0x21,0x0,0x0,
    0x0,0x3f,0x0,0x0,0x0,0x21,0x1e,0x4,0x0,0x0,0x2,0x1,0x2,0x1,0x0};

    /* clear DOT register */
    blankDisp();

    /* set to lowest power consumption */
    setBright(1);

    /* initialize the bitmap table */
    for (i=0; i<TABLE_SZ; i++)
      buf[i]=buf_i[i];

    if (numStatus<=2) {
       num_status = numStatus;
       num_active = NUM_DISP_CHAR - numStatus;
    }
    else {
       num_status = 0;
       num_active = NUM_DISP_CHAR;
    }

    for (i=0; i<numStatus*COLUMNS_PER_CHAR; i++)
       status_bitmap[i]=0;

    refresh_rate = 300; // default rate of update is 300 msec

    return SUCCESS;
  }

  // put display to sleep
  command result_t AlphaDisp.sleep() {
    uint8 c;
    int i;
    call Timer.stop();
    RS_HI;
    CE_LOW;
    c = 0x00;
    for (i=7; i>=0; i--) {
      if ((c & (1<<i)) == 0)
        SEND0;
      else
        SEND1;
      TIC;
    }
    CE_HI;
    return SUCCESS;
  }

  // display static characters
  command result_t AlphaDisp.staticDisp(char *c, uint8 count, uint8 bright) {
    int i;
    char *buf_ptr, *bitmap_ptr, c_temp;
    uint16 buf_st;
    if (count>num_active)
      count = num_active;
    call Timer.stop(); // disable the scrolling
    blankDisp();
    setBright(bright);
    bitmap_ptr = &outbuf[0];
    for (i=0; i<count; i++) {
      c_temp = c[i] & 0x7f;
      buf_st = (c_temp-REMOVED)*COLUMNS_PER_CHAR;
      buf_ptr = &buf[buf_st];
      bitmap_ptr=copyBitmap(bitmap_ptr, buf_ptr);
    }
    if (num_status>2)
      buf_ptr = &status_bitmap[0];
    else
      buf_ptr = &status_bitmap[5];
    //for (i=count; i<NUM_DISP_CHAR; i++)
    //  bitmap_ptr=copyBitmap(bitmap_ptr, buf_ptr);
    updateDisp(outbuf);
    return SUCCESS;
  }

  // scroll the characters continuously
  command result_t AlphaDisp.scrollInit(char *c, uint8 count, uint8 bright) {
    int i, buf_st;
    char *bitmap_ptr, *buf_ptr, c_temp;

    blankDisp();
    setBright(bright);

    s_len = count*COLUMNS_PER_CHAR+NUM_DISP_CHAR*COLUMNS_PER_CHAR; // blank the first 4 characters

    bitmap_ptr = &s_bitmap[0];
    for (i=0; i<NUM_DISP_CHAR*COLUMNS_PER_CHAR; i++)
      *bitmap_ptr++=0;

    for (i=0; i<count; i++) {
      c_temp = c[i] & 0x7f;
      buf_st = (c_temp-REMOVED)*COLUMNS_PER_CHAR;
      buf_ptr = &buf[buf_st];
      bitmap_ptr=copyBitmap(bitmap_ptr, buf_ptr);
    }
    s_i = 0;
    call Timer.start(TIMER_REPEAT, refresh_rate);
    return SUCCESS;
  }

  // set refresh rate
  // refresh value is in msec
  command result_t AlphaDisp.setRefresh(int refresh) {
    refresh_rate = refresh;
    call Timer.start(TIMER_REPEAT, refresh_rate);
    return SUCCESS;
  }

  // update scroll characters
  event result_t Timer.fired() {
    //char outbuf[COLUMNS_PER_CHAR*NUM_DISP_CHAR];
    int i, offset, offset2;

    for (i=0; i<COLUMNS_PER_CHAR*num_active; i++) {
    	if (s_i==s_len)
    	  s_i = 0;
    	outbuf[i]=s_bitmap[s_i++];
    }
    s_i = s_i-(num_active-1)*COLUMNS_PER_CHAR;
    if (s_i<0)
      s_i = s_len+s_i;

    offset = i;
    offset2 = 0;
    if (num_status <=2)
       offset2 = 5;
    for (i=0; i<num_status*COLUMNS_PER_CHAR; i++)
       outbuf[i+offset]=status_bitmap[i+offset2];

    updateDisp(outbuf);
    return SUCCESS;
  }

  // update status character bitmap according to linkQuality value
  command result_t AlphaDisp.linkStatusDisp(uint8 dispId, uint8 linkQuality) {
    char temp[15], tempBitmap[COLUMNS_PER_CHAR], *ptr, mask;
    int i, j, sh;
    //if ((dispId>>1) != (num_status>>1))
    //  return FAIL;
    for (i=0; i<linkQuality; i++)
      temp[i]=1;
    for (i=linkQuality; i<15; i++)
      temp[i]=0;
    ptr = &temp[0];
    for (i=0; i<COLUMNS_PER_CHAR; i++) {
      tempBitmap[i]=0;
      for (j=0; j<3; j++)
        tempBitmap[i] = tempBitmap[i] | (*ptr++ << j);
    }
    if ((dispId&1) == 0) {
      mask = 0x70;
      sh = 0;
    }
    else {
      mask = 0x07;
      sh = 4;
    }
    if ((dispId&2) == 0)
      //ptr = &status_bitmap[5];
      ptr = &outbuf[15];
    else
      //ptr = &status_bitmap[0];
      ptr = &outbuf[10];
    for (i=0; i<COLUMNS_PER_CHAR; i++) {
      *ptr = *ptr & mask;
      *ptr = *ptr++ | (tempBitmap[i] << sh);
    }
    updateDisp(outbuf);

    return SUCCESS;
  }

  // display the bitmap stored in outbuf
  void updateDisp (char *buffer) {
    int i, j;
    RS_LOW;
    CE_LOW;
    for (i=0; i<COLUMNS_PER_CHAR*NUM_DISP_CHAR; i++) {
      for (j=7; j>=0; j--) {
        if ((buf[i] & (1<<j)) == 0)
          SEND0;
        else
          SEND1;
        TIC;
      }
    }
    CE_HI;
  }

  // put display to sleep
  void blankDisp() {
  int i;
    RS_LOW;
    CE_LOW;
    for (i=0; i<BITS_PER_COLUMN*COLUMNS_PER_CHAR*NUM_DISP_CHAR; i++) {
      SEND0;
      TIC;
    }
    CE_HI;

  }

  // set brightness of display
  // bright = 1    ---->>    dimest
  // bright = 15   ---->>    brightest
  void setBright(uint8 bright) {
    uint8 ctrl;
    int i;
    RS_HI;
    CE_LOW;
    ctrl = 0x60 | (bright&0xf);
    for (i=7; i>=0; i--) {
      if ((ctrl & (1<<i)) == 0)
        SEND0;
      else
        SEND1;
      TIC;
    }
    CE_HI;
  }

  // copy the bitmap of 1 ASCII character
  char* copyBitmap (char *dest, char *src) {
      *dest++ = *src++;
      *dest++ = *src++;
      *dest++ = *src++;
      *dest++ = *src++;
      *dest++ = *src++;
      return dest;
  }
}

--- NEW FILE: BluSH.h ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

// Number of interfaces.
#define __BLUSH_APP_COUNT__ uniqueCount("BluSH")
enum
  {
    BLUSH_APP_COUNT = __BLUSH_APP_COUNT__
  };

--- NEW FILE: BluSHC.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

configuration BluSHC {
  provides interface StdControl;
  uses interface BluSH_AppI[uint8_t id];
}

implementation {
    components 
        //UARTBufferC as UARTBuffer,
        DebugUARTBufferC as UARTBuffer,
        NetworkCommandM,
        BluSHM;
  
    StdControl = BluSHM;
    
    BluSHM.UartControl -> UARTBuffer.Control;
    BluSHM.UartSend -> UARTBuffer.SendVarLenPacket;
    BluSHM.UartReceive -> UARTBuffer.ReceiveData;
    BluSHM.NetworkCommand -> NetworkCommandM;
    BluSH_AppI = BluSHM;
}

--- NEW FILE: BluSHM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

module BluSHM {
  provides
    {
      interface StdControl;
    }

    uses
      {
        interface StdControl as UartControl;
        interface SendVarLenPacket as UartSend;
        interface ReceiveData as UartReceive;
        
        interface NetworkCommand;
        interface BluSH_AppI[uint8_t id];
      }
}


implementation
{
#include "cmdlinetools.c"
#include "BluSH_types.h"

#define BLUSH_PROMPT_LENGTH 32
  char blush_prompt[ BLUSH_PROMPT_LENGTH ];


  // Index 0 is the current command line.
#define BLUSH_HISTORY_LENGTH 2
#define BLUSH_CMDLINE_LENGTH 40
  char blush_history[ BLUSH_HISTORY_LENGTH ][ BLUSH_CMDLINE_LENGTH ];
  uint16_t blush_cmdline_idx;
  uint16_t blush_history_idx;

  uint8_t funcIdx;
  uint8_t funcIdxInUse;
  char funcCmd[ BLUSH_CMDLINE_LENGTH ];

#define MAX_RETURN_STRING 255


  // Internal commands: help, ls, prompt, readmem, writemem.
  void TraceCallback(char *buf, uint16 buflen) __attribute__((C, spontaneous)){
      call UartSend.send(buf,buflen);
  }
  
  command result_t StdControl.init()
    {
      uint16_t i;
      uint32_t my_nodeid;
 
      blush_cmdline_idx = 0;
      blush_history_idx = 0;

      funcIdxInUse = 0;

      // Clear history.
      for( i = 0; i < BLUSH_HISTORY_LENGTH; i++ )
        {
          blush_history[i][0] = '\0';
        }

      trace_set(DBG_USR1|DBG_USR2|DBG_USR3);
      call UartControl.init();
      call NetworkCommand.GetMoteID(&my_nodeid);
      snprintf(blush_prompt,BLUSH_PROMPT_LENGTH, "%.5x>",my_nodeid);
      //strncpy( blush_prompt, "BluSH>", BLUSH_PROMPT_LENGTH );
      return SUCCESS;
    }
    
  command result_t StdControl.start(){
      call UartControl.start();
      call UartSend.send( "\r\n", strlen("\r\n") );
      call UartSend.send( blush_prompt, strlen(blush_prompt) );
      return SUCCESS;
  }

  command result_t StdControl.stop(){
      call UartControl.stop();
      return SUCCESS;
  }
  
  default command BluSH_result_t BluSH_AppI.getName[uint8_t id](char* buff, uint8_t len )
    {
      buff[0] = '\0';
      return BLUSH_SUCCESS_DONE;
    }

  default command BluSH_result_t BluSH_AppI.callApp[uint8_t id]( char* cmdBuff, uint8_t cmdLen,
                                                                 char* resBuff, uint8_t resLen )
    {
      resBuff[0] = '\0';
      return BLUSH_SUCCESS_DONE;
    }


  task void ls()
    {
      uint8_t i;
      char temp[ BLUSH_CMDLINE_LENGTH ];

      for( i = 0; i < BLUSH_APP_COUNT; i++ )
        {
          call BluSH_AppI.getName[i]( temp, BLUSH_CMDLINE_LENGTH );
          call UartSend.send( temp, strlen(temp) );
          call UartSend.send( "\r\n", 2 );
        }
    } 


  task void help()
    {
      call UartSend.send( "Blue Shell v1.0 (BluSH)\r\n", 
                          strlen("Blue Shell v1.0 (BluSH)\r\n") );
      call UartSend.send( "help - Display this list\r\n", 
                          strlen("help - Display this list\r\n") );
      call UartSend.send( "ls - Display all application commands\r\n", 
                          strlen("ls - Display all application commands\r\n") );
      call UartSend.send( "history - Display the command history\r\n", 
                          strlen("history - Display the command history\r\n") );
      call UartSend.send( "prompt - Allows you to change the prompt\r\n", 
                          strlen("prompt - Allows you to change the prompt\r\n") );
    }


  task void history()
    {
      uint16_t hist_idx;
      for( hist_idx = BLUSH_HISTORY_LENGTH-1; hist_idx > 0; hist_idx-- )
        {
          if( blush_history[ hist_idx ][0] != '\0' )
            {
              call UartSend.send( blush_history[ hist_idx ], 
                                  strlen(blush_history[ hist_idx ]) );
                              
              call UartSend.send( "\r\n", strlen("\r\n") );
            }
        }
    }

  /*
  task void prompt()
    {
      uint16_t frstSpc;
      frstSpc = firstSpace( blush_history[0], 0 );
      if( frstSpc == 0 )
        {
          call UartSend.send( "prompt <new prompt string>\r\n",
                              strlen("prompt <new prompt string>\r\n") );
        }
      else
        {
          strncpy( blush_prompt, &(blush_history[0][frstSpc+1]), BLUSH_PROMPT_LENGTH );
        }
    }
  */


  task void printCmdLine()
    {
      // Print out prompt.
      call UartSend.send( blush_prompt, strlen(blush_prompt) );
      // Last but not least, null terminate the command line.
      blush_history[0][0] = '\0';
      blush_cmdline_idx = 0;
      blush_history_idx = 0;
    }


  task void callFunc()
    {
      char retStr[ MAX_RETURN_STRING ];
      call BluSH_AppI.callApp[funcIdx]( funcCmd, BLUSH_CMDLINE_LENGTH, 
                                        retStr, MAX_RETURN_STRING );

      // Watch out for buffer overflow.
      retStr[ MAX_RETURN_STRING - 1 ] = '\0';
      
      call UartSend.send( retStr, strlen(retStr) );

      funcIdxInUse = 0;
    }

#define UP_ARROW 0x41
#define DOWN_ARROW 0x42
  
  event result_t UartReceive.receive( uint8_t* buff, uint32_t numBytesRead )
    {
      uint16_t i, hist_idx, cmd_idx;
      char temp[ BLUSH_CMDLINE_LENGTH ];

      uint8_t frstSpc;
      static uint8 uSpecialChar=0;
      
      for( i = 0; i < numBytesRead; i++ )
        {
            // Need to look for special characters:
            
          // ENTER is 0x0d
          if( buff[i] == 0x0d )
            {
              // Append \0
              blush_history[0][ blush_cmdline_idx ] = '\0';

              // Output new line.
              call UartSend.send( "\r\n", 2 );

              // Get rid of whitespace.
              killWhiteSpace( blush_history[0] );

              // check if there is anything meaningful
              if( blush_history[0][ 0 ] == '\0' )
                {
                  // Do nothing.
                  post printCmdLine();
                }
              else
                {              
                  // Copy history
                  for( hist_idx = BLUSH_HISTORY_LENGTH-1; hist_idx > 0; hist_idx-- )
                    {
                      // Rollover to 65535 is intentional.
                      cmd_idx = -1;
                      do
                        {
                          cmd_idx++;
                          blush_history[ hist_idx ][ cmd_idx ] = 
                            blush_history[ hist_idx-1 ][ cmd_idx ];
                        }
                      while( cmd_idx < BLUSH_CMDLINE_LENGTH
                             && blush_history[ hist_idx-1 ][ cmd_idx ] != '\0' );
                    }

                  // Process cmdline.
                  // Look for internal commands first, then blush_app commands.
                  if( 0 == strncmp( "help", blush_history[0], strlen("help") ) )
                    {
                      post help();
                      post printCmdLine();
                      
                      /*
                        call UartSend.send( "Blue Shell v1.0 (BluSH) Native Commands\r\n", 
                        strlen("Blue Shell (BluSH) Native Commands\r\n") );

                        call UartSend.send( "help - Display this list\r\n", 
                        strlen("help - Display this list\r\n") );
                        call UartSend.send( "ls - Display all application commands\r\n", 
                        strlen("ls - Display all application commands\r\n") );
                        call UartSend.send( "history - Display the command history\r\n", 
                        strlen("history - Display the command history\r\n") );
                        call UartSend.send( "prompt - Allows you to change the prompt\r\n", 
                        strlen("prompt - Allows you to change the prompt\r\n") );
                      */
                    }
                  else if( 0 == strncmp( "ls", blush_history[0], strlen("ls") ) )
                    {
                      post ls();
                      post printCmdLine();
                      /*
                        for( i = 0; i < BLUSH_APP_COUNT; i++ )
                        {
                        call BluSH_AppI.getName[i]( temp, BLUSH_CMDLINE_LENGTH );
                        call UartSend.send( temp, strlen(temp) );
                        call UartSend.send( "\r\n", 2 );
                        }
                      */
                    }
                  else if( 0 == strncmp( "prompt", blush_history[0], strlen("prompt") ) )
                    {
                      //post prompt();
                      //post printCmdLine();

                      
                      frstSpc = firstSpace( blush_history[0], 0 );
                      if( frstSpc == 0 )
                        {
                          call UartSend.send( "prompt <new prompt string>\r\n",
                                              strlen("prompt <new prompt string>\r\n") );
                        }
                      else
                        {
                          strncpy( blush_prompt, &(blush_history[0][frstSpc+1]), BLUSH_PROMPT_LENGTH );
                        }

                      post printCmdLine();
                      
                    }
                  else if( 0 == strncmp( "history", blush_history[0], strlen("history") ) )
                    {
                      post history();
                      post printCmdLine();

                      /*
                        for( hist_idx = BLUSH_HISTORY_LENGTH-1; hist_idx > 0; hist_idx-- )
                        {
                        if( blush_history[ hist_idx ][0] != '\0' )
                        {
                        call UartSend.send( blush_history[ hist_idx ], 
                        strlen(blush_history[ hist_idx ]) );
                              
                        sprintf( temp, "%d", strlen(blush_history[ hist_idx ]) );
                              
                        //call UartSend.send( temp,
                        //strlen(temp) );
                              

                        call UartSend.send( "\r\n", strlen("\r\n") );
                        }
                        }
                      */
                    }
                  else
                    {
                      if( funcIdxInUse == 0 )
                        {
                          // Loop through app commands.
                          for( i = 0; i < BLUSH_APP_COUNT; i++ )
                            {
                              call BluSH_AppI.getName[i]( temp, BLUSH_CMDLINE_LENGTH );
                              if( (strncmp( temp,
                                            blush_history[0],
                                            strlen(temp)) == 0)
                                  && ((blush_history[0][strlen(temp)] == ' ')
                                      || (blush_history[0][strlen(temp)] == '\0')) )
                                {
                                  funcIdx = i;
                                  funcIdxInUse = 1;
                                  strcpy( funcCmd, blush_history[0] );
                              
                                  post callFunc();
                                  
                                  /*
                                    call BluSH_AppI.callApp[i]( blush_history[0], BLUSH_CMDLINE_LENGTH, 
                                    temp2, BLUSH_CMDLINE_LENGTH );
                                    call UartSend.send( temp2, strlen(temp2) );
                                  */
                                  break;
                                }
                            }

                          if( i == BLUSH_APP_COUNT )
                            {
                              call UartSend.send( "Bad command\r\n", strlen("Bad command\r\n") );
                            }
                        }
                      else
                        {
                          call UartSend.send( "Shell Busy\r\n",
                                              strlen("Shell Busy\r\n") );
                        }
                      post printCmdLine();
                    }
                }

              /*
              // Print out prompt.
              call UartSend.send( blush_prompt, strlen(blush_prompt) );
              // Last but not least, null terminate the command line.
              blush_history[0][0] = '\0';
              blush_cmdline_idx = 0;
              blush_history_idx = 0;
              */
            }
          // CTRL-C
          else if( buff[i] == 0x03 )
            {
              // Discard history.
              blush_cmdline_idx = 0;
              blush_history_idx = 0;
              blush_history[0][0] = '\0';

              // print out new line and prompt.
              call UartSend.send( "\r\n", 2 );
              call UartSend.send( blush_prompt, strlen(blush_prompt) );

            }
          // TAB is 0x09
          else if( buff[i] == 0x09 )
            {
              // Tab completetion.
              // Search through list of available names.
              // Ouput correct one, or beep.
              for( i = 0; i < BLUSH_APP_COUNT; i++ )
                {
                  call BluSH_AppI.getName[i]( temp, BLUSH_CMDLINE_LENGTH );
                  if( strncmp( blush_history[0],
                               temp,
                               strlen(blush_history[0])) == 0 )
                    {
                      call UartSend.send( temp+strlen(blush_history[0]),
                                          strlen(temp)-strlen(blush_history[0]) );
                      call UartSend.send( " ", 1 );
                      strcat( blush_history[0], temp+strlen(blush_history[0]) );
                      strcat( blush_history[0], " " );
                      blush_cmdline_idx = strlen(temp)+1;

                      // add NULL.
                      blush_history[0][blush_cmdline_idx] = '\0';
                      break;
                    }
                }

              if( i >= BLUSH_APP_COUNT )
                {
                  // No match found.  Send beep.
                  call UartSend.send( "\a", 1 );
                }
            }
          // Arror keys.
          else if( buff[i] == 0x1b  || uSpecialChar!=0 ){
              static int special_i=0;
              //check to see if the current char is part of the escape sequence
              switch(special_i){
              case 0:
                  uSpecialChar=1;
                  special_i++;
                  break;
              case 1:
                  if(buff[i]!=0x5b){
                      uSpecialChar=0;
                      special_i=0;
                      //at this point, we know that our escape sequence was invalid, so we should treat
                      //the current character as a normal character...need to fall through on the outer loop
                      //at the moment, I'm happy with losing a character if the escape key is pressed
                      continue;
                  }
                  
                  special_i++;
                  break;
              case 2:
                  uSpecialChar=buff[i];
              case 3:
              case 4:
              case 5:
                  //pretty much need to assume that these characters are 0's
                  special_i++;
              }
              
              
              
              if( special_i == 6 && uSpecialChar == UP_ARROW ){
                  // Then it is an up arrow.
                  if( blush_history_idx < BLUSH_HISTORY_LENGTH-1 ){
                      blush_history_idx++;
                      
                      // Erase what's currently there.
                      for( i = 0; i < blush_cmdline_idx; i++ ){
                          // send backspace space backspace sequenence
                          call UartSend.send("\b \b", 3 );         
                      }
                      
                      // Copy history index.
                      strcpy( blush_history[0], blush_history[ blush_history_idx ] );
                      call UartSend.send( blush_history[0], strlen(blush_history[0]) );  
                      blush_cmdline_idx = strlen(blush_history[0]);
                  }
                  else{
                      call UartSend.send( "\a", 1 );
                  }
              } // Check for up arrow.
              else if( special_i == 6 && uSpecialChar == DOWN_ARROW ){
                  // Then it is a down arrow.
                  if( blush_history_idx > 0 ){
                      blush_history_idx--;
                      if( blush_history_idx == 0 ){
                          // Erase what's currently there.
                          for( i = 0; i < blush_cmdline_idx; i++ ){
                              // send backspace space backspace sequence
                              call UartSend.send("\b \b", 3 );         
                          }
                          blush_cmdline_idx = 0;
                          blush_history[0][0] = '\0';
                      }
                      else{
                          // Erase what's currently there.
                          for( i = 0; i < blush_cmdline_idx; i++ ){
                              // send backspace space backspace sequence
                              call UartSend.send("\b \b", 3 );         
                          }
                          
                          // Copy history index.
                          strcpy( blush_history[0], blush_history[ blush_history_idx ] );
                          call UartSend.send( blush_history[0], strlen(blush_history[0]) );  
                          blush_cmdline_idx = strlen(blush_history[0]);
                      }
                  }
                  else{
                      call UartSend.send( "\a", 1 );
                  }
              } // check for down arrow.
              if(special_i==6){
                  special_i=0;
                  uSpecialChar=0;
              }
          } // Special char check.
          
          // Backspace
          else if( buff[i] == '\b' )
            {
              if( blush_cmdline_idx > 0 )
                {
                  // Echo the character back.
                  call UartSend.send( &buff[i], 1 );         
                  // Print a space
                  call UartSend.send( " ", 1 );         
                  // Echo the character back.
                  call UartSend.send( &buff[i], 1 );         
                  blush_cmdline_idx--;
                  
                  blush_history[0][blush_cmdline_idx] = '\0';
                }
              else
                {
                  call UartSend.send( "\a", 1 );         
                }
            }
          else // Normal character.
            {
              // By this time we know that it's not a special character.
              // Copy it into our buffer.
              if( blush_cmdline_idx < BLUSH_CMDLINE_LENGTH - 1 )
                {
                  blush_history[0][ blush_cmdline_idx ] = buff[ i ];
                  blush_cmdline_idx++;
                  // Put a \0 on the end for safety.
                  blush_history[0][ blush_cmdline_idx ] = '\0';

                  // Echo the character back.
                  call UartSend.send( &buff[i], 1 );         
                }
              else
                {
                  // Send bell back, avoid buffer overflow.
                  //buff[i] = '\a';
                  call UartSend.send( "\a", 1 );         
                }
            }
        }
      
      return SUCCESS;
    }

  event result_t UartSend.sendDone(uint8_t* packet, result_t success)
    {
      // This function does nothing.
      return SUCCESS;
    }

/*
 * Start of NetworkCommand interface.
 */

  event result_t NetworkCommand.CommandResult( uint32 Command, uint32 value) {
     return SUCCESS;
  }


}

--- NEW FILE: BluSH_AppI.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

/* Blue Shell (BluSH) application (aka module) interface */

includes BluSH_types;
includes BluSH;

interface BluSH_AppI
{
  command BluSH_result_t getName( char* buff, uint8_t len );
  command BluSH_result_t callApp( char* cmdBuff, uint8_t cmdLen,
                                  char* resBuff, uint8_t resLen );
}

--- NEW FILE: BluSH_types.h ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

enum 
  {
    BLUSH_SUCCESS_DONE = 0,
    BLUSH_SUCCESS_NOT_DONE,
    BLUSH_FAIL
  };

typedef uint8_t BluSH_result_t;

--- NEW FILE: Clock.nc ---
// $Id: Clock.nc,v 1.1 2005/09/06 08:27:58 lnachman Exp $

/*									tab:4
 * "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."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */
/*
 * Authors:		Jason Hill, David Gay, Philip Levis, Nelson Lee
 * Date last modified:  6/25/02
 *
 *
 */



/**
 * The hardware clock interface. 
 * @author Jason Hill
 * @author David Gay
 * @author Philip Levis
 * @author Nelson Lee
 **/
includes Clock;

interface Clock {

  /**
   *  Set the clock rate.  For the specific meanings of interval
   * and scale, refer to the processor data sheet. For the mica and rene:
   * <p>
   * <pre>
   *     Clock scale
   *         0 - off
   *         1 - 32768 ticks/second
   *         2 - 4096 ticks/second
   *         3 - 1024 ticks/second
   *         4 - 512 ticks/second
   *         5 - 256 ticks/second
   *         6 - 128 ticks/second
   *         7 - 32 ticks/second
   * </pre>
   * <p>
   *
   * Interval is how many ticks per clock firing.
   * For example, setRate(160,7) will result in an event every 160/32
   * seconds.
   *
   * See also: <code>Clock.h</code> for predefined macros:
   *
   * <p>
   * <pre>
   *  interval      scale         result
   *  TOS_I1000PS   TOS_S1000PS   1000 ticks/sec
   *  TOS_I100PS    TOS_S100PS     100 ticks/sec
   *  TOS_I10PS     TOS_S10PS       10 ticks/sec
   *  TOS_I4096PS   TOS_S4096PS   4096 ticks/sec
   *  TOS_I2048PS   TOS_S2048PS   2048 ticks/sec
   *  TOS_I1024PS   TOS_S1024PS   1024 ticks/sec
   *  TOS_I512PS    TOS_S512PS     512 ticks/sec
   *  TOS_I256PS    TOS_S256PS     256 ticks/sec
   *  TOS_I128PS    TOS_S128PS     128 ticks/sec
   *  TOS_I64PS     TOS_S64PS       64 ticks/sec
   *  TOS_I32PS     TOS_S32PS       32 ticks/sec
   *  TOS_I16PS     TOS_S16PS       16 ticks/sec
   *  TOS_I8PS      TOS_S8PS         8 ticks/sec
   *  TOS_I4PS      TOS_S4PS         4 ticks/sec
   *  TOS_I2PS      TOS_S2PS         2 ticks/sec
   *  TOS_I1PS      TOS_S1PS         1 tick/sec
   *  TOS_I0PS      TOS_S0PS         0 ticks/sec (clock off)
   * </pre>
   **/
  async command result_t setRate(uint32_t interval, char scale);

  /**
   *  Set clock interval 
   * 
   *  @param value New clock interval
   *
   *  @return none
   **/
  async command void setInterval(uint32_t value);

  /**
   *  Set clock interval at next clock interrupt time
   * 
   *  @param value New clock interval
   *
   *  @return none
   **/
  async command void setNextInterval(uint8_t value);

  /**
   *  Get clock interval 
   * 
   *  @return current clock interval
   **/
  async command uint8_t getInterval();

  /**
   *  Get clock scale 
   * 
   *  @return current clock scale level
   **/  
  async command uint8_t getScale();

  /**
   *  Set clock scale at next clock interrupt time 
   * 
   *  @param scale New clock scale
   *
   *  @return none
   **/
  async command void setNextScale(uint8_t scale);

  /**
   *  Set both clock interval and scale
   * 
   *  @param interval New clock interval
   *
   *  @param scale New clock scale
   *
   *  @return SUCCESS or FAILED 
   **/
  async command result_t setIntervalAndScale(uint8_t interval, uint8_t scale);

  /**
   *  Read HW clock counter
   */
  async command uint32_t readCounter() ;

  /**
   *  Set HW clock counter to a specified value
   *
   *  @param n Value to write to TCNT0
   *
   *  @return None
   */
  async command void setCounter(uint32_t n);


  /**
   *  Disable Clock interrupt
   */
  async command void intDisable();


  /**
   *  Enable Clock interrupt
   */
  async command void intEnable() ;


  /**
   *  An event sent when the clock goes off.
   **/
  async event result_t fire();
}











--- NEW FILE: DebugC.nc ---
configuration DebugC{
    provides interface StdControl;
}

implementation {
    components DebugM, DebugUARTBufferC;   
    StdControl = DebugM;
    DebugM.SendVarLenPacket -> DebugUARTBufferC;
    DebugM.SendVarLenPacketControl -> DebugUARTBufferC;
}

--- NEW FILE: DebugM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

module DebugM {
	provides {
		interface StdControl as DebugControl;
	}
	uses {
        interface SendVarLenPacket;
        interface StdControl as SendVarLenPacketControl;
	}
}

implementation {
#include "motelib.h"
    
    void TraceCallback(char *buf, uint16 buflen) __attribute__((C, spontaneous)){
        call SendVarLenPacket.send(buf,buflen);
    }
        
    command result_t DebugControl.init(){
        trace_set(DBG_ALL);
        return call SendVarLenPacketControl.init();
    }
    
    command result_t DebugControl.start(){
        return  call SendVarLenPacketControl.start();
    }

    command result_t DebugControl.stop(){
        return  call SendVarLenPacketControl.stop();
    }
     
    event result_t SendVarLenPacket.sendDone(uint8* data, result_t suc) {
        return suc;
    }
}

--- NEW FILE: DebugUART.nc ---
// $Id: DebugUART.nc,v 1.1 2005/09/06 08:27:58 lnachman Exp $

/*									tab:4
 * "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."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */
/*
 *
 * Authors:		Jason Hill, David Gay, Philip Levis
 * Date last modified:  6/25/02
 *
 */

/**
 * @author Jason Hill
 * @author David Gay
 * @author Philip Levis
 */


configuration DebugUART {
  provides {
    interface ByteComm;
    interface StdControl as Control;
  }
}
implementation {
  components DebugUARTM, HPLDebugUartC;

  ByteComm = DebugUARTM;
  Control = DebugUARTM;
  DebugUARTM.HPLUART -> HPLDebugUartC;
}

--- NEW FILE: DebugUARTBufferC.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

configuration DebugUARTBufferC {
  provides {
    interface StdControl as Control;
    interface SendVarLenPacket;
    interface ReceiveData;
  }
}
implementation {
  components DebugUARTBufferM, DebugUART;

  Control = DebugUARTBufferM;
  SendVarLenPacket = DebugUARTBufferM;
  ReceiveData = DebugUARTBufferM;

  DebugUARTBufferM.ByteComm -> DebugUART;
  DebugUARTBufferM.ByteControl -> DebugUART;
}

--- NEW FILE: DebugUARTBufferM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */
/*
 * This module maintains a buffer of characters to put on the UART.
 * It copies incoming characters into the buffer and streams them out the
 * UART as each previous character finishes.
 */

module DebugUARTBufferM {
  provides {
    interface StdControl as Control;
    interface SendVarLenPacket;
    interface ReceiveData;

  }
  uses {
    interface ByteComm;
    interface StdControl as ByteControl;
  }
}

implementation
{

  uint32 Head;               // Next entry in the buffer to fill
  uint32 Tail;               // Oldest entry in the buffer
  // Head == Tail -> buffer is empty

  #define NEXT_BUFFER(ent, max) (((ent) >= ((max) - 1)) ? 0 : ((ent) + 1))
  #define BUFFER_SIZE 100    // maximum characters buffered in the queue
  char Buffer[BUFFER_SIZE];  // circular buffer of characters

  bool BytePending;          // whether there is a byte sent w/o a
                             // corresponding sendDone


/*
 * Start of StdControl interface
 */

  command result_t Control.init() {
    Head = 0;
    Tail = 0;
    atomic {
       BytePending = FALSE;
    }

    return call ByteControl.init();
  }

  command result_t Control.start() {
    return call ByteControl.start();
  }

  command result_t Control.stop() {
    return call ByteControl.stop();
  }

/*
 * End of StdControl interface
 */



   result_t SendNextByte() {
     bool busy;
     atomic {
        busy = (BytePending == TRUE);
     }
     if (busy) {
        return FAIL;
     }

     if (Head == Tail) return SUCCESS; // buffer is empty

     atomic {
        BytePending = TRUE;
     }

     call ByteComm.txByte(Buffer[Tail]);
//     if (call ByteComm.txByte(Buffer[Tail]) == FAIL) {
//       // UART not enabled
//       Tail = Head;
//       BytePending = FALSE;
//     }

     return SUCCESS;
   }

/*
 * Start of SendVarLenPacket interface
 */

  command result_t SendVarLenPacket.send(uint8* data, uint8 length) {
    int     i, size;
    bool    not_busy;

    // see if there's enough room for this packet
    size = (Head < Tail) ? Head + BUFFER_SIZE - Tail : Head - Tail;
    if (size + length >= BUFFER_SIZE) return FAIL; // not enough room

    // copy incoming bytes to the buffer
    for (i = 0; i < length; i++) {
      Buffer[Head] = data[i];
      Head = NEXT_BUFFER(Head, BUFFER_SIZE);
    }

    atomic {
       not_busy = (BytePending == FALSE);
    }

    if (not_busy) SendNextByte();

    return SUCCESS;
  }

  default event result_t SendVarLenPacket.sendDone(uint8* data, result_t suc) {
    return suc;
  }

/*
 * End of SendVarLenPacket interface
 */



/*
 * Start of ByteComm interface
 */

  async event result_t ByteComm.txByteReady(bool success) {

    atomic {
       BytePending = FALSE;
    }
if (Head == Tail) return SUCCESS;
    Tail = NEXT_BUFFER(Tail, BUFFER_SIZE);
    SendNextByte();

    return SUCCESS;
  }

  // this appears to be redundant in the interface with txByteReady
  async event result_t ByteComm.txDone() { return SUCCESS; }

  async event result_t ByteComm.rxByteReady(uint8 data, bool error, uint16_t str) {
    signal ReceiveData.receive(&data, 1);
    return SUCCESS;
  }

/*
 * End of ByteComm interface
 */



/*
 * Start of ReceiveData interface
 */

  default event result_t ReceiveData.receive(uint8* Data, uint32 Length) {
    return SUCCESS;
  }

/*
 * End of ReceiveData interface
 */

}


--- NEW FILE: DebugUARTM.nc ---
// $Id: DebugUARTM.nc,v 1.1 2005/09/06 08:27:58 lnachman Exp $

/*									tab:4
 * "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."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */
/*
 *
 * Authors:		Jason Hill, David Gay, Philip Levis
 * Date last modified:  5/27/03
 *
 *  5/27/03    pal      Added atomic sections for safety.
 *
 */

/**
 * @author Jason Hill
 * @author David Gay
 * @author Philip Levis
 */


module DebugUARTM {
  provides {
    interface ByteComm;
    interface StdControl as Control;
  }
  uses {
    interface HPLUART;
  }
}
implementation 
{
  bool state;

  command result_t Control.init() {
    dbg(DBG_BOOT, "UART initialized\n");
    atomic {
      state = FALSE;
    }
    return SUCCESS;
  }

  command result_t Control.start() {
    return call HPLUART.init();
  }

  command result_t Control.stop() {
      
    return call HPLUART.stop();
  }
    
  async event result_t HPLUART.get(uint8_t data) {
    // Changed SRM 7.8.02 -- No reason to clear state just because
    // we received some data, I think...

    //    state = FALSE;
    signal ByteComm.rxByteReady(data, FALSE, 0);
    dbg(DBG_UART, "signal: state %d\n", state);
    return SUCCESS;
  }

  async event result_t HPLUART.putDone() {
    bool oldState;
    
    atomic {
      dbg(DBG_UART, "intr: state %d\n", state);
      oldState = state;
      state = FALSE;
    }

    /* Note that the state transition/event signalling is not atomic.
       It is possible, after state has been set to FALSE, that
       someone calls txByte before txDone is signalled. The event
       handler therefore may not be able to transmit. Sharing
       the byte level can be very tricky, unless we assure non-preemptiveness
       or have client ids. The UART implementation is non-preemptive,
       but is not assuredly so. -pal*/
    if (oldState) {
      signal ByteComm.txDone();
      signal ByteComm.txByteReady(TRUE);
    }  
    return SUCCESS;
  }

  async command result_t ByteComm.txByte(uint8_t data) {
    bool oldState;
    
    dbg(DBG_UART, "UART_write_Byte_inlet %x\n", data);

    atomic {
      oldState = state;
      state = TRUE;
    }
    if (oldState) 
      return FAIL;

    call HPLUART.put(data);

    return SUCCESS;
  }

}

--- NEW FILE: FileSystem.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

includes FileSystemTypes;

interface FileSystem{
  result_t async command create(userId_t ID, uint16_t size);
  result_t async command delete(userId_t ID);
  uint16_t async command append(userId_t ID, uint8_t *buffer, uint16_t size);
  uint16_t async command write(userId_t ID, uint8_t *buffer, uint16_t location, uint16_t size);
  uint16_t async command getFileSize(userId_t ID);
  uint16_t async command read(userId_t ID, uint8_t *buffer, uint16_t location, uint16_t length);
  result_t async command commit(userId_t ID);
  result_t async command getFileInfo(FileInfo* fi);
}

--- NEW FILE: FileSystemM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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"
[...1048 lines suppressed...]
  }
 
   result_t async command FileSystem.getFileInfo(FileInfo* fi){
     uint16_t i,j;
     result_t success=!SUCCESS;
     j=0;
     atomic{
     for(i=0;i<MAX_FILES;i++){
       if(bootSector.record[i].flags&CREATED){
          fi[j].ID = bootSector.record[i].userId;
          fi[j].size = bootSector.record[i].size;
          j++;
          success=SUCCESS;
       }
      }
    }
   return success;
  }

}

--- NEW FILE: FileSystemTypes.h ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

typedef uint16_t zeevoId_t;
typedef uint16_t userId_t;
typedef uint8_t magicNum_t ;

typedef struct{
  userId_t ID;
  uint16_t size;
}FileInfo;

#define FS_DEBUG 

#ifdef FS_DEBUG
//#define WRITE_CRASH_ID 666 //(this is for testing boot crash)
//#define MAX_ZEEVO_IDS 4 // this is for testing failure of zeevo
                        //id distribution

#endif

--- NEW FILE: Flash.h ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

/*
 * Defines to mirror unix file io
 */

enum {
  FFS_O_RDONLY = 0x0000,
  FFS_O_WRONLY = 0x0001,
  FFS_O_RDWR = 0x0002,
  FFS_O_APPEND = 0x0008,
  FFS_O_CREAT = 0x0200,
  FFS_O_TRUNC = 0x0400
};

enum {
  FFS_SEEK_SET = 0x1,
  FFS_SEEK_CUR = 0x2,
  FFS_SEEK_END = 0x3
};

// Zeevo recomends < 200 B block size so make things simple by rounding to a
// power of 2.  Must match block size in config file
enum {
  BLOCK_SIZE = 256
};


--- NEW FILE: Flash.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

/*
 * Interface for directly manipulating the flash.
 */

includes Flash;

interface Flash {

  /*
   * Gets a memory pointer to a block for reading.  In this implementation
   * the memory is accessed directly from flash.  This pointer cannot be used 
   * to modify the contents in flash.  Any writes to the pointer will result
   * in unpredicted behavior.
   */

  command void *getReadBlock(int blockIndex);



  /*
   * Gets a memory pointer to a block for writing.  The contents of the block
   * can be read or written using this pointer.  Changes to the block are not
   * committed until the commitBlock command is called.
   */

  command void *getWriteBlock(int blockIndex);



  /*
   * Write a block from core memory back into flash memory and deallocate the
   * pointer.  Future writes to the same block must first call getWriteBlock.
   */
  command result_t commitBlock(int blockIndex);

}

--- NEW FILE: FlashAccessM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

module FlashAccessM
{
  provides {
    interface StdControl as FlashControl;
    interface LoggerWrite as FlashWrite;
    interface LoggerRead as FlashRead;
  }
  uses {
    interface Leds;
  }
}

implementation{
   uint16_t curFlashWriteID, curFlashReadID;
   uint16_t rec_size=1024;

  command result_t FlashControl.init() {
   // TM_InitFlashControl();
  //  bool res =  TM_InitFlashDynamicDB();
    
    curFlashWriteID = TM_FLASH_LAST_USER_ID-TM_FLASH_MAX_RECS;
    curFlashReadID = TM_FLASH_LAST_USER_ID-TM_FLASH_MAX_RECS;
    call Leds.init();
  }


  command result_t FlashControl.start() {
  }

  command result_t FlashControl.stop() {
  }

  command result_t FlashRead.read(uint16_t ID, uint8_t *buffer){
    uint8_t *rd_ptr;
    result_t result;
    rd_ptr = TM_API_GetFlashReadPtr(ID);
    if(rd_ptr){
      result = SUCCESS;
      //call Leds.greenToggle();
    }
    else
      result = !SUCCESS;
    buffer = rd_ptr;
    return signal FlashRead.readDone(rd_ptr,result);
    }
   

  command result_t FlashRead.readNext(uint8_t *buffer){
      curFlashReadID++;
      return call FlashRead.read(curFlashReadID,buffer);
  }
 
  command result_t FlashRead.resetPointer(){
    curFlashReadID = TM_FLASH_LAST_USER_ID - TM_FLASH_MAX_RECS;     
    return SUCCESS;
  }

  command result_t FlashRead.setPointer(uint16_t ID){
    curFlashReadID = ID;
  }

  command result_t FlashWrite.append(uint8_t *buffer){
    curFlashWriteID++;
    return call FlashWrite.write(curFlashWriteID,buffer);
  }

  command result_t FlashWrite.write(uint16_t ID, uint8_t* buffer){
     uint8_t* wrt_ptr;
     result_t result;
     wrt_ptr = TM_API_GetFlashWritePtr(ID,rec_size);
     if(wrt_ptr){
       //memcpy(wrt_ptr,buffer,16);
       TM_API_FlashWriteDone(ID); 
       result=SUCCESS;
       //call Leds.greenToggle();
     }
     else{
       result=!SUCCESS;
       //call Leds.greenToggle();
     }
     return signal FlashWrite.writeDone(result); 
  }

  command result_t FlashWrite.resetPointer(){
    curFlashWriteID = TM_FLASH_LAST_USER_ID - TM_FLASH_MAX_RECS;
    return SUCCESS;
  }
 
  command result_t FlashWrite.setPointer(uint16_t ID){
    curFlashReadID = ID;
  }

}

--- NEW FILE: FlashFS.h ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

/*
 * Defines and typedef's for inode structure
 */

#define MAX_NAME_LENGTH 10    // arbitrary; chosen to align to 16B
#define MAX_INODE 3           // making this larger breaks the assumption that
                              // all inodes are in the 0-page
#define ZERO_LEVEL_BLOCKS 4   // Number of direct block indexes contained in the
                              // inode
#define FIRST_LEVEL_BLOCKS 8  // Number of first level block indexes contained
                              // in the inode
#define FINODE_VALID 0xABCD

typedef struct {
  char       name[MAX_NAME_LENGTH];
  uint16     flags;
  uint32     fileSize;
  int16_t    dataBlock[ZERO_LEVEL_BLOCKS];
  int16_t    firstLevel[FIRST_LEVEL_BLOCKS];
} FInode;


--- NEW FILE: FlashFS.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

includes Flash;
includes FlashFS;

interface FlashFS {

  /*
   * Opens a file for reading or writing.  If the file does not exist and the
   * FFS_O_CREAT flag is set then a new file is created.  The return value is
   * a file descriptor used by the other file io functions or a -1 if there
   * was an error.
   */
  command int open(char *name, int flags);

  /*
   * Moves the read/ write pointer within a file.  The whence flag indicates
   * whether the new location is relative to the beginning, current location,
   * or end of the file.
   */
  command void lseek(int fd, int offset, int whence);

  /*
   * Copy the contents of the file to the buffer and advance the index pointer
   * by size.  The return value is the nuber of bytes read.
   */
  command int read (int fd, char *inbuf, int size);

  /*
   * Copy the contents fo the buffer to the file and advance the index pointer.
   * The return value is the number of bytes copied.
   */
  command int write (int fd, char *outbuf, int size);

  /* 
   * Close the file and commit all of the changes to flash.  The return value
   * is -1 if there was an error.
   */
  command int close (int fd);

  /*
   * Write the in-core contents of the file back to the storage device.
   */

  command int flush (int fd);

  /*
   * Release the storage associated with the file name.  The contents of the
   * file may not be 0'd out.  If an error occurs, -1 is returned.
   */

  command int delete (char *name);

  /*
   * Get a pointer to the inode data structure.  This should only be used to
   * display the contents of the structure.  Any modification of the structure
   * will result in unpredictable behavior.  The parameter next is an index
   * for the next value to return.  To start at the beginning, set next to 0.
   * When the last element is returned, next is set to -1.
   */

  command FInode *getInode(int *next);
}


--- NEW FILE: FlashFSC.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

configuration FlashFSC {
  provides {
    interface StdControl as FlashControl;
    interface FlashFS;
  }
}

implementation {
  components FlashFSM, HPLFlashM;

  FlashControl = FlashFSM;
  FlashFS = FlashFSM;

  FlashFSM.Flash -> HPLFlashM;
}

--- NEW FILE: FlashFSM.nc ---
/*
 * Copyright (c) 2004, Intel Corporation
 * 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 Intel Corporation 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.
 */

/*
 * This file system is loosely modeled after the unix file system with the
 * following paramters:
 *   Block size = 128B (page size == block size)
 *   i-node structure = 40B
 *   File i-nodes are limited to block 0
 *   Used page bitmask occupies block 1 => 128KB max
 *   i-node contains 4 direct block indexes
 *   i-node contains 8 1st level index blocks so max theoretical size =
 *       (4 + 8 * 64) * 128B ~= 66 KB
 *
 * No attempt is made to load balance the writes.
 */

module FlashFSM {

  provides {
    interface StdControl as Control;
    interface FlashFS;
  }

  uses {
    interface Flash;
  }    
}

implementation
{
  #define MAX_FD    3         // can't be larger than MAX_INODE
  #define MAX_BLOCKS 1024     // arbitrary
  #define INDEXES_PER_BLOCK (BLOCK_SIZE >> 1) // assume 2B per index

  // macros to generate the index of a block within the first and second level
  // tables
  #define FINDEX(block) (((block) - ZERO_LEVEL_BLOCKS) & (INDEXES_PER_BLOCK -1))
  #define SINDEX(block) (((block) - ZERO_LEVEL_BLOCKS) >> IndexBits)

  typedef struct fileDescriptor {
    uint32     inode;          // index into FInode structure
    uint32     fileOffset;     // current pointer offset into the file
    bool       valid;          // whether this fd is currently valid
    int        Mode;           // Current file access mode R, W, RW
    int        currentBlock;   // index of physical block of current pointer
                               // -1 if no blocks are open for writting
    char       *mptr;          // pointer to page currently open for writting
    int        fBlock;         // block id of the first level block open for
                               // writing; -1 if no blocks are open
    int16_t    *fptr;          // pointer to currently open first level index
                               // page
  } fileDescriptor;

  fileDescriptor fDesc[MAX_FD];// statically allocate space for the maximum
                               // number of files
  uint32  FlashBase;           // starting block id for lower level flash
                               // filesystem
  FInode  *inode;              // array pointer to the 0-page inode table
                               // When inode == NULL, there are no open files
  char    *usedPages;          // array pointer to the 1-page bit mask of 
                               // used blocks
  int     lastEmptyPage;       // index into usedPages array indicating where
                               // the last empty page came from.  This is just
                               // an optimization to accellerate finding the
                               // next empty page.
  int     BlockBits;           // optimization for manipulating offsets
  int     IndexBits;           // optimization for manipulating offsets

/*
 * Start of StdControl interface.
 */

  command result_t Control.init() {
    int i;

    inode = NULL;
    usedPages = NULL;
    lastEmptyPage = 0;

    for (i = 0; i < MAX_FD; i++) {
      fDesc[i].valid = FALSE;
      fDesc[i].currentBlock = -1;
      fDesc[i].mptr = NULL;
      fDesc[i].fBlock = -1;
      fDesc[i].fptr = NULL;
    }

    BlockBits = -1; for (i = BLOCK_SIZE; i != 0; i>>=1) BlockBits++;
    IndexBits = -1; for (i = INDEXES_PER_BLOCK; i != 0; i>>=1) IndexBits++;

    return SUCCESS;
  }



  command result_t Control.start() {
    // load the 0-page from flash by casting the inode array on top of it
    // this page stays open until the filesystem is stopped
    inode = (FInode *) call Flash.getWriteBlock(0);
    usedPages = (char *) call Flash.getWriteBlock(1);

    // mark first two pages as used for inode and used pages mask
    usedPages[0] = usedPages[0] | 0xC0;

    return SUCCESS;
  }



  command result_t Control.stop() {
    if (inode != NULL) {
      call Flash.commitBlock(0);
    }
    if (usedPages != NULL) {
      call Flash.commitBlock(1);
    }
  }

/*
 * End of StdControl interface.
 */



  /*
   * Look through the usedPages bitmask to find an unused page.  If one is found
   * mark it as used and return the physical block index.  If no empty pages are
   * found, return -1.
   */

  int AllocateEmptyBlock() {
    int i, j;

    for (i = 0; i < BLOCK_SIZE; i++) {
      if (usedPages[lastEmptyPage] != 0xff) {

        // find first empty bit corresponding to first unused block
        for (j = 0; j < 8; j++) {
          if ((usedPages[lastEmptyPage] & (0x80 >> j)) == 0) {

            // mark block as used and return index
            usedPages[lastEmptyPage] |= (0x80 >> j);
            return ((lastEmptyPage << 3) | j);
          }
        }
        // shouldn't get here
      }
      lastEmptyPage = (lastEmptyPage < (MAX_BLOCKS - 1)) ? lastEmptyPage+1 : 0;
    }

    // if flow gets to this point, there are no pages left
    return -1;
  }
  



  /*
   * Figure out which physical block contains the byte at <offset> in the
   * given inode.
   */

  int GetBlockIndex(int fd, int offset) {
    int     inumber;
    int     block;  // virtual block offset within this inode
    int     sindex;// virtual block offset within 1st level
    int     ind;    // physical block index of 1st level table
    int16_t *table; // pointer used to access blocks which contain block indexes

    inumber = fDesc[fd].inode;
    block = offset >> BlockBits;

    if (block < ZERO_LEVEL_BLOCKS) { 

      // block index is in the inode structure
      return (inode[inumber].dataBlock[block]);

    } else {

      // block index is accessed through first level index
      sindex = SINDEX(block);

      // if the requested block shares the same first level table as the current
      // block and that table is in core, use the cached version
      if ((inode[inumber].firstLevel[sindex] == fDesc[fd].fBlock) &&
          (fDesc[fd].fptr != NULL)) {
        table = fDesc[fd].fptr;
      } else {
        ind = inode[inumber].firstLevel[sindex];
        table = (int16_t *) call Flash.getReadBlock(ind);
      }
      return table[FINDEX(block)];

    }

    // shouldn't get here
    return -1;
  }



  /*
   * Allocate blocks and update the inode structure to a file size of offset.
   * Update file size.
   */

  result_t AppendBlocksToOffset (int fd, int offset) {
    int      curBlocks;  // current number of blocks in the file
    int      newBlocks;  // new number of blocks needed
    int      block;      // physical index of new block
    int      foffset;    // virtual block offset within 1st level array
    int      fInd;       // virtual block index in first level table
    int16_t  *fptr;      // pointer to first level index table
    int      inumber;
    int      tmp;
    char     *buf;

    inumber = fDesc[fd].inode;
    curBlocks = inode[inumber].fileSize >> BlockBits;
    newBlocks = offset >> BlockBits;

    fptr = fDesc[fd].fptr;
    while (curBlocks < newBlocks) {
      if ((block = AllocateEmptyBlock()) == -1) return FAIL; // should clean up?

      curBlocks++;
      if (curBlocks < ZERO_LEVEL_BLOCKS) {
        inode[inumber].dataBlock[curBlocks] = block;
      } else {
        foffset = (curBlocks - ZERO_LEVEL_BLOCKS) >> IndexBits;
        fInd = (curBlocks - ZERO_LEVEL_BLOCKS) & (INDEXES_PER_BLOCK - 1);
        if (fInd == 0) {
          // allocate 1st level page
          if ((inode[inumber].firstLevel[foffset]=AllocateEmptyBlock()) == -1) {
            return FAIL; // should clean up?
          }
          if (fptr != NULL) { // close previous page
            call Flash.commitBlock(inode[inumber].firstLevel[foffset - 1]);
            fptr = NULL;
          }
        }
        if (fptr == NULL) { // allocate page for writting
          tmp = inode[inumber].firstLevel[foffset];
          buf = call Flash.getWriteBlock(tmp);
          fptr = (int16_t *) buf;
          fDesc[fd].fptr = fptr;
          fDesc[fd].fBlock = tmp;
          if (fptr == NULL) {
            return FAIL;
          }
        }
        fptr[fInd] = block;
      }
      inode[inumber].fileSize = curBlocks << BlockBits;
    }

    // leave page open and cache pointer
/*    // close open pages
    if (fptr != NULL) {
      call Flash.commitBlock(inode[inumber].firstLevel[foffset]);
    }
*/

    if (inode[inumber].fileSize > offset) { // don't shrink the file
      inode[inumber].fileSize = offset;
    }

    return SUCCESS;
  }



  /*
   * Allocate an entry in the inode table and initialize the contents.
   * Return -1 if the entry could not be created.
   */

  int CreateInode(char *name) {
    int i, j, block;

    // find an empty inode and set the valid flag
    for (i = 0; i < MAX_INODE; i++) {
      if (inode[i].flags != FINODE_VALID) {
        // make sure there is at least one empty block before setting up inode
        if ((block = AllocateEmptyBlock()) == -1) {
          return -1;
        }

        strncpy (&(inode[i].name[0]), name, MAX_NAME_LENGTH);
        if (strlen(name) >= MAX_NAME_LENGTH) inode[i].name[MAX_NAME_LENGTH-1]=0;
        inode[i].flags = FINODE_VALID;
        inode[i].fileSize = 0;
        inode[i].dataBlock[0] = block;
        for (j = 1; j < ZERO_LEVEL_BLOCKS; j++) inode[i].dataBlock[j] = 0;
        for (j = 0; j < FIRST_LEVEL_BLOCKS; j++) inode[i].firstLevel[j] = 0;
        return i;
      }
    }
    return -1;
  }



  /*
   * Match string name to the file descriptor
   */
  int GetInode(char *name) {
    int i;

    for (i = 0; i < MAX_INODE; i++) {
      if (inode[i].flags == FINODE_VALID) {
        if (strcmp(name, inode[i].name) == 0) return i;
      }
    }

    return -1;   // not found
  }



  /*
   * Match string name to the file descriptor
   */
  int GetFileDescriptor(int inumber) {
    int i;

    for (i = 0; i < MAX_FD; i++) {
      if ((fDesc[i].valid == TRUE) && (fDesc[i].inode == inumber)) {
        return i;
      }
    }

    return -1;   // not found
  }



  /*
   * Return the lowest file descriptor which is not currently valid.  If all
   * of the file descriptors are taken, return -1.
   */
  int AllocateNewFileDescriptor(int inumber) {
    int i;

    for (i = 0; i < MAX_FD; i++) {
      if (fDesc[i].valid == FALSE) {
        fDesc[i].valid = TRUE;
        fDesc[i].currentBlock = -1;
        fDesc[i].mptr = NULL;
        fDesc[i].fBlock = -1;
        fDesc[i].fptr = NULL;
        return i;
      }
    }

    return -1;
  }



  int GetLowestFileDescriptor() {
    int i;

    for (i = 0; i < MAX_FD; i++) {
      if (fDesc[i].valid == FALSE) return i;
    }

    return -1;
  }



  /*
   * Start of FlashFS interface.
   */


  bool ValidFD(int fd) {
    return ((fd >= 0) && (fd < MAX_FD) && (fDesc[fd].valid == TRUE));
  }


  /*
   * Opens a file for reading or writing.  If the file does not exist and the
   * FFS_CREAT flag is set then a new file is created.  The return value is
   * a file descriptor used by the other file io functions or a -1 if there
   * was an error.
   */

  command int FlashFS.open(char *name, int flags) {
    int inumber; // inode index associated with name
    int fd;      // file descriptor associated with name

    // make sure the inode page is in core
    if (inode == NULL) {
      inode = (FInode *) call Flash.getWriteBlock(0);
      usedPages = (char *) call Flash.getWriteBlock(1);
    }

    inumber = GetInode(name);
    if ((inumber == -1) && (flags & FFS_O_CREAT)) {
      inumber = CreateInode(name);
    }
    if (inumber == -1) {
      return -1;  // file doesn't exist and we didn't create it
    }

    // If file is already open make sure that that access modes match.
    // The file must be closed and reopened to change the access mode.
    fd = GetFileDescriptor(inumber);
    if ((fd != -1) && (fDesc[fd].Mode != (flags & 0x3))) {
      return -1;
    }

    if (fd == -1) { // try to open the file
      if ((fd = AllocateNewFileDescriptor(inumber)) == -1) return -1;
      fDesc[fd].Mode = flags & 0x03;
      if ((flags & FFS_O_APPEND) && (flags & (FFS_O_WRONLY | FFS_O_RDWR))) {
        fDesc[fd].fileOffset = inode[inumber].fileSize;
      } else {
        fDesc[fd].fileOffset = 0;
      }
      fDesc[fd].inode = inumber;
    }

    // if the current access mode is write enabled, load the current page
    if (flags & (FFS_O_WRONLY | FFS_O_RDWR)) {
      fDesc[fd].currentBlock =
        GetBlockIndex(fd, fDesc[fd].fileOffset);
      fDesc[fd].mptr = call Flash.getWriteBlock(fDesc[fd].currentBlock);
      if ((fDesc[fd].fileOffset >> BlockBits) >= ZERO_LEVEL_BLOCKS) {
        fDesc[fd].fBlock = inode[inumber].firstLevel[SINDEX(fDesc[fd].fileOffset >> BlockBits)];
        fDesc[fd].fptr = call Flash.getWriteBlock(fDesc[fd].fBlock);
      }
    }

    return (fd);
  }



  /*
   * Moves the read/ write pointer within a file.  The whence flag indicates
   * whether the new location is relative to the beginning, current location,
   * or end of the file.
   */
  command void FlashFS.lseek(int fd, int offset, int whence) {
    int curOffset, newOffset, curSize;
    int oldFL, newFL;

    // verify that file descriptor is valid 
    if (ValidFD(fd) == FALSE) return;

    curOffset = fDesc[fd].fileOffset;
    curSize = inode[fDesc[fd].inode].fileSize;
    if (whence == FFS_SEEK_SET) {
      newOffset = offset;
    } else if (whence == FFS_SEEK_CUR) {
      newOffset = curOffset + offset;
    } else if (whence == FFS_SEEK_END) {
      newOffset = curSize + offset;
    }

    // if we've scanned past the last block of the file, allocate more blocks
    if (newOffset > curSize) {
      if (AppendBlocksToOffset (fd, newOffset) == FAIL) {
        return;
      };
    }

    // if the file is write enable and the seek enters a new block, close the
    // old one and open the new one for writting
    if ((fDesc[fd].currentBlock != -1) &&
        (fDesc[fd].Mode & (FFS_O_WRONLY | FFS_O_RDWR))) {
      if ((curOffset >> BlockBits) != (newOffset >> BlockBits)) {
        call Flash.commitBlock(fDesc[fd].currentBlock);
        fDesc[fd].currentBlock = GetBlockIndex(fd, newOffset);
        fDesc[fd].mptr = call Flash.getWriteBlock(fDesc[fd].currentBlock);

        // If the seek enters a block indexed by a different first level entry
        // then close the old entry and open the new one
        oldFL = ((fDesc[fd].fileOffset >> BlockBits) - ZERO_LEVEL_BLOCKS)
                >> IndexBits;
        newFL = ((newOffset >> BlockBits) - ZERO_LEVEL_BLOCKS) >> IndexBits;
        if (oldFL != newFL) {
          call Flash.commitBlock(oldFL);
          fDesc[fd].fptr = (int16_t *) call Flash.getWriteBlock(newFL);
        }
      }
    }

    fDesc[fd].fileOffset = newOffset;
    return;
  }



  /*
   * Copy the contents of the file to the buffer and advance the index pointer
   * by size.  The return value is the nuber of bytes read.
   */
  command int FlashFS.read (int fd, char *inbuf, int size) {
    int    i;
    int    block;         // physical block index of the current block
    int    offset;
    int    fileSize;
    char   *fbuf;
    int    oldFL, newFL;

    // verify that file descriptor is valid 
    if (ValidFD(fd) == FALSE) return 0;

    // verify access mode
    if ((fDesc[fd].Mode != FFS_O_RDONLY) && (fDesc[fd].Mode != FFS_O_RDWR)) {
      return 0;
    }

    offset = fDesc[fd].fileOffset;
    fileSize = inode[fDesc[fd].inode].fileSize;
    block = GetBlockIndex(fd, offset);
    fbuf = call Flash.getReadBlock(block);

    for (i = 0; (i < size) && ((offset + i) < fileSize); i++) {
       if (((offset + i) & (BLOCK_SIZE - 1)) == 0) {
         block = GetBlockIndex(fd, offset + i);
         fbuf = call Flash.getReadBlock(block);
       }
       ((char *)inbuf)[i] = fbuf[(offset + i) & (BLOCK_SIZE - 1)];

    }

    // if the current access mode is read/ write and we've entered a new block,
    // close the old block and open the new block for writing
    if ((fDesc[fd].currentBlock != -1) && (fDesc[fd].Mode & FFS_O_RDWR)) {
      if ((fDesc[fd].fileOffset >> BlockBits) !=
          ((fDesc[fd].fileOffset + i) >> BlockBits)) {
        call Flash.commitBlock(fDesc[fd].currentBlock);
        fDesc[fd].currentBlock =
          GetBlockIndex(fd, fDesc[fd].fileOffset + i);
        fDesc[fd].mptr = call Flash.getWriteBlock(fDesc[fd].currentBlock);

        // If the seek enters a block indexed by a different first level entry
        // then close the old entry and open the new one
        oldFL = ((offset >> BlockBits) - ZERO_LEVEL_BLOCKS) >> IndexBits;
        newFL = (((offset + i) >> BlockBits) - ZERO_LEVEL_BLOCKS) >> IndexBits;
        if (oldFL != newFL) {
          call Flash.commitBlock(oldFL);
          fDesc[fd].fptr = (int16_t *) call Flash.getWriteBlock(newFL);
        }
      }
    }

    fDesc[fd].fileOffset += i;

    return (i);
  }

      

  /*
   * Copy the contents of the buffer to the file and advance the index pointer.
   * The return value is the number of bytes copied.
   */
  command int FlashFS.write (int fd, char *outbuf, int size) {
    int    i;
    int    block;         // physical block index of the current block
    int    offset;
    int    fileSize;
    char   *bufptr;

    // verify that file descriptor is valid 
    if (ValidFD(fd) == FALSE) return 0;

    // verify acces mode
    if ((fDesc[fd].Mode != FFS_O_WRONLY) && (fDesc[fd].Mode != FFS_O_RDWR)) {
      return 0;
    }

    offset = fDesc[fd].fileOffset;
    fileSize = inode[fDesc[fd].inode].fileSize;
    block = fDesc[fd].currentBlock;
    bufptr = fDesc[fd].mptr;

    // make sure there is enough space to write
    if ((offset + size) > fileSize) {   
      if (AppendBlocksToOffset (fd, offset + size) == FAIL) {
        return 0;
      }
    }

    for (i = 0; i < size; i++) {
      if (((offset + i) & (BLOCK_SIZE - 1)) == 0) {
        if (block != -1) {
          call Flash.commitBlock(block);
        }
        block = GetBlockIndex(fd, offset + i);
        bufptr = call Flash.getWriteBlock(block);
      }
      bufptr[(offset + i) & (BLOCK_SIZE - 1)] = ((char *)outbuf)[i];
    }

    fDesc[fd].fileOffset += i;
    if (fDesc[fd].fileOffset > inode[fDesc[fd].inode].fileSize) {
      inode[fDesc[fd].inode].fileSize = fDesc[fd].fileOffset;
    }
    fDesc[fd].currentBlock = block;
    fDesc[fd].mptr = bufptr;

    return (i);
  }



  /*
   * Test whether there are any open file descriptors.  If there are not, write
   * the 0-page and 1-page back to flash.
   */
  void TestAndFlushInodes() {
    int i;

    for (i = 0; i < MAX_FD; i++) {
      if (fDesc[i].valid == TRUE) return;
    }

/* leave them open for testing
    call Flash.commitBlock(0);
    call Flash.commitBlock(1);
    inode = NULL;
    usedPages = NULL;
*/
  }



  /* 
   * Close the file and commit all of the changes to flash.  The return value
   * is -1 if there was an error.
   */
  command int FlashFS.close (int fd) {
    if (ValidFD(fd) == FALSE) return -1;

    if (fDesc[fd].currentBlock != -1) {
      call Flash.commitBlock(fDesc[fd].currentBlock);
      fDesc[fd].mptr = NULL;
    }
    if (fDesc[fd].fBlock != -1) {
      call Flash.commitBlock(fDesc[fd].fBlock);
      fDesc[fd].fptr = NULL;
    }

    fDesc[fd].valid = FALSE;

    TestAndFlushInodes();

    return 0;
  }



  /*
   * Write the in-core contents of the file back to the storage device
   * and leave the block open for writing.
   */

  command int FlashFS.flush (int fd) {
    int block, i;

    // flush all files to avoid inode synchronization issues

    if (ValidFD(fd) == FALSE) return -1;

    for (i = 0; i < MAX_FD; i++) {
      if ((block = fDesc[i].currentBlock) != -1) {
        call Flash.commitBlock(block);
        fDesc[i].mptr = (char *)call Flash.getWriteBlock(block);
      }
      if ((block = fDesc[i].fBlock) != -1) {
        call Flash.commitBlock(block);
        fDesc[i].fptr =