From: sallai Date: Mon, 5 Nov 2007 20:36:40 +0000 (+0000) Subject: platform support for the IRIS mote (atm1218 MCU and rf230 radio) X-Git-Tag: release_tinyos_2_1_0_0~671 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=c200f0d798d7f9631eabfb79008615936a52b5af platform support for the IRIS mote (atm1218 MCU and rf230 radio) --- diff --git a/tos/chips/atm1281/HplAtm128UartP.nc b/tos/chips/atm1281/HplAtm128UartP.nc new file mode 100644 index 00000000..5b9061d9 --- /dev/null +++ b/tos/chips/atm1281/HplAtm128UartP.nc @@ -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 + * @author Jonathan Hui + * @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 + * @author David Gay + * @author Janos Sallai + */ + +#include + +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 index 00000000..4c11f49d --- /dev/null +++ b/tos/chips/atm1281/McuSleepC.nc @@ -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. + * + *
+ *  $Id$
+ * 
+ * + * @author Philip Levis + * @author Robert Szewczyk + * @author Janos Sallai + * @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 index 00000000..2ed8763b --- /dev/null +++ b/tos/chips/atm1281/adc/Atm128Adc.h @@ -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 +// @author Hu Siquan + +/* + * 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 + +/* + 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 index 00000000..1dae8ac3 --- /dev/null +++ b/tos/chips/atm1281/adc/Atm128AdcP.nc @@ -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 + * @author Janos Sallai + */ + +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 index 00000000..ec886718 --- /dev/null +++ b/tos/chips/atm1281/adc/HplAtm128AdcP.nc @@ -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 + * @author Hu Siquan + * @author David Gay + * @author Janos Sallai + */ + +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 index 00000000..ccef9f52 --- /dev/null +++ b/tos/chips/atm1281/atm128hardware.h @@ -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 +#if __AVR_LIBC_VERSION__ >= 10400UL +#include +#else +#include +#include +#endif +#include +#include +#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 index 00000000..7dd543b6 --- /dev/null +++ b/tos/chips/atm1281/timer/Atm1281AlarmAsyncP.nc @@ -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 + */ +generic module Atm1281AlarmAsyncP(typedef precision, int divider) { + provides { + interface Init; + interface Alarm; + interface Counter; + } + uses { + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl8 as TimerCtrl; + interface HplAtm128Compare 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 index 00000000..9fbb9f8d --- /dev/null +++ b/tos/chips/atm1281/timer/Atm128AlarmAsyncC.nc @@ -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 + */ +generic configuration Atm128AlarmAsyncC(typedef precision, int divider) { + provides { + interface Init @atleastonce(); + interface Alarm; + interface Counter; + } +} +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 index 00000000..6ffb09d3 --- /dev/null +++ b/tos/chips/atm1281/timer/Atm128Timer.h @@ -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 + */ + +#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 index 00000000..0f6b4389 --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm1281Timer1P.nc @@ -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 + * @author Janos Sallai + */ + +#include + +module HplAtm1281Timer1P +{ + provides { + // 16-bit Timers + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl16 as TimerCtrl; + interface HplAtm128Capture as Capture; + interface HplAtm128Compare as CompareA; + interface HplAtm128Compare as CompareB; + interface HplAtm128Compare 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 index 00000000..0cb88d4d --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm1281Timer2AsyncC.nc @@ -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 + */ + +#include + +configuration HplAtm1281Timer2AsyncC +{ + provides { + // 8-bit Timers + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl8 as TimerCtrl; + interface HplAtm128Compare 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 index 00000000..b4b3623b --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm1281Timer2AsyncP.nc @@ -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 + * @author David Gay + * @author Janos Sallai + */ + +#include + +module HplAtm1281Timer2AsyncP +{ + provides { + // 8-bit Timers + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl8 as TimerCtrl; + interface HplAtm128Compare 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 index 00000000..9f25ec6e --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm1281Timer3P.nc @@ -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 + * @author Janos Sallai + */ + +#include + +module HplAtm1281Timer3P +{ + provides { + // 16-bit Timers + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl16 as TimerCtrl; + interface HplAtm128Capture as Capture; + interface HplAtm128Compare as CompareA; + interface HplAtm128Compare as CompareB; + interface HplAtm128Compare 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 index 00000000..a6472a2e --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm128Timer1C.nc @@ -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 + * @author David Gay + * @author Janos Sallai + */ + +configuration HplAtm128Timer1C +{ + provides { + // 16-bit Timers + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl16 as TimerCtrl; + interface HplAtm128Capture as Capture; + interface HplAtm128Compare 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 index 00000000..3f3fa2c7 --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm128Timer3C.nc @@ -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 + * @author David Gay + * @author Janos Sallai + */ + +configuration HplAtm128Timer3C +{ + provides { + // 16-bit Timers + interface HplAtm128Timer as Timer; + interface HplAtm128TimerCtrl16 as TimerCtrl; + interface HplAtm128Capture as Capture; + interface HplAtm128Compare 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 index 00000000..ea4a9f79 --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm128TimerAsync.nc @@ -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 + */ +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 index 00000000..39076ee1 --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm128TimerCtrl16.nc @@ -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 + * @author Janos Sallai + */ + +#include + +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 index 00000000..067417e4 --- /dev/null +++ b/tos/chips/atm1281/timer/HplAtm128TimerCtrl8.nc @@ -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 + * @author Janos Sallai + */ + +#include + +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 index 00000000..e47f0e8b --- /dev/null +++ b/tos/chips/rf230/ActiveMessageConfig.nc @@ -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 index 00000000..f635a9c6 --- /dev/null +++ b/tos/chips/rf230/ActiveMessageLayerC.nc @@ -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 index 00000000..9d453767 --- /dev/null +++ b/tos/chips/rf230/CsmaConfig.nc @@ -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 index 00000000..e0ddc262 --- /dev/null +++ b/tos/chips/rf230/CsmaLayerC.nc @@ -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 index 00000000..5bd1aa41 --- /dev/null +++ b/tos/chips/rf230/CsmaLayerP.nc @@ -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 +#include + +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 index 00000000..3547bde9 --- /dev/null +++ b/tos/chips/rf230/DefaultMac.h @@ -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 + +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 index 00000000..32296187 --- /dev/null +++ b/tos/chips/rf230/DefaultMacC.nc @@ -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 index 00000000..ba17f9ba --- /dev/null +++ b/tos/chips/rf230/DefaultMacP.nc @@ -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 +#include +#include + +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 index 00000000..c76631e6 --- /dev/null +++ b/tos/chips/rf230/DummyConfig.nc @@ -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 index 00000000..5aebc90d --- /dev/null +++ b/tos/chips/rf230/DummyLayerC.nc @@ -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 index 00000000..796a4fa1 --- /dev/null +++ b/tos/chips/rf230/IEEE154Packet.h @@ -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 index 00000000..2c5664c2 --- /dev/null +++ b/tos/chips/rf230/IEEE154Packet.nc @@ -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 +#include + +/** + * 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 index 00000000..2ea8ffeb --- /dev/null +++ b/tos/chips/rf230/IEEE154PacketC.nc @@ -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 index 00000000..73395da1 --- /dev/null +++ b/tos/chips/rf230/IEEE154PacketP.nc @@ -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 + +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 index 00000000..89f00594 --- /dev/null +++ b/tos/chips/rf230/MessageBufferLayerC.nc @@ -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 index 00000000..76ef080b --- /dev/null +++ b/tos/chips/rf230/MessageBufferLayerP.nc @@ -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 +#include + +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 index 00000000..40884e39 --- /dev/null +++ b/tos/chips/rf230/Neighborhood.h @@ -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 index 00000000..ec00392b --- /dev/null +++ b/tos/chips/rf230/Neighborhood.nc @@ -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 + +/** + * 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 index 00000000..e2ba9b50 --- /dev/null +++ b/tos/chips/rf230/NeighborhoodC.nc @@ -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 index 00000000..e1dda902 --- /dev/null +++ b/tos/chips/rf230/NeighborhoodFlag.nc @@ -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 + +/** + * 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 index 00000000..2f064eb6 --- /dev/null +++ b/tos/chips/rf230/NeighborhoodFlagC.nc @@ -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 index 00000000..fb84dc8a --- /dev/null +++ b/tos/chips/rf230/NeighborhoodP.nc @@ -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 + +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 index 00000000..b45eea03 --- /dev/null +++ b/tos/chips/rf230/PacketTimeStamp.nc @@ -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 +{ + /** + * 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 index 00000000..47b9051b --- /dev/null +++ b/tos/chips/rf230/PacketTimeSynch.nc @@ -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 +{ + /** + * 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 index 00000000..781a1330 --- /dev/null +++ b/tos/chips/rf230/RF230.h @@ -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 index 00000000..97d23928 --- /dev/null +++ b/tos/chips/rf230/RF230Config.nc @@ -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 index 00000000..d50ce40a --- /dev/null +++ b/tos/chips/rf230/RF230LayerC.nc @@ -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 index 00000000..ef4c52f6 --- /dev/null +++ b/tos/chips/rf230/RF230LayerP.nc @@ -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 +#include +#include +#include + +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; + + 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 index 00000000..d09c4f0e --- /dev/null +++ b/tos/chips/rf230/RadioAlarm.nc @@ -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 + +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 index 00000000..a1b811d6 --- /dev/null +++ b/tos/chips/rf230/RadioAlarmC.nc @@ -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 @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 index 00000000..d712c6ef --- /dev/null +++ b/tos/chips/rf230/RadioAlarmP.nc @@ -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 +#include + +module RadioAlarmP +{ + provides + { + interface RadioAlarm[uint8_t id]; + } + + uses + { + interface Alarm; + 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 index 00000000..19f17262 --- /dev/null +++ b/tos/chips/rf230/RadioAssert.h @@ -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 index 00000000..78e16949 --- /dev/null +++ b/tos/chips/rf230/RadioCCA.nc @@ -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 + +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 index 00000000..0e8330f9 --- /dev/null +++ b/tos/chips/rf230/RadioReceive.nc @@ -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 + +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 index 00000000..59437946 --- /dev/null +++ b/tos/chips/rf230/RadioSend.nc @@ -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 + +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 index 00000000..72543835 --- /dev/null +++ b/tos/chips/rf230/RadioState.nc @@ -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 + +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 index 00000000..b12cc692 --- /dev/null +++ b/tos/chips/rf230/RandomCollisionConfig.nc @@ -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 index 00000000..ba7ad054 --- /dev/null +++ b/tos/chips/rf230/RandomCollisionLayerC.nc @@ -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 index 00000000..c53d1b91 --- /dev/null +++ b/tos/chips/rf230/RandomCollisionLayerP.nc @@ -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 +#include + +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 index 00000000..4b6b9931 --- /dev/null +++ b/tos/chips/rf230/SlottedCollisionConfig.nc @@ -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 index 00000000..00288463 --- /dev/null +++ b/tos/chips/rf230/SlottedCollisionLayerC.nc @@ -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 index 00000000..f9108ee1 --- /dev/null +++ b/tos/chips/rf230/SlottedCollisionLayerP.nc @@ -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 +#include + +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 index 00000000..b3c87c73 --- /dev/null +++ b/tos/chips/rf230/SoftwareAckConfig.nc @@ -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 + +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 index 00000000..97703e1f --- /dev/null +++ b/tos/chips/rf230/SoftwareAckLayerC.nc @@ -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 index 00000000..51231b66 --- /dev/null +++ b/tos/chips/rf230/SoftwareAckLayerP.nc @@ -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 +#include + +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 index 00000000..38f185fb --- /dev/null +++ b/tos/chips/rf230/Tasklet.h @@ -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 index 00000000..527400aa --- /dev/null +++ b/tos/chips/rf230/Tasklet.nc @@ -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 + +/** + * 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 index 00000000..360f54fb --- /dev/null +++ b/tos/chips/rf230/TaskletC.nc @@ -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 +#include + +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 index 00000000..0b7bc649 --- /dev/null +++ b/tos/chips/rf230/TrafficMonitorConfig.nc @@ -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 + +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 index 00000000..b144c8ab --- /dev/null +++ b/tos/chips/rf230/TrafficMonitorLayerC.nc @@ -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 index 00000000..75328ac5 --- /dev/null +++ b/tos/chips/rf230/TrafficMonitorLayerP.nc @@ -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 + +/* + * 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 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 index 00000000..5f14c521 --- /dev/null +++ b/tos/chips/rf230/UniqueConfig.nc @@ -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 + +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 index 00000000..5d2e5f23 --- /dev/null +++ b/tos/chips/rf230/UniqueLayerC.nc @@ -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 index 00000000..d341942e --- /dev/null +++ b/tos/chips/rf230/UniqueLayerP.nc @@ -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 +#include + +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 index 00000000..b5bdd65b --- /dev/null +++ b/tos/chips/rf230/notes.txt @@ -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 index 00000000..b54675cc --- /dev/null +++ b/tos/lib/diagmsg/Assert.h @@ -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 index 00000000..56808c81 --- /dev/null +++ b/tos/lib/diagmsg/AssertC.nc @@ -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 index 00000000..c9631845 --- /dev/null +++ b/tos/lib/diagmsg/AssertP.nc @@ -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 index 00000000..4e91076d --- /dev/null +++ b/tos/lib/diagmsg/DiagMsg.nc @@ -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 + * printf(...). 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 15. + * 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 chrs + */ + 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 index 00000000..98a7f230 --- /dev/null +++ b/tos/lib/diagmsg/DiagMsg.txt @@ -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 index 00000000..5d53fa98 --- /dev/null +++ b/tos/lib/diagmsg/DiagMsgC.nc @@ -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 index 00000000..669a04b6 --- /dev/null +++ b/tos/lib/diagmsg/DiagMsgM.nc @@ -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 + +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 TYPE_END + 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 size bytes + * and sets the type information to type. + * Returns the index in msg.data where the data + * should be stored or -1 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 msgs 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 index 00000000..b638c533 --- /dev/null +++ b/tos/lib/diagmsg/NoDiagMsgC.nc @@ -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 index 00000000..9943593d --- /dev/null +++ b/tos/platforms/iris/.platform @@ -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 index 00000000..5515cc26 --- /dev/null +++ b/tos/platforms/iris/ActiveMessageC.nc @@ -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 index 00000000..f57478a6 --- /dev/null +++ b/tos/platforms/iris/MeasureClockC.nc @@ -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 +#include + +/** + * 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 index 00000000..872becab --- /dev/null +++ b/tos/platforms/iris/MicaTimer.h @@ -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 +#include + +/* 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 index 00000000..822d2d1d --- /dev/null +++ b/tos/platforms/iris/chips/rf230/HplRF230.h @@ -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 + +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 index 00000000..29faa760 --- /dev/null +++ b/tos/platforms/iris/chips/rf230/HplRF230.nc @@ -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 index 00000000..2e48b54f --- /dev/null +++ b/tos/platforms/iris/chips/rf230/HplRF230C.nc @@ -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 + +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 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 index 00000000..cbe6c948 --- /dev/null +++ b/tos/platforms/iris/chips/rf230/HplRF230P.nc @@ -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 +#include "Atm128Spi.h" + +module HplRF230P +{ + provides + { + interface GpioCapture as IRQ; + interface Init as PlatformInit; + + interface HplRF230; + } + + uses + { + interface HplAtm128Capture 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 index 00000000..e69de29b diff --git a/tos/platforms/iris/platform_message.h b/tos/platforms/iris/platform_message.h new file mode 100644 index 00000000..9b55ed77 --- /dev/null +++ b/tos/platforms/iris/platform_message.h @@ -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 +#include + +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 index 00000000..22dbab9b --- /dev/null +++ b/tos/platforms/iris/sim/.platform @@ -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; +