[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
- Previous message: [Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/scp-mac/tos/interfaces CarrierSense.nc, NONE, 1.1 Cntr8bCompInt.nc, NONE, 1.1 Cntr8bOverInt.nc, NONE, 1.1 CsThreshold.nc, NONE, 1.1 CsmaControl.nc, NONE, 1.1 GetSetU16.nc, NONE, 1.1 GetSetU32.nc, NONE, 1.1 GetSetU8.nc, NONE, 1.1 LplControl.nc, NONE, 1.1 LplPollTimer.nc, NONE, 1.1 MacActivity.nc, NONE, 1.1 MacMsg.nc, NONE, 1.1 PhyNotify.nc, NONE, 1.1 PhyPkt.nc, NONE, 1.1 PhyPktError.h, NONE, 1.1 PhyStreamByte.nc, NONE, 1.1 RSSISample.nc, NONE, 1.1 RadioByte.nc, NONE, 1.1 RadioEncoding.nc, NONE, 1.1 RadioEnergy.h, NONE, 1.1 RadioEnergy.nc, NONE, 1.1 RadioState.h, NONE, 1.1 RadioState.nc, NONE, 1.1 TestSignal.nc, NONE, 1.1 Timer.h, NONE, 1.1 Timer.nc, NONE, 1.1 TimerAsync.nc, NONE, 1.1 TxPreamble.nc, NONE, 1.1 UartDebug.nc, NONE, 1.1
- Next message: [Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/scp-mac/tos/platform/micaz ClockSCP.nc, NONE, 1.1 ClockSCPM.nc, NONE, 1.1 HPLCC2420InterruptM.nc, NONE, 1.1 HPLUART0M.nc, NONE, 1.1 MakeXbowlocal, NONE, 1.1 PhyConst.h, NONE, 1.1 PhyRadio.nc, NONE, 1.1 PhyRadioM.nc, NONE, 1.1 PhyRadioMsg.h, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
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
- Previous message: [Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/scp-mac/tos/interfaces CarrierSense.nc, NONE, 1.1 Cntr8bCompInt.nc, NONE, 1.1 Cntr8bOverInt.nc, NONE, 1.1 CsThreshold.nc, NONE, 1.1 CsmaControl.nc, NONE, 1.1 GetSetU16.nc, NONE, 1.1 GetSetU32.nc, NONE, 1.1 GetSetU8.nc, NONE, 1.1 LplControl.nc, NONE, 1.1 LplPollTimer.nc, NONE, 1.1 MacActivity.nc, NONE, 1.1 MacMsg.nc, NONE, 1.1 PhyNotify.nc, NONE, 1.1 PhyPkt.nc, NONE, 1.1 PhyPktError.h, NONE, 1.1 PhyStreamByte.nc, NONE, 1.1 RSSISample.nc, NONE, 1.1 RadioByte.nc, NONE, 1.1 RadioEncoding.nc, NONE, 1.1 RadioEnergy.h, NONE, 1.1 RadioEnergy.nc, NONE, 1.1 RadioState.h, NONE, 1.1 RadioState.nc, NONE, 1.1 TestSignal.nc, NONE, 1.1 Timer.h, NONE, 1.1 Timer.nc, NONE, 1.1 TimerAsync.nc, NONE, 1.1 TxPreamble.nc, NONE, 1.1 UartDebug.nc, NONE, 1.1
- Next message: [Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/scp-mac/tos/platform/micaz ClockSCP.nc, NONE, 1.1 ClockSCPM.nc, NONE, 1.1 HPLCC2420InterruptM.nc, NONE, 1.1 HPLUART0M.nc, NONE, 1.1 MakeXbowlocal, NONE, 1.1 PhyConst.h, NONE, 1.1 PhyRadio.nc, NONE, 1.1 PhyRadioM.nc, NONE, 1.1 PhyRadioMsg.h, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Tinyos-contrib-commits
mailing list