[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/scp-mac/tos/platform/mica2 CC1000Const.h, NONE, 1.1 CC1000Control.nc, NONE, 1.1 CC1000ControlM.nc, NONE, 1.1 HPLUART0M.nc, NONE, 1.1 PhyConst.h, NONE, 1.1 PhyRadio.nc, NONE, 1.1 PhyRadioM.nc, NONE, 1.1 PhyRadioMsg.h, NONE, 1.1 RadioControl.nc, NONE, 1.1 RadioControlM.nc, NONE, 1.1

Wei Ye weiyeisi at users.sourceforge.net
Tue May 6 10:31:00 PDT 2008


Update of /cvsroot/tinyos/tinyos-1.x/contrib/scp-mac/tos/platform/mica2
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv9805/scp-mac/tos/platform/mica2

Added Files:
	CC1000Const.h CC1000Control.nc CC1000ControlM.nc HPLUART0M.nc 
	PhyConst.h PhyRadio.nc PhyRadioM.nc PhyRadioMsg.h 
	RadioControl.nc RadioControlM.nc 
Log Message:
scp-mac implementation from USC/ISI

--- NEW FILE: CC1000Const.h ---

/* -*- Mode: C; c-basic-indent: 2; indent-tabs-mode: nil -*- */ 
/*									tab:4
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By
 *  downloading, copying, installing or using the software you agree to
 *  this license.  If you do not agree to this license, do not download,
 *  install, copy or use the software.
 *
 *  Intel Open Source License 
 *
 *  Copyright (c) 2002 Intel Corporation 
 *  All rights reserved. 
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 * 
 *	Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *      Neither the name of the Intel Corporation nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 */
/*
 *
 * Authors:		Phil Buonadonna
 * Date last modified:  1/10/03
 *
 */

/**
 * @author Phil Buonadonna
 */



#ifndef _CC1KCONST_H
#define _CC1KCONST_H

#include <avr/pgmspace.h>
/* Constants defined for CC1K */
/* Register addresses */

#define CC1K_MAIN            0x00
#define CC1K_FREQ_2A         0x01
#define CC1K_FREQ_1A         0x02
#define CC1K_FREQ_0A         0x03
#define CC1K_FREQ_2B         0x04
#define CC1K_FREQ_1B         0x05
#define CC1K_FREQ_0B         0x06
#define CC1K_FSEP1           0x07
#define CC1K_FSEP0           0x08
#define CC1K_CURRENT         0x09
#define CC1K_FRONT_END       0x0A //10
#define CC1K_PA_POW          0x0B //11
#define CC1K_PLL             0x0C //12
#define CC1K_LOCK            0x0D //13
#define CC1K_CAL             0x0E //14
#define CC1K_MODEM2          0x0F //15
#define CC1K_MODEM1          0x10 //16
#define CC1K_MODEM0          0x11 //17
#define CC1K_MATCH           0x12 //18
#define CC1K_FSCTRL          0x13 //19
#define CC1K_FSHAPE7         0x14 //20
#define CC1K_FSHAPE6         0x15 //21
#define CC1K_FSHAPE5         0x16 //22
#define CC1K_FSHAPE4         0x17 //23
#define CC1K_FSHAPE3         0x18 //24
#define CC1K_FSHAPE2         0x19 //25
#define CC1K_FSHAPE1         0x1A //26
#define CC1K_FSDELAY         0x1B //27
#define CC1K_PRESCALER       0x1C //28
#define CC1K_TEST6           0x40 //64
#define CC1K_TEST5           0x41 //66
#define CC1K_TEST4           0x42 //67
#define CC1K_TEST3           0x43 //68
#define CC1K_TEST2           0x44 //69
#define CC1K_TEST1           0x45 //70
#define CC1K_TEST0           0x46 //71

// MAIN Register Bit Posititions
#define CC1K_RXTX		7
#define CC1K_F_REG		6
#define CC1K_RX_PD		5
#define CC1K_TX_PD		4
#define CC1K_FS_PD		3
#define CC1K_CORE_PD		2
#define CC1K_BIAS_PD		1
#define CC1K_RESET_N		0

// CURRENT Register Bit Positions
#define CC1K_VCO_CURRENT	4
#define CC1K_LO_DRIVE		2
#define CC1K_PA_DRIVE		0

// FRONT_END Register Bit Positions
#define CC1K_BUF_CURRENT	5
#define CC1K_LNA_CURRENT	3
#define CC1K_IF_RSSI		1
#define CC1K_XOSC_BYPASS	0

// PA_POW Register Bit Positions
#define CC1K_PA_HIGHPOWER	4
#define CC1K_PA_LOWPOWER	0

// PLL Register Bit Positions
#define CC1K_EXT_FILTER		7
#define CC1K_REFDIV		3
#define CC1K_ALARM_DISABLE	2
#define CC1K_ALARM_H		1
#define CC1K_ALARM_L		0

// LOCK Register Bit Positions
#define CC1K_LOCK_SELECT	4
#define CC1K_PLL_LOCK_ACCURACY	3
#define CC1K_PLL_LOCK_LENGTH	2
#define CC1K_LOCK_INSTANT	1
#define CC1K_LOCK_CONTINUOUS	0

// CAL Register Bit Positions
#define CC1K_CAL_START		7
#define CC1K_CAL_DUAL		6
#define CC1K_CAL_WAIT		5
#define CC1K_CAL_CURRENT	4
#define CC1K_CAL_COMPLETE	3
#define CC1K_CAL_ITERATE	0

// MODEM2 Register Bit Positions
#define CC1K_PEAKDETECT		7
#define CC1K_PEAK_LEVEL_OFFSET	0

// MODEM1 Register Bit Positions
#define CC1K_MLIMIT		5
#define CC1K_LOCK_AVG_IN	4
#define CC1K_LOCK_AVG_MODE	3
#define CC1K_SETTLING		1
#define CC1K_MODEM_RESET_N	0

// MODEM0 Register Bit Positions
#define CC1K_BAUDRATE		4
#define CC1K_DATA_FORMAT	2
#define CC1K_XOSC_FREQ		0

// MATCH Register Bit Positions
#define CC1K_RX_MATCH		4
#define CC1K_TX_MATCH		0

// FSCTLR Register Bit Positions
#define CC1K_DITHER1		3
#define CC1K_DITHER0		2
#define CC1K_SHAPE		1
#define CC1K_FS_RESET_N		0

// PRESCALER Register Bit Positions
#define CC1K_PRE_SWING		6
#define CC1K_PRE_CURRENT	4
#define CC1K_IF_INPUT		3
#define CC1K_IF_FRONT		2

// TEST6 Register Bit Positions
#define CC1K_LOOPFILTER_TP1	7
#define CC1K_LOOPFILTER_TP2	6
#define CC1K_CHP_OVERRIDE	5
#define CC1K_CHP_CO		0

// TEST5 Register Bit Positions
#define CC1K_CHP_DISABLE	5
#define CC1K_VCO_OVERRIDE	4
#define CC1K_VCO_AO		0

// TEST3 Register Bit Positions
#define CC1K_BREAK_LOOP		4
#define CC1K_CAL_DAC_OPEN	0


/* 
 * CC1K Register Parameters Table
 *
 * This table follows the same format order as the CC1K register 
 * set EXCEPT for the last entry in the table which is the 
 * CURRENT register value for TX mode.
 *  
 * NOTE: To save RAM space, this table resides in program memory (flash). 
 * This has two important implications:
 *	1) You can't write to it (duh!)
 *	2) You must read it using the PRG_RDB(addr) macro. IT CANNOT BE ACCESSED AS AN ORDINARY C ARRAY.  
 * 
 * Add/remove individual entries below to suit your RF tastes.
 * 
 */
#define CC1K_433_002_MHZ	0x00
#define CC1K_915_998_MHZ	0x01
#define CC1K_434_845_MHZ        0x02
#define CC1K_914_077_MHZ        0x03
#define CC1K_315_178_MHZ        0x04

#ifdef CC1K_DEFAULT_FREQ
#define CC1K_DEF_PRESET (CC1K_DEFAULT_FREQ)
#endif
#ifdef CC1K_MANUAL_FREQ
#define CC1K_DEF_FREQ (CC1K_MANUAL_FREQ)
#endif

#ifndef CC1K_DEF_PRESET
#define CC1K_DEF_PRESET	(CC1K_433_002_MHZ)
#endif 


//#define CC1K_SquelchInit        0x02F8 // 0.90V using the bandgap reference
#define CC1K_SquelchInit        0x120
#define CC1K_SquelchTableSize   9     
#define CC1K_MaxRSSISamples     5
#define CC1K_Settling           1
#define CC1K_ValidPrecursor     2
#define CC1K_SquelchIntervalFast 128
#define CC1K_SquelchIntervalSlow 2560
#define CC1K_SquelchCount       30
#define CC1K_SquelchBuffer      16

#define CC1K_LPL_STATES         9

#define CC1K_LPL_PACKET_TIME    16

static const prog_uchar CC1K_LPL_PreambleLength[CC1K_LPL_STATES*2] = {
    0, 6,       // Always on, 6 byte preamble
    0x0, 48,    // 10ms check interval
    0x0, 60,    // 25ms 
    0x0, 144,   // 50ms 
    0x1, 0x0f,  // 100ms
    0x1, 0xf8,  // 200ms
    0x3, 0xd9,  // 400ms
    0x7, 0x9b,  // 800ms
    0xf, 0x06,  // 1600ms
};

static const prog_uchar CC1K_LPL_SleepTime[CC1K_LPL_STATES*2] = {
    0, 0,       //0
    0x0, 10,    // 10ms
    0x0, 25,    // 25ms
    0x0, 50,    // 50ms
    0x0, 100,   // 100ms
    0x0, 200,   // 200ms
    0x1, 0x90,  // 400ms
    0x3, 0x20,  // 800ms
    0x6, 0x40,  // 1600ms
};

static const prog_uchar CC1K_LPL_SleepPreamble[CC1K_LPL_STATES] = {
    0, 
    8,
    8,
    8, 
    8,
    8,
    8,
    8
};


static const prog_uchar CC1K_Params[6][31] = {
  // (0) 433.002 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO
  { // MAIN   0x00
    0x31,
    // FREQ2A,FREQ1A,FREQ0A  0x01-0x03
    0x58,0x00,0x00,					
    // FREQ2B,FREQ1B,FREQ0B  0x04-0x06
    0x57,0xf6,0x85,    //XBOW
    // FSEP1, FSEP0     0x07-0x08
    0X03,0x55,
    // CURRENT (RX MODE VALUE)   0x09 (also see below)
    ((4<<CC1K_VCO_CURRENT) | (1<<CC1K_LO_DRIVE)),	
    // FRONT_END  0x0a
    ((1<<CC1K_IF_RSSI)),
    // PA_POW  0x0b
    ((0x0<<CC1K_PA_HIGHPOWER) | (0xf<<CC1K_PA_LOWPOWER)), 
    // PLL  0x0c
    ((12<<CC1K_REFDIV)),		
    // LOCK  0x0d
    ((0xe<<CC1K_LOCK_SELECT)),
    // CAL  0x0e
    ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)),	
    // MODEM2  0x0f
    ((0<<CC1K_PEAKDETECT) | (28<<CC1K_PEAK_LEVEL_OFFSET)),
    // MODEM1  0x10
    ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | (CC1K_Settling<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N)), 
    // MODEM0  0x11
    ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | (1<<CC1K_XOSC_FREQ)),
    // MATCH  0x12
    ((0x7<<CC1K_RX_MATCH) | (0x0<<CC1K_TX_MATCH)),
    // FSCTRL 0x13
    ((1<<CC1K_FS_RESET_N)),			
    // FSHAPE7 - FSHAPE1   0x14-0x1a
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,	
    // FSDELAY   0x1b
    0x00,	
    // PRESCALER    0x1c
    0x00,
    // CURRENT (TX MODE VALUE)  0x1d
    ((8<<CC1K_VCO_CURRENT) | (1<<CC1K_PA_DRIVE)),
    // High side LO  0x1e (i.e. do we need to invert the data?)
    TRUE
  },

  // (1) 915.9988 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO
  { // MAIN   0x00 
    0x31,
    // FREQ2A,FREQ1A,FREQ0A  0x01-0x03
    0x7c,0x00,0x00,					
    // FREQ2B,FREQ1B,FREQ0B  0x04-0x06
    0x7b,0xf9,0xae,					
    // FSEP1, FSEP0     0x07-0x8
    0x02,0x38,
    // CURRENT (RX MODE VALUE)   0x09 (also see below)
    ((8<<CC1K_VCO_CURRENT) | (3<<CC1K_LO_DRIVE)),
    //0x8C,	
    // FRONT_END  0x0a
    ((1<<CC1K_BUF_CURRENT) | (2<<CC1K_LNA_CURRENT) | (1<<CC1K_IF_RSSI)),
    //0x32,
    // PA_POW  0x0b
    ((0x8<<CC1K_PA_HIGHPOWER) | (0x0<<CC1K_PA_LOWPOWER)), 
    //0xff,
    // PLL  0xc
    ((8<<CC1K_REFDIV)),		
    //0x40,
    // LOCK  0xd
    ((0x1<<CC1K_LOCK_SELECT)),
    //0x10,
    // CAL  0xe
    ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)),	
    //0x26,
    // MODEM2  0xf
    ((1<<CC1K_PEAKDETECT) | (33<<CC1K_PEAK_LEVEL_OFFSET)),
    //0xA1,
    // MODEM1  0x10
    ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | (CC1K_Settling<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N)), 
    //0x6f, 
    // MODEM0  0x11
    ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | (1<<CC1K_XOSC_FREQ)),
    //0x55,
    // MATCH 0x12
    ((0x1<<CC1K_RX_MATCH) | (0x0<<CC1K_TX_MATCH)),
    //0x10,
    // FSCTRL  0x13
    ((1<<CC1K_FS_RESET_N)),			
    //0x01,
    // FSHAPE7 - FSHAPE1   0x14..0x1a
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,	
    // FSDELAY   0x1b
    0x00,	
    // PRESCALER    0x1c
    0x00,
    // CURRENT (TX MODE VALUE)  0x1d
    ((15<<CC1K_VCO_CURRENT) | (3<<CC1K_PA_DRIVE)),
    //0xf3,
    // High side LO  0x1e (i.e. do we need to invert the data?)
    TRUE
  },

  // (2) 434.845200 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO
  { // MAIN   0x00
    0x31,
    // FREQ2A,FREQ1A,FREQ0A  0x01-0x03
    0x51,0x00,0x00,					
    // FREQ2B,FREQ1B,FREQ0B  0x04-0x06
    0x50,0xf7,0x4F,    //XBOW
    // FSEP1, FSEP0     0x07-0x08
    0X03,0x0E,
    // CURRENT (RX MODE VALUE)   0x09 (also see below)
    ((4<<CC1K_VCO_CURRENT) | (1<<CC1K_LO_DRIVE)),	
    // FRONT_END  0x0a
    ((1<<CC1K_IF_RSSI)),
    // PA_POW  0x0b
    ((0x0<<CC1K_PA_HIGHPOWER) | (0xf<<CC1K_PA_LOWPOWER)), 
    // PLL  0x0c
    ((11<<CC1K_REFDIV)),		
    // LOCK  0x0d
    ((0xe<<CC1K_LOCK_SELECT)),
    // CAL  0x0e
    ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)),	
    // MODEM2  0x0f
    ((1<<CC1K_PEAKDETECT) | (33<<CC1K_PEAK_LEVEL_OFFSET)),
    // MODEM1  0x10
    ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | (CC1K_Settling<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N)), 
    // MODEM0  0x11
    ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | (1<<CC1K_XOSC_FREQ)),
    // MATCH  0x12
    ((0x7<<CC1K_RX_MATCH) | (0x0<<CC1K_TX_MATCH)),
    // FSCTRL 0x13
    ((1<<CC1K_FS_RESET_N)),			
    // FSHAPE7 - FSHAPE1   0x14-0x1a
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,	
    // FSDELAY   0x1b
    0x00,	
    // PRESCALER    0x1c
    0x00,
    // CURRENT (TX MODE VALUE)  0x1d
    ((8<<CC1K_VCO_CURRENT) | (1<<CC1K_PA_DRIVE)),
    // High side LO  0x1e (i.e. do we need to invert the data?)
    TRUE
  },

 
  // (3) 914.077 MHz channel, 19.2 Kbps data, Manchester Encoding, High Side LO
  { // MAIN   0x00 
    0x31,
    // FREQ2A,FREQ1A,FREQ0A  0x01-0x03
    0x5c,0xe0,0x00,					
    // FREQ2B,FREQ1B,FREQ0B  0x04-0x06
    0x5c,0xdb,0x42,					
    // FSEP1, FSEP0     0x07-0x8
    0x01,0xAA,
    // CURRENT (RX MODE VALUE)   0x09 (also see below)
    ((8<<CC1K_VCO_CURRENT) | (3<<CC1K_LO_DRIVE)),
    //0x8C,	
    // FRONT_END  0x0a
    ((1<<CC1K_BUF_CURRENT) | (2<<CC1K_LNA_CURRENT) | (1<<CC1K_IF_RSSI)),
    //0x32,
    // PA_POW  0x0b
    ((0x8<<CC1K_PA_HIGHPOWER) | (0x0<<CC1K_PA_LOWPOWER)), 
    //0xff,
    // PLL  0xc
    ((6<<CC1K_REFDIV)),		
    //0x40,
    // LOCK  0xd
    ((0x1<<CC1K_LOCK_SELECT)),
    //0x10,
    // CAL  0xe
    ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)),	
    //0x26,
    // MODEM2  0xf
    ((1<<CC1K_PEAKDETECT) | (33<<CC1K_PEAK_LEVEL_OFFSET)),
    //0xA1,
    // MODEM1  0x10
    ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | (CC1K_Settling<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N)), 
    //0x6f, 
    // MODEM0  0x11
    ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | (1<<CC1K_XOSC_FREQ)),
    //0x55,
    // MATCH 0x12
    ((0x1<<CC1K_RX_MATCH) | (0x0<<CC1K_TX_MATCH)),
    //0x10,
    // FSCTRL  0x13
    ((1<<CC1K_FS_RESET_N)),			
    //0x01,
    // FSHAPE7 - FSHAPE1   0x14..0x1a
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,	
    // FSDELAY   0x1b
    0x00,	
    // PRESCALER    0x1c
    0x00,
    // CURRENT (TX MODE VALUE)  0x1d
    ((15<<CC1K_VCO_CURRENT) | (3<<CC1K_PA_DRIVE)),
    //0xf3,
    // High side LO  0x1e (i.e. do we need to invert the data?)
    TRUE 
  },

  // (4) 315.178985 MHz channel, 38.4 Kbps data, Manchester Encoding, High Side LO
  { // MAIN   0x00
    0x31,
    // FREQ2A,FREQ1A,FREQ0A  0x01-0x03
    0x45,0x60,0x00,					
    // FREQ2B,FREQ1B,FREQ0B  0x04-0x06
    0x45,0x55,0xBB,
    // FSEP1, FSEP0     0x07-0x08
    0X03,0x9C,
    // CURRENT (RX MODE VALUE)   0x09 (also see below)
    ((8<<CC1K_VCO_CURRENT) | (0<<CC1K_LO_DRIVE)),	
    // FRONT_END  0x0a
    ((1<<CC1K_IF_RSSI)),
    // PA_POW  0x0b
    ((0x0<<CC1K_PA_HIGHPOWER) | (0xf<<CC1K_PA_LOWPOWER)), 
    // PLL  0x0c
    ((13<<CC1K_REFDIV)),		
    // LOCK  0x0d
    ((0xe<<CC1K_LOCK_SELECT)),
    // CAL  0x0e
    ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)),	
    // MODEM2  0x0f
    ((1<<CC1K_PEAKDETECT) | (33<<CC1K_PEAK_LEVEL_OFFSET)),
    // MODEM1  0x10
    ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | (CC1K_Settling<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N)), 
    // MODEM0  0x11
    ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | (0<<CC1K_XOSC_FREQ)),
    // MATCH  0x12
    ((0x7<<CC1K_RX_MATCH) | (0x0<<CC1K_TX_MATCH)),
    // FSCTRL 0x13
    ((1<<CC1K_FS_RESET_N)),			
    // FSHAPE7 - FSHAPE1   0x14-0x1a
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,	
    // FSDELAY   0x1b
    0x00,	
    // PRESCALER    0x1c
    0x00,
    // CURRENT (TX MODE VALUE)  0x1d
    ((8<<CC1K_VCO_CURRENT) | (1<<CC1K_PA_DRIVE)),
    // High side LO  0x1e (i.e. do we need to invert the data?)
    TRUE
  },

  // (5) Spare
  { // MAIN   0x00
    0x31,
    // FREQ2A,FREQ1A,FREQ0A  0x01-0x03
    0x58,0x00,0x00,					
    // FREQ2B,FREQ1B,FREQ0B  0x04-0x06
    0x57,0xf6,0x85,    //XBOW
    // FSEP1, FSEP0     0x07-0x08
    0X03,0x55,
    // CURRENT (RX MODE VALUE)   0x09 (also see below)
    ((8<<CC1K_VCO_CURRENT) | (4<<CC1K_LO_DRIVE)),	
    // FRONT_END  0x0a
    ((1<<CC1K_IF_RSSI)),
    // PA_POW  0x0b
    ((0x0<<CC1K_PA_HIGHPOWER) | (0xf<<CC1K_PA_LOWPOWER)), 
    // PLL  0x0c
    ((12<<CC1K_REFDIV)),		
    // LOCK  0x0d
    ((0xe<<CC1K_LOCK_SELECT)),
    // CAL  0x0e
    ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)),	
    // MODEM2  0x0f
    ((1<<CC1K_PEAKDETECT) | (33<<CC1K_PEAK_LEVEL_OFFSET)),
    // MODEM1  0x10
    ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | (CC1K_Settling<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N)),    // MODEM0  0x11
    ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | (1<<CC1K_XOSC_FREQ)),
    // MATCH  0x12
    ((0x7<<CC1K_RX_MATCH) | (0x0<<CC1K_TX_MATCH)),
    // FSCTRL 0x13
    ((1<<CC1K_FS_RESET_N)),			
    // FSHAPE7 - FSHAPE1   0x14-0x1a
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,	
    // FSDELAY   0x1b
    0x00,	
    // PRESCALER    0x1c
    0x00,
    // CURRENT (TX MODE VALUE)  0x1d
    ((8<<CC1K_VCO_CURRENT) | (1<<CC1K_PA_DRIVE)),
    // High side LO  0x1e (i.e. do we need to invert the data?)
    TRUE
  },
};

#endif /* _CC1KCONST_H */

--- NEW FILE: CC1000Control.nc ---
/*									tab:4
 *
 *
 * "Copyright (c) 2000-2002 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."
 *
 */
/*									tab:4
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By
 *  downloading, copying, installing or using the software you agree to
 *  this license.  If you do not agree to this license, do not download,
 *  install, copy or use the software.
 *
 *  Intel Open Source License 
 *
 *  Copyright (c) 2002 Intel Corporation 
 *  All rights reserved. 
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 * 
 *	Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *      Neither the name of the Intel Corporation nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 */
/*
 *
 * Authors:		Philip Buonadonna, Jaein Jeong
 * Date last modified:  $Revision: 1.1 $
 *
 * Interface for CC1000 specific controls and signals
 */

/**
 * CC1000 Radio Control interface.
 */
interface CC1000Control
{
  /**
   * Tune the radio to one of the frequencies available in the CC1K_Params table.
   * Calling Tune will allso reset the rfpower and LockVal selections to the table 
   * values. 
   * 
   * @param freq The index into the CC1K_Params table that holds the desired preset
   * frequency parameters.
   * 
   * @return Status of the Tune operation.
   */

  command result_t TunePreset(uint8_t freq); 

  /**
   * Tune the radio to a given frequency. Since the CC1000 uses a digital
   * frequency synthesizer, it cannot tune to just an arbitrary frequency.
   * This routine will determine the closest achievable channel, compute 
   * the necessary parameters and tune the radio.
   * 
   * @param The desired channel frequency, in Hz.
   * 
   * @return The actual computed channel frequency, in Hz.  A return value
   * of '0' indicates that no frequency was computed and the radio was not
   * tuned.
   */

  command uint32_t TuneManual(uint32_t DesiredFreq);

  /**
   * Shift the CC1000 Radio into transmit mode.
   *
   * @return SUCCESS if the radio was successfully switched to TX mode.
   */

  async command result_t TxMode();

  /**
   * Shift the CC1000 Radio in receive mode.
   *
   * @return SUCCESS if the radio was successfully switched to RX mode.
   */

  async command result_t RxMode();

  /**
   * Turn off the BIAS power on the CC1000 radio, but leave the core 
   * and crystal oscillator powered.  This will result in approximately
   * a 750 uA power savings. 
   *
   * @return SUCCESS when the BIAS powered is shutdown.
   */

  command result_t BIASOff();			

  /**
   * Turn the BIAS power on. This function must be followed by a call
   * to either RxMode() or TxMode() to place the radio in a recieve/transmit
   * state respectively. There is approximately a 200us delay when restoring
   * BIAS power.
   *
   * @return SUCCESS when BIAS power has been restored.
   */

  command result_t BIASOn();			

  /**
   * Set the transmit RF power value.  The input value is simply an arbitrary
   * index that is programmed into the CC1000 registers.  Consult the CC1000
   * datasheet for the resulting power output/current consumption values.
   *
   * @param power A power index between 1 and 255.
   * 
   * @result SUCCESS if the radio power was adequately set.
   *
   */

  command result_t SetRFPower(uint8_t power);	

  /**
   * Get the present RF power index.
   *
   * @result The power index value.
   */

  command uint8_t  GetRFPower();		

  /** 
   * Select the signal to monitor at the CHP_OUT pin of the CC1000.  See the
   * CC1000 data sheet for the available signals.
   * 
   * @param LockVal The index of the signal to monitor at the CHP_OUT pin
   * 
   * @result SUCCESS if the selected signal was programmed into the CC1000
   *
   */

  command result_t SelectLock(uint8_t LockVal); 

  /**
   * Get the binary value from the CHP_OUT pin.  Analog signals cannot be read using
   * function.
   *
   * @result 1 - Pin is high or 0 - Pin is low
   *
   */

  command uint8_t  GetLock();

  /**
   * Returns whether the present frequency set is using high-side LO injection or not.  
   * This information is used to determine if the data from the CC1000 needs to be inverted
   * or not. 
   *
   * @result TRUE if high-side LO injection is being used (i.e. data does NOT need to be inverted
   * at the receiver.
   */
  command bool	   GetLOStatus();		// Query if frequency set LO side. High side LO = TRUE
}

--- NEW FILE: CC1000ControlM.nc ---
/*									tab:4
 *
 *
 * "Copyright (c) 2000-2002 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."
 *
 */
/*									tab:4
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By
 *  downloading, copying, installing or using the software you agree to
 *  this license.  If you do not agree to this license, do not download,
 *  install, copy or use the software.
 *
 *  Intel Open Source License 
 *
 *  Copyright (c) 2002 Intel Corporation 
 *  All rights reserved. 
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 * 
 *	Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *	Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *      Neither the name of the Intel Corporation nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 */
/*
 *
 * Authors:		Jaein Jeong, Phil Buonadonna
 * Date last modified:  $Revision: 1.1 $
 *
 * This module provides the CONTROL functionality for the Chipcon1000 series radio.
 * It exports both a standard control interface and a custom interface to control
 * CC1000 operation.
 */

module CC1000ControlM {
  provides {
    interface StdControl;
    interface CC1000Control;
  }
  uses {
    interface HPLCC1000 as HPLChipcon;
  }
}
implementation
{
  uint32_t gCurrentChannel;
  norace uint8_t gCurrentParameters[31];

  enum {
    IF = 150000,
    FREQ_MIN = 4194304,
    FREQ_MAX = 16751615
  };

  const uint32_t FRefTbl[9] = {2457600,
			       2106514,
			       1843200,
			       1638400,
			       1474560,
			       1340509,
			       1228800,
			       1134277,
			       1053257};
  
  const uint16_t CorTbl[9] = {1213,
			      1416,
			      1618,
			      1820,
			      2022,
			      2224,
			      2427,
			      2629,
			      2831};
  
  const uint16_t FSepTbl[9] = {0x1AA,
			       0x1F1,
			       0x238,
			       0x280,
			       0x2C7,
			       0x30E,
			       0x355,
			       0x39C,
			       0x3E3};
  
  //
  // PRIVATE Module functions
  //

  ///************************************************************/
  ///* Function: chipcon_cal                                    */
  ///* Description: places the chipcon radio in calibrate mode  */
  ///*                                                          */
  ///************************************************************/

  result_t chipcon_cal()
  {
    //int i;
    //int freq = tunefreq;

    call HPLChipcon.write(CC1K_PA_POW,0x00);  // turn off rf amp
    call HPLChipcon.write(CC1K_TEST4,0x3f);   // chip rate >= 38.4kb

    // RX - configure main freq A
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_TX_PD) | (1<<CC1K_RESET_N)));
    //TOSH_uwait(2000);

    // start cal
    call HPLChipcon.write(CC1K_CAL,
			  ((1<<CC1K_CAL_START) | 
			   (1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
#if 0
    for (i=0;i<34;i++)  // need 34 ms delay
      TOSH_uwait(1000);
#endif
    while (((call HPLChipcon.read(CC1K_CAL)) & (1<<CC1K_CAL_COMPLETE)) == 0);

    //exit cal mode
    call HPLChipcon.write(CC1K_CAL,
			  ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));


    // TX - configure main freq B
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RXTX) | (1<<CC1K_F_REG) | (1<<CC1K_RX_PD) | 
			   (1<<CC1K_RESET_N)));
    // Set TX current
    call HPLChipcon.write(CC1K_CURRENT,gCurrentParameters[29]);
    call HPLChipcon.write(CC1K_PA_POW,0x00);
    //TOSH_uwait(2000);

    // start cal
    call HPLChipcon.write(CC1K_CAL,
			  ((1<<CC1K_CAL_START) | 
			   (1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
#if 0
    for (i=0;i<28;i++)  // need 28 ms delay
      TOSH_uwait(1000);
#endif
    while (((call HPLChipcon.read(CC1K_CAL)) & (1<<CC1K_CAL_COMPLETE)) == 0);

    //exit cal mode
    call HPLChipcon.write(CC1K_CAL,
			  ((1<<CC1K_CAL_WAIT) | (6<<CC1K_CAL_ITERATE)));
    
    //TOSH_uwait(200);

    return SUCCESS;
  }

  void cc1000SetFreq() {
    uint8_t i;
    // FREQA, FREQB, FSEP, CURRENT(RX), FRONT_END, POWER, PLL
    for (i = 1;i < 0x0d;i++) {
      call HPLChipcon.write(i,gCurrentParameters[i]);
    }

    // MATCH
    call HPLChipcon.write(CC1K_MATCH,gCurrentParameters[0x12]);

    chipcon_cal();

    return;

  }

  void cc1000SetModem() {
    call HPLChipcon.write(CC1K_MODEM2,gCurrentParameters[0x0f]);
    call HPLChipcon.write(CC1K_MODEM1,gCurrentParameters[0x10]);
    call HPLChipcon.write(CC1K_MODEM0,gCurrentParameters[0x11]);

    return;

  }

  /*
   * cc1000ComputeFreq(uint32_t desiredFreq);
   *
   * Compute an achievable frequency and the necessary CC1K parameters from
   * a given desired frequency (Hz). The function returns the actual achieved
   * channel frequency in Hz.
   *
   * This routine assumes the following:
   *  - Crystal Freq: 14.7456 MHz
   *  - LO Injection: High
   *  - Separation: 64 KHz
   *  - IF: 150 KHz
   * 
   * Approximate costs for this function:
   *  - ~870 bytes FLASH
   *  - ~32 bytes RAM
   *  - 9400 cycles
   */
  uint32_t cc1000ComputeFreq(uint32_t desiredFreq) {
    uint32_t ActualChannel = 0;
    uint32_t RXFreq = 0, TXFreq = 0;
    int32_t Offset = 0x7fffffff;
    uint16_t FSep = 0;
    uint8_t RefDiv = 0;
    uint8_t i;

    for (i = 0; i < 9; i++) {

      uint32_t NRef = ((desiredFreq + IF));
      uint32_t FRef = FRefTbl[i];
      uint32_t Channel = 0;
      uint32_t RXCalc = 0, TXCalc = 0;
      int32_t  diff;

      NRef = ((desiredFreq + IF) << 2) / FRef;
      if (NRef & 0x1) {
 	NRef++;
      }

      if (NRef & 0x2) {
	RXCalc = 16384 >> 1;
	Channel = FRef >> 1;
      }

      NRef >>= 2;

      RXCalc += (NRef * 16384) - 8192;
      if ((RXCalc < FREQ_MIN) || (RXCalc > FREQ_MAX)) 
	continue;
    
      TXCalc = RXCalc - CorTbl[i];
      if ((TXCalc < FREQ_MIN) || (TXCalc > FREQ_MAX)) 
	continue;

      Channel += (NRef * FRef);
      Channel -= IF;

      diff = Channel - desiredFreq;
      if (diff < 0)
	diff = 0 - diff;

      if (diff < Offset) {
	RXFreq = RXCalc;
	TXFreq = TXCalc;
	ActualChannel = Channel;
	FSep = FSepTbl[i];
	RefDiv = i + 6;
	Offset = diff;
      }

    }

    if (RefDiv != 0) {
      // FREQA
      gCurrentParameters[0x3] = (uint8_t)((RXFreq) & 0xFF);  // LSB
      gCurrentParameters[0x2] = (uint8_t)((RXFreq >> 8) & 0xFF);
      gCurrentParameters[0x1] = (uint8_t)((RXFreq >> 16) & 0xFF);  // MSB
      // FREQB
      gCurrentParameters[0x6] = (uint8_t)((TXFreq) & 0xFF); // LSB
      gCurrentParameters[0x5] = (uint8_t)((TXFreq >> 8) & 0xFF);
      gCurrentParameters[0x4] = (uint8_t)((TXFreq >> 16) & 0xFF);  // MSB
      // FSEP
      gCurrentParameters[0x8] = (uint8_t)((FSep) & 0xFF);  // LSB
      gCurrentParameters[0x7] = (uint8_t)((FSep >> 8) & 0xFF); //MSB

      if (ActualChannel < 500000000) {
	if (ActualChannel < 400000000) {
	// CURRENT (RX)
	  gCurrentParameters[0x9] = ((8 << CC1K_VCO_CURRENT) | (1 << CC1K_LO_DRIVE));
	// CURRENT (TX)
	  gCurrentParameters[0x1d] = ((9 << CC1K_VCO_CURRENT) | (1 << CC1K_PA_DRIVE));
	}
	else {
	// CURRENT (RX)
	  gCurrentParameters[0x9] = ((4 << CC1K_VCO_CURRENT) | (1 << CC1K_LO_DRIVE));
	// CURRENT (TX)
	  gCurrentParameters[0x1d] = ((8 << CC1K_VCO_CURRENT) | (1 << CC1K_PA_DRIVE));
	}
	// FRONT_END
	gCurrentParameters[0xa] = (1 << CC1K_IF_RSSI); 
	// MATCH
	gCurrentParameters[0x12] = (7 << CC1K_RX_MATCH);
      }
      else {
	// CURRENT (RX)
	  gCurrentParameters[0x9] = ((8 << CC1K_VCO_CURRENT) | (3 << CC1K_LO_DRIVE));
	// CURRENT (TX)
	  gCurrentParameters[0x1d] = ((15 << CC1K_VCO_CURRENT) | (3 << CC1K_PA_DRIVE));

	// FRONT_END
	gCurrentParameters[0xa] = ((1<<CC1K_BUF_CURRENT) | (2<<CC1K_LNA_CURRENT) | 
				 (1<<CC1K_IF_RSSI));
	// MATCH
	gCurrentParameters[0x12] = (2 << CC1K_RX_MATCH);

      }
      // PLL
      gCurrentParameters[0xc] = (RefDiv << CC1K_REFDIV);
    }

    gCurrentChannel = ActualChannel;
    return ActualChannel;

  }


  //
  // PUBLIC Module Functions
  //

  command result_t StdControl.init() {
    outp (0x41,TCCR3B);
    call HPLChipcon.init();

    // wake up xtal and reset unit
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
			   (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD))); 
    // clear reset.
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
			   (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD) |
			   (1<<CC1K_RESET_N))); 
    // reset wait time
    TOSH_uwait(2000);        

    // Set default parameter values
    // POWER 0dbm
    gCurrentParameters[0xb] = ((8 << CC1K_PA_HIGHPOWER) | (0 << CC1K_PA_LOWPOWER)); 
    call HPLChipcon.write(CC1K_PA_POW, gCurrentParameters[0xb]);

    // LOCK Manchester Violation default
    gCurrentParameters[0xd] = (9 << CC1K_LOCK_SELECT);
    call HPLChipcon.write(CC1K_LOCK_SELECT, gCurrentParameters[0xd]);

    // Default modem values = 19.2 Kbps (38.4 kBaud), Manchester encoded
    // MODEM2
    gCurrentParameters[0xf] = 0;
    //call HPLChipcon.write(CC1K_MODEM2,gCurrentParameters[0xf]);
    // MODEM1
    gCurrentParameters[0x10] = ((3<<CC1K_MLIMIT) | (1<<CC1K_LOCK_AVG_MODE) | 
				(3<<CC1K_SETTLING) | (1<<CC1K_MODEM_RESET_N));
    //call HPLChipcon.write(CC1K_MODEM1,gCurrentParameters[0x10]);
    // MODEM0
    gCurrentParameters[0x11] = ((5<<CC1K_BAUDRATE) | (1<<CC1K_DATA_FORMAT) | 
				(1<<CC1K_XOSC_FREQ));
    //call HPLChipcon.write(CC1K_MODEM0,gCurrentParameters[0x11]);

    cc1000SetModem();
    // FSCTRL
    gCurrentParameters[0x13] = (1 << CC1K_FS_RESET_N);
    call HPLChipcon.write(CC1K_FSCTRL,gCurrentParameters[0x13]);

    // HIGH Side LO
    gCurrentParameters[0x1e] = TRUE;


    // Program registers w/ default freq and calibrate
#ifdef CC1K_DEF_FREQ
    call CC1000Control.TuneManual(CC1K_DEF_FREQ);
#else
    call CC1000Control.TunePreset(CC1K_DEF_PRESET);     // go to default tune frequency
#endif
    return SUCCESS;
  }



  command result_t CC1000Control.TunePreset(uint8_t freq) {
    int i;

    for (i=1;i < 31 /*0x14*/;i++) {
      //call HPLChipcon.write(i,PRG_RDB(&CC1K_Params[freq][i]));
      gCurrentParameters[i] = PRG_RDB(&CC1K_Params[freq][i]);
    }
    cc1000SetFreq();

    return SUCCESS;
  }

  command uint32_t CC1000Control.TuneManual(uint32_t DesiredFreq) {
    uint32_t actualFreq;

    actualFreq = cc1000ComputeFreq(DesiredFreq);

    cc1000SetFreq();

    return actualFreq;
  }

  async command result_t CC1000Control.TxMode() {
    // MAIN register to TX mode
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RXTX) | (1<<CC1K_F_REG) | (1<<CC1K_RX_PD) | 
			   (1<<CC1K_RESET_N)));
    // Set the TX mode VCO Current
    call HPLChipcon.write(CC1K_CURRENT,gCurrentParameters[29]);
    TOSH_uwait(250);
    call HPLChipcon.write(CC1K_PA_POW,gCurrentParameters[0xb] /*rfpower*/);
    TOSH_uwait(20);
    return SUCCESS;
  }

  async command result_t CC1000Control.RxMode() {
    // MAIN register to RX mode
    // Powerup Freqency Synthesizer and Receiver
    call HPLChipcon.write(CC1K_CURRENT,gCurrentParameters[0x09]);
    call HPLChipcon.write(CC1K_PA_POW,0x00); // turn off power amp
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_TX_PD) | (1<<CC1K_RESET_N)));
    // Sex the RX mode VCO Current
    TOSH_uwait(125);
    return SUCCESS;
  }

  command result_t CC1000Control.BIASOff() {
    // MAIN register to SLEEP mode
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
			   (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD) |
			   (1<<CC1K_RESET_N)));
								 
    return SUCCESS;
  }

  command result_t CC1000Control.BIASOn() {
    //call CC1000Control.RxMode();
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
			   (1<<CC1K_FS_PD) | 
			   (1<<CC1K_RESET_N)));
    
    TOSH_uwait(200 /*500*/);
    return SUCCESS;
  }


  command result_t StdControl.stop() {
    // MAIN register to power down mode. Shut everything off
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
			   (1<<CC1K_FS_PD) | (1<<CC1K_CORE_PD) | (1<<CC1K_BIAS_PD) |
			   (1<<CC1K_RESET_N)));

    call HPLChipcon.write(CC1K_PA_POW,0x00);  // turn off rf amp
    return SUCCESS;
  }

  command result_t StdControl.start() {
    // wake up xtal osc
    call HPLChipcon.write(CC1K_MAIN,
			  ((1<<CC1K_RX_PD) | (1<<CC1K_TX_PD) | 
			   (1<<CC1K_FS_PD) | (1<<CC1K_BIAS_PD) |
			   (1<<CC1K_RESET_N)));

    //TOSH_uwait(2000);
//    call CC1000Control.RxMode();

    return SUCCESS;
  }


  command result_t CC1000Control.SetRFPower(uint8_t power) {
    gCurrentParameters[0xb] = power;
    //rfpower = power;
    //call HPLChipcon.write(CC1K_PA_POW,rfpower); // Set power amp value
    return SUCCESS;
  }

  command uint8_t CC1000Control.GetRFPower() {
    return gCurrentParameters[0xb]; //rfpower;
  }

  command result_t CC1000Control.SelectLock(uint8_t Value) {
    //LockVal = Value;
    gCurrentParameters[0xd] = (Value << CC1K_LOCK_SELECT);
    return call HPLChipcon.write(CC1K_LOCK,(Value << CC1K_LOCK_SELECT));
  }

  command uint8_t CC1000Control.GetLock() {
    uint8_t retVal;
    retVal = (uint8_t)call HPLChipcon.GetLOCK(); 
    return retVal;
  }

  command bool CC1000Control.GetLOStatus() {

    return gCurrentParameters[0x1e];

  }

}



--- NEW FILE: HPLUART0M.nc ---
// $Id: HPLUART0M.nc,v 1.1 2008/05/06 17:30:58 weiyeisi Exp $

/*									tab:4
 * "Copyright (c) 2000-2003 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Copyright (c) 2002-2003 Intel Corporation
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached INTEL-LICENSE     
 * file. If you do not find these files, copies can be found by writing to
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
 * 94704.  Attention:  Intel License Inquiry.
 */
/*
 *
 * Authors:		Jason Hill, David Gay, Philip Levis, Phil Buonadonna, Joe Polastre
 * Date last modified:  $Revision: 1.1 $
 *
 */

// The hardware presentation layer. See hpl.h for the C side.
// Note: there's a separate C side (hpl.h) to get access to the avr macros

// The model is that HPL is stateless. If the desired interface is as stateless
// it can be implemented here (Clock, FlashBitSPI). Otherwise you should
// create a separate component


/**
 * @author Jason Hill
 * @author David Gay
 * @author Philip Levis
 * @author Phil Buonadonna
 * @author Joe Polastre
 */

module HPLUART0M {
  provides interface HPLUART as UART;

}
implementation
{
  async command result_t UART.init() {

    // UART will run at:
    // 115kbps, N-8-1

    // Set 57.6 KBps
    outp(0,UBRR0H); 
//    outp(15, UBRR0L);  // 57600 at 7.3728MHz
    outp(16, UBRR0L);  // 57600 at 8MHz

    // Set UART double speed
    outp((1<<U2X),UCSR0A);

    // Set frame format: 8 data-bits, 1 stop-bit
    outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C);

    // Enable reciever and transmitter and their interrupts
    outp(((1 << RXCIE) | (1 << TXCIE) | (1 << RXEN) | (1 << TXEN)) ,UCSR0B);


    return SUCCESS;
  }

  async command result_t UART.stop() {
    outp(0x00, UCSR0A);
    outp(0x00, UCSR0B);
    outp(0x00, UCSR0C);
    return SUCCESS;
  }

  default async event result_t UART.get(uint8_t data) { return SUCCESS; }
  TOSH_SIGNAL(SIG_UART0_RECV) {
    if (inp(UCSR0A) & (1 << RXC))
      signal UART.get(inp(UDR0));
  }

  default async event result_t UART.putDone() { return SUCCESS; }

#ifdef ENABLE_UART_DEBUG
#warning "UART Interrups Redirected"
#else
  TOSH_INTERRUPT(SIG_UART0_TRANS) {
    signal UART.putDone();
  }
#endif

  command async result_t UART.put(uint8_t data) {
   atomic{
    outp(data, UDR0); 
    sbi(UCSR0A, TXC);
   }

    return SUCCESS;
  }
}

--- NEW FILE: PhyConst.h ---
/*
 * Copyright (C) 2003-2005 the University of Southern California.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * In addition to releasing this program under the LGPL, the authors are
 * willing to dual-license it under other terms. You may contact the authors
 * of this project by writing to Wei Ye, USC/ISI, 4676 Admirality Way, Suite 
 * 1001, Marina del Rey, CA 90292, USA.
 */
/*
 * Authors: Wei Ye
 *
 * Physical layer parameters
 */

#ifndef PHY_CONST
#define PHY_CONST

/***
 * These parameters are not user adjustable
 * but can be used by other components
 */

// the bandwidth on Mica2 radio is 38400b/s
// with Manchester coding, actual data rate is 19200b/s

// time to transmit a byte (binary microseconds)
// nominal value is 427, but measurement shows 428
#define PHY_TX_BYTE_TIME 428

// carrier sense sample interval (binary microseconds)
#define PHY_CS_SAMPLE_INTERVAL 428

// maximum carrier sense extension (bytes) when channel state can't be
// immediately determined by requested samples
//#define PHY_MAX_CS_EXT 4
#define PHY_MAX_CS_EXT 3

// transition delay from sleep to active (ms)
#define PHY_WAKEUP_DELAY 2

// number of sychronization bytes (start of a frame)
#define PHY_NUM_SYNC_BYTES 2

// base preamble length (bytes)
//#define BASE_PREAMBLE_LEN 18
#define PHY_BASE_PREAMBLE_LEN 8

// number of preamble bytes to be received for considering as valid preamble
//#define VALID_PRECURSOR 5
#define PHY_VALID_PRECURSOR 2

// number of bytes before each pkt with base preamble
#define PHY_BASE_PRE_BYTES (PHY_BASE_PREAMBLE_LEN + PHY_NUM_SYNC_BYTES)

// processing delay for each received packet (ms)
// mainly caused by noise level measurement
#define PHY_PROCESSING_DELAY 1

// Delay between timestamping outgoing packet and incoming packet
#define PHY_TIMESTAMP_DELAY 0 // in ms

// Time to load a packet into the CC2420 FIFO (before sending)
#define PHY_LOADTONE_DELAY 0 // in ms

// Number of tones used (only in micaz)
#define PHY_NUMBER_OF_TONES 0
#endif

--- NEW FILE: PhyRadio.nc ---
/*
 * Copyright (C) 2003-2005 the University of Southern California.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * In addition to releasing this program under the LGPL, the authors are
 * willing to dual-license it under other terms. You may contact the authors
 * of this project by writing to Wei Ye, USC/ISI, 4676 Admirality Way, Suite 
 * 1001, Marina del Rey, CA 90292, USA.
 */
/*
 * Authors: Wei Ye
 * 
 * This is the physical layer that sends and receives a packet
 *   - accept any type and length (<= PHY_MAX_PKT_LEN in phy_radio_msg.h) of packet
 *   - sending a packet: encoding and byte spooling
 *   - receiving a packet: decoding, byte buffering
 *   - Optional CRC check
 *   - interface to radio control and physical carrier sense
 */

configuration PhyRadio
{
   provides {
      interface StdControl as PhyControl;
      interface RadioState;
      interface PhyPkt;
      interface PhyNotify;
      interface TxPreamble as PhyTxPreamble;
      interface CarrierSense;
      interface CsThreshold;
      interface GetSetU8 as RadioTxPower;
      interface PhyStreamByte;
      interface RadioEnergy;
   }
}

implementation
{
   components PhyRadioM, RadioControl, CodecNone, LocalTimeC,

#if defined PHY_UART_DEBUG_STATE_EVENT
    UartDebugStateEvent as UartDbg,
#elif defined PHY_UART_DEBUG_BYTE
    UartDebugByte as UartDbg,
#else
    UartDebugNone as UartDbg,
#endif

#ifdef PHY_LED_DEBUG  
    LedsC;
#else
    NoLeds as LedsC;
#endif
   
  PhyControl = PhyRadioM;
  RadioState = PhyRadioM;
  PhyPkt = PhyRadioM;
  PhyNotify = PhyRadioM;
  PhyTxPreamble = PhyRadioM;
  PhyStreamByte = PhyRadioM;
  CarrierSense = RadioControl;
  CsThreshold = RadioControl;
  RadioTxPower = RadioControl;
  RadioEnergy = RadioControl;
  
  // wiring to lower layers
  
  PhyRadioM.RadControl -> RadioControl;
  PhyRadioM.RadioState -> RadioControl;
  PhyRadioM.RadioByte -> RadioControl;
  PhyRadioM.RadioTxPreamble -> RadioControl;
  PhyRadioM.RadioCsThresh -> RadioControl;
  PhyRadioM.CodecControl -> CodecNone;
  PhyRadioM.Codec -> CodecNone;
  PhyRadioM.RSSISample -> RadioControl;
  PhyRadioM.LTimeControl -> LocalTimeC.TimeControl;
  PhyRadioM.LocalTime -> LocalTimeC;
  PhyRadioM.Leds -> LedsC;
  PhyRadioM.UartDebug -> UartDbg;

}

--- NEW FILE: PhyRadioM.nc ---
/*
 * Copyright (C) 2003-2005 the University of Southern California.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * In addition to releasing this program under the LGPL, the authors are
 * willing to dual-license it under other terms. You may contact the authors
 * of this project by writing to Wei Ye, USC/ISI, 4676 Admirality Way, Suite 
 * 1001, Marina del Rey, CA 90292, USA.
 */
/*
 * Authors: Wei Ye
 * 
 * This is the physical layer that sends and receives a packet
 *   - accept any type and length (<= PHY_MAX_PKT_LEN in phy_radio_msg.h) of packet
 *   - sending a packet: encoding and byte spooling
 *   - receiving a packet: decoding, byte buffering
 *   - Optional CRC check (CRC calculation is based on code from Jason Hill)
 *   - interface to radio control and physical carrier sense
 */

module PhyRadioM
{
   provides {
      interface StdControl as PhyControl;
      interface RadioState as PhyState;
      interface PhyPkt;
      interface PhyNotify;
      interface TxPreamble as PhyTxPreamble;
      interface PhyStreamByte;
   }
   uses {
      interface StdControl as RadControl;
      interface RadioState;
      interface RadioByte;
      interface TxPreamble as RadioTxPreamble;
      interface CsThreshold as RadioCsThresh;
      interface StdControl as CodecControl;
      interface RadioEncoding as Codec;
      interface RSSISample;
      interface StdControl as LTimeControl;
      interface GetSetU32 as LocalTime;
      interface Leds;
      interface UartDebug;
   }
}

implementation
{
#include "StdReturn.h"
#include "PhyRadioMsg.h"

   // Physical layer states
   enum {
      IDLE,
      RECEIVING,
      TRANSMITTING,
      TRANSMITTING_LAST,
      TRANSMITTING_DONE
   };
   
   // buffer states
   enum {FREE, BUSY};
   
   // type of RSSI measurement
   enum {POST_TX_NOISE, POST_RX_NOISE, SIGNAL};
   
   uint8_t state;
   uint8_t stateLock; // lock for state transition
   uint8_t pktLength; // pkt length including my header and trailer
   PhyPktBuf buffer1;  // 2 buffers for receiving and processing
   PhyPktBuf buffer2;
   uint8_t recvBufState;  // receiving buffer state
   uint8_t procBufState;  // processing buffer state
   uint8_t* procBufPtr;
   uint8_t* sendPtr;
   uint8_t* recvPtr;
   uint8_t* procPtr;
   uint8_t recvCount;
   uint8_t numEncoded;
   uint8_t txBuffer[3];
   uint8_t bufHead;
   uint8_t bufEnd;
   int16_t crcRx;     // CRC of received pkt
   int16_t crcTx;     // CRC of transmitted pkt
   uint8_t typeRSSI;  // type of RSSI sample
   
   static inline result_t lockAcquire(uint8_t* lock)
   {
      result_t tmp;
      atomic {
         if (*lock == 0) {
            *lock = 1;
            tmp = SUCCESS;
         } else {
            tmp = FAIL;
         }
      }
      return tmp;
   }
   
   static inline void lockRelease(uint8_t* lock)
   {
      *lock = 0;
   }

   uint16_t update_crc(uint8_t data, uint16_t crc)
   {
      uint8_t i;
      uint16_t tmp;
      tmp = (uint16_t)(data);
      crc = crc ^ (tmp << 8);
      for (i = 0; i < 8; i++) {
         if (crc & 0x8000)
            crc = crc << 1 ^ 0x1021;  // << is done before ^
         else
            crc = crc << 1;
         }
      return crc;
   }
	
   task void packet_received()
   {
      void* tmp;
      uint8_t error;
      uint8_t len;
      len = (uint8_t)procPtr[0];
      if (crcRx != *(uint16_t*)(procPtr + len - 2)) {
         error = PKT_ERROR;
      } else {
         error = PKT_RECV;
         call RadioCsThresh.update( ((PhyPktBuf*)procPtr)->info.strength, 
              ((PhyPktBuf*)procPtr)->info.noise );
      }
      tmp = signal PhyPkt.receiveDone(procPtr, error);
      if (tmp) {  // procBufState is still busy
        error = 0;
        atomic {
          if (recvBufState == BUSY) { // waiting for a free buffer
            procPtr = recvPtr;
            recvPtr = (uint8_t*)tmp;
            recvBufState = FREE;  // can start receive now
            if (!post packet_received()) {  // signal the pending packet
              error = 1; // task queue is full
              procBufPtr = procPtr;  //drop packet
              procBufState = FREE;
            }
          } else {
            procPtr = NULL;
            procBufPtr = (uint8_t*)tmp;
            procBufState = FREE;
          }
        }
        if (error) {  // can't post task
          signal PhyPkt.receiveDone(NULL, PKT_ERROR); // signal in case MAC is waiting
        }
      }
   }


   task void packet_sent()
   {
      signal PhyPkt.sendDone(sendPtr);
   }


   command result_t PhyControl.init()
   {
      state = IDLE;
      recvPtr = (uint8_t*)&buffer1;
      procBufPtr = (uint8_t*)&buffer2;
      recvBufState = FREE;
      procBufState = FREE;
      call RadControl.init();  // initialize radio
      call LTimeControl.init();  // initialize local system time
      call Leds.init();  // initialize LED debugging, only yellow is used
      call UartDebug.init(); // initialize UART debugging
      return SUCCESS;
   }


   command result_t PhyControl.start()
   {
      call RadControl.start();
      call LTimeControl.start();
      call Leds.yellowOn();
      return SUCCESS;
   }
   
   
   command result_t PhyControl.stop()
   {
      call RadControl.stop();
      return SUCCESS;
   }
   
   
  command int8_t PhyState.idle()
  {
    // put radio into idle state
    // if wakes up from sleep, may not be immediately done
    
    int8_t result;
    if (!lockAcquire(&stateLock)) return FAILURE; // in state transition
    result = call RadioState.idle();
    if (result == FAILURE) {  // failed to wake up radio
      lockRelease(&stateLock); // release state lock
    } else if (result == SUCCESS_DONE) {
      state = IDLE;
      lockRelease(&stateLock); // release state lock
      call Leds.yellowOn();
    } else if (result == SUCCESS_WAIT) {  // wait for wakeupDone signal
      state = IDLE;
      call Leds.yellowOn();
    }
    return result;
  }
  
  
  async event result_t RadioState.wakeupDone()
  {
    // Radio wakeup is done -- it's stable now
    lockRelease(&stateLock); // release state lock
    signal PhyState.wakeupDone();
    return SUCCESS;
  }
    

  default async event result_t PhyState.wakeupDone()
  {
    // default do-nothing handler
    return SUCCESS;
  }
  
   
  command result_t PhyState.sleep()
  {
    if (!lockAcquire(&stateLock)) return FAIL; // in state transition
    if (call RadioState.sleep()) {
       state = IDLE;
       lockRelease(&stateLock); // release state lock
       call Leds.yellowOff();
       return SUCCESS;
    }
    lockRelease(&stateLock); // release state lock
    return FAIL;
  }


  command uint8_t PhyState.get()
  {
    // get radio state
    return call RadioState.get();
  }


   command result_t PhyPkt.send(void* packet, uint8_t length, uint16_t addPreamble)
   {
      if (length > PHY_MAX_PKT_LEN || length < PHY_MIN_PKT_LEN) return FAIL;
      if (!lockAcquire(&stateLock)) return FAIL; // in state transition
      if (!call RadioByte.startTx(addPreamble)) {
        lockRelease(&stateLock); // release state lock
        return FAIL; // radio is busy
      }
      state = TRANSMITTING;
      sendPtr = (uint8_t*)packet;
      ((PhyHeader*)sendPtr)->length = length;  // fill my header field
      pktLength = length;
      // encode first byte of the packet
      bufHead = 0;
      bufEnd = 0;
      call Codec.encode(sendPtr[0]);
      numEncoded = 1;
      crcTx=update_crc(sendPtr[0], 0);
      lockRelease(&stateLock); // release state lock
      return SUCCESS;
   }


   // default do-nothing event handler for PhyPkt interface
   default async event result_t PhyNotify.startSymSent(void* packet)
   {
      return SUCCESS;
   }
   
   
   default event result_t PhyPkt.sendDone(void* packet)
   {
      return SUCCESS;
   }
   
   
   default async event result_t PhyNotify.startSymDetected(void* packet, uint8_t bitOffset)
   {
      return SUCCESS;
   }
   
   
   default event void* PhyPkt.receiveDone(void* packet, uint8_t error)
   {
      return packet;
   }
  
  command result_t PhyTxPreamble.preload(uint16_t length)
  {
    return SUCCESS;
  }
  
  command result_t PhyTxPreamble.start(uint16_t length)
  {
    if (length == 0) return FAIL;
    if (!lockAcquire(&stateLock)) return FAIL; // in state transition
    if (!call RadioTxPreamble.start(length)) {
      lockRelease(&stateLock); // release state lock
      return FAIL; // radio is busy
    }
    state = TRANSMITTING;
    lockRelease(&stateLock); // release state lock
    return SUCCESS;
  }
  
  
  async event void RadioTxPreamble.done()
  {
    if (stateLock) return; // in state transition
    state = IDLE;
    signal PhyTxPreamble.done();
  }
  
  
  default async event void PhyTxPreamble.done()
  {
    // default do-nothing handler
  }
  
  
   async event result_t Codec.encodeDone(uint8_t data)
   {
      txBuffer[bufEnd] = data;
      bufEnd++;
      return SUCCESS;
   }


   async event result_t Codec.decodeDone(uint8_t data, uint8_t error)
   {
      // one byte is decoded
      if (recvCount == 0) {  // first byte is packet length
         if (error == 1 || (uint8_t)data > PHY_MAX_PKT_LEN 
            || (uint8_t)data < PHY_MIN_PKT_LEN) {
            call RadioState.idle();
            state = IDLE;
            // signal received an erroneous packet with NULL buffer
            // unknown length (0) and error flag setting to 1
            signal PhyPkt.receiveDone(NULL, PKT_ERROR);
            return FAIL;
         }
         pktLength = (uint8_t)data;
         crcRx = 0;
         // sample signal strength
         typeRSSI = SIGNAL;
         call RSSISample.get();
      }
      recvPtr[recvCount] = data;

      // pass data for upper layer to stream bytes (e.g. snooper)
      signal PhyStreamByte.rxDone(recvPtr, recvCount);

      recvCount++;
      if (recvCount < pktLength - 1) {
         crcRx = update_crc(data, crcRx);
      } else if (recvCount == pktLength) { // Rx packet done
         call CodecControl.init();
         call RadioState.idle();
         state = IDLE;
         // sample noise level
         typeRSSI = POST_RX_NOISE;
         call RSSISample.get();
      }
      return SUCCESS;
   }


   // default do-nothing handler for PhyStreamByte
   default event void PhyStreamByte.rxDone(uint8_t* buffer, uint8_t byteIdx)
   {
   }


   async event result_t RadioByte.txByteReady()
   {
      // radio asks a byte to transmit
      if (stateLock) return FAIL; // in state transition
      if(state == TRANSMITTING) {
         call RadioByte.txNextByte(txBuffer[bufHead]);
         bufHead++;
         //now check if that was the last byte
         if (bufHead == bufEnd) {
            bufHead = 0;
            bufEnd = 0;
            if (numEncoded < pktLength) {
               if(numEncoded < pktLength - 2){
                  crcTx=update_crc(sendPtr[numEncoded], crcTx);	
               }
               call Codec.encode(sendPtr[numEncoded]);
               numEncoded++;
               if(numEncoded == pktLength - 2){
                  *(int16_t*)(sendPtr + pktLength - 2) = crcTx;
               }
            } else {
               call Codec.encode_flush();
               if (bufHead == bufEnd) {
                  // tx is done
                  state = TRANSMITTING_LAST;
               }
            }
         }	
      } else if (state == TRANSMITTING_LAST) {
         state = TRANSMITTING_DONE;
      } else if (state == TRANSMITTING_DONE) {
         call RadioState.idle();
         state = IDLE;
         // don't use noise samples after Tx, since collision may happen
         // this is for keep transitter silent for the same time, so
         // that the receiver can take noise samples
         typeRSSI = POST_TX_NOISE;
         call RSSISample.get();
      }
      return SUCCESS;
   }


  async event result_t RadioByte.startSymSent()
  {
    // just sent out start symbol, signal for putting outgoing timestamp
    signal PhyNotify.startSymSent(sendPtr);
    return SUCCESS;
  }


  async event result_t RadioByte.startSymDetected(uint8_t bitOffset)
  {
    // Phy must be in IDLE state, otherwise there is a bug
    if (stateLock) return FAIL; // in state transition
    if (state == IDLE && recvBufState == FREE) {
      state = RECEIVING;
      recvCount = 0;
      // put in timestamp in 1ms resolution
      ((PhyPktBuf*)recvPtr)->info.timestamp = call LocalTime.get();
      // signal upper layer
      signal PhyNotify.startSymDetected(recvPtr, bitOffset);
      return SUCCESS;
    }
    return FAIL;
  }


   async event result_t RadioByte.rxByteDone(uint8_t data)
   {
      if (stateLock) return FAIL; // in state transition
      if (state == RECEIVING) {
         call Codec.decode(data);
         return SUCCESS;
      }
      return FAIL;
   }


  async event void RSSISample.ready(uint16_t value)
  {
    // Got a sample of signal or noise level
    if (typeRSSI == SIGNAL) {  // signal strength of a receiving packet
      ((PhyPktBuf*)recvPtr)->info.strength = value;  // put into pkt
    } else if (typeRSSI == POST_TX_NOISE) {  // noise after Tx
      // signal Tx msg done
      if (!post packet_sent()) {  // task queue is full
        signal PhyPkt.sendDone(sendPtr); // signal directly
      }
    } else if (typeRSSI == POST_RX_NOISE) {
      // signal Rx msg done
      ((PhyPktBuf*)recvPtr)->info.noise = value;  // put into pkt
      if (procBufState == FREE) {  // have a free buffer, use it now
        procPtr = recvPtr;
        recvPtr = procBufPtr;
        // recvBufState = FREE;  // not set as busy during Rx
        if (post packet_received()) { // signal upper layer
           procBufState = BUSY;
        } else {  // task queue is full
           procBufPtr = procPtr;  //drop packet
           signal PhyPkt.receiveDone(NULL, PKT_ERROR); // signal in case MAC is waiting
        }
      } else {  // no buffer to use for Rx
        recvBufState = BUSY;
      }
    }
  }


  default command result_t RSSISample.get()
  {
    return FAIL;
  }

}  // end of implementation

--- NEW FILE: PhyRadioMsg.h ---
/*
 * Copyright (C) 2003-2005 the University of Southern California.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * In addition to releasing this program under the LGPL, the authors are
 * willing to dual-license it under other terms. You may contact the authors
 * of this project by writing to Wei Ye, USC/ISI, 4676 Admirality Way, Suite 
 * 1001, Marina del Rey, CA 90292, USA.
 */
/*
 * Authors: Wei Ye
 *
 * This file defines the header fields of phy_radio that will be
 * added before the payload of each packet.
 * The upper layer (MAC) that use phy_radio should include this header
 * as its first field and CRC as its last field in each packet it 
 * declares (see smac_msg.h for example).
 */

#ifndef PHY_MSG
#define PHY_MSG

// Maximum packet length -- including headers of all layers
// Each application can override the default max length in Makefile
// Maximum allowable value is 250
#ifndef PHY_MAX_PKT_LEN
#define PHY_MAX_PKT_LEN 100
#endif

// Physical-layer header to be put before data payload
typedef struct {
  uint8_t length; // length of entire packet
} __attribute__((packed)) PhyHeader;


// packet information to be recorded by physical layer
typedef struct {
  uint32_t timestamp;   // time stamp based on LocalTime (1ms resolution)
  uint16_t strength;  // signal strength
  uint16_t noise;  // noise measurement immediately following pkt Rx
} __attribute__((packed)) PhyPktInfo;

// Physical layer packet buffer (for receiving packets)
// Sending buffer should be provided by the top-level application

#define PHY_MIN_PKT_LEN (sizeof(PhyHeader) + 2)
#define PHY_MAX_PAYLOAD (PHY_MAX_PKT_LEN - PHY_MIN_PKT_LEN)

typedef struct {
  PhyHeader hdr;
  char data[PHY_MAX_PAYLOAD];
  int16_t crc;      // last field of a packet
  PhyPktInfo info;  // not part of a packet
} __attribute__((packed)) PhyPktBuf;

#endif  // PHY_MSG

--- NEW FILE: RadioControl.nc ---
/*
 * Copyright (C) 2003-2005 the University of Southern California.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * In addition to releasing this program under the LGPL, the authors are
 * willing to dual-license it under other terms. You may contact the authors
 * of this project by writing to Wei Ye, USC/ISI, 4676 Admirality Way, Suite 
 * 1001, Marina del Rey, CA 90292, USA.
 */
/*
 * Authors: Wei Ye
 *
 * The radio for Mica consists of 3 parts:
 *   1) RFM; 2) SPI; 3) Timer/counter 2
 *
 * This module implements the radio control functions:
 *   1) Put radio into different states:
 *   	a) idle; b) sleep; c) receive; d) transmit
 *   2) Physical carrier sense
 *   3) Tx and Rx of bytes
 */

configuration RadioControl
{
   provides {
      interface StdControl;
      interface RadioState;
      interface CarrierSense;
      interface CsThreshold;
      interface RadioByte;
      interface TxPreamble as RadioTxPreamble;
      interface GetSetU8 as RadioTxPower;
      interface RSSISample;
      interface RadioEnergy;
   }
}

implementation
{
   components RadioControlM, CC1000ControlM, HPLCC1000M, ADCC, TimerC,
      HPLPowerManagementM, LocalTimeC;
   
   StdControl = RadioControlM;
   RadioState = RadioControlM;
   CarrierSense = RadioControlM;
   CsThreshold = RadioControlM;
   RadioByte = RadioControlM;
   RadioTxPreamble = RadioControlM;
   RadioTxPower = RadioControlM;
   RSSISample = RadioControlM;
   RadioEnergy = RadioControlM;
   
   RadioControlM.CC1000StdControl -> CC1000ControlM;
   RadioControlM.CC1000Control -> CC1000ControlM;
   RadioControlM.ADCControl -> ADCC;
   RadioControlM.RSSIADC -> ADCC.ADC[TOS_ADC_CC_RSSI_PORT];
   RadioControlM.WakeupTimer -> TimerC.TimerAsync[unique("Timer")];
   RadioControlM.PowerManagement -> HPLPowerManagementM;
   RadioControlM.LocalTime -> LocalTimeC;
   
   CC1000ControlM.HPLChipcon -> HPLCC1000M.HPLCC1000;
}

--- NEW FILE: RadioControlM.nc ---
/*
 * Copyright (C) 2003-2005 the University of Southern California.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * In addition to releasing this program under the LGPL, the authors are
 * willing to dual-license it under other terms. You may contact the authors
 * of this project by writing to Wei Ye, USC/ISI, 4676 Admirality Way, Suite 
 * 1001, Marina del Rey, CA 90292, USA.
 */
/* Authors: Wei Ye, Honghui Chen
 *
 * This module implements the radio control functions:
 *   1) Put radio into different states:
 *   	a) idle; b) sleep; c) receive; d) transmit
 *   2) Start symbol detection in idle state
 *      (Partially based on CC1000RadioM.nc)
 *   3) Physical carrier sense
 */

module RadioControlM
{
   provides {
      interface StdControl as RadControl;
      interface RadioState;
      interface CarrierSense;
      interface CsThreshold;
      interface RadioByte;
      interface TxPreamble;
      interface GetSetU8 as RadioTxPower;
      interface RSSISample;
      interface RadioEnergy;
   }
   uses {
      interface StdControl as CC1000StdControl;
      interface CC1000Control;
      interface ADCControl;
      interface ADC as RSSIADC;
      interface TimerAsync as WakeupTimer;
      interface PowerManagement;
      interface GetSetU32 as LocalTime;
   }
}

implementation
{
#include "PhyConst.h"
#include "StdReturn.h"

// carrier sense threshold that determines a busy channel

  enum {
    RADIO_BUSY_THRESHOLD = 0xb0,  // definitely busy above this level
    RADIO_NOISE_LEVEL = 0x160  // initial noise level before any Rx
  };

  uint8_t start[2] __attribute((C)) = {0x33, 0xcc};

  // radio control states. INIT is a temperary state only at start up
  // these states are used internally by this component
  enum { INIT, SLEEP, IDLE, SYNC_START, RECEIVE, TRANSMIT };
  
  // Tx type
  enum { PREAMBLE_ONLY, PACKET };
  
  uint8_t state;        // state of radio control componet, used internally
  uint8_t radioState;   // radio hardware state, for use by other components
  uint8_t stateLock;    // lock for state transition
  uint16_t carrSenTime; // carrier sense time
  uint8_t extFlag;      // carrier sense extension flag
  uint8_t nextByte;     // tx buffer
  uint16_t preambleLen; // preamble length for current tx packet
  uint16_t txCount;      // for start symbol tx
  uint8_t txType;       // tx packet or just preamble
  uint16_t minSignal;   // measured minimum signal strength
  uint16_t avgSignal;   // measured average signal strength
  uint16_t noiseLevel;  // measured average noise level
  uint8_t measureRSSI;  // flag indicating RSSI measurement
  uint16_t valueRSSI;   // RSSI value
  uint16_t extCsVal;    // extended carrier sense sample
  bool updThreshEnabled; // if updating carrier sense threshold is enabled

  bool bManchesterBad;
  bool bInvertRxData;	// data inverted
  
  enum {
    //SYNC_BYTE = 0x33,
    //NSYNC_BYTE = 0xcc,
    SYNC_WORD = 0x33cc,
    NSYNC_WORD = 0xcc33
  };

  uint8_t PreambleCount;  //  found a valid preamble
  uint8_t SOFCount;
  union {
    uint16_t W;
    struct {
      uint8_t LSB;
      uint8_t MSB;
    };
  } RxShiftBuf;
  uint8_t RxBitOffset;	// bit offset for SPI bus
  uint16_t preambleLen;
  uint16_t LocalAddr;
   
#ifdef RADIO_MEASURE_ENERGY
  bool measureEnergy;  // energy measurement flag
  uint8_t lastRadioState;  // last radio state
  uint32_t lastUpdateTime;  // last time to update energy
  RadioTime radioTime;  // time the radio in different states
#endif

  // function prototypes
  static inline result_t lockAcquire(uint8_t* lock);
  static inline void lockRelease(uint8_t* lock);
  void wakeupRadio();
  void setRadioRx();
  void prepareTx();
  void startSend();
  void prepareRx();
  void updateEnergy();
 
  // functions for using locks
  static inline result_t lockAcquire(uint8_t* lock)
  {
    result_t tmp;
    atomic {
      if (*lock == 0) {
        *lock = 1;
        tmp = SUCCESS;
      } else {
        tmp = FAIL;
      }
    }
    return tmp;
  }
  
  static inline void lockRelease(uint8_t* lock)
  {
    *lock = 0;
  }
  
  
  command result_t RadControl.init()
  {
    // initialize the radio
      
    state = INIT;
    LocalAddr = TOS_LOCAL_ADDRESS;

    avgSignal = RADIO_BUSY_THRESHOLD;
    minSignal = RADIO_BUSY_THRESHOLD;
    noiseLevel = RADIO_NOISE_LEVEL;
    updThreshEnabled = TRUE;
    
    call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT);
    call ADCControl.init();

    call CC1000StdControl.init();
    call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION
    bInvertRxData = call CC1000Control.GetLOStatus(); //if need to invert Rcvd Data

    // set SPI clock pin as input -- clock provided by radio
    TOSH_MAKE_SPI_SCK_INPUT();
    
#ifndef DISABLE_CPU_SLEEP
    call PowerManagement.enable(); // enable CPU sleep mode
#endif
#ifdef RADIO_MEASURE_ENERGY
    measureEnergy = FALSE;
#endif
    call RadioState.idle();
    return SUCCESS;
  }
   
   
  command result_t RadControl.start()
  {
    // start radio -- go to idle state
    call RadioState.idle();
    return SUCCESS;
  }
   
   
  command result_t RadControl.stop()
  {
    // turn off radio
    outp(0x00, SPCR);  // turn off SPI
    call CC1000StdControl.stop();
    state = SLEEP;
    radioState = RADIO_SLEEP;
    updateEnergy();
    lockRelease(&stateLock); // clear state lock
    call PowerManagement.adjustPower();
    return SUCCESS;
  }


  void wakeupRadio()
  {
    // wake up radio from sleep
    // when this function is called, the radio will not immediately wake up
    // we have to wait until the WakeupTimer fires for radio to be stable
    call WakeupTimer.start(TIMER_ONE_SHOT, PHY_WAKEUP_DELAY);
    call CC1000StdControl.start();
    call CC1000Control.BIASOn();
//    call WakeupTimer.start(TIMER_ONE_SHOT, PHY_WAKEUP_DELAY);
    call PowerManagement.adjustPower();
  }

  void setRadioRx()
  {
    // set radio into Rx mode
    call CC1000Control.RxMode(); //set radio to Rx mode
    // configure SPI for input
    TOSH_MAKE_MISO_INPUT();
    TOSH_MAKE_MOSI_INPUT();
    outp(0xc0, SPCR);  // start SPI and enable SPI interrupt
  }
      
   
  // set radio into idle state. Automatically detect start symbol
  command int8_t RadioState.idle()
  {
    // set radio into idle state. Automatically detect start symbol
      
    if (state == IDLE) return SUCCESS_DONE;
    if (!lockAcquire(&stateLock)) return FAILURE; // in state transition
    // clear state variables
    PreambleCount = 0;
    SOFCount = 0;
    RxBitOffset = 0;
    RxShiftBuf.W = 0;
    carrSenTime = 0;
    if (state == SYNC_START) {
       state = IDLE;
       radioState = RADIO_IDLE;
       updateEnergy();
       lockRelease(&stateLock); // release state lock
       return SUCCESS_DONE;
    } else if (state == SLEEP) {  // wake up radio if in sleep state
       state = IDLE;
       radioState = RADIO_WAKEUP;
       updateEnergy();
       wakeupRadio();
       return SUCCESS_WAIT;  // wait for radio to be stable
    } else {  // Tx or Rx state
       cbi(SPCR, SPIE);       // disable SPI interrupt
       cbi(SPCR, SPE);   // disable SPI
       setRadioRx();  // put radio into Rx mode
       state = IDLE;
       radioState = RADIO_IDLE;
       updateEnergy();
       lockRelease(&stateLock); // release state lock
       return SUCCESS_DONE;
    }
  }
   
   
   // set radio into sleep mode: can't Tx or Rx
   command result_t RadioState.sleep()
   {
      if (state == SLEEP) return SUCCESS;
      if (!lockAcquire(&stateLock)) return FAIL; // in state transition
      call RadControl.stop();
      return SUCCESS;
   }


  command uint8_t RadioState.get()
  {
    // get current radio hardware state
    return radioState;
  }
  
  
  command result_t RadioByte.startTx(uint16_t addPreamble)
  {
    // start sending a new packet. Automatically send preamble first
    preambleLen = PHY_BASE_PREAMBLE_LEN + addPreamble;
    txType = PACKET;
    prepareTx();
    return SUCCESS;
  }
  
  
  void prepareTx()
  {
    // prepare for Tx -- wake up if in sleep mode
    
    if (!lockAcquire(&stateLock)) return; // in state transition
    cbi(SPCR, SPIE);  // disable SPI interrupt
    cbi(SPCR, SPE);   // disable SPI
    if (state == SLEEP) {  // wake up radio if in sleep state
      state = TRANSMIT;
      radioState = RADIO_WAKEUP;
      updateEnergy();
      wakeupRadio();  // will wait for radio to be stable
    } else {
      state = TRANSMIT;
      radioState = RADIO_TX;
      updateEnergy();
      startSend();
      lockRelease(&stateLock); // release state lock
    }
  }
    
  
  void startSend()
  {
    // start packet sending
    
    uint8_t temp;
    
    nextByte = 0xaa; // buffer second byte
    txCount = 2;
    temp = inp(SPSR);  // clear possible pending SPI interrupt
    outp(0xaa, SPDR);  // put first byte into SPI data register

    //set radio to Tx mode
    call CC1000Control.TxMode();      // radio to tx mode
    TOSH_MAKE_MISO_OUTPUT();
    TOSH_MAKE_MOSI_OUTPUT();
    outp(0xc0, SPCR);  // enable SPI and SPI interrupt
  }    
  
  
  command result_t RadioByte.txNextByte(uint8_t data)
  {
    // send next byte
    nextByte = data;
    return SUCCESS;
  }
  
  command result_t TxPreamble.preload(uint16_t length)
  {
    return SUCCESS;
  }

  command result_t TxPreamble.start(uint16_t length)
  {
    // send start symbol only -- can be used as a wakeup tone
    preambleLen = length;
    txType = PREAMBLE_ONLY;
    prepareTx();
    return SUCCESS;
  }
  
  
  default async event void TxPreamble.done()
  {
    // default do-nothing handler
  }
  
  
  async event result_t WakeupTimer.fired()
  {
    // now radio wakup is done, radio becomes stable
    if (state == IDLE) {
      setRadioRx();  // put radio into Rx mode
      radioState = RADIO_IDLE;
      updateEnergy();
      lockRelease(&stateLock); // release state lock
      signal RadioState.wakeupDone();
    } else if (state == TRANSMIT) {
      startSend();
      radioState = RADIO_TX;
      updateEnergy();
      lockRelease(&stateLock); // release state lock
    }
    return SUCCESS;
  }


  default async event result_t RadioState.wakeupDone()
  {
    return SUCCESS;
  }
  

  command result_t CarrierSense.start(uint16_t numSamples)
  {
    // start carrier sense
    if ((state != IDLE && state != SYNC_START) || numSamples == 0) 
      return FAIL;
    extFlag = 0;
    carrSenTime = numSamples;
    call RSSIADC.getData(); // take sample immediately
    return SUCCESS;
  }
	
  
  default async event result_t CarrierSense.channelIdle()
  {
    // default do-nothing handler for carrier sense
    return SUCCESS;
  }


  default async event result_t CarrierSense.channelBusy()
  {
    return SUCCESS;
  }
   
   
  command result_t RSSISample.get()
  {
    // get a sample of RSSI
    valueRSSI = 0;
    measureRSSI = 1;
    call RSSIADC.getData();
    return SUCCESS;
  }
  
  
  command uint8_t RadioTxPower.get()
  {
    // get current radio Tx power
    return call CC1000Control.GetRFPower();
  }
  
  
  command result_t RadioTxPower.set(uint8_t level)
  {
    // set radio tx power
    return call CC1000Control.SetRFPower(level);
  }
  
  
//  inline void prepareRx()
  void prepareRx()
  {
    // start symbol is detected, prepare for receiving
    // this function is called within SPI interrupt handler, where
    // global interrupt is disabled
    
    if (carrSenTime > 0) {  // MAC is in Carrier Sense state
      carrSenTime = 0;  // stop carrier sense
      signal CarrierSense.channelBusy();
    }
    if (!stateLock) {  // radio state transition allowed
      if (signal RadioByte.startSymDetected(RxBitOffset)) {
        state = RECEIVE;
        radioState = RADIO_RX;
        updateEnergy();
      } else {
        call RadioState.idle();
      }
    }
  }
   
   
  // Interrupt handler for SPI
  // (called everytime a byte arrives from the radio).
  // The signal handler disables global interrupts by default.
  TOSH_SIGNAL(SIG_SPI)
  {
    uint8_t data;
    data = inp(SPDR);
    if (bInvertRxData) data = ~data;

    if (state == TRANSMIT) {
      outp(nextByte, SPDR);  // send buffered byte
      if (txCount < preambleLen) {
        nextByte = 0xaa;
      } else if (txCount < preambleLen + sizeof(start)) {
        nextByte = start[txCount - preambleLen];
        if (txCount == preambleLen + 1 && txType == PREAMBLE_ONLY) {
          // I was asked to only send preamble
          call RadioState.idle();  // go back to idle
          __nesc_enable_interrupt();
          signal TxPreamble.done();
        }
      } else {
        signal RadioByte.txByteReady(); // ask a byte from upper layer
        if (txCount == preambleLen + sizeof(start) + 1) {
          signal RadioByte.startSymSent(); // for outgoing timestamp
        }
      }
      txCount++;
    } else if (state == IDLE) {
      bManchesterBad = call CC1000Control.GetLock();
      if ((!bManchesterBad) && (data == 0xaa || data == 0x55)) {
        PreambleCount++;
        if (PreambleCount > PHY_VALID_PRECURSOR) {
          if (stateLock) return; // radio is in transition
          state = SYNC_START;
        }
      } else {
        PreambleCount = 0;
      }
      if (carrSenTime > 0) call RSSIADC.getData(); // carrier sense
    } else if (state == SYNC_START) {
      uint8_t i;
      if (data == 0xaa || data == 0x55) {
        SOFCount = 0;   // tolerate of additional preamble bytes
      } else {
        uint8_t usTmp;
        SOFCount++;
        switch (SOFCount) {
        case 1:
          RxShiftBuf.MSB = data;
          break;
        case 2:
          RxShiftBuf.LSB = data;
          if (RxShiftBuf.W == SYNC_WORD) {
            // start symbol detected, prepare for receiving
            RxBitOffset = 0;
            prepareRx();
          } 
          break;            
        case 3: 
          // bit shift the data into previous samples to find SOF
          usTmp = data;
          for(i=0;i<8;i++) {
            RxShiftBuf.W <<= 1;
            if(usTmp & 0x80)
              RxShiftBuf.W |= 0x1;
            usTmp <<= 1;
            // check for SOF bytes
            if (RxShiftBuf.W == SYNC_WORD) {
              // start symbol detected, prepare for receiving
              RxBitOffset = 7-i;
              RxShiftBuf.LSB = data;
              prepareRx();
              break;
            }
          }
          break;
        default:
          // We didn't find it after a reasonable number of tries
          call RadioState.idle();
          break;
        }
      }
      if (carrSenTime > 0) call RSSIADC.getData(); // carrier sense
    }else if (state == RECEIVE) {
      uint8_t Byte;
      RxShiftBuf.W <<=8;
      RxShiftBuf.LSB = data;
      Byte = (RxShiftBuf.W >> RxBitOffset);
      signal RadioByte.rxByteDone(Byte);
    }         
  }


  async event result_t RSSIADC.dataReady(uint16_t data)
  {
    // ADC got a sample of signal strength
    if (carrSenTime > 0) {
      carrSenTime--;
      if (carrSenTime > 0 && extFlag == 0) { // requested byte
        if (data <= minSignal) { // stronger than min signal
          carrSenTime = 0; // stop carrier sense
          signal CarrierSense.channelBusy();
        }
      } else if (carrSenTime == 0 && extFlag == 0) { // last requested byte
        if (data <= minSignal) { // stronger than min signal
          signal CarrierSense.channelBusy();
        } else if (data >= noiseLevel) { // weaker than average noise level
          updThreshEnabled = TRUE;
          signal CarrierSense.channelIdle();
        } else { // need to check a few more bytes
          extFlag = 1;  // set flag for extended bytes
          extCsVal = data;
          carrSenTime = PHY_MAX_CS_EXT;
        }
      } else if (extFlag == 1) { // extended byte
        if (data <= minSignal) { // stronger than min signal
          carrSenTime = 0; // stop carrier sense
          signal CarrierSense.channelBusy();
        } else if (data >= noiseLevel) { // weaker than average noise level
          carrSenTime = 0; // stop carrier sense
          updThreshEnabled = TRUE;
          signal CarrierSense.channelIdle();
        } else {  // can't decide with individual sample
          if (carrSenTime > 0) {
            // average on extended samples
            extCsVal = (extCsVal + data) >> 1;
          } else {
            // has to make dicision based on averaged extended bytes
            // use half line between minSignal and noiseLevel as threshold
            if (extCsVal <= ((minSignal + noiseLevel) >> 1)) {
              signal CarrierSense.channelBusy();
            } else {
              updThreshEnabled = TRUE;
              signal CarrierSense.channelIdle();
            }
          }
        }
      }
    }
    if (measureRSSI == 1) {  // measuring signal or noise level
      if (valueRSSI == 0) {
        valueRSSI = data;
        call RSSIADC.getData(); // get another sample
      } else {
        measureRSSI = 0;
        valueRSSI = (valueRSSI + data) >> 1; // average on two samples
        signal RSSISample.ready(valueRSSI);
      }
      
    }
    return SUCCESS;
  }
  
  
  command void CsThreshold.reset()
  {
    // reset carrier sense threshold to initial value
    
    avgSignal = RADIO_BUSY_THRESHOLD;
    minSignal = RADIO_BUSY_THRESHOLD;
    noiseLevel = RADIO_NOISE_LEVEL;
  }    
  
  
  command void CsThreshold.update(uint16_t signalVal, uint16_t noiseVal)
  {
    // update carrier sense threshold with new RSSI samples
    // it is required that ALL samples are taken when a packet is correctly 
    // received, i.e., it should be signaled by PhyRadio after CRC check
    
    if (noiseVal > minSignal) {  // exclude possible false positives
      // average noise level: new sample gets 0.25 weight
      noiseLevel = (noiseLevel >> 1) + ((noiseLevel + noiseVal) >> 2);
    }
    // average signal strength: new sample gets 0.25 weight
    avgSignal = (avgSignal >> 1) + ((avgSignal + signalVal) >> 2);
    if (updThreshEnabled && signalVal > minSignal) {
      minSignal = signalVal;   // busy threshold goes to minimum
      if (noiseLevel < minSignal) {  // noise is too high
        minSignal = noiseLevel;  // signal can't be lower than noise
      }
    }
  }
  
  
  command void CsThreshold.starved()
  {
    // when a node gets starved on Tx, minSignal will be raised to make
    // it more aggressive. Starvation is defined by MAC that uses carrier
    // sense, e.g., consecutive failures on randamized carrier sense
    
    if (minSignal <= RADIO_BUSY_THRESHOLD) return;
    if (avgSignal > RADIO_BUSY_THRESHOLD) {
      minSignal = (minSignal + avgSignal) >> 1;
    } else {
      minSignal = (minSignal + RADIO_BUSY_THRESHOLD) >> 1;
    }
    updThreshEnabled = FALSE;  // don't lower busy threshold during starvation
  }
  
  
  default async command uint8_t PowerManagement.adjustPower()
  {
    // default command if PowerManagement is not used
    return 1;
  }
  
  
  command result_t RadioEnergy.startMeasure()
  {
    // start measuring radio energy consumption
    // it clears all measurement variables
#ifdef RADIO_MEASURE_ENERGY
    lastUpdateTime = call LocalTime.get();
    lastRadioState = radioState;
    radioTime.sleepTime = 0;
    radioTime.wakeupTime = 0;
    radioTime.idleTime = 0;
    radioTime.rxTime = 0;
    radioTime.txTime = 0;
    measureEnergy = TRUE;
#endif
    return SUCCESS;
  }
  
  
  command result_t RadioEnergy.stopMeasure()
  {
    // stop measuring radio energy consumption
    // add the time since last update
#ifdef RADIO_MEASURE_ENERGY
    atomic{
      updateEnergy();
      measureEnergy = FALSE;
    }
#endif
    return SUCCESS;
  }
  
  
  command RadioTime* RadioEnergy.get()
  {
    // get energy measurement result
#ifdef RADIO_MEASURE_ENERGY
    updateEnergy();
    return &radioTime;
#else
    return NULL; // might cause problems if caller doesn't check return value
#endif
  }
  
  
  void updateEnergy()
  {
    // update radio energy after radio state changes
#ifdef RADIO_MEASURE_ENERGY
    uint32_t now, timeElapsed;
    if (!measureEnergy) return;
    now = call LocalTime.get();
    timeElapsed = now - lastUpdateTime;
    if (lastRadioState == RADIO_SLEEP) {
      radioTime.sleepTime += timeElapsed;
    } else if (lastRadioState == RADIO_WAKEUP) {
      radioTime.wakeupTime += timeElapsed;
    } else if (lastRadioState == RADIO_IDLE) {
      radioTime.idleTime +=  timeElapsed;
    } else if (lastRadioState == RADIO_RX) {
      radioTime.rxTime +=  timeElapsed;
    } else if (lastRadioState == RADIO_TX) {
      radioTime.txTime +=  timeElapsed;
    }
    lastRadioState = radioState;
    lastUpdateTime = now;
#endif
  }    

}  // end of implementation



More information about the Tinyos-contrib-commits mailing list