]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
platform support for the IRIS mote (atm1218 MCU and rf230 radio)
authorsallai <sallai>
Mon, 5 Nov 2007 20:36:40 +0000 (20:36 +0000)
committersallai <sallai>
Mon, 5 Nov 2007 20:36:40 +0000 (20:36 +0000)
92 files changed:
tos/chips/atm1281/HplAtm128UartP.nc [new file with mode: 0644]
tos/chips/atm1281/McuSleepC.nc [new file with mode: 0644]
tos/chips/atm1281/adc/Atm128Adc.h [new file with mode: 0644]
tos/chips/atm1281/adc/Atm128AdcP.nc [new file with mode: 0644]
tos/chips/atm1281/adc/HplAtm128AdcP.nc [new file with mode: 0644]
tos/chips/atm1281/atm128hardware.h [new file with mode: 0644]
tos/chips/atm1281/timer/Atm1281AlarmAsyncP.nc [new file with mode: 0644]
tos/chips/atm1281/timer/Atm128AlarmAsyncC.nc [new file with mode: 0644]
tos/chips/atm1281/timer/Atm128Timer.h [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm1281Timer1P.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm1281Timer2AsyncC.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm1281Timer2AsyncP.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm1281Timer3P.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm128Timer1C.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm128Timer3C.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm128TimerAsync.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm128TimerCtrl16.nc [new file with mode: 0644]
tos/chips/atm1281/timer/HplAtm128TimerCtrl8.nc [new file with mode: 0644]
tos/chips/rf230/ActiveMessageConfig.nc [new file with mode: 0644]
tos/chips/rf230/ActiveMessageLayerC.nc [new file with mode: 0644]
tos/chips/rf230/CsmaConfig.nc [new file with mode: 0644]
tos/chips/rf230/CsmaLayerC.nc [new file with mode: 0644]
tos/chips/rf230/CsmaLayerP.nc [new file with mode: 0644]
tos/chips/rf230/DefaultMac.h [new file with mode: 0644]
tos/chips/rf230/DefaultMacC.nc [new file with mode: 0644]
tos/chips/rf230/DefaultMacP.nc [new file with mode: 0644]
tos/chips/rf230/DummyConfig.nc [new file with mode: 0644]
tos/chips/rf230/DummyLayerC.nc [new file with mode: 0644]
tos/chips/rf230/IEEE154Packet.h [new file with mode: 0644]
tos/chips/rf230/IEEE154Packet.nc [new file with mode: 0644]
tos/chips/rf230/IEEE154PacketC.nc [new file with mode: 0644]
tos/chips/rf230/IEEE154PacketP.nc [new file with mode: 0644]
tos/chips/rf230/MessageBufferLayerC.nc [new file with mode: 0644]
tos/chips/rf230/MessageBufferLayerP.nc [new file with mode: 0644]
tos/chips/rf230/Neighborhood.h [new file with mode: 0644]
tos/chips/rf230/Neighborhood.nc [new file with mode: 0644]
tos/chips/rf230/NeighborhoodC.nc [new file with mode: 0644]
tos/chips/rf230/NeighborhoodFlag.nc [new file with mode: 0644]
tos/chips/rf230/NeighborhoodFlagC.nc [new file with mode: 0644]
tos/chips/rf230/NeighborhoodP.nc [new file with mode: 0644]
tos/chips/rf230/PacketTimeStamp.nc [new file with mode: 0644]
tos/chips/rf230/PacketTimeSynch.nc [new file with mode: 0644]
tos/chips/rf230/RF230.h [new file with mode: 0644]
tos/chips/rf230/RF230Config.nc [new file with mode: 0644]
tos/chips/rf230/RF230LayerC.nc [new file with mode: 0644]
tos/chips/rf230/RF230LayerP.nc [new file with mode: 0644]
tos/chips/rf230/RadioAlarm.nc [new file with mode: 0644]
tos/chips/rf230/RadioAlarmC.nc [new file with mode: 0644]
tos/chips/rf230/RadioAlarmP.nc [new file with mode: 0644]
tos/chips/rf230/RadioAssert.h [new file with mode: 0644]
tos/chips/rf230/RadioCCA.nc [new file with mode: 0644]
tos/chips/rf230/RadioReceive.nc [new file with mode: 0644]
tos/chips/rf230/RadioSend.nc [new file with mode: 0644]
tos/chips/rf230/RadioState.nc [new file with mode: 0644]
tos/chips/rf230/RandomCollisionConfig.nc [new file with mode: 0644]
tos/chips/rf230/RandomCollisionLayerC.nc [new file with mode: 0644]
tos/chips/rf230/RandomCollisionLayerP.nc [new file with mode: 0644]
tos/chips/rf230/SlottedCollisionConfig.nc [new file with mode: 0644]
tos/chips/rf230/SlottedCollisionLayerC.nc [new file with mode: 0644]
tos/chips/rf230/SlottedCollisionLayerP.nc [new file with mode: 0644]
tos/chips/rf230/SoftwareAckConfig.nc [new file with mode: 0644]
tos/chips/rf230/SoftwareAckLayerC.nc [new file with mode: 0644]
tos/chips/rf230/SoftwareAckLayerP.nc [new file with mode: 0644]
tos/chips/rf230/Tasklet.h [new file with mode: 0644]
tos/chips/rf230/Tasklet.nc [new file with mode: 0644]
tos/chips/rf230/TaskletC.nc [new file with mode: 0644]
tos/chips/rf230/TrafficMonitorConfig.nc [new file with mode: 0644]
tos/chips/rf230/TrafficMonitorLayerC.nc [new file with mode: 0644]
tos/chips/rf230/TrafficMonitorLayerP.nc [new file with mode: 0644]
tos/chips/rf230/UniqueConfig.nc [new file with mode: 0644]
tos/chips/rf230/UniqueLayerC.nc [new file with mode: 0644]
tos/chips/rf230/UniqueLayerP.nc [new file with mode: 0644]
tos/chips/rf230/notes.txt [new file with mode: 0644]
tos/lib/diagmsg/Assert.h [new file with mode: 0644]
tos/lib/diagmsg/AssertC.nc [new file with mode: 0644]
tos/lib/diagmsg/AssertP.nc [new file with mode: 0644]
tos/lib/diagmsg/DiagMsg.nc [new file with mode: 0644]
tos/lib/diagmsg/DiagMsg.txt [new file with mode: 0644]
tos/lib/diagmsg/DiagMsgC.nc [new file with mode: 0644]
tos/lib/diagmsg/DiagMsgM.nc [new file with mode: 0644]
tos/lib/diagmsg/NoDiagMsgC.nc [new file with mode: 0644]
tos/platforms/iris/.platform [new file with mode: 0644]
tos/platforms/iris/ActiveMessageC.nc [new file with mode: 0644]
tos/platforms/iris/MeasureClockC.nc [new file with mode: 0644]
tos/platforms/iris/MicaTimer.h [new file with mode: 0644]
tos/platforms/iris/chips/rf230/HplRF230.h [new file with mode: 0644]
tos/platforms/iris/chips/rf230/HplRF230.nc [new file with mode: 0644]
tos/platforms/iris/chips/rf230/HplRF230C.nc [new file with mode: 0644]
tos/platforms/iris/chips/rf230/HplRF230P.nc [new file with mode: 0644]
tos/platforms/iris/platform.h [new file with mode: 0644]
tos/platforms/iris/platform_message.h [new file with mode: 0644]
tos/platforms/iris/sim/.platform [new file with mode: 0644]

diff --git a/tos/chips/atm1281/HplAtm128UartP.nc b/tos/chips/atm1281/HplAtm128UartP.nc
new file mode 100644 (file)
index 0000000..5b9061d
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2006 Arch Rock 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 Arch Rock 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
+ * ARCH ROCK 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
+ */
+
+/**
+ * @author Alec Woo <awoo@archrock.com>
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/** 
+ * Private component of the Atmega1281 serial port HPL.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Uart.h>
+
+module HplAtm128UartP {
+  
+  provides interface Init as Uart0Init;
+  provides interface StdControl as Uart0TxControl;
+  provides interface StdControl as Uart0RxControl;
+  provides interface HplAtm128Uart as HplUart0;
+    
+  provides interface Init as Uart1Init;
+  provides interface StdControl as Uart1TxControl;
+  provides interface StdControl as Uart1RxControl;
+  provides interface HplAtm128Uart as HplUart1;
+  
+  uses interface Atm128Calibrate;
+  uses interface McuPowerState;
+}
+implementation {
+  
+  //=== Uart Init Commands. ====================================
+  command error_t Uart0Init.init() {
+    Atm128UartMode_t    mode;
+    Atm128UartStatus_t  stts;
+    Atm128UartControl_t ctrl;
+    uint16_t ubrr0;
+
+    ctrl.bits = (struct Atm128_UCSRB_t) {rxcie:0, txcie:0, rxen:0, txen:0};
+    stts.bits = (struct Atm128_UCSRA_t) {u2x:1};
+    mode.bits = (struct Atm128_UCSRC_t) {ucsz:ATM128_UART_DATA_SIZE_8_BITS};
+
+    ubrr0 = call Atm128Calibrate.baudrateRegister(PLATFORM_BAUDRATE);
+    UBRR0L = ubrr0;
+    UBRR0H = ubrr0 >> 8;
+    UCSR0A = stts.flat;
+    UCSR0C = mode.flat;
+    UCSR0B = ctrl.flat;
+
+    return SUCCESS;
+  }
+
+  command error_t Uart0TxControl.start() {
+    SET_BIT(UCSR0B, TXCIE0);
+    SET_BIT(UCSR0B, TXEN0);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+
+  command error_t Uart0TxControl.stop() {
+    CLR_BIT(UCSR0B, TXCIE0);
+    CLR_BIT(UCSR0B, TXEN0);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+
+  command error_t Uart0RxControl.start() {
+    SET_BIT(UCSR0B, RXCIE0);
+    SET_BIT(UCSR0B, RXEN0);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+
+  command error_t Uart0RxControl.stop() {
+    CLR_BIT(UCSR0B, RXCIE0);
+    CLR_BIT(UCSR0B, RXEN0);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+  
+  async command error_t HplUart0.enableTxIntr() {
+    SET_BIT(UCSR0B, TXEN0);
+    return SUCCESS;
+  }
+  
+  async command error_t HplUart0.disableTxIntr(){
+    CLR_BIT(UCSR0B, TXEN0);
+    return SUCCESS;
+  }
+  
+  async command error_t HplUart0.enableRxIntr(){
+    SET_BIT(UCSR0B, RXEN0);
+    return SUCCESS;
+  }
+
+  async command error_t HplUart0.disableRxIntr(){
+    CLR_BIT(UCSR0B, RXEN0);
+    return SUCCESS;
+  }
+  
+  async command bool HplUart0.isTxEmpty(){
+    return READ_BIT(UCSR0A, TXC0);
+  }
+
+  async command bool HplUart0.isRxEmpty(){
+    return !READ_BIT(UCSR0A, RXC0);
+  }
+  
+  async command uint8_t HplUart0.rx(){
+    return UDR0;
+  }
+
+  async command void HplUart0.tx(uint8_t data) {
+    atomic{
+      UDR0 = data; 
+      SET_BIT(UCSR0A, TXC0);
+    }
+  }
+  
+  AVR_ATOMIC_HANDLER(SIG_USART0_RECV) {
+    if (READ_BIT(UCSR0A, RXC0)) {
+      signal HplUart0.rxDone(UDR0);
+    }
+  }
+  
+  AVR_NONATOMIC_HANDLER(SIG_USART0_TRANS) {
+    signal HplUart0.txDone();
+  }
+  
+  command error_t Uart1Init.init() {
+    Atm128UartMode_t    mode;
+    Atm128UartStatus_t  stts;
+    Atm128UartControl_t ctrl;
+    uint16_t ubrr1;
+    
+    ctrl.bits = (struct Atm128_UCSRB_t) {rxcie:0, txcie:0, rxen:0, txen:0};
+    stts.bits = (struct Atm128_UCSRA_t) {u2x:1};
+    mode.bits = (struct Atm128_UCSRC_t) {ucsz:ATM128_UART_DATA_SIZE_8_BITS};
+
+    ubrr1 = call Atm128Calibrate.baudrateRegister(PLATFORM_BAUDRATE);
+    UBRR1L = ubrr1;
+    UBRR1H = ubrr1 >> 8;
+    UCSR1A = stts.flat;
+    UCSR1C = mode.flat;
+    UCSR1B = ctrl.flat;
+
+    return SUCCESS;
+  }
+
+  command error_t Uart1TxControl.start() {
+    SET_BIT(UCSR1B, TXCIE1);
+    SET_BIT(UCSR1B, TXEN1);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+
+  command error_t Uart1TxControl.stop() {
+    CLR_BIT(UCSR1B, TXCIE1);
+    CLR_BIT(UCSR1B, TXEN1);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+
+  command error_t Uart1RxControl.start() {
+    SET_BIT(UCSR1B, RXCIE1);
+    SET_BIT(UCSR1B, RXEN1);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+
+  command error_t Uart1RxControl.stop() {
+    CLR_BIT(UCSR1B, RXCIE1);
+    CLR_BIT(UCSR1B, RXEN1);
+    call McuPowerState.update();
+    return SUCCESS;
+  }
+  
+  async command error_t HplUart1.enableTxIntr() {
+    SET_BIT(UCSR1B, TXEN1);
+    return SUCCESS;
+  }
+  
+  async command error_t HplUart1.disableTxIntr(){
+    CLR_BIT(UCSR1B, TXEN1);
+    return SUCCESS;
+  }
+  
+  async command error_t HplUart1.enableRxIntr(){
+    SET_BIT(UCSR1B, RXEN1);
+    return SUCCESS;
+  }
+
+  async command error_t HplUart1.disableRxIntr(){
+    CLR_BIT(UCSR1B, RXEN1);
+    return SUCCESS;
+  }
+  
+  async command bool HplUart1.isTxEmpty() {
+    return READ_BIT(UCSR1A, TXC1);
+  }
+
+  async command bool HplUart1.isRxEmpty() {
+    return !READ_BIT(UCSR1A, RXC1);
+  }
+  
+  async command uint8_t HplUart1.rx(){
+    return UDR1;
+  }
+
+  async command void HplUart1.tx(uint8_t data) {
+    atomic{
+      UDR1 = data; 
+      SET_BIT(UCSR1A, TXC1);
+    }
+  }
+  
+  AVR_ATOMIC_HANDLER(SIG_USART1_RECV) {
+    if (READ_BIT(UCSR1A, RXC1))
+      signal HplUart1.rxDone(UDR1);
+  }
+  
+  AVR_NONATOMIC_HANDLER(SIG_USART1_TRANS) {
+    signal HplUart1.txDone();
+  }
+  
+  default async event void HplUart0.txDone() {} 
+  default async event void HplUart0.rxDone(uint8_t data) {}
+  default async event void HplUart1.txDone() {}
+  default async event void HplUart1.rxDone(uint8_t data) {}
+  
+}
diff --git a/tos/chips/atm1281/McuSleepC.nc b/tos/chips/atm1281/McuSleepC.nc
new file mode 100644 (file)
index 0000000..4c11f49
--- /dev/null
@@ -0,0 +1,148 @@
+/// $Id$
+
+/*
+ * "Copyright (c) 2005 Stanford University. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without written
+ * agreement is hereby granted, provided that the above copyright
+ * notice, the following two paragraphs and the author appear in all
+ * copies of this software.
+ * 
+ * IN NO EVENT SHALL STANFORD UNIVERSITY 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 STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * STANFORD UNIVERSITY 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 STANFORD UNIVERSITY
+ * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS."
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Implementation of TEP 112 (Microcontroller Power Management) for
+ * the Atmega128. Power state calculation code copied from Rob
+ * Szewczyk's 1.x code in HPLPowerManagementM.nc.
+ *
+ * <pre>
+ *  $Id$
+ * </pre>
+ *
+ * @author Philip Levis
+ * @author Robert Szewczyk
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ * @date   October 30, 2007
+ */
+
+module McuSleepC {
+  provides {
+    interface McuSleep;
+    interface McuPowerState;
+  }
+  uses {
+    interface McuPowerOverride;
+  }
+}
+implementation {
+  /* There is no dirty bit management because the sleep mode depends on
+     the amount of time remaining in timer2. */
+
+  /* Note that the power values are maintained in an order
+   * based on their active components, NOT on their values.
+   * Look at atm1281hardware.h and page 54 of the ATmeg1281
+   * manual (Table 25).*/
+  const_uint8_t atm128PowerBits[ATM128_POWER_DOWN + 1] = {
+    0,
+    (1 << SM0),
+    (1 << SM2) | (1 << SM1) | (1 << SM0),
+    (1 << SM1) | (1 << SM0),
+    (1 << SM2) | (1 << SM1),
+    (1 << SM1)};
+    
+  mcu_power_t getPowerState() {
+    // Note: we go to sleep even if timer 0, 1, 3, 4,  or 5's overflow interrupt
+    // is enabled - this allows using these timers as TinyOS "Alarm"s
+    // while still having power management.
+
+    // Are external timers running?  
+    if (
+        TIMSK0 & (1 << OCIE0A | 1 << OCIE0B | 1 << TOIE0) ||
+        TIMSK1 & (1 << ICIE1  | 1 << OCIE1A | 1 << OCIE1B | 1 << OCIE1C | 1 << TOIE1) ||
+        TIMSK3 & (1 << ICIE3  | 1 << OCIE3A | 1 << OCIE3B | 1 << OCIE3C | 1 << TOIE3) ||
+        // input capture and output compare for timer 4 and 5 are
+        // not functional on atm1281
+        TIMSK4 & (1 << TOIE4) ||
+        TIMSK5 & (1 << TOIE5)
+    ) {
+      return ATM128_POWER_IDLE;
+    }    
+    // SPI (Radio stack)
+    else if (bit_is_set(SPCR, SPIE)) { 
+      return ATM128_POWER_IDLE;
+    }
+    // UARTs are active
+    else if (UCSR0B & (1 << TXCIE0 | 1 << RXCIE0)) { // UART
+      return ATM128_POWER_IDLE;
+    }
+    else if (UCSR1B & (1 << TXCIE1 | 1 << RXCIE1)) { // UART
+      return ATM128_POWER_IDLE;
+    }
+    // I2C (Two-wire) is active
+    else if (bit_is_set(TWCR, TWEN)){
+      return ATM128_POWER_IDLE;
+    }    
+    // ADC is enabled
+    else if (bit_is_set(ADCSRA, ADEN)) { 
+      return ATM128_POWER_ADC_NR;
+    }
+    else {
+      return ATM128_POWER_DOWN;
+    }
+  }
+
+  async command void McuSleep.sleep() {
+    uint8_t powerState;
+
+    powerState = mcombine(getPowerState(), call McuPowerOverride.lowestState());
+    SMCR =
+      (SMCR & 0xf0) | 1 << SE | read_uint8_t(&atm128PowerBits[powerState]);      
+    sei();
+    asm volatile ("sleep");
+    cli();
+    
+    CLR_BIT(SMCR, SE);
+  }
+
+  async command void McuPowerState.update() {
+  }
+
+  default async command mcu_power_t McuPowerOverride.lowestState() {
+    return ATM128_POWER_DOWN;
+  }
+}
diff --git a/tos/chips/atm1281/adc/Atm128Adc.h b/tos/chips/atm1281/adc/Atm128Adc.h
new file mode 100644 (file)
index 0000000..2ed8763
--- /dev/null
@@ -0,0 +1,197 @@
+// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+// @author Martin Turon <mturon@xbow.com>
+// @author Hu Siquan <husq@xbow.com>
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+// @author Janos Sallai <janos.sallai@vanderbilt.edu>
+
+/*
+   Updated chips/atm128 to include atm1281's ADCSRB register.
+*/
+
+#ifndef _H_Atm128ADC_h
+#define _H_Atm128ADC_h
+
+//================== 8 channel 10-bit ADC ==============================
+
+/* Voltage Reference Settings */
+enum {
+    ATM128_ADC_VREF_OFF = 0, //!< VR+ = AREF   and VR- = GND
+    ATM128_ADC_VREF_AVCC = 1,//!< VR+ = AVcc   and VR- = GND
+    ATM128_ADC_VREF_RSVD,
+    ATM128_ADC_VREF_2_56 = 3,//!< VR+ = 2.56V  and VR- = GND
+};
+
+/* Voltage Reference Settings */
+enum {
+    ATM128_ADC_RIGHT_ADJUST = 0, 
+    ATM128_ADC_LEFT_ADJUST = 1,
+};
+
+
+/* ADC Multiplexer Settings */
+enum {
+    ATM128_ADC_SNGL_ADC0 = 0,
+    ATM128_ADC_SNGL_ADC1,
+    ATM128_ADC_SNGL_ADC2,
+    ATM128_ADC_SNGL_ADC3,
+    ATM128_ADC_SNGL_ADC4,
+    ATM128_ADC_SNGL_ADC5,
+    ATM128_ADC_SNGL_ADC6,
+    ATM128_ADC_SNGL_ADC7,
+    ATM128_ADC_DIFF_ADC00_10x,
+    ATM128_ADC_DIFF_ADC10_10x,
+    ATM128_ADC_DIFF_ADC00_200x,
+    ATM128_ADC_DIFF_ADC10_200x,
+    ATM128_ADC_DIFF_ADC22_10x,
+    ATM128_ADC_DIFF_ADC32_10x,
+    ATM128_ADC_DIFF_ADC22_200x,
+    ATM128_ADC_DIFF_ADC32_200x,
+    ATM128_ADC_DIFF_ADC01_1x,
+    ATM128_ADC_DIFF_ADC11_1x,
+    ATM128_ADC_DIFF_ADC21_1x,
+    ATM128_ADC_DIFF_ADC31_1x,
+    ATM128_ADC_DIFF_ADC41_1x,
+    ATM128_ADC_DIFF_ADC51_1x,
+    ATM128_ADC_DIFF_ADC61_1x,
+    ATM128_ADC_DIFF_ADC71_1x,
+    ATM128_ADC_DIFF_ADC02_1x,
+    ATM128_ADC_DIFF_ADC12_1x,
+    ATM128_ADC_DIFF_ADC22_1x,
+    ATM128_ADC_DIFF_ADC32_1x,
+    ATM128_ADC_DIFF_ADC42_1x,
+    ATM128_ADC_DIFF_ADC52_1x,
+    ATM128_ADC_SNGL_1_23,
+    ATM128_ADC_SNGL_GND,
+};
+
+/* ADC Multiplexer Selection Register */
+typedef struct
+{
+    uint8_t mux   : 5;  //!< Analog Channel and Gain Selection Bits
+    uint8_t adlar : 1;  //!< ADC Left Adjust Result
+    uint8_t refs  : 2;  //!< Reference Selection Bits
+} Atm128Admux_t;
+
+/* ADC Prescaler Settings */
+/* Note: each platform must define ATM128_ADC_PRESCALE to the smallest
+   prescaler which guarantees full A/D precision. */
+enum {
+    ATM128_ADC_PRESCALE_2 = 0,
+    ATM128_ADC_PRESCALE_2b,
+    ATM128_ADC_PRESCALE_4,
+    ATM128_ADC_PRESCALE_8,
+    ATM128_ADC_PRESCALE_16,
+    ATM128_ADC_PRESCALE_32,
+    ATM128_ADC_PRESCALE_64,
+    ATM128_ADC_PRESCALE_128,
+
+    // This special value is used to ask the platform for the prescaler
+    // which gives full precision.
+    ATM128_ADC_PRESCALE
+};
+
+/* ADC Enable Settings */
+enum {
+    ATM128_ADC_ENABLE_OFF = 0,
+    ATM128_ADC_ENABLE_ON,
+};
+
+/* ADC Start Conversion Settings */
+enum {
+    ATM128_ADC_START_CONVERSION_OFF = 0,
+    ATM128_ADC_START_CONVERSION_ON,
+};
+
+/* ADC Free Running Select Settings */
+enum {
+    ATM128_ADC_FREE_RUNNING_OFF = 0,
+    ATM128_ADC_FREE_RUNNING_ON,
+};
+
+/* ADC Interrupt Flag Settings */
+enum {
+    ATM128_ADC_INT_FLAG_OFF = 0,
+    ATM128_ADC_INT_FLAG_ON,
+};
+
+/* ADC Interrupt Enable Settings */
+enum {
+    ATM128_ADC_INT_ENABLE_OFF = 0,
+    ATM128_ADC_INT_ENABLE_ON,
+};
+
+/* ADC Multiplexer Selection Register */
+typedef struct
+{
+    uint8_t adps  : 3;  //!< ADC Prescaler Select Bits
+    uint8_t adie  : 1;  //!< ADC Interrupt Enable
+    uint8_t adif  : 1;  //!< ADC Interrupt Flag
+    uint8_t adate : 1;  //!< ADC Auto Trigger Enable
+    uint8_t adsc  : 1;  //!< ADC Start Conversion
+    uint8_t aden  : 1;  //!< ADC Enable
+} Atm128Adcsra_t;
+
+/* ADC Multiplexer Selection Register */
+typedef struct
+{
+    uint8_t adts  : 3;  //!< ADC Trigger Select
+    uint8_t mux5  : 1;  //!< Analog Channel and Gain Selection Bit
+    uint8_t resv1 : 2;  //!< Reserved
+    uint8_t acme  : 1;  //!< Analog Comparator Multiplexer Enable
+    uint8_t resv2 : 1;  //!< Reserved
+} Atm128Adcsrb_t;
+
+
+typedef uint8_t Atm128_ADCH_t;         //!< ADC data register high
+typedef uint8_t Atm128_ADCL_t;         //!< ADC data register low
+
+// The resource identifier string for the ADC subsystem
+#define UQ_ATM128ADC_RESOURCE "atm128adc.resource"
+
+#endif //_H_Atm128ADC_h
+
diff --git a/tos/chips/atm1281/adc/Atm128AdcP.nc b/tos/chips/atm1281/adc/Atm128AdcP.nc
new file mode 100644 (file)
index 0000000..1dae8ac
--- /dev/null
@@ -0,0 +1,268 @@
+/* $Id$
+ * "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-2005 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.
+ *
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ *
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+
+#include "Atm128Adc.h"
+
+/**
+ * Internal component of the Atmega1281 A/D HAL.
+ *
+ * @author Jason Hill
+ * @author David Gay
+ * @author Philip Levis
+ * @author Phil Buonadonna
+ * @author Hu Siquan <husq@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+module Atm128AdcP 
+{
+  provides {
+    interface Init;
+    interface AsyncStdControl;
+    interface Atm128AdcSingle;
+    interface Atm128AdcMultiple;
+  }
+  uses {
+    interface HplAtm128Adc;
+    interface Atm128Calibrate;
+  }
+}
+implementation
+{  
+  /* State for the current and next (multiple-sampling only) conversion */
+  struct {
+    bool multiple : 1;         /* single and multiple-sampling mode */
+    bool precise : 1;          /* is this result going to be precise? */
+    uint8_t channel : 5;       /* what channel did this sample come from? */
+  } f, nextF;
+  
+  command error_t Init.init() {
+    atomic
+      {
+       Atm128Adcsra_t adcsr;
+
+       adcsr.aden = ATM128_ADC_ENABLE_OFF;
+       adcsr.adsc = ATM128_ADC_START_CONVERSION_OFF;  
+       adcsr.adate= ATM128_ADC_FREE_RUNNING_OFF; 
+       adcsr.adif = ATM128_ADC_INT_FLAG_OFF;               
+       adcsr.adie = ATM128_ADC_INT_ENABLE_OFF;       
+       adcsr.adps = ATM128_ADC_PRESCALE_2;
+       call HplAtm128Adc.setAdcsra(adcsr);
+      }
+    return SUCCESS;
+  }
+
+  /* We enable the A/D when start is called, and disable it when stop is
+     called. This drops A/D conversion latency by a factor of two (but
+     increases idle mode power consumption a little). 
+  */
+  async command error_t AsyncStdControl.start() {
+    atomic call HplAtm128Adc.enableAdc();
+    return SUCCESS;
+  }
+
+  async command error_t AsyncStdControl.stop() {
+    atomic call HplAtm128Adc.disableAdc();
+
+    return SUCCESS;
+  }
+
+  /* Return TRUE if switching to 'channel' with reference voltage 'refVoltage'
+     will give a precise result (the first sample after changing reference
+     voltage or switching to/between a differential channel is imprecise)
+  */
+  inline bool isPrecise(Atm128Admux_t admux, uint8_t channel, uint8_t refVoltage) {
+    return refVoltage == admux.refs &&
+      (channel <= ATM128_ADC_SNGL_ADC7 || channel >= ATM128_ADC_SNGL_1_23 || channel == admux.mux);
+  }
+
+  async event void HplAtm128Adc.dataReady(uint16_t data) {
+    bool precise, multiple;
+    uint8_t channel;
+
+    atomic 
+      {
+       channel = f.channel;
+       precise = f.precise;
+       multiple = f.multiple;
+      }
+
+    if (!multiple)
+      {
+       /* A single sample. Disable the ADC interrupt to avoid starting
+          a new sample at the next "sleep" instruction. */
+       call HplAtm128Adc.disableInterruption();
+       signal Atm128AdcSingle.dataReady(data, precise);
+      }
+    else
+      {
+       /* Multiple sampling. The user can:
+          - tell us to stop sampling
+          - or, to continue sampling on a new channel, possibly with a
+            new reference voltage; however this change applies not to
+            the next sample (the hardware has already started working on
+            that), but on the one after.
+       */
+       bool cont;
+       uint8_t nextChannel, nextVoltage;
+       Atm128Admux_t admux;
+
+       atomic 
+         {
+           admux = call HplAtm128Adc.getAdmux();
+           nextVoltage = admux.refs;
+           nextChannel = admux.mux;
+         }
+
+       cont = signal Atm128AdcMultiple.dataReady(data, precise, channel,
+                                                 &nextChannel, &nextVoltage);
+       atomic
+         if (cont)
+           {
+             /* Switch channels and update our internal channel+precision
+                tracking state (f and nextF). Note that this tracking will
+                be incorrect if we take too long to get to this point. */
+             admux.refs = nextVoltage;
+             admux.mux = nextChannel;
+             call HplAtm128Adc.setAdmux(admux);
+
+             f = nextF;
+             nextF.channel = nextChannel;
+             nextF.precise = isPrecise(admux, nextChannel, nextVoltage);
+           }
+         else
+           call HplAtm128Adc.cancel();
+      }
+  }
+
+  /* Start sampling based on request parameters */
+  void getData(uint8_t channel, uint8_t refVoltage, bool leftJustify, uint8_t prescaler) {
+    Atm128Admux_t admux;
+    Atm128Adcsra_t adcsr;
+
+    admux = call HplAtm128Adc.getAdmux();
+    f.precise = isPrecise(admux, channel, refVoltage);
+    f.channel = channel;
+
+    admux.refs = refVoltage;
+    admux.adlar = leftJustify;
+    admux.mux = channel;
+    call HplAtm128Adc.setAdmux(admux);
+
+    adcsr.aden = ATM128_ADC_ENABLE_ON;
+    adcsr.adsc = ATM128_ADC_START_CONVERSION_ON;
+    adcsr.adate= f.multiple;
+    adcsr.adif = ATM128_ADC_INT_FLAG_ON; // clear any stale flag
+    adcsr.adie = ATM128_ADC_INT_ENABLE_ON;
+    if (prescaler == ATM128_ADC_PRESCALE)
+      prescaler = call Atm128Calibrate.adcPrescaler();
+    adcsr.adps = prescaler;
+    call HplAtm128Adc.setAdcsra(adcsr);
+  }
+
+  async command bool Atm128AdcSingle.getData(uint8_t channel, uint8_t refVoltage,
+                                            bool leftJustify, uint8_t prescaler) {
+    atomic
+      {
+       f.multiple = FALSE;
+       getData(channel, refVoltage, leftJustify, prescaler);
+
+       return f.precise;
+      }
+  }
+
+  async command bool Atm128AdcSingle.cancel() {
+    /* There is no Atm128AdcMultiple.cancel, for reasons discussed in that
+       interface */
+    return call HplAtm128Adc.cancel();
+  }
+
+  async command bool Atm128AdcMultiple.getData(uint8_t channel, uint8_t refVoltage,
+                                              bool leftJustify, uint8_t prescaler) {
+    atomic
+      {
+       f.multiple = TRUE;
+       getData(channel, refVoltage, leftJustify, prescaler);
+       nextF = f;
+       /* We assume the 2nd sample is precise */
+       nextF.precise = TRUE;
+
+       return f.precise;
+      }
+  }
+
+  default async event void Atm128AdcSingle.dataReady(uint16_t data, bool precise) {
+  }
+
+  default async event bool Atm128AdcMultiple.dataReady(uint16_t data, bool precise, uint8_t channel,
+                                                      uint8_t *newChannel, uint8_t *newRefVoltage) {
+    return FALSE; // stop conversion if we somehow end up here.
+  }
+}
diff --git a/tos/chips/atm1281/adc/HplAtm128AdcP.nc b/tos/chips/atm1281/adc/HplAtm128AdcP.nc
new file mode 100644 (file)
index 0000000..ec88671
--- /dev/null
@@ -0,0 +1,160 @@
+/// $Id$
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS. 
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+
+#include "Atm128Adc.h"
+
+/**
+ * HPL for the Atmega1281 A/D conversion susbsystem.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Hu Siquan <husq@xbow.com>
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+module HplAtm128AdcP {
+  provides interface HplAtm128Adc;
+  uses interface McuPowerState;
+}
+implementation {
+  //=== Direct read of HW registers. =================================
+  async command Atm128Admux_t HplAtm128Adc.getAdmux() { 
+    return *(Atm128Admux_t*)&ADMUX; 
+  }
+  async command Atm128Adcsra_t HplAtm128Adc.getAdcsra() { 
+    return *(Atm128Adcsra_t*)&ADCSRA; 
+  }
+  async command uint16_t HplAtm128Adc.getValue() { 
+    return ADC; 
+  }
+
+  DEFINE_UNION_CAST(Admux2int, Atm128Admux_t, uint8_t);
+  DEFINE_UNION_CAST(Adcsra2int, Atm128Adcsra_t, uint8_t);
+
+  //=== Direct write of HW registers. ================================
+  async command void HplAtm128Adc.setAdmux( Atm128Admux_t x ) { 
+    ADMUX = Admux2int(x); 
+  }
+  async command void HplAtm128Adc.setAdcsra( Atm128Adcsra_t x ) { 
+    ADCSRA = Adcsra2int(x); 
+  }
+
+  async command void HplAtm128Adc.setPrescaler(uint8_t scale){
+    Atm128Adcsra_t  current_val = call HplAtm128Adc.getAdcsra(); 
+    current_val.adif = FALSE;
+    current_val.adps = scale;
+    call HplAtm128Adc.setAdcsra(current_val);
+  }
+
+  // Individual bit manipulation. These all clear any pending A/D interrupt.
+  // It's not clear these are that useful...
+  async command void HplAtm128Adc.enableAdc() {
+    SET_BIT(ADCSRA, ADEN); 
+    call McuPowerState.update();
+  }
+  async command void HplAtm128Adc.disableAdc() {
+    CLR_BIT(ADCSRA, ADEN); 
+    call McuPowerState.update();
+  }
+  async command void HplAtm128Adc.enableInterruption() { SET_BIT(ADCSRA, ADIE); }
+  async command void HplAtm128Adc.disableInterruption() { CLR_BIT(ADCSRA, ADIE); }
+  async command void HplAtm128Adc.setContinuous() { 
+    ((Atm128Adcsrb_t*)&ADCSRB)->adts = 0; 
+    SET_BIT(ADCSRA, ADATE);
+  }
+  async command void HplAtm128Adc.setSingle() { CLR_BIT(ADCSRA, ADATE); }
+  async command void HplAtm128Adc.resetInterrupt() { SET_BIT(ADCSRA, ADIF); }
+  async command void HplAtm128Adc.startConversion() { SET_BIT(ADCSRA, ADSC); }
+
+
+  /* A/D status checks */
+  async command bool HplAtm128Adc.isEnabled()     {       
+    return (call HplAtm128Adc.getAdcsra()).aden; 
+  }
+
+  async command bool HplAtm128Adc.isStarted()     {
+    return (call HplAtm128Adc.getAdcsra()).adsc; 
+  }
+  
+  async command bool HplAtm128Adc.isComplete()    {
+    return (call HplAtm128Adc.getAdcsra()).adif; 
+  }
+
+  /* A/D interrupt handlers. Signals dataReady event with interrupts enabled */
+  AVR_ATOMIC_HANDLER(SIG_ADC) {
+    uint16_t data = call HplAtm128Adc.getValue();
+    
+    __nesc_enable_interrupt();
+    signal HplAtm128Adc.dataReady(data);
+  }
+
+  default async event void HplAtm128Adc.dataReady(uint16_t done) { }
+
+  async command bool HplAtm128Adc.cancel() { 
+    /* This is tricky */
+    atomic
+      {
+       Atm128Adcsra_t oldSr = call HplAtm128Adc.getAdcsra(), newSr;
+
+       /* To cancel a conversion, first turn off ADEN, then turn off
+          ADSC. We also cancel any pending interrupt.
+          Finally we reenable the ADC.
+       */
+       newSr = oldSr;
+       newSr.aden = FALSE;
+       newSr.adif = TRUE; /* This clears a pending interrupt... */
+       newSr.adie = FALSE; /* We don't want to start sampling again at the
+                              next sleep */
+       call HplAtm128Adc.setAdcsra(newSr);
+       newSr.adsc = FALSE;
+       call HplAtm128Adc.setAdcsra(newSr);
+       newSr.aden = TRUE;
+       call HplAtm128Adc.setAdcsra(newSr);
+
+       return oldSr.adif || oldSr.adsc;
+      }
+  }
+}
diff --git a/tos/chips/atm1281/atm128hardware.h b/tos/chips/atm1281/atm128hardware.h
new file mode 100644 (file)
index 0000000..ccef9f5
--- /dev/null
@@ -0,0 +1,192 @@
+/*                                                                     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.
+ *
+ *  Copyright (c) 2004-2005 Crossbow Technology, Inc.
+ *  Copyright (c) 2002-2003 Intel Corporation.
+ *  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 (updated) modification history and the author appear in
+ *  all copies of this source code.
+ *
+ *  Permission is also granted to distribute this software under the
+ *  standard BSD license as contained in the TinyOS distribution.
+ *
+ *  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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/*
+ *  Updated chips/atm128/atm128hardware.h with atm1281's MCU status and
+ *  memory control registers.
+ *
+ *  @author Janos Sallai, Martin Turon, Jason Hill, Philip Levis, Nelson Lee, David Gay
+ */
+
+
+#ifndef _H_atmega128hardware_H
+#define _H_atmega128hardware_H
+
+#include <avr/io.h>
+#if __AVR_LIBC_VERSION__ >= 10400UL
+#include <avr/interrupt.h>
+#else
+#include <avr/interrupt.h>
+#include <avr/signal.h>
+#endif
+#include <avr/wdt.h>
+#include <avr/pgmspace.h>
+#include "atm128const.h"
+
+/* We need slightly different defs than SIGNAL, INTERRUPT */
+#define AVR_ATOMIC_HANDLER(signame) \
+  void signame() __attribute__ ((signal)) @atomic_hwevent() @C()
+
+#define AVR_NONATOMIC_HANDLER(signame) \
+  void signame() __attribute__ ((interrupt)) @hwevent() @C()
+
+/* Macro to create union casting functions. */
+#define DEFINE_UNION_CAST(func_name, from_type, to_type) \
+  to_type func_name(from_type x) { \
+  union {from_type f; to_type t;} c = {f:x}; return c.t; }
+
+// Bit operators using bit number
+#define SET_BIT(port, bit)    ((port) |= _BV(bit))
+#define CLR_BIT(port, bit)    ((port) &= ~_BV(bit))
+#define READ_BIT(port, bit)   (((port) & _BV(bit)) != 0)
+#define FLIP_BIT(port, bit)   ((port) ^= _BV(bit))
+#define WRITE_BIT(port, bit, value) \
+   if (value) SET_BIT((port), (bit)); \
+   else CLR_BIT((port), (bit))
+
+// Bit operators using bit flag mask
+#define SET_FLAG(port, flag)  ((port) |= (flag))
+#define CLR_FLAG(port, flag)  ((port) &= ~(flag))
+#define READ_FLAG(port, flag) ((port) & (flag))
+
+/* Enables interrupts. */
+inline void __nesc_enable_interrupt() {
+    sei();
+}
+/* Disables all interrupts. */
+inline void __nesc_disable_interrupt() {
+    cli();
+}
+
+/* Defines data type for storing interrupt mask state during atomic. */
+typedef uint8_t __nesc_atomic_t;
+__nesc_atomic_t __nesc_atomic_start(void);
+void __nesc_atomic_end(__nesc_atomic_t original_SREG);
+
+#ifndef NESC_BUILD_BINARY
+/* @spontaneous() functions should not be included when NESC_BUILD_BINARY
+   is #defined, to avoid duplicate functions definitions wheb binary
+   components are used. Such functions do need a prototype in all cases,
+   though. */
+
+/* Saves current interrupt mask state and disables interrupts. */
+inline __nesc_atomic_t 
+__nesc_atomic_start(void) @spontaneous()
+{
+    __nesc_atomic_t result = SREG;
+    __nesc_disable_interrupt();
+    asm volatile("" : : : "memory"); /* ensure atomic section effect visibility */
+    return result;
+}
+
+/* Restores interrupt mask to original state. */
+inline void 
+__nesc_atomic_end(__nesc_atomic_t original_SREG) @spontaneous()
+{
+  asm volatile("" : : : "memory"); /* ensure atomic section effect visibility */
+  SREG = original_SREG;
+}
+#endif
+
+/* Defines the mcu_power_t type for atm128 power management. */
+typedef uint8_t mcu_power_t @combine("mcombine");
+
+
+enum {
+  ATM128_POWER_IDLE        = 0,
+  ATM128_POWER_ADC_NR      = 1,
+  ATM128_POWER_EXT_STANDBY = 2,
+  ATM128_POWER_SAVE        = 3,
+  ATM128_POWER_STANDBY     = 4,
+  ATM128_POWER_DOWN        = 5, 
+};
+
+/* Combine function.  */
+mcu_power_t mcombine(mcu_power_t m1, mcu_power_t m2) {
+  return (m1 < m2)? m1: m2;
+}
+
+/* MCU Status Register*/
+typedef struct
+{
+  uint8_t porf  : 1;    //!< Power-on Reset Flag
+  uint8_t extrf : 1;    //!< External Reset Flag
+  uint8_t borf  : 1;    //!< Brown-out Reset Flag
+  uint8_t wdrf  : 1;    //!< Watchdog Reset Flag
+  uint8_t jtrf  : 1;    //!< JTAG Reset Flag
+  uint8_t resv1 : 3;    //!< Reserved
+} Atm128_MCUSR_t;
+
+/* External Memory Control Register A*/
+typedef struct
+{
+  uint8_t srw00 : 1;    //!< Wait-state Select Bits for Lower Sector
+  uint8_t srw01 : 1;    //!< Wait-state Select Bits for Lower Sector
+  uint8_t srw10 : 1;    //!< Wait-state Select Bits for Upper Sector
+  uint8_t srw11 : 1;    //!< Wait-state Select Bits for Upper Sector
+  uint8_t srl   : 3;    //!< Wait-state Sector Limit
+  uint8_t sre   : 1;    //!< External SRAM/XMEM Enable
+} Atm128_XMCRA_t;
+
+/* External Memory Control Register B*/
+typedef struct
+{
+  uint8_t xmm    : 3;    //!< External Memory High Mask
+  uint8_t resv1  : 4;    //!< Reserved
+  uint8_t xmbk   : 1;    //!< External Memory Bus-keeper Enable
+} Atm128_XMCRB_t;
+
+
+#endif //_H_atmega128hardware_H
diff --git a/tos/chips/atm1281/timer/Atm1281AlarmAsyncP.nc b/tos/chips/atm1281/timer/Atm1281AlarmAsyncP.nc
new file mode 100644 (file)
index 0000000..7dd543b
--- /dev/null
@@ -0,0 +1,258 @@
+// $Id$
+/*
+ * Copyright (c) 2007 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+  
+/**
+ * Build a 32-bit alarm and counter from the atmega1281's 8-bit timer 2
+ * in asynchronous mode. Attempting to use the generic Atm128AlarmC
+ * component and the generic timer components runs into problems
+ * apparently related to letting timer 2 overflow.
+ * 
+ * So, instead, this version (inspired by the 1.x code and a remark from
+ * Martin Turon) directly builds a 32-bit alarm and counter on top of timer 2
+ * and never lets timer 2 overflow.
+ *
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+generic module Atm1281AlarmAsyncP(typedef precision, int divider) {
+  provides {
+    interface Init;
+    interface Alarm<precision, uint32_t>;
+    interface Counter<precision, uint32_t>;
+  }
+  uses {
+    interface HplAtm128Timer<uint8_t> as Timer;
+    interface HplAtm128TimerCtrl8 as TimerCtrl;
+    interface HplAtm128Compare<uint8_t> as Compare;
+    interface HplAtm128TimerAsync as TimerAsync;
+  }
+}
+implementation
+{
+  uint8_t set;                         /* Is the alarm set? */
+  uint32_t t0, dt;             /* Time of the next alarm */
+  norace uint32_t base;                /* base+TCNT2 is the current time if no
+                                  interrupt is pending. See Counter.get()
+                                  for the full details. */
+
+  enum {
+    MINDT = 2,                 /* Minimum interval between interrupts */
+    MAXT = 230                 /* Maximum value to let timer 2 reach
+                                  (from Joe Polastre and Robert Szewczyk's
+                                  painful experiences with the 1.x timer ;-)) */
+  };
+
+  void setInterrupt();
+
+  /* Configure timer 2 */
+  command error_t Init.init() {
+    atomic
+      {
+       Atm128_TCCR2A_t x;
+       Atm128_TCCR2B_t y;
+    
+       call TimerAsync.setTimer2Asynchronous();
+       x.flat = 0;
+       x.bits.wgm21 = 1; /* We use the clear-on-compare mode */
+       call TimerCtrl.setControlA(x.flat);
+       y.flat = 0;
+       y.bits.cs = divider;
+       call TimerCtrl.setControlB(y.flat);
+       call Compare.set(MAXT); /* setInterrupt needs a valid value here */
+       call Compare.start();
+      }
+    setInterrupt();
+    return SUCCESS;
+  }
+
+  /* Set compare register for timer 2 to n. But increment n by 1 if TCNT2 
+     reaches this value before we can set the compare register.
+  */
+  void setOcr2A(uint8_t n) {
+    while (call TimerAsync.compareABusy())
+      ;
+    if (n == call Timer.get())
+      n++;
+    /* Support for overflow. Force interrupt at wrap around value. 
+       This does not cause a backwards-in-time value as we do this
+       every time we set OCR2A. */
+    if (base + n + 1 < base)
+      n = -base - 1;
+    call Compare.set(n);
+  }
+
+  /* Update the compare register to trigger an interrupt at the
+     appropriate time based on the current alarm settings
+   */
+  void setInterrupt() {
+    bool fired = FALSE;
+
+    atomic
+      {
+       /* interrupt_in is the time to the next interrupt. Note that
+          compare register values are off by 1 (i.e., if you set OCR2A to
+          3, the interrupt will happen when TCNT2 is 4) */
+       uint8_t interrupt_in = 1 + call Compare.get() - call Timer.get();
+       uint8_t newOcr2A;
+       uint8_t tifr2 = call TimerCtrl.getInterruptFlag();
+       dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: TIFR is %hhx\n", tifr2);
+       if ((interrupt_in != 0 && interrupt_in < MINDT) || (tifr2 & (1 << OCF2A))) {
+         if (interrupt_in < MINDT) {
+           dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: under min: %hhu.\n", interrupt_in);
+         }
+         else {
+           dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: OCF2A set.\n");
+         }
+         return; // wait for next interrupt
+       }
+
+       /* When no alarm is set, we just ask for an interrupt every MAXT */
+       if (!set) {
+         newOcr2A = MAXT;
+         dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: no alarm set, set at max.\n");
+       }
+       else
+         {
+           uint32_t now = call Counter.get();
+           dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: now-t0 = %llu, dt = %llu\n", (now-t0), dt);
+           /* Check if alarm expired */
+           if ((uint32_t)(now - t0) >= dt)
+             {
+               set = FALSE;
+               fired = TRUE;
+               newOcr2A = MAXT;
+             }
+           else
+             {
+               /* No. Set compare register to time of next alarm if it's
+                  within the next MAXT units */
+               uint32_t alarm_in = (t0 + dt) - base;
+
+               if (alarm_in > MAXT)
+                 newOcr2A = MAXT;
+               else if ((uint8_t)alarm_in < MINDT) // alarm_in < MAXT ...
+                 newOcr2A = MINDT;
+               else
+                 newOcr2A = alarm_in;
+             }
+         }
+       newOcr2A--; // interrupt is 1ms late
+       setOcr2A(newOcr2A);
+      }
+    if (fired)
+      signal Alarm.fired();
+  }
+
+  async event void Compare.fired() {
+    int overflowed;
+
+    /* Compare register fired. Update time knowledge */
+    base += call Compare.get() + 1U; // interrupt is 1ms late
+    overflowed = !base;
+    __nesc_enable_interrupt();
+    setInterrupt();
+    if (overflowed)
+      signal Counter.overflow();
+  }  
+
+  async command uint32_t Counter.get() {
+    uint32_t now;
+
+    atomic
+      {
+       /* Current time is base+TCNT2 if no interrupt is pending. But if
+          an interrupt is pending, then it's base + compare value + 1 + TCNT2 */
+       uint8_t now8 = call Timer.get();
+
+       if ((((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag())).bits.ocfa)
+         /* We need to reread TCNT2 as it might've overflowed after we
+            read TCNT2 the first time */
+         now = base + call Compare.get() + 1 + call Timer.get();
+       else
+         /* We need to use the value of TCNT2 from before we check the
+            interrupt flag, as it might wrap around after the check */
+         now = base + now8;
+      }
+    return now;
+  }
+
+  async command bool Counter.isOverflowPending() {
+    atomic
+      return (((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag())).bits.ocfa &&
+       !(base + call Compare.get() + 1);
+  }
+
+  async command void Counter.clearOverflow() { 
+    atomic
+      if (call Counter.isOverflowPending())
+       {
+         base = 0;
+         call Compare.reset();
+       }
+      else
+       return;
+    setInterrupt();
+  }
+
+  async command void Alarm.start(uint32_t ndt) {
+    call Alarm.startAt(call Counter.get(), ndt);
+  }
+
+  async command void Alarm.stop() {
+    atomic set = FALSE;
+  }
+
+  async command bool Alarm.isRunning() {
+    atomic return set;
+  }
+
+  async command void Alarm.startAt(uint32_t nt0, uint32_t ndt) {
+    atomic
+      {
+       set = TRUE;
+       t0 = nt0;
+       dt = ndt;
+      }
+    setInterrupt();
+  }
+
+  async command uint32_t Alarm.getNow() {
+    return call Counter.get();
+  }
+
+  async command uint32_t Alarm.getAlarm() {
+    atomic return t0 + dt;
+  }
+
+  async event void Timer.overflow() { }
+}
diff --git a/tos/chips/atm1281/timer/Atm128AlarmAsyncC.nc b/tos/chips/atm1281/timer/Atm128AlarmAsyncC.nc
new file mode 100644 (file)
index 0000000..9fbb9f8
--- /dev/null
@@ -0,0 +1,67 @@
+// $Id$
+/*
+ * Copyright (c) 2007 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+/**
+ * Build a 32-bit alarm and counter from the atmega1281's 8-bit timer 2
+ * in asynchronous mode. Attempting to use the generic Atm128AlarmC
+ * component and the generic timer components runs into problems
+ * apparently related to letting timer 2 overflow.
+ * 
+ * So, instead, this version (inspired by the 1.x code and a remark from
+ * Martin Turon) directly builds a 32-bit alarm and counter on top of timer 2
+ * and never lets timer 2 overflow.
+ *
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+generic configuration Atm128AlarmAsyncC(typedef precision, int divider) {
+  provides {
+    interface Init @atleastonce();
+    interface Alarm<precision, uint32_t>;
+    interface Counter<precision, uint32_t>;
+  }
+}
+implementation
+{
+  components new Atm1281AlarmAsyncP(precision, divider),
+    HplAtm1281Timer2AsyncC;
+
+  Init = Atm1281AlarmAsyncP;
+  Alarm = Atm1281AlarmAsyncP;
+  Counter = Atm1281AlarmAsyncP;
+
+  Atm1281AlarmAsyncP.Timer -> HplAtm1281Timer2AsyncC;
+  Atm1281AlarmAsyncP.TimerCtrl -> HplAtm1281Timer2AsyncC;
+  Atm1281AlarmAsyncP.Compare -> HplAtm1281Timer2AsyncC;
+  Atm1281AlarmAsyncP.TimerAsync -> HplAtm1281Timer2AsyncC;
+}
diff --git a/tos/chips/atm1281/timer/Atm128Timer.h b/tos/chips/atm1281/timer/Atm128Timer.h
new file mode 100644 (file)
index 0000000..6ffb09d
--- /dev/null
@@ -0,0 +1,393 @@
+// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+
+/*
+ * This file contains the configuration constants for the Atmega1281
+ * clocks and timers.
+ *
+ * @author Philip Levis
+ * @author Martin Turon
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#ifndef _H_Atm128Timer_h
+#define _H_Atm128Timer_h
+
+/* Prescaler values for Timer/Counter 2 (8-bit asynchronous ) */
+enum {
+  ATM128_CLK8_OFF         = 0x0,
+  ATM128_CLK8_NORMAL      = 0x1,
+  ATM128_CLK8_DIVIDE_8    = 0x2,
+  ATM128_CLK8_DIVIDE_32   = 0x3,
+  ATM128_CLK8_DIVIDE_64   = 0x4,
+  ATM128_CLK8_DIVIDE_128  = 0x5,
+  ATM128_CLK8_DIVIDE_256  = 0x6,
+  ATM128_CLK8_DIVIDE_1024 = 0x7,
+};
+
+/* Prescaler values for Timer/Counter 0 (8-bit) and 1, 3, 4, 5 (16-bit) */
+enum {
+  ATM128_CLK16_OFF           = 0x0,
+  ATM128_CLK16_NORMAL        = 0x1,
+  ATM128_CLK16_DIVIDE_8      = 0x2,
+  ATM128_CLK16_DIVIDE_64     = 0x3,
+  ATM128_CLK16_DIVIDE_256    = 0x4,
+  ATM128_CLK16_DIVIDE_1024   = 0x5,
+  ATM128_CLK16_EXTERNAL_FALL = 0x6,
+  ATM128_CLK16_EXTERNAL_RISE = 0x7,
+};
+
+/* Common scales across both 8-bit and 16-bit clocks. */
+enum {
+    AVR_CLOCK_OFF = 0,
+    AVR_CLOCK_ON  = 1,
+    AVR_CLOCK_DIVIDE_8 = 2,
+};
+
+enum {
+    ATM128_TIMER_COMPARE_NORMAL = 0,
+    ATM128_TIMER_COMPARE_TOGGLE,
+    ATM128_TIMER_COMPARE_CLEAR,
+    ATM128_TIMER_COMPARE_SET
+};
+
+
+/* 8-bit Waveform Generation Modes */
+enum {
+    ATM128_WAVE8_NORMAL = 0,
+    ATM128_WAVE8_PWM,
+    ATM128_WAVE8_CTC,
+    ATM128_WAVE8_PWM_FAST,
+};
+
+/* 16-bit Waveform Generation Modes */
+enum {
+    ATM128_WAVE16_NORMAL = 0,
+    ATM128_WAVE16_PWM_8BIT,
+    ATM128_WAVE16_PWM_9BIT,
+    ATM128_WAVE16_PWM_10BIT,
+    ATM128_WAVE16_CTC_COMPARE,
+    ATM128_WAVE16_PWM_FAST_8BIT,
+    ATM128_WAVE16_PWM_FAST_9BIT,
+    ATM128_WAVE16_PWM_FAST_10BIT,
+    ATM128_WAVE16_PWM_CAPTURE_LOW,
+    ATM128_WAVE16_PWM_COMPARE_LOW,
+    ATM128_WAVE16_PWM_CAPTURE_HIGH,
+    ATM128_WAVE16_PWM_COMPARE_HIGH,
+    ATM128_WAVE16_CTC_CAPTURE,
+    ATM128_WAVE16_RESERVED,
+    ATM128_WAVE16_PWM_FAST_CAPTURE,
+    ATM128_WAVE16_PWM_FAST_COMPARE,
+};
+
+/* 8-bit Timer compare settings */
+enum {
+    ATM128_COMPARE_OFF = 0,  //!< compare disconnected
+    ATM128_COMPARE_TOGGLE,   //!< toggle on match (PWM reserved
+    ATM128_COMPARE_CLEAR,    //!< clear on match  (PWM downcount)
+    ATM128_COMPARE_SET,      //!< set on match    (PWN upcount)
+};
+
+/* 8-bit Timer/Counter 0 Control Register A*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t wgm00 : 1;  //!< Waveform generation mode (low bit)
+    uint8_t wgm01 : 1;  //!< Waveform generation mode (high bit)
+    uint8_t resv1 : 2;  //!< Compare Match Output
+    uint8_t com0b0: 1;  //!< Compare Match Output
+    uint8_t com0b1: 1;  //!< Compare Match Output
+    uint8_t com0a0: 1;  //!< Compare Match Output
+    uint8_t com0a1: 1;  //!< Compare Match Output
+  } bits;
+} Atm128_TCCR0A_t;
+
+/* 8-bit Timer/Counter 0 Control Register B*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t cs00  : 1;  //!< Clock Select 0
+    uint8_t cs01  : 1;  //!< Clock Select 1
+    uint8_t cs02  : 2;  //!< Clock Select 2
+    uint8_t wgm02 : 1;  //!< Waveform Generation Mode
+    uint8_t resv1 : 2;  //!< Reserved
+    uint8_t foc0b : 1;  //!< Force Output Compare B
+    uint8_t foc0a : 1;  //!< Force Output Compare A
+  } bits;
+} Atm128_TCCR0B_t;
+
+/* Timer/Counter 0 Interrupt Mask Register */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t toie0 : 1; //!< Timer/Counter0 Overflow Interrupt Enable
+    uint8_t ocie0a: 1; //!< Timer/Counter0 Output Compare Match A Interrupt Enable
+    uint8_t ocie0e: 1; //!< Timer/Counter Output Compare Match B Interrupt Enable
+    uint8_t resv1 : 5; //!< Reserved
+  } bits;
+} Atm128_TIMSK0_t;
+
+/* Timer/Counter 0 Interrupt Flag Register*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t tov0  : 1; //!< Timer/Counter0 Overflow Flag
+    uint8_t ocf0a : 1; //!< Timer/Counter 0 Output Compare A Match Flag
+    uint8_t ocf0b : 1; //!< Timer/Counter 0 Output Compare B Match Flag
+    uint8_t resv1 : 5; //!< Reserved
+  } bits;
+} Atm128_TIFR0_t;
+
+/* Asynchronous Status Register -- Timer2 */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t tcr2bub: 1;  //!< Timer/Counter Control Register2 Update Busy
+    uint8_t tcr2aub: 1;  //!< Timer/Counter Control Register2 Update Busy
+    uint8_t ocr2bub: 1;  //!< Output Compare Register2 Update Busy
+    uint8_t ocr2aub: 1;  //!< Output Compare Register2 Update Busy
+    uint8_t tcn2ub : 1;  //!< Timer/Counter2 Update Busy
+    uint8_t as2    : 1;  //!< Asynchronous Timer/Counter2 (off=CLK_IO,on=TOSC1)
+    uint8_t exclk  : 1;  //!< Enable External Clock Input
+    uint8_t resv1  : 1;  //!< Reserved
+  } bits;
+} Atm128_ASSR_t;
+
+/* Timer/Counter 2 Control Register A*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t wgm20 : 1; //!< Waveform Generation Mode
+    uint8_t wgm21 : 1; //!< Waveform Generation Mode
+    uint8_t resv1 : 2; //!< Reserved
+    uint8_t comb: 2; //!< Compare Output Mode for Channel B
+    uint8_t coma: 2; //!< Compare Output Mode for Channel A
+  } bits;
+} Atm128_TCCR2A_t;
+
+/* Timer/Counter 2 Control Register B*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t cs    : 3; //!< Clock Select
+    uint8_t wgm22 : 1; //!< Waveform Generation Mode
+    uint8_t resv1 : 2; //!< Reserved
+    uint8_t foc2b : 1; //!< Force Output Compare B
+    uint8_t foc2a : 1; //!< Force Output Compare A
+  } bits;
+} Atm128_TCCR2B_t;
+
+/* Timer/Counter 2 Interrupt Mask Register */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t toie : 1; //!< Timer/Counter2 Overflow Interrupt Enable
+    uint8_t ociea: 1; //!< Timer/Counter2 Output Compare Match A Interrupt Enable
+    uint8_t ocieb: 1; //!< Timer/Counter Output Compare Match B Interrupt Enable
+    uint8_t resv1 : 5; //!< Reserved
+  } bits;
+} Atm128_TIMSK2_t;
+
+/* Timer/Counter 2 Interrupt Flag Register */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t tov  : 1; //!< Timer1 Overflow Flag
+    uint8_t ocfa : 1; //!< Timer1 Output Compare Flag A
+    uint8_t ocfb : 1; //!< Timer1 Output Compare Flag B
+    uint8_t resv1 : 5; //!< Reserved
+  } bits;
+} Atm128_TIFR2_t;
+
+
+/* Timer/Counter 1,3,4,5 Control Register A*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t wgm01  : 2; //!< Waveform Generation Mode
+    uint8_t comc   : 2; //!< Compare Output Mode for Channel C
+    uint8_t comb   : 2; //!< Compare Output Mode for Channel B
+    uint8_t coma   : 2; //!< Compare Output Mode for Channel A
+  } bits;
+} Atm128_TCCRA_t;
+
+/* Timer/Counter 1,3,4,5 Control Register B*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t cs    : 3; //!< Clock Select
+    uint8_t wgm23 : 2; //!< Waveform Generation Mode
+    uint8_t resv1 : 1; //!< Reserved
+    uint8_t ices  : 1; //!< Input Capture Edge Select
+    uint8_t icnc  : 1; //!< Input Capture Noise Canceler
+  } bits;
+} Atm128_TCCRB_t;
+
+/* Timer/Counter 1,3,4,5 Control Register C*/
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t resv1 : 5; //!< Reserved
+    uint8_t focc : 1; //!< Force Output Compare for Channel A
+    uint8_t focb : 1; //!< Force Output Compare for Channel A
+    uint8_t foca : 1; //!< Force Output Compare for Channel A
+  } bits;
+} Atm128_TCCRC_t;
+
+/* Timer/Counter 1,3,4,5 Interrupt Mask Register */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t toie : 1; //!< Timer/Counter1 Overflow Interrupt Enable
+    uint8_t ociea: 1; //!< Timer/Counter1 Output Compare Match A Interrupt Enable
+    uint8_t ocieb: 1; //!< Timer/Counter1 Output Compare Match B Interrupt Enable
+    uint8_t ociec: 1; //!< Timer/Counter1 Output Compare Match C Interrupt Enable
+    uint8_t resv1: 1; //!< Reserved
+    uint8_t icie : 1; //!< Timer/Counter1, Input Capture Interrupt Enable
+    uint8_t resv2 : 2; //!< Reserved
+  } bits;
+} Atm128_TIMSK_t;
+
+/* Timer/Counter 1,3,4,5 Interrupt Flag Register */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t tov  : 1; //!< Timer1 Overflow Flag
+    uint8_t ocfa : 1; //!< Timer1 Output Compare Flag A
+    uint8_t ocfb : 1; //!< Timer1 Output Compare Flag B
+    uint8_t ocfc : 1; //!< Timer1 Output Compare Flag C
+    uint8_t resv1: 1; //!< Reserved
+    uint8_t icf  : 1; //!< Timer1 Input Capture Flag 
+    uint8_t resv2: 2; //!< Reserved
+  } bits;
+} Atm128_TIFR_t;
+
+/* General Timer/Counter Control Register */
+typedef union
+{
+  uint8_t flat;
+  struct {
+    uint8_t psrsync: 1; //!< Prescaler Reset for Synchronous Timer/Counters 0,1,3,4,5
+    uint8_t psrasy : 1; //!< Prescaler Reset Timer/Counter2
+    uint8_t resv1  : 5; //!< Reserved
+    uint8_t tsm    : 1; //!< Timer/Counter Synchronization Mode
+  } bits;
+} Atm128_GTCCR_t;
+
+// Read/Write these 16-bit Timer registers
+// Access as bytes.  Read low before high.  Write high before low. 
+typedef uint8_t Atm128_TCNT1H_t;  //!< Timer1 Register
+typedef uint8_t Atm128_TCNT1L_t;  //!< Timer1 Register
+typedef uint8_t Atm128_TCNT3H_t;  //!< Timer3 Register
+typedef uint8_t Atm128_TCNT3L_t;  //!< Timer3 Register
+typedef uint8_t Atm128_TCNT4H_t;  //!< Timer4 Register
+typedef uint8_t Atm128_TCNT4L_t;  //!< Timer4 Register
+typedef uint8_t Atm128_TCNT5H_t;  //!< Timer5 Register
+typedef uint8_t Atm128_TCNT5L_t;  //!< Timer5 Register
+
+/* Contains value to continuously compare with Timer1 */
+typedef uint8_t Atm128_OCR1AH_t;  //!< Output Compare Register 1A
+typedef uint8_t Atm128_OCR1AL_t;  //!< Output Compare Register 1A
+typedef uint8_t Atm128_OCR1BH_t;  //!< Output Compare Register 1B
+typedef uint8_t Atm128_OCR1BL_t;  //!< Output Compare Register 1B
+typedef uint8_t Atm128_OCR1CH_t;  //!< Output Compare Register 1C
+typedef uint8_t Atm128_OCR1CL_t;  //!< Output Compare Register 1C
+
+/* Contains value to continuously compare with Timer3 */
+typedef uint8_t Atm128_OCR3AH_t;  //!< Output Compare Register 3A
+typedef uint8_t Atm128_OCR3AL_t;  //!< Output Compare Register 3A
+typedef uint8_t Atm128_OCR3BH_t;  //!< Output Compare Register 3B
+typedef uint8_t Atm128_OCR3BL_t;  //!< Output Compare Register 3B
+typedef uint8_t Atm128_OCR3CH_t;  //!< Output Compare Register 3C
+typedef uint8_t Atm128_OCR3CL_t;  //!< Output Compare Register 3C
+
+/* Contains value to continuously compare with Timer4 */
+typedef uint8_t Atm128_OCR4AH_t;  //!< Output Compare Register 4A
+typedef uint8_t Atm128_OCR4AL_t;  //!< Output Compare Register 4A
+typedef uint8_t Atm128_OCR4BH_t;  //!< Output Compare Register 4B
+typedef uint8_t Atm128_OCR4BL_t;  //!< Output Compare Register 4B
+typedef uint8_t Atm128_OCR4CH_t;  //!< Output Compare Register 4C
+typedef uint8_t Atm128_OCR4CL_t;  //!< Output Compare Register 4C
+
+/* Contains value to continuously compare with Timer5 */
+typedef uint8_t Atm128_OCR5AH_t;  //!< Output Compare Register 5A
+typedef uint8_t Atm128_OCR5AL_t;  //!< Output Compare Register 5A
+typedef uint8_t Atm128_OCR5BH_t;  //!< Output Compare Register 5B
+typedef uint8_t Atm128_OCR5BL_t;  //!< Output Compare Register 5B
+typedef uint8_t Atm128_OCR5CH_t;  //!< Output Compare Register 5C
+typedef uint8_t Atm128_OCR5CL_t;  //!< Output Compare Register 5C
+
+/* Contains counter value when event occurs on ICPn pin. */
+typedef uint8_t Atm128_ICR1H_t;  //!< Input Capture Register 1
+typedef uint8_t Atm128_ICR1L_t;  //!< Input Capture Register 1
+typedef uint8_t Atm128_ICR3H_t;  //!< Input Capture Register 3
+typedef uint8_t Atm128_ICR3L_t;  //!< Input Capture Register 3
+typedef uint8_t Atm128_ICR4H_t;  //!< Input Capture Register 4
+typedef uint8_t Atm128_ICR4L_t;  //!< Input Capture Register 4
+typedef uint8_t Atm128_ICR5H_t;  //!< Input Capture Register 5
+typedef uint8_t Atm128_ICR5L_t;  //!< Input Capture Register 5
+
+/* Resource strings for timer 1 and 3 compare registers */
+#define UQ_TIMER1_COMPARE "atm128.timer1"
+#define UQ_TIMER3_COMPARE "atm128.timer3" 
+
+#endif //_H_Atm128Timer_h
+
diff --git a/tos/chips/atm1281/timer/HplAtm1281Timer1P.nc b/tos/chips/atm1281/timer/HplAtm1281Timer1P.nc
new file mode 100644 (file)
index 0000000..0f6b438
--- /dev/null
@@ -0,0 +1,225 @@
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Internal component of the HPL interface to Atmega1281 timer 1.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+module HplAtm1281Timer1P
+{
+  provides {
+    // 16-bit Timers
+    interface HplAtm128Timer<uint16_t>   as Timer;
+    interface HplAtm128TimerCtrl16       as TimerCtrl;
+    interface HplAtm128Capture<uint16_t> as Capture;
+    interface HplAtm128Compare<uint16_t> as CompareA;
+    interface HplAtm128Compare<uint16_t> as CompareB;
+    interface HplAtm128Compare<uint16_t> as CompareC;
+  }
+}
+implementation
+{
+  //=== Read the current timer value. ===================================
+  async command uint16_t Timer.get() { return TCNT1; }
+
+  //=== Set/clear the current timer value. ==============================
+  async command void Timer.set(uint16_t t) { TCNT1 = t; }
+
+  //=== Read the current timer scale. ===================================
+  async command uint8_t Timer.getScale() { return TCCR1B & 0x7; }
+
+  //=== Turn off the timers. ============================================
+  async command void Timer.off() { call Timer.setScale(AVR_CLOCK_OFF); }
+
+  //=== Write a new timer scale. ========================================
+  async command void Timer.setScale(uint8_t s)  { 
+    Atm128_TCCRB_t x = (Atm128_TCCRB_t) call TimerCtrl.getControlB();
+    x.bits.cs = s;
+    call TimerCtrl.setControlB(x.flat);  
+  }
+
+  //=== Read the control registers. =====================================
+  async command uint8_t TimerCtrl.getControlA() { 
+    return TCCR1A; 
+  }
+
+  async command uint8_t TimerCtrl.getControlB() { 
+    return TCCR1B; 
+  }
+
+  async command uint8_t TimerCtrl.getControlC() { 
+    return TCCR1C; 
+  }
+
+  //=== Write the control registers. ====================================
+  async command void TimerCtrl.setControlA( uint8_t x ) { 
+    TCCR1A = x; 
+  }
+
+  async command void TimerCtrl.setControlB( uint8_t x ) { 
+    TCCR1B = x; 
+  }
+
+  async command void TimerCtrl.setControlC( uint8_t x ) { 
+    TCCR1C = x; 
+  }
+
+  //=== Read the interrupt mask. =====================================
+  async command uint8_t TimerCtrl.getInterruptMask() { 
+    return TIMSK1; 
+  }
+
+  //=== Write the interrupt mask. ====================================
+  async command void TimerCtrl.setInterruptMask( uint8_t x ) { 
+    TIMSK1 = x; 
+  }
+
+  //=== Read the interrupt flags. =====================================
+  async command uint8_t TimerCtrl.getInterruptFlag() { 
+    return TIFR1; 
+  }
+
+  //=== Write the interrupt flags. ====================================
+  async command void TimerCtrl.setInterruptFlag( uint8_t x ) { 
+    TIFR1 = x; 
+  }
+
+  //=== Capture 16-bit implementation. ===================================
+  async command void Capture.setEdge(bool up) { WRITE_BIT(TCCR1B,ICES1, up); }
+
+  //=== Timer 16-bit implementation. ===================================
+  async command void Timer.reset()    { TIFR1 = 1 << TOV1; }
+  async command void Capture.reset()  { TIFR1 = 1 << ICF1; }
+  async command void CompareA.reset() { TIFR1 = 1 << OCF1A; }
+  async command void CompareB.reset() { TIFR1 = 1 << OCF1B; }
+  async command void CompareC.reset() { TIFR1 = 1 << OCF1C; }
+
+  async command void Timer.start()    { SET_BIT(TIMSK1,TOIE1); }
+  async command void Capture.start()  { SET_BIT(TIMSK1,ICIE1); }
+  async command void CompareA.start() { SET_BIT(TIMSK1,OCIE1A); }
+  async command void CompareB.start() { SET_BIT(TIMSK1,OCIE1B); }
+  async command void CompareC.start() { SET_BIT(TIMSK1,OCIE1C); }
+
+  async command void Timer.stop()    { CLR_BIT(TIMSK1,TOIE1); }
+  async command void Capture.stop()  { CLR_BIT(TIMSK1,ICIE1); }
+  async command void CompareA.stop() { CLR_BIT(TIMSK1,OCIE1A); }
+  async command void CompareB.stop() { CLR_BIT(TIMSK1,OCIE1B); }
+  async command void CompareC.stop() { CLR_BIT(TIMSK1,OCIE1C); }
+
+  async command bool Timer.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.tov; 
+  }
+  async command bool Capture.test()  { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.icf; 
+  }
+  async command bool CompareA.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfa; 
+  }
+  async command bool CompareB.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfb; 
+  }
+  async command bool CompareC.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfc; 
+  }
+
+  async command bool Timer.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.toie;
+  }
+  async command bool Capture.isOn()  {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.icie;
+  }
+  async command bool CompareA.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociea;
+  }
+  async command bool CompareB.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ocieb;
+  }
+  async command bool CompareC.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociec;
+  }
+
+  //=== Read the compare registers. =====================================
+  async command uint16_t CompareA.get() { return OCR1A; }
+  async command uint16_t CompareB.get() { return OCR1B; }
+  async command uint16_t CompareC.get() { return OCR1C; }
+
+  //=== Write the compare registers. ====================================
+  async command void CompareA.set(uint16_t t) { OCR1A = t; }
+  async command void CompareB.set(uint16_t t) { OCR1B = t; }
+  async command void CompareC.set(uint16_t t) { OCR1C = t; }
+
+  //=== Read the capture registers. =====================================
+  async command uint16_t Capture.get() { return ICR1; }
+
+  //=== Write the capture registers. ====================================
+  async command void Capture.set(uint16_t t)  { ICR1 = t; }
+
+  //=== Timer interrupts signals ========================================
+  default async event void CompareA.fired() { }
+  AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE1A) {
+    signal CompareA.fired();
+  }
+  default async event void CompareB.fired() { }
+  AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE1B) {
+    signal CompareB.fired();
+  }
+  default async event void CompareC.fired() { }
+  AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE1C) {
+    signal CompareC.fired();
+  }
+  default async event void Capture.captured(uint16_t time) { }
+  AVR_NONATOMIC_HANDLER(SIG_INPUT_CAPTURE1) {
+    signal Capture.captured(call Timer.get());
+  }
+  default async event void Timer.overflow() { }
+  AVR_NONATOMIC_HANDLER(SIG_OVERFLOW1) {
+    signal Timer.overflow();
+  }
+}
diff --git a/tos/chips/atm1281/timer/HplAtm1281Timer2AsyncC.nc b/tos/chips/atm1281/timer/HplAtm1281Timer2AsyncC.nc
new file mode 100644 (file)
index 0000000..0cb88d4
--- /dev/null
@@ -0,0 +1,87 @@
+/// $Id$
+/*
+ * Copyright (c) 2006 Stanford University.
+ * 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 Stanford University 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 STANFORD
+ * UNIVERSITY 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Simple wrapper around the actual timer implementation that automatically
+ * wires it to McuSleepC for low-power calculations..
+ *
+ * @author Philip Levis
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+configuration HplAtm1281Timer2AsyncC
+{
+  provides {
+    // 8-bit Timers
+    interface HplAtm128Timer<uint8_t>   as Timer;
+    interface HplAtm128TimerCtrl8       as TimerCtrl;
+    interface HplAtm128Compare<uint8_t> as Compare;
+    interface HplAtm128TimerAsync       as TimerAsync;
+  }
+}
+implementation
+{
+  components HplAtm1281Timer2AsyncP;
+  components McuSleepC;
+
+  McuSleepC.McuPowerOverride -> HplAtm1281Timer2AsyncP;
+
+  Timer = HplAtm1281Timer2AsyncP;
+  TimerCtrl = HplAtm1281Timer2AsyncP;
+  Compare = HplAtm1281Timer2AsyncP;
+  TimerAsync = HplAtm1281Timer2AsyncP;
+}
diff --git a/tos/chips/atm1281/timer/HplAtm1281Timer2AsyncP.nc b/tos/chips/atm1281/timer/HplAtm1281Timer2AsyncP.nc
new file mode 100644 (file)
index 0000000..b4b3623
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL interface to Atmega1281 timer 2 in ASYNC mode. This is a specialised
+ * HPL component that assumes that timer 2 is used in ASYNC mode and
+ * includes some workarounds for some of the weirdnesses (delayed overflow
+ * interrupt) of that mode.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay <dgay@intel-research.net>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+module HplAtm1281Timer2AsyncP
+{
+  provides {
+    // 8-bit Timers
+    interface HplAtm128Timer<uint8_t>   as Timer;
+    interface HplAtm128TimerCtrl8       as TimerCtrl;
+    interface HplAtm128Compare<uint8_t> as Compare;
+    interface McuPowerOverride;
+    interface HplAtm128TimerAsync       as TimerAsync;
+  }
+}
+implementation
+{
+//  bool inOverflow;
+
+//  command error_t Init.init() {
+//    SET_BIT(ASSR, AS2);  // set Timer/Counter2 to asynchronous mode
+//    return SUCCESS;
+//  }
+
+  //=== Read the current timer value. ===================================
+  async command uint8_t  Timer.get() { return TCNT2; }
+
+  //=== Set/clear the current timer value. ==============================
+  async command void Timer.set(uint8_t t)  {
+    while (ASSR & 1 << TCN2UB)
+      ;
+    TCNT2 = t;
+  }
+
+  //=== Read the current timer scale. ===================================
+  async command uint8_t Timer.getScale() { return TCCR2B & 0x7; }
+
+  //=== Turn off the timers. ============================================
+  async command void Timer.off() { call Timer.setScale(AVR_CLOCK_OFF); }
+
+  //=== Write a new timer scale. ========================================
+  async command void Timer.setScale(uint8_t s)  { 
+    Atm128_TCCR2B_t x = (Atm128_TCCR2B_t) call TimerCtrl.getControlB();
+    x.bits.cs = s;
+    call TimerCtrl.setControlB(x.flat);  
+  }
+
+  //=== Read the control registers. =====================================
+  async command uint8_t TimerCtrl.getControlA() { 
+    return TCCR2A; 
+  }
+
+  async command uint8_t TimerCtrl.getControlB() { 
+    return TCCR2B; 
+  }
+
+  //=== Write the control registers. ====================================
+  async command void TimerCtrl.setControlA( uint8_t x ) { 
+    while (ASSR & 1 << TCR2AUB)
+      ;
+    TCCR2A = ((Atm128_TCCR2A_t)x).flat; 
+  }
+
+  async command void TimerCtrl.setControlB( uint8_t x ) { 
+    while (ASSR & 1 << TCR2BUB)
+      ;
+    TCCR2B = ((Atm128_TCCR2B_t)x).flat; 
+  }
+
+  //=== Read the interrupt mask. =====================================
+  async command uint8_t TimerCtrl.getInterruptMask() { 
+    return TIMSK2; 
+  }
+
+  //=== Write the interrupt mask. ====================================
+  async command void TimerCtrl.setInterruptMask( uint8_t x ) { 
+    TIMSK2 = x; 
+  }
+
+  //=== Read the interrupt flags. =====================================
+  async command uint8_t TimerCtrl.getInterruptFlag() { 
+    return TIFR2; 
+  }
+
+  //=== Write the interrupt flags. ====================================
+  async command void TimerCtrl.setInterruptFlag( uint8_t x ) { 
+    TIFR2 = x; 
+  }
+
+  //=== Timer 8-bit implementation. ====================================
+  async command void Timer.reset() { TIFR2 = 1 << TOV2; }
+  async command void Timer.start() { SET_BIT(TIMSK2, TOIE2); }
+  async command void Timer.stop()  { CLR_BIT(TIMSK2, TOIE2); }
+
+  bool overflowed() {
+    return ((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag()).bits.tov; 
+  }
+
+  async command bool Timer.test()  { 
+    return overflowed();
+  }
+  
+  async command bool Timer.isOn()  { 
+    return ((Atm128_TIMSK2_t)call TimerCtrl.getInterruptMask()).bits.toie; 
+  }
+  
+  async command void Compare.reset() { TIFR2 = 1 << OCF2A; }
+  async command void Compare.start() { SET_BIT(TIMSK2,OCIE2A); }
+  async command void Compare.stop()  { CLR_BIT(TIMSK2,OCIE2A); }
+  async command bool Compare.test()  { 
+    return ((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag()).bits.ocfa; 
+  }
+  async command bool Compare.isOn()  { 
+    return ((Atm128_TIMSK2_t)call TimerCtrl.getInterruptMask()).bits.ociea; 
+  }
+
+  //=== Read the compare registers. =====================================
+  async command uint8_t Compare.get(){ return OCR2A; }
+
+  //=== Write the compare registers. ====================================
+  async command void Compare.set(uint8_t t)   { 
+    atomic
+      {
+       while (ASSR & 1 << OCR2AUB)
+         ;
+       OCR2A = t; 
+      }
+  }
+
+  //=== Timer interrupts signals ========================================
+  inline void stabiliseTimer2() {
+    TCCR2A = TCCR2A;
+    while (ASSR & 1 << TCR2AUB)
+      ;
+  }
+
+  /**
+   * On the atm128, there is a small latency when waking up from
+   * POWER_SAVE mode. So if a timer is going to go off very soon, it's
+   * better to drop down until EXT_STANDBY, which has a 6 cycle wakeup
+   * latency. This function calculates whether staying in EXT_STANDBY
+   * is needed. If the timer is not running it returns POWER_DOWN.
+   * Please refer to TEP 112 and the atm128 datasheet for details.
+   */
+  
+  async command mcu_power_t McuPowerOverride.lowestState() {
+    uint8_t diff;
+    // We need to make sure that the sleep wakeup latency will not
+    // cause us to miss a timer. POWER_SAVE 
+    if (TIMSK2 & (1 << OCIE2A | 1 << TOIE2)) {
+      // need to wait for timer 2 updates propagate before sleeping
+      // (we don't need to worry about reentering sleep mode too early,
+      // as the wake ups from timer2 wait at least one TOSC1 cycle
+      // anyway - see the stabiliseTimer2 function)
+      while (ASSR & (1 << TCN2UB | 1 << OCR2AUB | 1 << TCR2AUB))
+       ;
+      diff = OCR2A - TCNT2;
+      if (diff < EXT_STANDBY_T0_THRESHOLD ||
+         TCNT2 > 256 - EXT_STANDBY_T0_THRESHOLD) 
+       return ATM128_POWER_EXT_STANDBY;
+      return ATM128_POWER_SAVE;
+    }
+    else {
+      return ATM128_POWER_DOWN;
+    }
+  }
+
+  default async event void Compare.fired() { }
+  AVR_ATOMIC_HANDLER(SIG_OUTPUT_COMPARE2A) {
+    stabiliseTimer2();
+//    __nesc_enable_interrupt();
+   
+    signal Compare.fired();
+  }
+
+  default async event void Timer.overflow() { }
+  AVR_ATOMIC_HANDLER(SIG_OVERFLOW2) {
+    stabiliseTimer2();
+//    inOverflow = TRUE;
+    signal Timer.overflow();
+//    inOverflow = FALSE;
+  }
+
+  // Asynchronous status register support
+  async command Atm128_ASSR_t TimerAsync.getAssr() {
+    return *(Atm128_ASSR_t *)&ASSR;
+  }
+
+  async command void TimerAsync.setAssr(Atm128_ASSR_t x) {
+    ASSR = x.flat;
+  }
+
+  async command void TimerAsync.setTimer2Asynchronous() {
+    ASSR |= 1 << AS2;
+  }
+
+  async command int TimerAsync.controlABusy() {
+    return (ASSR & (1 << TCR2AUB)) != 0;
+  }
+
+  async command int TimerAsync.controlBBusy() {
+    return (ASSR & (1 << TCR2BUB)) != 0;
+  }
+
+  async command int TimerAsync.compareABusy() {
+    return (ASSR & (1 << OCR2AUB)) != 0;
+  }
+
+  async command int TimerAsync.compareBBusy() {
+    return (ASSR & (1 << OCR2BUB)) != 0;
+  }
+
+  async command int TimerAsync.countBusy() {
+    return (ASSR & (1 << TCN2UB)) != 0;
+  }
+
+}
diff --git a/tos/chips/atm1281/timer/HplAtm1281Timer3P.nc b/tos/chips/atm1281/timer/HplAtm1281Timer3P.nc
new file mode 100644 (file)
index 0000000..9f25ec6
--- /dev/null
@@ -0,0 +1,225 @@
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Internal component of the HPL interface to Atmega1281 timer 3.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+module HplAtm1281Timer3P
+{
+  provides {
+    // 16-bit Timers
+    interface HplAtm128Timer<uint16_t>   as Timer;
+    interface HplAtm128TimerCtrl16       as TimerCtrl;
+    interface HplAtm128Capture<uint16_t> as Capture;
+    interface HplAtm128Compare<uint16_t> as CompareA;
+    interface HplAtm128Compare<uint16_t> as CompareB;
+    interface HplAtm128Compare<uint16_t> as CompareC;
+  }
+}
+implementation
+{
+  //=== Read the current timer value. ===================================
+  async command uint16_t Timer.get() { return TCNT3; }
+
+  //=== Set/clear the current timer value. ==============================
+  async command void Timer.set(uint16_t t) { TCNT3 = t; }
+
+  //=== Read the current timer scale. ===================================
+  async command uint8_t Timer.getScale() { return TCCR3B & 0x7; }
+
+  //=== Turn off the timers. ============================================
+  async command void Timer.off() { call Timer.setScale(AVR_CLOCK_OFF); }
+
+  //=== Write a new timer scale. ========================================
+  async command void Timer.setScale(uint8_t s)  { 
+    Atm128_TCCRB_t x = (Atm128_TCCRB_t) call TimerCtrl.getControlB();
+    x.bits.cs = s;
+    call TimerCtrl.setControlB(x.flat);  
+  }
+
+  //=== Read the control registers. =====================================
+  async command uint8_t TimerCtrl.getControlA() { 
+    return TCCR3A; 
+  }
+
+  async command uint8_t TimerCtrl.getControlB() { 
+    return TCCR3B; 
+  }
+
+  async command uint8_t TimerCtrl.getControlC() { 
+    return TCCR3C; 
+  }
+
+  //=== Write the control registers. ====================================
+  async command void TimerCtrl.setControlA( uint8_t x ) { 
+    TCCR3A = x; 
+  }
+
+  async command void TimerCtrl.setControlB( uint8_t x ) { 
+    TCCR3B = x; 
+  }
+
+  async command void TimerCtrl.setControlC( uint8_t x ) { 
+    TCCR3C = x; 
+  }
+
+  //=== Read the interrupt mask. =====================================
+  async command uint8_t TimerCtrl.getInterruptMask() { 
+    return TIMSK3; 
+  }
+
+  //=== Write the interrupt mask. ====================================
+  async command void TimerCtrl.setInterruptMask( uint8_t x ) { 
+    TIMSK3 = x; 
+  }
+
+  //=== Read the interrupt flags. =====================================
+  async command uint8_t TimerCtrl.getInterruptFlag() { 
+    return TIFR3; 
+  }
+
+  //=== Write the interrupt flags. ====================================
+  async command void TimerCtrl.setInterruptFlag( uint8_t x ) { 
+    TIFR3 = x; 
+  }
+
+  //=== Capture 16-bit implementation. ===================================
+  async command void Capture.setEdge(bool up) { WRITE_BIT(TCCR3B, ICES3, up); }
+
+  //=== Timer 16-bit implementation. ===================================
+  async command void Timer.reset()    { TIFR3 = 1 << TOV3; }
+  async command void Capture.reset()  { TIFR3 = 1 << ICF3; }
+  async command void CompareA.reset() { TIFR3 = 1 << OCF3A; }
+  async command void CompareB.reset() { TIFR3 = 1 << OCF3B; }
+  async command void CompareC.reset() { TIFR3 = 1 << OCF3C; }
+
+  async command void Timer.start()    { SET_BIT(TIMSK3,TOIE3); }
+  async command void Capture.start()  { SET_BIT(TIMSK3,ICIE3); }
+  async command void CompareA.start() { SET_BIT(TIMSK3,OCIE3A); }
+  async command void CompareB.start() { SET_BIT(TIMSK3,OCIE3B); }
+  async command void CompareC.start() { SET_BIT(TIMSK3,OCIE3C); }
+
+  async command void Timer.stop()    { CLR_BIT(TIMSK3,TOIE3); }
+  async command void Capture.stop()  { CLR_BIT(TIMSK3,ICIE3); }
+  async command void CompareA.stop() { CLR_BIT(TIMSK3,OCIE3A); }
+  async command void CompareB.stop() { CLR_BIT(TIMSK3,OCIE3B); }
+  async command void CompareC.stop() { CLR_BIT(TIMSK3,OCIE3C); }
+
+  async command bool Timer.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.tov; 
+  }
+  async command bool Capture.test()  { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.icf; 
+  }
+  async command bool CompareA.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfa; 
+  }
+  async command bool CompareB.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfb; 
+  }
+  async command bool CompareC.test() { 
+    return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfc; 
+  }
+
+  async command bool Timer.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.toie;
+  }
+  async command bool Capture.isOn()  {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.icie;
+  }
+  async command bool CompareA.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociea;
+  }
+  async command bool CompareB.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ocieb;
+  }
+  async command bool CompareC.isOn() {
+    return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociec;
+  }
+
+  //=== Read the compare registers. =====================================
+  async command uint16_t CompareA.get() { return OCR3A; }
+  async command uint16_t CompareB.get() { return OCR3B; }
+  async command uint16_t CompareC.get() { return OCR3C; }
+
+  //=== Write the compare registers. ====================================
+  async command void CompareA.set(uint16_t t) { OCR3A = t; }
+  async command void CompareB.set(uint16_t t) { OCR3B = t; }
+  async command void CompareC.set(uint16_t t) { OCR3C = t; }
+
+  //=== Read the capture registers. =====================================
+  async command uint16_t Capture.get() { return ICR3; }
+
+  //=== Write the capture registers. ====================================
+  async command void Capture.set(uint16_t t)  { ICR3 = t; }
+
+  //=== Timer interrupts signals ========================================
+  default async event void CompareA.fired() { }
+  AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE3A) {
+    signal CompareA.fired();
+  }
+  default async event void CompareB.fired() { }
+  AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE3B) {
+    signal CompareB.fired();
+  }
+  default async event void CompareC.fired() { }
+  AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE3C) {
+    signal CompareC.fired();
+  }
+  default async event void Capture.captured(uint16_t time) { }
+  AVR_NONATOMIC_HANDLER(SIG_INPUT_CAPTURE3) {
+    signal Capture.captured(call Timer.get());
+  }
+  default async event void Timer.overflow() { }
+  AVR_NONATOMIC_HANDLER(SIG_OVERFLOW3) {
+    signal Timer.overflow();
+  }
+}
diff --git a/tos/chips/atm1281/timer/HplAtm128Timer1C.nc b/tos/chips/atm1281/timer/HplAtm128Timer1C.nc
new file mode 100644 (file)
index 0000000..a6472a2
--- /dev/null
@@ -0,0 +1,76 @@
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL interface to Atmega1281 timer 1.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay <dgay@intel-research.net>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+configuration HplAtm128Timer1C
+{
+  provides {
+    // 16-bit Timers
+    interface HplAtm128Timer<uint16_t>   as Timer;
+    interface HplAtm128TimerCtrl16       as TimerCtrl;
+    interface HplAtm128Capture<uint16_t> as Capture;
+    interface HplAtm128Compare<uint16_t> as Compare[uint8_t id];
+  }
+}
+implementation
+{
+  components HplAtm1281Timer1P;
+
+  Timer = HplAtm1281Timer1P;
+  TimerCtrl = HplAtm1281Timer1P;
+  Capture = HplAtm1281Timer1P;
+
+  Compare[0] = HplAtm1281Timer1P.CompareA; 
+  Compare[1] = HplAtm1281Timer1P.CompareB;
+  Compare[2] = HplAtm1281Timer1P.CompareC;
+}
diff --git a/tos/chips/atm1281/timer/HplAtm128Timer3C.nc b/tos/chips/atm1281/timer/HplAtm128Timer3C.nc
new file mode 100644 (file)
index 0000000..3f3fa2c
--- /dev/null
@@ -0,0 +1,76 @@
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL interface to Atmega1281 timer 3.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay <dgay@intel-research.net>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+configuration HplAtm128Timer3C
+{
+  provides {
+    // 16-bit Timers
+    interface HplAtm128Timer<uint16_t>   as Timer;
+    interface HplAtm128TimerCtrl16       as TimerCtrl;
+    interface HplAtm128Capture<uint16_t> as Capture;
+    interface HplAtm128Compare<uint16_t> as Compare[uint8_t id];
+  }
+}
+implementation
+{
+  components HplAtm1281Timer3P;
+
+  Timer = HplAtm1281Timer3P;
+  TimerCtrl = HplAtm1281Timer3P;
+  Capture = HplAtm1281Timer3P;
+
+  Compare[0] = HplAtm1281Timer3P.CompareA; 
+  Compare[1] = HplAtm1281Timer3P.CompareB;
+  Compare[2] = HplAtm1281Timer3P.CompareC;
+}
diff --git a/tos/chips/atm1281/timer/HplAtm128TimerAsync.nc b/tos/chips/atm1281/timer/HplAtm128TimerAsync.nc
new file mode 100644 (file)
index 0000000..ea4a9f7
--- /dev/null
@@ -0,0 +1,89 @@
+// $Id$
+/*
+ * Copyright (c) 2007 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL Interface to Atmega1281 8-bit asynchronous timer control registers
+ *
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+interface HplAtm128TimerAsync
+{
+  /**
+   * Read timer2 asynchronous status register (ASSR)
+   * @return Current value of ASSR
+   */
+  async command Atm128_ASSR_t getAssr();
+
+  /**
+   * Set timer2 asynchronous status register (ASSR)
+   * @param x New value for ASSR
+   */
+  async command void setAssr(Atm128_ASSR_t x);
+
+  /**
+   * Turn on timer 2 asynchronous mode
+   */
+  async command void setTimer2Asynchronous();
+
+  /**
+   * Check if control register TCCR2A is busy (should not be updated if true)
+   * @return TRUE if TCCR2A is busy, FALSE otherwise (can be updated)
+   */
+  async command int controlABusy();
+
+  /**
+   * Check if control register TCCR2B is busy (should not be updated if true)
+   * @return TRUE if TCCR2B is busy, FALSE otherwise (can be updated)
+   */
+  async command int controlBBusy();
+
+  /**
+   * Check if compare register OCR2A is busy (should not be updated if true)
+   * @return TRUE if OCR2A is busy, FALSE otherwise (can be updated)
+   */
+  async command int compareABusy();
+
+  /**
+   * Check if compare register OCR2B is busy (should not be updated if true)
+   * @return TRUE if OCR2B is busy, FALSE otherwise (can be updated)
+   */
+  async command int compareBBusy();
+
+  /**
+   * Check if current timer value (TCNT2) is busy (should not be updated if true)
+   * @return TRUE if TCNT2 is busy, FALSE otherwise (can be updated)
+   */
+  async command int countBusy();
+
+}
diff --git a/tos/chips/atm1281/timer/HplAtm128TimerCtrl16.nc b/tos/chips/atm1281/timer/HplAtm128TimerCtrl16.nc
new file mode 100644 (file)
index 0000000..39076ee
--- /dev/null
@@ -0,0 +1,74 @@
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL Interface to Atmega1281 16-bit timer control registers
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+interface HplAtm128TimerCtrl16
+{
+  /// Timer control register: Direct access
+  async command uint8_t getControlA();
+  async command uint8_t getControlB();
+  async command uint8_t getControlC();
+  async command void setControlA( uint8_t control );
+  async command void setControlB( uint8_t control );
+  async command void setControlC( uint8_t control );
+    
+  /// Interrupt mask register: Direct access
+  async command uint8_t getInterruptMask();
+  async command void setInterruptMask( uint8_t mask);
+
+  /// Interrupt flag register: Direct access
+  async command uint8_t getInterruptFlag();
+  async command void setInterruptFlag( uint8_t flags );
+}
+
diff --git a/tos/chips/atm1281/timer/HplAtm128TimerCtrl8.nc b/tos/chips/atm1281/timer/HplAtm128TimerCtrl8.nc
new file mode 100644 (file)
index 0000000..067417e
--- /dev/null
@@ -0,0 +1,71 @@
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.  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 CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS 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 CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
+ * DAMAGE. 
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL 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 NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY 
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL Interface to Atmega1281 8-bit timer control registers
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+interface HplAtm128TimerCtrl8
+{
+  /// Timer control register: Direct access
+  async command uint8_t getControlA();
+  async command uint8_t getControlB();
+  async command void setControlA( uint8_t control );
+  async command void setControlB( uint8_t control );
+
+  /// Interrupt mask register: Direct access
+  async command uint8_t getInterruptMask();
+  async command void setInterruptMask( uint8_t mask);
+
+  /// Interrupt flag register: Direct access
+  async command uint8_t getInterruptFlag();
+  async command void setInterruptFlag( uint8_t flags );
+}
diff --git a/tos/chips/rf230/ActiveMessageConfig.nc b/tos/chips/rf230/ActiveMessageConfig.nc
new file mode 100644 (file)
index 0000000..e47f0e8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface ActiveMessageConfig
+{
+       /**
+        * This command is called when the message first enters the radio stack
+        * via the Send.send command. This should clear the packet if the user
+        * forgot to do so (or return EINVAL to be strict).
+        */
+       command error_t checkPacket(message_t* msg);
+}
diff --git a/tos/chips/rf230/ActiveMessageLayerC.nc b/tos/chips/rf230/ActiveMessageLayerC.nc
new file mode 100644 (file)
index 0000000..f635a9c
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+module ActiveMessageLayerC
+{
+       provides
+       {
+               interface AMSend[am_id_t id];
+               interface Receive[am_id_t id];
+               interface Receive as Snoop[am_id_t id]; 
+       }
+       uses
+       {
+               interface Send as SubSend;
+               interface Receive as SubReceive;
+               interface AMPacket;
+               interface ActiveMessageConfig as Config;
+       }
+}
+
+implementation
+{
+/*----------------- Send -----------------*/
+
+       command error_t AMSend.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len)
+       {
+               error_t error;
+
+               error = call Config.checkPacket(msg);
+               if( error != SUCCESS )
+                       return error;
+
+               call AMPacket.setSource(msg, call AMPacket.address());
+               call AMPacket.setGroup(msg, call AMPacket.localGroup());
+               call AMPacket.setType(msg, id);
+               call AMPacket.setDestination(msg, addr);
+
+               return call SubSend.send(msg, len);
+       }
+
+       inline event void SubSend.sendDone(message_t* msg, error_t error)
+       {
+               signal AMSend.sendDone[call AMPacket.type(msg)](msg, error);
+       }
+
+       inline command error_t AMSend.cancel[am_id_t id](message_t* msg)
+       {
+               return call SubSend.cancel(msg);
+       }
+
+       default event void AMSend.sendDone[am_id_t id](message_t* msg, error_t error)
+       {
+       }
+
+       inline command uint8_t AMSend.maxPayloadLength[am_id_t id]()
+       {
+               return call SubSend.maxPayloadLength();
+       }
+
+       inline command void* AMSend.getPayload[am_id_t id](message_t* msg, uint8_t len)
+       {
+               return call SubSend.getPayload(msg, len);
+       }
+
+/*----------------- Receive -----------------*/
+
+       event message_t* SubReceive.receive(message_t* msg, void* payload, uint8_t len)
+       {
+               am_id_t type = call AMPacket.type(msg);
+
+               msg = call AMPacket.isForMe(msg) 
+                       ? signal Receive.receive[type](msg, payload, len)
+                       : signal Snoop.receive[type](msg, payload, len);
+
+               return msg;
+       }
+
+       default event message_t* Receive.receive[am_id_t id](message_t* msg, void* payload, uint8_t len)
+       {
+               return msg;
+       }
+
+       default event message_t* Snoop.receive[am_id_t id](message_t* msg, void* payload, uint8_t len)
+       {
+               return msg;
+       }
+}
diff --git a/tos/chips/rf230/CsmaConfig.nc b/tos/chips/rf230/CsmaConfig.nc
new file mode 100644 (file)
index 0000000..9d45376
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface CsmaConfig
+{
+       /**
+        * This command is called when the message is transmitted to
+        * check if it needs software clear channel assesment.
+        */
+       async command bool requiresSoftwareCCA(message_t* msg);
+}
diff --git a/tos/chips/rf230/CsmaLayerC.nc b/tos/chips/rf230/CsmaLayerC.nc
new file mode 100644 (file)
index 0000000..e0ddc26
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration CsmaLayerC
+{
+       provides
+       {
+               interface RadioSend;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioCCA as SubCCA;
+
+               interface CsmaConfig as Config;
+       }
+}
+
+implementation
+{
+       components CsmaLayerP;
+
+       RadioSend = CsmaLayerP;
+       SubSend = CsmaLayerP;
+       SubCCA = CsmaLayerP;
+       Config = CsmaLayerP;
+}
diff --git a/tos/chips/rf230/CsmaLayerP.nc b/tos/chips/rf230/CsmaLayerP.nc
new file mode 100644 (file)
index 0000000..5bd1aa4
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module CsmaLayerP
+{
+       provides
+       {
+               interface RadioSend;
+       }
+
+       uses
+       {
+               interface CsmaConfig as Config;
+
+               interface RadioSend as SubSend;
+               interface RadioCCA as SubCCA;
+       }
+}
+
+implementation
+{
+       tasklet_norace message_t *txMsg;
+
+       tasklet_norace uint8_t state;
+       enum
+       {
+               STATE_READY = 0,
+               STATE_CCA_WAIT = 1,
+               STATE_SEND = 2,
+       };
+
+       tasklet_async event void SubSend.ready()
+       {
+               if( state == STATE_READY )
+                       signal RadioSend.ready();
+       }
+
+       tasklet_async command error_t RadioSend.send(message_t* msg)
+       {
+               error_t error;
+
+               if( state == STATE_READY )
+               {
+                       if( call Config.requiresSoftwareCCA(msg) )
+                       {
+                               txMsg = msg;
+
+                               if( (error = call SubCCA.request()) == SUCCESS )
+                                       state = STATE_CCA_WAIT;
+                       }
+                       else if( (error = call SubSend.send(msg)) == SUCCESS )
+                               state = STATE_SEND;
+               }
+               else
+                       error = EBUSY;
+
+               return error;
+       }
+
+       tasklet_async event void SubCCA.done(error_t error)
+       {
+               ASSERT( state == STATE_CCA_WAIT );
+
+               if( error == SUCCESS && (error = call SubSend.send(txMsg)) == SUCCESS )
+                       state = STATE_SEND;
+               else
+               {
+                       state = STATE_READY;
+                       signal RadioSend.sendDone(EBUSY);
+               }
+       }
+
+       tasklet_async event void SubSend.sendDone(error_t error)
+       {
+               ASSERT( state == STATE_SEND );
+
+               state = STATE_READY;
+               signal RadioSend.sendDone(error);
+       }
+}
diff --git a/tos/chips/rf230/DefaultMac.h b/tos/chips/rf230/DefaultMac.h
new file mode 100644 (file)
index 0000000..3547bde
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __DEFAULTMAC_H__
+#define __DEFAULTMAC_H__
+
+#include <IEEE154Packet.h>
+
+typedef ieee154_header_t defaultmac_header_t;
+
+typedef nx_struct defaultmac_metadata_t
+{
+       nx_uint8_t flags;
+       nx_uint8_t lqi;
+       nx_uint16_t timestamp;
+} defaultmac_metadata_t;
+
+enum defaultmac_metadata_flags
+{
+       DEFAULTMAC_WAS_ACKED = 0x01,
+       DEFAULTMAC_SCHEDULED_TX = 0x02,
+};
+
+/* This is the default value of the TX_PWR field of the PHY_TX_PWR register. */
+#ifndef RF230_DEF_RFPOWER
+#define RF230_DEF_RFPOWER      0
+#endif
+
+/* This is the default value of the CHANNEL field of the PHY_CC_CCA register. */
+#ifndef RF230_DEF_CHANNEL
+#define RF230_DEF_CHANNEL      11
+#endif
+
+#endif//__DEFAULTMAC_H__
diff --git a/tos/chips/rf230/DefaultMacC.nc b/tos/chips/rf230/DefaultMacC.nc
new file mode 100644 (file)
index 0000000..3229618
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration DefaultMacC
+{
+       provides 
+       {
+               interface SplitControl;
+
+               interface AMSend[am_id_t id];
+               interface Receive[am_id_t id];
+               interface Receive as Snoop[am_id_t id];
+
+               interface Packet;
+               interface AMPacket;
+               interface PacketAcknowledgements;
+       }
+}
+
+implementation
+{
+       components DefaultMacP, IEEE154PacketC, RadioAlarmC;
+
+#ifdef RF230_DEBUG
+       components AssertC;
+#endif
+
+       DefaultMacP.IEEE154Packet -> IEEE154PacketC;
+       DefaultMacP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
+
+       components ActiveMessageLayerC;
+       components MessageBufferLayerC;
+       components UniqueLayerC;
+       components TrafficMonitorLayerC;
+       components RandomCollisionLayerC as CollisionAvoidanceLayerC;
+//     components SlottedCollisionLayerC as CollisionAvoidanceLayerC;
+       components SoftwareAckLayerC;
+       components new DummyLayerC() as CsmaLayerC;
+       components RF230LayerC;
+
+       SplitControl = MessageBufferLayerC;
+       AMSend = ActiveMessageLayerC;
+       Receive = ActiveMessageLayerC.Receive;
+       Snoop = ActiveMessageLayerC.Snoop;
+       Packet = DefaultMacP;
+       AMPacket = IEEE154PacketC;
+       PacketAcknowledgements = DefaultMacP;
+
+       ActiveMessageLayerC.Config -> DefaultMacP;
+       ActiveMessageLayerC.AMPacket -> IEEE154PacketC;
+       ActiveMessageLayerC.SubSend -> UniqueLayerC;
+       ActiveMessageLayerC.SubReceive -> MessageBufferLayerC;
+
+       UniqueLayerC.Config -> DefaultMacP;
+       UniqueLayerC.SubSend -> MessageBufferLayerC;
+
+       MessageBufferLayerC.Packet -> DefaultMacP;
+       MessageBufferLayerC.RadioSend -> TrafficMonitorLayerC;
+       MessageBufferLayerC.RadioReceive -> UniqueLayerC;
+       MessageBufferLayerC.RadioState -> TrafficMonitorLayerC;
+
+       UniqueLayerC.SubReceive -> TrafficMonitorLayerC;
+
+       TrafficMonitorLayerC.Config -> DefaultMacP;
+       TrafficMonitorLayerC.SubSend -> CollisionAvoidanceLayerC;
+       TrafficMonitorLayerC.SubReceive -> CollisionAvoidanceLayerC;
+       TrafficMonitorLayerC.SubState -> RF230LayerC;
+
+       CollisionAvoidanceLayerC.Config -> DefaultMacP;
+       CollisionAvoidanceLayerC.SubSend -> SoftwareAckLayerC;
+       CollisionAvoidanceLayerC.SubReceive -> SoftwareAckLayerC;
+
+       SoftwareAckLayerC.Config -> DefaultMacP;
+       SoftwareAckLayerC.SubSend -> CsmaLayerC;
+       SoftwareAckLayerC.SubReceive -> RF230LayerC;
+
+       CsmaLayerC.Config -> DefaultMacP;
+       CsmaLayerC.SubSend -> RF230LayerC;
+       CsmaLayerC.SubCCA -> RF230LayerC;
+
+       RF230LayerC.RF230Config -> DefaultMacP;
+}
diff --git a/tos/chips/rf230/DefaultMacP.nc b/tos/chips/rf230/DefaultMacP.nc
new file mode 100644 (file)
index 0000000..ba17f9b
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <DefaultMac.h>
+#include <HplRF230.h>
+#include <Tasklet.h>
+
+module DefaultMacP
+{
+       provides
+       {
+               interface RF230Config;
+               interface SoftwareAckConfig;
+               interface UniqueConfig;
+               interface CsmaConfig;
+               interface TrafficMonitorConfig;
+               interface RandomCollisionConfig;
+               interface SlottedCollisionConfig;
+               interface ActiveMessageConfig;
+               interface DummyConfig;
+
+               interface PacketAcknowledgements;
+               interface Packet;
+       }
+
+       uses
+       {
+               interface IEEE154Packet;
+               interface RadioAlarm;
+       }
+}
+
+implementation
+{
+/*----------------- Packet -----------------*/
+
+       command void Packet.clear(message_t* msg) 
+       {
+               call IEEE154Packet.createDataFrame(msg);
+
+#ifdef IEEE154_6LOWPAN
+               call IEEE154Packet.set6LowPan(msg, TINYOS_6LOWPAN_NETWORK_ID);
+#endif
+       }
+  
+       command uint8_t Packet.payloadLength(message_t* msg) 
+       {
+               return call IEEE154Packet.getLength(msg) - sizeof(ieee154_header_t) + 1 - sizeof(ieee154_footer_t);
+       }
+  
+       command void Packet.setPayloadLength(message_t* msg, uint8_t len) 
+       {
+               call IEEE154Packet.setLength(msg, len + sizeof(ieee154_header_t) - 1 + sizeof(ieee154_footer_t));
+       }
+  
+       command uint8_t Packet.maxPayloadLength()
+       {
+               return TOSH_DATA_LENGTH;
+       }
+  
+       command void* Packet.getPayload(message_t* msg, uint8_t len)
+       {
+               if( len > TOSH_DATA_LENGTH )
+                       return NULL;
+
+               return msg->data;
+       }
+
+       command error_t ActiveMessageConfig.checkPacket(message_t* msg)
+       {
+               // the user forgot to call clear, we should return EINVAL
+               if( ! call IEEE154Packet.isDataFrame(msg) )
+                       call Packet.clear(msg);
+
+               return SUCCESS;
+       }
+
+/*----------------- RF230Config -----------------*/
+
+       async command uint8_t RF230Config.getLength(message_t* msg)
+       {
+               return call IEEE154Packet.getLength(msg);
+       }
+
+       async command void RF230Config.setLength(message_t* msg, uint8_t len)
+       {
+               call IEEE154Packet.setLength(msg, len);
+       }
+
+       async command uint8_t* RF230Config.getPayload(message_t* msg)
+       {
+               return ((uint8_t*)(call IEEE154Packet.getHeader(msg))) + 1;
+       }
+
+       inline defaultmac_metadata_t* getMeta(message_t* msg)
+       {
+               return (defaultmac_metadata_t*)(msg->metadata);
+       }
+
+       async command void RF230Config.setTimestamp(message_t* msg, uint16_t time)
+       {
+               getMeta(msg)->timestamp = time;
+       }
+
+       async command void RF230Config.setLinkQuality(message_t* msg, uint8_t lqi)
+       {
+               getMeta(msg)->lqi = lqi;
+       }
+
+       async command uint8_t RF230Config.getHeaderLength()
+       {
+               // we need the fcf, dsn, destpan and dest
+               return 7;
+       }
+
+       async command uint8_t RF230Config.getMaxLength()
+       {
+               // note, that the ieee154_footer_t is not stored, but we should include it here
+               return sizeof(defaultmac_header_t) - 1 + TOSH_DATA_LENGTH + sizeof(ieee154_footer_t);
+       }
+
+       async command uint8_t RF230Config.getTransmitPower(message_t* msg)
+       {
+               return RF230_DEF_RFPOWER;
+       }
+
+       async command uint8_t RF230Config.getDefaultChannel()
+       {
+               return RF230_DEF_CHANNEL;
+       }
+
+       async command bool RF230Config.requiresRssiCca(message_t* msg)
+       {
+               return call IEEE154Packet.isDataFrame(msg);
+       }
+
+/*----------------- SoftwareAckConfig -----------------*/
+
+       async command bool SoftwareAckConfig.requiresAckWait(message_t* msg)
+       {
+               return call IEEE154Packet.requiresAckWait(msg);
+       }
+
+       async command bool SoftwareAckConfig.isAckPacket(message_t* msg)
+       {
+               return call IEEE154Packet.isAckFrame(msg);
+       }
+
+       async command bool SoftwareAckConfig.verifyAckPacket(message_t* data, message_t* ack)
+       {
+               return call IEEE154Packet.verifyAckReply(data, ack);
+       }
+
+       async command bool SoftwareAckConfig.requiresAckReply(message_t* msg)
+       {
+               return call IEEE154Packet.requiresAckReply(msg);
+       }
+
+       async command void SoftwareAckConfig.createAckPacket(message_t* data, message_t* ack)
+       {
+               call IEEE154Packet.createAckReply(data, ack);
+       }
+
+       async command void SoftwareAckConfig.setAckReceived(message_t* msg, bool acked)
+       {
+               if( acked )
+                       getMeta(msg)->flags |= DEFAULTMAC_WAS_ACKED;
+               else
+                       getMeta(msg)->flags &= ~DEFAULTMAC_WAS_ACKED;
+       }
+
+       async command uint16_t SoftwareAckConfig.getAckTimeout()
+       {
+               return (uint16_t)(800 * RF230_ALARM_MICROSEC);
+       }
+
+       tasklet_async command void SoftwareAckConfig.reportChannelError()
+       {
+               signal TrafficMonitorConfig.channelError();
+       }
+
+/*----------------- PacketAcknowledgements -----------------*/
+
+       async command error_t PacketAcknowledgements.requestAck(message_t* msg)
+       {
+               call IEEE154Packet.setAckRequired(msg, TRUE);
+
+               return SUCCESS;
+       }
+
+       async command error_t PacketAcknowledgements.noAck(message_t* msg)
+       {
+               call IEEE154Packet.setAckRequired(msg, FALSE);
+
+               return SUCCESS;
+       }
+
+       async command bool PacketAcknowledgements.wasAcked(message_t* msg)
+       {
+               return getMeta(msg)->flags & DEFAULTMAC_WAS_ACKED;
+       }
+
+/*----------------- UniqueConfig -----------------*/
+
+       async command uint8_t UniqueConfig.getSequenceNumber(message_t* msg)
+       {
+               return call IEEE154Packet.getDSN(msg);
+       }
+
+       async command void UniqueConfig.setSequenceNumber(message_t* msg, uint8_t dsn)
+       {
+               call IEEE154Packet.setDSN(msg, dsn);
+       }
+
+       async command am_addr_t UniqueConfig.getSender(message_t* msg)
+       {
+               return call IEEE154Packet.getSrcAddr(msg);
+       }
+
+       tasklet_async command void UniqueConfig.reportChannelError()
+       {
+               signal TrafficMonitorConfig.channelError();
+       }
+
+/*----------------- CsmaConfig -----------------*/
+
+       async command bool CsmaConfig.requiresSoftwareCCA(message_t* msg)
+       {
+               return call IEEE154Packet.isDataFrame(msg);
+       }
+
+/*----------------- TrafficMonitorConfig -----------------*/
+
+       enum
+       {
+               TRAFFIC_UPDATE_PERIOD = 100,    // in milliseconds
+               TRAFFIC_MAX_BYTES = (uint16_t)(TRAFFIC_UPDATE_PERIOD * 1000.0 / 32),    // 3125
+       };
+
+       async command uint16_t TrafficMonitorConfig.getUpdatePeriod()
+       {
+               return TRAFFIC_UPDATE_PERIOD;
+       }
+
+       async command uint16_t TrafficMonitorConfig.getChannelTime(message_t* msg)
+       {
+               /* We count in bytes, one byte is 32 microsecond. We are conservative here.
+                *
+                * pure airtime: preable (4 bytes), SFD (1 byte), length (1 byte), payload + CRC (len bytes)
+                * frame separation: 5-10 bytes
+                * ack required: 8-16 byte separation, 11 bytes airtime, 5-10 bytes separation
+                */
+
+               uint8_t len = call IEEE154Packet.getLength(msg);
+               return call IEEE154Packet.getAckRequired(msg) ? len + 6 + 16 + 11 + 10 : len + 6 + 10;
+       }
+
+       async command am_addr_t TrafficMonitorConfig.getSender(message_t* msg)
+       {
+               return call IEEE154Packet.getSrcAddr(msg);
+       }
+
+       tasklet_async command void TrafficMonitorConfig.timerTick()
+       {
+               signal SlottedCollisionConfig.timerTick();
+       }
+
+/*----------------- RandomCollisionConfig -----------------*/
+
+       /*
+        * We try to use the same values as in CC2420
+        *
+        * CC2420_MIN_BACKOFF = 10 jiffies = 320 microsec
+        * CC2420_BACKOFF_PERIOD = 10 jiffies
+        * initial backoff = 0x1F * CC2420_BACKOFF_PERIOD = 310 jiffies = 9920 microsec
+        * congestion backoff = 0x7 * CC2420_BACKOFF_PERIOD = 70 jiffies = 2240 microsec
+        */
+
+       async command uint16_t RandomCollisionConfig.getMinimumBackoff()
+       {
+               return (uint16_t)(320 * RF230_ALARM_MICROSEC);
+       }
+
+       async command uint16_t RandomCollisionConfig.getInitialBackoff(message_t* msg)
+       {
+               return (uint16_t)(9920 * RF230_ALARM_MICROSEC);
+       }
+
+       async command uint16_t RandomCollisionConfig.getCongestionBackoff(message_t* msg)
+       {
+               return (uint16_t)(2240 * RF230_ALARM_MICROSEC);
+       }
+
+       async command uint16_t RandomCollisionConfig.getTransmitBarrier(message_t* msg)
+       {
+               uint16_t time;
+
+               // TODO: maybe we should use the embedded timestamp of the message
+               time = call RadioAlarm.getNow();
+
+               // estimated response time (download the message, etc) is 5-8 bytes
+               if( call IEEE154Packet.requiresAckReply(msg) )
+                       time += (uint16_t)(32 * (-5 + 16 + 11 + 5) * RF230_ALARM_MICROSEC);
+               else
+                       time += (uint16_t)(32 * (-5 + 5) * RF230_ALARM_MICROSEC);
+
+               return time;
+       }
+
+       tasklet_async event void RadioAlarm.fired()     { }
+
+/*----------------- SlottedCollisionConfig -----------------*/
+
+       async command uint16_t SlottedCollisionConfig.getInitialDelay()
+       {
+               return 300;
+       }
+
+       async command uint8_t SlottedCollisionConfig.getScheduleExponent()
+       {
+               return 11;
+       }
+
+       async command uint16_t SlottedCollisionConfig.getTransmitTime(message_t* msg)
+       {
+               // TODO: check if the timestamp is correct
+               return getMeta(msg)->timestamp;
+       }
+
+       async command uint16_t SlottedCollisionConfig.getCollisionWindowStart(message_t* msg)
+       {
+               // the preamble (4 bytes), SFD (1 byte), plus two extra for safety
+               return getMeta(msg)->timestamp - (uint16_t)(7 * 32 * RF230_ALARM_MICROSEC);
+       }
+
+       async command uint16_t SlottedCollisionConfig.getCollisionWindowLength(message_t* msg)
+       {
+               return (uint16_t)(2 * 7 * 32 * RF230_ALARM_MICROSEC);
+       }
+
+       default tasklet_async event void SlottedCollisionConfig.timerTick() { }
+
+/*----------------- Dummy -----------------*/
+
+       async command void DummyConfig.nothing()
+       {
+       }
+
+}
diff --git a/tos/chips/rf230/DummyConfig.nc b/tos/chips/rf230/DummyConfig.nc
new file mode 100644 (file)
index 0000000..c76631e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface DummyConfig
+{
+       /**
+        * We need to put something here, but this is not going to get called
+        */
+       async command void nothing();
+}
diff --git a/tos/chips/rf230/DummyLayerC.nc b/tos/chips/rf230/DummyLayerC.nc
new file mode 100644 (file)
index 0000000..5aebc90
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+generic configuration DummyLayerC()
+{
+       provides
+       {
+               interface RadioState;
+               interface RadioSend;
+               interface RadioReceive;
+               interface RadioCCA;
+
+               interface DummyConfig as UnconnectedConfig;
+       }
+
+       uses 
+       {
+               interface RadioState as SubState;
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RadioCCA as SubCCA;
+
+               interface DummyConfig as Config;
+       }
+}
+
+implementation
+{
+       RadioState = SubState;
+       RadioSend = SubSend;
+       RadioReceive = SubReceive;
+       RadioCCA = SubCCA;
+       Config = UnconnectedConfig;
+}
diff --git a/tos/chips/rf230/IEEE154Packet.h b/tos/chips/rf230/IEEE154Packet.h
new file mode 100644 (file)
index 0000000..796a4fa
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __IEEE154PACKET_H__
+#define __IEEE154PACKET_H__
+
+typedef nx_struct ieee154_header_t
+{
+       nxle_uint8_t length;
+       nxle_uint16_t fcf;
+       nxle_uint8_t dsn;
+       nxle_uint16_t destpan;
+       nxle_uint16_t dest;
+       nxle_uint16_t src;
+
+// I-Frame 6LowPAN interoperability byte
+#ifdef IEEE154_6LOWPAN 
+       nxle_uint8_t network;
+#endif
+
+       nxle_uint8_t type;
+} ieee154_header_t;
+
+// the actual radio driver might not use this
+typedef nx_struct ieee154_footer_t
+{ 
+       nxle_uint16_t crc;
+} ieee154_footer_t;
+
+enum ieee154_fcf_enums {
+       IEEE154_FCF_FRAME_TYPE = 0,
+       IEEE154_FCF_SECURITY_ENABLED = 3,
+       IEEE154_FCF_FRAME_PENDING = 4,
+       IEEE154_FCF_ACK_REQ = 5,
+       IEEE154_FCF_INTRAPAN = 6,
+       IEEE154_FCF_DEST_ADDR_MODE = 10,
+       IEEE154_FCF_SRC_ADDR_MODE = 14,
+};
+
+enum ieee154_fcf_type_enums {
+       IEEE154_TYPE_BEACON = 0,
+       IEEE154_TYPE_DATA = 1,
+       IEEE154_TYPE_ACK = 2,
+       IEEE154_TYPE_MAC_CMD = 3,
+       IEEE154_TYPE_MASK = 7,
+};
+
+enum iee154_fcf_addr_mode_enums {
+       IEEE154_ADDR_NONE = 0,
+       IEEE154_ADDR_SHORT = 2,
+       IEEE154_ADDR_EXT = 3,
+       IEEE154_ADDR_MASK = 3,
+};
+
+#endif//__IEEE154PACKET_H__
diff --git a/tos/chips/rf230/IEEE154Packet.nc b/tos/chips/rf230/IEEE154Packet.nc
new file mode 100644 (file)
index 0000000..2c5664c
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <IEEE154Packet.h>
+#include <message.h>
+
+/**
+ * This interface encapsulates IEEE 802.15.4 intrapan data frames with 
+ * 16-bit destination pan, source and destination addresses. It also 
+ * supports 6LowPan interoperability mode, and acknowledgement frames.
+ * Note, that this interface does not support the CRC-16 value, which
+ * should be verified before the data can be trusted.
+ */
+interface IEEE154Packet
+{
+       /**
+        * Returns the IEEE 802.15.4 header including the length field.
+        */
+       async command ieee154_header_t* getHeader(message_t* msg);
+
+       /**
+        * Returns the raw value (unadjusted) of the length field
+        */
+       async command uint8_t getLength(message_t* msg);
+
+       /**
+        * Sets the length field
+        */
+       async command void setLength(message_t* msg, uint8_t length);
+
+       /**
+        * Returns the frame control field. This method should not be used, 
+        * isDataFrame and isAckFrame should be used instead.
+        */
+       async command uint16_t getFCF(message_t* msg);
+
+       /**
+        * Sets the frame control field. This method should not be used, 
+        * createDataFrame and createAckFrame should be used instead.
+        */
+       async command void setFCF(message_t* msg, uint16_t fcf);
+
+       /**
+        * Returns TRUE if the message is a data frame supported by 
+        * this interface (based on the value of the FCF).
+        */
+       async command bool isDataFrame(message_t* msg);
+
+       /**
+        * Sets the FCF to create a data frame supported by this interface.
+        * You may call setAckRequired and setFramePending commands after this.
+        */
+       async command void createDataFrame(message_t* msg);
+
+       /**
+        * Returns TRUE if the message is an acknowledgement frame supported
+        * by this interface (based on the value of the FCF).
+        */
+       async command bool isAckFrame(message_t* msg);
+
+       /**
+        * Sets the FCF to create an acknowledgement frame supported by
+        * this interface. You may call setFramePending after this.
+        */
+       async command void createAckFrame(message_t* msg);
+
+       /**
+        * Creates an acknowledgement packet for the given data packet.
+        * This also sets the DSN value. The data message must be a 
+        * data frame, the ack message will be overwritten.
+        */
+       async command void createAckReply(message_t* data, message_t* ack);
+
+       /**
+        * Returns TRUE if the acknowledgement packet corresponds to the
+        * data packet. The data message must be a data packet.
+        */
+       async command bool verifyAckReply(message_t* data, message_t* ack);
+
+       /**
+        * Returns TRUE if the ACK required field is set in the FCF.
+        */
+       async command bool getAckRequired(message_t* msg);
+
+       /**
+        * Sets the ACK required field in the FCF, should never be set
+        * for acknowledgement frames.
+        */
+       async command void setAckRequired(message_t* msg, bool ack);
+
+       /**
+        * Returns TRUE if the frame pending field is set in the FCF.
+        */
+       async command bool getFramePending(message_t* msg);
+
+       /**
+        * Sets the frame pending field in the FCF.
+        */
+       async command void setFramePending(message_t* msg, bool pending);
+
+       /**
+        * Returns the data sequence number
+        */
+       async command uint8_t getDSN(message_t* msg);
+
+       /**
+        * Sets the data sequence number
+        */
+       async command void setDSN(message_t* msg, uint8_t dsn);
+
+       /**
+        * returns the destination PAN id, values <= 255 are tinyos groups,
+        * valid only for data frames
+        */
+       async command uint16_t getDestPan(message_t* msg);
+
+       /**
+        * Sets the destination PAN id, valid only for data frames
+        */
+       async command void setDestPan(message_t* msg, uint16_t pan);
+
+       /**
+        * Returns the destination address, valid only for data frames
+        */
+       async command uint16_t getDestAddr(message_t* msg);
+
+       /**
+        * Sets the destination address, valid only for data frames
+        */
+       async command void setDestAddr(message_t* msg, uint16_t addr);
+
+       /**
+        * Returns the source address, valid only for data frames
+        */
+       async command uint16_t getSrcAddr(message_t* msg);
+
+       /**
+        * Sets the source address, valid only for data frames
+        */
+       async command void setSrcAddr(message_t* msg, uint16_t addr);
+
+#ifdef IEEE154_6LOWPAN
+
+       /**
+        * Returns the value of the 6LowPan network field.
+        */
+       async command uint8_t get6LowPan(message_t* msg);
+
+       /**
+        * Sets the value of the 6LowPan network field.
+        */
+       async command void set6LowPan(message_t* msg, uint8_t network);
+
+#endif
+
+       /**
+        * Returns the active message type of the message
+        */
+       async command am_id_t getType(message_t* msg);
+
+       /**
+        * Sets the active message type
+        */
+       async command void setType(message_t* msg, am_id_t type);
+
+       /**
+        * Returns TRUE if the packet is a data packet, the ACK_REQ field
+        * is set and the destination address is not the broadcast address.
+        */
+       async command bool requiresAckWait(message_t* msg);
+
+       /**
+        * Returns TRUE if the packet is a data packet, the ACK_REQ field
+        * is set and the destionation address is this node.
+        */
+       async command bool requiresAckReply(message_t* msg);
+}
diff --git a/tos/chips/rf230/IEEE154PacketC.nc b/tos/chips/rf230/IEEE154PacketC.nc
new file mode 100644 (file)
index 0000000..2ea8ffe
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration IEEE154PacketC
+{
+       provides
+       {
+               interface IEEE154Packet;
+               interface AMPacket;
+       }
+}
+
+implementation
+{
+       components IEEE154PacketP, ActiveMessageAddressC;
+       IEEE154PacketP.ActiveMessageAddress -> ActiveMessageAddressC;
+
+       IEEE154Packet = IEEE154PacketP;
+       AMPacket = IEEE154PacketP;
+}
diff --git a/tos/chips/rf230/IEEE154PacketP.nc b/tos/chips/rf230/IEEE154PacketP.nc
new file mode 100644 (file)
index 0000000..73395da
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <IEEE154Packet.h>
+
+module IEEE154PacketP
+{
+       provides 
+       {
+               interface IEEE154Packet;
+               interface AMPacket;
+       }
+
+       uses interface ActiveMessageAddress;
+}
+
+implementation
+{
+/*----------------- IEEE154Packet -----------------*/
+
+       enum
+       {
+               IEEE154_DATA_FRAME_MASK = (IEEE154_TYPE_MASK << IEEE154_FCF_FRAME_TYPE) 
+                       | (1 << IEEE154_FCF_INTRAPAN) 
+                       | (IEEE154_ADDR_MASK << IEEE154_FCF_DEST_ADDR_MODE) 
+                       | (IEEE154_ADDR_MASK << IEEE154_FCF_SRC_ADDR_MODE),
+
+               IEEE154_DATA_FRAME_VALUE = (IEEE154_TYPE_DATA << IEEE154_FCF_FRAME_TYPE) 
+                       | (1 << IEEE154_FCF_INTRAPAN) 
+                       | (IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE) 
+                       | (IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE),
+
+               IEEE154_ACK_FRAME_LENGTH = 5,   // includes the FCF, DSN and FCS
+               IEEE154_ACK_FRAME_MASK = (IEEE154_TYPE_MASK << IEEE154_FCF_FRAME_TYPE), 
+               IEEE154_ACK_FRAME_VALUE = (IEEE154_TYPE_ACK << IEEE154_FCF_FRAME_TYPE),
+       };
+
+       inline ieee154_header_t* getHeader(message_t* msg)
+       {
+               return (ieee154_header_t*)(msg->data - sizeof(ieee154_header_t));
+       }
+
+       inline async command ieee154_header_t* IEEE154Packet.getHeader(message_t* msg)
+       {
+               return getHeader(msg);
+       }
+
+       inline async command uint8_t IEEE154Packet.getLength(message_t* msg)
+       {
+               return getHeader(msg)->length;
+       }
+
+       inline async command void IEEE154Packet.setLength(message_t* msg, uint8_t length)
+       {
+               getHeader(msg)->length = length;
+       }
+
+       inline async command uint16_t IEEE154Packet.getFCF(message_t* msg)
+       {
+               return getHeader(msg)->fcf;
+       }
+
+       inline async command void IEEE154Packet.setFCF(message_t* msg, uint16_t fcf)
+       {
+               getHeader(msg)->fcf = fcf;
+       }
+
+       inline async command bool IEEE154Packet.isDataFrame(message_t* msg)
+       {
+               return (getHeader(msg)->fcf & IEEE154_DATA_FRAME_MASK) == IEEE154_DATA_FRAME_VALUE;
+       }
+
+       inline async command void IEEE154Packet.createDataFrame(message_t* msg)
+       {
+               getHeader(msg)->fcf = IEEE154_DATA_FRAME_VALUE;
+       }
+
+       inline async command bool IEEE154Packet.isAckFrame(message_t* msg)
+       {
+               return (getHeader(msg)->fcf & IEEE154_ACK_FRAME_MASK) == IEEE154_ACK_FRAME_VALUE;
+       }
+
+       inline async command void IEEE154Packet.createAckFrame(message_t* msg)
+       {
+               ieee154_header_t* header = getHeader(msg);
+
+               header->length = IEEE154_ACK_FRAME_LENGTH;
+               header->fcf = IEEE154_ACK_FRAME_VALUE;
+       }
+
+       inline async command void IEEE154Packet.createAckReply(message_t* data, message_t* ack)
+       {
+               ieee154_header_t* header = getHeader(ack);
+
+               header->length = IEEE154_ACK_FRAME_LENGTH;
+               header->fcf = IEEE154_ACK_FRAME_VALUE;
+               header->dsn = getHeader(data)->dsn;
+       }
+
+       inline async command bool IEEE154Packet.verifyAckReply(message_t* data, message_t* ack)
+       {
+               ieee154_header_t* header = getHeader(ack);
+
+               return header->dsn == getHeader(data)->dsn
+                       && (header->fcf & IEEE154_ACK_FRAME_MASK) == IEEE154_ACK_FRAME_VALUE;
+       }
+
+       inline async command bool IEEE154Packet.getAckRequired(message_t* msg)
+       {
+               return getHeader(msg)->fcf & (1 << IEEE154_FCF_ACK_REQ);
+       }
+
+       inline async command void IEEE154Packet.setAckRequired(message_t* msg, bool ack)
+       {
+               if( ack )
+                       getHeader(msg)->fcf |= (1 << IEEE154_FCF_ACK_REQ);
+               else
+                       getHeader(msg)->fcf &= ~(uint16_t)(1 << IEEE154_FCF_ACK_REQ);
+       }
+
+       inline async command bool IEEE154Packet.getFramePending(message_t* msg)
+       {
+               return getHeader(msg)->fcf & (1 << IEEE154_FCF_FRAME_PENDING);
+       }
+
+       inline async command void IEEE154Packet.setFramePending(message_t* msg, bool pending)
+       {
+               if( pending )
+                       getHeader(msg)->fcf |= (1 << IEEE154_FCF_FRAME_PENDING);
+               else
+                       getHeader(msg)->fcf &= ~(uint16_t)(1 << IEEE154_FCF_FRAME_PENDING);
+       }
+
+       inline async command uint8_t IEEE154Packet.getDSN(message_t* msg)
+       {
+               return getHeader(msg)->dsn;
+       }
+
+       inline async command void IEEE154Packet.setDSN(message_t* msg, uint8_t dsn)
+       {
+               getHeader(msg)->dsn = dsn;
+       }
+
+       inline async command uint16_t IEEE154Packet.getDestPan(message_t* msg)
+       {
+               return getHeader(msg)->destpan;
+       }
+
+       inline async command void IEEE154Packet.setDestPan(message_t* msg, uint16_t pan)
+       {
+               getHeader(msg)->destpan = pan;
+       }
+
+       inline async command uint16_t IEEE154Packet.getDestAddr(message_t* msg)
+       {
+               return getHeader(msg)->dest;
+       }
+
+       inline async command void IEEE154Packet.setDestAddr(message_t* msg, uint16_t addr)
+       {
+               getHeader(msg)->dest = addr;
+       }
+
+       inline async command uint16_t IEEE154Packet.getSrcAddr(message_t* msg)
+       {
+               return getHeader(msg)->src;
+       }
+
+       inline async command void IEEE154Packet.setSrcAddr(message_t* msg, uint16_t addr)
+       {
+               getHeader(msg)->src = addr;
+       }
+
+#ifdef IEEE154_6LOWPAN
+
+       inline async command uint8_t IEEE154Packet.get6LowPan(message_t* msg)
+       {
+               return getHeader(msg)->network;
+       }
+
+       inline async command void IEEE154Packet.set6LowPan(message_t* msg, uint8_t network)
+       {
+               getHeader(msg)->network = network;
+       }
+
+#endif
+
+       inline async command am_id_t IEEE154Packet.getType(message_t* msg)
+       {
+               return getHeader(msg)->type;
+       }
+
+       inline async command void IEEE154Packet.setType(message_t* msg, am_id_t type)
+       {
+               getHeader(msg)->type = type;
+       }
+
+       async command bool IEEE154Packet.requiresAckWait(message_t* msg)
+       {
+               return call IEEE154Packet.getAckRequired(msg)
+                       && call IEEE154Packet.isDataFrame(msg)
+                       && call IEEE154Packet.getDestAddr(msg) != 0xFFFF;
+       }
+
+       async command bool IEEE154Packet.requiresAckReply(message_t* msg)
+       {
+               return call IEEE154Packet.getAckRequired(msg)
+                       && call IEEE154Packet.isDataFrame(msg)
+                       && call IEEE154Packet.getDestAddr(msg) == call ActiveMessageAddress.amAddress();
+       }
+
+       inline async event void ActiveMessageAddress.changed()
+       {
+       }
+
+/*----------------- AMPacket -----------------*/
+
+       inline command am_addr_t AMPacket.address()
+       {
+               return call ActiveMessageAddress.amAddress();
+       }
+       inline command am_group_t AMPacket.localGroup()
+       {
+               // TODO: check if this is correct
+               return call ActiveMessageAddress.amGroup();
+       }
+
+       inline command am_addr_t AMPacket.destination(message_t* msg)
+       {
+               return call IEEE154Packet.getDestAddr(msg);
+       }
+       inline command am_addr_t AMPacket.source(message_t* msg)
+       {
+               return call IEEE154Packet.getSrcAddr(msg);
+       }
+
+       inline command void AMPacket.setDestination(message_t* msg, am_addr_t addr)
+       {
+               call IEEE154Packet.setDestAddr(msg, addr);
+       }
+
+       inline command void AMPacket.setSource(message_t* msg, am_addr_t addr)
+       {
+               call IEEE154Packet.setSrcAddr(msg, addr);
+       }
+
+       inline command bool AMPacket.isForMe(message_t* msg)
+       {
+               am_addr_t addr = call AMPacket.destination(msg);
+               return addr == call AMPacket.address() || addr == AM_BROADCAST_ADDR;
+       }
+
+       inline command am_id_t AMPacket.type(message_t* msg)
+       {
+               return call IEEE154Packet.getType(msg);
+       }
+
+       inline command void AMPacket.setType(message_t* msg, am_id_t type)
+       {
+               call IEEE154Packet.setType(msg, type);
+       }
+  
+       inline command am_group_t AMPacket.group(message_t* msg) 
+       {
+               return call IEEE154Packet.getDestPan(msg);
+       }
+
+       inline command void AMPacket.setGroup(message_t* msg, am_group_t grp)
+       {
+               call IEEE154Packet.setDestPan(msg, grp);
+       }
+}
diff --git a/tos/chips/rf230/MessageBufferLayerC.nc b/tos/chips/rf230/MessageBufferLayerC.nc
new file mode 100644 (file)
index 0000000..89f0059
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration MessageBufferLayerC
+{
+       provides
+       {
+               interface SplitControl;
+               interface Send;
+               interface Receive;
+       }
+       uses
+       {
+               interface RadioState;
+               interface RadioSend;
+               interface RadioReceive;
+
+               interface Packet;
+       }
+}
+
+implementation
+{
+       components MessageBufferLayerP, MainC, TaskletC;
+
+       MainC.SoftwareInit -> MessageBufferLayerP;
+
+       SplitControl = MessageBufferLayerP;
+       Send = MessageBufferLayerP;
+       Receive = MessageBufferLayerP.Receive;
+
+       RadioState = MessageBufferLayerP;
+       MessageBufferLayerP.Tasklet -> TaskletC;
+       RadioSend = MessageBufferLayerP;
+       RadioReceive = MessageBufferLayerP;
+
+       Packet = MessageBufferLayerP;
+}
diff --git a/tos/chips/rf230/MessageBufferLayerP.nc b/tos/chips/rf230/MessageBufferLayerP.nc
new file mode 100644 (file)
index 0000000..76ef080
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module MessageBufferLayerP
+{
+       provides
+       {
+               interface SplitControl;
+               interface Init as SoftwareInit;
+
+               interface Send;
+               interface Receive;
+       }
+       uses
+       {
+               interface RadioState;
+               interface Tasklet;
+               interface RadioSend;
+               interface RadioReceive;
+
+               interface Packet;
+       }
+}
+
+implementation
+{
+/*----------------- State -----------------*/
+
+       norace uint8_t state;   // written only from tasks
+       enum
+       {
+               STATE_READY = 0,
+               STATE_TX_PENDING = 1,
+               STATE_TX_SEND = 2,
+               STATE_TX_DONE = 3,
+               STATE_TURN_ON = 4,
+               STATE_TURN_OFF = 5,
+       };
+
+       command error_t SplitControl.start()
+       {
+               error_t error;
+
+               call Tasklet.suspend();
+
+               if( state != STATE_READY )
+                       error = EBUSY;
+               else
+                       error = call RadioState.turnOn();
+
+               if( error == SUCCESS )
+                       state = STATE_TURN_ON;
+
+               call Tasklet.resume();
+
+               return error;
+       }
+
+       command error_t SplitControl.stop()
+       {
+               error_t error;
+
+               call Tasklet.suspend();
+
+               if( state != STATE_READY )
+                       error = EBUSY;
+               else
+                       error = call RadioState.turnOff();
+
+               if( error == SUCCESS )
+                       state = STATE_TURN_OFF;
+
+               call Tasklet.resume();
+
+               return error;
+       }
+
+       task void stateDoneTask()
+       {
+               uint8_t s;
+               
+               s = state;
+
+               if( s == STATE_TURN_ON || s == STATE_TURN_OFF )
+                       state = STATE_READY;
+
+               if( s == STATE_TURN_ON )
+                       signal SplitControl.startDone(SUCCESS);
+               else
+                       signal SplitControl.stopDone(SUCCESS);
+       }
+
+       tasklet_async event void RadioState.done()
+       {
+               post stateDoneTask();
+       }
+
+       default event void SplitControl.startDone(error_t error)
+       {
+       }
+
+       default event void SplitControl.stopDone(error_t error)
+       {
+       }
+
+/*----------------- Send -----------------*/
+
+       message_t* txMsg;
+       error_t txError;
+       uint8_t retries;
+
+       // Many EBUSY replies from RadioSend are normal if the channel is cognested
+       enum { MAX_RETRIES = 5 };
+
+       task void sendTask()
+       {
+               error_t error;
+
+               ASSERT( state == STATE_TX_PENDING || state == STATE_TX_SEND );
+
+               atomic error = txError;
+               if( (state == STATE_TX_SEND && error == SUCCESS) || ++retries > MAX_RETRIES )
+                       state = STATE_TX_DONE;
+               else
+               {
+                       call Tasklet.suspend();
+
+                       error = call RadioSend.send(txMsg);
+                       if( error == SUCCESS )
+                               state = STATE_TX_SEND;
+                       else if( retries == MAX_RETRIES )
+                               state = STATE_TX_DONE;
+                       else
+                               state = STATE_TX_PENDING;
+
+                       call Tasklet.resume();
+               }
+
+               if( state == STATE_TX_DONE )
+               {
+                       state = STATE_READY;
+                       signal Send.sendDone(txMsg, error);
+               }
+       }
+
+       tasklet_async event void RadioSend.sendDone(error_t error)
+       {
+               ASSERT( state == STATE_TX_SEND );
+
+               atomic txError = error;
+               post sendTask();
+       }
+
+       command error_t Send.send(message_t* msg, uint8_t len)
+       {
+               if( len > call Packet.maxPayloadLength() )
+                       return EINVAL;
+               else if( state != STATE_READY )
+                       return EBUSY;
+
+               call Packet.setPayloadLength(msg, len);
+
+               txMsg = msg;
+               state = STATE_TX_PENDING;
+               retries = 0;
+               post sendTask();
+
+               return SUCCESS;
+       }
+
+       tasklet_async event void RadioSend.ready()
+       {
+               if( state == STATE_TX_PENDING )
+                       post sendTask();
+       }
+
+       tasklet_async event void Tasklet.run()
+       {
+       }
+
+       command error_t Send.cancel(message_t* msg)
+       {
+               if( state == STATE_TX_PENDING )
+               {
+                       state = STATE_READY;
+
+                       // TODO: check if sendDone can be called before cancel returns
+                       signal Send.sendDone(msg, ECANCEL);
+
+                       return SUCCESS;
+               }
+               else
+                       return FAIL;
+       }
+
+       default event void Send.sendDone(message_t* msg, error_t error)
+       {
+       }
+
+       inline command uint8_t Send.maxPayloadLength()
+       {
+               return call Packet.maxPayloadLength();
+       }
+
+       inline command void* Send.getPayload(message_t* msg, uint8_t len)
+       {
+               return call Packet.getPayload(msg, len);
+       }
+
+/*----------------- Receive -----------------*/
+
+       enum
+       {
+               RECEIVE_QUEUE_SIZE = 3,
+       };
+
+       message_t receiveQueueData[RECEIVE_QUEUE_SIZE];
+       message_t* receiveQueue[RECEIVE_QUEUE_SIZE];
+
+       uint8_t receiveQueueHead;
+       uint8_t receiveQueueSize;
+
+       command error_t SoftwareInit.init()
+       {
+               uint8_t i;
+
+               for(i = 0; i < RECEIVE_QUEUE_SIZE; ++i)
+                       receiveQueue[i] = receiveQueueData + i;
+
+               return SUCCESS;
+       }
+
+       tasklet_async event bool RadioReceive.header(message_t* msg)
+       {
+               bool notFull;
+
+               // this prevents undelivered messages to be acknowledged
+               atomic notFull = receiveQueueSize < RECEIVE_QUEUE_SIZE;
+
+               return notFull;
+       }
+
+       task void deliverTask()
+       {
+               // get rid of as many messages as possible without interveining tasks
+               for(;;)
+               {
+                       message_t* msg;
+
+                       atomic
+                       {
+                               if( receiveQueueSize == 0 )
+                                       return;
+
+                               msg = receiveQueue[receiveQueueHead];
+                       }
+
+                       msg = signal Receive.receive(msg, 
+                               call Packet.getPayload(msg, call Packet.maxPayloadLength()), 
+                               call Packet.payloadLength(msg));
+
+                       atomic
+                       {
+                               receiveQueue[receiveQueueHead] = msg;
+
+                               if( ++receiveQueueHead >= RECEIVE_QUEUE_SIZE )
+                                       receiveQueueHead = 0;
+
+                               --receiveQueueSize;
+                       }
+               }
+       }
+
+       tasklet_async event message_t* RadioReceive.receive(message_t* msg)
+       {
+               message_t *m;
+
+               atomic
+               {
+                       if( receiveQueueSize >= RECEIVE_QUEUE_SIZE )
+                               m = msg;
+                       else
+                       {
+                               uint8_t index = receiveQueueHead + receiveQueueSize;
+                               if( index >= RECEIVE_QUEUE_SIZE )
+                                       index -= RECEIVE_QUEUE_SIZE;
+
+                               m = receiveQueue[index];
+                               receiveQueue[index] = msg;
+
+                               ++receiveQueueSize;
+                               post deliverTask();
+                       }
+               }
+
+               return m;
+       }
+
+       default event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
+       {
+               return msg;
+       }
+}
diff --git a/tos/chips/rf230/Neighborhood.h b/tos/chips/rf230/Neighborhood.h
new file mode 100644 (file)
index 0000000..40884e3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __NEIGHBORHOOD_H__
+#define __NEIGHBORHOOD_H__
+
+#ifndef NEIGHBORHOOD_SIZE
+#define NEIGHBORHOOD_SIZE      5
+#endif
+
+#endif//__NEIGHBORHOOD_H__
diff --git a/tos/chips/rf230/Neighborhood.nc b/tos/chips/rf230/Neighborhood.nc
new file mode 100644 (file)
index 0000000..ec00392
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/**
+ * Every component maintains its own neighborhood data. The Neighboorhood
+ * component maintains only the nodeids and ages of the neighbors, and
+ * evicts old entries from the table when necessary.
+ */
+interface Neighborhood
+{
+       /**
+        * Returns the index of the neighbor in the table. If the node was not 
+        * found in the table, then the value NEIGHBORHOOD is  returned, 
+        * otherwise an index in the range [0, NEIGHBORHOOD-1] is returned.
+        */
+       tasklet_async command uint8_t getIndex(am_addr_t id);
+
+       /**
+        * Returns the age of the given entry. The age is incremented by one
+        * every time a new node is inserted into the neighborhood table that
+        * is not already at the very end. If the age would get too large to
+        * fit into a byte, then it is periodically reset to a large value.
+        */
+       tasklet_async command uint8_t getAge(uint8_t index);
+
+       /**
+        * Returns the node address for the given entry.
+        */
+       tasklet_async command am_addr_t getNode(uint8_t index);
+
+       /**
+        * Adds a new node into the neighborhood table. If this node was already
+        * in the table, then it is just brought to the front (its age is reset
+        * to zero). If the node was not in the table, then the oldest is evicted
+        * and its entry is replaced with this node. The index of the entry
+        * is returned in the range [0, NEIGHBORHOOD-1]. 
+        */
+       tasklet_async command uint8_t insertNode(am_addr_t id);
+
+       /**
+        * This event is fired when the oldest entry is replaced with a new
+        * node. The same interface is used by many users, so all of them
+        * will receive this event and can clear the corresponding entry.
+        * After this event is fired, all flags for this entry are cleared
+        * (see the NeighborhoodFlag interface)
+        */
+       tasklet_async event void evicted(uint8_t index);
+}
diff --git a/tos/chips/rf230/NeighborhoodC.nc b/tos/chips/rf230/NeighborhoodC.nc
new file mode 100644 (file)
index 0000000..e2ba9b5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration NeighborhoodC
+{
+       provides interface Neighborhood;
+}
+
+implementation
+{
+       components NeighborhoodP, MainC;
+
+       Neighborhood = NeighborhoodP;
+       MainC.SoftwareInit -> NeighborhoodP;
+}
diff --git a/tos/chips/rf230/NeighborhoodFlag.nc b/tos/chips/rf230/NeighborhoodFlag.nc
new file mode 100644 (file)
index 0000000..e1dda90
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/**
+ * This interface provides one bit storage for each neighbor in a very
+ * fast and conveint way (without using shifts for example). 
+ */
+interface NeighborhoodFlag
+{
+       /**
+        * Returns the value of the flag for the given index
+        */
+       tasklet_async command bool get(uint8_t index);
+       
+       /**
+        * Sets the flag for the given index
+        */
+       tasklet_async command void set(uint8_t index);
+
+       /**
+        * Clears the flag for the given index. The flag is automatically
+        * cleared after the Neighborhood.evicted event is fired.
+        */
+       tasklet_async command void clear(uint8_t index);
+
+       /**
+        * Clears the flag for all indices
+        */
+       tasklet_async command void clearAll();
+}
diff --git a/tos/chips/rf230/NeighborhoodFlagC.nc b/tos/chips/rf230/NeighborhoodFlagC.nc
new file mode 100644 (file)
index 0000000..2f064eb
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+generic configuration NeighborhoodFlagC()
+{
+       provides interface NeighborhoodFlag;
+}
+
+implementation
+{
+       components NeighborhoodP;
+
+       // TODO: make sure that no more than 8 flags are used at a time
+       NeighborhoodFlag = NeighborhoodP.NeighborhoodFlag[unique("NeighborhoodFlag")];
+}
diff --git a/tos/chips/rf230/NeighborhoodP.nc b/tos/chips/rf230/NeighborhoodP.nc
new file mode 100644 (file)
index 0000000..fb84dc8
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Neighborhood.h>
+
+module NeighborhoodP
+{
+       provides
+       {
+               interface Init;
+               interface Neighborhood;
+               interface NeighborhoodFlag[uint8_t bit];
+       }
+}
+
+implementation
+{
+       tasklet_norace am_addr_t nodes[NEIGHBORHOOD_SIZE];
+       tasklet_norace uint8_t ages[NEIGHBORHOOD_SIZE];
+       tasklet_norace uint8_t flags[NEIGHBORHOOD_SIZE];
+       tasklet_norace uint8_t time;
+       tasklet_norace uint8_t last;
+
+       command error_t Init.init()
+       {
+               uint8_t i;
+
+               for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+                       nodes[i] = AM_BROADCAST_ADDR;
+       
+               return SUCCESS;
+       }
+
+       inline tasklet_async command am_addr_t Neighborhood.getNode(uint8_t index)
+       {
+               return nodes[index];
+       }
+
+       inline tasklet_async command uint8_t Neighborhood.getAge(uint8_t index)
+       {
+               return time - ages[index];
+       }
+
+       tasklet_async uint8_t command Neighborhood.getIndex(am_addr_t node)
+       {
+               uint8_t i;
+
+               if( nodes[last] == node )
+                       return last;
+
+               for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+               {
+                       if( nodes[i] == node )
+                       {
+                               last = i;
+                               break;
+                       }
+               }
+
+               return i;
+       }
+
+       tasklet_async uint8_t command Neighborhood.insertNode(am_addr_t node)
+       {
+               uint8_t i;
+               uint8_t maxAge;
+
+               if( nodes[last] == node )
+               {
+                       if( ages[last] == time )
+                               return last;
+
+                       ages[last] = ++time;
+                       maxAge = 0x80;
+               }
+               else
+               {
+                       uint8_t oldest = 0;
+                       maxAge = 0;
+
+                       for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+                       {
+                               uint8_t age;
+
+                               if( nodes[i] == node )
+                               {
+                                       last = i;
+                                       if( ages[i] == time )
+                                               return i;
+
+                                       ages[i] = ++time;
+                                       maxAge = 0x80;
+                                       break;
+                               }
+
+                               age = time - ages[i];
+                               if( age > maxAge )
+                               {
+                                       maxAge = age;
+                                       oldest = i;
+                               }
+                       }
+
+                       if( i == NEIGHBORHOOD_SIZE )
+                       {
+                               signal Neighborhood.evicted(oldest);
+
+                               last = oldest;
+                               nodes[oldest] = node;
+                               ages[oldest] = ++time;
+                               flags[oldest] = 0;
+                       }
+               }
+
+               if( (time & 0x7F) == 0x7F && maxAge >= 0x7F )
+               {
+                       for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+                       {
+                               if( (ages[i] | 0x7F) != time )
+                                       ages[i] = time & 0x80;
+                       }
+               }
+
+               return last;
+       }
+
+       inline tasklet_async command bool NeighborhoodFlag.get[uint8_t bit](uint8_t index)
+       {
+               return flags[index] & (1 << bit);
+       }
+
+       inline tasklet_async command void NeighborhoodFlag.set[uint8_t bit](uint8_t index)
+       {
+               flags[index] |= (1 << bit);
+       }
+
+       inline tasklet_async command void NeighborhoodFlag.clear[uint8_t bit](uint8_t index)
+       {
+               flags[index] &= ~(1 << bit);
+       }
+
+       tasklet_async command void NeighborhoodFlag.clearAll[uint8_t bit]()
+       {
+               uint8_t i;
+
+               bit = ~(1 << bit);
+
+               for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+                       flags[i] &= bit;
+       }
+}
diff --git a/tos/chips/rf230/PacketTimeStamp.nc b/tos/chips/rf230/PacketTimeStamp.nc
new file mode 100644 (file)
index 0000000..b45eea0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface PacketTimeStamp<precision_tag, size_type>
+{
+       /**
+        * Returns TRUE if the time stamp stored in the message is valid. Under
+        * special circumstances the radio chip might not be able to correctly
+        * assign a precise time value to an incoming packet (e.g. under very 
+        * heavy traffic multiple interrupts can occur before they could be 
+        * serviced, and even if capture registers are used, it is not possible 
+        * to get the time stamp for the first or last unserviced event), in
+        * which case the time stamp value should not be used.
+        */
+       async command bool isSet(message_t* msg);
+
+       /**
+        * Return the time stamp for the given message. Please check with the 
+        * isSet command if this value can be relied upon. If this command is
+        * called after transmission, then the transmit time of the packet
+        * is returned (the time when the frame synchronization byte was 
+        * transmitted). If this command is called after the message is received,
+        * the tne receive time of the message is returned.
+        */
+       async command size_type get(message_t* msg);
+
+       /**
+        * Sets the isSet flag to FALSE.
+        */
+       async command void clear(message_t* msg);
+
+       /**
+        * Sets the isSet false to TRUE and the time stamp value to the 
+        * specified value.
+        */
+       async command void set(message_t* msg, size_type value);
+}
diff --git a/tos/chips/rf230/PacketTimeSynch.nc b/tos/chips/rf230/PacketTimeSynch.nc
new file mode 100644 (file)
index 0000000..47b9051
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface PacketTimeSynch<precision_tag, size_type>
+{
+       /**
+        * This command should be called by the sender on packets used for sender- 
+        * receiver time synchronization. The eventTime parameter should be as 
+        * close to the current time as possible (precision and size of the stamp 
+        * permitting) to avoid large time synchronization errors resulting from
+        * the time skew between the clocks of the sender and receiver. The
+        * time difference between the sending time and eventTime is stored in 
+        * the message just before it is transmitted over the air.
+        */
+       async command void set(message_t* msg, size_type eventTime);
+
+       /**
+        * The recveive should call this method to ensure that the received time
+        * stamp is correct (for the same reason as for PacketTimeStamp.isSet).
+        * If this method returns TRUE, then the eventTime returned by the get
+        * command is correct.
+        */
+       async command bool isSet(message_t* msg);
+
+       /**
+        * This command should be called by the receiver. The time stamp of the
+        * received message is added to the embedded time difference to get the
+        * eventTime as measured by the clock of the receiver. The caller should
+        * call the isSet command before to make sure that the returned time is
+        * correct.
+        */
+       async command size_type get(message_t* msg);
+}
diff --git a/tos/chips/rf230/RF230.h b/tos/chips/rf230/RF230.h
new file mode 100644 (file)
index 0000000..781a133
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __RF230_H__
+#define __RF230_H__
+
+enum rf230_registers_enum
+{
+       RF230_TRX_STATUS = 0x01,
+       RF230_TRX_STATE = 0x02,
+       RF230_TRX_CTRL_0 = 0x03,
+       RF230_PHY_TX_PWR = 0x05,
+       RF230_PHY_RSSI = 0x06,
+       RF230_PHY_ED_LEVEL = 0x07,
+       RF230_PHY_CC_CCA = 0x08,
+       RF230_CCA_THRES = 0x09,
+       RF230_IRQ_MASK = 0x0E,
+       RF230_IRQ_STATUS = 0x0F,
+       RF230_VREG_CTRL = 0x10,
+       RF230_BATMON = 0x11,
+       RF230_XOSC_CTRL = 0x12,
+       RF230_PLL_CF = 0x1A,
+       RF230_PLL_DCU = 0x1B,
+       RF230_PART_NUM = 0x1C,
+       RF230_VERSION_NUM = 0x1D,
+       RF230_MAN_ID_0 = 0x1E,
+       RF230_MAN_ID_1 = 0x1F,
+       RF230_SHORT_ADDR_0 = 0x20,
+       RF230_SHORT_ADDR_1 = 0x21,
+       RF230_PAN_ID_0 = 0x22,
+       RF230_PAN_ID_1 = 0x23,
+       RF230_IEEE_ADDR_0 = 0x24,
+       RF230_IEEE_ADDR_1 = 0x25,
+       RF230_IEEE_ADDR_2 = 0x26,
+       RF230_IEEE_ADDR_3 = 0x27,
+       RF230_IEEE_ADDR_4 = 0x28,
+       RF230_IEEE_ADDR_5 = 0x29,
+       RF230_IEEE_ADDR_6 = 0x2A,
+       RF230_IEEE_ADDR_7 = 0x2B,
+       RF230_XAH_CTRL = 0x2C,
+       RF230_CSMA_SEED_0 = 0x2D,
+       RF230_CSMA_SEED_1 = 0x2E,
+};
+
+enum rf230_trx_register_enums
+{
+       RF230_CCA_DONE = 1 << 7,
+       RF230_CCA_STATUS = 1 << 6,
+       RF230_TRX_STATUS_MASK = 0x1F,
+       RF230_P_ON = 0,
+       RF230_BUSY_RX = 1,
+       RF230_BUSY_TX = 2,
+       RF230_RX_ON = 6,
+       RF230_TRX_OFF = 8,
+       RF230_PLL_ON = 9,
+       RF230_SLEEP = 15,
+       RF230_BUSY_RX_AACK = 16,
+       RF230_BUSR_TX_ARET = 17,
+       RF230_RX_AACK_ON = 22,
+       RF230_TX_ARET_ON = 25,
+       RF230_RX_ON_NOCLK = 28,
+       RF230_AACK_ON_NOCLK = 29,
+       RF230_BUSY_RX_AACK_NOCLK = 30,
+       RF230_STATE_TRANSITION_IN_PROGRESS = 31,
+       RF230_TRAC_STATUS_MASK = 0xE0,
+       RF230_TRAC_SUCCESS = 0,
+       RF230_TRAC_CHANNEL_ACCESS_FAILURE = 3 << 5,
+       RF230_TRAC_NO_ACK = 5 << 5,
+       RF230_TRX_CMD_MASK = 0x1F,
+       RF230_NOP = 0,
+       RF230_TX_START = 2,
+       RF230_FORCE_TRX_OFF = 3,
+};
+
+enum rf230_phy_register_enums
+{
+       RF230_TX_AUTO_CRC_ON = 1 << 7,
+       RF230_TX_PWR_MASK = 0x0F,
+       RF230_TX_PWR_DEFAULT = 0,
+       RF230_RSSI_MASK = 0x1F,
+       RF230_CCA_REQUEST = 1 << 7,
+       RF230_CCA_MODE_0 = 0 << 5,
+       RF230_CCA_MODE_1 = 1 << 5,
+       RF230_CCA_MODE_2 = 2 << 5,
+       RF230_CCA_MODE_3 = 3 << 5,
+       RF230_CHANNEL_DEFAULT = 11,
+       RF230_CHANNEL_MASK = 0x1F,
+       RF230_CCA_CS_THRES_SHIFT = 4,
+       RF230_CCA_ED_THRES_SHIFT = 0,
+};
+
+enum rf230_irq_register_enums
+{
+       RF230_IRQ_BAT_LOW = 1 << 7,
+       RF230_IRQ_TRX_UR = 1 << 6,
+       RF230_IRQ_TRX_END = 1 << 3,
+       RF230_IRQ_RX_START = 1 << 2,
+       RF230_IRQ_PLL_UNLOCK = 1 << 1,
+       RF230_IRQ_PLL_LOCK = 1 << 0,
+};
+
+enum rf230_control_register_enums
+{
+       RF230_AVREG_EXT = 1 << 7,
+       RF230_AVDD_OK = 1 << 6,
+       RF230_DVREG_EXT = 1 << 3,
+       RF230_DVDD_OK = 1 << 2,
+       RF230_BATMON_OK = 1 << 5,
+       RF230_BATMON_VHR = 1 << 4,
+       RF230_BATMON_VTH_MASK = 0x0F,
+       RF230_XTAL_MODE_OFF = 0 << 4,
+       RF230_XTAL_MODE_EXTERNAL = 4 << 4,
+       RF230_XTAL_MODE_INTERNAL = 15 << 4,
+};
+
+enum rf230_pll_register_enums
+{
+       RF230_PLL_CF_START = 1 << 7,
+       RF230_PLL_DCU_START = 1 << 7,
+};
+
+enum rf230_spi_command_enums
+{
+       RF230_CMD_REGISTER_READ = 0x80,
+       RF230_CMD_REGISTER_WRITE = 0xC0,
+       RF230_CMD_REGISTER_MASK = 0x3F,
+       RF230_CMD_FRAME_READ = 0x20,
+       RF230_CMD_FRAME_WRITE = 0x60,
+       RF230_CMD_SRAM_READ = 0x00,
+       RF230_CMD_SRAM_WRITE = 0x40,
+};
+
+#endif//__RF230_H__
diff --git a/tos/chips/rf230/RF230Config.nc b/tos/chips/rf230/RF230Config.nc
new file mode 100644 (file)
index 0000000..97d2392
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+/**
+ * This interface needs to be implemented by the MAC to control the behaviour 
+ * of the RF230LayerC component.
+ */
+interface RF230Config
+{
+       /**
+        * Returns the length of the PHY payload (including the FCF field).
+        * This value must be in the range [3, 127].
+        */
+       async command uint8_t getLength(message_t* msg);
+
+       /**
+        * Sets the length of the PHY payload.
+        */
+       async command void setLength(message_t* msg, uint8_t len);
+
+       /**
+        * Returns a pointer to the start of the PHY payload that contains 
+        * getLength()-2 number of bytes. The FCF field (CRC-16) is not stored,
+        * but automatically appended / verified.
+        */
+       async command uint8_t* getPayload(message_t* msg);
+
+       /**
+        * Sets the timestamp (when the message was sent or received)
+        */
+       async command void setTimestamp(message_t* msg, uint16_t time);
+
+       /**
+        * Sets the link quality indicator field for the received message
+        */
+       async command void setLinkQuality(message_t* msg, uint8_t lqi);
+
+       /**
+        * Gets the number of bytes we should read before the RadioReceive.header
+        * event is fired. If the length of the packet is less than this amount, 
+        * then that event is fired earlier.
+        */
+       async command uint8_t getHeaderLength();
+
+       /**
+        * Returns the maximum PHY length that can be set via the setLength command
+        */
+       async command uint8_t getMaxLength();
+
+       /**
+        * Returns the transmit power for the given message, this must be a value 
+        * in the range [0, 15] which will be stored in the PHY_TX_PWR register.
+        */
+       async command uint8_t getTransmitPower(message_t* msg);
+
+       /**
+        * This command is used at power up to set the default channel.
+        * The default CC2420 channel is 26.
+        */
+       async command uint8_t getDefaultChannel();
+
+       /**
+        * Returns TRUE if before sending this message we should make sure that
+        * the channel is clear via a very basic (and quick) RSSI check.
+        */
+       async command bool requiresRssiCca(message_t* msg);
+}
diff --git a/tos/chips/rf230/RF230LayerC.nc b/tos/chips/rf230/RF230LayerC.nc
new file mode 100644 (file)
index 0000000..d50ce40
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration RF230LayerC
+{
+       provides
+       {
+               interface Init as PlatformInit @exactlyonce();
+
+               interface RadioState;
+               interface RadioSend;
+               interface RadioReceive;
+               interface RadioCCA;
+       }
+
+       uses 
+       {
+               interface RF230Config;
+       }
+}
+
+implementation
+{
+       components RF230LayerP, HplRF230C, BusyWaitMicroC, TaskletC, MainC, RadioAlarmC;
+
+       PlatformInit = RF230LayerP.PlatformInit;
+
+       RadioState = RF230LayerP;
+       RadioSend = RF230LayerP;
+       RadioReceive = RF230LayerP;
+       RadioCCA = RF230LayerP;
+
+       RF230Config = RF230LayerP;
+
+       RF230LayerP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
+       RadioAlarmC.Alarm -> HplRF230C.Alarm;
+
+       RF230LayerP.SELN -> HplRF230C.SELN;
+       RF230LayerP.SpiResource -> HplRF230C.SpiResource;
+       RF230LayerP.SpiByte -> HplRF230C;
+       RF230LayerP.HplRF230 -> HplRF230C;
+
+       RF230LayerP.SLP_TR -> HplRF230C.SLP_TR;
+       RF230LayerP.RSTN -> HplRF230C.RSTN;
+
+       RF230LayerP.IRQ -> HplRF230C.IRQ;
+       RF230LayerP.Tasklet -> TaskletC;
+       RF230LayerP.BusyWait -> BusyWaitMicroC;
+
+#ifdef RF230_DEBUG
+       components DiagMsgC;
+       RF230LayerP.DiagMsg -> DiagMsgC;
+#endif
+
+       MainC.SoftwareInit -> RF230LayerP.SoftwareInit;
+}
diff --git a/tos/chips/rf230/RF230LayerP.nc b/tos/chips/rf230/RF230LayerP.nc
new file mode 100644 (file)
index 0000000..ef4c52f
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <RF230.h>
+#include <HplRF230.h>
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module RF230LayerP
+{
+       provides
+       {
+               interface Init as PlatformInit @exactlyonce();
+               interface Init as SoftwareInit @exactlyonce();
+
+               interface RadioState;
+               interface RadioSend;
+               interface RadioReceive;
+               interface RadioCCA;
+       }
+
+       uses
+       {
+               interface GeneralIO as SELN;
+               interface Resource as SpiResource;
+
+               interface SpiByte;
+               interface HplRF230;
+
+               interface GeneralIO as SLP_TR;
+               interface GeneralIO as RSTN;
+
+               interface GpioCapture as IRQ;
+
+               interface BusyWait<TMicro, uint16_t>;
+
+               interface RF230Config;
+               interface Tasklet;
+
+#ifdef RF230_DEBUG
+               interface DiagMsg;
+#endif
+
+               interface RadioAlarm;
+       }
+}
+
+implementation
+{
+/*----------------- STATE -----------------*/
+
+       tasklet_norace uint8_t state;
+       enum
+       {
+               STATE_P_ON = 0,
+               STATE_SLEEP = 1,
+               STATE_SLEEP_2_TRX_OFF = 2,
+               STATE_TRX_OFF = 3,
+               STATE_TRX_OFF_2_RX_ON = 4,
+               STATE_RX_ON = 5,
+               STATE_BUSY_TX_2_RX_ON = 6,
+               STATE_PLL_ON_2_RX_ON = 7,
+       };
+
+       tasklet_norace uint8_t cmd;
+       enum
+       {
+               CMD_NONE = 0,                   // the state machine has stopped
+               CMD_TURNOFF = 1,                // goto SLEEP state
+               CMD_STANDBY = 2,                // goto TRX_OFF state
+               CMD_TURNON = 3,                 // goto RX_ON state
+               CMD_TRANSMIT = 4,               // currently transmitting a message
+               CMD_RECEIVE = 5,                // currently receiving a message
+               CMD_CCA = 6,                    // performing clear chanel assesment
+               CMD_CHANNEL = 7,                // changing the channel
+               CMD_SIGNAL_DONE = 8,    // signal the end of the state transition
+               CMD_DOWNLOAD = 9,               // download the received message
+       };
+
+       norace bool radioIrq;
+
+       tasklet_norace uint8_t txPower;
+       tasklet_norace uint8_t channel;
+
+       tasklet_norace message_t* rxMsg;
+       message_t rxMsgBuffer;
+
+       uint16_t capturedTime;  // the current time when the last interrupt has occured
+
+       tasklet_norace uint8_t rssiClear;
+       tasklet_norace uint8_t rssiBusy;
+
+/*----------------- REGISTER -----------------*/
+
+       inline void writeRegister(uint8_t reg, uint8_t value)
+       {
+               ASSERT( call SpiResource.isOwner() );
+               ASSERT( reg == (reg & RF230_CMD_REGISTER_MASK) );
+
+               call SELN.clr();
+               call HplRF230.spiSplitWrite(RF230_CMD_REGISTER_WRITE | reg);
+               call HplRF230.spiSplitReadWrite(value);
+               call HplRF230.spiSplitRead();
+               call SELN.set();
+       }
+
+       inline uint8_t readRegister(uint8_t reg)
+       {
+               ASSERT( call SpiResource.isOwner() );
+               ASSERT( reg == (reg & RF230_CMD_REGISTER_MASK) );
+
+               call SELN.clr();
+               call HplRF230.spiSplitWrite(RF230_CMD_REGISTER_READ | reg);
+               call HplRF230.spiSplitReadWrite(0);
+               reg = call HplRF230.spiSplitRead();
+               call SELN.set();
+
+               return reg;
+       }
+
+/*----------------- ALARM -----------------*/
+
+       enum
+       {
+               SLEEP_WAKEUP_TIME = (uint16_t)(880 * RF230_ALARM_MICROSEC),
+               CCA_REQUEST_TIME = (uint16_t)(140 * RF230_ALARM_MICROSEC),
+
+               TX_SFD_DELAY = (uint16_t)(176 * RF230_ALARM_MICROSEC),
+               RX_SFD_DELAY = (uint16_t)(8 * RF230_ALARM_MICROSEC),
+       };
+
+       tasklet_async event void RadioAlarm.fired()
+       {
+               if( state == STATE_SLEEP_2_TRX_OFF )
+               {
+                       state = STATE_TRX_OFF;
+               }
+               else if( cmd == CMD_CCA )
+               {
+                       uint8_t cca;
+
+                       ASSERT( state == STATE_RX_ON );
+
+                       cmd = CMD_NONE;
+                       cca = readRegister(RF230_TRX_STATUS);
+
+                       ASSERT( (cca & RF230_TRX_STATUS_MASK) == RF230_RX_ON );
+
+                       signal RadioCCA.done( (cca & RF230_CCA_DONE) ? ((cca & RF230_CCA_STATUS) ? SUCCESS : EBUSY) : FAIL );
+               }
+               else
+                       ASSERT(FALSE);
+
+               // make sure the rest of the command processing is called
+               call Tasklet.schedule();
+       }
+
+/*----------------- INIT -----------------*/
+
+       command error_t PlatformInit.init()
+       {
+               call SELN.makeOutput();
+               call SELN.set();
+               call SLP_TR.makeOutput();
+               call SLP_TR.clr();
+               call RSTN.makeOutput();
+               call RSTN.set();
+
+               rxMsg = &rxMsgBuffer;
+
+               // these are just good approximates
+               rssiClear = 0;
+               rssiBusy = 90;
+
+               return SUCCESS;
+       }
+
+       command error_t SoftwareInit.init()
+       {
+               // for powering up the radio
+               return call SpiResource.request();
+       }
+
+       void initRadio()
+       {
+               call BusyWait.wait(510);
+
+               call RSTN.clr();
+               call SLP_TR.clr();
+               call BusyWait.wait(6);
+               call RSTN.set();
+
+               writeRegister(RF230_TRX_CTRL_0, RF230_TRX_CTRL_0_VALUE);
+               writeRegister(RF230_TRX_STATE, RF230_TRX_OFF);
+
+               call BusyWait.wait(510);
+
+               writeRegister(RF230_IRQ_MASK, RF230_IRQ_TRX_UR | RF230_IRQ_PLL_UNLOCK | RF230_IRQ_PLL_LOCK | RF230_IRQ_TRX_END | RF230_IRQ_RX_START);
+               writeRegister(RF230_CCA_THRES, RF230_CCA_THRES_VALUE);
+               writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | RF230_TX_PWR_DEFAULT);
+
+               txPower = RF230_TX_PWR_DEFAULT;
+               channel = call RF230Config.getDefaultChannel() & RF230_CHANNEL_MASK;
+               writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel);
+
+               call SLP_TR.set();
+               state = STATE_SLEEP;
+       }
+
+/*----------------- SPI -----------------*/
+
+       event void SpiResource.granted()
+       {
+               // TODO: this should not be here, see my comment in HplRF230C.nc
+               call SELN.set();
+
+               if( state == STATE_P_ON )
+               {
+                       initRadio();
+                       call SpiResource.release();
+               }
+               else
+                       call Tasklet.schedule();
+       }
+
+       bool isSpiAcquired()
+       {
+               if( call SpiResource.isOwner() )
+                       return TRUE;
+
+               if( call SpiResource.immediateRequest() == SUCCESS )
+               {
+                       // TODO: this should not be here, see my comment in HplRF230C.nc
+                       call SELN.set();
+
+                       return TRUE;
+               }
+
+               call SpiResource.request();
+               return FALSE;
+       }
+
+/*----------------- CHANNEL -----------------*/
+
+       tasklet_async command error_t RadioState.setChannel(uint8_t c)
+       {
+               c &= RF230_CHANNEL_MASK;
+
+               if( cmd != CMD_NONE )
+                       return EBUSY;
+               else if( channel == c )
+                       return EALREADY;
+
+               channel = c;
+               cmd = CMD_CHANNEL;
+               call Tasklet.schedule();
+
+               return SUCCESS;
+       }
+
+       inline void changeChannel()
+       {
+               ASSERT( cmd == CMD_CHANNEL );
+               ASSERT( state == STATE_SLEEP || state == STATE_TRX_OFF || state == STATE_RX_ON );
+
+               if( isSpiAcquired() )
+               {
+                       writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel);
+
+                       if( state == STATE_RX_ON )
+                               state = STATE_TRX_OFF_2_RX_ON;
+                       else
+                               cmd = CMD_SIGNAL_DONE;
+               }
+       }
+
+/*----------------- TURN ON/OFF -----------------*/
+
+       inline void changeState()
+       {
+               if( (cmd == CMD_STANDBY || cmd == CMD_TURNON)
+                       && state == STATE_SLEEP && call RadioAlarm.isFree() )
+               {
+                       call SLP_TR.clr();
+
+                       call RadioAlarm.wait(SLEEP_WAKEUP_TIME);
+                       state = STATE_SLEEP_2_TRX_OFF;
+               }
+               else if( cmd == CMD_TURNON && state == STATE_TRX_OFF && isSpiAcquired() )
+               {
+                       call IRQ.captureRisingEdge();
+                       writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+                       state = STATE_TRX_OFF_2_RX_ON;
+               }
+               else if( (cmd == CMD_TURNOFF || cmd == CMD_STANDBY) 
+                       && state == STATE_RX_ON && isSpiAcquired() )
+               {
+                       call IRQ.disable();
+                       writeRegister(RF230_TRX_STATE, RF230_FORCE_TRX_OFF);
+                       state = STATE_TRX_OFF;
+               }
+
+               if( cmd == CMD_TURNOFF && state == STATE_TRX_OFF )
+               {
+                       call SLP_TR.set();
+                       state = STATE_SLEEP;
+                       cmd = CMD_SIGNAL_DONE;
+               }
+               else if( cmd == CMD_STANDBY && state == STATE_TRX_OFF )
+                       cmd = CMD_SIGNAL_DONE;
+       }
+
+       tasklet_async command error_t RadioState.turnOff()
+       {
+               if( cmd != CMD_NONE )
+                       return EBUSY;
+               else if( state == STATE_SLEEP )
+                       return EALREADY;
+
+               cmd = CMD_TURNOFF;
+               call Tasklet.schedule();
+
+               return SUCCESS;
+       }
+       
+       tasklet_async command error_t RadioState.standby()
+       {
+               if( cmd != CMD_NONE || (state == STATE_SLEEP && ! call RadioAlarm.isFree()) )
+                       return EBUSY;
+               else if( state == STATE_TRX_OFF )
+                       return EALREADY;
+
+               cmd = CMD_STANDBY;
+               call Tasklet.schedule();
+
+               return SUCCESS;
+       }
+
+       tasklet_async command error_t RadioState.turnOn()
+       {
+               if( cmd != CMD_NONE || (state == STATE_SLEEP && ! call RadioAlarm.isFree()) )
+                       return EBUSY;
+               else if( state == STATE_RX_ON )
+                       return EALREADY;
+
+               cmd = CMD_TURNON;
+               call Tasklet.schedule();
+
+               return SUCCESS;
+       }
+
+       default tasklet_async event void RadioState.done() { }
+
+/*----------------- TRANSMIT -----------------*/
+
+       tasklet_async command error_t RadioSend.send(message_t* msg)
+       {
+               uint16_t time;
+               uint8_t length;
+               uint8_t* data;
+
+               if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || radioIrq )
+                       return EBUSY;
+
+               if( call RF230Config.requiresRssiCca(msg) 
+                               && readRegister(RF230_PHY_RSSI) > ((rssiClear + rssiBusy) >> 3) )
+                       return EBUSY;
+
+               writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
+
+               // do something useful, just to wait a little
+               length = call RF230Config.getTransmitPower(msg) & RF230_TX_PWR_MASK;
+               if( length != txPower )
+               {
+                       txPower = length;
+                       writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | txPower);
+               }
+
+               // we have missed an incoming message in this short amount of time
+               if( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) != RF230_PLL_ON )
+               {
+                       ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_BUSY_RX );
+
+                       state = STATE_PLL_ON_2_RX_ON;
+                       return EBUSY;
+               }
+
+               atomic
+               {
+                       call SLP_TR.set();
+                       time = call RadioAlarm.getNow();
+               }
+               call SLP_TR.clr();
+
+               ASSERT( ! radioIrq );
+
+               call SELN.clr();
+               call HplRF230.spiSplitWrite(RF230_CMD_FRAME_WRITE);
+
+               length = call RF230Config.getLength(msg);
+               data = call RF230Config.getPayload(msg);
+
+               // length | data[0] ... data[length-3] | automatically generated FCS
+               call HplRF230.spiSplitReadWrite(length);
+
+               // the FCS is atomatically generated
+               length -= 2;
+
+               do {
+                       call HplRF230.spiSplitReadWrite(*(data++));
+               }
+               while( --length != 0 );
+
+               // wait for the SPI transfer to finish
+               call HplRF230.spiSplitRead();
+               call SELN.set();
+
+               length = readRegister(RF230_TRX_STATUS); 
+
+               // go back to RX_ON state when finished
+               writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+
+               /*
+                * There is a very small window (~1 microsecond) when the RF230 went 
+                * into PLL_ON state but was somehow not properly initialized because 
+                * of an incoming message and could not go into BUSY_TX. 
+                */
+               if( (length & RF230_TRX_STATUS_MASK) != RF230_BUSY_TX )
+               {
+#ifdef RF230_DEBUG
+                       if( call DiagMsg.record() )
+                       {
+                               call DiagMsg.str("assert tx");
+                               call DiagMsg.uint16(call RadioAlarm.getNow());
+                               call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
+                               call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
+                               call DiagMsg.hex8(radioIrq);
+                               call DiagMsg.uint8(state);
+                               call DiagMsg.uint8(cmd);
+                               call DiagMsg.send();
+                       }
+#endif
+                       ASSERT( (length & RF230_TRX_STATUS_MASK) == RF230_PLL_ON );
+                       return FAIL;
+               }
+
+               time += TX_SFD_DELAY;
+               call RF230Config.setTimestamp(msg, time);
+
+               // wait for the TRX_END interrupt
+               state = STATE_BUSY_TX_2_RX_ON;
+               cmd = CMD_TRANSMIT;
+
+               return SUCCESS;
+       }
+
+       default tasklet_async event void RadioSend.sendDone(error_t error) { }
+
+/*----------------- CCA -----------------*/
+
+       tasklet_async command error_t RadioCCA.request()
+       {
+               if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || ! call RadioAlarm.isFree() )
+                       return EBUSY;
+
+               // see Errata B7 of the datasheet
+               // writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
+               // writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+
+               writeRegister(RF230_PHY_CC_CCA, RF230_CCA_REQUEST | RF230_CCA_MODE_VALUE | channel);
+               call RadioAlarm.wait(CCA_REQUEST_TIME);
+               cmd = CMD_CCA;
+               
+               return SUCCESS;
+       }
+
+       default tasklet_async event void RadioCCA.done(error_t error) { }
+
+/*----------------- RECEIVE -----------------*/
+
+       inline void downloadMessage()
+       {
+               uint8_t length;
+               uint16_t crc;
+
+               call SELN.clr();
+               call HplRF230.spiWrite(RF230_CMD_FRAME_READ);
+
+               // read the length byte
+               length = call HplRF230.spiWrite(0);
+
+               // if correct length
+               if( length >= 3 && length <= call RF230Config.getMaxLength() )
+               {
+                       uint8_t read;
+                       uint8_t* data;
+
+                       // initiate the reading
+                       call HplRF230.spiSplitWrite(0);
+
+                       call RF230Config.setLength(rxMsg, length);
+                       data = call RF230Config.getPayload(rxMsg);
+                       crc = 0;
+
+                       // we do not store the CRC field
+                       length -= 2;
+
+                       read = call RF230Config.getHeaderLength();
+                       if( length < read )
+                               read = length;
+
+                       length -= read;
+
+                       while( read-- != 0 )
+                               crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
+
+                       if( signal RadioReceive.header(rxMsg) )
+                       {
+                               while( length-- != 0 )
+                                       crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
+
+                               crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
+                               crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
+
+                               call RF230Config.setLinkQuality(rxMsg, call HplRF230.spiSplitRead());
+                       }
+                       else
+                               crc = 1;
+               }
+               else
+                       crc = 1;
+
+               call SELN.set();
+               state = STATE_RX_ON;
+               cmd = CMD_NONE;
+
+               // signal only if it has passed the CRC check
+               if( crc == 0 )
+                       rxMsg = signal RadioReceive.receive(rxMsg);
+       }
+
+/*----------------- IRQ -----------------*/
+
+       async event void IRQ.captured(uint16_t time)
+       {
+               ASSERT( ! radioIrq );
+
+               atomic
+               {
+                       capturedTime = time;
+                       radioIrq = TRUE;
+               }
+
+               call Tasklet.schedule();
+       }
+
+       void serviceRadio()
+       {
+               if( isSpiAcquired() )
+               {
+                       uint16_t time;
+                       uint8_t irq;
+                       
+                       atomic time = capturedTime;
+                       radioIrq = FALSE;
+                       irq = readRegister(RF230_IRQ_STATUS);
+
+#ifdef RF230_DEBUG
+                       // TODO: handle this interrupt
+//                     ASSERT( ! (irq & RF230_IRQ_TRX_UR) );
+                       if( irq & RF230_IRQ_TRX_UR )
+                       {
+                               if( call DiagMsg.record() )
+                               {
+                                       call DiagMsg.str("assert ur");
+                                       call DiagMsg.uint16(call RadioAlarm.getNow());
+                                       call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
+                                       call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
+                                       call DiagMsg.hex8(irq);
+                                       call DiagMsg.uint8(state);
+                                       call DiagMsg.uint8(cmd);
+                                       call DiagMsg.send();
+                               }
+                       }
+#endif
+
+                       // TODO: handle this interrupt
+                       ASSERT( ! (irq & RF230_IRQ_PLL_UNLOCK) );
+
+                       if( irq & RF230_IRQ_PLL_LOCK )
+                       {
+                               if( cmd == CMD_TURNON || cmd == CMD_CHANNEL )
+                               {
+                                       ASSERT( state == STATE_TRX_OFF_2_RX_ON );
+
+                                       state = STATE_RX_ON;
+                                       cmd = CMD_SIGNAL_DONE;
+                               }
+                               else if( cmd == CMD_TRANSMIT )
+                               {
+                                       ASSERT( state == STATE_BUSY_TX_2_RX_ON );
+                               }
+                               else
+                                       ASSERT(FALSE);
+                       }
+
+                       if( irq & RF230_IRQ_RX_START )
+                       {
+                               if( cmd == CMD_CCA )
+                               {
+                                       signal RadioCCA.done(FAIL);
+                                       cmd = CMD_NONE;
+                               }
+
+                               if( cmd == CMD_NONE )
+                               {
+                                       ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
+
+                                       // the most likely place for busy channel
+                                       rssiBusy += readRegister(RF230_PHY_RSSI) - (rssiBusy >> 2);
+
+                                       /*
+                                        * The timestamp corresponds to the first event which could not
+                                        * have been a PLL_LOCK because then cmd != CMD_NONE, so we must
+                                        * have received a message (and could also have received the 
+                                        * TRX_END interrupt in the mean time, but that is fine. Also,
+                                        * we could not be after a transmission, because then cmd = 
+                                        * CMD_TRANSMIT.
+                                        */
+                                       call RF230Config.setTimestamp(rxMsg, time - RX_SFD_DELAY);
+                                       cmd = CMD_RECEIVE;
+                               }
+                               else
+                               {
+#ifdef RF230_DEBUG
+                                       if( call DiagMsg.record() )
+                                       {
+                                               call DiagMsg.str("assert irq");
+                                               call DiagMsg.uint16(call RadioAlarm.getNow());
+                                               call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
+                                               call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
+                                               call DiagMsg.hex8(irq);
+                                               call DiagMsg.uint8(state);
+                                               call DiagMsg.uint8(cmd);
+                                               call DiagMsg.send();
+                                       }
+#endif
+                               }
+                       }
+
+                       if( irq & RF230_IRQ_TRX_END )
+                       {
+                               if( cmd == CMD_TRANSMIT )
+                               {
+                                       ASSERT( state == STATE_BUSY_TX_2_RX_ON );
+
+                                       state = STATE_RX_ON;
+                                       cmd = CMD_NONE;
+                                       signal RadioSend.sendDone(SUCCESS);
+
+                                       // TODO: we could have missed a received message
+                                       ASSERT( ! (irq & RF230_IRQ_RX_START) );
+                               }
+                               else if( cmd == CMD_RECEIVE )
+                               {
+                                       ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
+
+                                       if( state == STATE_PLL_ON_2_RX_ON )
+                                       {
+                                               ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_PLL_ON );
+
+                                               writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+                                               state = STATE_RX_ON;
+                                       }
+                                       else
+                                       {
+                                               // the most likely place for clear channel (hope to avoid acks)
+                                               rssiClear += readRegister(RF230_PHY_RSSI) - (rssiClear >> 2);
+                                       }
+
+                                       cmd = CMD_DOWNLOAD;
+                               }
+                               else
+                                       ASSERT(FALSE);
+                       }
+               }
+       }
+
+       default tasklet_async event bool RadioReceive.header(message_t* msg)
+       {
+               return TRUE;
+       }
+
+       default tasklet_async event message_t* RadioReceive.receive(message_t* msg)
+       {
+               return msg;
+       }
+
+/*----------------- TASKLET -----------------*/
+
+       tasklet_async event void Tasklet.run()
+       {
+               if( radioIrq )
+                       serviceRadio();
+
+               if( cmd != CMD_NONE )
+               {
+                       if( cmd == CMD_DOWNLOAD )
+                               downloadMessage();
+                       else if( cmd <= CMD_TURNON && CMD_TURNOFF <= cmd )
+                               changeState();
+                       else if( cmd == CMD_CHANNEL )
+                               changeChannel();
+                       
+                       if( cmd == CMD_SIGNAL_DONE )
+                       {
+                               cmd = CMD_NONE;
+                               signal RadioState.done();
+                       }
+               }
+
+               if( cmd == CMD_NONE && state == STATE_RX_ON && ! radioIrq )
+                       signal RadioSend.ready();
+
+               if( cmd == CMD_NONE )
+                       call SpiResource.release();
+       }
+}
diff --git a/tos/chips/rf230/RadioAlarm.nc b/tos/chips/rf230/RadioAlarm.nc
new file mode 100644 (file)
index 0000000..d09c4f0
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioAlarm
+{
+       /**
+        * Returns TRUE if the alarm is free and ready to be used. Once the alarm
+        * is free, it cannot become nonfree in the same tasklet block. Note,
+        * if the alarm is currently set (even if for ourselves) then it is not free.
+        */
+       tasklet_async command bool isFree();
+
+       /**
+        * Waits till the specified timeout period expires. The alarm must be free.
+        */
+       tasklet_async command void wait(uint16_t timeout);
+
+       /**
+        * Cancels the running alarm. The alarm must be pending.
+        */
+       tasklet_async command void cancel();
+
+       /**
+        * This event is fired when the specified timeout period expires.
+        */
+       tasklet_async event void fired();
+
+       /**
+        * Returns the current time as measured by the radio stack.
+        */
+       async command uint16_t getNow();
+}
diff --git a/tos/chips/rf230/RadioAlarmC.nc b/tos/chips/rf230/RadioAlarmC.nc
new file mode 100644 (file)
index 0000000..a1b811d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration RadioAlarmC
+{
+       provides
+       {
+               interface RadioAlarm[uint8_t id]; // use unique("RadioAlarm")
+       }
+
+       uses
+       {
+               interface Alarm<TRF230, uint16_t> @exactlyonce();
+       }
+}
+
+implementation
+{
+       components RadioAlarmP, TaskletC;
+
+       RadioAlarm = RadioAlarmP;
+       Alarm = RadioAlarmP;
+       RadioAlarmP.Tasklet -> TaskletC;
+}
diff --git a/tos/chips/rf230/RadioAlarmP.nc b/tos/chips/rf230/RadioAlarmP.nc
new file mode 100644 (file)
index 0000000..d712c6e
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module RadioAlarmP
+{
+       provides
+       {
+               interface RadioAlarm[uint8_t id];
+       }
+
+       uses
+       {
+               interface Alarm<TRF230, uint16_t>;
+               interface Tasklet;
+       }
+}
+
+implementation
+{
+       norace uint8_t state;
+       enum
+       {
+               STATE_READY = 0,
+               STATE_WAIT = 1,
+               STATE_FIRED = 2,
+       };
+
+       tasklet_norace uint8_t alarm;
+
+       async event void Alarm.fired()
+       {
+               atomic
+               {
+                       if( state == STATE_WAIT )
+                               state = STATE_FIRED;
+               }
+
+               call Tasklet.schedule();
+       }
+
+       inline async command uint16_t RadioAlarm.getNow[uint8_t id]()
+       {
+               return call Alarm.getNow();
+       }
+
+       tasklet_async event void Tasklet.run()
+       {
+               if( state == STATE_FIRED )
+               {
+                       state = STATE_READY;
+                       signal RadioAlarm.fired[alarm]();
+               }
+       }
+
+       default tasklet_async event void RadioAlarm.fired[uint8_t id]()
+       {
+       }
+
+       inline tasklet_async command bool RadioAlarm.isFree[uint8_t id]()
+       {
+               return state == STATE_READY;
+       }
+
+       tasklet_async command void RadioAlarm.wait[uint8_t id](uint16_t timeout)
+       {
+               ASSERT( state == STATE_READY );
+
+               alarm = id;
+               state = STATE_WAIT;
+               call Alarm.start(timeout);
+       }
+
+       tasklet_async command void RadioAlarm.cancel[uint8_t id]()
+       {
+               ASSERT( alarm == id );
+               ASSERT( state != STATE_READY );
+
+               call Alarm.stop();
+               state = STATE_READY;
+       }
+}
diff --git a/tos/chips/rf230/RadioAssert.h b/tos/chips/rf230/RadioAssert.h
new file mode 100644 (file)
index 0000000..19f1726
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __RADIOASSERT_H__
+#define __RADIOASSERT_H__
+
+#ifdef RF230_DEBUG
+
+       void assert(bool condition, const char* file, uint16_t line);
+       #define ASSERT(COND) assert(COND, __FILE__, __LINE__)
+
+#else
+
+       #define ASSERT(COND) for(;0;)
+
+#endif
+
+#endif//__RADIOASSERT_H__
diff --git a/tos/chips/rf230/RadioCCA.nc b/tos/chips/rf230/RadioCCA.nc
new file mode 100644 (file)
index 0000000..78e1694
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioCCA
+{
+       /**
+        * Starts the clear channel assesment procedure. Returns EBUSY if the radio
+        * is currently servicing a clear channel assesment, and SUCCESS otherwise.
+        * The check will be performed only in the RX_READY state.
+        */
+       tasklet_async command error_t request();
+
+       /**
+        * Signals the completion of the clear channel assesment send command.
+        * SUCCESS means the channel is clear, EBUSY means the channel is not
+        * clear, and FAIL means that the clear channel assesment could not
+        * be finished or the operation was cancelled.
+        */
+       tasklet_async event void done(error_t error);
+}
diff --git a/tos/chips/rf230/RadioReceive.nc b/tos/chips/rf230/RadioReceive.nc
new file mode 100644 (file)
index 0000000..0e8330f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioReceive
+{
+       /**
+        * This event is fired when the header is received/downloaded and the 
+        * higher layers are consulted whether it needs to be downloaded and 
+        * further processed. Return FALSE if the message should be discarded.
+        * In particular, the message buffer layer returns FALSE if there is
+        * no space for a new message, so this message will not get acknowledged.
+        */
+       tasklet_async event bool header(message_t* msg);
+
+       /**
+        * Signals the reception of a message, but only for those messages for
+        * which SUCCESS was returned in the header event. The usual owner rules 
+        * apply to the message pointers.
+        */
+       tasklet_async event message_t* receive(message_t* msg);
+}
diff --git a/tos/chips/rf230/RadioSend.nc b/tos/chips/rf230/RadioSend.nc
new file mode 100644 (file)
index 0000000..5943794
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioSend
+{
+       /**
+        * Starts the transmission of the given message. This command must not
+        * be called while another send is in progress (so one must wait for the
+        * sendDone event). Returns EBUSY if a reception is in progress or for
+        * some other reason the request cannot be temporarily satisfied (e.g.
+        * the SPI bus access could not be acquired). In this case the send 
+        * command could be retried from a tasklet. Returns SUCCESS if the 
+        * transmission could be started. In this case sendDone will be fired.
+        */
+       tasklet_async command error_t send(message_t* msg);
+       
+       /**
+        * Signals the completion of the send command, exactly once for each 
+        * successfull send command. If the returned error code is SUCCESS, then 
+        * the message was sent (may not have been acknowledged), otherwise 
+        * the message was not transmitted over the air.
+        */
+       tasklet_async event void sendDone(error_t error);
+
+       /**
+        * This event is fired when the component is most likely able to accept 
+        * a send request. If the send command has returned with a failure, then
+        * this event will be called at least once in the near future.
+        */
+       tasklet_async event void ready();
+}
diff --git a/tos/chips/rf230/RadioState.nc b/tos/chips/rf230/RadioState.nc
new file mode 100644 (file)
index 0000000..7254383
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioState
+{
+       /**
+        * Moves to radio into sleep state with the lowest power consumption but 
+        * highest wakeup time. The radio cannot send or receive in this state 
+        * and releases all access to shared resources (e.g. SPI bus). 
+        */
+       tasklet_async command error_t turnOff();
+
+       /**
+        * The same as the turnOff command, except it is not as deep sleep, and
+        * it is quicker to recover from this state.
+        */
+       tasklet_async command error_t standby();
+
+       /**
+        * Goes into receive state. The radio continuously receive messages 
+        * and able to transmit.
+        */
+       tasklet_async command error_t turnOn();
+
+       /**
+        * Sets the current channel. Returns EBUSY if the stack is unable
+        * to change the channel this time (some other operation is in progress)
+        * SUCCESS otherwise.
+        */
+       tasklet_async command error_t setChannel(uint8_t channel);
+
+       /**
+        * This event is signaled exactly once for each sucessfully posted state 
+        * transition and setChannel command when it is completed.
+        */
+       tasklet_async event void done();
+}
diff --git a/tos/chips/rf230/RandomCollisionConfig.nc b/tos/chips/rf230/RandomCollisionConfig.nc
new file mode 100644 (file)
index 0000000..b12cc69
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface RandomCollisionConfig
+{
+       /**
+        * Returns the initial amount of maximum backoff for this message.
+        */
+       async command uint16_t getInitialBackoff(message_t* msg);
+
+       /**
+        * Returns the amount of maximum backoff when there is congestion
+        * (the channel was busy for the first try)
+        */
+       async command uint16_t getCongestionBackoff(message_t* msg);
+
+       /**
+        * Returns the minimum ticks before the message could be sent.
+        */
+       async command uint16_t getMinimumBackoff();
+
+       /**
+        * The provided message was just received, and this command should return 
+        * the time till no transmission should be initiated.
+        */
+       async command uint16_t getTransmitBarrier(message_t* msg);
+}
diff --git a/tos/chips/rf230/RandomCollisionLayerC.nc b/tos/chips/rf230/RandomCollisionLayerC.nc
new file mode 100644 (file)
index 0000000..ba7ad05
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration RandomCollisionLayerC
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RandomCollisionConfig as Config;
+       }
+}
+
+implementation
+{
+       components RandomCollisionLayerP, RadioAlarmC, RandomC;
+
+       RadioSend = RandomCollisionLayerP;
+       SubSend = RandomCollisionLayerP;
+       Config = RandomCollisionLayerP;
+       RadioReceive = RandomCollisionLayerP;
+       SubReceive = RandomCollisionLayerP;
+
+       RandomCollisionLayerP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
+       RandomCollisionLayerP.Random -> RandomC;
+}
diff --git a/tos/chips/rf230/RandomCollisionLayerP.nc b/tos/chips/rf230/RandomCollisionLayerP.nc
new file mode 100644 (file)
index 0000000..c53d1b9
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module RandomCollisionLayerP
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RadioAlarm;
+               interface Random;
+               interface RandomCollisionConfig as Config;
+       }
+}
+
+implementation
+{
+       tasklet_norace uint8_t state;
+       enum
+       {
+               STATE_READY = 0,
+               STATE_TX_PENDING_FIRST = 1,
+               STATE_TX_PENDING_SECOND = 2,
+               STATE_TX_SENDING = 3,
+
+               STATE_BARRIER = 0x80,
+       };
+
+       tasklet_norace message_t *txMsg;
+       tasklet_norace uint16_t txBarrier;
+
+       tasklet_async event void SubSend.ready()
+       {
+               if( state == STATE_READY && call RadioAlarm.isFree() )
+                       signal RadioSend.ready();
+       }
+
+       uint16_t nextRandom;
+       task void calcNextRandom()
+       {
+               uint16_t a = call Random.rand16();
+               atomic nextRandom = a;
+       }
+
+       uint16_t getBackoff(uint16_t maxBackoff)
+       {
+               uint16_t a;
+
+               atomic
+               {
+                       a = nextRandom;
+                       nextRandom += 273;
+               }
+               post calcNextRandom();
+
+               return (a % maxBackoff) + call Config.getMinimumBackoff();
+       }
+
+       tasklet_async command error_t RadioSend.send(message_t* msg)
+       {
+               if( state != STATE_READY || ! call RadioAlarm.isFree() )
+                       return EBUSY;
+
+               txMsg = msg;
+               state = STATE_TX_PENDING_FIRST;
+               call RadioAlarm.wait(getBackoff(call Config.getInitialBackoff(msg)));
+
+               return SUCCESS;
+       }
+
+       tasklet_async event void RadioAlarm.fired()
+       {
+               error_t error;
+               int16_t delay;
+
+               ASSERT( state != STATE_READY );
+
+               delay = (int16_t)txBarrier - call RadioAlarm.getNow();
+
+               if( state == STATE_BARRIER )
+               {
+                       state = STATE_READY;
+
+                       signal RadioSend.ready();
+                       return;
+               }
+               else if( (state & STATE_BARRIER) && delay > 0 )
+                       error = EBUSY;
+               else
+                       error = call SubSend.send(txMsg);
+
+               if( error != SUCCESS )
+               {
+                       if( (state & ~STATE_BARRIER) == STATE_TX_PENDING_FIRST )
+                       {
+                               state = (state & STATE_BARRIER) | STATE_TX_PENDING_SECOND;
+                               call RadioAlarm.wait(getBackoff(call Config.getCongestionBackoff(txMsg)));
+                       }
+                       else
+                       {
+                               if( (state & STATE_BARRIER) && delay > 0 )
+                               {
+                                       state = STATE_BARRIER;
+                                       call RadioAlarm.wait(delay);
+                               }
+                               else
+                                       state = STATE_READY;
+
+                               signal RadioSend.sendDone(error);
+                       }
+               }
+               else
+                       state = STATE_TX_SENDING;
+       }
+
+       tasklet_async event void SubSend.sendDone(error_t error)
+       {
+               ASSERT( state == STATE_TX_SENDING );
+
+               state = STATE_READY;
+               signal RadioSend.sendDone(error);
+       }
+
+       tasklet_async event bool SubReceive.header(message_t* msg)
+       {
+               return signal RadioReceive.header(msg);
+       }
+
+       tasklet_async event message_t* SubReceive.receive(message_t* msg)
+       {
+               int16_t delay;
+
+               txBarrier = call Config.getTransmitBarrier(msg);
+               delay = txBarrier - call RadioAlarm.getNow();
+
+               if( delay > 0 )
+               {
+                       if( state == STATE_READY )
+                       {
+                               call RadioAlarm.wait(delay);
+                               state = STATE_BARRIER;
+                       }
+                       else
+                               state |= STATE_BARRIER;
+               }
+
+               return signal RadioReceive.receive(msg);
+       }
+}
diff --git a/tos/chips/rf230/SlottedCollisionConfig.nc b/tos/chips/rf230/SlottedCollisionConfig.nc
new file mode 100644 (file)
index 0000000..4b6b993
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface SlottedCollisionConfig
+{
+       /**
+        * This command should return the approximate transmit delay between
+        * setting an alarm, waiting for the fire event, calling send and
+        * obtaining the timestamp for the transmitted message.
+        */
+       async command uint16_t getInitialDelay();
+
+       /**
+        * Must return a binary exponent so that the collision avoidance layer
+        * can assign slots in the range of [0, 1 << exponent) of size collision
+        * window.
+        */
+       async command uint8_t getScheduleExponent();
+
+       /**
+        * This command must return the time when the message was transmitted.
+        */
+       async command uint16_t getTransmitTime(message_t* msg);
+
+       /**
+        * Returns the start of the collision window for this received message,
+        * so transmit times in this range would be considered possible collisions.
+        */
+       async command uint16_t getCollisionWindowStart(message_t* msg);
+
+       /**
+        * Returns the size of the collision window for this received message.
+        */
+       async command uint16_t getCollisionWindowLength(message_t* msg);
+
+       /**
+        * This event should be called periodically to indicate the passing of
+        * time (maybe we should use a timer)
+        */
+       tasklet_async event void timerTick();
+}
diff --git a/tos/chips/rf230/SlottedCollisionLayerC.nc b/tos/chips/rf230/SlottedCollisionLayerC.nc
new file mode 100644 (file)
index 0000000..0028846
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration SlottedCollisionLayerC
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface SlottedCollisionConfig as Config;
+       }
+}
+
+implementation
+{
+       components SlottedCollisionLayerP, MainC, RadioAlarmC, RandomC;
+
+       RadioSend = SlottedCollisionLayerP;
+       RadioReceive = SlottedCollisionLayerP;
+       SubSend = SlottedCollisionLayerP;
+       SubReceive = SlottedCollisionLayerP;
+       Config = SlottedCollisionLayerP;
+       
+       SlottedCollisionLayerP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
+       SlottedCollisionLayerP.Random -> RandomC;
+       MainC.SoftwareInit -> SlottedCollisionLayerP;
+
+#ifdef RF230_DEBUG
+       components DiagMsgC;
+       SlottedCollisionLayerP.DiagMsg -> DiagMsgC;
+#endif
+}
diff --git a/tos/chips/rf230/SlottedCollisionLayerP.nc b/tos/chips/rf230/SlottedCollisionLayerP.nc
new file mode 100644 (file)
index 0000000..f9108ee
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module SlottedCollisionLayerP
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+               interface Init;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RadioAlarm;
+               interface Random;
+               interface SlottedCollisionConfig as Config;
+#ifdef RF230_DEBUG
+               interface DiagMsg;
+#endif
+       }
+}
+
+implementation
+{
+/* ----- random ----- */
+
+       uint16_t nextRandom;
+
+       task void calcNextRandom()
+       {
+               uint16_t a = call Random.rand16();
+               atomic nextRandom = a;
+       }
+
+       uint16_t getNextRandom()
+       {
+               uint16_t a;
+
+               atomic
+               {
+                       a = nextRandom;
+                       nextRandom += 273;
+               }
+               post calcNextRandom();
+
+               return a;
+       }
+
+/* ----- schedule selection ----- */
+
+       tasklet_async event bool SubReceive.header(message_t* msg)
+       {
+               return signal RadioReceive.header(msg);
+       }
+
+       // WARNING!!! Do not change these values, the error values can overflow
+       enum
+       {
+               ERROR_DECAY = 3,
+               ERROR_SWITCH = 30,              // should be a multiple of (1 << decay)
+               ERROR_COLLISION = 20,   // must be less than (255 - switch) >> decay
+               ERROR_BUSY = 1,                 // must be less than collision
+               ERROR_INITIAL = 80,             // must be less than giveup
+               ERROR_GIVEUP = 120,             // must be less than collision * (1 << decay)
+               ERROR_REPRESS = 40,             // must be more than switch
+               ERROR_MAX = 255,
+       };
+
+       /**
+        * Returns TRUE if time is between start and start + window 
+        * modulo the schedule size of (1 << exponent)
+        */
+       inline bool isBetween(uint8_t exponent, uint16_t time, uint16_t start, uint16_t length)
+       {
+               return (uint16_t)((time - start) & ((1 << exponent) - 1)) < length;
+       }
+
+       tasklet_norace uint16_t schedule1;
+       tasklet_norace uint16_t schedule2;
+
+       tasklet_norace uint8_t error1;
+       tasklet_norace uint8_t error2;
+
+       tasklet_async event message_t* SubReceive.receive(message_t* msg)
+       {
+               uint8_t exponent = call Config.getScheduleExponent();
+               uint16_t start = call Config.getCollisionWindowStart(msg);
+               uint16_t length = call Config.getCollisionWindowLength(msg);
+
+               error1 -= error1 >> ERROR_DECAY;
+               if( isBetween(exponent, schedule1, start, length) )
+                       error1 += ERROR_COLLISION; 
+
+               error2 -= error2 >> ERROR_DECAY;
+               if( isBetween(exponent, schedule2, start, length) )
+                       error2 += ERROR_COLLISION;
+
+               if( error2 + ERROR_SWITCH <= error1 )
+               {
+                       error1 = error2;
+                       schedule1 = schedule2;
+                       error2 = ERROR_GIVEUP;
+               }
+
+               if( error2 >= ERROR_GIVEUP )
+               {
+                       error2 = ERROR_INITIAL;
+                       schedule2 = getNextRandom();
+               }
+
+               return signal RadioReceive.receive(msg);
+       }
+
+       void printStats();
+
+       tasklet_async event void Config.timerTick()
+       {
+               if( error1 >= (1 << ERROR_DECAY) )
+                       error1 -= error1 >> ERROR_DECAY;
+               else if( error1 > 0 )
+                       --error1;
+
+               if( error2 >= (1 << ERROR_DECAY) )
+                       error2 -= error2 >> ERROR_DECAY;
+               else if( error2 > 0 )
+                       --error2;
+
+               printStats();
+       }
+
+/* ------ transmit ------ */
+
+       tasklet_norace uint8_t state;
+       enum
+       {
+               STATE_READY = 0,
+               STATE_PENDING = 1,
+               STATE_SENDING = 2,
+       };
+
+       enum { DELAY_DECAY = 2 };
+
+       tasklet_norace message_t *txMsg;
+       tasklet_norace uint16_t txDelay;        // the averaged delay between schedule and timestamp
+       tasklet_norace uint16_t txTime;         // the schedule time of transmission
+
+       tasklet_async event void SubSend.ready()
+       {
+               if( state == STATE_READY && call RadioAlarm.isFree() )
+                       signal RadioSend.ready();
+       }
+
+       tasklet_async command error_t RadioSend.send(message_t* msg)
+       {
+               uint16_t backoff;
+               uint16_t time;
+
+               // TODO: we could supress transmission while error is large
+               if( state != STATE_READY || ! call RadioAlarm.isFree() || error1 >= ERROR_REPRESS )
+                       return EBUSY;
+
+               txMsg = msg;
+               state = STATE_PENDING;
+
+               time = call RadioAlarm.getNow();
+               backoff = 1 + ((schedule1 - time - (txDelay >> DELAY_DECAY))
+                       & ((1 << call Config.getScheduleExponent()) - 1));
+
+               backoff += getNextRandom() & (3 << call Config.getScheduleExponent());
+
+               call RadioAlarm.wait(backoff);
+               txTime = time + backoff;
+
+               return SUCCESS;
+       }
+
+       tasklet_async event void RadioAlarm.fired()
+       {
+               error_t error;
+
+               ASSERT( state == STATE_PENDING );
+
+               error = call SubSend.send(txMsg);
+               if( error == SUCCESS )
+                       state = STATE_SENDING;
+               else
+               {
+                       if( error2 + ERROR_SWITCH <= error1 )
+                       {
+                               error1 = error2;
+                               schedule1 = schedule2;
+                               error2 = ERROR_INITIAL;
+                               schedule2 = getNextRandom();
+                       }
+                       else if( error1 < ERROR_MAX - ERROR_BUSY )
+                               error1 = error1 + ERROR_BUSY;
+
+                       state = STATE_READY;
+                       signal RadioSend.sendDone(error);
+               }
+       }
+
+       tasklet_async event void SubSend.sendDone(error_t error)
+       {
+               ASSERT( state == STATE_SENDING );
+
+               if( error == SUCCESS )
+               {
+                       txDelay += (call Config.getTransmitTime(txMsg) - txTime) - (txDelay >> DELAY_DECAY);
+
+                       ASSERT( (txDelay >> DELAY_DECAY) < (1 << call Config.getScheduleExponent()) );
+               }
+
+               state = STATE_READY;
+               signal RadioSend.sendDone(error);
+       }
+
+/* ------ init  ------ */
+
+       command error_t Init.init()
+       {
+               // do not use Random here because it might not be initialized
+               schedule1 = (uint16_t)(TOS_NODE_ID * 1973);
+               schedule2 = schedule1 + 0117;
+               txDelay = call Config.getInitialDelay() << DELAY_DECAY;
+
+               return SUCCESS;
+       }
+
+#ifdef RF230_DEBUG
+       tasklet_norace uint8_t count;
+       void printStats()
+       {
+               if( ++count > 10 && call DiagMsg.record() )
+               {
+                       count = 0;
+
+                       call DiagMsg.str("slotted");
+                       call DiagMsg.uint16(txDelay >> DELAY_DECAY);
+                       call DiagMsg.uint16(schedule1);
+                       call DiagMsg.uint8(error1);
+                       call DiagMsg.uint16(schedule2);
+                       call DiagMsg.uint8(error2);
+                       call DiagMsg.send();
+               }
+       }
+#else
+       void printStats() { }
+#endif
+}
diff --git a/tos/chips/rf230/SoftwareAckConfig.nc b/tos/chips/rf230/SoftwareAckConfig.nc
new file mode 100644 (file)
index 0000000..b3c87c7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface SoftwareAckConfig
+{
+       /**
+        * Returns the acknowledgement timeout (in the radio clock units),
+        * in which a sent packet must be acknowledged.
+        */
+       async command uint16_t getAckTimeout();
+
+       /**
+        * Returns TRUE if the layer should wait for a software acknowledgement
+        * to be received after this packet was transmitted.
+        */
+       async command bool requiresAckWait(message_t* msg);
+
+       /**
+        * Sets for the transmitted message whether it was acknowledged or not.
+        */
+       async command void setAckReceived(message_t* msg, bool acked);
+
+       /**
+        * Returns TRUE if the received packet is an acknowledgement packet.
+        * The AckedSend layer will filter out all received acknowledgement
+        * packets and uses  only the matching one for the acknowledgement.
+        */
+       async command bool isAckPacket(message_t* msg);
+
+       /**
+        * Returns TRUE if the acknowledgement packet corresponds to the
+        * data packet. The acknowledgement packect was already verified 
+        * to be a valid acknowledgement packet via the isAckPacket command.
+        */
+       async command bool verifyAckPacket(message_t* data, message_t* ack);
+
+       /**
+        * Returns TRUE if the received packet needs software acknowledgements
+        * to be sent back to the sender.
+        */
+       async command bool requiresAckReply(message_t* msg);
+
+       /**
+        * Creates an acknowledgement packet for the given data packet.
+        */
+       async command void createAckPacket(message_t* data, message_t* ack);
+
+       /**
+        * This command is called when a sent packet did not receive an
+        * acknowledgement.
+        */
+       tasklet_async command void reportChannelError();
+}
diff --git a/tos/chips/rf230/SoftwareAckLayerC.nc b/tos/chips/rf230/SoftwareAckLayerC.nc
new file mode 100644 (file)
index 0000000..97703e1
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration SoftwareAckLayerC
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+
+               interface SoftwareAckConfig as Config;
+       }
+}
+
+implementation
+{
+       components SoftwareAckLayerP, RadioAlarmC;
+
+       RadioSend = SoftwareAckLayerP;
+       RadioReceive = SoftwareAckLayerP;
+       SubSend = SoftwareAckLayerP;
+       SubReceive = SoftwareAckLayerP;
+       Config = SoftwareAckLayerP;
+
+       SoftwareAckLayerP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
+}
diff --git a/tos/chips/rf230/SoftwareAckLayerP.nc b/tos/chips/rf230/SoftwareAckLayerP.nc
new file mode 100644 (file)
index 0000000..51231b6
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module SoftwareAckLayerP
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RadioAlarm;
+
+               interface SoftwareAckConfig;
+       }
+}
+
+implementation
+{
+       tasklet_norace uint8_t state;
+       enum
+       {
+               STATE_READY = 0,
+               STATE_DATA_SEND = 1,
+               STATE_ACK_WAIT = 2,
+               STATE_ACK_SEND = 3,
+       };
+
+       tasklet_norace message_t *txMsg;
+       tasklet_norace message_t ackMsg;
+
+       tasklet_async event void SubSend.ready()
+       {
+               if( state == STATE_READY )
+                       signal RadioSend.ready();
+       }
+
+       tasklet_async command error_t RadioSend.send(message_t* msg)
+       {
+               error_t error;
+
+               if( state == STATE_READY )
+               {
+                       if( (error = call SubSend.send(msg)) == SUCCESS )
+                       {
+                               call SoftwareAckConfig.setAckReceived(msg, FALSE);
+                               state = STATE_DATA_SEND;
+                               txMsg = msg;
+                       }
+               }
+               else
+                       error = EBUSY;
+
+               return error;
+       }
+
+       tasklet_async event void SubSend.sendDone(error_t error)
+       {
+               if( state == STATE_ACK_SEND )
+               {
+                       // TODO: what if error != SUCCESS
+                       ASSERT( error == SUCCESS );
+
+                       state = STATE_READY;
+               }
+               else
+               {
+                       ASSERT( state == STATE_DATA_SEND );
+                       ASSERT( call RadioAlarm.isFree() );
+
+                       if( error == SUCCESS && call SoftwareAckConfig.requiresAckWait(txMsg) && call RadioAlarm.isFree() )
+                       {
+                               call RadioAlarm.wait(call SoftwareAckConfig.getAckTimeout());
+                               state = STATE_ACK_WAIT;
+                       }
+                       else
+                       {
+                               state = STATE_READY;
+                               signal RadioSend.sendDone(error);
+                       }
+               }
+       }
+
+       tasklet_async event void RadioAlarm.fired()
+       {
+               ASSERT( state == STATE_ACK_WAIT );
+
+               call SoftwareAckConfig.reportChannelError();
+
+               state = STATE_READY;
+               signal RadioSend.sendDone(SUCCESS);     // we have sent it, but not acked
+       }
+
+       tasklet_async event bool SubReceive.header(message_t* msg)
+       {
+               if( call SoftwareAckConfig.isAckPacket(msg) )
+                       return state == STATE_ACK_WAIT && call SoftwareAckConfig.verifyAckPacket(txMsg, msg);
+               else
+                       return signal RadioReceive.header(msg);
+       }
+
+       tasklet_async event message_t* SubReceive.receive(message_t* msg)
+       {
+               bool ack = call SoftwareAckConfig.isAckPacket(msg);
+
+               ASSERT( state == STATE_ACK_WAIT || state == STATE_READY );
+
+               if( state == STATE_ACK_WAIT )
+               {
+                       call RadioAlarm.cancel();
+                       call SoftwareAckConfig.setAckReceived(txMsg, ack);
+
+                       state = STATE_READY;
+                       signal RadioSend.sendDone(SUCCESS);
+               }
+
+               if( ack )
+                       return msg;
+
+               if( call SoftwareAckConfig.requiresAckReply(msg) )
+               {
+                       call SoftwareAckConfig.createAckPacket(msg, &ackMsg);
+
+                       // TODO: what to do if we are busy and cannot send an ack
+                       if( call SubSend.send(&ackMsg) == SUCCESS )
+                               state = STATE_ACK_SEND;
+                       else
+                               ASSERT(FALSE);
+               }
+
+               return signal RadioReceive.receive(msg);
+       }
+}
diff --git a/tos/chips/rf230/Tasklet.h b/tos/chips/rf230/Tasklet.h
new file mode 100644 (file)
index 0000000..38f185f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __TASKLET_H__
+#define __TASKLET_H__
+
+#ifdef TASKLET_IS_TASK
+
+       #define tasklet_async
+       #define tasklet_norace
+
+#else
+
+       #define tasklet_async   async   
+       #define tasklet_norace  norace
+
+#endif
+
+#endif//__RF230_H__
diff --git a/tos/chips/rf230/Tasklet.nc b/tos/chips/rf230/Tasklet.nc
new file mode 100644 (file)
index 0000000..527400a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/**
+ * This interface is useful in building state machines when the state 
+ * transitions should be executed atomically but with interrupts enabled. 
+ * All state transitions should take place in the run event handler or
+ * in blocks protected by the suspend and resume commands.
+ */
+interface Tasklet
+{
+       /**
+        * This method is executed atomically. 
+        */
+       tasklet_async event void run();
+
+       /**
+        * Makes sure that the run event is called at least once more. If the 
+        * run event is currently not executing, then it  is called immediately 
+        * and this command returns only after the completion of the run event. 
+        * If the run event is currently executed, then this method returns at 
+        * once, and makes sure that the run event is called once more when 
+        * it is finished. If this method is called from a task, then by the 
+        * above rules, the run event will be called from a task as well.
+        */
+       async command void schedule();
+
+       /**
+        * Enters a critical section of the code and meakes sure that the
+        * run event is not called while in this section. No long running
+        * computation should be called from the critical session, and
+        * in particular no user event should be fired. This call is only
+        * possible from task context, otherwise we cannot guarantee that
+        * the run event is not currently running. The suspend calls
+        * can be nested. It is very important that the same number of
+        * resume commands must be called in all control paths, e.g. be very
+        * careful with the return and break commands.
+        */
+       command void suspend();
+
+       /**
+        * Leaves the critical section. This call is conly possible from 
+        * task context. If there were scheduled executions of the run
+        * event, then those will be called before this command returns.
+        */
+       command void resume();
+}
diff --git a/tos/chips/rf230/TaskletC.nc b/tos/chips/rf230/TaskletC.nc
new file mode 100644 (file)
index 0000000..360f54f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module TaskletC
+{
+       provides interface Tasklet;
+}
+
+implementation
+{
+#ifdef TASKLET_IS_TASK
+
+       task void tasklet()
+       {
+               signal Tasklet.run();
+       }
+
+       inline async command void Tasklet.schedule()
+       {
+               post tasklet();
+       }
+
+       inline command void Tasklet.suspend()
+       {
+       }
+
+       inline command void Tasklet.resume()
+       {
+       }
+
+#else
+       
+       /**
+        * The lower 7 bits contain the number of suspends plus one if the run 
+        * event is currently beeing executed. The highest bit is set if the run 
+        * event needs to be called again when the suspend count goes down to zero.
+        */
+       uint8_t state;
+
+       void doit()
+       {
+               for(;;)
+               {
+                       signal Tasklet.run();
+
+                       atomic
+                       {
+                               if( state == 1 )
+                               {
+                                       state = 0;
+                                       return;
+                               }
+
+                               ASSERT( state == 0x81 );
+                               state = 1;
+                       }
+               }
+       }
+
+       inline command void Tasklet.suspend()
+       {
+               atomic ++state;
+       }
+
+       command void Tasklet.resume()
+       {
+               atomic
+               {
+                       if( --state != 0x80 )
+                               return;
+
+                       state = 1;
+               }
+
+               doit();
+       }
+
+       async command void Tasklet.schedule()
+       {
+               atomic
+               {
+                       if( state != 0 )
+                       {
+                               state |= 0x80;
+                               return;
+                       }
+
+                       state = 1;
+               }
+
+               doit();
+       }
+
+#endif
+}
diff --git a/tos/chips/rf230/TrafficMonitorConfig.nc b/tos/chips/rf230/TrafficMonitorConfig.nc
new file mode 100644 (file)
index 0000000..0b7bc64
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface TrafficMonitorConfig
+{
+       /**
+        * Returns the frequency (in milliseconds) when the traffic averages
+        * should be updated. 
+        */
+       async command uint16_t getUpdatePeriod();
+
+       /**
+        * Returns the amount of time this message has occupied the channel.
+        */
+       async command uint16_t getChannelTime(message_t* msg);
+
+       /**
+        * Returns the sender address of the message so we can calculate the
+        * average number of neighbors that send messages per update period.
+        */
+       async command am_addr_t getSender(message_t* msg);
+
+       /**
+        * This event should be fired if we notice some anomalies in the operation
+        * of the channel, such as not receiving acknowledgements, missing
+        * sequence numbers or packets with corrupted CRC.
+        */
+       tasklet_async event void channelError();
+
+       /**
+        * Returns the averaged (exponential decay) transmit channel time 
+        * during one update period.
+        */
+       tasklet_async event uint16_t getTransmitAverage();
+
+       /**
+        * Returns the averaged (exponential decay) receive channel time 
+        * during one update period.
+        */
+       tasklet_async event uint16_t getReceiveAverage();
+
+       /**
+        * Returns the averaged (exponential decay) number of neighbors 
+        * whose messages this component receives during one update period.
+        */
+       tasklet_async event uint8_t getNeighborAverage();
+
+       /**
+        * Returns the averaged error events during one update period.
+        */
+       tasklet_async event uint8_t getErrorAverage();
+
+       /**
+        * This command is periodically called when the timer is fired and
+        * the averages are updated
+        */
+       tasklet_async command void timerTick();
+}
diff --git a/tos/chips/rf230/TrafficMonitorLayerC.nc b/tos/chips/rf230/TrafficMonitorLayerC.nc
new file mode 100644 (file)
index 0000000..b144c8a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration TrafficMonitorLayerC
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+               interface RadioState;
+       }
+       uses
+       {
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RadioState as SubState;
+
+               interface TrafficMonitorConfig as Config;
+       }
+}
+
+implementation
+{
+       components TrafficMonitorLayerP, new TimerMilliC() as UpdateTimerC; 
+       components NeighborhoodC, new NeighborhoodFlagC(), TaskletC;
+
+       RadioSend = TrafficMonitorLayerP;
+       RadioReceive = TrafficMonitorLayerP;
+       RadioState = TrafficMonitorLayerP;
+       SubSend = TrafficMonitorLayerP;
+       SubReceive = TrafficMonitorLayerP;
+       SubState = TrafficMonitorLayerP;
+       Config = TrafficMonitorLayerP;
+
+       TrafficMonitorLayerP.Timer -> UpdateTimerC;
+       TrafficMonitorLayerP.Neighborhood -> NeighborhoodC;
+       TrafficMonitorLayerP.NeighborhoodFlag -> NeighborhoodFlagC;
+       TrafficMonitorLayerP.Tasklet -> TaskletC;
+
+#ifdef RF230_DEBUG
+       components DiagMsgC;
+       TrafficMonitorLayerP.DiagMsg -> DiagMsgC;
+#endif
+}
diff --git a/tos/chips/rf230/TrafficMonitorLayerP.nc b/tos/chips/rf230/TrafficMonitorLayerP.nc
new file mode 100644 (file)
index 0000000..75328ac
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, reportS, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/*
+ * You have to make sure that the maximum channel time in one report
+ * period times (1 << TRAFFIC_MONITOR_DECAY) is less than 65535.
+ */
+#ifndef TRAFFIC_MONITOR_DECAY
+#define TRAFFIC_MONITOR_DECAY  3
+#endif
+
+module TrafficMonitorLayerP
+{
+       provides
+       {
+               interface RadioSend;
+               interface RadioReceive;
+               interface RadioState;
+       }
+
+       uses
+       {
+               interface TrafficMonitorConfig;
+               interface RadioSend as SubSend;
+               interface RadioReceive as SubReceive;
+               interface RadioState as SubState;
+               interface Timer<TMilli> as Timer;
+               interface Neighborhood;
+               interface NeighborhoodFlag;
+               interface Tasklet;
+#ifdef RF230_DEBUG
+               interface DiagMsg;
+#endif
+       }
+}
+
+implementation
+{
+       tasklet_norace message_t *txMsg;
+       tasklet_norace uint8_t neighborCount;
+
+       tasklet_norace uint16_t txAverage;
+       tasklet_norace uint16_t rxAverage;
+       tasklet_norace uint8_t neighborAverage;
+       tasklet_norace uint8_t errorAverage;
+
+       enum
+       {
+               // the maximum average value
+               TRAFFIC_MONITOR_UINT8_MAX = 1 << (7-TRAFFIC_MONITOR_DECAY),
+
+               // the unsignificant bits of the averaged values
+               TRAFFIC_MONITOR_MASK = (1 << TRAFFIC_MONITOR_DECAY) - 1,
+
+               // to get the ceiling integer value
+               TRAFFIC_MONITOR_ROUND_UP = (1 << TRAFFIC_MONITOR_DECAY) - 1,
+       };
+
+       tasklet_async event void SubSend.ready()
+       {
+               signal RadioSend.ready();
+       }
+
+       tasklet_async command error_t RadioSend.send(message_t* msg)
+       {
+               txMsg = msg;
+               return call SubSend.send(msg);
+       }
+
+       tasklet_async event void SubSend.sendDone(error_t error)
+       {
+               if( error == SUCCESS )
+                       txAverage += call TrafficMonitorConfig.getChannelTime(txMsg);
+
+               signal RadioSend.sendDone(error);
+       }
+
+       tasklet_async event bool SubReceive.header(message_t* msg)
+       {
+               return signal RadioReceive.header(msg);
+       }
+
+       tasklet_async event message_t* SubReceive.receive(message_t* msg)
+       {
+               uint8_t index;
+
+               rxAverage += call TrafficMonitorConfig.getChannelTime(msg);
+
+               index = call Neighborhood.insertNode(call TrafficMonitorConfig.getSender(msg));
+               if( ! call NeighborhoodFlag.get(index) )
+               {
+                       if( neighborCount < TRAFFIC_MONITOR_UINT8_MAX )
+                       {
+                               ++neighborCount;
+                               call NeighborhoodFlag.set(index);
+                       }
+               }
+
+               return signal RadioReceive.receive(msg);
+       }
+
+       tasklet_async event void TrafficMonitorConfig.channelError()
+       {
+               if( errorAverage < 255 )
+                       ++errorAverage;
+       }
+
+       uint8_t debugCounter;
+
+       event void Timer.fired()
+       {
+               uint8_t fraction;
+
+               call Tasklet.suspend();
+
+               txAverage -= (txAverage >> TRAFFIC_MONITOR_DECAY);
+               rxAverage -= (rxAverage >> TRAFFIC_MONITOR_DECAY);
+               errorAverage -= (errorAverage >> TRAFFIC_MONITOR_DECAY);
+
+               // we could get stuck in the [1,7] range with no neighbors, so be more precise
+               fraction = neighborAverage >> TRAFFIC_MONITOR_DECAY;
+               if( fraction == neighborCount && (neighborAverage & TRAFFIC_MONITOR_MASK) != 0 )
+                       --neighborAverage;
+               else
+                       neighborAverage += neighborCount - fraction;
+
+               call NeighborhoodFlag.clearAll();
+               neighborCount = 0;
+
+               call TrafficMonitorConfig.timerTick();
+
+               call Tasklet.resume();
+
+#ifdef RF230_DEBUG
+               if( ++debugCounter >= 10 && call DiagMsg.record() )
+               {
+                       debugCounter = 0;
+
+                       call DiagMsg.str("traffic");
+                       call DiagMsg.uint16(signal TrafficMonitorConfig.getTransmitAverage());
+                       call DiagMsg.uint16(signal TrafficMonitorConfig.getReceiveAverage());
+                       call DiagMsg.uint8(signal TrafficMonitorConfig.getNeighborAverage());
+                       call DiagMsg.uint8(signal TrafficMonitorConfig.getErrorAverage());
+                       call DiagMsg.send();
+               }
+#endif
+       }
+
+       tasklet_async event void Tasklet.run()
+       {
+       }
+
+       tasklet_async event uint16_t TrafficMonitorConfig.getTransmitAverage()
+       {
+               return txAverage >> TRAFFIC_MONITOR_DECAY;
+       }
+
+       tasklet_async event uint16_t TrafficMonitorConfig.getReceiveAverage()
+       {
+               return rxAverage >> TRAFFIC_MONITOR_DECAY;
+       }
+
+       tasklet_async event uint8_t TrafficMonitorConfig.getNeighborAverage()
+       {
+               return (neighborAverage + TRAFFIC_MONITOR_ROUND_UP) >> TRAFFIC_MONITOR_DECAY;
+       }
+
+       tasklet_async event uint8_t TrafficMonitorConfig.getErrorAverage()
+       {
+               return errorAverage >> TRAFFIC_MONITOR_DECAY;
+       }
+
+       tasklet_async event void Neighborhood.evicted(uint8_t index) { }
+
+       enum
+       {
+               RADIO_CMD_NONE = 0,
+               RADIO_CMD_TURNON = 1,
+               RADIO_CMD_TURNOFF = 2,
+       };
+       tasklet_norace uint8_t radioCmd;
+
+       tasklet_async command error_t RadioState.turnOff()
+       {
+               radioCmd = RADIO_CMD_TURNOFF;
+               return call SubState.turnOff();
+       }
+
+       tasklet_async command error_t RadioState.standby()
+       {
+               radioCmd = RADIO_CMD_TURNOFF;
+               return call SubState.standby();
+       }
+
+       tasklet_async command error_t RadioState.turnOn()
+       {
+               radioCmd = RADIO_CMD_TURNON;
+               return call SubState.turnOn();
+       }
+
+       tasklet_async command error_t RadioState.setChannel(uint8_t channel)
+       {
+               radioCmd = RADIO_CMD_NONE;
+               return call SubState.setChannel(channel);
+       }
+
+       task void startStopTimer()
+       {
+               if( radioCmd == RADIO_CMD_TURNON )
+                       call Timer.startPeriodic(call TrafficMonitorConfig.getUpdatePeriod());
+               else if( radioCmd == RADIO_CMD_TURNOFF )
+                       call Timer.stop();
+       }
+
+       tasklet_async event void SubState.done()
+       {
+               post startStopTimer();
+               signal RadioState.done();
+       }
+}
diff --git a/tos/chips/rf230/UniqueConfig.nc b/tos/chips/rf230/UniqueConfig.nc
new file mode 100644 (file)
index 0000000..5f14c52
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface UniqueConfig
+{
+       /**
+        * Returns the sequence number of the packet.
+        */
+       async command uint8_t getSequenceNumber(message_t* msg);
+
+       /**
+        * Returns the sender of the packet. 
+        */
+       async command am_addr_t getSender(message_t* msg);
+
+       /**
+        * Sets the sequence number of the packet.
+        */
+       async command void setSequenceNumber(message_t*msg, uint8_t number);
+
+       /**
+        * This command is called when the unqiue layer detects a missing (jump 
+        * in the data sequence number) or a duplicate packet.
+        */
+       tasklet_async command void reportChannelError();
+}
diff --git a/tos/chips/rf230/UniqueLayerC.nc b/tos/chips/rf230/UniqueLayerC.nc
new file mode 100644 (file)
index 0000000..5d2e5f2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration UniqueLayerC
+{
+       provides
+       {
+               // NOTE, this is a combined layer, should be hooked up at two places
+               interface Send;
+               interface RadioReceive;
+       }
+       uses
+       {
+               interface Send as SubSend;
+               interface RadioReceive as SubReceive;
+
+               interface UniqueConfig as Config;
+       }
+}
+
+implementation
+{
+       components UniqueLayerP, MainC, NeighborhoodC, new NeighborhoodFlagC();
+
+       MainC.SoftwareInit -> UniqueLayerP;
+       UniqueLayerP.Neighborhood -> NeighborhoodC;
+       UniqueLayerP.NeighborhoodFlag -> NeighborhoodFlagC;
+
+       Send = UniqueLayerP;
+       SubSend = UniqueLayerP;
+
+       RadioReceive = UniqueLayerP;
+       SubReceive = UniqueLayerP;
+       Config = UniqueLayerP;
+}
diff --git a/tos/chips/rf230/UniqueLayerP.nc b/tos/chips/rf230/UniqueLayerP.nc
new file mode 100644 (file)
index 0000000..d341942
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <Neighborhood.h>
+
+module UniqueLayerP
+{
+       provides
+       {
+               interface Send;
+               interface RadioReceive;
+
+               interface Init;
+       }
+
+       uses
+       {
+               interface Send as SubSend;
+               interface RadioReceive as SubReceive;
+
+               interface UniqueConfig;
+               interface Neighborhood;
+               interface NeighborhoodFlag;
+       }
+}
+
+implementation
+{
+       uint8_t sequenceNumber;
+
+       command error_t Init.init()
+       {
+               sequenceNumber = TOS_NODE_ID << 4;
+               return SUCCESS;
+       }
+
+       command error_t Send.send(message_t* msg, uint8_t len)
+       {
+               call UniqueConfig.setSequenceNumber(msg, ++sequenceNumber);
+               return call SubSend.send(msg, len);
+       }
+
+       command error_t Send.cancel(message_t* msg)
+       {
+               return call SubSend.cancel(msg);
+       }
+
+       event void SubSend.sendDone(message_t* msg, error_t error)
+       {
+               signal Send.sendDone(msg, error);
+       }
+
+       command uint8_t Send.maxPayloadLength()
+       {
+               return call SubSend.maxPayloadLength();
+       }
+
+       command void* Send.getPayload(message_t* msg, uint8_t len)
+       {
+               return call SubSend.getPayload(msg, len);
+       }
+
+       tasklet_async event bool SubReceive.header(message_t* msg)
+       {
+               // we could scan here, but better be lazy
+               return signal RadioReceive.header(msg);
+       }
+
+       tasklet_norace uint8_t receivedNumbers[NEIGHBORHOOD_SIZE];
+
+       tasklet_async event message_t* SubReceive.receive(message_t* msg)
+       {
+               uint8_t index = call Neighborhood.insertNode(call UniqueConfig.getSender(msg));
+               uint8_t dsn = call UniqueConfig.getSequenceNumber(msg);
+
+               if( call NeighborhoodFlag.get(index) )
+               {
+                       uint8_t diff = dsn - receivedNumbers[index];
+
+                       if( diff == 0 )
+                       {
+                               call UniqueConfig.reportChannelError();
+                               return msg;
+                       }
+               }
+               else
+                       call NeighborhoodFlag.set(index);
+
+               receivedNumbers[index] = dsn;
+
+               return signal RadioReceive.receive(msg);
+       }
+
+       tasklet_async event void Neighborhood.evicted(uint8_t index) { }
+}
diff --git a/tos/chips/rf230/notes.txt b/tos/chips/rf230/notes.txt
new file mode 100644 (file)
index 0000000..b5bdd65
--- /dev/null
@@ -0,0 +1,113 @@
+
+1. to support multiple sends through the ascynronous radio send interface 
+the send() must return error_t to indicate it cannot service more
+
+2. to have guaranteed timing we need guaranteed access to the send interface, 
+so we cannot have multiple sends through the radio send interface.
+
+3. time critical tasks:
+       CCA -> TX-DATA
+       RX-DATA -> TX-ACK
+       TX-DATA -> RX-ACK
+
+4. after the CCA we need to send data, but then TX-DATA cannot wait for the
+completion of a receieved packet (maybe we should), so maybe we should not
+have concurrent receives with everything else, enable receive only when 
+needed
+
+5. if there are no multiple sends in the radio send interface, then to have 
+robustness, the separate interfaces should record the requests until they are 
+ready to service them 
+
+6. to support receiving messages in the TX-DATA -> RX-ACK gap that need to be 
+acknowledged we must have a TX-ACK queue (we do not want to saturate the 
+channel while waiting for ACK). If this gap is large, then many messages 
+could accumulate that have not been acked, which can get out of control
+
+7. for low power listeing the TX-DATA -> RX-ACK -> TX-DATA gap should be 
+minimal to have the best duty cycle possible (maybe with a pair of CCA 
+checks it is possible to cover the gap).
+
+8. if only single requests are serviced by the radio send interface, then
+there is no need for the message pointer in the sendDone event.
+
+9. the receive buffer cannot service the higher layer via the asynchronous
+radio receive interface (or there should be another buffering down the road)
+that is pumped with a task. Also, the sendDone event must be fired from a
+task too.
+
+10. if a valid packet is received in the TX-DATA -> RX-ACK gap, then we could
+fail the TX-DATA but accept the RX-DATA. This requires two events to be 
+fiered: sendDone(FAIL) and receive(msg). We cannot fire the sendDone first
+because then our component does not become ready, and the higher layer might
+want to transmit again instead of listening (needs buffering) 
+
+11. four ways to handle the receive data while waiting for ACK problem 
+  a) drop these packets, 
+  b) drop only those that need acknowledgements, 
+  c) buffer them at the acked send layer (needs message_t) and deliver them
+     when receiving is allowed again
+  d) deliver them before signaling the sendDone(FAIL), but then we have to 
+     allow concurrent receives with sends
+
+12. It is very problematic to receive unexpected packets, what to do with 
+these? They could occur in the following gaps
+  a) CCA -> TX-DATA
+  b) RX-DATA -> TX-ACK
+  c) TX-DATA -> RX-ACK
+
+13. The hidden terminal problem can occur at 12b), i.e. NodeA transmits that 
+is received by NodeB but not heard by NodeC, which starts to transmit before 
+NodeB could send an acknowledgment. 
+
+14. with dedicated receive start calls, 
+   a) we could set the channel there, 
+   b) would have no problem with unexpected receives
+   c) could set a timeout parameter
+   d) need cancel command in the asynchronous receive interface
+   e) after receive we could go to PLL_ON state, could always download frame
+
+15. async send done could return an error code to indicate that something 
+went wrong, for example the CCA did not complete or the channel was busy
+
+16. If we want to cancel the receive process, then it is not clear what to do
+in the BUSY_RX case. We could either go with FORCE_TRX_OFF and then PLL_ON, 
+or do a PLL_ON and wait for the completion of the received message. Therefore
+once we are in the RX_ON state, we cannot guarantee to start TX_ON precisely. 
+We need to verify this.
+
+17. We need to transmit and cancel the listening process because of user 
+input. The listening cancelling is not atomic (we might need to receive 
+messages) and then send acknowledgment etc. Either we are always listening
+(conccurent receive / transmit) or call cancel and wait for receive(ECANCEL).
+
+18. The CC2420 has a receive queue, that needs to be flushed. This mean that 
+we might not able to prevent more than one message to arrive when listening.
+So we are either always on, or need purge functionality to receive all 
+messages from the receive queue.
+
+19. The RF230 does not support promisculous mode, so in general we cannot
+use the hardware TX-ACK feature with the RX_AACK command.
+
+20. With software acknowledgements on the RF230 we cannot reply to a RX-DATA
+with a TX-ACK faster than at least 200 microsec, because we need to download
+the full frame, check the CRC and only then we can send the ACK to avoid
+acking corrupted frames. This means that item 13 is a real problem, and we
+should go with item 11 d). Receiving a data packet while waiting for an ACK
+should fail the previous transmission and send an ack for the incoming frame.
+
+21. We cannot receive a message while a transmission is in progress because
+what would an ack layer do in this case? It cannot send the acknowledgment
+because a send is in progress. So send should return an error_t and while
+a send is in progress no receive is going to be fired.
+
+22. If we use dedicated receive start calls, then an uxpected message can
+arrive (such as when waiting for ACK but getting some DATA), in which case
+the returned message_t pointer might be something else than the one with
+which the receive command was called. So in this case we need to return
+the message with the messageDone event.
+
+23. What do we do with a received DATA packet while waiting for an ACK
+packet? We cannot signal higher layers that we have received it because
+the receive command was not called, so we have to buffer it, which can
+be problematic.
diff --git a/tos/lib/diagmsg/Assert.h b/tos/lib/diagmsg/Assert.h
new file mode 100644 (file)
index 0000000..b54675c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __ASSERT_H__
+#define __ASSERT_H__
+
+#ifdef ASSERT_NONE
+
+       #define ASSERT(COND) for(;0;)
+
+#else
+
+       void assert(bool condition, const char* file, uint16_t line);
+       #define ASSERT(COND) assert(COND, __FILE__, __LINE__)
+
+#endif
+
+#endif//__ASSERT_H__
diff --git a/tos/lib/diagmsg/AssertC.nc b/tos/lib/diagmsg/AssertC.nc
new file mode 100644 (file)
index 0000000..56808c8
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration AssertC
+{
+}
+
+implementation
+{
+#ifndef ASSERT_NONE
+
+       components AssertP, DiagMsgC;
+       AssertP.DiagMsg -> DiagMsgC;
+
+#endif
+}
diff --git a/tos/lib/diagmsg/AssertP.nc b/tos/lib/diagmsg/AssertP.nc
new file mode 100644 (file)
index 0000000..c963184
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+module AssertP
+{
+       uses interface DiagMsg;
+}
+
+implementation
+{
+       void assert(bool condition, const char* file, uint16_t line) __attribute__((noinline)) @C() @spontaneous()
+       {
+               if( ! condition && call DiagMsg.record() )
+               {
+                       uint8_t del = 0;
+                       uint8_t len = 0;
+
+                       while( file[len] != 0 )
+                       {
+                               if( file[len] == '\\' || file[len] == '/' )
+                                       del = len + 1;
+
+                               ++len;
+                       }
+
+                       file += del;
+
+                       call DiagMsg.str("assert");
+                       call DiagMsg.str(file);
+                       call DiagMsg.uint16(line);
+                       call DiagMsg.send();
+               }
+       }
+}
diff --git a/tos/lib/diagmsg/DiagMsg.nc b/tos/lib/diagmsg/DiagMsg.nc
new file mode 100644 (file)
index 0000000..4e91076
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002-2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+/**
+ * The DiagMsg interface allows messages to be sent back to the base station
+ * containing several values and their type information, like in 
+ * <code>printf(...)</code>. The base station must be connected to a PC using 
+ * a serial cable. On the PC a Java application (net.tinyos.util.DiagMsg) 
+ * decodes the message and displays its content using the correct type 
+ * information. See the implementation for the format of the message.
+ */
+interface DiagMsg
+{
+       /**
+        * Initiates the recording of a new DiagMsg. It returns FALSE if
+        * the component is busy recording or sending another message.
+        */
+       async command bool record();
+
+       /**
+        * Adds a new value to the end of the message. If the message 
+        * cannot hold more information, then the new value is simply dropped.
+        */
+       async command void int8(int8_t value);
+       async command void uint8(uint8_t value);
+       async command void hex8(uint8_t value);
+       async command void int16(int16_t value);
+       async command void uint16(uint16_t value);
+       async command void hex16(uint16_t value);
+       async command void int32(int32_t value);
+       async command void int64(int64_t value);
+       async command void uint64(uint64_t value);
+       async command void uint32(uint32_t value);
+       async command void hex32(uint32_t value);
+       async command void real(float value);
+       async command void chr(char value);
+
+       /**
+        * Adds an array of values to the end of the message. 
+        * The maximum length of the array is <code>15</code>.
+        * If the message cannot hold all elements of the array,
+        * then no value is stored.
+        */
+       async command void int8s(const int8_t *value, uint8_t len);
+       async command void uint8s(const uint8_t *value, uint8_t len);
+       async command void hex8s(const uint8_t *value, uint8_t len);
+       async command void int16s(const int16_t *value, uint8_t len);
+       async command void uint16s(const uint16_t *value, uint8_t len);
+       async command void hex16s(const uint16_t *value, uint8_t len);
+       async command void int32s(const int32_t *value, uint8_t len);
+       async command void uint32s(const uint32_t *value, uint8_t len);
+       async command void hex32s(const uint32_t *value, uint8_t len);
+       async command void int64s(const int64_t *value, uint8_t len);
+       async command void uint64s(const uint64_t *value, uint8_t len);
+       async command void reals(const float *value, uint8_t len);
+       async command void chrs(const char *value, uint8_t len);
+
+       /**
+        * This is a shorthand method for <code>chrs</code>
+        */
+       async command void str(const char* value);
+
+       /**
+        * Initiates the sending of the recorded message. 
+        */
+       async command void send();
+}
diff --git a/tos/lib/diagmsg/DiagMsg.txt b/tos/lib/diagmsg/DiagMsg.txt
new file mode 100644 (file)
index 0000000..98a7f23
--- /dev/null
@@ -0,0 +1,64 @@
+DiagMsg:
+
+Author/Contact: miklos.maroti@vanderbilt.edu (Miklos Maroti, ISIS, Vanderbilt)
+
+DESCRIPTION:
+
+The DiagMsg component allows messages to be sent back to the base station 
+containing several diagnostic or debugging values together with their type 
+information. The base station must run the GenericBase or TOSBase application 
+which forwards all messages to a PC connected to the base station. A java 
+programm (PrintDiagMsgs) displays the messages on the screen according to 
+the formating rules contained in the message.
+
+The following data types are supported: 1,2, 4 and 8 byte long signed, unsigned and 
+hexadecimal integers, characters, floating point numbers, strings and arrays 
+of the previous types (of length up to 15). Each field requires an additional 
+4 bit type descriptor.
+
+USAGE:
+
+When you want to report some data, write code something like this:
+
+       if( call DiagMsg.record() )
+       {
+               call DiagMsg.str("test");
+               call DiagMsg.uint8(17);
+               call DiagMsg.int16(1973);
+               call DiagMsg.real(12.345);
+               call DiagMsg.chr('Z');
+               call DiagMsg.uint32(123456789);
+               call DiagMsg.send();
+       }
+
+The DiagMsg component will record the message and will send it as soon 
+as possible. You can record up to 29 bytes of data in a single message.
+Each field uses and additional 4-bit type descriptor. For arrays, including
+strings, there is an additional 1-byte length descriptor as well. The diag 
+message above, for example, uses
+
+       5+1+1+2+4+1+4+7*0.5 = 21.5
+
+that is 22 bytes. If the message cannot hold more fields, then additional 
+fields will be silently ignored. 
+
+THE JAVA PROGRAM:
+
+The java program (DiagMsgs) displays each DiagMsg in a line. The program 
+can connect to a SerialForward application, or can use the serial port directly.
+
+TUNABLE PARAMETERS:
+
+The DiagMsg component can be configured by defining the following values in 
+your make file:
+
+DIAGMSG_BASE_STATION: The node ID of the base station or 0xFFFF to broadcast
+the message. The default value is to broadcast the message.
+
+DIAGMSG_RETRY_COUNT: The DiagMsg component will retry messages this many times 
+before dropping them. The base station must acknowledge them (this is done 
+automatically).
+
+DIAGMSG_RECORDED_MSGS: The DiagMsg component keeps an internal buffer of this 
+many messages. This allows sending several small messages without waiting for 
+their completion.
diff --git a/tos/lib/diagmsg/DiagMsgC.nc b/tos/lib/diagmsg/DiagMsgC.nc
new file mode 100644 (file)
index 0000000..5d53fa9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002-2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration DiagMsgC
+{
+       provides interface DiagMsg;
+}
+
+implementation 
+{
+#ifdef DIAGMSG_NONE
+
+components NoDiagMsgC;
+       DiagMsg = NoDiagMsgC;
+
+#else
+
+       enum
+       {
+               AM_DIAG_MSG = 0xB1,
+       };
+
+       components DiagMsgM, MainC, SerialActiveMessageC;
+
+       DiagMsg = DiagMsgM.DiagMsg;
+
+       MainC.SoftwareInit -> DiagMsgM.Init;
+       DiagMsgM.AMSend -> SerialActiveMessageC.AMSend[AM_DIAG_MSG];
+       DiagMsgM.Packet -> SerialActiveMessageC;
+
+#endif
+}
diff --git a/tos/lib/diagmsg/DiagMsgM.nc b/tos/lib/diagmsg/DiagMsgM.nc
new file mode 100644 (file)
index 0000000..669a04b
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2002-2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <message.h>
+
+module DiagMsgM
+{
+       provides 
+       {
+               interface DiagMsg;
+               interface Init;
+       }
+
+       uses 
+       {
+               interface AMSend;
+               interface Packet;
+       }
+}
+
+#ifndef DIAGMSG_BASE_STATION
+#define        DIAGMSG_BASE_STATION    AM_BROADCAST_ADDR
+#endif
+
+#ifndef DIAGMSG_RETRY_COUNT
+#define        DIAGMSG_RETRY_COUNT     2
+#endif
+
+#ifndef DIAGMSG_RECORDED_MSGS
+#define DIAGMSG_RECORDED_MSGS  10
+#endif
+
+implementation
+{
+       enum
+       {
+               STATE_READY = 1,
+               STATE_RECORDING_FIRST = 2,      // recording the first 4-bit descriptor
+               STATE_RECORDING_SECOND = 3,     // recording the second 4-bit descriptor
+               STATE_MSG_FULL = 4,
+               STATE_BUFFER_FULL = 5,
+       };
+
+       norace volatile uint8_t state;  // the state of the recording
+
+       message_t msgs[DIAGMSG_RECORDED_MSGS];  // circular buffer of messages
+
+       norace message_t *recording;    // the message that is beeing or going to be recorded
+       message_t *sending;     // the message that is beeing sent, or the null pointer
+
+       norace uint8_t nextData;        // points to the next unsued byte
+       norace uint8_t prevType;        // points to the type descriptor
+       norace uint8_t retries; // number of remaining retries
+
+       command error_t Init.init()
+       {
+               state = STATE_READY;
+               recording = msgs;
+               sending = 0;
+
+               return SUCCESS;
+       }
+
+       // two type fields are stored in on byte
+       enum
+       {
+               TYPE_END = 0,
+               TYPE_INT8 = 1,
+               TYPE_UINT8 = 2,
+               TYPE_HEX8 = 3,
+               TYPE_INT16 = 4,
+               TYPE_UINT16 = 5,
+               TYPE_HEX16 = 6,
+               TYPE_INT32 = 7,
+               TYPE_UINT32 = 8,
+               TYPE_HEX32 = 9,
+               TYPE_FLOAT = 10,
+               TYPE_CHAR = 11,
+               TYPE_INT64 = 12,
+               TYPE_UINT64 = 13,
+               TYPE_ARRAY = 15,
+       };
+
+/*
+       The format of the payload is as follows: 
+       
+       Each value has an associated data type descriptor. The descriptor takes 4-bits,
+       and two descriptors are packed into one byte. The double-descriptor is followed
+       by the data bytes needed to store the corresponding value. Two sample layouts are:
+
+       [D2, D1] [V1] ... [V1] [V2] ... [V2]
+       [D2, D1] [V1] ... [V1] [V2] ... [V2] [0, D3] [V3] ... [V3]
+
+       where D1, D2, D3 denotes the data type descriptors, and V1, V2 and V3
+       denotes the bytes where the corresponding values are stored. If there is an odd
+       number of data descriptors, then a zero data descriptor <code>TYPE_END</code> 
+       is inserted.
+
+       Each data type (except arrays) uses a fixed number of bytes to store the value.
+       For arrays, the first byte of the array holds the data type of the array (higer
+       4 bits) and the length of the array (lower 4 bits). The actual data follows 
+       this first byte.
+*/
+
+       async command bool DiagMsg.record()
+       {
+               atomic
+               {
+                       // currently recording or no more space
+                       if( state != STATE_READY )
+                               return FALSE;
+
+                       state = STATE_RECORDING_FIRST;
+                       nextData = 0;
+               }
+
+               return TRUE;
+       }
+
+       /**
+        * Allocates space in the message for <code>size</code> bytes
+        * and sets the type information to <code>type</code>. 
+        * Returns the index in <code>msg.data</code> where the data 
+        * should be stored or <code>-1</code> if no more space is avaliable.
+        */
+       int8_t allocate(uint8_t size, uint8_t type)
+       {
+               int8_t ret = -1;
+
+               if( state == STATE_RECORDING_FIRST )
+               {
+                       if( nextData + 1 + size <= TOSH_DATA_LENGTH )
+                       {
+                               state = STATE_RECORDING_SECOND;
+
+                               prevType = nextData++;
+                               ((uint8_t*) &(recording->data))[prevType] = type;
+                               ret = nextData;
+                               nextData += size;
+                       }
+                       else
+                               state = STATE_MSG_FULL;
+               }
+               else if( state == STATE_RECORDING_SECOND )
+               {
+                       if( nextData + size <= TOSH_DATA_LENGTH )
+                       {
+                               state = STATE_RECORDING_FIRST;
+
+                               ((uint8_t*) &(recording->data))[prevType] += (type << 4);
+                               ret = nextData;
+                               nextData += size;
+                       }
+                       else
+                               state = STATE_MSG_FULL;
+               }
+
+               return ret;
+       }
+
+#define IMPLEMENT(NAME, TYPE, TYPE2) \
+       async command void DiagMsg.NAME(TYPE value) \
+       { \
+               int8_t start = allocate(sizeof(TYPE), TYPE2); \
+               if( start >= 0 ) \
+                       *(TYPE*)((uint8_t*) &(recording->data) + start) = value; \
+       } \
+       async command void DiagMsg.NAME##s(const TYPE *value, uint8_t len) \
+       { \
+               int8_t start; \
+               if( len > 15 ) len = 15; \
+               start = allocate(sizeof(TYPE)*len + 1, TYPE_ARRAY); \
+               if( start >= 0 ) \
+               { \
+                       ((uint8_t*) &(recording->data))[start++] = (TYPE2 << 4) + len; \
+                       while( len-- != 0 ) \
+                               ((TYPE*)((uint8_t*) &(recording->data) + start))[len] = value[len]; \
+               } \
+       }
+
+       IMPLEMENT(int8, int8_t, TYPE_INT8)
+       IMPLEMENT(uint8, uint8_t, TYPE_UINT8)
+       IMPLEMENT(hex8, uint8_t, TYPE_HEX8)
+       IMPLEMENT(int16, int16_t, TYPE_INT16)
+       IMPLEMENT(uint16, uint16_t, TYPE_UINT16)
+       IMPLEMENT(hex16, uint16_t, TYPE_HEX16)
+       IMPLEMENT(int32, int32_t, TYPE_INT32)
+       IMPLEMENT(uint32, uint32_t, TYPE_UINT32)
+       IMPLEMENT(hex32, uint32_t, TYPE_HEX32)
+       IMPLEMENT(int64, int64_t, TYPE_INT64)
+       IMPLEMENT(uint64, uint64_t, TYPE_UINT64)
+       IMPLEMENT(real, float, TYPE_FLOAT)
+       IMPLEMENT(chr, char, TYPE_CHAR)
+
+       async command void DiagMsg.str(const char* str)
+       {
+               int8_t len = 0;
+               while( str[len] != 0 && len < 15 )
+                       ++len;
+               
+               call DiagMsg.chrs(str, len);
+       }
+
+       // TODO: this is a hack because setPayloadLength should be async
+       inline void setPayloadLength(message_t* msg, uint8_t length)
+       {
+               (*(uint8_t*) &(msg->header)) = length;
+       }
+
+       inline uint8_t getPayloadLength(message_t* msg)
+       {
+               return *(uint8_t*) &(msg->header);
+       }
+
+       task void send()
+       {
+               message_t* msg;
+
+               atomic msg = sending;
+
+               if( call AMSend.send(DIAGMSG_BASE_STATION, msg, getPayloadLength(msg)) != SUCCESS )
+                       post send();
+       }
+
+       // calculates the next message_t pointer in the <code>msgs</code> circular buffer
+       static inline message_t* nextPointer(message_t* ptr)
+       {
+               if( ++ptr >= msgs + DIAGMSG_RECORDED_MSGS )
+                       return msgs;
+               else
+                       return ptr;
+       }
+
+       async command void DiagMsg.send()
+       {
+               // no message recorded
+               if( state == STATE_READY )
+                       return;
+
+               // store the length
+               setPayloadLength(recording, nextData);
+
+               atomic
+               {
+                       if( sending == 0 )
+                       {
+                               sending = recording;
+                               retries = DIAGMSG_RETRY_COUNT;
+                               post send();
+                       }
+       
+                       recording = nextPointer(recording);
+
+                       if( recording == sending )
+                               state = STATE_BUFFER_FULL;
+                       else
+                               state = STATE_READY;
+               }
+       }
+
+       event void AMSend.sendDone(message_t* p, error_t error)
+       {
+               atomic
+               {
+                       // retry if not successful
+                       if( error != SUCCESS && --retries > 0 )
+                               post send();
+                       else
+                       {
+                               p = nextPointer(sending);
+                               if( p != recording )
+                               {
+                                       sending = p;
+                                       retries = DIAGMSG_RETRY_COUNT;
+                                       post send();
+                               }
+                               else
+                               {
+                                       sending = 0;
+
+                                       if( state == STATE_BUFFER_FULL )
+                                       {
+                                               state = STATE_READY;
+                                               if( call DiagMsg.record() )
+                                               {
+                                                       call DiagMsg.str("DiagMsgOverflow");
+                                                       call DiagMsg.send();
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
diff --git a/tos/lib/diagmsg/NoDiagMsgC.nc b/tos/lib/diagmsg/NoDiagMsgC.nc
new file mode 100644 (file)
index 0000000..b638c53
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003-2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+module NoDiagMsgC
+{
+       provides interface DiagMsg;
+}
+
+implementation
+{
+       async command bool DiagMsg.record()
+       {
+               return FALSE;
+       }
+
+#define IMPLEMENT(NAME, TYPE, TYPE2) \
+       async command void DiagMsg.NAME(TYPE value) { } \
+       async command void DiagMsg.NAME##s(const TYPE *value, uint8_t len) { }
+
+       IMPLEMENT(int8, int8_t, TYPE_INT8)
+       IMPLEMENT(uint8, uint8_t, TYPE_UINT8)
+       IMPLEMENT(hex8, uint8_t, TYPE_HEX8)
+       IMPLEMENT(int16, int16_t, TYPE_INT16)
+       IMPLEMENT(uint16, uint16_t, TYPE_UINT16)
+       IMPLEMENT(hex16, uint16_t, TYPE_HEX16)
+       IMPLEMENT(int32, int32_t, TYPE_INT32)
+       IMPLEMENT(uint32, uint32_t, TYPE_UINT32)
+       IMPLEMENT(hex32, uint32_t, TYPE_HEX32)
+       IMPLEMENT(int64, int64_t, TYPE_INT64)
+       IMPLEMENT(uint64, uint64_t, TYPE_UINT64)
+       IMPLEMENT(real, float, TYPE_FLOAT)
+       IMPLEMENT(chr, char, TYPE_CHAR)
+
+       async command void DiagMsg.str(const char* str) { }
+       async command void DiagMsg.send() { }
+}
diff --git a/tos/platforms/iris/.platform b/tos/platforms/iris/.platform
new file mode 100644 (file)
index 0000000..9943593
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# FILE: micaz/.platform
+# 
+# Includes that should take precedence come first.  Platforms come before
+# chips because they may override files.  These must be specified as
+# @includes instead of -I's to @opts, otherwise the %T won't be processed
+# by ncc.  
+#
+# $Id$
+#
+push( @includes, qw(
+
+  %T/platforms/micaz
+  %T/platforms/mica
+  %T/platforms/iris/chips/rf230
+  %T/chips/rf230
+  %T/chips/cc2420      # for IEEE802154.h
+  %T/platforms/mica2/chips/at45db
+  %T/platforms/mica/chips/at45db
+  %T/chips/at45db
+  %T/chips/atm1281  
+  %T/chips/atm1281/adc
+  %T/chips/atm1281/timer  
+  %T/chips/atm128
+  %T/chips/atm128/adc
+  %T/chips/atm128/pins
+  %T/chips/atm128/spi
+  %T/chips/atm128/i2c
+  %T/chips/atm128/timer
+  %T/lib/timer
+  %T/lib/serial
+  %T/lib/power
+  %T/lib/diagmsg       # for testing purposes
+
+) );
+
+@opts = qw(
+
+  -gcc=avr-gcc
+  -mmcu=atmega1281
+  -fnesc-target=avr
+  -fnesc-no-debug
+  -fnesc-scheduler=TinySchedulerC,TinySchedulerC.TaskBasic,TaskBasic,TaskBasic,runTask,postTask
+
+);
+
+push @opts, "-mingw-gcc" if $cygwin;
+
diff --git a/tos/platforms/iris/ActiveMessageC.nc b/tos/platforms/iris/ActiveMessageC.nc
new file mode 100644 (file)
index 0000000..5515cc2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration ActiveMessageC
+{
+       provides
+       {
+               interface SplitControl;
+
+               interface AMSend[uint8_t id];
+               interface Receive[uint8_t id];
+               interface Receive as Snoop[uint8_t id];
+               interface Packet;
+               interface AMPacket;
+               interface PacketAcknowledgements as Acks;
+       }
+}
+
+implementation
+{
+       components DefaultMacC as MAC;
+
+       SplitControl = MAC;
+       AMSend       = MAC;
+       Receive      = MAC.Receive;
+       Snoop        = MAC.Snoop;
+       Packet       = MAC;
+       AMPacket     = MAC;
+       Acks         = MAC;
+
+       // TODO: do these from PlatformC
+//     components RealMainP, HplRF230C, RF230DriverC;
+//     RealMainP.PlatformInit -> HplRF230C.PlatformInit;
+//     RealMainP.PlatformInit -> RF230DriverC.PlatformInit;
+}
diff --git a/tos/platforms/iris/MeasureClockC.nc b/tos/platforms/iris/MeasureClockC.nc
new file mode 100644 (file)
index 0000000..f57478a
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#include <MicaTimer.h>
+#include <scale.h>
+
+/**
+ * Measure cpu clock frequency at boot time. Provides an Atm128Calibrate
+ * interface so that other components can adjust their calibration as
+ * needed.
+ *
+ * @author David Gay
+ * @author Janos Sallai
+ */
+
+module MeasureClockC {
+  provides {
+    /**
+     * This code MUST be called from PlatformP only, hence the exactlyonce.
+     */
+    interface Init @exactlyonce();
+    interface Atm128Calibrate;
+  }
+}
+implementation 
+{
+  enum {
+    /* This is expected number of cycles per jiffy at the platform's
+       specified MHz. Assumes PLATFORM_MHZ == 1, 2, 4, 8 or 16. */
+    MAGIC = 488 / (16 / PLATFORM_MHZ)
+  };
+
+  uint16_t cycles;
+
+  command error_t Init.init() {
+    /* Measure clock cycles per Jiffy (1/32768s) */
+    /* This code doesn't use the HPL to avoid timing issues when compiling
+       with debugging on */
+    atomic
+      {
+       uint8_t now, wraps;
+       uint16_t start;
+
+       /* Setup timer2 to count 32 jiffies, and timer1 cpu cycles */
+       TCCR1B = 1 << CS10;
+       ASSR = 1 << AS2;
+       TCCR2B = 1 << CS21 | 1 << CS20;
+
+       /* Wait for 1s for counter to stablilize after power-up (yes, it
+          really does take that long). That's 122 wrap arounds of timer 1
+          at 8MHz. */
+       start = TCNT1;
+       for (wraps = MAGIC / 2; wraps; )
+         {
+           uint16_t next = TCNT1;
+
+           if (next < start)
+             wraps--;
+           start = next;
+         }
+
+       /* Wait for a TCNT0 change */
+       now = TCNT2;
+       while (TCNT2 == now) ;
+
+       /* Read cpu cycles and wait for next TCNT2 change */
+       start = TCNT1;
+       now = TCNT2;
+       while (TCNT2 == now) ;
+       cycles = TCNT1;
+
+       cycles = (cycles - start + 16) >> 5;
+
+       /* Reset to boot state */
+       ASSR = TCCR1B = TCCR2B = 0;
+       TCNT2 = 0;
+       TCNT1 = 0;
+       TIFR1 = TIFR2 = 0xff;
+       while (ASSR & (1 << TCN2UB | 1 << OCR2BUB | 1 << TCR2BUB))
+         ;
+      }
+    return SUCCESS;
+  }
+
+  async command uint16_t Atm128Calibrate.cyclesPerJiffy() {
+    return cycles;
+  }
+
+  async command uint32_t Atm128Calibrate.calibrateMicro(uint32_t n) {
+    return scale32(n + MAGIC / 2, cycles, MAGIC);
+  }
+
+  async command uint32_t Atm128Calibrate.actualMicro(uint32_t n) {
+    return scale32(n + (cycles >> 1), MAGIC, cycles);
+  }
+
+  async command uint8_t Atm128Calibrate.adcPrescaler() {
+    /* This is also log2(cycles/3.05). But that's a pain to compute */
+    if (cycles >= 390)
+      return ATM128_ADC_PRESCALE_128;
+    if (cycles >= 195)
+      return ATM128_ADC_PRESCALE_64;
+    if (cycles >= 97)
+      return ATM128_ADC_PRESCALE_32;
+    if (cycles >= 48)
+      return ATM128_ADC_PRESCALE_16;
+    if (cycles >= 24)
+      return ATM128_ADC_PRESCALE_8;
+    if (cycles >= 12)
+      return ATM128_ADC_PRESCALE_4;
+    return ATM128_ADC_PRESCALE_2;
+  }
+
+  async command uint16_t Atm128Calibrate.baudrateRegister(uint32_t baudrate) {
+    // value is (cycles*32768) / (8*baudrate) - 1
+    return ((uint32_t)cycles << 12) / baudrate - 1;
+  }
+}
diff --git a/tos/platforms/iris/MicaTimer.h b/tos/platforms/iris/MicaTimer.h
new file mode 100644 (file)
index 0000000..872beca
--- /dev/null
@@ -0,0 +1,167 @@
+// $Id$
+/*
+ * Copyright (c) 2005-2006 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef MICATIMER_H
+#define MICATIMER_H
+
+/* This file defines the rates at which the mica family's atmega1281 timer 1
+   and 3 timers run at. The goal is to present the user with microsend and
+   32khz timers, but it may not be possible to run the timers at these rates
+   (because of the limited prescaler selection).
+
+   So TinyOS picks a prescaler (based on the selected processor MHz) for
+   each of these timers, and builds corresponding 16-bit alarms&counters
+   (AlarmOne16C, AlarmThree16C, CounterOne16C, CounterThree16C) over
+   hardware timers 1 and 3. TinyOS then divides these hardware timers by
+   the appropriate power of 2 to get approximate 32-bit 32kHz and 1MHz
+   alarms and counters (Alarm32khz32C, AlarmMicro32C, Counter32khz32C,
+   CounterMicro32C).
+
+   The constants and typedefs for all this configuration are defined here,
+   based on the value of the MHZ preprocessor symbol, which shoud approximate
+   the platform's MHZ rate.
+
+   Note that the timers thus obtained will not be exactly at 32768Hz or
+   1MHz, because the clock doesn't divide by a power of two to those
+   frequencies, and/or the clock frequency is not accurate. If you need
+   more accurate timing, you should use the calibration functions
+   offered by the Atm128Calibrate interface provided by PlatformC.
+
+   This file also defines EXT_STANDBY_T0_THRESHOLD, a threshold on
+   remaining time till the next timer 0 interrupt under which the mote
+   should sleep in ext standby rather than power save. This is only
+   important when not using the internal oscillator.  Wake up from power
+   save takes 65536 cycles (6 cycles for ext standby), which is, e.g.,
+   ~9.4ms at 7Mhz.
+*/
+
+#include <Timer.h>
+#include <Atm128Timer.h>
+
+/* Some types for the non-standard rates that mica timers might be running
+   at.
+ */
+typedef struct { } T64khz;
+typedef struct { } T128khz;
+typedef struct { } T2mhz;
+typedef struct { } T4mhz;
+
+/* TX is the typedef for the rate of timer X, 
+   MICA_PRESCALER_X is the prescaler for timer X,
+   MICA_DIVIDER_X_FOR_Y_LOG2 is the number of bits to shift timer X by
+     to get rate Y,
+   counter_X_overflow_t is uint16_t if MICA_DIVIDER_X_FOR_Y_LOG2 is 0,
+     uint32_t otherwise.
+*/
+
+#if MHZ == 1
+typedef T128khz TOne;
+typedef TMicro TThree;
+typedef uint32_t counter_one_overflow_t;
+typedef uint16_t counter_three_overflow_t;
+
+enum {
+  MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_8,
+  MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 2,
+  MICA_PRESCALER_THREE = ATM128_CLK16_NORMAL,
+  MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 0,
+  EXT_STANDBY_T0_THRESHOLD = 80,
+};
+
+#elif MHZ == 2
+typedef T32khz TOne;
+typedef T2mhz TThree;
+typedef uint16_t counter_one_overflow_t;
+typedef uint32_t counter_three_overflow_t;
+
+enum {
+  MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_64,
+  MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 0,
+  MICA_PRESCALER_THREE = ATM128_CLK16_NORMAL,
+  MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 1,
+  EXT_STANDBY_T0_THRESHOLD = 40
+};
+
+#elif MHZ == 4
+typedef T64khz TOne;
+typedef T4mhz TThree;
+typedef uint32_t counter_one_overflow_t;
+typedef uint32_t counter_three_overflow_t;
+
+enum {
+  MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_64,
+  MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 1,
+  MICA_PRESCALER_THREE = ATM128_CLK16_NORMAL,
+  MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 2,
+  EXT_STANDBY_T0_THRESHOLD = 24
+};
+
+#elif MHZ == 8
+/*
+typedef T32khz TOne;
+typedef TMicro TThree;
+typedef uint16_t counter_one_overflow_t;
+typedef uint16_t counter_three_overflow_t;
+
+enum {
+  MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_256,
+  MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 0,
+  MICA_PRESCALER_THREE = ATM128_CLK16_DIVIDE_8,
+  MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 0,
+  EXT_STANDBY_T0_THRESHOLD = 12
+};
+*/
+
+// get a 1MHz (1 microsecond resolution) timer for debugging purposes
+
+typedef TMilli TOne;
+typedef TMicro TThree;
+typedef uint32_t counter_one_overflow_t;
+typedef uint16_t counter_three_overflow_t;
+enum {
+  MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_8,
+  MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 5,
+  MICA_PRESCALER_THREE = ATM128_CLK16_DIVIDE_8,
+  MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 0,
+  EXT_STANDBY_T0_THRESHOLD = 12,
+};
+
+#else
+#error "Unknown clock rate. MHZ must be defined to one of 1, 2, 4, or 8."
+#endif
+
+enum {
+  PLATFORM_MHZ = MHZ
+};
+
+#endif
diff --git a/tos/platforms/iris/chips/rf230/HplRF230.h b/tos/platforms/iris/chips/rf230/HplRF230.h
new file mode 100644 (file)
index 0000000..822d2d1
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __HPLRF230_H__
+#define __HPLRF230_H__
+
+#include <RF230.h>
+
+enum
+{
+       /**
+        * This is the value of the TRX_CTRL_0 register
+        * which configures the output pin currents and the CLKM clock
+        */
+       RF230_TRX_CTRL_0_VALUE = 0,
+
+       /**
+        * This is the default value of the CCA_MODE field in the PHY_CC_CCA register
+        * which is used to configure the default mode of the clear channel assesment
+        */
+       RF230_CCA_MODE_VALUE = RF230_CCA_MODE_3,
+
+       /**
+        * This is the value of the CCA_THRES register that controls the
+        * energy levels used for clear channel assesment
+        */
+       RF230_CCA_THRES_VALUE = 0xC7,
+};
+
+/**
+ * This is the timer type of the RF230 alarm interface
+ */
+typedef TOne TRF230;
+
+/**
+ * The number of alarm ticks per one microsecond (0.9216)
+ */
+#define RF230_ALARM_MICROSEC   ((7.3728 / MHZ / 32.0) * (1 << MICA_DIVIDE_ONE_FOR_32KHZ_LOG2))
+
+#endif//__HPLRF230_H__
diff --git a/tos/platforms/iris/chips/rf230/HplRF230.nc b/tos/platforms/iris/chips/rf230/HplRF230.nc
new file mode 100644 (file)
index 0000000..29faa76
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+/**
+ * There should be standard interfaces/commands for these
+*/
+interface HplRF230
+{
+       /**
+        * Calculates the crc. For some unknown reason the standard
+        * tinyos crcByte command swiches endianness.
+        */
+       async command uint16_t crcByte(uint16_t crc, uint8_t data);
+
+       /**
+        * Starts a split-phase SPI data transfer with the given data.
+        * A spiSplitRead command must follow this command even if the
+        * result is unimportant. The SpiByte interface should be 
+        * extended with this protocol.
+        */
+       async command void spiSplitWrite(uint8_t data);
+
+       /**
+        * Finishes the split-phase SPI data transfer by waiting till 
+        * the write command comletes and returning the received data.
+        */
+       async command uint8_t spiSplitRead();
+
+       /**
+        * This command first reads the SPI register and then writes
+        * there the new data, then returns
+        */
+       async command uint8_t spiSplitReadWrite(uint8_t data);
+
+       /**
+        * This is the standard SpiByte.write command but a little
+        * faster as we shuold not need to adjust the power state there.
+        */
+       async command uint8_t spiWrite(uint8_t data);
+}
diff --git a/tos/platforms/iris/chips/rf230/HplRF230C.nc b/tos/platforms/iris/chips/rf230/HplRF230C.nc
new file mode 100644 (file)
index 0000000..2e48b54
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <HplRF230.h>
+
+configuration HplRF230C
+{
+       provides
+       {
+               interface GeneralIO as SELN;
+               interface Resource as SpiResource;
+               interface SpiByte;
+
+               interface GeneralIO as SLP_TR;
+               interface GeneralIO as RSTN;
+
+               interface GpioCapture as IRQ;
+               interface Alarm<TRF230, uint16_t> as Alarm;
+
+               interface HplRF230;
+       }
+}
+
+implementation
+{
+       components HplRF230P;
+       IRQ = HplRF230P.IRQ;
+
+       HplRF230P.PortCLKM -> IO.PortD6;
+       HplRF230P.PortIRQ -> IO.PortD4;
+       
+       // TODO: Ask why the HplAtm128SpiC does SlaveSelect via PortB0
+       // TODO: Remove the unused started field from Atm128SpiP
+       components Atm128SpiC as SpiC;
+       SpiResource = SpiC.Resource[unique("Atm128SpiC.Resource")];
+       SpiByte = SpiC;
+
+       HplRF230 = HplRF230P;
+
+       components HplAtm128GeneralIOC as IO;
+       SLP_TR = IO.PortB7;
+       RSTN = IO.PortA6;
+       SELN = IO.PortB0;
+
+       components HplAtm128Timer1C as TimerC;
+       HplRF230P.Capture -> TimerC.Capture;
+
+       components new AlarmOne16C() as AlarmC;
+       Alarm = AlarmC;
+
+       // TODO: do these from PlatformC
+       components RealMainP, RF230LayerC;
+       RealMainP.PlatformInit -> HplRF230P.PlatformInit;
+       RealMainP.PlatformInit -> RF230LayerC.PlatformInit;
+}
diff --git a/tos/platforms/iris/chips/rf230/HplRF230P.nc b/tos/platforms/iris/chips/rf230/HplRF230P.nc
new file mode 100644 (file)
index 0000000..cbe6c94
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <util/crc16.h>
+#include "Atm128Spi.h"
+
+module HplRF230P
+{
+       provides
+       {
+               interface GpioCapture as IRQ;
+               interface Init as PlatformInit;
+
+               interface HplRF230;
+       }
+
+       uses
+       {
+               interface HplAtm128Capture<uint16_t> as Capture;
+               interface GeneralIO as PortCLKM;
+               interface GeneralIO as PortIRQ;
+       }
+}
+
+implementation
+{
+       command error_t PlatformInit.init()
+       {
+               call PortCLKM.makeInput();
+               call PortCLKM.clr();
+               call PortIRQ.makeInput();
+               call PortIRQ.clr();
+               call Capture.stop();
+
+               return SUCCESS;
+       }
+
+       async event void Capture.captured(uint16_t time)
+       {
+               time = call Capture.get();      // TODO: ask Cory why time is not the captured time
+               signal IRQ.captured(time);
+       }
+
+       default async event void IRQ.captured(uint16_t time)
+       {
+       }
+
+       async command error_t IRQ.captureRisingEdge()
+       {
+               call Capture.setEdge(TRUE);
+               call Capture.reset();
+               call Capture.start();
+       
+               return SUCCESS;
+       }
+
+       async command error_t IRQ.captureFallingEdge()
+       {
+               // falling edge comes when the IRQ_STATUS register of the RF230 is read
+               return FAIL;    
+       }
+
+       async command void IRQ.disable()
+       {
+               call Capture.stop();
+       }
+
+       // TODO: Check why the default crcByte implementation is in a different endianness
+       inline async command uint16_t HplRF230.crcByte(uint16_t crc, uint8_t data)
+       {
+               return _crc_ccitt_update(crc, data);
+       }
+
+       inline async command void HplRF230.spiSplitWrite(uint8_t data)
+       {
+               // the SPI must have been started, so do not waste time here
+               // SET_BIT(SPCR, SPE);
+
+               SPDR = data;
+       }
+
+       inline async command uint8_t HplRF230.spiSplitRead()
+       {
+           while( !( SPSR & 0x80 ) )
+                       ;
+               return SPDR;
+       }
+
+       inline async command uint8_t HplRF230.spiSplitReadWrite(uint8_t data)
+       {
+               uint8_t b;
+
+           while( !( SPSR & 0x80 ) )
+                       ;
+               b = SPDR;
+               SPDR = data;
+
+               return b;
+       }
+
+       inline async command uint8_t HplRF230.spiWrite(uint8_t data)
+       {
+               // the SPI must have been started, so do not waste time here
+               // SET_BIT(SPCR, SPE);
+
+               SPDR = data;
+           while( !( SPSR & 0x80 ) )
+                       ;
+
+               return SPDR;
+       }
+}
diff --git a/tos/platforms/iris/platform.h b/tos/platforms/iris/platform.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tos/platforms/iris/platform_message.h b/tos/platforms/iris/platform_message.h
new file mode 100644 (file)
index 0000000..9b55ed7
--- /dev/null
@@ -0,0 +1,80 @@
+/* $Id$
+ * "Copyright (c) 2005 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-2005 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.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY 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 VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE VANDERBILT UNIVERSITY 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 VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Defining the platform-independently named packet structures to be the
+ * chip-specific CC1000 packet structures.
+ *
+ * @author Philip Levis
+ * @date   May 16 2005
+ * Revision:  $Revision$
+ */
+
+
+#ifndef PLATFORM_MESSAGE_H
+#define PLATFORM_MESSAGE_H
+
+#include <DefaultMac.h>
+#include <Serial.h>
+
+typedef union message_header {
+  defaultmac_header_t rf230;
+  serial_header_t serial;
+} message_header_t;
+
+typedef union message_footer {
+} message_footer_t;
+
+typedef union message_metadata {
+  defaultmac_metadata_t rf230;
+} message_metadata_t;
+
+#endif
diff --git a/tos/platforms/iris/sim/.platform b/tos/platforms/iris/sim/.platform
new file mode 100644 (file)
index 0000000..22dbab9
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# FILE: iris/.platform
+# 
+# Includes that should take precedence come first.  Platforms come before
+# chips because they may override files.  These must be specified as
+# @includes instead of -I's to @opts, otherwise the %T won't be processed
+# by ncc.  And because of that, the current platform's include directory
+# must be specified, otherwise its search order is last instead of first.
+#
+#
+push( @includes, qw(
+
+  %T/platforms/iris
+  %T/platforms/micaz
+  %T/platforms/mica
+  %T/platforms/micaz/chips/cc2420
+  %T/chips/cc2420
+  %T/chips/atm128
+  %T/chips/atm128/adc
+  %T/chips/atm128/pins
+  %T/chips/atm128/spi
+  %T/chips/atm128/timer
+  %T/lib/power
+  %T/lib/timer
+  %T/lib/serial
+
+) );
+
+@opts = qw(
+
+  -gcc=gcc
+  -fnesc-no-debug
+  -fnesc-scheduler=TinySchedulerC,TinySchedulerC.TaskBasic,TaskBasic,TaskBasic,runTask,postTask
+
+);
+
+push @opts, "-mingw-gcc" if $cygwin;
+