[Tinyos-2-commits] CVS: tinyos-2.x/tos/lib/net/Deluge AutoStarterC.nc, NONE, 1.1 AutoStarterP.nc, NONE, 1.1 BitVecUtils.h, NONE, 1.1 BitVecUtils.nc, NONE, 1.1 BitVecUtilsC.nc, NONE, 1.1 Crc.nc, NONE, 1.1 CrcP.nc, NONE, 1.1 Deluge.h, NONE, 1.1 DelugeC.nc, NONE, 1.1 DelugeMetadata.h, NONE, 1.1 DelugeMetadata.nc, NONE, 1.1 DelugeMsgs.h, NONE, 1.1 DelugeP.nc, NONE, 1.1 DelugePageTransfer.h, NONE, 1.1 DelugePageTransfer.nc, NONE, 1.1 DelugePageTransferC.nc, NONE, 1.1 DelugePageTransferP.nc, NONE, 1.1 DelugeStorageC.nc, NONE, 1.1 DelugeStorageP.nc, NONE, 1.1 FakeBlockReaderC.nc, NONE, 1.1 FakeBlockWriterC.nc, NONE, 1.1 FakeBlockWriterP.nc, NONE, 1.1 Globals.nc, NONE, 1.1 GlobalsC.nc, NONE, 1.1 ObjectTransfer.nc, NONE, 1.1 ObjectTransferC.nc, NONE, 1.1 ObjectTransferP.nc, NONE, 1.1 SerialStarterC.nc, NONE, 1.1 StatsCollector.nc, NONE, 1.1 StatsCollectorC.nc, NONE, 1.1 StatsCollectorP.nc, NONE, 1.1

Razvan Musaloiu-E. razvanm at users.sourceforge.net
Tue May 22 13:34:25 PDT 2007


Update of /cvsroot/tinyos/tinyos-2.x/tos/lib/net/Deluge
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv24715/tos/lib/net/Deluge

Added Files:
	AutoStarterC.nc AutoStarterP.nc BitVecUtils.h BitVecUtils.nc 
	BitVecUtilsC.nc Crc.nc CrcP.nc Deluge.h DelugeC.nc 
	DelugeMetadata.h DelugeMetadata.nc DelugeMsgs.h DelugeP.nc 
	DelugePageTransfer.h DelugePageTransfer.nc 
	DelugePageTransferC.nc DelugePageTransferP.nc 
	DelugeStorageC.nc DelugeStorageP.nc FakeBlockReaderC.nc 
	FakeBlockWriterC.nc FakeBlockWriterP.nc Globals.nc GlobalsC.nc 
	ObjectTransfer.nc ObjectTransferC.nc ObjectTransferP.nc 
	SerialStarterC.nc StatsCollector.nc StatsCollectorC.nc 
	StatsCollectorP.nc 
Log Message:
Initial commit of the Deluge T2. Some notes:
- TOSBoot includes some code to allow the MicaZ version to compile but it's not support for it it's not done yet.
- tools/tinyos/misc/Makefile.am is not updated yet so the new tools will not be installed by default.


--- NEW FILE: AutoStarterC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

configuration AutoStarterC
{
  uses interface SplitControl;
}

implementation
{
  components MainC, AutoStarterP;
  
  SplitControl = AutoStarterP;
  AutoStarterP.Boot -> MainC;
}

--- NEW FILE: AutoStarterP.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

module AutoStarterP
{
  uses {
    interface Boot;
    interface SplitControl;
  }
}

implementation
{
  event void Boot.booted()
  {
    call SplitControl.start();
  }
  
  event void SplitControl.startDone(error_t error) { }
  event void SplitControl.stopDone(error_t error) { }

}

--- NEW FILE: BitVecUtils.h ---
/*
 * "Copyright (c) 2000-2004 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."
 */

/**
 * Provides generic methods for manipulating bit vectors.
 *
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

#ifndef __BITVEC_UTILS_H__
#define __BITVEC_UTILS_H__

#define BIT_GET(x, i) ((x) & (1 << (i)))
#define BIT_SET(x, i) ((x) | (1 << (i)))
#define BIT_CLEAR(x, i) ((x) & ~(1 << (i)))

#define BITVEC_GET(x, i) (BIT_GET((x)[(i)/8], (i)%8))
#define BITVEC_SET(x, i) ((x)[(i)/8] = BIT_SET((x)[(i)/8], (i)%8))
#define BITVEC_CLEAR(x, i) ((x)[(i)/8] = BIT_CLEAR((x)[(i)/8], (i)%8))

#endif

--- NEW FILE: BitVecUtils.nc ---
/*
 * "Copyright (c) 2000-2004 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."
 */

/**
 * Provides generic methods for manipulating bit vectors.
 *
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

interface BitVecUtils {
  /**
   * Locates the index of the first '1' bit in a bit vector.
   *
   * @param result     the location of the '1' bit
   * @param fromIndex  the index to start search for '1' bit
   * @param bitVec     the bit vector
   * @param length     the length of the bit vector in bits
   * @return           <code>SUCCESS</code> if a '1' bit was found;
   *                   <code>FAIL</code> otherwise.
   */
  command error_t indexOf(uint16_t* pResult, uint16_t fromIndex, 
			   uint8_t* bitVec, uint16_t length);

  /**
   * Counts the number of '1' bits in a bit vector.
   *
   * @param result  the number of '1' bits
   * @param bitVec  the bit vector
   * @param length  the length of the bit vector in bits
   * @return        <code>SUCCESS</code> if the operation completed successfully;
   *                <code>FAIL</code> otherwise.
   */
  command error_t countOnes(uint16_t* pResult, uint8_t* bitVec, 
			     uint16_t length);

  /**
   * Generates an ASCII representation of the bit vector.
   *
   * @param buf     the character array to place the ASCII string
   * @param bitVec  the bit vector
   * @param length  the length of the bit vector in bits
   */
  command void printBitVec(char* buf, uint8_t* bitVec, uint16_t length);
}

--- NEW FILE: BitVecUtilsC.nc ---
/*
 * "Copyright (c) 2000-2004 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."
 */

/**
 * Provides generic methods for manipulating bit vectors.
 *
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

#include "BitVecUtils.h"

module BitVecUtilsC {
  provides interface BitVecUtils;
}

implementation {
  command error_t BitVecUtils.indexOf(uint16_t* pResult, uint16_t fromIndex, 
				                               uint8_t* bitVec, uint16_t length) {
    uint16_t i = fromIndex;

    if (length == 0)
      return FAIL;
    
    do {
      if (BITVEC_GET(bitVec, i)) {
        *pResult = i;
        return SUCCESS;
      }
      i = (i+1) % length;
    } while (i != fromIndex);
    
    return FAIL;
  }

  command error_t BitVecUtils.countOnes(uint16_t* pResult, uint8_t* bitVec, uint16_t length) {

    int count = 0;
    int i;

    for ( i = 0; i < length; i++ ) {
      if (BITVEC_GET(bitVec, i))
	count++;
    }

    *pResult = count;

    return SUCCESS;

  }

  command void BitVecUtils.printBitVec(char* buf, uint8_t* bitVec, uint16_t length) {
#ifdef PLATFORM_PC
    uint16_t i;
    
    dbg(DBG_TEMP, "");
    for ( i = 0; i < length; i++ ) {
      sprintf(buf++, "%d", !!BITVEC_GET(bitVec, i));
    }
#endif	  
  }

}

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

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

interface Crc
{
  command uint16_t crc16(void* buf, uint8_t len);
}

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

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

#include "crc.h"

module CrcP
{
  provides interface Crc;
}

implementation
{
  // From T1 "tos/system/CrcC.nc"
  command uint16_t Crc.crc16(void* buf, uint8_t len)
  {
    uint8_t* tmpBuf = (uint8_t*)buf;
    uint16_t crc;
    
    for (crc = 0; len > 0; len--) {
      crc = crcByte(crc, *tmpBuf);   // Calculates running CRC
      tmpBuf++;
    }
    
    return crc;
  }
}

--- NEW FILE: Deluge.h ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#ifndef __DELUGE_H__
#define __DELUGE_H__

#include "DelugeMetadata.h"

enum {
  DELUGE_INVALID_UID = 0xffffffff,
  DELUGE_NUM_VOLUMES = 2,
};

typedef nx_struct DelugeDissemination {
  nx_uint32_t uid;      // unique id of image
  nx_uint16_t vNum;     // version num of image
  nx_uint8_t  imgNum;   // image number
  nx_uint16_t size;     // size of the image
} DelugeDissemination;

typedef struct DelugeNodeDesc {
  imgvnum_t vNum;
  uint32_t  uid;
  imgnum_t  imgNum;
  uint8_t   reserved;
  uint16_t  crc;
} DelugeNodeDesc;

#endif

--- NEW FILE: DelugeC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "Deluge.h"

configuration DelugeC {}

implementation
{
  components DelugeStorageC;

#ifdef DELUGE_BASESTATION
  components SerialStarterC;
  components new FlashVolumeManagerC(0xAB);

  DelugeP.ReprogNotify -> FlashVolumeManagerC;
  FlashVolumeManagerC.BlockRead[0] -> DelugeStorageC.BlockRead[0];
  FlashVolumeManagerC.BlockWrite[0] -> DelugeStorageC.BlockWrite[0];
  FlashVolumeManagerC.StorageMap[0] -> DelugeStorageC.StorageMap[0];
  FlashVolumeManagerC.BlockRead[1] -> DelugeStorageC.BlockRead[1];
  FlashVolumeManagerC.BlockWrite[1] -> DelugeStorageC.BlockWrite[1];
  FlashVolumeManagerC.StorageMap[1] -> DelugeStorageC.StorageMap[1];
#endif
  
  components ObjectTransferC;
  ObjectTransferC.BlockRead[0] -> DelugeStorageC.BlockRead[0];
  ObjectTransferC.BlockWrite[0] -> DelugeStorageC.BlockWrite[0];
  ObjectTransferC.BlockRead[1] -> DelugeStorageC.BlockRead[1];
  ObjectTransferC.BlockWrite[1] -> DelugeStorageC.BlockWrite[1];
  
  components new DisseminatorC(DelugeDissemination, 0xDE00), DisseminationC;
  components ActiveMessageC;
  components NetProgC, DelugeP;
  components new TimerMilliC() as Timer;
  components LedsC, NoLedsC;
  DelugeP.Leds -> LedsC;  
  DelugeP.DisseminationValue -> DisseminatorC;
  DelugeP.DisseminationUpdate -> DisseminatorC;
  DelugeP.StdControlDissemination -> DisseminationC;
  DelugeP.ObjectTransfer -> ObjectTransferC;
  DelugeP.NetProg -> NetProgC;
  DelugeP.StorageReadyNotify -> DelugeStorageC;
  DelugeP.DelugeMetadata -> DelugeStorageC;
  DelugeP.RadioSplitControl -> ActiveMessageC;
  
  components InternalFlashC as IFlash;
  DelugeP.IFlash -> IFlash;
}

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

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

#ifndef __DELUGE_METADATA_H__
#define __DELUGE_METADATA_H__

#define DELUGE_METADATA_SIZE 16

typedef int16_t imgvnum_t;
typedef uint8_t  imgnum_t;
typedef uint8_t   pgnum_t;

typedef struct DelugeImgDesc {
  uint32_t  uid;            // unique id of image
  imgvnum_t vNum;           // version num of image
  imgnum_t  imgNum;         // image number
  pgnum_t   numPgs;         // num pages of complete image
  uint16_t  crc;            // crc for vNum and numPgs
  uint8_t   numPgsComplete; // numPgsComplete in image
  uint8_t   reserved;
  uint16_t  size;           // size of the whole image (metadata + CRCs + ident + binary)
} DelugeImgDesc;

#endif

--- NEW FILE: DelugeMetadata.nc ---
/*
 * "Copyright (c) 2000-2004 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) 2007 Johns Hopkins University.
 * All rights reserved.
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

interface DelugeMetadata {
  command DelugeImgDesc* getImgDesc(imgnum_t imgNum);
}

--- NEW FILE: DelugeMsgs.h ---
/*
 * "Copyright (c) 2000-2004 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) 2007 Johns Hopkins University.
 * All rights reserved.
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#ifndef __DELUGE_MSGS_H__
#define __DELUGE_MSGS_H__

#include "DelugePageTransfer.h"

enum {
  DELUGE_ADV_NORMAL = 0,
  DELUGE_ADV_ERROR  = 1,
  DELUGE_ADV_PC     = 2,
  DELUGE_ADV_PING   = 3,
  DELUGE_ADV_RESET  = 4,
};

typedef nx_struct DelugeAdvMsg {
  nx_uint16_t       sourceAddr;
  nx_uint8_t        version;    // Deluge Version
  nx_uint8_t        type;
  //DelugeNodeDesc nodeDesc;
  DelugeObjDesc  objDesc;
  nx_uint8_t        reserved;
} DelugeAdvMsg;

typedef nx_struct DelugeReqMsg {
  nx_uint16_t     dest;
  nx_uint16_t     sourceAddr;
  nx_object_id_t  objid;
  nx_page_num_t   pgNum;
  nx_uint8_t      requestedPkts[DELUGE_PKT_BITVEC_SIZE];
} DelugeReqMsg;

typedef nx_struct DelugeDataMsg {
  nx_object_id_t objid;
  nx_page_num_t pgNum;
  nx_uint8_t    pktNum;
  nx_uint8_t    data[DELUGE_PKT_PAYLOAD_SIZE];
} DelugeDataMsg;

#endif

--- NEW FILE: DelugeP.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

module DelugeP
{
  uses {
    interface Leds;
    interface Notify<uint8_t> as StorageReadyNotify;
    interface DisseminationUpdate<DelugeDissemination>;
    interface DisseminationValue<DelugeDissemination>;
    interface StdControl as StdControlDissemination;
    interface DelugeMetadata;
    interface ObjectTransfer;
    interface NetProg;
    interface InternalFlash as IFlash;
    interface SplitControl as RadioSplitControl;
    
#ifdef DELUGE_BASESTATION
    interface Notify<uint8_t> as ReprogNotify;
#endif
  }
}

implementation
{
  uint8_t img_num;
  
  /**
   * Starts the radio
   */
  event void StorageReadyNotify.notify(uint8_t val)
  {
    call RadioSplitControl.start();
  }

#ifdef DELUGE_BASESTATION
  /**
   * Starts disseminating image information
   */
  event void ReprogNotify.notify(uint8_t new_img_num)
  {
    DelugeDissemination delugeDis;
    DelugeImgDesc *imgDesc;
    
    imgDesc = call DelugeMetadata.getImgDesc(new_img_num);
    if (imgDesc->uid != DELUGE_INVALID_UID) {
      call ObjectTransfer.stop();
      call Leds.led0Toggle();
      img_num = new_img_num;
      
      delugeDis.uid = imgDesc->uid;
      delugeDis.vNum = imgDesc->vNum;
      delugeDis.imgNum = imgDesc->imgNum;
      delugeDis.size = imgDesc->size;
      
      call DisseminationUpdate.change(&delugeDis);   // Disseminates image information
      call ObjectTransfer.publish(delugeDis.uid,
                                  delugeDis.size,
                                  delugeDis.imgNum);   // Prepares to publish image data
    }
  }
#endif

  /**
   * Receives a disseminated message. If the message contains information about a
   * newer image, then we should grab this image from the network
   */
  event void DisseminationValue.changed()
  {
    const DelugeDissemination *delugeDis = call DisseminationValue.get();
    DelugeImgDesc *imgDesc = call DelugeMetadata.getImgDesc(delugeDis->imgNum);
    
    if (imgDesc->uid == delugeDis->uid) {
      if (imgDesc->vNum < delugeDis->vNum) {
        img_num = delugeDis->imgNum;   // Note which image number to boot
        call ObjectTransfer.receive(delugeDis->uid, delugeDis->size, delugeDis->imgNum);
      }
    } else {
      img_num = delugeDis->imgNum;   // Note which image number to boot
      call ObjectTransfer.receive(delugeDis->uid, delugeDis->size, delugeDis->imgNum);
    }
  }

  /**
   * Reboots and reprograms with the newly received image
   */
  event void ObjectTransfer.receiveDone(error_t error)
  {
    call ObjectTransfer.stop();
    if (error == SUCCESS) {
      call NetProg.programImgAndReboot(img_num);
    }
  }

  /**
   * Prepares to publish the image that was just reprogrammed
   */
  event void RadioSplitControl.startDone(error_t error)
  {
    if (error == SUCCESS) {
      // Start publishing the current image
      DelugeImgDesc *imgDesc;
      DelugeNodeDesc nodeDesc;
      call IFlash.read((uint8_t*)IFLASH_NODE_DESC_ADDR,
                       &nodeDesc,
                       sizeof(DelugeNodeDesc));   // Reads which image was just reprogrammed
      imgDesc = call DelugeMetadata.getImgDesc(nodeDesc.imgNum);
      if (nodeDesc.uid == imgDesc->uid && imgDesc->uid != DELUGE_INVALID_UID) {
        call ObjectTransfer.publish(imgDesc->uid, imgDesc->size, imgDesc->imgNum);
      }
            
      call StdControlDissemination.start();
    }
  }
  
  event void RadioSplitControl.stopDone(error_t error) {}
}

--- NEW FILE: DelugePageTransfer.h ---
/*
 * "Copyright (c) 2000-2004 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) 2007 Johns Hopkins University.
 * All rights reserved.
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#ifndef DELUGEPAGETRANSFER_H
#define DELUGEPAGETRANSFER_H

#include "extra/telosb/TOSBoot_platform.h"

#define AM_DELUGEADVMSG  161
#define AM_DELUGEREQMSG  162
#define AM_DELUGEDATAMSG 163

typedef int32_t object_id_t;
typedef nx_int32_t nx_object_id_t;
typedef uint32_t object_size_t;
typedef nx_uint32_t nx_object_size_t;
typedef uint8_t page_num_t;
typedef nx_uint8_t nx_page_num_t;

enum {
//  DELUGE_PKTS_PER_PAGE    = 48,
//  DELUGE_PKT_PAYLOAD_SIZE = 23,
//  DELUGE_BYTES_PER_PAGE   = (DELUGE_PKTS_PER_PAGE * DELUGE_PKT_PAYLOAD_SIZE),
  DELUGE_PKT_PAYLOAD_SIZE  = TOSH_DATA_LENGTH - sizeof(nx_object_id_t) - sizeof(nx_page_num_t) - sizeof(nx_uint8_t),
  DELUGE_BYTES_PER_PAGE    = 1024,
  DELUGE_PKTS_PER_PAGE     = ((DELUGE_BYTES_PER_PAGE - 1) / DELUGE_PKT_PAYLOAD_SIZE) + 1,
  
  DELUGE_VERSION                    = 2,
  DELUGE_MAX_ADV_PERIOD_LOG2        = 22,
  DELUGE_NUM_NEWDATA_ADVS_REQUIRED  = 2,
  DELUGE_NUM_MIN_ADV_PERIODS        = 2,
  DELUGE_MAX_NUM_REQ_TRIES          = 1,
  DELUGE_REBOOT_DELAY               = 4,
  DELUGE_FAILED_SEND_DELAY          = 16,
  DELUGE_MIN_DELAY                  = 16,
  DELUGE_DATA_OFFSET                = 128,
  DELUGE_IDENT_SIZE                 = 128,
  DELUGE_INVALID_ADDR               = (0x7fffffffL),
  DELUGE_MAX_REQ_DELAY              = (0x1L << (DELUGE_MIN_ADV_PERIOD_LOG2 - 1)),
  DELUGE_NACK_TIMEOUT               = (DELUGE_MAX_REQ_DELAY >> 0x1),
  DELUGE_PKT_BITVEC_SIZE            = (((DELUGE_PKTS_PER_PAGE - 1) / 8) + 1),
  DELUGE_MAX_IMAGE_SIZE             = (128L * 1024L),
  DELUGE_MAX_PAGES                  = 128,
  DELUGE_CRC_SIZE                   = sizeof(uint16_t),
  DELUGE_CRC_BLOCK_SIZE             = DELUGE_MAX_PAGES * DELUGE_CRC_SIZE,
  DELUGE_GOLDEN_IMAGE_NUM           = 0x0,
  DELUGE_INVALID_OBJID              = 0xff,
  DELUGE_INVALID_PKTNUM             = 0xff,
  DELUGE_INVALID_PGNUM              = 0xff,
  
  // From "DelugeMetadata.h"
};

typedef struct DelugeAdvTimer {
  uint32_t timer      : 32;
  uint8_t  periodLog2 : 8;
  bool     overheard  : 1;
  uint8_t  newAdvs    : 7;
} DelugeAdvTimer;

typedef nx_struct DelugeObjDesc {
  nx_object_id_t objid;
  nx_page_num_t  numPgs;         // num pages of complete image
  nx_uint16_t    crc;            // crc for vNum and numPgs
  nx_page_num_t  numPgsComplete; // numPgsComplete in image
  nx_uint8_t     reserved;
} DelugeObjDesc;

#endif

--- NEW FILE: DelugePageTransfer.nc ---
/*
 * "Copyright (c) 2000-2004 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) 2007 Johns Hopkins University.
 * All rights reserved.
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "DelugePageTransfer.h"

interface DelugePageTransfer {
  command error_t setWorkingPage(object_id_t new_objid, page_num_t new_pgNum);
  command error_t dataAvailable(uint16_t sourceAddr);
  command bool isTransferring();
  event void suppressMsgs(object_id_t new_objid);
  event void receivedPage(object_id_t new_objid, page_num_t new_pgNum);
  command void setImgNum(uint8_t new_img_num);
  
  command error_t stop();
}

--- NEW FILE: DelugePageTransferC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

configuration DelugePageTransferC
{
  provides interface DelugePageTransfer;
  uses {
    interface BlockRead[uint8_t img_num];
    interface BlockWrite[uint8_t img_num];
    
    interface Receive as ReceiveDataMsg;
    interface Receive as ReceiveReqMsg;
    interface AMSend as SendDataMsg;
    interface AMSend as SendReqMsg;
    interface AMPacket;
    interface PacketAcknowledgements;
  }
}

implementation
{
  components DelugePageTransferP;
  
  DelugePageTransfer = DelugePageTransferP;
  BlockRead[0] = DelugePageTransferP.BlockRead[0];
  BlockWrite[0] = DelugePageTransferP.BlockWrite[0];
  BlockRead[1] = DelugePageTransferP.BlockRead[1];
  BlockWrite[1] = DelugePageTransferP.BlockWrite[1];
  
  ReceiveDataMsg = DelugePageTransferP.ReceiveDataMsg;
  ReceiveReqMsg = DelugePageTransferP.ReceiveReqMsg;
  SendDataMsg = DelugePageTransferP.SendDataMsg;
  SendReqMsg = DelugePageTransferP.SendReqMsg;
  
  AMPacket = DelugePageTransferP.AMPacket;
  PacketAcknowledgements = DelugePageTransferP.PacketAcknowledgements;
  
  components RandomC, BitVecUtilsC, new TimerMilliC() as Timer;
  DelugePageTransferP.Random -> RandomC;
  DelugePageTransferP.Timer -> Timer;
  DelugePageTransferP.BitVecUtils -> BitVecUtilsC;
  
  components NoLedsC, LedsC;
  DelugePageTransferP.Leds -> LedsC;
  
  // For collecting statistics
  //components StatsCollectorC;
  //DelugePageTransferP.StatsCollector -> StatsCollectorC.StatsCollector;
}

--- NEW FILE: DelugePageTransferP.nc ---
/*
 * "Copyright (c) 2000-2004 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) 2007 Johns Hopkins University.
 * All rights reserved.
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "DelugeMsgs.h"
#include "BitVecUtils.h"

module DelugePageTransferP
{
  provides interface DelugePageTransfer;
  uses {
    interface BitVecUtils;
    interface BlockRead[uint8_t img_num];
    interface BlockWrite[uint8_t img_num];
    
    interface Receive as ReceiveDataMsg;
    interface Receive as ReceiveReqMsg;
    interface AMSend as SendDataMsg;
    interface AMSend as SendReqMsg;
    interface AMPacket;
    interface PacketAcknowledgements;
    interface Timer<TMilli> as Timer;
    interface Random;
    
    interface Leds;
    //interface StatsCollector;
  }
}

implementation
{
  // send/receive page buffers, and state variables for buffers
  uint8_t pktsToSend[DELUGE_PKT_BITVEC_SIZE];    // bit vec of packets to send
  uint8_t pktsToReceive[DELUGE_PKT_BITVEC_SIZE]; // bit vec of packets to receive

  DelugeDataMsg rxQueue[DELUGE_QSIZE];
  uint8_t       head, size;

  enum {
    S_DISABLED,
    S_IDLE,     
    S_TX_LOCKING,
    S_SENDING,
    S_RX_LOCKING,
    S_RECEIVING,
  };
  
  // state variables
  uint8_t      state        = S_DISABLED;
  uint16_t     nodeAddr;
  uint8_t      remainingAttempts;
  bool         suppressReq;
  object_id_t  objToSend    = DELUGE_INVALID_OBJID;
  page_num_t   pageToSend   = DELUGE_INVALID_PGNUM;
  object_id_t  workingObjid = DELUGE_INVALID_OBJID;
  page_num_t   workingPgNum = DELUGE_INVALID_PGNUM;
  uint8_t      imgNum       = 0;
  
  message_t pMsgBuf;
  bool      isBusy_pMsgBuf = FALSE;
  uint8_t   publisher_addr;   // For collecting stats only
  
  void changeState(uint8_t newState);
  
  void startReqTimer(bool first)
  {
    uint32_t delay;
    if (first) {
      delay = DELUGE_MIN_DELAY + (call Random.rand32() % DELUGE_MAX_REQ_DELAY);
    } else {
      delay = DELUGE_NACK_TIMEOUT + (call Random.rand32() % DELUGE_NACK_TIMEOUT);
    }
    call Timer.startOneShot(delay);
  }
  
  void setupReqMsg()
  {
    DelugeReqMsg *pReqMsg = (DelugeReqMsg *)(call SendReqMsg.getPayload(&pMsgBuf));
    
    if (state == S_RX_LOCKING) {
      if (isBusy_pMsgBuf) {
        return;
      }
      isBusy_pMsgBuf = TRUE;
      changeState(S_RECEIVING);
      pReqMsg->dest = nodeAddr;
      pReqMsg->sourceAddr = TOS_NODE_ID;
      pReqMsg->objid = workingObjid;
      pReqMsg->pgNum = workingPgNum;
    }
    
    if (state != S_RECEIVING) {
      return;
    }
    
    // suppress request
    if (suppressReq) {
      startReqTimer(FALSE);
      suppressReq = FALSE;
    }
    // tried too many times, give up
    else if (remainingAttempts == 0) {
      changeState(S_IDLE);
    }
    // send req message
    else {
      uint32_t i;
      for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
        pReqMsg->requestedPkts[i] = pktsToReceive[i];
      }
      //memcpy(pReqMsg->requestedPkts, pktsToReceive, DELUGE_PKT_BITVEC_SIZE);
      
      if (call SendReqMsg.send(pReqMsg->dest, &pMsgBuf, sizeof(DelugeReqMsg)) != SUCCESS) {
	startReqTimer(FALSE);
      }
    }
  }
  
  storage_addr_t calcOffset(page_num_t pgNum, uint8_t pktNum)
  {
    return (storage_addr_t)pgNum * (storage_addr_t)DELUGE_BYTES_PER_PAGE
            + (uint16_t)pktNum * (uint16_t)DELUGE_PKT_PAYLOAD_SIZE;
            //+ DELUGE_METADATA_SIZE;
  }
  
  void setupDataMsg()
  {
    DelugeDataMsg *pDataMsg = (DelugeDataMsg *)(call SendDataMsg.getPayload(&pMsgBuf));
    uint16_t nextPkt;
    
    if (state != S_SENDING && state != S_TX_LOCKING) {
      return;
    }
    
    signal DelugePageTransfer.suppressMsgs(objToSend);
    
    if (state == S_TX_LOCKING) {
      if (isBusy_pMsgBuf) {
        return;
      }
      isBusy_pMsgBuf = TRUE;
      changeState(S_SENDING);
      pDataMsg->objid = objToSend;
      pDataMsg->pgNum = pageToSend;
      pDataMsg->pktNum = 0;
    }
    
    if (call BitVecUtils.indexOf(&nextPkt, pDataMsg->pktNum, pktsToSend, DELUGE_PKTS_PER_PAGE) != SUCCESS) {
      // no more packets to send
      //dbg(DBG_USR1, "DELUGE: SEND_DONE\n");
      changeState(S_IDLE);
    } else {
      pDataMsg->pktNum = nextPkt;
      if (call BlockRead.read[imgNum](calcOffset(pageToSend, nextPkt), pDataMsg->data, DELUGE_PKT_PAYLOAD_SIZE) != SUCCESS) {
        call Timer.startOneShot(DELUGE_FAILED_SEND_DELAY);
      }
    }
  }
  
  void unlockPMsgBuf()
  {
    isBusy_pMsgBuf = FALSE;
    
    switch(state) {
      case S_TX_LOCKING:
        setupDataMsg();
        break;
      case S_RX_LOCKING:
        setupReqMsg();
        break;
    }
  }
  
  void changeState(uint8_t newState)
  {
    if ((newState == S_DISABLED || newState == S_IDLE)
	&& (state == S_SENDING || state == S_RECEIVING)) {
      unlockPMsgBuf();
    }
    
    state = newState;
  }
  
  void suppressMsgs(object_id_t objid, page_num_t pgNum)
  {
    if (state == S_SENDING || state == S_TX_LOCKING) {
      if (objid < objToSend || (objid == objToSend && pgNum < pageToSend)) {
	uint32_t i;
	changeState(S_IDLE);
	for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
          pktsToSend[i] = 0x00;
	}
	//memset(pktsToSend, 0x00, DELUGE_PKT_BITVEC_SIZE);
      }
    } else if (state == S_RECEIVING || state == S_RX_LOCKING) {
      if (objid < workingObjid || (objid == workingObjid && pgNum <= workingPgNum)) {
	// suppress next request since similar request has been overheard
	suppressReq = TRUE;
      }
    }
  }
  
  void writeData()
  {
    if(call BlockWrite.write[imgNum](calcOffset(rxQueue[head].pgNum, rxQueue[head].pktNum),
                            rxQueue[head].data, DELUGE_PKT_PAYLOAD_SIZE) != SUCCESS) {
      size = 0;
    }
  }
  
  command error_t DelugePageTransfer.stop()
  {
    uint32_t i;
    
    call Timer.stop();
    changeState(S_DISABLED);
    workingObjid = DELUGE_INVALID_OBJID;
    workingPgNum = DELUGE_INVALID_PGNUM;
    
    for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
      pktsToReceive[i] = 0x00;
    }
    for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
      pktsToSend[i] = 0x00;
    }
    //memset(pktsToReceive, 0x00, DELUGE_PKT_BITVEC_SIZE);
    //memset(pktsToSend, 0x00, DELUGE_PKT_BITVEC_SIZE);
    
    return SUCCESS;
  }
  
  command error_t DelugePageTransfer.setWorkingPage(object_id_t new_objid, page_num_t new_pgNum)
  {
    uint32_t i;
    
    if (state == S_DISABLED) {
      changeState(S_IDLE);
    }
    
    workingObjid = new_objid;
    workingPgNum = new_pgNum;
    
    for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
      pktsToReceive[i] = 0xFF;
    }
    //memset(pktsToReceive, (nx_uint8_t)0xff, DELUGE_PKT_BITVEC_SIZE);
    
    return SUCCESS;
  }
  
  command bool DelugePageTransfer.isTransferring()
  {
    return (state != S_IDLE && state != S_DISABLED);
  }
  
  command error_t DelugePageTransfer.dataAvailable(uint16_t sourceAddr)
  {
    if (state == S_IDLE) {
      // currently idle, so request data from source
      changeState(S_RX_LOCKING);
      nodeAddr = sourceAddr;
      remainingAttempts = DELUGE_MAX_NUM_REQ_TRIES;
      suppressReq = FALSE;
      
      // randomize request to prevent collision
      startReqTimer(TRUE);
    }
    
    return SUCCESS;
  }
  
  event void Timer.fired()
  {
    setupReqMsg();
    setupDataMsg();
  }
  
  event void SendReqMsg.sendDone(message_t* msg, error_t error)
  {
    if (state != S_RECEIVING) {
      return;
    }
    
    remainingAttempts--;
    // start timeout timer in case request is not serviced
    startReqTimer(FALSE);
  }
  
  event message_t* ReceiveReqMsg.receive(message_t* msg, void* payload, uint8_t len)
  {
    DelugeReqMsg *rxReqMsg = (DelugeReqMsg*)payload;
    object_id_t objid;
    page_num_t pgNum;
    int i;
    
    //dbg(DBG_USR1, "DELUGE: Received REQ_MSG(dest=%d,vNum=%d,imgNum=%d,pgNum=%d,pkts=%x)\n",
    //    rxReqMsg->dest, rxReqMsg->vNum, rxReqMsg->imgNum, rxReqMsg->pgNum, rxReqMsg->requestedPkts[0]);
    
    if (state == S_DISABLED) {
      return msg;
    }
    
    objid = rxReqMsg->objid;
    pgNum = rxReqMsg->pgNum;
    
    // check if need to suppress req or data msgs
    suppressMsgs(objid, pgNum);
    
    // if not for me, ignore request
    if (rxReqMsg->dest != TOS_NODE_ID
        || objid != workingObjid
	|| pgNum >= workingPgNum) {
      return msg;
    }
    
    if (state == S_IDLE
	|| ((state == S_SENDING || state == S_TX_LOCKING)
           && objid == objToSend
           && pgNum == pageToSend)) {
      // take union of packet bit vectors
      for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
        pktsToSend[i] |= rxReqMsg->requestedPkts[i];
      }
    }
    
    if (state == S_IDLE) {
      // not currently sending, so start sending data
      changeState(S_TX_LOCKING);
      objToSend = objid;
      pageToSend = pgNum;
      nodeAddr = AM_BROADCAST_ADDR;
      setupDataMsg();
    }
    
    return msg;
  }
  
  event void SendDataMsg.sendDone(message_t* msg, error_t error)
  {
    DelugeDataMsg *pDataMsg = (DelugeDataMsg *)(call SendDataMsg.getPayload(&pMsgBuf));
    BITVEC_CLEAR(pktsToSend, pDataMsg->pktNum);
    call Timer.startOneShot(2);
    
// For collecting stats
if (error == SUCCESS) {
  //call StatsCollector.endPubPktTransTime();
}
  }
  
  event message_t* ReceiveDataMsg.receive(message_t* msg, void* payload, uint8_t len)
  {
    DelugeDataMsg* rxDataMsg = (DelugeDataMsg*)payload;
    
    if (state == S_DISABLED) {
      return msg;
    }
    
    //dbg(DBG_USR1, "DELUGE: Received DATA_MSG(vNum=%d,imgNum=%d,pgNum=%d,pktNum=%d)\n",
    //    rxDataMsg->vNum, rxDataMsg->imgNum, rxDataMsg->pgNum, rxDataMsg->pktNum);
    
    // check if need to suppress req or data messages
    suppressMsgs(rxDataMsg->objid, rxDataMsg->pgNum);
    
    if (rxDataMsg->objid == workingObjid
	&& rxDataMsg->pgNum == workingPgNum
	&& BITVEC_GET(pktsToReceive, rxDataMsg->pktNum)
	&& size < DELUGE_QSIZE) {
      // got a packet we need
      
// For collecting stats
if (rxDataMsg->pktNum == 0) {
  //call StatsCollector.startRecvPageTransTime(0);
  dbg("Deluge", "%.3f 115 116 116 117 115 1 %d\n", ((float)((sim_time() * 1000) / sim_ticks_per_sec())) / 1000, CC2420_DEF_CHANNEL);
}
call Leds.led1Toggle();
//call Leds.set(rxDataMsg->pktNum);
      
      //dbg(DBG_USR1, "DELUGE: SAVING(pgNum=%d,pktNum=%d)\n", 
      //    rxDataMsg->pgNum, rxDataMsg->pktNum);
      
      // copy data
      memcpy(&rxQueue[head^size], rxDataMsg, sizeof(DelugeDataMsg));
      if (++size == 1) {
        publisher_addr = call AMPacket.source(msg);   // For collecting stats
	writeData();
      }
    }
    
    return msg;
  }
  
  event void BlockRead.readDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error)
  {
    DelugeDataMsg *pDataMsg = (DelugeDataMsg *)(call SendDataMsg.getPayload(&pMsgBuf));
    // make sure this event for us
    if (buf != pDataMsg->data) {
      return;
    }
    
    if (state != S_SENDING) {
      return;
    }
    
    if (error != SUCCESS) {
      changeState(S_IDLE);
      return;
    }
    
    if (call SendDataMsg.send(nodeAddr, &pMsgBuf, sizeof(DelugeDataMsg)) != SUCCESS) {
      call Timer.startOneShot(DELUGE_FAILED_SEND_DELAY);
    } else {
// For collecting stats
//call StatsCollector.startPubPktTransTime();
//call Leds.led1Toggle();
    }
  }
  
  event void BlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) { }
  
  event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error)
  {
    uint16_t tmp;
    
    // make sure this event for us
    if (buf != rxQueue[head].data) {
      return;
    }
    
    // failed to write
    if (error != SUCCESS) {
      uint32_t i;
      for (i = 0; i < DELUGE_PKT_BITVEC_SIZE; i++) {
        pktsToReceive[i] = 0xFF;
      }
      size = 0;
      return;
    }
    
    // mark packet as received
    BITVEC_CLEAR(pktsToReceive, rxQueue[head].pktNum);
    head = (head + 1) % DELUGE_QSIZE;
    size--;
    
    if (call BitVecUtils.indexOf(&tmp, 0, pktsToReceive, DELUGE_PKTS_PER_PAGE) != SUCCESS) {
// For collecting stats
//call StatsCollector.endRecvPageTransTime(publisher_addr);
dbg("Deluge", "%.3f 115 116 116 117 115 2 %d\n", ((float)((sim_time() * 1000) / sim_ticks_per_sec())) / 1000, publisher_addr);

      signal DelugePageTransfer.receivedPage(workingObjid, workingPgNum);
      changeState(S_IDLE);
      size = 0;
    } else if (size) {
      writeData();
    }
  }
  
  event void BlockWrite.eraseDone[uint8_t img_num](error_t error) {}
  event void BlockWrite.syncDone[uint8_t img_num](error_t error) {}
  
  command void DelugePageTransfer.setImgNum(uint8_t new_img_num)
  {
    imgNum = new_img_num;
  }
  
  default command error_t BlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
  default command error_t BlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
}

--- NEW FILE: DelugeStorageC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "StorageVolumes.h"

configuration DelugeStorageC
{
  provides {
    interface BlockRead[uint8_t img_num];
    interface BlockWrite[uint8_t img_num];
    interface StorageMap[uint8_t img_num];
    interface DelugeMetadata;
    
    interface Notify<uint8_t>;
  }
}

implementation
{
  components new BlockStorageC(VOLUME_DELUGE0) as BlockStorageC_0;
  components new BlockStorageC(VOLUME_DELUGE1) as BlockStorageC_1;
  components DelugeStorageP;

  BlockRead[0] = DelugeStorageP.BlockRead[0];
  BlockWrite[0] = DelugeStorageP.BlockWrite[0];
  StorageMap[0] = BlockStorageC_0;
  BlockRead[1] = DelugeStorageP.BlockRead[1];
  BlockWrite[1] = DelugeStorageP.BlockWrite[1];
  StorageMap[1] = BlockStorageC_1;
  DelugeMetadata = DelugeStorageP.DelugeMetadata;

  DelugeStorageP.SubBlockRead[0] -> BlockStorageC_0;
  DelugeStorageP.SubBlockWrite[0] -> BlockStorageC_0;
  DelugeStorageP.SubBlockRead[1] -> BlockStorageC_1;
  DelugeStorageP.SubBlockWrite[1] -> BlockStorageC_1;
  
  components LedsC, MainC;
  DelugeStorageP.Leds -> LedsC;
  DelugeStorageP.Boot -> MainC;
  
  Notify = DelugeStorageP.Notify;
}

--- NEW FILE: DelugeStorageP.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "Deluge.h"

module DelugeStorageP
{
  uses {
    interface BlockRead as SubBlockRead[uint8_t img_num];
    interface BlockWrite as SubBlockWrite[uint8_t img_num];
    interface Boot;
    interface Leds;
  }
  provides {
    interface BlockRead[uint8_t img_num];
    interface BlockWrite[uint8_t img_num];
    interface DelugeMetadata;
    
    interface Notify<uint8_t>;
  }
}

implementation
{
  enum {
    S_INIT,
    S_READY,
  };

  uint8_t state = S_INIT;
  uint8_t last_init_img_num = 0;
  DelugeImgDesc imgDesc[DELUGE_NUM_VOLUMES];

  event void Boot.booted()
  {
    uint32_t i;
    for (i = 0; i < DELUGE_NUM_VOLUMES; i++) {
      imgDesc[i].uid = DELUGE_INVALID_UID;
      imgDesc[i].vNum = 0;
      imgDesc[i].imgNum = 0;
      imgDesc[i].numPgs = 0;
      imgDesc[i].crc = 0;
      imgDesc[i].numPgsComplete = 0;
      imgDesc[i].reserved = 0;
      imgDesc[i].size = 0;
    }
    
    // Reads image descriptions
    state = S_INIT;
    if (DELUGE_NUM_VOLUMES > 0) {
      call SubBlockRead.read[last_init_img_num](0, &(imgDesc[last_init_img_num]), sizeof(DelugeImgDesc));
    }
  }

  command DelugeImgDesc* DelugeMetadata.getImgDesc(imgnum_t imgNum)
  {
    return &(imgDesc[imgNum]);
  }

  // SubBlockRead commands
  command error_t BlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len)
  {
    return call SubBlockRead.read[img_num](addr, buf, len);
  }

  command error_t BlockRead.computeCrc[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc)
  {
    return call SubBlockRead.computeCrc[img_num](addr, len, crc);
  }

  command storage_len_t BlockRead.getSize[uint8_t img_num]()
  {
    return call SubBlockRead.getSize[img_num]();
  }

  // BlockRead events
  event void SubBlockRead.readDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error)
  {
    if (state == S_READY) {
      signal BlockRead.readDone[img_num](addr, buf, len, error);
    } else {
      // Continues reading image descriptions
      if (error == SUCCESS) {
        last_init_img_num++;
        if (last_init_img_num >= DELUGE_NUM_VOLUMES) {
          signal Notify.notify(SUCCESS);
          state = S_READY;
        } else {
          call SubBlockRead.read[last_init_img_num](0, &(imgDesc[last_init_img_num]), sizeof(DelugeImgDesc));
        }
      }
    }
  }

  event void SubBlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error)
  {
    signal BlockRead.computeCrcDone[img_num](addr, len, crc, error);
  }

  // SubBlockWrite commands
  command error_t BlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len)
  {
    return call SubBlockWrite.write[img_num](addr, buf, len);
  }

  command error_t BlockWrite.erase[uint8_t img_num]()
  {
    return call SubBlockWrite.erase[img_num]();
  }

  command error_t BlockWrite.sync[uint8_t img_num]()
  {
    return call SubBlockWrite.sync[img_num]();
  }

  // BlockWrite events
  event void SubBlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error)
  {
    if (error == SUCCESS) {
      if (addr < sizeof(DelugeImgDesc)) {
        memcpy((char*)&(imgDesc[img_num]) + addr, buf, sizeof(DelugeImgDesc) - addr);
      }
    }
    
    signal BlockWrite.writeDone[img_num](addr, buf, len, error);
  }

  event void SubBlockWrite.eraseDone[uint8_t img_num](error_t error)
  {
    if (error == SUCCESS) {
      // Successful erase triggers resetting the cached image description
      imgDesc[img_num].uid = DELUGE_INVALID_UID;
      imgDesc[img_num].vNum = 0;
      imgDesc[img_num].imgNum = 0;
      imgDesc[img_num].numPgs = 0;
      imgDesc[img_num].crc = 0;
      imgDesc[img_num].numPgsComplete = 0;
      imgDesc[img_num].reserved = 0;
      imgDesc[img_num].size = 0;
    }
    
    signal BlockWrite.eraseDone[img_num](error);
  }

  event void SubBlockWrite.syncDone[uint8_t img_num](error_t error)
  {
    signal BlockWrite.syncDone[img_num](error);
  }

  default event void BlockRead.readDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {}
  default event void BlockRead.computeCrcDone[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error) {}
  default event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {}
  default event void BlockWrite.eraseDone[uint8_t img_num](error_t error) {}
  default event void BlockWrite.syncDone[uint8_t img_num](error_t error) {}
  
  default command error_t SubBlockWrite.write[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
  default command error_t SubBlockWrite.erase[uint8_t img_num]() { return FAIL; }
  default command error_t SubBlockWrite.sync[uint8_t img_num]() { return FAIL; }
  default command error_t SubBlockRead.read[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len) { return FAIL; }
  default command error_t SubBlockRead.computeCrc[uint8_t img_num](storage_addr_t addr, storage_len_t len, uint16_t crc) { return FAIL; }
  default command storage_len_t SubBlockRead.getSize[uint8_t img_num]() { return 0; }
  
  command error_t Notify.enable() { return SUCCESS; }
  command error_t Notify.disable() { return SUCCESS; }
}

--- NEW FILE: FakeBlockReaderC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

generic module FakeBlockReaderC(uint32_t size)
{
  provides interface BlockRead;
}

implementation
{
  enum {
    S_IDLE,
    S_BUSY
  };

  storage_addr_t saddr;
  uint8_t *oribuf;
  uint8_t *sbuf;
  storage_len_t slen;
  uint8_t state = S_IDLE;

  task void task_read()
  {
    while (slen > 0) {
      *sbuf = saddr & 0xFF;
      saddr++;
      sbuf++;
      slen--;
    }

    signal BlockRead.readDone(saddr, oribuf, slen, SUCCESS);
    state = S_IDLE;
  }

  command error_t BlockRead.read(storage_addr_t addr,
				 void* buf,
				 storage_len_t len)
  {
    if (state != S_IDLE) {
      return FAIL;
    }


    state = S_BUSY;
    saddr = addr;
    sbuf = buf;
    oribuf = buf;
    slen = len;
    post task_read();
    return SUCCESS;
  };

  task void task_computeCRC()
  {
    signal BlockRead.computeCrcDone(saddr, slen, 0, SUCCESS);
  }

  command error_t BlockRead.computeCrc(storage_addr_t addr,
				       storage_len_t len,
				       uint16_t crc)
  {
    saddr = addr;
    slen = len;
    post task_computeCRC();
    return SUCCESS;
  }

  command storage_len_t BlockRead.getSize()
  {
    return size;
  }
}

--- NEW FILE: FakeBlockWriterC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

generic configuration FakeBlockWriterC(uint32_t size)
{
  provides interface BlockWrite;
}

implementation
{
  components LedsC, NoLedsC,
             new FakeBlockWriterP(size);
  
  BlockWrite = FakeBlockWriterP;
  FakeBlockWriterP.Leds -> NoLedsC;
}

--- NEW FILE: FakeBlockWriterP.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

generic module FakeBlockWriterP(uint32_t size)
{
  provides interface BlockWrite;
  uses interface Leds;
}

implementation
{
  enum {
    S_IDLE,
    S_BUSY
  };
  
  storage_addr_t saddr;
  uint8_t *oribuf;
  uint8_t *sbuf;
  storage_len_t slen;
  uint8_t state;
  
  task void task_write()
  {
    error_t error = SUCCESS;
    
    while (slen > 0) {
      if (*sbuf != (saddr & 0xFF)) {
        error = FAIL;
call Leds.led2Toggle();
      }
      saddr++;
      sbuf++;
      slen--;
    }
    
    signal BlockWrite.writeDone(saddr, oribuf, slen, error);
    state = S_IDLE;
  }
  
  command error_t BlockWrite.write(storage_addr_t addr,
				   void* buf,
				   storage_len_t len)
  {
    if (state != S_IDLE) {
      return FAIL;
    }
    
    state = S_BUSY;
    saddr = addr;
    sbuf = buf;
    oribuf = buf;
    slen = len;
    post task_write();
    return SUCCESS;
  }
  
  task void task_erase()
  {
    signal BlockWrite.eraseDone(SUCCESS);
  }
  
  command error_t BlockWrite.erase()
  {
    post task_erase();
    return SUCCESS;
  }
  
  task void task_sync()
  {
    signal BlockWrite.syncDone(SUCCESS);
  }
  
  command error_t BlockWrite.sync()
  {
    post task_sync();
    return SUCCESS;
  }
}

--- NEW FILE: Globals.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

interface Globals
{
  command uint32_t getNumPubPktTrans();
  command void setNumPubPktTrans(uint32_t val);
  command void incNumPubPktTrans();

  command uint32_t getNumRecvPageTrans();
  command void setNumRecvPageTrans(uint32_t val);
  command void incNumRecvPageTrans();

  command uint32_t getAvgPubPktTransTime();
  command void setAvgPubPktTransTime(uint32_t val);

  command uint32_t getAvgRecvPageTransTime();
  command void setAvgRecvPageTransTime(uint32_t val);

  command uint32_t getNumPubPktRetrans();
  command void setNumPubPktRetrans(uint32_t val);
  command void incNumPubPktRetrans();

  command uint32_t getNumPubHSRetrans();
  command void setNumPubHSRetrans(uint32_t val);
  command void incNumPubHSRetrans();

  command uint32_t getNumRecvHSRetrans();
  command void setNumRecvHSRetrans(uint32_t val);
  command void incNumRecvHSRetrans();

  command void* _getStartAddr();
  command uint32_t _getSize();
}

--- NEW FILE: GlobalsC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

module GlobalsC
{
  provides interface Globals;
}

implementation
{
  struct {
    uint32_t NumPubPktTrans;
    uint32_t NumRecvPageTrans;
    uint32_t AvgPubPktTransTime;
    uint32_t AvgRecvPageTransTime;
    uint32_t NumPubPktRetrans;
    uint32_t NumPubHSRetrans;
    uint32_t NumRecvHSRetrans;
  } _g = {0, 0, 0, 0, 0, 0, 0};

  command uint32_t Globals.getNumPubPktTrans() { return _g.NumPubPktTrans; }
  command void Globals.setNumPubPktTrans(uint32_t val) { _g.NumPubPktTrans = val; }
  command void Globals.incNumPubPktTrans() { _g.NumPubPktTrans++; }

  command uint32_t Globals.getNumRecvPageTrans() { return _g.NumRecvPageTrans; }
  command void Globals.setNumRecvPageTrans(uint32_t val) { _g.NumRecvPageTrans = val; }
  command void Globals.incNumRecvPageTrans() { _g.NumRecvPageTrans++; }

  command uint32_t Globals.getAvgPubPktTransTime() { return _g.AvgPubPktTransTime; }
  command void Globals.setAvgPubPktTransTime(uint32_t val) { _g.AvgPubPktTransTime = val; }

  command uint32_t Globals.getAvgRecvPageTransTime() { return _g.AvgRecvPageTransTime; }
  command void Globals.setAvgRecvPageTransTime(uint32_t val) { _g.AvgRecvPageTransTime = val; }

  command uint32_t Globals.getNumPubPktRetrans() { return _g.NumPubPktRetrans; }
  command void Globals.setNumPubPktRetrans(uint32_t val) { _g.NumPubPktRetrans = val; }
  command void Globals.incNumPubPktRetrans() { _g.NumPubPktRetrans++; }

  command uint32_t Globals.getNumPubHSRetrans() { return _g.NumPubHSRetrans; }
  command void Globals.setNumPubHSRetrans(uint32_t val) { _g.NumPubHSRetrans = val; }
  command void Globals.incNumPubHSRetrans() { _g.NumPubHSRetrans++; }

  command uint32_t Globals.getNumRecvHSRetrans() { return _g.NumRecvHSRetrans; }
  command void Globals.setNumRecvHSRetrans(uint32_t val) { _g.NumRecvHSRetrans = val; }
  command void Globals.incNumRecvHSRetrans() { _g.NumRecvHSRetrans++; }

  command void* Globals._getStartAddr() { return &_g; }
  command uint32_t Globals._getSize() { return sizeof(_g); }
}

--- NEW FILE: ObjectTransfer.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "DelugePageTransfer.h"

interface ObjectTransfer
{
  command error_t publish(object_id_t new_objid, object_size_t new_size, uint8_t img_num);
  command error_t receive(object_id_t new_objid, object_size_t new_size, uint8_t img_num);
  event void receiveDone(error_t error);

  command error_t stop();
}

--- NEW FILE: ObjectTransferC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "DelugePageTransfer.h"

configuration ObjectTransferC
{
  provides interface ObjectTransfer;
  uses {
    interface BlockRead[uint8_t img_num];
    interface BlockWrite[uint8_t img_num];
  }
}

implementation
{
  components ObjectTransferP, DelugePageTransferC;
  
  ObjectTransfer = ObjectTransferP;
  BlockRead[0] = DelugePageTransferC.BlockRead[0];
  BlockWrite[0] = DelugePageTransferC.BlockWrite[0];
  BlockRead[1] = DelugePageTransferC.BlockRead[1];
  BlockWrite[1] = DelugePageTransferC.BlockWrite[1];
  ObjectTransferP.DelugePageTransfer -> DelugePageTransferC.DelugePageTransfer;
  
  components CrcP;
  ObjectTransferP.Crc -> CrcP.Crc;
  
  components new AMSenderC(AM_DELUGEADVMSG) as SendAdvMsg, 
             new AMReceiverC(AM_DELUGEADVMSG) as ReceiveAdvMsg,
             new AMSenderC(AM_DELUGEREQMSG) as SendReqMsg, 
             new AMReceiverC(AM_DELUGEREQMSG) as ReceiveReqMsg,
             new AMSenderC(AM_DELUGEDATAMSG) as SendDataMsg, 
             new AMReceiverC(AM_DELUGEDATAMSG) as ReceiveDataMsg;
  
  ObjectTransferP.SendAdvMsg -> SendAdvMsg;
  ObjectTransferP.ReceiveAdvMsg -> ReceiveAdvMsg;
  DelugePageTransferC.SendReqMsg -> SendReqMsg;
  DelugePageTransferC.ReceiveReqMsg -> ReceiveReqMsg;
  DelugePageTransferC.SendDataMsg -> SendDataMsg;
  DelugePageTransferC.ReceiveDataMsg -> ReceiveDataMsg;
  DelugePageTransferC.AMPacket -> SendDataMsg;
  
  ObjectTransferP.BlockWrite[0] = BlockWrite[0];
  ObjectTransferP.BlockWrite[1] = BlockWrite[1];
  
  components MainC, LedsC, NoLedsC;
  ObjectTransferP.Leds -> NoLedsC;
  
  components RandomC, new TimerMilliC() as Timer;
  ObjectTransferP.Random -> RandomC;
  ObjectTransferP.Timer -> Timer;
  
  // For collecting statistics
//  components StatsCollectorC;
//  ObjectTransferP.StatsCollector -> StatsCollectorC.StatsCollector;
}

--- NEW FILE: ObjectTransferP.nc ---
/*
 * "Copyright (c) 2000-2004 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) 2007 Johns Hopkins University.
 * All rights reserved.
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

#include "DelugePageTransfer.h"
#include "DelugeMsgs.h"

module ObjectTransferP
{
  provides interface ObjectTransfer;
  uses {
    interface Random;
    interface Timer<TMilli> as Timer;
    interface DelugePageTransfer;
    interface Crc;
    
    interface AMSend as SendAdvMsg;
    interface Receive as ReceiveAdvMsg;
    
    interface BlockWrite[uint8_t img_num];
    
    interface Leds;
//  interface StatsCollector;
  }
}

implementation
{
  // States
  enum {
    S_ERASE,
    S_INITIALIZING_PUB,
    S_INITIALIZING_RECV,
    S_STARTED,
    S_STOPPED,
  };
  
  DelugeAdvTimer advTimers;
  //DelugeNodeDesc nodeDesc;
  uint8_t state = S_STOPPED;
  
  object_id_t cont_receive_new_objid;
  object_size_t cont_receive_new_size;
  uint8_t cont_receive_img_num;
  
  message_t pMsgBuf;
  bool isBusy_pMsgBuf = FALSE;
  DelugeObjDesc curObjDesc;
  
  void updateTimers()
  {
    //advTimers.timer = 0;
  }
  
  void setupAdvTimer()
  {
    advTimers.timer = (uint32_t)0x1 << (advTimers.periodLog2 - 1);
    advTimers.timer += call Random.rand16() & (advTimers.timer - 1);
    advTimers.overheard = 0;
    
    call Timer.stop();
    call Timer.startOneShot(advTimers.timer);
  }
  
  void resetTimer()
  {
    if (advTimers.periodLog2 != DELUGE_MIN_ADV_PERIOD_LOG2) {
      advTimers.periodLog2 = DELUGE_MIN_ADV_PERIOD_LOG2;
      setupAdvTimer();
    }
  }
  
  task void signalObjRecvDone()
  {
    signal ObjectTransfer.receiveDone(SUCCESS);
  }
  
  void setNextPage()
  {
    if (curObjDesc.numPgsComplete < curObjDesc.numPgs) {
      call DelugePageTransfer.setWorkingPage(curObjDesc.objid, curObjDesc.numPgsComplete);
      advTimers.newAdvs = DELUGE_NUM_NEWDATA_ADVS_REQUIRED;    
      advTimers.overheard = 0;
      resetTimer();
    } else {
      call DelugePageTransfer.setWorkingPage(DELUGE_INVALID_OBJID, DELUGE_INVALID_PGNUM);
      post signalObjRecvDone();
    }
  }
  
//  bool isNodeDescValid(DelugeNodeDesc* tmpNodeDesc)
//  {
//    return (tmpNodeDesc->crc == crc16(tmpNodeDesc, 4 + sizeof(object_id_t) + 1));
//  }
  
  bool isObjDescValid(DelugeObjDesc* tmpObjDesc)
  {
    return (tmpObjDesc->crc == call Crc.crc16(tmpObjDesc, sizeof(object_id_t) + sizeof(page_num_t))
	    && tmpObjDesc->crc != 0);
  }
  
  void sendAdvMsg(uint16_t addr)
  {
    DelugeAdvMsg *pMsg = (DelugeAdvMsg *)(call SendAdvMsg.getPayload(&pMsgBuf));
    
    if (isBusy_pMsgBuf == FALSE) {
      pMsg->sourceAddr = TOS_NODE_ID;
      pMsg->version = DELUGE_VERSION;
      //pMsg->type = (imagesLoaded) ? DELUGE_ADV_NORMAL : DELUGE_ADV_ERROR;
      pMsg->type = DELUGE_ADV_NORMAL;
      
      // make sure node desc is valid
//      if (!isNodeDescValid(&nodeDesc)) {
//        memset(&nodeDesc, 0xff, sizeof(nodeDesc));
//      }
//      memcpy(&pMsg->nodeDesc, &nodeDesc, sizeof(DelugeNodeDesc));
      
      // make sure obj desc is valid
//      if (!isObjDescValid(&curObjDesc)) {
//        //curObjDesc.objid = objid;
//      }
      memcpy(&(pMsg->objDesc), &curObjDesc, sizeof(DelugeObjDesc));
      
      if (call SendAdvMsg.send(addr, &pMsgBuf, sizeof(DelugeAdvMsg)) == SUCCESS) {
        //dbg(DBG_USR1, "DELUGE: Sent ADV_MSG(imgNum=%d)\n", imgDesc->imgNum);
//call StatsCollector.msg_bcastReq();
call Leds.led0Toggle();
        isBusy_pMsgBuf = TRUE;
      }
    }
  }
  
  /**
   * Starts publisher
   */
  command error_t ObjectTransfer.publish(object_id_t new_objid, object_size_t new_size, uint8_t img_num)
  {
    call ObjectTransfer.stop();
//call StatsCollector.startStatsCollector();
    
    state = S_INITIALIZING_PUB;
    curObjDesc.objid = new_objid;
    curObjDesc.numPgs = ((new_size - 1) / DELUGE_BYTES_PER_PAGE) + 1;   // Number of pages to transmit
    curObjDesc.numPgsComplete = curObjDesc.numPgs;   // Publisher doesn't really care about this
    curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t));
    
    if (state == S_INITIALIZING_PUB) {
      resetTimer();
    }
    state = S_STARTED;
    
    call DelugePageTransfer.setImgNum(img_num);
    call DelugePageTransfer.setWorkingPage(curObjDesc.objid, curObjDesc.numPgs);
    
    return SUCCESS;
  }
  
  /**
   * Resumes the process of preparing the receiver after the target volume is erased
   */
  void cont_receive() {
    state = S_INITIALIZING_RECV;
    curObjDesc.objid = cont_receive_new_objid;
    curObjDesc.numPgs = ((cont_receive_new_size - 1) / DELUGE_BYTES_PER_PAGE) + 1;   // Number of pages to receive
    curObjDesc.numPgsComplete = 0;
    curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t));
    
    if (state == S_INITIALIZING_RECV) {
      resetTimer();
    }
    state = S_STARTED;
    
    call DelugePageTransfer.setImgNum(cont_receive_img_num);
    setNextPage();
  }
  
  /**
   * Starts receiver
   */
  command error_t ObjectTransfer.receive(object_id_t new_objid, object_size_t new_size, uint8_t img_num)
  {
    error_t error;
    
    call ObjectTransfer.stop();
    state = S_STOPPED;
//call StatsCollector.startStatsCollector();
    
    cont_receive_new_objid = new_objid;
    cont_receive_new_size = new_size;
    cont_receive_img_num = img_num;
    
    error = call BlockWrite.erase[img_num]();
    if (error == SUCCESS) {
      state = S_ERASE;
    }
    
    return error;
  }
  
  command error_t ObjectTransfer.stop()
  {
    call Timer.stop();
    call DelugePageTransfer.stop();
//call StatsCollector.stopStatsCollector();
    
    state = S_STOPPED;
    curObjDesc.objid = DELUGE_INVALID_OBJID;
    curObjDesc.numPgs = DELUGE_INVALID_PGNUM;
    curObjDesc.numPgsComplete = DELUGE_INVALID_PGNUM;
    
    return SUCCESS;
  }
  
  event void DelugePageTransfer.receivedPage(object_id_t new_objid, page_num_t new_pgNum)
  {
    if (new_objid == curObjDesc.objid && new_pgNum == curObjDesc.numPgsComplete) {
      curObjDesc.numPgsComplete++;
      curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t));
      if (curObjDesc.numPgsComplete < curObjDesc.numPgs) {
        setNextPage();
      } else {
        call DelugePageTransfer.setWorkingPage(curObjDesc.objid, curObjDesc.numPgsComplete);
        post signalObjRecvDone();
      }
    }
  }
  
  event void DelugePageTransfer.suppressMsgs(object_id_t new_objid)
  {
    if (new_objid == curObjDesc.objid) {
      advTimers.overheard = 1;
    }
  }
  
  event void SendAdvMsg.sendDone(message_t* msg, error_t error)
  {
    isBusy_pMsgBuf = FALSE;
  }
  
  event message_t* ReceiveAdvMsg.receive(message_t* msg, void* payload, uint8_t len)
  {
    DelugeAdvMsg *rxAdvMsg = (DelugeAdvMsg*)payload;
    DelugeObjDesc *cmpObjDesc = &(rxAdvMsg->objDesc);
    bool isEqual = FALSE;
 
    if (cmpObjDesc->objid != curObjDesc.objid) {
      return msg;
    }
    
    if (rxAdvMsg->version != DELUGE_VERSION 
        //|| !isNodeDescValid(&rxAdvMsg->nodeDesc)
        || state != S_STARTED) {
      return msg;
    }
    
    if (isObjDescValid(&(rxAdvMsg->objDesc)) && state == S_STARTED) {
      // Their image is larger (They have something we need)
      if (cmpObjDesc->numPgsComplete > curObjDesc.numPgsComplete) {
        if ( advTimers.newAdvs == 0 ) {
          call DelugePageTransfer.dataAvailable(rxAdvMsg->sourceAddr);
        }
      }
      // Their image is smaller (They need something we have)
      else if (cmpObjDesc->numPgsComplete < curObjDesc.numPgsComplete) {
        advTimers.newAdvs = DELUGE_NUM_NEWDATA_ADVS_REQUIRED;
      }      
      // image is the same
      else {
        advTimers.overheard = 1;
        isEqual = TRUE;
      }
      
      if (!isEqual) {
        resetTimer();
      }
    }
    
    return msg;
  }
    
  event void Timer.fired()
  {
    updateTimers();
    
    if (advTimers.overheard == 0) {
      sendAdvMsg(AM_BROADCAST_ADDR);
    }
    
    if (call DelugePageTransfer.isTransferring())
      advTimers.newAdvs = DELUGE_NUM_NEWDATA_ADVS_REQUIRED;
    else if (advTimers.newAdvs > 0)
      advTimers.newAdvs--;
    
    if (advTimers.newAdvs == 0 &&
        advTimers.periodLog2 < DELUGE_MAX_ADV_PERIOD_LOG2) {
      advTimers.periodLog2++;
    }
    
    setupAdvTimer();
  }
  
  default command error_t BlockWrite.erase[uint8_t img_num]() { return FAIL; }
  event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {}
  event void BlockWrite.eraseDone[uint8_t img_num](error_t error)
  {
    if (state == S_ERASE) {
      cont_receive();
    }
  }
  event void BlockWrite.syncDone[uint8_t img_num](error_t error) {}
}

--- NEW FILE: SerialStarterC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

configuration SerialStarterC { }

implementation
{
  components SerialActiveMessageC, AutoStarterC;
  
  AutoStarterC.SplitControl -> SerialActiveMessageC;
}

--- NEW FILE: StatsCollector.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

interface StatsCollector
{
  command void stopStatsCollector();
  command void startStatsCollector();
  command void startPubPktTransTime();
  command void endPubPktTransTime();
  command void startRecvPageTransTime(uint8_t channel);
  command void endRecvPageTransTime(uint8_t senderAddr);
  command void incPub_numPktRetrans();
  command void incNumRecvHSRetrans();
  
  command void startCCTime();
  command void endCCTime();
  
  command void sendVariableReport(uint32_t value);
  command void msg_bcastReq();
}

--- NEW FILE: StatsCollectorC.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

configuration StatsCollectorC
{
  provides {
    interface StatsCollector;
  }
}

implementation
{
  components GlobalsC, StatsCollectorP,
    new CounterToLocalTimeC(TMilli),
#ifdef TOSSIM
    HilTimerMilliC,
#else
    new TransformCounterC(TMilli, uint32_t, T32khz, uint16_t, 5, uint32_t) as Transform,
    Msp430Counter32khzC,
#endif
    new TimerMilliC() as Timer;

#ifdef TOSSIM
    StatsCollectorP.LocalTime -> HilTimerMilliC;
#else
  CounterToLocalTimeC.Counter -> Transform;
  Transform.CounterFrom -> Msp430Counter32khzC;
  StatsCollectorP.LocalTime -> CounterToLocalTimeC;
#endif
  
  StatsCollectorP.Globals -> GlobalsC.Globals;
  StatsCollector = StatsCollectorP.StatsCollector;
  StatsCollectorP.Timer -> Timer;
  
  components SerialStarterC, new SerialAMSenderC(0);
  StatsCollectorP.AMSend -> SerialAMSenderC;
}

--- NEW FILE: StatsCollectorP.nc ---
/* Copyright (c) 2007 Johns Hopkins University.
*  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 (updated) modification history and the author appear in
*  all copies of this source code.
*
*  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 HOLDERS OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
*  OR PROFITS) 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.
*/

/**
 * @author Chieh-Jan Mike Liang <cliang4 at cs.jhu.edu>
 * @author Razvan Musaloiu-E. <razvanm at cs.jhu.edu>
 */

module StatsCollectorP
{
  provides {
    interface StatsCollector;
  }
  uses {
    interface LocalTime<TMilli> as LocalTime;
    interface Globals;
    interface Timer<TMilli> as Timer;
    interface AMSend;
  }
}

implementation
{
  enum {
    TIMER = 0,
    FORCED_START = 1,
    FORCED_END = 2
  };
  
  enum {
    BROADCAST_REQ = 0,
    START_RECV_DATA = 1,
    END_RECV_DATA = 2
  };
  
  typedef nx_struct StatsReport {
    nx_uint8_t text[5];
    nx_uint32_t NumPubPktTrans;
    nx_uint32_t NumRecvPageTrans;
    nx_uint32_t AvgPubPktTransTime;
    nx_uint32_t AvgRecvPageTransTime;
    nx_uint32_t NumPubPktRetrans;
    nx_uint32_t NumRecvHSRetrans;
  } StatsReport;
  
  typedef nx_struct StatusReport {
    nx_uint8_t text[5];
    nx_uint8_t flag;
    nx_uint8_t channel;
  } StatusReport;
  
  typedef nx_struct VariableReport {
    nx_uint8_t text[5];
    nx_uint32_t value;
  } VariableReport;
  
  uint32_t startPubTime = 0;
  uint32_t startRecvTime = 0;
  uint32_t startCCTime = 0;   // Change channel
  message_t stats_msg;
  message_t status_msg;
  message_t variable_msg;
 
  void startTimer() {
    if(call Timer.isRunning() == FALSE || call Timer.isOneShot() == TRUE) {
      call Timer.startPeriodic(5000);
    }
  }
  
  void stopTimer() {
    if(call Timer.isRunning() == TRUE) {
      call Timer.stop();
    }
  }
  
  void sendStatsReport() {
    StatsReport *report = (StatsReport *)call AMSend.getPayload(&stats_msg);

    report->text[0] = 's';
    report->text[1] = 't';
    report->text[2] = 'a';
    report->text[3] = 't';
    report->text[4] = 's';
    report->NumPubPktTrans = call Globals.getNumPubPktTrans();
    report->NumRecvPageTrans = call Globals.getNumRecvPageTrans();
    report->AvgPubPktTransTime = call Globals.getAvgPubPktTransTime();
    report->AvgRecvPageTransTime = call Globals.getAvgRecvPageTransTime();
    report->NumPubPktRetrans = call Globals.getNumPubPktRetrans();
    report->NumRecvHSRetrans = call Globals.getNumRecvHSRetrans();
    
    call AMSend.send(AM_BROADCAST_ADDR, &stats_msg, sizeof(StatsReport));
  }
  
  void sendStatusMsg(uint8_t flag, uint8_t channel) {
    StatusReport *report = (StatusReport *)call AMSend.getPayload(&status_msg);
    
    report->text[0] = 's';
    report->text[1] = 't';
    report->text[2] = 't';
    report->text[3] = 'u';
    report->text[4] = 's';
    report->flag = flag;
    report->channel = channel;
    
    call AMSend.send(AM_BROADCAST_ADDR, &status_msg, sizeof(StatusReport));
  }
  
  command void StatsCollector.sendVariableReport(uint32_t value) {
    VariableReport *report = (VariableReport *)call AMSend.getPayload(&variable_msg);
    
    report->text[0] = 'r';
    report->text[1] = 'e';
    report->text[2] = 'p';
    report->text[3] = 'r';
    report->text[4] = 't';
    report->value = value;
    
    call AMSend.send(AM_BROADCAST_ADDR, &variable_msg, sizeof(VariableReport));
  }
  
  command void StatsCollector.msg_bcastReq() {
    sendStatusMsg(BROADCAST_REQ, CC2420_DEF_CHANNEL);
  }
  
  event void Timer.fired() {
    sendStatsReport();
  }
  
  event void AMSend.sendDone(message_t* pstats_msg, error_t error) { }
  
  command void StatsCollector.startStatsCollector()
  {
    startTimer();
  }
  
  command void StatsCollector.stopStatsCollector()
  {
    stopTimer();
    call Timer.startOneShot(500);
    //sendStatsReport();   // Just in case
  }
  
  command void StatsCollector.startPubPktTransTime()
  {
    startPubTime = call LocalTime.get();
  }
  command void StatsCollector.endPubPktTransTime()
  {
    uint32_t diff = (call LocalTime.get()) - startPubTime;
    uint32_t temp = (call Globals.getAvgPubPktTransTime()) * (call Globals.getNumPubPktTrans());
    call Globals.incNumPubPktTrans();
    call Globals.setAvgPubPktTransTime((temp + diff) / (call Globals.getNumPubPktTrans()));
  }
  command void StatsCollector.startRecvPageTransTime(uint8_t channel)
  {
    startRecvTime = call LocalTime.get();
    sendStatusMsg(START_RECV_DATA, channel);
  }
  command void StatsCollector.endRecvPageTransTime(uint8_t senderAddr)
  {
    uint32_t curTime = call LocalTime.get();
    uint32_t temp = (call Globals.getAvgRecvPageTransTime()) * (call Globals.getNumRecvPageTrans());
    call Globals.incNumRecvPageTrans();
    call Globals.setAvgRecvPageTransTime((temp + (curTime - startRecvTime)) / (call Globals.getNumRecvPageTrans()));
    sendStatusMsg(END_RECV_DATA, senderAddr);
  }
  
  command void StatsCollector.incPub_numPktRetrans()
  {
    call Globals.incNumPubPktRetrans();
  }
  
  command void StatsCollector.startCCTime() {
    startCCTime = call LocalTime.get();
  }
  
  command void StatsCollector.endCCTime() {
    uint32_t diff = (call LocalTime.get()) - startCCTime;
    call StatsCollector.sendVariableReport(diff);
  }
  
  command void StatsCollector.incNumRecvHSRetrans() {
    call Globals.incNumRecvHSRetrans();
  }
}



More information about the Tinyos-2-commits mailing list