--- /dev/null
+/*
+ * Copyright (c) 2006 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * ARCH ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+/**
+ * @author Alec Woo <awoo@archrock.com>
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Private component of the Atmega1281 serial port HPL.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Uart.h>
+
+module HplAtm128UartP {
+
+ provides interface Init as Uart0Init;
+ provides interface StdControl as Uart0TxControl;
+ provides interface StdControl as Uart0RxControl;
+ provides interface HplAtm128Uart as HplUart0;
+
+ provides interface Init as Uart1Init;
+ provides interface StdControl as Uart1TxControl;
+ provides interface StdControl as Uart1RxControl;
+ provides interface HplAtm128Uart as HplUart1;
+
+ uses interface Atm128Calibrate;
+ uses interface McuPowerState;
+}
+implementation {
+
+ //=== Uart Init Commands. ====================================
+ command error_t Uart0Init.init() {
+ Atm128UartMode_t mode;
+ Atm128UartStatus_t stts;
+ Atm128UartControl_t ctrl;
+ uint16_t ubrr0;
+
+ ctrl.bits = (struct Atm128_UCSRB_t) {rxcie:0, txcie:0, rxen:0, txen:0};
+ stts.bits = (struct Atm128_UCSRA_t) {u2x:1};
+ mode.bits = (struct Atm128_UCSRC_t) {ucsz:ATM128_UART_DATA_SIZE_8_BITS};
+
+ ubrr0 = call Atm128Calibrate.baudrateRegister(PLATFORM_BAUDRATE);
+ UBRR0L = ubrr0;
+ UBRR0H = ubrr0 >> 8;
+ UCSR0A = stts.flat;
+ UCSR0C = mode.flat;
+ UCSR0B = ctrl.flat;
+
+ return SUCCESS;
+ }
+
+ command error_t Uart0TxControl.start() {
+ SET_BIT(UCSR0B, TXCIE0);
+ SET_BIT(UCSR0B, TXEN0);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ command error_t Uart0TxControl.stop() {
+ CLR_BIT(UCSR0B, TXCIE0);
+ CLR_BIT(UCSR0B, TXEN0);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ command error_t Uart0RxControl.start() {
+ SET_BIT(UCSR0B, RXCIE0);
+ SET_BIT(UCSR0B, RXEN0);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ command error_t Uart0RxControl.stop() {
+ CLR_BIT(UCSR0B, RXCIE0);
+ CLR_BIT(UCSR0B, RXEN0);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ async command error_t HplUart0.enableTxIntr() {
+ SET_BIT(UCSR0B, TXEN0);
+ return SUCCESS;
+ }
+
+ async command error_t HplUart0.disableTxIntr(){
+ CLR_BIT(UCSR0B, TXEN0);
+ return SUCCESS;
+ }
+
+ async command error_t HplUart0.enableRxIntr(){
+ SET_BIT(UCSR0B, RXEN0);
+ return SUCCESS;
+ }
+
+ async command error_t HplUart0.disableRxIntr(){
+ CLR_BIT(UCSR0B, RXEN0);
+ return SUCCESS;
+ }
+
+ async command bool HplUart0.isTxEmpty(){
+ return READ_BIT(UCSR0A, TXC0);
+ }
+
+ async command bool HplUart0.isRxEmpty(){
+ return !READ_BIT(UCSR0A, RXC0);
+ }
+
+ async command uint8_t HplUart0.rx(){
+ return UDR0;
+ }
+
+ async command void HplUart0.tx(uint8_t data) {
+ atomic{
+ UDR0 = data;
+ SET_BIT(UCSR0A, TXC0);
+ }
+ }
+
+ AVR_ATOMIC_HANDLER(SIG_USART0_RECV) {
+ if (READ_BIT(UCSR0A, RXC0)) {
+ signal HplUart0.rxDone(UDR0);
+ }
+ }
+
+ AVR_NONATOMIC_HANDLER(SIG_USART0_TRANS) {
+ signal HplUart0.txDone();
+ }
+
+ command error_t Uart1Init.init() {
+ Atm128UartMode_t mode;
+ Atm128UartStatus_t stts;
+ Atm128UartControl_t ctrl;
+ uint16_t ubrr1;
+
+ ctrl.bits = (struct Atm128_UCSRB_t) {rxcie:0, txcie:0, rxen:0, txen:0};
+ stts.bits = (struct Atm128_UCSRA_t) {u2x:1};
+ mode.bits = (struct Atm128_UCSRC_t) {ucsz:ATM128_UART_DATA_SIZE_8_BITS};
+
+ ubrr1 = call Atm128Calibrate.baudrateRegister(PLATFORM_BAUDRATE);
+ UBRR1L = ubrr1;
+ UBRR1H = ubrr1 >> 8;
+ UCSR1A = stts.flat;
+ UCSR1C = mode.flat;
+ UCSR1B = ctrl.flat;
+
+ return SUCCESS;
+ }
+
+ command error_t Uart1TxControl.start() {
+ SET_BIT(UCSR1B, TXCIE1);
+ SET_BIT(UCSR1B, TXEN1);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ command error_t Uart1TxControl.stop() {
+ CLR_BIT(UCSR1B, TXCIE1);
+ CLR_BIT(UCSR1B, TXEN1);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ command error_t Uart1RxControl.start() {
+ SET_BIT(UCSR1B, RXCIE1);
+ SET_BIT(UCSR1B, RXEN1);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ command error_t Uart1RxControl.stop() {
+ CLR_BIT(UCSR1B, RXCIE1);
+ CLR_BIT(UCSR1B, RXEN1);
+ call McuPowerState.update();
+ return SUCCESS;
+ }
+
+ async command error_t HplUart1.enableTxIntr() {
+ SET_BIT(UCSR1B, TXEN1);
+ return SUCCESS;
+ }
+
+ async command error_t HplUart1.disableTxIntr(){
+ CLR_BIT(UCSR1B, TXEN1);
+ return SUCCESS;
+ }
+
+ async command error_t HplUart1.enableRxIntr(){
+ SET_BIT(UCSR1B, RXEN1);
+ return SUCCESS;
+ }
+
+ async command error_t HplUart1.disableRxIntr(){
+ CLR_BIT(UCSR1B, RXEN1);
+ return SUCCESS;
+ }
+
+ async command bool HplUart1.isTxEmpty() {
+ return READ_BIT(UCSR1A, TXC1);
+ }
+
+ async command bool HplUart1.isRxEmpty() {
+ return !READ_BIT(UCSR1A, RXC1);
+ }
+
+ async command uint8_t HplUart1.rx(){
+ return UDR1;
+ }
+
+ async command void HplUart1.tx(uint8_t data) {
+ atomic{
+ UDR1 = data;
+ SET_BIT(UCSR1A, TXC1);
+ }
+ }
+
+ AVR_ATOMIC_HANDLER(SIG_USART1_RECV) {
+ if (READ_BIT(UCSR1A, RXC1))
+ signal HplUart1.rxDone(UDR1);
+ }
+
+ AVR_NONATOMIC_HANDLER(SIG_USART1_TRANS) {
+ signal HplUart1.txDone();
+ }
+
+ default async event void HplUart0.txDone() {}
+ default async event void HplUart0.rxDone(uint8_t data) {}
+ default async event void HplUart1.txDone() {}
+ default async event void HplUart1.rxDone(uint8_t data) {}
+
+}
--- /dev/null
+/// $Id$
+
+/*
+ * "Copyright (c) 2005 Stanford University. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without written
+ * agreement is hereby granted, provided that the above copyright
+ * notice, the following two paragraphs and the author appear in all
+ * copies of this software.
+ *
+ * IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+ * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY
+ * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS."
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Implementation of TEP 112 (Microcontroller Power Management) for
+ * the Atmega128. Power state calculation code copied from Rob
+ * Szewczyk's 1.x code in HPLPowerManagementM.nc.
+ *
+ * <pre>
+ * $Id$
+ * </pre>
+ *
+ * @author Philip Levis
+ * @author Robert Szewczyk
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ * @date October 30, 2007
+ */
+
+module McuSleepC {
+ provides {
+ interface McuSleep;
+ interface McuPowerState;
+ }
+ uses {
+ interface McuPowerOverride;
+ }
+}
+implementation {
+ /* There is no dirty bit management because the sleep mode depends on
+ the amount of time remaining in timer2. */
+
+ /* Note that the power values are maintained in an order
+ * based on their active components, NOT on their values.
+ * Look at atm1281hardware.h and page 54 of the ATmeg1281
+ * manual (Table 25).*/
+ const_uint8_t atm128PowerBits[ATM128_POWER_DOWN + 1] = {
+ 0,
+ (1 << SM0),
+ (1 << SM2) | (1 << SM1) | (1 << SM0),
+ (1 << SM1) | (1 << SM0),
+ (1 << SM2) | (1 << SM1),
+ (1 << SM1)};
+
+ mcu_power_t getPowerState() {
+ // Note: we go to sleep even if timer 0, 1, 3, 4, or 5's overflow interrupt
+ // is enabled - this allows using these timers as TinyOS "Alarm"s
+ // while still having power management.
+
+ // Are external timers running?
+ if (
+ TIMSK0 & (1 << OCIE0A | 1 << OCIE0B | 1 << TOIE0) ||
+ TIMSK1 & (1 << ICIE1 | 1 << OCIE1A | 1 << OCIE1B | 1 << OCIE1C | 1 << TOIE1) ||
+ TIMSK3 & (1 << ICIE3 | 1 << OCIE3A | 1 << OCIE3B | 1 << OCIE3C | 1 << TOIE3) ||
+ // input capture and output compare for timer 4 and 5 are
+ // not functional on atm1281
+ TIMSK4 & (1 << TOIE4) ||
+ TIMSK5 & (1 << TOIE5)
+ ) {
+ return ATM128_POWER_IDLE;
+ }
+ // SPI (Radio stack)
+ else if (bit_is_set(SPCR, SPIE)) {
+ return ATM128_POWER_IDLE;
+ }
+ // UARTs are active
+ else if (UCSR0B & (1 << TXCIE0 | 1 << RXCIE0)) { // UART
+ return ATM128_POWER_IDLE;
+ }
+ else if (UCSR1B & (1 << TXCIE1 | 1 << RXCIE1)) { // UART
+ return ATM128_POWER_IDLE;
+ }
+ // I2C (Two-wire) is active
+ else if (bit_is_set(TWCR, TWEN)){
+ return ATM128_POWER_IDLE;
+ }
+ // ADC is enabled
+ else if (bit_is_set(ADCSRA, ADEN)) {
+ return ATM128_POWER_ADC_NR;
+ }
+ else {
+ return ATM128_POWER_DOWN;
+ }
+ }
+
+ async command void McuSleep.sleep() {
+ uint8_t powerState;
+
+ powerState = mcombine(getPowerState(), call McuPowerOverride.lowestState());
+ SMCR =
+ (SMCR & 0xf0) | 1 << SE | read_uint8_t(&atm128PowerBits[powerState]);
+ sei();
+ asm volatile ("sleep");
+ cli();
+
+ CLR_BIT(SMCR, SE);
+ }
+
+ async command void McuPowerState.update() {
+ }
+
+ default async command mcu_power_t McuPowerOverride.lowestState() {
+ return ATM128_POWER_DOWN;
+ }
+}
--- /dev/null
+// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+// @author Martin Turon <mturon@xbow.com>
+// @author Hu Siquan <husq@xbow.com>
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+// @author Janos Sallai <janos.sallai@vanderbilt.edu>
+
+/*
+ Updated chips/atm128 to include atm1281's ADCSRB register.
+*/
+
+#ifndef _H_Atm128ADC_h
+#define _H_Atm128ADC_h
+
+//================== 8 channel 10-bit ADC ==============================
+
+/* Voltage Reference Settings */
+enum {
+ ATM128_ADC_VREF_OFF = 0, //!< VR+ = AREF and VR- = GND
+ ATM128_ADC_VREF_AVCC = 1,//!< VR+ = AVcc and VR- = GND
+ ATM128_ADC_VREF_RSVD,
+ ATM128_ADC_VREF_2_56 = 3,//!< VR+ = 2.56V and VR- = GND
+};
+
+/* Voltage Reference Settings */
+enum {
+ ATM128_ADC_RIGHT_ADJUST = 0,
+ ATM128_ADC_LEFT_ADJUST = 1,
+};
+
+
+/* ADC Multiplexer Settings */
+enum {
+ ATM128_ADC_SNGL_ADC0 = 0,
+ ATM128_ADC_SNGL_ADC1,
+ ATM128_ADC_SNGL_ADC2,
+ ATM128_ADC_SNGL_ADC3,
+ ATM128_ADC_SNGL_ADC4,
+ ATM128_ADC_SNGL_ADC5,
+ ATM128_ADC_SNGL_ADC6,
+ ATM128_ADC_SNGL_ADC7,
+ ATM128_ADC_DIFF_ADC00_10x,
+ ATM128_ADC_DIFF_ADC10_10x,
+ ATM128_ADC_DIFF_ADC00_200x,
+ ATM128_ADC_DIFF_ADC10_200x,
+ ATM128_ADC_DIFF_ADC22_10x,
+ ATM128_ADC_DIFF_ADC32_10x,
+ ATM128_ADC_DIFF_ADC22_200x,
+ ATM128_ADC_DIFF_ADC32_200x,
+ ATM128_ADC_DIFF_ADC01_1x,
+ ATM128_ADC_DIFF_ADC11_1x,
+ ATM128_ADC_DIFF_ADC21_1x,
+ ATM128_ADC_DIFF_ADC31_1x,
+ ATM128_ADC_DIFF_ADC41_1x,
+ ATM128_ADC_DIFF_ADC51_1x,
+ ATM128_ADC_DIFF_ADC61_1x,
+ ATM128_ADC_DIFF_ADC71_1x,
+ ATM128_ADC_DIFF_ADC02_1x,
+ ATM128_ADC_DIFF_ADC12_1x,
+ ATM128_ADC_DIFF_ADC22_1x,
+ ATM128_ADC_DIFF_ADC32_1x,
+ ATM128_ADC_DIFF_ADC42_1x,
+ ATM128_ADC_DIFF_ADC52_1x,
+ ATM128_ADC_SNGL_1_23,
+ ATM128_ADC_SNGL_GND,
+};
+
+/* ADC Multiplexer Selection Register */
+typedef struct
+{
+ uint8_t mux : 5; //!< Analog Channel and Gain Selection Bits
+ uint8_t adlar : 1; //!< ADC Left Adjust Result
+ uint8_t refs : 2; //!< Reference Selection Bits
+} Atm128Admux_t;
+
+/* ADC Prescaler Settings */
+/* Note: each platform must define ATM128_ADC_PRESCALE to the smallest
+ prescaler which guarantees full A/D precision. */
+enum {
+ ATM128_ADC_PRESCALE_2 = 0,
+ ATM128_ADC_PRESCALE_2b,
+ ATM128_ADC_PRESCALE_4,
+ ATM128_ADC_PRESCALE_8,
+ ATM128_ADC_PRESCALE_16,
+ ATM128_ADC_PRESCALE_32,
+ ATM128_ADC_PRESCALE_64,
+ ATM128_ADC_PRESCALE_128,
+
+ // This special value is used to ask the platform for the prescaler
+ // which gives full precision.
+ ATM128_ADC_PRESCALE
+};
+
+/* ADC Enable Settings */
+enum {
+ ATM128_ADC_ENABLE_OFF = 0,
+ ATM128_ADC_ENABLE_ON,
+};
+
+/* ADC Start Conversion Settings */
+enum {
+ ATM128_ADC_START_CONVERSION_OFF = 0,
+ ATM128_ADC_START_CONVERSION_ON,
+};
+
+/* ADC Free Running Select Settings */
+enum {
+ ATM128_ADC_FREE_RUNNING_OFF = 0,
+ ATM128_ADC_FREE_RUNNING_ON,
+};
+
+/* ADC Interrupt Flag Settings */
+enum {
+ ATM128_ADC_INT_FLAG_OFF = 0,
+ ATM128_ADC_INT_FLAG_ON,
+};
+
+/* ADC Interrupt Enable Settings */
+enum {
+ ATM128_ADC_INT_ENABLE_OFF = 0,
+ ATM128_ADC_INT_ENABLE_ON,
+};
+
+/* ADC Multiplexer Selection Register */
+typedef struct
+{
+ uint8_t adps : 3; //!< ADC Prescaler Select Bits
+ uint8_t adie : 1; //!< ADC Interrupt Enable
+ uint8_t adif : 1; //!< ADC Interrupt Flag
+ uint8_t adate : 1; //!< ADC Auto Trigger Enable
+ uint8_t adsc : 1; //!< ADC Start Conversion
+ uint8_t aden : 1; //!< ADC Enable
+} Atm128Adcsra_t;
+
+/* ADC Multiplexer Selection Register */
+typedef struct
+{
+ uint8_t adts : 3; //!< ADC Trigger Select
+ uint8_t mux5 : 1; //!< Analog Channel and Gain Selection Bit
+ uint8_t resv1 : 2; //!< Reserved
+ uint8_t acme : 1; //!< Analog Comparator Multiplexer Enable
+ uint8_t resv2 : 1; //!< Reserved
+} Atm128Adcsrb_t;
+
+
+typedef uint8_t Atm128_ADCH_t; //!< ADC data register high
+typedef uint8_t Atm128_ADCL_t; //!< ADC data register low
+
+// The resource identifier string for the ADC subsystem
+#define UQ_ATM128ADC_RESOURCE "atm128adc.resource"
+
+#endif //_H_Atm128ADC_h
+
--- /dev/null
+/* $Id$
+ * "Copyright (c) 2000-2003 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2005 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ *
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ *
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+
+#include "Atm128Adc.h"
+
+/**
+ * Internal component of the Atmega1281 A/D HAL.
+ *
+ * @author Jason Hill
+ * @author David Gay
+ * @author Philip Levis
+ * @author Phil Buonadonna
+ * @author Hu Siquan <husq@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+module Atm128AdcP
+{
+ provides {
+ interface Init;
+ interface AsyncStdControl;
+ interface Atm128AdcSingle;
+ interface Atm128AdcMultiple;
+ }
+ uses {
+ interface HplAtm128Adc;
+ interface Atm128Calibrate;
+ }
+}
+implementation
+{
+ /* State for the current and next (multiple-sampling only) conversion */
+ struct {
+ bool multiple : 1; /* single and multiple-sampling mode */
+ bool precise : 1; /* is this result going to be precise? */
+ uint8_t channel : 5; /* what channel did this sample come from? */
+ } f, nextF;
+
+ command error_t Init.init() {
+ atomic
+ {
+ Atm128Adcsra_t adcsr;
+
+ adcsr.aden = ATM128_ADC_ENABLE_OFF;
+ adcsr.adsc = ATM128_ADC_START_CONVERSION_OFF;
+ adcsr.adate= ATM128_ADC_FREE_RUNNING_OFF;
+ adcsr.adif = ATM128_ADC_INT_FLAG_OFF;
+ adcsr.adie = ATM128_ADC_INT_ENABLE_OFF;
+ adcsr.adps = ATM128_ADC_PRESCALE_2;
+ call HplAtm128Adc.setAdcsra(adcsr);
+ }
+ return SUCCESS;
+ }
+
+ /* We enable the A/D when start is called, and disable it when stop is
+ called. This drops A/D conversion latency by a factor of two (but
+ increases idle mode power consumption a little).
+ */
+ async command error_t AsyncStdControl.start() {
+ atomic call HplAtm128Adc.enableAdc();
+ return SUCCESS;
+ }
+
+ async command error_t AsyncStdControl.stop() {
+ atomic call HplAtm128Adc.disableAdc();
+
+ return SUCCESS;
+ }
+
+ /* Return TRUE if switching to 'channel' with reference voltage 'refVoltage'
+ will give a precise result (the first sample after changing reference
+ voltage or switching to/between a differential channel is imprecise)
+ */
+ inline bool isPrecise(Atm128Admux_t admux, uint8_t channel, uint8_t refVoltage) {
+ return refVoltage == admux.refs &&
+ (channel <= ATM128_ADC_SNGL_ADC7 || channel >= ATM128_ADC_SNGL_1_23 || channel == admux.mux);
+ }
+
+ async event void HplAtm128Adc.dataReady(uint16_t data) {
+ bool precise, multiple;
+ uint8_t channel;
+
+ atomic
+ {
+ channel = f.channel;
+ precise = f.precise;
+ multiple = f.multiple;
+ }
+
+ if (!multiple)
+ {
+ /* A single sample. Disable the ADC interrupt to avoid starting
+ a new sample at the next "sleep" instruction. */
+ call HplAtm128Adc.disableInterruption();
+ signal Atm128AdcSingle.dataReady(data, precise);
+ }
+ else
+ {
+ /* Multiple sampling. The user can:
+ - tell us to stop sampling
+ - or, to continue sampling on a new channel, possibly with a
+ new reference voltage; however this change applies not to
+ the next sample (the hardware has already started working on
+ that), but on the one after.
+ */
+ bool cont;
+ uint8_t nextChannel, nextVoltage;
+ Atm128Admux_t admux;
+
+ atomic
+ {
+ admux = call HplAtm128Adc.getAdmux();
+ nextVoltage = admux.refs;
+ nextChannel = admux.mux;
+ }
+
+ cont = signal Atm128AdcMultiple.dataReady(data, precise, channel,
+ &nextChannel, &nextVoltage);
+ atomic
+ if (cont)
+ {
+ /* Switch channels and update our internal channel+precision
+ tracking state (f and nextF). Note that this tracking will
+ be incorrect if we take too long to get to this point. */
+ admux.refs = nextVoltage;
+ admux.mux = nextChannel;
+ call HplAtm128Adc.setAdmux(admux);
+
+ f = nextF;
+ nextF.channel = nextChannel;
+ nextF.precise = isPrecise(admux, nextChannel, nextVoltage);
+ }
+ else
+ call HplAtm128Adc.cancel();
+ }
+ }
+
+ /* Start sampling based on request parameters */
+ void getData(uint8_t channel, uint8_t refVoltage, bool leftJustify, uint8_t prescaler) {
+ Atm128Admux_t admux;
+ Atm128Adcsra_t adcsr;
+
+ admux = call HplAtm128Adc.getAdmux();
+ f.precise = isPrecise(admux, channel, refVoltage);
+ f.channel = channel;
+
+ admux.refs = refVoltage;
+ admux.adlar = leftJustify;
+ admux.mux = channel;
+ call HplAtm128Adc.setAdmux(admux);
+
+ adcsr.aden = ATM128_ADC_ENABLE_ON;
+ adcsr.adsc = ATM128_ADC_START_CONVERSION_ON;
+ adcsr.adate= f.multiple;
+ adcsr.adif = ATM128_ADC_INT_FLAG_ON; // clear any stale flag
+ adcsr.adie = ATM128_ADC_INT_ENABLE_ON;
+ if (prescaler == ATM128_ADC_PRESCALE)
+ prescaler = call Atm128Calibrate.adcPrescaler();
+ adcsr.adps = prescaler;
+ call HplAtm128Adc.setAdcsra(adcsr);
+ }
+
+ async command bool Atm128AdcSingle.getData(uint8_t channel, uint8_t refVoltage,
+ bool leftJustify, uint8_t prescaler) {
+ atomic
+ {
+ f.multiple = FALSE;
+ getData(channel, refVoltage, leftJustify, prescaler);
+
+ return f.precise;
+ }
+ }
+
+ async command bool Atm128AdcSingle.cancel() {
+ /* There is no Atm128AdcMultiple.cancel, for reasons discussed in that
+ interface */
+ return call HplAtm128Adc.cancel();
+ }
+
+ async command bool Atm128AdcMultiple.getData(uint8_t channel, uint8_t refVoltage,
+ bool leftJustify, uint8_t prescaler) {
+ atomic
+ {
+ f.multiple = TRUE;
+ getData(channel, refVoltage, leftJustify, prescaler);
+ nextF = f;
+ /* We assume the 2nd sample is precise */
+ nextF.precise = TRUE;
+
+ return f.precise;
+ }
+ }
+
+ default async event void Atm128AdcSingle.dataReady(uint16_t data, bool precise) {
+ }
+
+ default async event bool Atm128AdcMultiple.dataReady(uint16_t data, bool precise, uint8_t channel,
+ uint8_t *newChannel, uint8_t *newRefVoltage) {
+ return FALSE; // stop conversion if we somehow end up here.
+ }
+}
--- /dev/null
+/// $Id$
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+
+#include "Atm128Adc.h"
+
+/**
+ * HPL for the Atmega1281 A/D conversion susbsystem.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Hu Siquan <husq@xbow.com>
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+module HplAtm128AdcP {
+ provides interface HplAtm128Adc;
+ uses interface McuPowerState;
+}
+implementation {
+ //=== Direct read of HW registers. =================================
+ async command Atm128Admux_t HplAtm128Adc.getAdmux() {
+ return *(Atm128Admux_t*)&ADMUX;
+ }
+ async command Atm128Adcsra_t HplAtm128Adc.getAdcsra() {
+ return *(Atm128Adcsra_t*)&ADCSRA;
+ }
+ async command uint16_t HplAtm128Adc.getValue() {
+ return ADC;
+ }
+
+ DEFINE_UNION_CAST(Admux2int, Atm128Admux_t, uint8_t);
+ DEFINE_UNION_CAST(Adcsra2int, Atm128Adcsra_t, uint8_t);
+
+ //=== Direct write of HW registers. ================================
+ async command void HplAtm128Adc.setAdmux( Atm128Admux_t x ) {
+ ADMUX = Admux2int(x);
+ }
+ async command void HplAtm128Adc.setAdcsra( Atm128Adcsra_t x ) {
+ ADCSRA = Adcsra2int(x);
+ }
+
+ async command void HplAtm128Adc.setPrescaler(uint8_t scale){
+ Atm128Adcsra_t current_val = call HplAtm128Adc.getAdcsra();
+ current_val.adif = FALSE;
+ current_val.adps = scale;
+ call HplAtm128Adc.setAdcsra(current_val);
+ }
+
+ // Individual bit manipulation. These all clear any pending A/D interrupt.
+ // It's not clear these are that useful...
+ async command void HplAtm128Adc.enableAdc() {
+ SET_BIT(ADCSRA, ADEN);
+ call McuPowerState.update();
+ }
+ async command void HplAtm128Adc.disableAdc() {
+ CLR_BIT(ADCSRA, ADEN);
+ call McuPowerState.update();
+ }
+ async command void HplAtm128Adc.enableInterruption() { SET_BIT(ADCSRA, ADIE); }
+ async command void HplAtm128Adc.disableInterruption() { CLR_BIT(ADCSRA, ADIE); }
+ async command void HplAtm128Adc.setContinuous() {
+ ((Atm128Adcsrb_t*)&ADCSRB)->adts = 0;
+ SET_BIT(ADCSRA, ADATE);
+ }
+ async command void HplAtm128Adc.setSingle() { CLR_BIT(ADCSRA, ADATE); }
+ async command void HplAtm128Adc.resetInterrupt() { SET_BIT(ADCSRA, ADIF); }
+ async command void HplAtm128Adc.startConversion() { SET_BIT(ADCSRA, ADSC); }
+
+
+ /* A/D status checks */
+ async command bool HplAtm128Adc.isEnabled() {
+ return (call HplAtm128Adc.getAdcsra()).aden;
+ }
+
+ async command bool HplAtm128Adc.isStarted() {
+ return (call HplAtm128Adc.getAdcsra()).adsc;
+ }
+
+ async command bool HplAtm128Adc.isComplete() {
+ return (call HplAtm128Adc.getAdcsra()).adif;
+ }
+
+ /* A/D interrupt handlers. Signals dataReady event with interrupts enabled */
+ AVR_ATOMIC_HANDLER(SIG_ADC) {
+ uint16_t data = call HplAtm128Adc.getValue();
+
+ __nesc_enable_interrupt();
+ signal HplAtm128Adc.dataReady(data);
+ }
+
+ default async event void HplAtm128Adc.dataReady(uint16_t done) { }
+
+ async command bool HplAtm128Adc.cancel() {
+ /* This is tricky */
+ atomic
+ {
+ Atm128Adcsra_t oldSr = call HplAtm128Adc.getAdcsra(), newSr;
+
+ /* To cancel a conversion, first turn off ADEN, then turn off
+ ADSC. We also cancel any pending interrupt.
+ Finally we reenable the ADC.
+ */
+ newSr = oldSr;
+ newSr.aden = FALSE;
+ newSr.adif = TRUE; /* This clears a pending interrupt... */
+ newSr.adie = FALSE; /* We don't want to start sampling again at the
+ next sleep */
+ call HplAtm128Adc.setAdcsra(newSr);
+ newSr.adsc = FALSE;
+ call HplAtm128Adc.setAdcsra(newSr);
+ newSr.aden = TRUE;
+ call HplAtm128Adc.setAdcsra(newSr);
+
+ return oldSr.adif || oldSr.adsc;
+ }
+ }
+}
--- /dev/null
+/* tab:4
+ * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
+ * downloading, copying, installing or using the software you agree to
+ * this license. If you do not agree to this license, do not download,
+ * install, copy or use the software.
+ *
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc.
+ * Copyright (c) 2002-2003 Intel Corporation.
+ * Copyright (c) 2000-2003 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written
+ * agreement is hereby granted, provided that the above copyright
+ * notice, the (updated) modification history and the author appear in
+ * all copies of this source code.
+ *
+ * Permission is also granted to distribute this software under the
+ * standard BSD license as contained in the TinyOS distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/*
+ * Updated chips/atm128/atm128hardware.h with atm1281's MCU status and
+ * memory control registers.
+ *
+ * @author Janos Sallai, Martin Turon, Jason Hill, Philip Levis, Nelson Lee, David Gay
+ */
+
+
+#ifndef _H_atmega128hardware_H
+#define _H_atmega128hardware_H
+
+#include <avr/io.h>
+#if __AVR_LIBC_VERSION__ >= 10400UL
+#include <avr/interrupt.h>
+#else
+#include <avr/interrupt.h>
+#include <avr/signal.h>
+#endif
+#include <avr/wdt.h>
+#include <avr/pgmspace.h>
+#include "atm128const.h"
+
+/* We need slightly different defs than SIGNAL, INTERRUPT */
+#define AVR_ATOMIC_HANDLER(signame) \
+ void signame() __attribute__ ((signal)) @atomic_hwevent() @C()
+
+#define AVR_NONATOMIC_HANDLER(signame) \
+ void signame() __attribute__ ((interrupt)) @hwevent() @C()
+
+/* Macro to create union casting functions. */
+#define DEFINE_UNION_CAST(func_name, from_type, to_type) \
+ to_type func_name(from_type x) { \
+ union {from_type f; to_type t;} c = {f:x}; return c.t; }
+
+// Bit operators using bit number
+#define SET_BIT(port, bit) ((port) |= _BV(bit))
+#define CLR_BIT(port, bit) ((port) &= ~_BV(bit))
+#define READ_BIT(port, bit) (((port) & _BV(bit)) != 0)
+#define FLIP_BIT(port, bit) ((port) ^= _BV(bit))
+#define WRITE_BIT(port, bit, value) \
+ if (value) SET_BIT((port), (bit)); \
+ else CLR_BIT((port), (bit))
+
+// Bit operators using bit flag mask
+#define SET_FLAG(port, flag) ((port) |= (flag))
+#define CLR_FLAG(port, flag) ((port) &= ~(flag))
+#define READ_FLAG(port, flag) ((port) & (flag))
+
+/* Enables interrupts. */
+inline void __nesc_enable_interrupt() {
+ sei();
+}
+/* Disables all interrupts. */
+inline void __nesc_disable_interrupt() {
+ cli();
+}
+
+/* Defines data type for storing interrupt mask state during atomic. */
+typedef uint8_t __nesc_atomic_t;
+__nesc_atomic_t __nesc_atomic_start(void);
+void __nesc_atomic_end(__nesc_atomic_t original_SREG);
+
+#ifndef NESC_BUILD_BINARY
+/* @spontaneous() functions should not be included when NESC_BUILD_BINARY
+ is #defined, to avoid duplicate functions definitions wheb binary
+ components are used. Such functions do need a prototype in all cases,
+ though. */
+
+/* Saves current interrupt mask state and disables interrupts. */
+inline __nesc_atomic_t
+__nesc_atomic_start(void) @spontaneous()
+{
+ __nesc_atomic_t result = SREG;
+ __nesc_disable_interrupt();
+ asm volatile("" : : : "memory"); /* ensure atomic section effect visibility */
+ return result;
+}
+
+/* Restores interrupt mask to original state. */
+inline void
+__nesc_atomic_end(__nesc_atomic_t original_SREG) @spontaneous()
+{
+ asm volatile("" : : : "memory"); /* ensure atomic section effect visibility */
+ SREG = original_SREG;
+}
+#endif
+
+/* Defines the mcu_power_t type for atm128 power management. */
+typedef uint8_t mcu_power_t @combine("mcombine");
+
+
+enum {
+ ATM128_POWER_IDLE = 0,
+ ATM128_POWER_ADC_NR = 1,
+ ATM128_POWER_EXT_STANDBY = 2,
+ ATM128_POWER_SAVE = 3,
+ ATM128_POWER_STANDBY = 4,
+ ATM128_POWER_DOWN = 5,
+};
+
+/* Combine function. */
+mcu_power_t mcombine(mcu_power_t m1, mcu_power_t m2) {
+ return (m1 < m2)? m1: m2;
+}
+
+/* MCU Status Register*/
+typedef struct
+{
+ uint8_t porf : 1; //!< Power-on Reset Flag
+ uint8_t extrf : 1; //!< External Reset Flag
+ uint8_t borf : 1; //!< Brown-out Reset Flag
+ uint8_t wdrf : 1; //!< Watchdog Reset Flag
+ uint8_t jtrf : 1; //!< JTAG Reset Flag
+ uint8_t resv1 : 3; //!< Reserved
+} Atm128_MCUSR_t;
+
+/* External Memory Control Register A*/
+typedef struct
+{
+ uint8_t srw00 : 1; //!< Wait-state Select Bits for Lower Sector
+ uint8_t srw01 : 1; //!< Wait-state Select Bits for Lower Sector
+ uint8_t srw10 : 1; //!< Wait-state Select Bits for Upper Sector
+ uint8_t srw11 : 1; //!< Wait-state Select Bits for Upper Sector
+ uint8_t srl : 3; //!< Wait-state Sector Limit
+ uint8_t sre : 1; //!< External SRAM/XMEM Enable
+} Atm128_XMCRA_t;
+
+/* External Memory Control Register B*/
+typedef struct
+{
+ uint8_t xmm : 3; //!< External Memory High Mask
+ uint8_t resv1 : 4; //!< Reserved
+ uint8_t xmbk : 1; //!< External Memory Bus-keeper Enable
+} Atm128_XMCRB_t;
+
+
+#endif //_H_atmega128hardware_H
--- /dev/null
+// $Id$
+/*
+ * Copyright (c) 2007 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Build a 32-bit alarm and counter from the atmega1281's 8-bit timer 2
+ * in asynchronous mode. Attempting to use the generic Atm128AlarmC
+ * component and the generic timer components runs into problems
+ * apparently related to letting timer 2 overflow.
+ *
+ * So, instead, this version (inspired by the 1.x code and a remark from
+ * Martin Turon) directly builds a 32-bit alarm and counter on top of timer 2
+ * and never lets timer 2 overflow.
+ *
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+generic module Atm1281AlarmAsyncP(typedef precision, int divider) {
+ provides {
+ interface Init;
+ interface Alarm<precision, uint32_t>;
+ interface Counter<precision, uint32_t>;
+ }
+ uses {
+ interface HplAtm128Timer<uint8_t> as Timer;
+ interface HplAtm128TimerCtrl8 as TimerCtrl;
+ interface HplAtm128Compare<uint8_t> as Compare;
+ interface HplAtm128TimerAsync as TimerAsync;
+ }
+}
+implementation
+{
+ uint8_t set; /* Is the alarm set? */
+ uint32_t t0, dt; /* Time of the next alarm */
+ norace uint32_t base; /* base+TCNT2 is the current time if no
+ interrupt is pending. See Counter.get()
+ for the full details. */
+
+ enum {
+ MINDT = 2, /* Minimum interval between interrupts */
+ MAXT = 230 /* Maximum value to let timer 2 reach
+ (from Joe Polastre and Robert Szewczyk's
+ painful experiences with the 1.x timer ;-)) */
+ };
+
+ void setInterrupt();
+
+ /* Configure timer 2 */
+ command error_t Init.init() {
+ atomic
+ {
+ Atm128_TCCR2A_t x;
+ Atm128_TCCR2B_t y;
+
+ call TimerAsync.setTimer2Asynchronous();
+ x.flat = 0;
+ x.bits.wgm21 = 1; /* We use the clear-on-compare mode */
+ call TimerCtrl.setControlA(x.flat);
+ y.flat = 0;
+ y.bits.cs = divider;
+ call TimerCtrl.setControlB(y.flat);
+ call Compare.set(MAXT); /* setInterrupt needs a valid value here */
+ call Compare.start();
+ }
+ setInterrupt();
+ return SUCCESS;
+ }
+
+ /* Set compare register for timer 2 to n. But increment n by 1 if TCNT2
+ reaches this value before we can set the compare register.
+ */
+ void setOcr2A(uint8_t n) {
+ while (call TimerAsync.compareABusy())
+ ;
+ if (n == call Timer.get())
+ n++;
+ /* Support for overflow. Force interrupt at wrap around value.
+ This does not cause a backwards-in-time value as we do this
+ every time we set OCR2A. */
+ if (base + n + 1 < base)
+ n = -base - 1;
+ call Compare.set(n);
+ }
+
+ /* Update the compare register to trigger an interrupt at the
+ appropriate time based on the current alarm settings
+ */
+ void setInterrupt() {
+ bool fired = FALSE;
+
+ atomic
+ {
+ /* interrupt_in is the time to the next interrupt. Note that
+ compare register values are off by 1 (i.e., if you set OCR2A to
+ 3, the interrupt will happen when TCNT2 is 4) */
+ uint8_t interrupt_in = 1 + call Compare.get() - call Timer.get();
+ uint8_t newOcr2A;
+ uint8_t tifr2 = call TimerCtrl.getInterruptFlag();
+ dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: TIFR is %hhx\n", tifr2);
+ if ((interrupt_in != 0 && interrupt_in < MINDT) || (tifr2 & (1 << OCF2A))) {
+ if (interrupt_in < MINDT) {
+ dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: under min: %hhu.\n", interrupt_in);
+ }
+ else {
+ dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: OCF2A set.\n");
+ }
+ return; // wait for next interrupt
+ }
+
+ /* When no alarm is set, we just ask for an interrupt every MAXT */
+ if (!set) {
+ newOcr2A = MAXT;
+ dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: no alarm set, set at max.\n");
+ }
+ else
+ {
+ uint32_t now = call Counter.get();
+ dbg("Atm1281AlarmAsyncP", "Atm1281AlarmAsyncP: now-t0 = %llu, dt = %llu\n", (now-t0), dt);
+ /* Check if alarm expired */
+ if ((uint32_t)(now - t0) >= dt)
+ {
+ set = FALSE;
+ fired = TRUE;
+ newOcr2A = MAXT;
+ }
+ else
+ {
+ /* No. Set compare register to time of next alarm if it's
+ within the next MAXT units */
+ uint32_t alarm_in = (t0 + dt) - base;
+
+ if (alarm_in > MAXT)
+ newOcr2A = MAXT;
+ else if ((uint8_t)alarm_in < MINDT) // alarm_in < MAXT ...
+ newOcr2A = MINDT;
+ else
+ newOcr2A = alarm_in;
+ }
+ }
+ newOcr2A--; // interrupt is 1ms late
+ setOcr2A(newOcr2A);
+ }
+ if (fired)
+ signal Alarm.fired();
+ }
+
+ async event void Compare.fired() {
+ int overflowed;
+
+ /* Compare register fired. Update time knowledge */
+ base += call Compare.get() + 1U; // interrupt is 1ms late
+ overflowed = !base;
+ __nesc_enable_interrupt();
+ setInterrupt();
+ if (overflowed)
+ signal Counter.overflow();
+ }
+
+ async command uint32_t Counter.get() {
+ uint32_t now;
+
+ atomic
+ {
+ /* Current time is base+TCNT2 if no interrupt is pending. But if
+ an interrupt is pending, then it's base + compare value + 1 + TCNT2 */
+ uint8_t now8 = call Timer.get();
+
+ if ((((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag())).bits.ocfa)
+ /* We need to reread TCNT2 as it might've overflowed after we
+ read TCNT2 the first time */
+ now = base + call Compare.get() + 1 + call Timer.get();
+ else
+ /* We need to use the value of TCNT2 from before we check the
+ interrupt flag, as it might wrap around after the check */
+ now = base + now8;
+ }
+ return now;
+ }
+
+ async command bool Counter.isOverflowPending() {
+ atomic
+ return (((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag())).bits.ocfa &&
+ !(base + call Compare.get() + 1);
+ }
+
+ async command void Counter.clearOverflow() {
+ atomic
+ if (call Counter.isOverflowPending())
+ {
+ base = 0;
+ call Compare.reset();
+ }
+ else
+ return;
+ setInterrupt();
+ }
+
+ async command void Alarm.start(uint32_t ndt) {
+ call Alarm.startAt(call Counter.get(), ndt);
+ }
+
+ async command void Alarm.stop() {
+ atomic set = FALSE;
+ }
+
+ async command bool Alarm.isRunning() {
+ atomic return set;
+ }
+
+ async command void Alarm.startAt(uint32_t nt0, uint32_t ndt) {
+ atomic
+ {
+ set = TRUE;
+ t0 = nt0;
+ dt = ndt;
+ }
+ setInterrupt();
+ }
+
+ async command uint32_t Alarm.getNow() {
+ return call Counter.get();
+ }
+
+ async command uint32_t Alarm.getAlarm() {
+ atomic return t0 + dt;
+ }
+
+ async event void Timer.overflow() { }
+}
--- /dev/null
+// $Id$
+/*
+ * Copyright (c) 2007 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Build a 32-bit alarm and counter from the atmega1281's 8-bit timer 2
+ * in asynchronous mode. Attempting to use the generic Atm128AlarmC
+ * component and the generic timer components runs into problems
+ * apparently related to letting timer 2 overflow.
+ *
+ * So, instead, this version (inspired by the 1.x code and a remark from
+ * Martin Turon) directly builds a 32-bit alarm and counter on top of timer 2
+ * and never lets timer 2 overflow.
+ *
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+generic configuration Atm128AlarmAsyncC(typedef precision, int divider) {
+ provides {
+ interface Init @atleastonce();
+ interface Alarm<precision, uint32_t>;
+ interface Counter<precision, uint32_t>;
+ }
+}
+implementation
+{
+ components new Atm1281AlarmAsyncP(precision, divider),
+ HplAtm1281Timer2AsyncC;
+
+ Init = Atm1281AlarmAsyncP;
+ Alarm = Atm1281AlarmAsyncP;
+ Counter = Atm1281AlarmAsyncP;
+
+ Atm1281AlarmAsyncP.Timer -> HplAtm1281Timer2AsyncC;
+ Atm1281AlarmAsyncP.TimerCtrl -> HplAtm1281Timer2AsyncC;
+ Atm1281AlarmAsyncP.Compare -> HplAtm1281Timer2AsyncC;
+ Atm1281AlarmAsyncP.TimerAsync -> HplAtm1281Timer2AsyncC;
+}
--- /dev/null
+// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+
+/*
+ * This file contains the configuration constants for the Atmega1281
+ * clocks and timers.
+ *
+ * @author Philip Levis
+ * @author Martin Turon
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#ifndef _H_Atm128Timer_h
+#define _H_Atm128Timer_h
+
+/* Prescaler values for Timer/Counter 2 (8-bit asynchronous ) */
+enum {
+ ATM128_CLK8_OFF = 0x0,
+ ATM128_CLK8_NORMAL = 0x1,
+ ATM128_CLK8_DIVIDE_8 = 0x2,
+ ATM128_CLK8_DIVIDE_32 = 0x3,
+ ATM128_CLK8_DIVIDE_64 = 0x4,
+ ATM128_CLK8_DIVIDE_128 = 0x5,
+ ATM128_CLK8_DIVIDE_256 = 0x6,
+ ATM128_CLK8_DIVIDE_1024 = 0x7,
+};
+
+/* Prescaler values for Timer/Counter 0 (8-bit) and 1, 3, 4, 5 (16-bit) */
+enum {
+ ATM128_CLK16_OFF = 0x0,
+ ATM128_CLK16_NORMAL = 0x1,
+ ATM128_CLK16_DIVIDE_8 = 0x2,
+ ATM128_CLK16_DIVIDE_64 = 0x3,
+ ATM128_CLK16_DIVIDE_256 = 0x4,
+ ATM128_CLK16_DIVIDE_1024 = 0x5,
+ ATM128_CLK16_EXTERNAL_FALL = 0x6,
+ ATM128_CLK16_EXTERNAL_RISE = 0x7,
+};
+
+/* Common scales across both 8-bit and 16-bit clocks. */
+enum {
+ AVR_CLOCK_OFF = 0,
+ AVR_CLOCK_ON = 1,
+ AVR_CLOCK_DIVIDE_8 = 2,
+};
+
+enum {
+ ATM128_TIMER_COMPARE_NORMAL = 0,
+ ATM128_TIMER_COMPARE_TOGGLE,
+ ATM128_TIMER_COMPARE_CLEAR,
+ ATM128_TIMER_COMPARE_SET
+};
+
+
+/* 8-bit Waveform Generation Modes */
+enum {
+ ATM128_WAVE8_NORMAL = 0,
+ ATM128_WAVE8_PWM,
+ ATM128_WAVE8_CTC,
+ ATM128_WAVE8_PWM_FAST,
+};
+
+/* 16-bit Waveform Generation Modes */
+enum {
+ ATM128_WAVE16_NORMAL = 0,
+ ATM128_WAVE16_PWM_8BIT,
+ ATM128_WAVE16_PWM_9BIT,
+ ATM128_WAVE16_PWM_10BIT,
+ ATM128_WAVE16_CTC_COMPARE,
+ ATM128_WAVE16_PWM_FAST_8BIT,
+ ATM128_WAVE16_PWM_FAST_9BIT,
+ ATM128_WAVE16_PWM_FAST_10BIT,
+ ATM128_WAVE16_PWM_CAPTURE_LOW,
+ ATM128_WAVE16_PWM_COMPARE_LOW,
+ ATM128_WAVE16_PWM_CAPTURE_HIGH,
+ ATM128_WAVE16_PWM_COMPARE_HIGH,
+ ATM128_WAVE16_CTC_CAPTURE,
+ ATM128_WAVE16_RESERVED,
+ ATM128_WAVE16_PWM_FAST_CAPTURE,
+ ATM128_WAVE16_PWM_FAST_COMPARE,
+};
+
+/* 8-bit Timer compare settings */
+enum {
+ ATM128_COMPARE_OFF = 0, //!< compare disconnected
+ ATM128_COMPARE_TOGGLE, //!< toggle on match (PWM reserved
+ ATM128_COMPARE_CLEAR, //!< clear on match (PWM downcount)
+ ATM128_COMPARE_SET, //!< set on match (PWN upcount)
+};
+
+/* 8-bit Timer/Counter 0 Control Register A*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t wgm00 : 1; //!< Waveform generation mode (low bit)
+ uint8_t wgm01 : 1; //!< Waveform generation mode (high bit)
+ uint8_t resv1 : 2; //!< Compare Match Output
+ uint8_t com0b0: 1; //!< Compare Match Output
+ uint8_t com0b1: 1; //!< Compare Match Output
+ uint8_t com0a0: 1; //!< Compare Match Output
+ uint8_t com0a1: 1; //!< Compare Match Output
+ } bits;
+} Atm128_TCCR0A_t;
+
+/* 8-bit Timer/Counter 0 Control Register B*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t cs00 : 1; //!< Clock Select 0
+ uint8_t cs01 : 1; //!< Clock Select 1
+ uint8_t cs02 : 2; //!< Clock Select 2
+ uint8_t wgm02 : 1; //!< Waveform Generation Mode
+ uint8_t resv1 : 2; //!< Reserved
+ uint8_t foc0b : 1; //!< Force Output Compare B
+ uint8_t foc0a : 1; //!< Force Output Compare A
+ } bits;
+} Atm128_TCCR0B_t;
+
+/* Timer/Counter 0 Interrupt Mask Register */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t toie0 : 1; //!< Timer/Counter0 Overflow Interrupt Enable
+ uint8_t ocie0a: 1; //!< Timer/Counter0 Output Compare Match A Interrupt Enable
+ uint8_t ocie0e: 1; //!< Timer/Counter Output Compare Match B Interrupt Enable
+ uint8_t resv1 : 5; //!< Reserved
+ } bits;
+} Atm128_TIMSK0_t;
+
+/* Timer/Counter 0 Interrupt Flag Register*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t tov0 : 1; //!< Timer/Counter0 Overflow Flag
+ uint8_t ocf0a : 1; //!< Timer/Counter 0 Output Compare A Match Flag
+ uint8_t ocf0b : 1; //!< Timer/Counter 0 Output Compare B Match Flag
+ uint8_t resv1 : 5; //!< Reserved
+ } bits;
+} Atm128_TIFR0_t;
+
+/* Asynchronous Status Register -- Timer2 */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t tcr2bub: 1; //!< Timer/Counter Control Register2 Update Busy
+ uint8_t tcr2aub: 1; //!< Timer/Counter Control Register2 Update Busy
+ uint8_t ocr2bub: 1; //!< Output Compare Register2 Update Busy
+ uint8_t ocr2aub: 1; //!< Output Compare Register2 Update Busy
+ uint8_t tcn2ub : 1; //!< Timer/Counter2 Update Busy
+ uint8_t as2 : 1; //!< Asynchronous Timer/Counter2 (off=CLK_IO,on=TOSC1)
+ uint8_t exclk : 1; //!< Enable External Clock Input
+ uint8_t resv1 : 1; //!< Reserved
+ } bits;
+} Atm128_ASSR_t;
+
+/* Timer/Counter 2 Control Register A*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t wgm20 : 1; //!< Waveform Generation Mode
+ uint8_t wgm21 : 1; //!< Waveform Generation Mode
+ uint8_t resv1 : 2; //!< Reserved
+ uint8_t comb: 2; //!< Compare Output Mode for Channel B
+ uint8_t coma: 2; //!< Compare Output Mode for Channel A
+ } bits;
+} Atm128_TCCR2A_t;
+
+/* Timer/Counter 2 Control Register B*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t cs : 3; //!< Clock Select
+ uint8_t wgm22 : 1; //!< Waveform Generation Mode
+ uint8_t resv1 : 2; //!< Reserved
+ uint8_t foc2b : 1; //!< Force Output Compare B
+ uint8_t foc2a : 1; //!< Force Output Compare A
+ } bits;
+} Atm128_TCCR2B_t;
+
+/* Timer/Counter 2 Interrupt Mask Register */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t toie : 1; //!< Timer/Counter2 Overflow Interrupt Enable
+ uint8_t ociea: 1; //!< Timer/Counter2 Output Compare Match A Interrupt Enable
+ uint8_t ocieb: 1; //!< Timer/Counter Output Compare Match B Interrupt Enable
+ uint8_t resv1 : 5; //!< Reserved
+ } bits;
+} Atm128_TIMSK2_t;
+
+/* Timer/Counter 2 Interrupt Flag Register */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t tov : 1; //!< Timer1 Overflow Flag
+ uint8_t ocfa : 1; //!< Timer1 Output Compare Flag A
+ uint8_t ocfb : 1; //!< Timer1 Output Compare Flag B
+ uint8_t resv1 : 5; //!< Reserved
+ } bits;
+} Atm128_TIFR2_t;
+
+
+/* Timer/Counter 1,3,4,5 Control Register A*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t wgm01 : 2; //!< Waveform Generation Mode
+ uint8_t comc : 2; //!< Compare Output Mode for Channel C
+ uint8_t comb : 2; //!< Compare Output Mode for Channel B
+ uint8_t coma : 2; //!< Compare Output Mode for Channel A
+ } bits;
+} Atm128_TCCRA_t;
+
+/* Timer/Counter 1,3,4,5 Control Register B*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t cs : 3; //!< Clock Select
+ uint8_t wgm23 : 2; //!< Waveform Generation Mode
+ uint8_t resv1 : 1; //!< Reserved
+ uint8_t ices : 1; //!< Input Capture Edge Select
+ uint8_t icnc : 1; //!< Input Capture Noise Canceler
+ } bits;
+} Atm128_TCCRB_t;
+
+/* Timer/Counter 1,3,4,5 Control Register C*/
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t resv1 : 5; //!< Reserved
+ uint8_t focc : 1; //!< Force Output Compare for Channel A
+ uint8_t focb : 1; //!< Force Output Compare for Channel A
+ uint8_t foca : 1; //!< Force Output Compare for Channel A
+ } bits;
+} Atm128_TCCRC_t;
+
+/* Timer/Counter 1,3,4,5 Interrupt Mask Register */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t toie : 1; //!< Timer/Counter1 Overflow Interrupt Enable
+ uint8_t ociea: 1; //!< Timer/Counter1 Output Compare Match A Interrupt Enable
+ uint8_t ocieb: 1; //!< Timer/Counter1 Output Compare Match B Interrupt Enable
+ uint8_t ociec: 1; //!< Timer/Counter1 Output Compare Match C Interrupt Enable
+ uint8_t resv1: 1; //!< Reserved
+ uint8_t icie : 1; //!< Timer/Counter1, Input Capture Interrupt Enable
+ uint8_t resv2 : 2; //!< Reserved
+ } bits;
+} Atm128_TIMSK_t;
+
+/* Timer/Counter 1,3,4,5 Interrupt Flag Register */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t tov : 1; //!< Timer1 Overflow Flag
+ uint8_t ocfa : 1; //!< Timer1 Output Compare Flag A
+ uint8_t ocfb : 1; //!< Timer1 Output Compare Flag B
+ uint8_t ocfc : 1; //!< Timer1 Output Compare Flag C
+ uint8_t resv1: 1; //!< Reserved
+ uint8_t icf : 1; //!< Timer1 Input Capture Flag
+ uint8_t resv2: 2; //!< Reserved
+ } bits;
+} Atm128_TIFR_t;
+
+/* General Timer/Counter Control Register */
+typedef union
+{
+ uint8_t flat;
+ struct {
+ uint8_t psrsync: 1; //!< Prescaler Reset for Synchronous Timer/Counters 0,1,3,4,5
+ uint8_t psrasy : 1; //!< Prescaler Reset Timer/Counter2
+ uint8_t resv1 : 5; //!< Reserved
+ uint8_t tsm : 1; //!< Timer/Counter Synchronization Mode
+ } bits;
+} Atm128_GTCCR_t;
+
+// Read/Write these 16-bit Timer registers
+// Access as bytes. Read low before high. Write high before low.
+typedef uint8_t Atm128_TCNT1H_t; //!< Timer1 Register
+typedef uint8_t Atm128_TCNT1L_t; //!< Timer1 Register
+typedef uint8_t Atm128_TCNT3H_t; //!< Timer3 Register
+typedef uint8_t Atm128_TCNT3L_t; //!< Timer3 Register
+typedef uint8_t Atm128_TCNT4H_t; //!< Timer4 Register
+typedef uint8_t Atm128_TCNT4L_t; //!< Timer4 Register
+typedef uint8_t Atm128_TCNT5H_t; //!< Timer5 Register
+typedef uint8_t Atm128_TCNT5L_t; //!< Timer5 Register
+
+/* Contains value to continuously compare with Timer1 */
+typedef uint8_t Atm128_OCR1AH_t; //!< Output Compare Register 1A
+typedef uint8_t Atm128_OCR1AL_t; //!< Output Compare Register 1A
+typedef uint8_t Atm128_OCR1BH_t; //!< Output Compare Register 1B
+typedef uint8_t Atm128_OCR1BL_t; //!< Output Compare Register 1B
+typedef uint8_t Atm128_OCR1CH_t; //!< Output Compare Register 1C
+typedef uint8_t Atm128_OCR1CL_t; //!< Output Compare Register 1C
+
+/* Contains value to continuously compare with Timer3 */
+typedef uint8_t Atm128_OCR3AH_t; //!< Output Compare Register 3A
+typedef uint8_t Atm128_OCR3AL_t; //!< Output Compare Register 3A
+typedef uint8_t Atm128_OCR3BH_t; //!< Output Compare Register 3B
+typedef uint8_t Atm128_OCR3BL_t; //!< Output Compare Register 3B
+typedef uint8_t Atm128_OCR3CH_t; //!< Output Compare Register 3C
+typedef uint8_t Atm128_OCR3CL_t; //!< Output Compare Register 3C
+
+/* Contains value to continuously compare with Timer4 */
+typedef uint8_t Atm128_OCR4AH_t; //!< Output Compare Register 4A
+typedef uint8_t Atm128_OCR4AL_t; //!< Output Compare Register 4A
+typedef uint8_t Atm128_OCR4BH_t; //!< Output Compare Register 4B
+typedef uint8_t Atm128_OCR4BL_t; //!< Output Compare Register 4B
+typedef uint8_t Atm128_OCR4CH_t; //!< Output Compare Register 4C
+typedef uint8_t Atm128_OCR4CL_t; //!< Output Compare Register 4C
+
+/* Contains value to continuously compare with Timer5 */
+typedef uint8_t Atm128_OCR5AH_t; //!< Output Compare Register 5A
+typedef uint8_t Atm128_OCR5AL_t; //!< Output Compare Register 5A
+typedef uint8_t Atm128_OCR5BH_t; //!< Output Compare Register 5B
+typedef uint8_t Atm128_OCR5BL_t; //!< Output Compare Register 5B
+typedef uint8_t Atm128_OCR5CH_t; //!< Output Compare Register 5C
+typedef uint8_t Atm128_OCR5CL_t; //!< Output Compare Register 5C
+
+/* Contains counter value when event occurs on ICPn pin. */
+typedef uint8_t Atm128_ICR1H_t; //!< Input Capture Register 1
+typedef uint8_t Atm128_ICR1L_t; //!< Input Capture Register 1
+typedef uint8_t Atm128_ICR3H_t; //!< Input Capture Register 3
+typedef uint8_t Atm128_ICR3L_t; //!< Input Capture Register 3
+typedef uint8_t Atm128_ICR4H_t; //!< Input Capture Register 4
+typedef uint8_t Atm128_ICR4L_t; //!< Input Capture Register 4
+typedef uint8_t Atm128_ICR5H_t; //!< Input Capture Register 5
+typedef uint8_t Atm128_ICR5L_t; //!< Input Capture Register 5
+
+/* Resource strings for timer 1 and 3 compare registers */
+#define UQ_TIMER1_COMPARE "atm128.timer1"
+#define UQ_TIMER3_COMPARE "atm128.timer3"
+
+#endif //_H_Atm128Timer_h
+
--- /dev/null
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Internal component of the HPL interface to Atmega1281 timer 1.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+module HplAtm1281Timer1P
+{
+ provides {
+ // 16-bit Timers
+ interface HplAtm128Timer<uint16_t> as Timer;
+ interface HplAtm128TimerCtrl16 as TimerCtrl;
+ interface HplAtm128Capture<uint16_t> as Capture;
+ interface HplAtm128Compare<uint16_t> as CompareA;
+ interface HplAtm128Compare<uint16_t> as CompareB;
+ interface HplAtm128Compare<uint16_t> as CompareC;
+ }
+}
+implementation
+{
+ //=== Read the current timer value. ===================================
+ async command uint16_t Timer.get() { return TCNT1; }
+
+ //=== Set/clear the current timer value. ==============================
+ async command void Timer.set(uint16_t t) { TCNT1 = t; }
+
+ //=== Read the current timer scale. ===================================
+ async command uint8_t Timer.getScale() { return TCCR1B & 0x7; }
+
+ //=== Turn off the timers. ============================================
+ async command void Timer.off() { call Timer.setScale(AVR_CLOCK_OFF); }
+
+ //=== Write a new timer scale. ========================================
+ async command void Timer.setScale(uint8_t s) {
+ Atm128_TCCRB_t x = (Atm128_TCCRB_t) call TimerCtrl.getControlB();
+ x.bits.cs = s;
+ call TimerCtrl.setControlB(x.flat);
+ }
+
+ //=== Read the control registers. =====================================
+ async command uint8_t TimerCtrl.getControlA() {
+ return TCCR1A;
+ }
+
+ async command uint8_t TimerCtrl.getControlB() {
+ return TCCR1B;
+ }
+
+ async command uint8_t TimerCtrl.getControlC() {
+ return TCCR1C;
+ }
+
+ //=== Write the control registers. ====================================
+ async command void TimerCtrl.setControlA( uint8_t x ) {
+ TCCR1A = x;
+ }
+
+ async command void TimerCtrl.setControlB( uint8_t x ) {
+ TCCR1B = x;
+ }
+
+ async command void TimerCtrl.setControlC( uint8_t x ) {
+ TCCR1C = x;
+ }
+
+ //=== Read the interrupt mask. =====================================
+ async command uint8_t TimerCtrl.getInterruptMask() {
+ return TIMSK1;
+ }
+
+ //=== Write the interrupt mask. ====================================
+ async command void TimerCtrl.setInterruptMask( uint8_t x ) {
+ TIMSK1 = x;
+ }
+
+ //=== Read the interrupt flags. =====================================
+ async command uint8_t TimerCtrl.getInterruptFlag() {
+ return TIFR1;
+ }
+
+ //=== Write the interrupt flags. ====================================
+ async command void TimerCtrl.setInterruptFlag( uint8_t x ) {
+ TIFR1 = x;
+ }
+
+ //=== Capture 16-bit implementation. ===================================
+ async command void Capture.setEdge(bool up) { WRITE_BIT(TCCR1B,ICES1, up); }
+
+ //=== Timer 16-bit implementation. ===================================
+ async command void Timer.reset() { TIFR1 = 1 << TOV1; }
+ async command void Capture.reset() { TIFR1 = 1 << ICF1; }
+ async command void CompareA.reset() { TIFR1 = 1 << OCF1A; }
+ async command void CompareB.reset() { TIFR1 = 1 << OCF1B; }
+ async command void CompareC.reset() { TIFR1 = 1 << OCF1C; }
+
+ async command void Timer.start() { SET_BIT(TIMSK1,TOIE1); }
+ async command void Capture.start() { SET_BIT(TIMSK1,ICIE1); }
+ async command void CompareA.start() { SET_BIT(TIMSK1,OCIE1A); }
+ async command void CompareB.start() { SET_BIT(TIMSK1,OCIE1B); }
+ async command void CompareC.start() { SET_BIT(TIMSK1,OCIE1C); }
+
+ async command void Timer.stop() { CLR_BIT(TIMSK1,TOIE1); }
+ async command void Capture.stop() { CLR_BIT(TIMSK1,ICIE1); }
+ async command void CompareA.stop() { CLR_BIT(TIMSK1,OCIE1A); }
+ async command void CompareB.stop() { CLR_BIT(TIMSK1,OCIE1B); }
+ async command void CompareC.stop() { CLR_BIT(TIMSK1,OCIE1C); }
+
+ async command bool Timer.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.tov;
+ }
+ async command bool Capture.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.icf;
+ }
+ async command bool CompareA.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfa;
+ }
+ async command bool CompareB.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfb;
+ }
+ async command bool CompareC.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfc;
+ }
+
+ async command bool Timer.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.toie;
+ }
+ async command bool Capture.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.icie;
+ }
+ async command bool CompareA.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociea;
+ }
+ async command bool CompareB.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ocieb;
+ }
+ async command bool CompareC.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociec;
+ }
+
+ //=== Read the compare registers. =====================================
+ async command uint16_t CompareA.get() { return OCR1A; }
+ async command uint16_t CompareB.get() { return OCR1B; }
+ async command uint16_t CompareC.get() { return OCR1C; }
+
+ //=== Write the compare registers. ====================================
+ async command void CompareA.set(uint16_t t) { OCR1A = t; }
+ async command void CompareB.set(uint16_t t) { OCR1B = t; }
+ async command void CompareC.set(uint16_t t) { OCR1C = t; }
+
+ //=== Read the capture registers. =====================================
+ async command uint16_t Capture.get() { return ICR1; }
+
+ //=== Write the capture registers. ====================================
+ async command void Capture.set(uint16_t t) { ICR1 = t; }
+
+ //=== Timer interrupts signals ========================================
+ default async event void CompareA.fired() { }
+ AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE1A) {
+ signal CompareA.fired();
+ }
+ default async event void CompareB.fired() { }
+ AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE1B) {
+ signal CompareB.fired();
+ }
+ default async event void CompareC.fired() { }
+ AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE1C) {
+ signal CompareC.fired();
+ }
+ default async event void Capture.captured(uint16_t time) { }
+ AVR_NONATOMIC_HANDLER(SIG_INPUT_CAPTURE1) {
+ signal Capture.captured(call Timer.get());
+ }
+ default async event void Timer.overflow() { }
+ AVR_NONATOMIC_HANDLER(SIG_OVERFLOW1) {
+ signal Timer.overflow();
+ }
+}
--- /dev/null
+/// $Id$
+/*
+ * Copyright (c) 2006 Stanford University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Stanford University nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD
+ * UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Simple wrapper around the actual timer implementation that automatically
+ * wires it to McuSleepC for low-power calculations..
+ *
+ * @author Philip Levis
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+configuration HplAtm1281Timer2AsyncC
+{
+ provides {
+ // 8-bit Timers
+ interface HplAtm128Timer<uint8_t> as Timer;
+ interface HplAtm128TimerCtrl8 as TimerCtrl;
+ interface HplAtm128Compare<uint8_t> as Compare;
+ interface HplAtm128TimerAsync as TimerAsync;
+ }
+}
+implementation
+{
+ components HplAtm1281Timer2AsyncP;
+ components McuSleepC;
+
+ McuSleepC.McuPowerOverride -> HplAtm1281Timer2AsyncP;
+
+ Timer = HplAtm1281Timer2AsyncP;
+ TimerCtrl = HplAtm1281Timer2AsyncP;
+ Compare = HplAtm1281Timer2AsyncP;
+ TimerAsync = HplAtm1281Timer2AsyncP;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL interface to Atmega1281 timer 2 in ASYNC mode. This is a specialised
+ * HPL component that assumes that timer 2 is used in ASYNC mode and
+ * includes some workarounds for some of the weirdnesses (delayed overflow
+ * interrupt) of that mode.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay <dgay@intel-research.net>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+module HplAtm1281Timer2AsyncP
+{
+ provides {
+ // 8-bit Timers
+ interface HplAtm128Timer<uint8_t> as Timer;
+ interface HplAtm128TimerCtrl8 as TimerCtrl;
+ interface HplAtm128Compare<uint8_t> as Compare;
+ interface McuPowerOverride;
+ interface HplAtm128TimerAsync as TimerAsync;
+ }
+}
+implementation
+{
+// bool inOverflow;
+
+// command error_t Init.init() {
+// SET_BIT(ASSR, AS2); // set Timer/Counter2 to asynchronous mode
+// return SUCCESS;
+// }
+
+ //=== Read the current timer value. ===================================
+ async command uint8_t Timer.get() { return TCNT2; }
+
+ //=== Set/clear the current timer value. ==============================
+ async command void Timer.set(uint8_t t) {
+ while (ASSR & 1 << TCN2UB)
+ ;
+ TCNT2 = t;
+ }
+
+ //=== Read the current timer scale. ===================================
+ async command uint8_t Timer.getScale() { return TCCR2B & 0x7; }
+
+ //=== Turn off the timers. ============================================
+ async command void Timer.off() { call Timer.setScale(AVR_CLOCK_OFF); }
+
+ //=== Write a new timer scale. ========================================
+ async command void Timer.setScale(uint8_t s) {
+ Atm128_TCCR2B_t x = (Atm128_TCCR2B_t) call TimerCtrl.getControlB();
+ x.bits.cs = s;
+ call TimerCtrl.setControlB(x.flat);
+ }
+
+ //=== Read the control registers. =====================================
+ async command uint8_t TimerCtrl.getControlA() {
+ return TCCR2A;
+ }
+
+ async command uint8_t TimerCtrl.getControlB() {
+ return TCCR2B;
+ }
+
+ //=== Write the control registers. ====================================
+ async command void TimerCtrl.setControlA( uint8_t x ) {
+ while (ASSR & 1 << TCR2AUB)
+ ;
+ TCCR2A = ((Atm128_TCCR2A_t)x).flat;
+ }
+
+ async command void TimerCtrl.setControlB( uint8_t x ) {
+ while (ASSR & 1 << TCR2BUB)
+ ;
+ TCCR2B = ((Atm128_TCCR2B_t)x).flat;
+ }
+
+ //=== Read the interrupt mask. =====================================
+ async command uint8_t TimerCtrl.getInterruptMask() {
+ return TIMSK2;
+ }
+
+ //=== Write the interrupt mask. ====================================
+ async command void TimerCtrl.setInterruptMask( uint8_t x ) {
+ TIMSK2 = x;
+ }
+
+ //=== Read the interrupt flags. =====================================
+ async command uint8_t TimerCtrl.getInterruptFlag() {
+ return TIFR2;
+ }
+
+ //=== Write the interrupt flags. ====================================
+ async command void TimerCtrl.setInterruptFlag( uint8_t x ) {
+ TIFR2 = x;
+ }
+
+ //=== Timer 8-bit implementation. ====================================
+ async command void Timer.reset() { TIFR2 = 1 << TOV2; }
+ async command void Timer.start() { SET_BIT(TIMSK2, TOIE2); }
+ async command void Timer.stop() { CLR_BIT(TIMSK2, TOIE2); }
+
+ bool overflowed() {
+ return ((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag()).bits.tov;
+ }
+
+ async command bool Timer.test() {
+ return overflowed();
+ }
+
+ async command bool Timer.isOn() {
+ return ((Atm128_TIMSK2_t)call TimerCtrl.getInterruptMask()).bits.toie;
+ }
+
+ async command void Compare.reset() { TIFR2 = 1 << OCF2A; }
+ async command void Compare.start() { SET_BIT(TIMSK2,OCIE2A); }
+ async command void Compare.stop() { CLR_BIT(TIMSK2,OCIE2A); }
+ async command bool Compare.test() {
+ return ((Atm128_TIFR2_t)call TimerCtrl.getInterruptFlag()).bits.ocfa;
+ }
+ async command bool Compare.isOn() {
+ return ((Atm128_TIMSK2_t)call TimerCtrl.getInterruptMask()).bits.ociea;
+ }
+
+ //=== Read the compare registers. =====================================
+ async command uint8_t Compare.get(){ return OCR2A; }
+
+ //=== Write the compare registers. ====================================
+ async command void Compare.set(uint8_t t) {
+ atomic
+ {
+ while (ASSR & 1 << OCR2AUB)
+ ;
+ OCR2A = t;
+ }
+ }
+
+ //=== Timer interrupts signals ========================================
+ inline void stabiliseTimer2() {
+ TCCR2A = TCCR2A;
+ while (ASSR & 1 << TCR2AUB)
+ ;
+ }
+
+ /**
+ * On the atm128, there is a small latency when waking up from
+ * POWER_SAVE mode. So if a timer is going to go off very soon, it's
+ * better to drop down until EXT_STANDBY, which has a 6 cycle wakeup
+ * latency. This function calculates whether staying in EXT_STANDBY
+ * is needed. If the timer is not running it returns POWER_DOWN.
+ * Please refer to TEP 112 and the atm128 datasheet for details.
+ */
+
+ async command mcu_power_t McuPowerOverride.lowestState() {
+ uint8_t diff;
+ // We need to make sure that the sleep wakeup latency will not
+ // cause us to miss a timer. POWER_SAVE
+ if (TIMSK2 & (1 << OCIE2A | 1 << TOIE2)) {
+ // need to wait for timer 2 updates propagate before sleeping
+ // (we don't need to worry about reentering sleep mode too early,
+ // as the wake ups from timer2 wait at least one TOSC1 cycle
+ // anyway - see the stabiliseTimer2 function)
+ while (ASSR & (1 << TCN2UB | 1 << OCR2AUB | 1 << TCR2AUB))
+ ;
+ diff = OCR2A - TCNT2;
+ if (diff < EXT_STANDBY_T0_THRESHOLD ||
+ TCNT2 > 256 - EXT_STANDBY_T0_THRESHOLD)
+ return ATM128_POWER_EXT_STANDBY;
+ return ATM128_POWER_SAVE;
+ }
+ else {
+ return ATM128_POWER_DOWN;
+ }
+ }
+
+ default async event void Compare.fired() { }
+ AVR_ATOMIC_HANDLER(SIG_OUTPUT_COMPARE2A) {
+ stabiliseTimer2();
+// __nesc_enable_interrupt();
+
+ signal Compare.fired();
+ }
+
+ default async event void Timer.overflow() { }
+ AVR_ATOMIC_HANDLER(SIG_OVERFLOW2) {
+ stabiliseTimer2();
+// inOverflow = TRUE;
+ signal Timer.overflow();
+// inOverflow = FALSE;
+ }
+
+ // Asynchronous status register support
+ async command Atm128_ASSR_t TimerAsync.getAssr() {
+ return *(Atm128_ASSR_t *)&ASSR;
+ }
+
+ async command void TimerAsync.setAssr(Atm128_ASSR_t x) {
+ ASSR = x.flat;
+ }
+
+ async command void TimerAsync.setTimer2Asynchronous() {
+ ASSR |= 1 << AS2;
+ }
+
+ async command int TimerAsync.controlABusy() {
+ return (ASSR & (1 << TCR2AUB)) != 0;
+ }
+
+ async command int TimerAsync.controlBBusy() {
+ return (ASSR & (1 << TCR2BUB)) != 0;
+ }
+
+ async command int TimerAsync.compareABusy() {
+ return (ASSR & (1 << OCR2AUB)) != 0;
+ }
+
+ async command int TimerAsync.compareBBusy() {
+ return (ASSR & (1 << OCR2BUB)) != 0;
+ }
+
+ async command int TimerAsync.countBusy() {
+ return (ASSR & (1 << TCN2UB)) != 0;
+ }
+
+}
--- /dev/null
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Internal component of the HPL interface to Atmega1281 timer 3.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+module HplAtm1281Timer3P
+{
+ provides {
+ // 16-bit Timers
+ interface HplAtm128Timer<uint16_t> as Timer;
+ interface HplAtm128TimerCtrl16 as TimerCtrl;
+ interface HplAtm128Capture<uint16_t> as Capture;
+ interface HplAtm128Compare<uint16_t> as CompareA;
+ interface HplAtm128Compare<uint16_t> as CompareB;
+ interface HplAtm128Compare<uint16_t> as CompareC;
+ }
+}
+implementation
+{
+ //=== Read the current timer value. ===================================
+ async command uint16_t Timer.get() { return TCNT3; }
+
+ //=== Set/clear the current timer value. ==============================
+ async command void Timer.set(uint16_t t) { TCNT3 = t; }
+
+ //=== Read the current timer scale. ===================================
+ async command uint8_t Timer.getScale() { return TCCR3B & 0x7; }
+
+ //=== Turn off the timers. ============================================
+ async command void Timer.off() { call Timer.setScale(AVR_CLOCK_OFF); }
+
+ //=== Write a new timer scale. ========================================
+ async command void Timer.setScale(uint8_t s) {
+ Atm128_TCCRB_t x = (Atm128_TCCRB_t) call TimerCtrl.getControlB();
+ x.bits.cs = s;
+ call TimerCtrl.setControlB(x.flat);
+ }
+
+ //=== Read the control registers. =====================================
+ async command uint8_t TimerCtrl.getControlA() {
+ return TCCR3A;
+ }
+
+ async command uint8_t TimerCtrl.getControlB() {
+ return TCCR3B;
+ }
+
+ async command uint8_t TimerCtrl.getControlC() {
+ return TCCR3C;
+ }
+
+ //=== Write the control registers. ====================================
+ async command void TimerCtrl.setControlA( uint8_t x ) {
+ TCCR3A = x;
+ }
+
+ async command void TimerCtrl.setControlB( uint8_t x ) {
+ TCCR3B = x;
+ }
+
+ async command void TimerCtrl.setControlC( uint8_t x ) {
+ TCCR3C = x;
+ }
+
+ //=== Read the interrupt mask. =====================================
+ async command uint8_t TimerCtrl.getInterruptMask() {
+ return TIMSK3;
+ }
+
+ //=== Write the interrupt mask. ====================================
+ async command void TimerCtrl.setInterruptMask( uint8_t x ) {
+ TIMSK3 = x;
+ }
+
+ //=== Read the interrupt flags. =====================================
+ async command uint8_t TimerCtrl.getInterruptFlag() {
+ return TIFR3;
+ }
+
+ //=== Write the interrupt flags. ====================================
+ async command void TimerCtrl.setInterruptFlag( uint8_t x ) {
+ TIFR3 = x;
+ }
+
+ //=== Capture 16-bit implementation. ===================================
+ async command void Capture.setEdge(bool up) { WRITE_BIT(TCCR3B, ICES3, up); }
+
+ //=== Timer 16-bit implementation. ===================================
+ async command void Timer.reset() { TIFR3 = 1 << TOV3; }
+ async command void Capture.reset() { TIFR3 = 1 << ICF3; }
+ async command void CompareA.reset() { TIFR3 = 1 << OCF3A; }
+ async command void CompareB.reset() { TIFR3 = 1 << OCF3B; }
+ async command void CompareC.reset() { TIFR3 = 1 << OCF3C; }
+
+ async command void Timer.start() { SET_BIT(TIMSK3,TOIE3); }
+ async command void Capture.start() { SET_BIT(TIMSK3,ICIE3); }
+ async command void CompareA.start() { SET_BIT(TIMSK3,OCIE3A); }
+ async command void CompareB.start() { SET_BIT(TIMSK3,OCIE3B); }
+ async command void CompareC.start() { SET_BIT(TIMSK3,OCIE3C); }
+
+ async command void Timer.stop() { CLR_BIT(TIMSK3,TOIE3); }
+ async command void Capture.stop() { CLR_BIT(TIMSK3,ICIE3); }
+ async command void CompareA.stop() { CLR_BIT(TIMSK3,OCIE3A); }
+ async command void CompareB.stop() { CLR_BIT(TIMSK3,OCIE3B); }
+ async command void CompareC.stop() { CLR_BIT(TIMSK3,OCIE3C); }
+
+ async command bool Timer.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.tov;
+ }
+ async command bool Capture.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.icf;
+ }
+ async command bool CompareA.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfa;
+ }
+ async command bool CompareB.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfb;
+ }
+ async command bool CompareC.test() {
+ return ((Atm128_TIFR_t)call TimerCtrl.getInterruptFlag()).bits.ocfc;
+ }
+
+ async command bool Timer.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.toie;
+ }
+ async command bool Capture.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.icie;
+ }
+ async command bool CompareA.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociea;
+ }
+ async command bool CompareB.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ocieb;
+ }
+ async command bool CompareC.isOn() {
+ return ((Atm128_TIMSK_t)call TimerCtrl.getInterruptMask()).bits.ociec;
+ }
+
+ //=== Read the compare registers. =====================================
+ async command uint16_t CompareA.get() { return OCR3A; }
+ async command uint16_t CompareB.get() { return OCR3B; }
+ async command uint16_t CompareC.get() { return OCR3C; }
+
+ //=== Write the compare registers. ====================================
+ async command void CompareA.set(uint16_t t) { OCR3A = t; }
+ async command void CompareB.set(uint16_t t) { OCR3B = t; }
+ async command void CompareC.set(uint16_t t) { OCR3C = t; }
+
+ //=== Read the capture registers. =====================================
+ async command uint16_t Capture.get() { return ICR3; }
+
+ //=== Write the capture registers. ====================================
+ async command void Capture.set(uint16_t t) { ICR3 = t; }
+
+ //=== Timer interrupts signals ========================================
+ default async event void CompareA.fired() { }
+ AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE3A) {
+ signal CompareA.fired();
+ }
+ default async event void CompareB.fired() { }
+ AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE3B) {
+ signal CompareB.fired();
+ }
+ default async event void CompareC.fired() { }
+ AVR_NONATOMIC_HANDLER(SIG_OUTPUT_COMPARE3C) {
+ signal CompareC.fired();
+ }
+ default async event void Capture.captured(uint16_t time) { }
+ AVR_NONATOMIC_HANDLER(SIG_INPUT_CAPTURE3) {
+ signal Capture.captured(call Timer.get());
+ }
+ default async event void Timer.overflow() { }
+ AVR_NONATOMIC_HANDLER(SIG_OVERFLOW3) {
+ signal Timer.overflow();
+ }
+}
--- /dev/null
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL interface to Atmega1281 timer 1.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay <dgay@intel-research.net>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+configuration HplAtm128Timer1C
+{
+ provides {
+ // 16-bit Timers
+ interface HplAtm128Timer<uint16_t> as Timer;
+ interface HplAtm128TimerCtrl16 as TimerCtrl;
+ interface HplAtm128Capture<uint16_t> as Capture;
+ interface HplAtm128Compare<uint16_t> as Compare[uint8_t id];
+ }
+}
+implementation
+{
+ components HplAtm1281Timer1P;
+
+ Timer = HplAtm1281Timer1P;
+ TimerCtrl = HplAtm1281Timer1P;
+ Capture = HplAtm1281Timer1P;
+
+ Compare[0] = HplAtm1281Timer1P.CompareA;
+ Compare[1] = HplAtm1281Timer1P.CompareB;
+ Compare[2] = HplAtm1281Timer1P.CompareC;
+}
--- /dev/null
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL interface to Atmega1281 timer 3.
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author David Gay <dgay@intel-research.net>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+configuration HplAtm128Timer3C
+{
+ provides {
+ // 16-bit Timers
+ interface HplAtm128Timer<uint16_t> as Timer;
+ interface HplAtm128TimerCtrl16 as TimerCtrl;
+ interface HplAtm128Capture<uint16_t> as Capture;
+ interface HplAtm128Compare<uint16_t> as Compare[uint8_t id];
+ }
+}
+implementation
+{
+ components HplAtm1281Timer3P;
+
+ Timer = HplAtm1281Timer3P;
+ TimerCtrl = HplAtm1281Timer3P;
+ Capture = HplAtm1281Timer3P;
+
+ Compare[0] = HplAtm1281Timer3P.CompareA;
+ Compare[1] = HplAtm1281Timer3P.CompareB;
+ Compare[2] = HplAtm1281Timer3P.CompareC;
+}
--- /dev/null
+// $Id$
+/*
+ * Copyright (c) 2007 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL Interface to Atmega1281 8-bit asynchronous timer control registers
+ *
+ * @author David Gay
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+interface HplAtm128TimerAsync
+{
+ /**
+ * Read timer2 asynchronous status register (ASSR)
+ * @return Current value of ASSR
+ */
+ async command Atm128_ASSR_t getAssr();
+
+ /**
+ * Set timer2 asynchronous status register (ASSR)
+ * @param x New value for ASSR
+ */
+ async command void setAssr(Atm128_ASSR_t x);
+
+ /**
+ * Turn on timer 2 asynchronous mode
+ */
+ async command void setTimer2Asynchronous();
+
+ /**
+ * Check if control register TCCR2A is busy (should not be updated if true)
+ * @return TRUE if TCCR2A is busy, FALSE otherwise (can be updated)
+ */
+ async command int controlABusy();
+
+ /**
+ * Check if control register TCCR2B is busy (should not be updated if true)
+ * @return TRUE if TCCR2B is busy, FALSE otherwise (can be updated)
+ */
+ async command int controlBBusy();
+
+ /**
+ * Check if compare register OCR2A is busy (should not be updated if true)
+ * @return TRUE if OCR2A is busy, FALSE otherwise (can be updated)
+ */
+ async command int compareABusy();
+
+ /**
+ * Check if compare register OCR2B is busy (should not be updated if true)
+ * @return TRUE if OCR2B is busy, FALSE otherwise (can be updated)
+ */
+ async command int compareBBusy();
+
+ /**
+ * Check if current timer value (TCNT2) is busy (should not be updated if true)
+ * @return TRUE if TCNT2 is busy, FALSE otherwise (can be updated)
+ */
+ async command int countBusy();
+
+}
--- /dev/null
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL Interface to Atmega1281 16-bit timer control registers
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+interface HplAtm128TimerCtrl16
+{
+ /// Timer control register: Direct access
+ async command uint8_t getControlA();
+ async command uint8_t getControlB();
+ async command uint8_t getControlC();
+ async command void setControlA( uint8_t control );
+ async command void setControlB( uint8_t control );
+ async command void setControlC( uint8_t control );
+
+ /// Interrupt mask register: Direct access
+ async command uint8_t getInterruptMask();
+ async command void setInterruptMask( uint8_t mask);
+
+ /// Interrupt flag register: Direct access
+ async command uint8_t getInterruptFlag();
+ async command void setInterruptFlag( uint8_t flags );
+}
+
--- /dev/null
+/// $Id$
+
+/*
+ * Copyright (c) 2004-2005 Crossbow Technology, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CROSSBOW TECHNOLOGY OR ANY OF ITS LICENSORS BE LIABLE TO
+ * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF CROSSBOW OR ITS LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * CROSSBOW TECHNOLOGY AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND NEITHER CROSSBOW NOR ANY LICENSOR HAS ANY
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * HPL Interface to Atmega1281 8-bit timer control registers
+ *
+ * @author Martin Turon <mturon@xbow.com>
+ * @author Janos Sallai <janos.sallai@vanderbilt.edu>
+ */
+
+#include <Atm128Timer.h>
+
+interface HplAtm128TimerCtrl8
+{
+ /// Timer control register: Direct access
+ async command uint8_t getControlA();
+ async command uint8_t getControlB();
+ async command void setControlA( uint8_t control );
+ async command void setControlB( uint8_t control );
+
+ /// Interrupt mask register: Direct access
+ async command uint8_t getInterruptMask();
+ async command void setInterruptMask( uint8_t mask);
+
+ /// Interrupt flag register: Direct access
+ async command uint8_t getInterruptFlag();
+ async command void setInterruptFlag( uint8_t flags );
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module CsmaLayerP
+{
+ provides
+ {
+ interface RadioSend;
+ }
+
+ uses
+ {
+ interface CsmaConfig as Config;
+
+ interface RadioSend as SubSend;
+ interface RadioCCA as SubCCA;
+ }
+}
+
+implementation
+{
+ tasklet_norace message_t *txMsg;
+
+ tasklet_norace uint8_t state;
+ enum
+ {
+ STATE_READY = 0,
+ STATE_CCA_WAIT = 1,
+ STATE_SEND = 2,
+ };
+
+ tasklet_async event void SubSend.ready()
+ {
+ if( state == STATE_READY )
+ signal RadioSend.ready();
+ }
+
+ tasklet_async command error_t RadioSend.send(message_t* msg)
+ {
+ error_t error;
+
+ if( state == STATE_READY )
+ {
+ if( call Config.requiresSoftwareCCA(msg) )
+ {
+ txMsg = msg;
+
+ if( (error = call SubCCA.request()) == SUCCESS )
+ state = STATE_CCA_WAIT;
+ }
+ else if( (error = call SubSend.send(msg)) == SUCCESS )
+ state = STATE_SEND;
+ }
+ else
+ error = EBUSY;
+
+ return error;
+ }
+
+ tasklet_async event void SubCCA.done(error_t error)
+ {
+ ASSERT( state == STATE_CCA_WAIT );
+
+ if( error == SUCCESS && (error = call SubSend.send(txMsg)) == SUCCESS )
+ state = STATE_SEND;
+ else
+ {
+ state = STATE_READY;
+ signal RadioSend.sendDone(EBUSY);
+ }
+ }
+
+ tasklet_async event void SubSend.sendDone(error_t error)
+ {
+ ASSERT( state == STATE_SEND );
+
+ state = STATE_READY;
+ signal RadioSend.sendDone(error);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __DEFAULTMAC_H__
+#define __DEFAULTMAC_H__
+
+#include <IEEE154Packet.h>
+
+typedef ieee154_header_t defaultmac_header_t;
+
+typedef nx_struct defaultmac_metadata_t
+{
+ nx_uint8_t flags;
+ nx_uint8_t lqi;
+ nx_uint16_t timestamp;
+} defaultmac_metadata_t;
+
+enum defaultmac_metadata_flags
+{
+ DEFAULTMAC_WAS_ACKED = 0x01,
+ DEFAULTMAC_SCHEDULED_TX = 0x02,
+};
+
+/* This is the default value of the TX_PWR field of the PHY_TX_PWR register. */
+#ifndef RF230_DEF_RFPOWER
+#define RF230_DEF_RFPOWER 0
+#endif
+
+/* This is the default value of the CHANNEL field of the PHY_CC_CCA register. */
+#ifndef RF230_DEF_CHANNEL
+#define RF230_DEF_CHANNEL 11
+#endif
+
+#endif//__DEFAULTMAC_H__
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <DefaultMac.h>
+#include <HplRF230.h>
+#include <Tasklet.h>
+
+module DefaultMacP
+{
+ provides
+ {
+ interface RF230Config;
+ interface SoftwareAckConfig;
+ interface UniqueConfig;
+ interface CsmaConfig;
+ interface TrafficMonitorConfig;
+ interface RandomCollisionConfig;
+ interface SlottedCollisionConfig;
+ interface ActiveMessageConfig;
+ interface DummyConfig;
+
+ interface PacketAcknowledgements;
+ interface Packet;
+ }
+
+ uses
+ {
+ interface IEEE154Packet;
+ interface RadioAlarm;
+ }
+}
+
+implementation
+{
+/*----------------- Packet -----------------*/
+
+ command void Packet.clear(message_t* msg)
+ {
+ call IEEE154Packet.createDataFrame(msg);
+
+#ifdef IEEE154_6LOWPAN
+ call IEEE154Packet.set6LowPan(msg, TINYOS_6LOWPAN_NETWORK_ID);
+#endif
+ }
+
+ command uint8_t Packet.payloadLength(message_t* msg)
+ {
+ return call IEEE154Packet.getLength(msg) - sizeof(ieee154_header_t) + 1 - sizeof(ieee154_footer_t);
+ }
+
+ command void Packet.setPayloadLength(message_t* msg, uint8_t len)
+ {
+ call IEEE154Packet.setLength(msg, len + sizeof(ieee154_header_t) - 1 + sizeof(ieee154_footer_t));
+ }
+
+ command uint8_t Packet.maxPayloadLength()
+ {
+ return TOSH_DATA_LENGTH;
+ }
+
+ command void* Packet.getPayload(message_t* msg, uint8_t len)
+ {
+ if( len > TOSH_DATA_LENGTH )
+ return NULL;
+
+ return msg->data;
+ }
+
+ command error_t ActiveMessageConfig.checkPacket(message_t* msg)
+ {
+ // the user forgot to call clear, we should return EINVAL
+ if( ! call IEEE154Packet.isDataFrame(msg) )
+ call Packet.clear(msg);
+
+ return SUCCESS;
+ }
+
+/*----------------- RF230Config -----------------*/
+
+ async command uint8_t RF230Config.getLength(message_t* msg)
+ {
+ return call IEEE154Packet.getLength(msg);
+ }
+
+ async command void RF230Config.setLength(message_t* msg, uint8_t len)
+ {
+ call IEEE154Packet.setLength(msg, len);
+ }
+
+ async command uint8_t* RF230Config.getPayload(message_t* msg)
+ {
+ return ((uint8_t*)(call IEEE154Packet.getHeader(msg))) + 1;
+ }
+
+ inline defaultmac_metadata_t* getMeta(message_t* msg)
+ {
+ return (defaultmac_metadata_t*)(msg->metadata);
+ }
+
+ async command void RF230Config.setTimestamp(message_t* msg, uint16_t time)
+ {
+ getMeta(msg)->timestamp = time;
+ }
+
+ async command void RF230Config.setLinkQuality(message_t* msg, uint8_t lqi)
+ {
+ getMeta(msg)->lqi = lqi;
+ }
+
+ async command uint8_t RF230Config.getHeaderLength()
+ {
+ // we need the fcf, dsn, destpan and dest
+ return 7;
+ }
+
+ async command uint8_t RF230Config.getMaxLength()
+ {
+ // note, that the ieee154_footer_t is not stored, but we should include it here
+ return sizeof(defaultmac_header_t) - 1 + TOSH_DATA_LENGTH + sizeof(ieee154_footer_t);
+ }
+
+ async command uint8_t RF230Config.getTransmitPower(message_t* msg)
+ {
+ return RF230_DEF_RFPOWER;
+ }
+
+ async command uint8_t RF230Config.getDefaultChannel()
+ {
+ return RF230_DEF_CHANNEL;
+ }
+
+ async command bool RF230Config.requiresRssiCca(message_t* msg)
+ {
+ return call IEEE154Packet.isDataFrame(msg);
+ }
+
+/*----------------- SoftwareAckConfig -----------------*/
+
+ async command bool SoftwareAckConfig.requiresAckWait(message_t* msg)
+ {
+ return call IEEE154Packet.requiresAckWait(msg);
+ }
+
+ async command bool SoftwareAckConfig.isAckPacket(message_t* msg)
+ {
+ return call IEEE154Packet.isAckFrame(msg);
+ }
+
+ async command bool SoftwareAckConfig.verifyAckPacket(message_t* data, message_t* ack)
+ {
+ return call IEEE154Packet.verifyAckReply(data, ack);
+ }
+
+ async command bool SoftwareAckConfig.requiresAckReply(message_t* msg)
+ {
+ return call IEEE154Packet.requiresAckReply(msg);
+ }
+
+ async command void SoftwareAckConfig.createAckPacket(message_t* data, message_t* ack)
+ {
+ call IEEE154Packet.createAckReply(data, ack);
+ }
+
+ async command void SoftwareAckConfig.setAckReceived(message_t* msg, bool acked)
+ {
+ if( acked )
+ getMeta(msg)->flags |= DEFAULTMAC_WAS_ACKED;
+ else
+ getMeta(msg)->flags &= ~DEFAULTMAC_WAS_ACKED;
+ }
+
+ async command uint16_t SoftwareAckConfig.getAckTimeout()
+ {
+ return (uint16_t)(800 * RF230_ALARM_MICROSEC);
+ }
+
+ tasklet_async command void SoftwareAckConfig.reportChannelError()
+ {
+ signal TrafficMonitorConfig.channelError();
+ }
+
+/*----------------- PacketAcknowledgements -----------------*/
+
+ async command error_t PacketAcknowledgements.requestAck(message_t* msg)
+ {
+ call IEEE154Packet.setAckRequired(msg, TRUE);
+
+ return SUCCESS;
+ }
+
+ async command error_t PacketAcknowledgements.noAck(message_t* msg)
+ {
+ call IEEE154Packet.setAckRequired(msg, FALSE);
+
+ return SUCCESS;
+ }
+
+ async command bool PacketAcknowledgements.wasAcked(message_t* msg)
+ {
+ return getMeta(msg)->flags & DEFAULTMAC_WAS_ACKED;
+ }
+
+/*----------------- UniqueConfig -----------------*/
+
+ async command uint8_t UniqueConfig.getSequenceNumber(message_t* msg)
+ {
+ return call IEEE154Packet.getDSN(msg);
+ }
+
+ async command void UniqueConfig.setSequenceNumber(message_t* msg, uint8_t dsn)
+ {
+ call IEEE154Packet.setDSN(msg, dsn);
+ }
+
+ async command am_addr_t UniqueConfig.getSender(message_t* msg)
+ {
+ return call IEEE154Packet.getSrcAddr(msg);
+ }
+
+ tasklet_async command void UniqueConfig.reportChannelError()
+ {
+ signal TrafficMonitorConfig.channelError();
+ }
+
+/*----------------- CsmaConfig -----------------*/
+
+ async command bool CsmaConfig.requiresSoftwareCCA(message_t* msg)
+ {
+ return call IEEE154Packet.isDataFrame(msg);
+ }
+
+/*----------------- TrafficMonitorConfig -----------------*/
+
+ enum
+ {
+ TRAFFIC_UPDATE_PERIOD = 100, // in milliseconds
+ TRAFFIC_MAX_BYTES = (uint16_t)(TRAFFIC_UPDATE_PERIOD * 1000.0 / 32), // 3125
+ };
+
+ async command uint16_t TrafficMonitorConfig.getUpdatePeriod()
+ {
+ return TRAFFIC_UPDATE_PERIOD;
+ }
+
+ async command uint16_t TrafficMonitorConfig.getChannelTime(message_t* msg)
+ {
+ /* We count in bytes, one byte is 32 microsecond. We are conservative here.
+ *
+ * pure airtime: preable (4 bytes), SFD (1 byte), length (1 byte), payload + CRC (len bytes)
+ * frame separation: 5-10 bytes
+ * ack required: 8-16 byte separation, 11 bytes airtime, 5-10 bytes separation
+ */
+
+ uint8_t len = call IEEE154Packet.getLength(msg);
+ return call IEEE154Packet.getAckRequired(msg) ? len + 6 + 16 + 11 + 10 : len + 6 + 10;
+ }
+
+ async command am_addr_t TrafficMonitorConfig.getSender(message_t* msg)
+ {
+ return call IEEE154Packet.getSrcAddr(msg);
+ }
+
+ tasklet_async command void TrafficMonitorConfig.timerTick()
+ {
+ signal SlottedCollisionConfig.timerTick();
+ }
+
+/*----------------- RandomCollisionConfig -----------------*/
+
+ /*
+ * We try to use the same values as in CC2420
+ *
+ * CC2420_MIN_BACKOFF = 10 jiffies = 320 microsec
+ * CC2420_BACKOFF_PERIOD = 10 jiffies
+ * initial backoff = 0x1F * CC2420_BACKOFF_PERIOD = 310 jiffies = 9920 microsec
+ * congestion backoff = 0x7 * CC2420_BACKOFF_PERIOD = 70 jiffies = 2240 microsec
+ */
+
+ async command uint16_t RandomCollisionConfig.getMinimumBackoff()
+ {
+ return (uint16_t)(320 * RF230_ALARM_MICROSEC);
+ }
+
+ async command uint16_t RandomCollisionConfig.getInitialBackoff(message_t* msg)
+ {
+ return (uint16_t)(9920 * RF230_ALARM_MICROSEC);
+ }
+
+ async command uint16_t RandomCollisionConfig.getCongestionBackoff(message_t* msg)
+ {
+ return (uint16_t)(2240 * RF230_ALARM_MICROSEC);
+ }
+
+ async command uint16_t RandomCollisionConfig.getTransmitBarrier(message_t* msg)
+ {
+ uint16_t time;
+
+ // TODO: maybe we should use the embedded timestamp of the message
+ time = call RadioAlarm.getNow();
+
+ // estimated response time (download the message, etc) is 5-8 bytes
+ if( call IEEE154Packet.requiresAckReply(msg) )
+ time += (uint16_t)(32 * (-5 + 16 + 11 + 5) * RF230_ALARM_MICROSEC);
+ else
+ time += (uint16_t)(32 * (-5 + 5) * RF230_ALARM_MICROSEC);
+
+ return time;
+ }
+
+ tasklet_async event void RadioAlarm.fired() { }
+
+/*----------------- SlottedCollisionConfig -----------------*/
+
+ async command uint16_t SlottedCollisionConfig.getInitialDelay()
+ {
+ return 300;
+ }
+
+ async command uint8_t SlottedCollisionConfig.getScheduleExponent()
+ {
+ return 11;
+ }
+
+ async command uint16_t SlottedCollisionConfig.getTransmitTime(message_t* msg)
+ {
+ // TODO: check if the timestamp is correct
+ return getMeta(msg)->timestamp;
+ }
+
+ async command uint16_t SlottedCollisionConfig.getCollisionWindowStart(message_t* msg)
+ {
+ // the preamble (4 bytes), SFD (1 byte), plus two extra for safety
+ return getMeta(msg)->timestamp - (uint16_t)(7 * 32 * RF230_ALARM_MICROSEC);
+ }
+
+ async command uint16_t SlottedCollisionConfig.getCollisionWindowLength(message_t* msg)
+ {
+ return (uint16_t)(2 * 7 * 32 * RF230_ALARM_MICROSEC);
+ }
+
+ default tasklet_async event void SlottedCollisionConfig.timerTick() { }
+
+/*----------------- Dummy -----------------*/
+
+ async command void DummyConfig.nothing()
+ {
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <IEEE154Packet.h>
+#include <message.h>
+
+/**
+ * This interface encapsulates IEEE 802.15.4 intrapan data frames with
+ * 16-bit destination pan, source and destination addresses. It also
+ * supports 6LowPan interoperability mode, and acknowledgement frames.
+ * Note, that this interface does not support the CRC-16 value, which
+ * should be verified before the data can be trusted.
+ */
+interface IEEE154Packet
+{
+ /**
+ * Returns the IEEE 802.15.4 header including the length field.
+ */
+ async command ieee154_header_t* getHeader(message_t* msg);
+
+ /**
+ * Returns the raw value (unadjusted) of the length field
+ */
+ async command uint8_t getLength(message_t* msg);
+
+ /**
+ * Sets the length field
+ */
+ async command void setLength(message_t* msg, uint8_t length);
+
+ /**
+ * Returns the frame control field. This method should not be used,
+ * isDataFrame and isAckFrame should be used instead.
+ */
+ async command uint16_t getFCF(message_t* msg);
+
+ /**
+ * Sets the frame control field. This method should not be used,
+ * createDataFrame and createAckFrame should be used instead.
+ */
+ async command void setFCF(message_t* msg, uint16_t fcf);
+
+ /**
+ * Returns TRUE if the message is a data frame supported by
+ * this interface (based on the value of the FCF).
+ */
+ async command bool isDataFrame(message_t* msg);
+
+ /**
+ * Sets the FCF to create a data frame supported by this interface.
+ * You may call setAckRequired and setFramePending commands after this.
+ */
+ async command void createDataFrame(message_t* msg);
+
+ /**
+ * Returns TRUE if the message is an acknowledgement frame supported
+ * by this interface (based on the value of the FCF).
+ */
+ async command bool isAckFrame(message_t* msg);
+
+ /**
+ * Sets the FCF to create an acknowledgement frame supported by
+ * this interface. You may call setFramePending after this.
+ */
+ async command void createAckFrame(message_t* msg);
+
+ /**
+ * Creates an acknowledgement packet for the given data packet.
+ * This also sets the DSN value. The data message must be a
+ * data frame, the ack message will be overwritten.
+ */
+ async command void createAckReply(message_t* data, message_t* ack);
+
+ /**
+ * Returns TRUE if the acknowledgement packet corresponds to the
+ * data packet. The data message must be a data packet.
+ */
+ async command bool verifyAckReply(message_t* data, message_t* ack);
+
+ /**
+ * Returns TRUE if the ACK required field is set in the FCF.
+ */
+ async command bool getAckRequired(message_t* msg);
+
+ /**
+ * Sets the ACK required field in the FCF, should never be set
+ * for acknowledgement frames.
+ */
+ async command void setAckRequired(message_t* msg, bool ack);
+
+ /**
+ * Returns TRUE if the frame pending field is set in the FCF.
+ */
+ async command bool getFramePending(message_t* msg);
+
+ /**
+ * Sets the frame pending field in the FCF.
+ */
+ async command void setFramePending(message_t* msg, bool pending);
+
+ /**
+ * Returns the data sequence number
+ */
+ async command uint8_t getDSN(message_t* msg);
+
+ /**
+ * Sets the data sequence number
+ */
+ async command void setDSN(message_t* msg, uint8_t dsn);
+
+ /**
+ * returns the destination PAN id, values <= 255 are tinyos groups,
+ * valid only for data frames
+ */
+ async command uint16_t getDestPan(message_t* msg);
+
+ /**
+ * Sets the destination PAN id, valid only for data frames
+ */
+ async command void setDestPan(message_t* msg, uint16_t pan);
+
+ /**
+ * Returns the destination address, valid only for data frames
+ */
+ async command uint16_t getDestAddr(message_t* msg);
+
+ /**
+ * Sets the destination address, valid only for data frames
+ */
+ async command void setDestAddr(message_t* msg, uint16_t addr);
+
+ /**
+ * Returns the source address, valid only for data frames
+ */
+ async command uint16_t getSrcAddr(message_t* msg);
+
+ /**
+ * Sets the source address, valid only for data frames
+ */
+ async command void setSrcAddr(message_t* msg, uint16_t addr);
+
+#ifdef IEEE154_6LOWPAN
+
+ /**
+ * Returns the value of the 6LowPan network field.
+ */
+ async command uint8_t get6LowPan(message_t* msg);
+
+ /**
+ * Sets the value of the 6LowPan network field.
+ */
+ async command void set6LowPan(message_t* msg, uint8_t network);
+
+#endif
+
+ /**
+ * Returns the active message type of the message
+ */
+ async command am_id_t getType(message_t* msg);
+
+ /**
+ * Sets the active message type
+ */
+ async command void setType(message_t* msg, am_id_t type);
+
+ /**
+ * Returns TRUE if the packet is a data packet, the ACK_REQ field
+ * is set and the destination address is not the broadcast address.
+ */
+ async command bool requiresAckWait(message_t* msg);
+
+ /**
+ * Returns TRUE if the packet is a data packet, the ACK_REQ field
+ * is set and the destionation address is this node.
+ */
+ async command bool requiresAckReply(message_t* msg);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <IEEE154Packet.h>
+
+module IEEE154PacketP
+{
+ provides
+ {
+ interface IEEE154Packet;
+ interface AMPacket;
+ }
+
+ uses interface ActiveMessageAddress;
+}
+
+implementation
+{
+/*----------------- IEEE154Packet -----------------*/
+
+ enum
+ {
+ IEEE154_DATA_FRAME_MASK = (IEEE154_TYPE_MASK << IEEE154_FCF_FRAME_TYPE)
+ | (1 << IEEE154_FCF_INTRAPAN)
+ | (IEEE154_ADDR_MASK << IEEE154_FCF_DEST_ADDR_MODE)
+ | (IEEE154_ADDR_MASK << IEEE154_FCF_SRC_ADDR_MODE),
+
+ IEEE154_DATA_FRAME_VALUE = (IEEE154_TYPE_DATA << IEEE154_FCF_FRAME_TYPE)
+ | (1 << IEEE154_FCF_INTRAPAN)
+ | (IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE)
+ | (IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE),
+
+ IEEE154_ACK_FRAME_LENGTH = 5, // includes the FCF, DSN and FCS
+ IEEE154_ACK_FRAME_MASK = (IEEE154_TYPE_MASK << IEEE154_FCF_FRAME_TYPE),
+ IEEE154_ACK_FRAME_VALUE = (IEEE154_TYPE_ACK << IEEE154_FCF_FRAME_TYPE),
+ };
+
+ inline ieee154_header_t* getHeader(message_t* msg)
+ {
+ return (ieee154_header_t*)(msg->data - sizeof(ieee154_header_t));
+ }
+
+ inline async command ieee154_header_t* IEEE154Packet.getHeader(message_t* msg)
+ {
+ return getHeader(msg);
+ }
+
+ inline async command uint8_t IEEE154Packet.getLength(message_t* msg)
+ {
+ return getHeader(msg)->length;
+ }
+
+ inline async command void IEEE154Packet.setLength(message_t* msg, uint8_t length)
+ {
+ getHeader(msg)->length = length;
+ }
+
+ inline async command uint16_t IEEE154Packet.getFCF(message_t* msg)
+ {
+ return getHeader(msg)->fcf;
+ }
+
+ inline async command void IEEE154Packet.setFCF(message_t* msg, uint16_t fcf)
+ {
+ getHeader(msg)->fcf = fcf;
+ }
+
+ inline async command bool IEEE154Packet.isDataFrame(message_t* msg)
+ {
+ return (getHeader(msg)->fcf & IEEE154_DATA_FRAME_MASK) == IEEE154_DATA_FRAME_VALUE;
+ }
+
+ inline async command void IEEE154Packet.createDataFrame(message_t* msg)
+ {
+ getHeader(msg)->fcf = IEEE154_DATA_FRAME_VALUE;
+ }
+
+ inline async command bool IEEE154Packet.isAckFrame(message_t* msg)
+ {
+ return (getHeader(msg)->fcf & IEEE154_ACK_FRAME_MASK) == IEEE154_ACK_FRAME_VALUE;
+ }
+
+ inline async command void IEEE154Packet.createAckFrame(message_t* msg)
+ {
+ ieee154_header_t* header = getHeader(msg);
+
+ header->length = IEEE154_ACK_FRAME_LENGTH;
+ header->fcf = IEEE154_ACK_FRAME_VALUE;
+ }
+
+ inline async command void IEEE154Packet.createAckReply(message_t* data, message_t* ack)
+ {
+ ieee154_header_t* header = getHeader(ack);
+
+ header->length = IEEE154_ACK_FRAME_LENGTH;
+ header->fcf = IEEE154_ACK_FRAME_VALUE;
+ header->dsn = getHeader(data)->dsn;
+ }
+
+ inline async command bool IEEE154Packet.verifyAckReply(message_t* data, message_t* ack)
+ {
+ ieee154_header_t* header = getHeader(ack);
+
+ return header->dsn == getHeader(data)->dsn
+ && (header->fcf & IEEE154_ACK_FRAME_MASK) == IEEE154_ACK_FRAME_VALUE;
+ }
+
+ inline async command bool IEEE154Packet.getAckRequired(message_t* msg)
+ {
+ return getHeader(msg)->fcf & (1 << IEEE154_FCF_ACK_REQ);
+ }
+
+ inline async command void IEEE154Packet.setAckRequired(message_t* msg, bool ack)
+ {
+ if( ack )
+ getHeader(msg)->fcf |= (1 << IEEE154_FCF_ACK_REQ);
+ else
+ getHeader(msg)->fcf &= ~(uint16_t)(1 << IEEE154_FCF_ACK_REQ);
+ }
+
+ inline async command bool IEEE154Packet.getFramePending(message_t* msg)
+ {
+ return getHeader(msg)->fcf & (1 << IEEE154_FCF_FRAME_PENDING);
+ }
+
+ inline async command void IEEE154Packet.setFramePending(message_t* msg, bool pending)
+ {
+ if( pending )
+ getHeader(msg)->fcf |= (1 << IEEE154_FCF_FRAME_PENDING);
+ else
+ getHeader(msg)->fcf &= ~(uint16_t)(1 << IEEE154_FCF_FRAME_PENDING);
+ }
+
+ inline async command uint8_t IEEE154Packet.getDSN(message_t* msg)
+ {
+ return getHeader(msg)->dsn;
+ }
+
+ inline async command void IEEE154Packet.setDSN(message_t* msg, uint8_t dsn)
+ {
+ getHeader(msg)->dsn = dsn;
+ }
+
+ inline async command uint16_t IEEE154Packet.getDestPan(message_t* msg)
+ {
+ return getHeader(msg)->destpan;
+ }
+
+ inline async command void IEEE154Packet.setDestPan(message_t* msg, uint16_t pan)
+ {
+ getHeader(msg)->destpan = pan;
+ }
+
+ inline async command uint16_t IEEE154Packet.getDestAddr(message_t* msg)
+ {
+ return getHeader(msg)->dest;
+ }
+
+ inline async command void IEEE154Packet.setDestAddr(message_t* msg, uint16_t addr)
+ {
+ getHeader(msg)->dest = addr;
+ }
+
+ inline async command uint16_t IEEE154Packet.getSrcAddr(message_t* msg)
+ {
+ return getHeader(msg)->src;
+ }
+
+ inline async command void IEEE154Packet.setSrcAddr(message_t* msg, uint16_t addr)
+ {
+ getHeader(msg)->src = addr;
+ }
+
+#ifdef IEEE154_6LOWPAN
+
+ inline async command uint8_t IEEE154Packet.get6LowPan(message_t* msg)
+ {
+ return getHeader(msg)->network;
+ }
+
+ inline async command void IEEE154Packet.set6LowPan(message_t* msg, uint8_t network)
+ {
+ getHeader(msg)->network = network;
+ }
+
+#endif
+
+ inline async command am_id_t IEEE154Packet.getType(message_t* msg)
+ {
+ return getHeader(msg)->type;
+ }
+
+ inline async command void IEEE154Packet.setType(message_t* msg, am_id_t type)
+ {
+ getHeader(msg)->type = type;
+ }
+
+ async command bool IEEE154Packet.requiresAckWait(message_t* msg)
+ {
+ return call IEEE154Packet.getAckRequired(msg)
+ && call IEEE154Packet.isDataFrame(msg)
+ && call IEEE154Packet.getDestAddr(msg) != 0xFFFF;
+ }
+
+ async command bool IEEE154Packet.requiresAckReply(message_t* msg)
+ {
+ return call IEEE154Packet.getAckRequired(msg)
+ && call IEEE154Packet.isDataFrame(msg)
+ && call IEEE154Packet.getDestAddr(msg) == call ActiveMessageAddress.amAddress();
+ }
+
+ inline async event void ActiveMessageAddress.changed()
+ {
+ }
+
+/*----------------- AMPacket -----------------*/
+
+ inline command am_addr_t AMPacket.address()
+ {
+ return call ActiveMessageAddress.amAddress();
+ }
+
+ inline command am_group_t AMPacket.localGroup()
+ {
+ // TODO: check if this is correct
+ return call ActiveMessageAddress.amGroup();
+ }
+
+ inline command am_addr_t AMPacket.destination(message_t* msg)
+ {
+ return call IEEE154Packet.getDestAddr(msg);
+ }
+
+ inline command am_addr_t AMPacket.source(message_t* msg)
+ {
+ return call IEEE154Packet.getSrcAddr(msg);
+ }
+
+ inline command void AMPacket.setDestination(message_t* msg, am_addr_t addr)
+ {
+ call IEEE154Packet.setDestAddr(msg, addr);
+ }
+
+ inline command void AMPacket.setSource(message_t* msg, am_addr_t addr)
+ {
+ call IEEE154Packet.setSrcAddr(msg, addr);
+ }
+
+ inline command bool AMPacket.isForMe(message_t* msg)
+ {
+ am_addr_t addr = call AMPacket.destination(msg);
+ return addr == call AMPacket.address() || addr == AM_BROADCAST_ADDR;
+ }
+
+ inline command am_id_t AMPacket.type(message_t* msg)
+ {
+ return call IEEE154Packet.getType(msg);
+ }
+
+ inline command void AMPacket.setType(message_t* msg, am_id_t type)
+ {
+ call IEEE154Packet.setType(msg, type);
+ }
+
+ inline command am_group_t AMPacket.group(message_t* msg)
+ {
+ return call IEEE154Packet.getDestPan(msg);
+ }
+
+ inline command void AMPacket.setGroup(message_t* msg, am_group_t grp)
+ {
+ call IEEE154Packet.setDestPan(msg, grp);
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module MessageBufferLayerP
+{
+ provides
+ {
+ interface SplitControl;
+ interface Init as SoftwareInit;
+
+ interface Send;
+ interface Receive;
+ }
+ uses
+ {
+ interface RadioState;
+ interface Tasklet;
+ interface RadioSend;
+ interface RadioReceive;
+
+ interface Packet;
+ }
+}
+
+implementation
+{
+/*----------------- State -----------------*/
+
+ norace uint8_t state; // written only from tasks
+ enum
+ {
+ STATE_READY = 0,
+ STATE_TX_PENDING = 1,
+ STATE_TX_SEND = 2,
+ STATE_TX_DONE = 3,
+ STATE_TURN_ON = 4,
+ STATE_TURN_OFF = 5,
+ };
+
+ command error_t SplitControl.start()
+ {
+ error_t error;
+
+ call Tasklet.suspend();
+
+ if( state != STATE_READY )
+ error = EBUSY;
+ else
+ error = call RadioState.turnOn();
+
+ if( error == SUCCESS )
+ state = STATE_TURN_ON;
+
+ call Tasklet.resume();
+
+ return error;
+ }
+
+ command error_t SplitControl.stop()
+ {
+ error_t error;
+
+ call Tasklet.suspend();
+
+ if( state != STATE_READY )
+ error = EBUSY;
+ else
+ error = call RadioState.turnOff();
+
+ if( error == SUCCESS )
+ state = STATE_TURN_OFF;
+
+ call Tasklet.resume();
+
+ return error;
+ }
+
+ task void stateDoneTask()
+ {
+ uint8_t s;
+
+ s = state;
+
+ if( s == STATE_TURN_ON || s == STATE_TURN_OFF )
+ state = STATE_READY;
+
+ if( s == STATE_TURN_ON )
+ signal SplitControl.startDone(SUCCESS);
+ else
+ signal SplitControl.stopDone(SUCCESS);
+ }
+
+ tasklet_async event void RadioState.done()
+ {
+ post stateDoneTask();
+ }
+
+ default event void SplitControl.startDone(error_t error)
+ {
+ }
+
+ default event void SplitControl.stopDone(error_t error)
+ {
+ }
+
+/*----------------- Send -----------------*/
+
+ message_t* txMsg;
+ error_t txError;
+ uint8_t retries;
+
+ // Many EBUSY replies from RadioSend are normal if the channel is cognested
+ enum { MAX_RETRIES = 5 };
+
+ task void sendTask()
+ {
+ error_t error;
+
+ ASSERT( state == STATE_TX_PENDING || state == STATE_TX_SEND );
+
+ atomic error = txError;
+ if( (state == STATE_TX_SEND && error == SUCCESS) || ++retries > MAX_RETRIES )
+ state = STATE_TX_DONE;
+ else
+ {
+ call Tasklet.suspend();
+
+ error = call RadioSend.send(txMsg);
+ if( error == SUCCESS )
+ state = STATE_TX_SEND;
+ else if( retries == MAX_RETRIES )
+ state = STATE_TX_DONE;
+ else
+ state = STATE_TX_PENDING;
+
+ call Tasklet.resume();
+ }
+
+ if( state == STATE_TX_DONE )
+ {
+ state = STATE_READY;
+ signal Send.sendDone(txMsg, error);
+ }
+ }
+
+ tasklet_async event void RadioSend.sendDone(error_t error)
+ {
+ ASSERT( state == STATE_TX_SEND );
+
+ atomic txError = error;
+ post sendTask();
+ }
+
+ command error_t Send.send(message_t* msg, uint8_t len)
+ {
+ if( len > call Packet.maxPayloadLength() )
+ return EINVAL;
+ else if( state != STATE_READY )
+ return EBUSY;
+
+ call Packet.setPayloadLength(msg, len);
+
+ txMsg = msg;
+ state = STATE_TX_PENDING;
+ retries = 0;
+ post sendTask();
+
+ return SUCCESS;
+ }
+
+ tasklet_async event void RadioSend.ready()
+ {
+ if( state == STATE_TX_PENDING )
+ post sendTask();
+ }
+
+ tasklet_async event void Tasklet.run()
+ {
+ }
+
+ command error_t Send.cancel(message_t* msg)
+ {
+ if( state == STATE_TX_PENDING )
+ {
+ state = STATE_READY;
+
+ // TODO: check if sendDone can be called before cancel returns
+ signal Send.sendDone(msg, ECANCEL);
+
+ return SUCCESS;
+ }
+ else
+ return FAIL;
+ }
+
+ default event void Send.sendDone(message_t* msg, error_t error)
+ {
+ }
+
+ inline command uint8_t Send.maxPayloadLength()
+ {
+ return call Packet.maxPayloadLength();
+ }
+
+ inline command void* Send.getPayload(message_t* msg, uint8_t len)
+ {
+ return call Packet.getPayload(msg, len);
+ }
+
+/*----------------- Receive -----------------*/
+
+ enum
+ {
+ RECEIVE_QUEUE_SIZE = 3,
+ };
+
+ message_t receiveQueueData[RECEIVE_QUEUE_SIZE];
+ message_t* receiveQueue[RECEIVE_QUEUE_SIZE];
+
+ uint8_t receiveQueueHead;
+ uint8_t receiveQueueSize;
+
+ command error_t SoftwareInit.init()
+ {
+ uint8_t i;
+
+ for(i = 0; i < RECEIVE_QUEUE_SIZE; ++i)
+ receiveQueue[i] = receiveQueueData + i;
+
+ return SUCCESS;
+ }
+
+ tasklet_async event bool RadioReceive.header(message_t* msg)
+ {
+ bool notFull;
+
+ // this prevents undelivered messages to be acknowledged
+ atomic notFull = receiveQueueSize < RECEIVE_QUEUE_SIZE;
+
+ return notFull;
+ }
+
+ task void deliverTask()
+ {
+ // get rid of as many messages as possible without interveining tasks
+ for(;;)
+ {
+ message_t* msg;
+
+ atomic
+ {
+ if( receiveQueueSize == 0 )
+ return;
+
+ msg = receiveQueue[receiveQueueHead];
+ }
+
+ msg = signal Receive.receive(msg,
+ call Packet.getPayload(msg, call Packet.maxPayloadLength()),
+ call Packet.payloadLength(msg));
+
+ atomic
+ {
+ receiveQueue[receiveQueueHead] = msg;
+
+ if( ++receiveQueueHead >= RECEIVE_QUEUE_SIZE )
+ receiveQueueHead = 0;
+
+ --receiveQueueSize;
+ }
+ }
+ }
+
+ tasklet_async event message_t* RadioReceive.receive(message_t* msg)
+ {
+ message_t *m;
+
+ atomic
+ {
+ if( receiveQueueSize >= RECEIVE_QUEUE_SIZE )
+ m = msg;
+ else
+ {
+ uint8_t index = receiveQueueHead + receiveQueueSize;
+ if( index >= RECEIVE_QUEUE_SIZE )
+ index -= RECEIVE_QUEUE_SIZE;
+
+ m = receiveQueue[index];
+ receiveQueue[index] = msg;
+
+ ++receiveQueueSize;
+ post deliverTask();
+ }
+ }
+
+ return m;
+ }
+
+ default event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
+ {
+ return msg;
+ }
+}
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/**
+ * Every component maintains its own neighborhood data. The Neighboorhood
+ * component maintains only the nodeids and ages of the neighbors, and
+ * evicts old entries from the table when necessary.
+ */
+interface Neighborhood
+{
+ /**
+ * Returns the index of the neighbor in the table. If the node was not
+ * found in the table, then the value NEIGHBORHOOD is returned,
+ * otherwise an index in the range [0, NEIGHBORHOOD-1] is returned.
+ */
+ tasklet_async command uint8_t getIndex(am_addr_t id);
+
+ /**
+ * Returns the age of the given entry. The age is incremented by one
+ * every time a new node is inserted into the neighborhood table that
+ * is not already at the very end. If the age would get too large to
+ * fit into a byte, then it is periodically reset to a large value.
+ */
+ tasklet_async command uint8_t getAge(uint8_t index);
+
+ /**
+ * Returns the node address for the given entry.
+ */
+ tasklet_async command am_addr_t getNode(uint8_t index);
+
+ /**
+ * Adds a new node into the neighborhood table. If this node was already
+ * in the table, then it is just brought to the front (its age is reset
+ * to zero). If the node was not in the table, then the oldest is evicted
+ * and its entry is replaced with this node. The index of the entry
+ * is returned in the range [0, NEIGHBORHOOD-1].
+ */
+ tasklet_async command uint8_t insertNode(am_addr_t id);
+
+ /**
+ * This event is fired when the oldest entry is replaced with a new
+ * node. The same interface is used by many users, so all of them
+ * will receive this event and can clear the corresponding entry.
+ * After this event is fired, all flags for this entry are cleared
+ * (see the NeighborhoodFlag interface)
+ */
+ tasklet_async event void evicted(uint8_t index);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/**
+ * This interface provides one bit storage for each neighbor in a very
+ * fast and conveint way (without using shifts for example).
+ */
+interface NeighborhoodFlag
+{
+ /**
+ * Returns the value of the flag for the given index
+ */
+ tasklet_async command bool get(uint8_t index);
+
+ /**
+ * Sets the flag for the given index
+ */
+ tasklet_async command void set(uint8_t index);
+
+ /**
+ * Clears the flag for the given index. The flag is automatically
+ * cleared after the Neighborhood.evicted event is fired.
+ */
+ tasklet_async command void clear(uint8_t index);
+
+ /**
+ * Clears the flag for all indices
+ */
+ tasklet_async command void clearAll();
+}
--- /dev/null
+/*
+ * 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")];
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Neighborhood.h>
+
+module NeighborhoodP
+{
+ provides
+ {
+ interface Init;
+ interface Neighborhood;
+ interface NeighborhoodFlag[uint8_t bit];
+ }
+}
+
+implementation
+{
+ tasklet_norace am_addr_t nodes[NEIGHBORHOOD_SIZE];
+ tasklet_norace uint8_t ages[NEIGHBORHOOD_SIZE];
+ tasklet_norace uint8_t flags[NEIGHBORHOOD_SIZE];
+ tasklet_norace uint8_t time;
+ tasklet_norace uint8_t last;
+
+ command error_t Init.init()
+ {
+ uint8_t i;
+
+ for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+ nodes[i] = AM_BROADCAST_ADDR;
+
+ return SUCCESS;
+ }
+
+ inline tasklet_async command am_addr_t Neighborhood.getNode(uint8_t index)
+ {
+ return nodes[index];
+ }
+
+ inline tasklet_async command uint8_t Neighborhood.getAge(uint8_t index)
+ {
+ return time - ages[index];
+ }
+
+ tasklet_async uint8_t command Neighborhood.getIndex(am_addr_t node)
+ {
+ uint8_t i;
+
+ if( nodes[last] == node )
+ return last;
+
+ for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+ {
+ if( nodes[i] == node )
+ {
+ last = i;
+ break;
+ }
+ }
+
+ return i;
+ }
+
+ tasklet_async uint8_t command Neighborhood.insertNode(am_addr_t node)
+ {
+ uint8_t i;
+ uint8_t maxAge;
+
+ if( nodes[last] == node )
+ {
+ if( ages[last] == time )
+ return last;
+
+ ages[last] = ++time;
+ maxAge = 0x80;
+ }
+ else
+ {
+ uint8_t oldest = 0;
+ maxAge = 0;
+
+ for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+ {
+ uint8_t age;
+
+ if( nodes[i] == node )
+ {
+ last = i;
+ if( ages[i] == time )
+ return i;
+
+ ages[i] = ++time;
+ maxAge = 0x80;
+ break;
+ }
+
+ age = time - ages[i];
+ if( age > maxAge )
+ {
+ maxAge = age;
+ oldest = i;
+ }
+ }
+
+ if( i == NEIGHBORHOOD_SIZE )
+ {
+ signal Neighborhood.evicted(oldest);
+
+ last = oldest;
+ nodes[oldest] = node;
+ ages[oldest] = ++time;
+ flags[oldest] = 0;
+ }
+ }
+
+ if( (time & 0x7F) == 0x7F && maxAge >= 0x7F )
+ {
+ for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+ {
+ if( (ages[i] | 0x7F) != time )
+ ages[i] = time & 0x80;
+ }
+ }
+
+ return last;
+ }
+
+ inline tasklet_async command bool NeighborhoodFlag.get[uint8_t bit](uint8_t index)
+ {
+ return flags[index] & (1 << bit);
+ }
+
+ inline tasklet_async command void NeighborhoodFlag.set[uint8_t bit](uint8_t index)
+ {
+ flags[index] |= (1 << bit);
+ }
+
+ inline tasklet_async command void NeighborhoodFlag.clear[uint8_t bit](uint8_t index)
+ {
+ flags[index] &= ~(1 << bit);
+ }
+
+ tasklet_async command void NeighborhoodFlag.clearAll[uint8_t bit]()
+ {
+ uint8_t i;
+
+ bit = ~(1 << bit);
+
+ for(i = 0; i < NEIGHBORHOOD_SIZE; ++i)
+ flags[i] &= bit;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface PacketTimeStamp<precision_tag, size_type>
+{
+ /**
+ * Returns TRUE if the time stamp stored in the message is valid. Under
+ * special circumstances the radio chip might not be able to correctly
+ * assign a precise time value to an incoming packet (e.g. under very
+ * heavy traffic multiple interrupts can occur before they could be
+ * serviced, and even if capture registers are used, it is not possible
+ * to get the time stamp for the first or last unserviced event), in
+ * which case the time stamp value should not be used.
+ */
+ async command bool isSet(message_t* msg);
+
+ /**
+ * Return the time stamp for the given message. Please check with the
+ * isSet command if this value can be relied upon. If this command is
+ * called after transmission, then the transmit time of the packet
+ * is returned (the time when the frame synchronization byte was
+ * transmitted). If this command is called after the message is received,
+ * the tne receive time of the message is returned.
+ */
+ async command size_type get(message_t* msg);
+
+ /**
+ * Sets the isSet flag to FALSE.
+ */
+ async command void clear(message_t* msg);
+
+ /**
+ * Sets the isSet false to TRUE and the time stamp value to the
+ * specified value.
+ */
+ async command void set(message_t* msg, size_type value);
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+interface PacketTimeSynch<precision_tag, size_type>
+{
+ /**
+ * This command should be called by the sender on packets used for sender-
+ * receiver time synchronization. The eventTime parameter should be as
+ * close to the current time as possible (precision and size of the stamp
+ * permitting) to avoid large time synchronization errors resulting from
+ * the time skew between the clocks of the sender and receiver. The
+ * time difference between the sending time and eventTime is stored in
+ * the message just before it is transmitted over the air.
+ */
+ async command void set(message_t* msg, size_type eventTime);
+
+ /**
+ * The recveive should call this method to ensure that the received time
+ * stamp is correct (for the same reason as for PacketTimeStamp.isSet).
+ * If this method returns TRUE, then the eventTime returned by the get
+ * command is correct.
+ */
+ async command bool isSet(message_t* msg);
+
+ /**
+ * This command should be called by the receiver. The time stamp of the
+ * received message is added to the embedded time difference to get the
+ * eventTime as measured by the clock of the receiver. The caller should
+ * call the isSet command before to make sure that the returned time is
+ * correct.
+ */
+ async command size_type get(message_t* msg);
+}
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <RF230.h>
+#include <HplRF230.h>
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module RF230LayerP
+{
+ provides
+ {
+ interface Init as PlatformInit @exactlyonce();
+ interface Init as SoftwareInit @exactlyonce();
+
+ interface RadioState;
+ interface RadioSend;
+ interface RadioReceive;
+ interface RadioCCA;
+ }
+
+ uses
+ {
+ interface GeneralIO as SELN;
+ interface Resource as SpiResource;
+
+ interface SpiByte;
+ interface HplRF230;
+
+ interface GeneralIO as SLP_TR;
+ interface GeneralIO as RSTN;
+
+ interface GpioCapture as IRQ;
+
+ interface BusyWait<TMicro, uint16_t>;
+
+ interface RF230Config;
+ interface Tasklet;
+
+#ifdef RF230_DEBUG
+ interface DiagMsg;
+#endif
+
+ interface RadioAlarm;
+ }
+}
+
+implementation
+{
+/*----------------- STATE -----------------*/
+
+ tasklet_norace uint8_t state;
+ enum
+ {
+ STATE_P_ON = 0,
+ STATE_SLEEP = 1,
+ STATE_SLEEP_2_TRX_OFF = 2,
+ STATE_TRX_OFF = 3,
+ STATE_TRX_OFF_2_RX_ON = 4,
+ STATE_RX_ON = 5,
+ STATE_BUSY_TX_2_RX_ON = 6,
+ STATE_PLL_ON_2_RX_ON = 7,
+ };
+
+ tasklet_norace uint8_t cmd;
+ enum
+ {
+ CMD_NONE = 0, // the state machine has stopped
+ CMD_TURNOFF = 1, // goto SLEEP state
+ CMD_STANDBY = 2, // goto TRX_OFF state
+ CMD_TURNON = 3, // goto RX_ON state
+ CMD_TRANSMIT = 4, // currently transmitting a message
+ CMD_RECEIVE = 5, // currently receiving a message
+ CMD_CCA = 6, // performing clear chanel assesment
+ CMD_CHANNEL = 7, // changing the channel
+ CMD_SIGNAL_DONE = 8, // signal the end of the state transition
+ CMD_DOWNLOAD = 9, // download the received message
+ };
+
+ norace bool radioIrq;
+
+ tasklet_norace uint8_t txPower;
+ tasklet_norace uint8_t channel;
+
+ tasklet_norace message_t* rxMsg;
+ message_t rxMsgBuffer;
+
+ uint16_t capturedTime; // the current time when the last interrupt has occured
+
+ tasklet_norace uint8_t rssiClear;
+ tasklet_norace uint8_t rssiBusy;
+
+/*----------------- REGISTER -----------------*/
+
+ inline void writeRegister(uint8_t reg, uint8_t value)
+ {
+ ASSERT( call SpiResource.isOwner() );
+ ASSERT( reg == (reg & RF230_CMD_REGISTER_MASK) );
+
+ call SELN.clr();
+ call HplRF230.spiSplitWrite(RF230_CMD_REGISTER_WRITE | reg);
+ call HplRF230.spiSplitReadWrite(value);
+ call HplRF230.spiSplitRead();
+ call SELN.set();
+ }
+
+ inline uint8_t readRegister(uint8_t reg)
+ {
+ ASSERT( call SpiResource.isOwner() );
+ ASSERT( reg == (reg & RF230_CMD_REGISTER_MASK) );
+
+ call SELN.clr();
+ call HplRF230.spiSplitWrite(RF230_CMD_REGISTER_READ | reg);
+ call HplRF230.spiSplitReadWrite(0);
+ reg = call HplRF230.spiSplitRead();
+ call SELN.set();
+
+ return reg;
+ }
+
+/*----------------- ALARM -----------------*/
+
+ enum
+ {
+ SLEEP_WAKEUP_TIME = (uint16_t)(880 * RF230_ALARM_MICROSEC),
+ CCA_REQUEST_TIME = (uint16_t)(140 * RF230_ALARM_MICROSEC),
+
+ TX_SFD_DELAY = (uint16_t)(176 * RF230_ALARM_MICROSEC),
+ RX_SFD_DELAY = (uint16_t)(8 * RF230_ALARM_MICROSEC),
+ };
+
+ tasklet_async event void RadioAlarm.fired()
+ {
+ if( state == STATE_SLEEP_2_TRX_OFF )
+ {
+ state = STATE_TRX_OFF;
+ }
+ else if( cmd == CMD_CCA )
+ {
+ uint8_t cca;
+
+ ASSERT( state == STATE_RX_ON );
+
+ cmd = CMD_NONE;
+ cca = readRegister(RF230_TRX_STATUS);
+
+ ASSERT( (cca & RF230_TRX_STATUS_MASK) == RF230_RX_ON );
+
+ signal RadioCCA.done( (cca & RF230_CCA_DONE) ? ((cca & RF230_CCA_STATUS) ? SUCCESS : EBUSY) : FAIL );
+ }
+ else
+ ASSERT(FALSE);
+
+ // make sure the rest of the command processing is called
+ call Tasklet.schedule();
+ }
+
+/*----------------- INIT -----------------*/
+
+ command error_t PlatformInit.init()
+ {
+ call SELN.makeOutput();
+ call SELN.set();
+ call SLP_TR.makeOutput();
+ call SLP_TR.clr();
+ call RSTN.makeOutput();
+ call RSTN.set();
+
+ rxMsg = &rxMsgBuffer;
+
+ // these are just good approximates
+ rssiClear = 0;
+ rssiBusy = 90;
+
+ return SUCCESS;
+ }
+
+ command error_t SoftwareInit.init()
+ {
+ // for powering up the radio
+ return call SpiResource.request();
+ }
+
+ void initRadio()
+ {
+ call BusyWait.wait(510);
+
+ call RSTN.clr();
+ call SLP_TR.clr();
+ call BusyWait.wait(6);
+ call RSTN.set();
+
+ writeRegister(RF230_TRX_CTRL_0, RF230_TRX_CTRL_0_VALUE);
+ writeRegister(RF230_TRX_STATE, RF230_TRX_OFF);
+
+ call BusyWait.wait(510);
+
+ writeRegister(RF230_IRQ_MASK, RF230_IRQ_TRX_UR | RF230_IRQ_PLL_UNLOCK | RF230_IRQ_PLL_LOCK | RF230_IRQ_TRX_END | RF230_IRQ_RX_START);
+ writeRegister(RF230_CCA_THRES, RF230_CCA_THRES_VALUE);
+ writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | RF230_TX_PWR_DEFAULT);
+
+ txPower = RF230_TX_PWR_DEFAULT;
+ channel = call RF230Config.getDefaultChannel() & RF230_CHANNEL_MASK;
+ writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel);
+
+ call SLP_TR.set();
+ state = STATE_SLEEP;
+ }
+
+/*----------------- SPI -----------------*/
+
+ event void SpiResource.granted()
+ {
+ // TODO: this should not be here, see my comment in HplRF230C.nc
+ call SELN.set();
+
+ if( state == STATE_P_ON )
+ {
+ initRadio();
+ call SpiResource.release();
+ }
+ else
+ call Tasklet.schedule();
+ }
+
+ bool isSpiAcquired()
+ {
+ if( call SpiResource.isOwner() )
+ return TRUE;
+
+ if( call SpiResource.immediateRequest() == SUCCESS )
+ {
+ // TODO: this should not be here, see my comment in HplRF230C.nc
+ call SELN.set();
+
+ return TRUE;
+ }
+
+ call SpiResource.request();
+ return FALSE;
+ }
+
+/*----------------- CHANNEL -----------------*/
+
+ tasklet_async command error_t RadioState.setChannel(uint8_t c)
+ {
+ c &= RF230_CHANNEL_MASK;
+
+ if( cmd != CMD_NONE )
+ return EBUSY;
+ else if( channel == c )
+ return EALREADY;
+
+ channel = c;
+ cmd = CMD_CHANNEL;
+ call Tasklet.schedule();
+
+ return SUCCESS;
+ }
+
+ inline void changeChannel()
+ {
+ ASSERT( cmd == CMD_CHANNEL );
+ ASSERT( state == STATE_SLEEP || state == STATE_TRX_OFF || state == STATE_RX_ON );
+
+ if( isSpiAcquired() )
+ {
+ writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel);
+
+ if( state == STATE_RX_ON )
+ state = STATE_TRX_OFF_2_RX_ON;
+ else
+ cmd = CMD_SIGNAL_DONE;
+ }
+ }
+
+/*----------------- TURN ON/OFF -----------------*/
+
+ inline void changeState()
+ {
+ if( (cmd == CMD_STANDBY || cmd == CMD_TURNON)
+ && state == STATE_SLEEP && call RadioAlarm.isFree() )
+ {
+ call SLP_TR.clr();
+
+ call RadioAlarm.wait(SLEEP_WAKEUP_TIME);
+ state = STATE_SLEEP_2_TRX_OFF;
+ }
+ else if( cmd == CMD_TURNON && state == STATE_TRX_OFF && isSpiAcquired() )
+ {
+ call IRQ.captureRisingEdge();
+ writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+ state = STATE_TRX_OFF_2_RX_ON;
+ }
+ else if( (cmd == CMD_TURNOFF || cmd == CMD_STANDBY)
+ && state == STATE_RX_ON && isSpiAcquired() )
+ {
+ call IRQ.disable();
+ writeRegister(RF230_TRX_STATE, RF230_FORCE_TRX_OFF);
+ state = STATE_TRX_OFF;
+ }
+
+ if( cmd == CMD_TURNOFF && state == STATE_TRX_OFF )
+ {
+ call SLP_TR.set();
+ state = STATE_SLEEP;
+ cmd = CMD_SIGNAL_DONE;
+ }
+ else if( cmd == CMD_STANDBY && state == STATE_TRX_OFF )
+ cmd = CMD_SIGNAL_DONE;
+ }
+
+ tasklet_async command error_t RadioState.turnOff()
+ {
+ if( cmd != CMD_NONE )
+ return EBUSY;
+ else if( state == STATE_SLEEP )
+ return EALREADY;
+
+ cmd = CMD_TURNOFF;
+ call Tasklet.schedule();
+
+ return SUCCESS;
+ }
+
+ tasklet_async command error_t RadioState.standby()
+ {
+ if( cmd != CMD_NONE || (state == STATE_SLEEP && ! call RadioAlarm.isFree()) )
+ return EBUSY;
+ else if( state == STATE_TRX_OFF )
+ return EALREADY;
+
+ cmd = CMD_STANDBY;
+ call Tasklet.schedule();
+
+ return SUCCESS;
+ }
+
+ tasklet_async command error_t RadioState.turnOn()
+ {
+ if( cmd != CMD_NONE || (state == STATE_SLEEP && ! call RadioAlarm.isFree()) )
+ return EBUSY;
+ else if( state == STATE_RX_ON )
+ return EALREADY;
+
+ cmd = CMD_TURNON;
+ call Tasklet.schedule();
+
+ return SUCCESS;
+ }
+
+ default tasklet_async event void RadioState.done() { }
+
+/*----------------- TRANSMIT -----------------*/
+
+ tasklet_async command error_t RadioSend.send(message_t* msg)
+ {
+ uint16_t time;
+ uint8_t length;
+ uint8_t* data;
+
+ if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || radioIrq )
+ return EBUSY;
+
+ if( call RF230Config.requiresRssiCca(msg)
+ && readRegister(RF230_PHY_RSSI) > ((rssiClear + rssiBusy) >> 3) )
+ return EBUSY;
+
+ writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
+
+ // do something useful, just to wait a little
+ length = call RF230Config.getTransmitPower(msg) & RF230_TX_PWR_MASK;
+ if( length != txPower )
+ {
+ txPower = length;
+ writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | txPower);
+ }
+
+ // we have missed an incoming message in this short amount of time
+ if( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) != RF230_PLL_ON )
+ {
+ ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_BUSY_RX );
+
+ state = STATE_PLL_ON_2_RX_ON;
+ return EBUSY;
+ }
+
+ atomic
+ {
+ call SLP_TR.set();
+ time = call RadioAlarm.getNow();
+ }
+ call SLP_TR.clr();
+
+ ASSERT( ! radioIrq );
+
+ call SELN.clr();
+ call HplRF230.spiSplitWrite(RF230_CMD_FRAME_WRITE);
+
+ length = call RF230Config.getLength(msg);
+ data = call RF230Config.getPayload(msg);
+
+ // length | data[0] ... data[length-3] | automatically generated FCS
+ call HplRF230.spiSplitReadWrite(length);
+
+ // the FCS is atomatically generated
+ length -= 2;
+
+ do {
+ call HplRF230.spiSplitReadWrite(*(data++));
+ }
+ while( --length != 0 );
+
+ // wait for the SPI transfer to finish
+ call HplRF230.spiSplitRead();
+ call SELN.set();
+
+ length = readRegister(RF230_TRX_STATUS);
+
+ // go back to RX_ON state when finished
+ writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+
+ /*
+ * There is a very small window (~1 microsecond) when the RF230 went
+ * into PLL_ON state but was somehow not properly initialized because
+ * of an incoming message and could not go into BUSY_TX.
+ */
+ if( (length & RF230_TRX_STATUS_MASK) != RF230_BUSY_TX )
+ {
+#ifdef RF230_DEBUG
+ if( call DiagMsg.record() )
+ {
+ call DiagMsg.str("assert tx");
+ call DiagMsg.uint16(call RadioAlarm.getNow());
+ call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
+ call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
+ call DiagMsg.hex8(radioIrq);
+ call DiagMsg.uint8(state);
+ call DiagMsg.uint8(cmd);
+ call DiagMsg.send();
+ }
+#endif
+ ASSERT( (length & RF230_TRX_STATUS_MASK) == RF230_PLL_ON );
+ return FAIL;
+ }
+
+ time += TX_SFD_DELAY;
+ call RF230Config.setTimestamp(msg, time);
+
+ // wait for the TRX_END interrupt
+ state = STATE_BUSY_TX_2_RX_ON;
+ cmd = CMD_TRANSMIT;
+
+ return SUCCESS;
+ }
+
+ default tasklet_async event void RadioSend.sendDone(error_t error) { }
+
+/*----------------- CCA -----------------*/
+
+ tasklet_async command error_t RadioCCA.request()
+ {
+ if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || ! call RadioAlarm.isFree() )
+ return EBUSY;
+
+ // see Errata B7 of the datasheet
+ // writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
+ // writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+
+ writeRegister(RF230_PHY_CC_CCA, RF230_CCA_REQUEST | RF230_CCA_MODE_VALUE | channel);
+ call RadioAlarm.wait(CCA_REQUEST_TIME);
+ cmd = CMD_CCA;
+
+ return SUCCESS;
+ }
+
+ default tasklet_async event void RadioCCA.done(error_t error) { }
+
+/*----------------- RECEIVE -----------------*/
+
+ inline void downloadMessage()
+ {
+ uint8_t length;
+ uint16_t crc;
+
+ call SELN.clr();
+ call HplRF230.spiWrite(RF230_CMD_FRAME_READ);
+
+ // read the length byte
+ length = call HplRF230.spiWrite(0);
+
+ // if correct length
+ if( length >= 3 && length <= call RF230Config.getMaxLength() )
+ {
+ uint8_t read;
+ uint8_t* data;
+
+ // initiate the reading
+ call HplRF230.spiSplitWrite(0);
+
+ call RF230Config.setLength(rxMsg, length);
+ data = call RF230Config.getPayload(rxMsg);
+ crc = 0;
+
+ // we do not store the CRC field
+ length -= 2;
+
+ read = call RF230Config.getHeaderLength();
+ if( length < read )
+ read = length;
+
+ length -= read;
+
+ while( read-- != 0 )
+ crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
+
+ if( signal RadioReceive.header(rxMsg) )
+ {
+ while( length-- != 0 )
+ crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
+
+ crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
+ crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
+
+ call RF230Config.setLinkQuality(rxMsg, call HplRF230.spiSplitRead());
+ }
+ else
+ crc = 1;
+ }
+ else
+ crc = 1;
+
+ call SELN.set();
+ state = STATE_RX_ON;
+ cmd = CMD_NONE;
+
+ // signal only if it has passed the CRC check
+ if( crc == 0 )
+ rxMsg = signal RadioReceive.receive(rxMsg);
+ }
+
+/*----------------- IRQ -----------------*/
+
+ async event void IRQ.captured(uint16_t time)
+ {
+ ASSERT( ! radioIrq );
+
+ atomic
+ {
+ capturedTime = time;
+ radioIrq = TRUE;
+ }
+
+ call Tasklet.schedule();
+ }
+
+ void serviceRadio()
+ {
+ if( isSpiAcquired() )
+ {
+ uint16_t time;
+ uint8_t irq;
+
+ atomic time = capturedTime;
+ radioIrq = FALSE;
+ irq = readRegister(RF230_IRQ_STATUS);
+
+#ifdef RF230_DEBUG
+ // TODO: handle this interrupt
+// ASSERT( ! (irq & RF230_IRQ_TRX_UR) );
+ if( irq & RF230_IRQ_TRX_UR )
+ {
+ if( call DiagMsg.record() )
+ {
+ call DiagMsg.str("assert ur");
+ call DiagMsg.uint16(call RadioAlarm.getNow());
+ call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
+ call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
+ call DiagMsg.hex8(irq);
+ call DiagMsg.uint8(state);
+ call DiagMsg.uint8(cmd);
+ call DiagMsg.send();
+ }
+ }
+#endif
+
+ // TODO: handle this interrupt
+ ASSERT( ! (irq & RF230_IRQ_PLL_UNLOCK) );
+
+ if( irq & RF230_IRQ_PLL_LOCK )
+ {
+ if( cmd == CMD_TURNON || cmd == CMD_CHANNEL )
+ {
+ ASSERT( state == STATE_TRX_OFF_2_RX_ON );
+
+ state = STATE_RX_ON;
+ cmd = CMD_SIGNAL_DONE;
+ }
+ else if( cmd == CMD_TRANSMIT )
+ {
+ ASSERT( state == STATE_BUSY_TX_2_RX_ON );
+ }
+ else
+ ASSERT(FALSE);
+ }
+
+ if( irq & RF230_IRQ_RX_START )
+ {
+ if( cmd == CMD_CCA )
+ {
+ signal RadioCCA.done(FAIL);
+ cmd = CMD_NONE;
+ }
+
+ if( cmd == CMD_NONE )
+ {
+ ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
+
+ // the most likely place for busy channel
+ rssiBusy += readRegister(RF230_PHY_RSSI) - (rssiBusy >> 2);
+
+ /*
+ * The timestamp corresponds to the first event which could not
+ * have been a PLL_LOCK because then cmd != CMD_NONE, so we must
+ * have received a message (and could also have received the
+ * TRX_END interrupt in the mean time, but that is fine. Also,
+ * we could not be after a transmission, because then cmd =
+ * CMD_TRANSMIT.
+ */
+ call RF230Config.setTimestamp(rxMsg, time - RX_SFD_DELAY);
+ cmd = CMD_RECEIVE;
+ }
+ else
+ {
+#ifdef RF230_DEBUG
+ if( call DiagMsg.record() )
+ {
+ call DiagMsg.str("assert irq");
+ call DiagMsg.uint16(call RadioAlarm.getNow());
+ call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
+ call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
+ call DiagMsg.hex8(irq);
+ call DiagMsg.uint8(state);
+ call DiagMsg.uint8(cmd);
+ call DiagMsg.send();
+ }
+#endif
+ }
+ }
+
+ if( irq & RF230_IRQ_TRX_END )
+ {
+ if( cmd == CMD_TRANSMIT )
+ {
+ ASSERT( state == STATE_BUSY_TX_2_RX_ON );
+
+ state = STATE_RX_ON;
+ cmd = CMD_NONE;
+ signal RadioSend.sendDone(SUCCESS);
+
+ // TODO: we could have missed a received message
+ ASSERT( ! (irq & RF230_IRQ_RX_START) );
+ }
+ else if( cmd == CMD_RECEIVE )
+ {
+ ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
+
+ if( state == STATE_PLL_ON_2_RX_ON )
+ {
+ ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_PLL_ON );
+
+ writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+ state = STATE_RX_ON;
+ }
+ else
+ {
+ // the most likely place for clear channel (hope to avoid acks)
+ rssiClear += readRegister(RF230_PHY_RSSI) - (rssiClear >> 2);
+ }
+
+ cmd = CMD_DOWNLOAD;
+ }
+ else
+ ASSERT(FALSE);
+ }
+ }
+ }
+
+ default tasklet_async event bool RadioReceive.header(message_t* msg)
+ {
+ return TRUE;
+ }
+
+ default tasklet_async event message_t* RadioReceive.receive(message_t* msg)
+ {
+ return msg;
+ }
+
+/*----------------- TASKLET -----------------*/
+
+ tasklet_async event void Tasklet.run()
+ {
+ if( radioIrq )
+ serviceRadio();
+
+ if( cmd != CMD_NONE )
+ {
+ if( cmd == CMD_DOWNLOAD )
+ downloadMessage();
+ else if( cmd <= CMD_TURNON && CMD_TURNOFF <= cmd )
+ changeState();
+ else if( cmd == CMD_CHANNEL )
+ changeChannel();
+
+ if( cmd == CMD_SIGNAL_DONE )
+ {
+ cmd = CMD_NONE;
+ signal RadioState.done();
+ }
+ }
+
+ if( cmd == CMD_NONE && state == STATE_RX_ON && ! radioIrq )
+ signal RadioSend.ready();
+
+ if( cmd == CMD_NONE )
+ call SpiResource.release();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioAlarm
+{
+ /**
+ * Returns TRUE if the alarm is free and ready to be used. Once the alarm
+ * is free, it cannot become nonfree in the same tasklet block. Note,
+ * if the alarm is currently set (even if for ourselves) then it is not free.
+ */
+ tasklet_async command bool isFree();
+
+ /**
+ * Waits till the specified timeout period expires. The alarm must be free.
+ */
+ tasklet_async command void wait(uint16_t timeout);
+
+ /**
+ * Cancels the running alarm. The alarm must be pending.
+ */
+ tasklet_async command void cancel();
+
+ /**
+ * This event is fired when the specified timeout period expires.
+ */
+ tasklet_async event void fired();
+
+ /**
+ * Returns the current time as measured by the radio stack.
+ */
+ async command uint16_t getNow();
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+configuration RadioAlarmC
+{
+ provides
+ {
+ interface RadioAlarm[uint8_t id]; // use unique("RadioAlarm")
+ }
+
+ uses
+ {
+ interface Alarm<TRF230, uint16_t> @exactlyonce();
+ }
+}
+
+implementation
+{
+ components RadioAlarmP, TaskletC;
+
+ RadioAlarm = RadioAlarmP;
+ Alarm = RadioAlarmP;
+ RadioAlarmP.Tasklet -> TaskletC;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module RadioAlarmP
+{
+ provides
+ {
+ interface RadioAlarm[uint8_t id];
+ }
+
+ uses
+ {
+ interface Alarm<TRF230, uint16_t>;
+ interface Tasklet;
+ }
+}
+
+implementation
+{
+ norace uint8_t state;
+ enum
+ {
+ STATE_READY = 0,
+ STATE_WAIT = 1,
+ STATE_FIRED = 2,
+ };
+
+ tasklet_norace uint8_t alarm;
+
+ async event void Alarm.fired()
+ {
+ atomic
+ {
+ if( state == STATE_WAIT )
+ state = STATE_FIRED;
+ }
+
+ call Tasklet.schedule();
+ }
+
+ inline async command uint16_t RadioAlarm.getNow[uint8_t id]()
+ {
+ return call Alarm.getNow();
+ }
+
+ tasklet_async event void Tasklet.run()
+ {
+ if( state == STATE_FIRED )
+ {
+ state = STATE_READY;
+ signal RadioAlarm.fired[alarm]();
+ }
+ }
+
+ default tasklet_async event void RadioAlarm.fired[uint8_t id]()
+ {
+ }
+
+ inline tasklet_async command bool RadioAlarm.isFree[uint8_t id]()
+ {
+ return state == STATE_READY;
+ }
+
+ tasklet_async command void RadioAlarm.wait[uint8_t id](uint16_t timeout)
+ {
+ ASSERT( state == STATE_READY );
+
+ alarm = id;
+ state = STATE_WAIT;
+ call Alarm.start(timeout);
+ }
+
+ tasklet_async command void RadioAlarm.cancel[uint8_t id]()
+ {
+ ASSERT( alarm == id );
+ ASSERT( state != STATE_READY );
+
+ call Alarm.stop();
+ state = STATE_READY;
+ }
+}
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioCCA
+{
+ /**
+ * Starts the clear channel assesment procedure. Returns EBUSY if the radio
+ * is currently servicing a clear channel assesment, and SUCCESS otherwise.
+ * The check will be performed only in the RX_READY state.
+ */
+ tasklet_async command error_t request();
+
+ /**
+ * Signals the completion of the clear channel assesment send command.
+ * SUCCESS means the channel is clear, EBUSY means the channel is not
+ * clear, and FAIL means that the clear channel assesment could not
+ * be finished or the operation was cancelled.
+ */
+ tasklet_async event void done(error_t error);
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioReceive
+{
+ /**
+ * This event is fired when the header is received/downloaded and the
+ * higher layers are consulted whether it needs to be downloaded and
+ * further processed. Return FALSE if the message should be discarded.
+ * In particular, the message buffer layer returns FALSE if there is
+ * no space for a new message, so this message will not get acknowledged.
+ */
+ tasklet_async event bool header(message_t* msg);
+
+ /**
+ * Signals the reception of a message, but only for those messages for
+ * which SUCCESS was returned in the header event. The usual owner rules
+ * apply to the message pointers.
+ */
+ tasklet_async event message_t* receive(message_t* msg);
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioSend
+{
+ /**
+ * Starts the transmission of the given message. This command must not
+ * be called while another send is in progress (so one must wait for the
+ * sendDone event). Returns EBUSY if a reception is in progress or for
+ * some other reason the request cannot be temporarily satisfied (e.g.
+ * the SPI bus access could not be acquired). In this case the send
+ * command could be retried from a tasklet. Returns SUCCESS if the
+ * transmission could be started. In this case sendDone will be fired.
+ */
+ tasklet_async command error_t send(message_t* msg);
+
+ /**
+ * Signals the completion of the send command, exactly once for each
+ * successfull send command. If the returned error code is SUCCESS, then
+ * the message was sent (may not have been acknowledged), otherwise
+ * the message was not transmitted over the air.
+ */
+ tasklet_async event void sendDone(error_t error);
+
+ /**
+ * This event is fired when the component is most likely able to accept
+ * a send request. If the send command has returned with a failure, then
+ * this event will be called at least once in the near future.
+ */
+ tasklet_async event void ready();
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface RadioState
+{
+ /**
+ * Moves to radio into sleep state with the lowest power consumption but
+ * highest wakeup time. The radio cannot send or receive in this state
+ * and releases all access to shared resources (e.g. SPI bus).
+ */
+ tasklet_async command error_t turnOff();
+
+ /**
+ * The same as the turnOff command, except it is not as deep sleep, and
+ * it is quicker to recover from this state.
+ */
+ tasklet_async command error_t standby();
+
+ /**
+ * Goes into receive state. The radio continuously receive messages
+ * and able to transmit.
+ */
+ tasklet_async command error_t turnOn();
+
+ /**
+ * Sets the current channel. Returns EBUSY if the stack is unable
+ * to change the channel this time (some other operation is in progress)
+ * SUCCESS otherwise.
+ */
+ tasklet_async command error_t setChannel(uint8_t channel);
+
+ /**
+ * This event is signaled exactly once for each sucessfully posted state
+ * transition and setChannel command when it is completed.
+ */
+ tasklet_async event void done();
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module RandomCollisionLayerP
+{
+ provides
+ {
+ interface RadioSend;
+ interface RadioReceive;
+ }
+ uses
+ {
+ interface RadioSend as SubSend;
+ interface RadioReceive as SubReceive;
+ interface RadioAlarm;
+ interface Random;
+ interface RandomCollisionConfig as Config;
+ }
+}
+
+implementation
+{
+ tasklet_norace uint8_t state;
+ enum
+ {
+ STATE_READY = 0,
+ STATE_TX_PENDING_FIRST = 1,
+ STATE_TX_PENDING_SECOND = 2,
+ STATE_TX_SENDING = 3,
+
+ STATE_BARRIER = 0x80,
+ };
+
+ tasklet_norace message_t *txMsg;
+ tasklet_norace uint16_t txBarrier;
+
+ tasklet_async event void SubSend.ready()
+ {
+ if( state == STATE_READY && call RadioAlarm.isFree() )
+ signal RadioSend.ready();
+ }
+
+ uint16_t nextRandom;
+ task void calcNextRandom()
+ {
+ uint16_t a = call Random.rand16();
+ atomic nextRandom = a;
+ }
+
+ uint16_t getBackoff(uint16_t maxBackoff)
+ {
+ uint16_t a;
+
+ atomic
+ {
+ a = nextRandom;
+ nextRandom += 273;
+ }
+ post calcNextRandom();
+
+ return (a % maxBackoff) + call Config.getMinimumBackoff();
+ }
+
+ tasklet_async command error_t RadioSend.send(message_t* msg)
+ {
+ if( state != STATE_READY || ! call RadioAlarm.isFree() )
+ return EBUSY;
+
+ txMsg = msg;
+ state = STATE_TX_PENDING_FIRST;
+ call RadioAlarm.wait(getBackoff(call Config.getInitialBackoff(msg)));
+
+ return SUCCESS;
+ }
+
+ tasklet_async event void RadioAlarm.fired()
+ {
+ error_t error;
+ int16_t delay;
+
+ ASSERT( state != STATE_READY );
+
+ delay = (int16_t)txBarrier - call RadioAlarm.getNow();
+
+ if( state == STATE_BARRIER )
+ {
+ state = STATE_READY;
+
+ signal RadioSend.ready();
+ return;
+ }
+ else if( (state & STATE_BARRIER) && delay > 0 )
+ error = EBUSY;
+ else
+ error = call SubSend.send(txMsg);
+
+ if( error != SUCCESS )
+ {
+ if( (state & ~STATE_BARRIER) == STATE_TX_PENDING_FIRST )
+ {
+ state = (state & STATE_BARRIER) | STATE_TX_PENDING_SECOND;
+ call RadioAlarm.wait(getBackoff(call Config.getCongestionBackoff(txMsg)));
+ }
+ else
+ {
+ if( (state & STATE_BARRIER) && delay > 0 )
+ {
+ state = STATE_BARRIER;
+ call RadioAlarm.wait(delay);
+ }
+ else
+ state = STATE_READY;
+
+ signal RadioSend.sendDone(error);
+ }
+ }
+ else
+ state = STATE_TX_SENDING;
+ }
+
+ tasklet_async event void SubSend.sendDone(error_t error)
+ {
+ ASSERT( state == STATE_TX_SENDING );
+
+ state = STATE_READY;
+ signal RadioSend.sendDone(error);
+ }
+
+ tasklet_async event bool SubReceive.header(message_t* msg)
+ {
+ return signal RadioReceive.header(msg);
+ }
+
+ tasklet_async event message_t* SubReceive.receive(message_t* msg)
+ {
+ int16_t delay;
+
+ txBarrier = call Config.getTransmitBarrier(msg);
+ delay = txBarrier - call RadioAlarm.getNow();
+
+ if( delay > 0 )
+ {
+ if( state == STATE_READY )
+ {
+ call RadioAlarm.wait(delay);
+ state = STATE_BARRIER;
+ }
+ else
+ state |= STATE_BARRIER;
+ }
+
+ return signal RadioReceive.receive(msg);
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module SlottedCollisionLayerP
+{
+ provides
+ {
+ interface RadioSend;
+ interface RadioReceive;
+ interface Init;
+ }
+ uses
+ {
+ interface RadioSend as SubSend;
+ interface RadioReceive as SubReceive;
+ interface RadioAlarm;
+ interface Random;
+ interface SlottedCollisionConfig as Config;
+#ifdef RF230_DEBUG
+ interface DiagMsg;
+#endif
+ }
+}
+
+implementation
+{
+/* ----- random ----- */
+
+ uint16_t nextRandom;
+
+ task void calcNextRandom()
+ {
+ uint16_t a = call Random.rand16();
+ atomic nextRandom = a;
+ }
+
+ uint16_t getNextRandom()
+ {
+ uint16_t a;
+
+ atomic
+ {
+ a = nextRandom;
+ nextRandom += 273;
+ }
+ post calcNextRandom();
+
+ return a;
+ }
+
+/* ----- schedule selection ----- */
+
+ tasklet_async event bool SubReceive.header(message_t* msg)
+ {
+ return signal RadioReceive.header(msg);
+ }
+
+ // WARNING!!! Do not change these values, the error values can overflow
+ enum
+ {
+ ERROR_DECAY = 3,
+ ERROR_SWITCH = 30, // should be a multiple of (1 << decay)
+ ERROR_COLLISION = 20, // must be less than (255 - switch) >> decay
+ ERROR_BUSY = 1, // must be less than collision
+ ERROR_INITIAL = 80, // must be less than giveup
+ ERROR_GIVEUP = 120, // must be less than collision * (1 << decay)
+ ERROR_REPRESS = 40, // must be more than switch
+ ERROR_MAX = 255,
+ };
+
+ /**
+ * Returns TRUE if time is between start and start + window
+ * modulo the schedule size of (1 << exponent)
+ */
+ inline bool isBetween(uint8_t exponent, uint16_t time, uint16_t start, uint16_t length)
+ {
+ return (uint16_t)((time - start) & ((1 << exponent) - 1)) < length;
+ }
+
+ tasklet_norace uint16_t schedule1;
+ tasklet_norace uint16_t schedule2;
+
+ tasklet_norace uint8_t error1;
+ tasklet_norace uint8_t error2;
+
+ tasklet_async event message_t* SubReceive.receive(message_t* msg)
+ {
+ uint8_t exponent = call Config.getScheduleExponent();
+ uint16_t start = call Config.getCollisionWindowStart(msg);
+ uint16_t length = call Config.getCollisionWindowLength(msg);
+
+ error1 -= error1 >> ERROR_DECAY;
+ if( isBetween(exponent, schedule1, start, length) )
+ error1 += ERROR_COLLISION;
+
+ error2 -= error2 >> ERROR_DECAY;
+ if( isBetween(exponent, schedule2, start, length) )
+ error2 += ERROR_COLLISION;
+
+ if( error2 + ERROR_SWITCH <= error1 )
+ {
+ error1 = error2;
+ schedule1 = schedule2;
+ error2 = ERROR_GIVEUP;
+ }
+
+ if( error2 >= ERROR_GIVEUP )
+ {
+ error2 = ERROR_INITIAL;
+ schedule2 = getNextRandom();
+ }
+
+ return signal RadioReceive.receive(msg);
+ }
+
+ void printStats();
+
+ tasklet_async event void Config.timerTick()
+ {
+ if( error1 >= (1 << ERROR_DECAY) )
+ error1 -= error1 >> ERROR_DECAY;
+ else if( error1 > 0 )
+ --error1;
+
+ if( error2 >= (1 << ERROR_DECAY) )
+ error2 -= error2 >> ERROR_DECAY;
+ else if( error2 > 0 )
+ --error2;
+
+ printStats();
+ }
+
+/* ------ transmit ------ */
+
+ tasklet_norace uint8_t state;
+ enum
+ {
+ STATE_READY = 0,
+ STATE_PENDING = 1,
+ STATE_SENDING = 2,
+ };
+
+ enum { DELAY_DECAY = 2 };
+
+ tasklet_norace message_t *txMsg;
+ tasklet_norace uint16_t txDelay; // the averaged delay between schedule and timestamp
+ tasklet_norace uint16_t txTime; // the schedule time of transmission
+
+ tasklet_async event void SubSend.ready()
+ {
+ if( state == STATE_READY && call RadioAlarm.isFree() )
+ signal RadioSend.ready();
+ }
+
+ tasklet_async command error_t RadioSend.send(message_t* msg)
+ {
+ uint16_t backoff;
+ uint16_t time;
+
+ // TODO: we could supress transmission while error is large
+ if( state != STATE_READY || ! call RadioAlarm.isFree() || error1 >= ERROR_REPRESS )
+ return EBUSY;
+
+ txMsg = msg;
+ state = STATE_PENDING;
+
+ time = call RadioAlarm.getNow();
+ backoff = 1 + ((schedule1 - time - (txDelay >> DELAY_DECAY))
+ & ((1 << call Config.getScheduleExponent()) - 1));
+
+ backoff += getNextRandom() & (3 << call Config.getScheduleExponent());
+
+ call RadioAlarm.wait(backoff);
+ txTime = time + backoff;
+
+ return SUCCESS;
+ }
+
+ tasklet_async event void RadioAlarm.fired()
+ {
+ error_t error;
+
+ ASSERT( state == STATE_PENDING );
+
+ error = call SubSend.send(txMsg);
+ if( error == SUCCESS )
+ state = STATE_SENDING;
+ else
+ {
+ if( error2 + ERROR_SWITCH <= error1 )
+ {
+ error1 = error2;
+ schedule1 = schedule2;
+ error2 = ERROR_INITIAL;
+ schedule2 = getNextRandom();
+ }
+ else if( error1 < ERROR_MAX - ERROR_BUSY )
+ error1 = error1 + ERROR_BUSY;
+
+ state = STATE_READY;
+ signal RadioSend.sendDone(error);
+ }
+ }
+
+ tasklet_async event void SubSend.sendDone(error_t error)
+ {
+ ASSERT( state == STATE_SENDING );
+
+ if( error == SUCCESS )
+ {
+ txDelay += (call Config.getTransmitTime(txMsg) - txTime) - (txDelay >> DELAY_DECAY);
+
+ ASSERT( (txDelay >> DELAY_DECAY) < (1 << call Config.getScheduleExponent()) );
+ }
+
+ state = STATE_READY;
+ signal RadioSend.sendDone(error);
+ }
+
+/* ------ init ------ */
+
+ command error_t Init.init()
+ {
+ // do not use Random here because it might not be initialized
+ schedule1 = (uint16_t)(TOS_NODE_ID * 1973);
+ schedule2 = schedule1 + 0117;
+ txDelay = call Config.getInitialDelay() << DELAY_DECAY;
+
+ return SUCCESS;
+ }
+
+#ifdef RF230_DEBUG
+ tasklet_norace uint8_t count;
+ void printStats()
+ {
+ if( ++count > 10 && call DiagMsg.record() )
+ {
+ count = 0;
+
+ call DiagMsg.str("slotted");
+ call DiagMsg.uint16(txDelay >> DELAY_DECAY);
+ call DiagMsg.uint16(schedule1);
+ call DiagMsg.uint8(error1);
+ call DiagMsg.uint16(schedule2);
+ call DiagMsg.uint8(error2);
+ call DiagMsg.send();
+ }
+ }
+#else
+ void printStats() { }
+#endif
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface SoftwareAckConfig
+{
+ /**
+ * Returns the acknowledgement timeout (in the radio clock units),
+ * in which a sent packet must be acknowledged.
+ */
+ async command uint16_t getAckTimeout();
+
+ /**
+ * Returns TRUE if the layer should wait for a software acknowledgement
+ * to be received after this packet was transmitted.
+ */
+ async command bool requiresAckWait(message_t* msg);
+
+ /**
+ * Sets for the transmitted message whether it was acknowledged or not.
+ */
+ async command void setAckReceived(message_t* msg, bool acked);
+
+ /**
+ * Returns TRUE if the received packet is an acknowledgement packet.
+ * The AckedSend layer will filter out all received acknowledgement
+ * packets and uses only the matching one for the acknowledgement.
+ */
+ async command bool isAckPacket(message_t* msg);
+
+ /**
+ * Returns TRUE if the acknowledgement packet corresponds to the
+ * data packet. The acknowledgement packect was already verified
+ * to be a valid acknowledgement packet via the isAckPacket command.
+ */
+ async command bool verifyAckPacket(message_t* data, message_t* ack);
+
+ /**
+ * Returns TRUE if the received packet needs software acknowledgements
+ * to be sent back to the sender.
+ */
+ async command bool requiresAckReply(message_t* msg);
+
+ /**
+ * Creates an acknowledgement packet for the given data packet.
+ */
+ async command void createAckPacket(message_t* data, message_t* ack);
+
+ /**
+ * This command is called when a sent packet did not receive an
+ * acknowledgement.
+ */
+ tasklet_async command void reportChannelError();
+}
--- /dev/null
+/*
+ * 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")];
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module SoftwareAckLayerP
+{
+ provides
+ {
+ interface RadioSend;
+ interface RadioReceive;
+ }
+ uses
+ {
+ interface RadioSend as SubSend;
+ interface RadioReceive as SubReceive;
+ interface RadioAlarm;
+
+ interface SoftwareAckConfig;
+ }
+}
+
+implementation
+{
+ tasklet_norace uint8_t state;
+ enum
+ {
+ STATE_READY = 0,
+ STATE_DATA_SEND = 1,
+ STATE_ACK_WAIT = 2,
+ STATE_ACK_SEND = 3,
+ };
+
+ tasklet_norace message_t *txMsg;
+ tasklet_norace message_t ackMsg;
+
+ tasklet_async event void SubSend.ready()
+ {
+ if( state == STATE_READY )
+ signal RadioSend.ready();
+ }
+
+ tasklet_async command error_t RadioSend.send(message_t* msg)
+ {
+ error_t error;
+
+ if( state == STATE_READY )
+ {
+ if( (error = call SubSend.send(msg)) == SUCCESS )
+ {
+ call SoftwareAckConfig.setAckReceived(msg, FALSE);
+ state = STATE_DATA_SEND;
+ txMsg = msg;
+ }
+ }
+ else
+ error = EBUSY;
+
+ return error;
+ }
+
+ tasklet_async event void SubSend.sendDone(error_t error)
+ {
+ if( state == STATE_ACK_SEND )
+ {
+ // TODO: what if error != SUCCESS
+ ASSERT( error == SUCCESS );
+
+ state = STATE_READY;
+ }
+ else
+ {
+ ASSERT( state == STATE_DATA_SEND );
+ ASSERT( call RadioAlarm.isFree() );
+
+ if( error == SUCCESS && call SoftwareAckConfig.requiresAckWait(txMsg) && call RadioAlarm.isFree() )
+ {
+ call RadioAlarm.wait(call SoftwareAckConfig.getAckTimeout());
+ state = STATE_ACK_WAIT;
+ }
+ else
+ {
+ state = STATE_READY;
+ signal RadioSend.sendDone(error);
+ }
+ }
+ }
+
+ tasklet_async event void RadioAlarm.fired()
+ {
+ ASSERT( state == STATE_ACK_WAIT );
+
+ call SoftwareAckConfig.reportChannelError();
+
+ state = STATE_READY;
+ signal RadioSend.sendDone(SUCCESS); // we have sent it, but not acked
+ }
+
+ tasklet_async event bool SubReceive.header(message_t* msg)
+ {
+ if( call SoftwareAckConfig.isAckPacket(msg) )
+ return state == STATE_ACK_WAIT && call SoftwareAckConfig.verifyAckPacket(txMsg, msg);
+ else
+ return signal RadioReceive.header(msg);
+ }
+
+ tasklet_async event message_t* SubReceive.receive(message_t* msg)
+ {
+ bool ack = call SoftwareAckConfig.isAckPacket(msg);
+
+ ASSERT( state == STATE_ACK_WAIT || state == STATE_READY );
+
+ if( state == STATE_ACK_WAIT )
+ {
+ call RadioAlarm.cancel();
+ call SoftwareAckConfig.setAckReceived(txMsg, ack);
+
+ state = STATE_READY;
+ signal RadioSend.sendDone(SUCCESS);
+ }
+
+ if( ack )
+ return msg;
+
+ if( call SoftwareAckConfig.requiresAckReply(msg) )
+ {
+ call SoftwareAckConfig.createAckPacket(msg, &ackMsg);
+
+ // TODO: what to do if we are busy and cannot send an ack
+ if( call SubSend.send(&ackMsg) == SUCCESS )
+ state = STATE_ACK_SEND;
+ else
+ ASSERT(FALSE);
+ }
+
+ return signal RadioReceive.receive(msg);
+ }
+}
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/**
+ * This interface is useful in building state machines when the state
+ * transitions should be executed atomically but with interrupts enabled.
+ * All state transitions should take place in the run event handler or
+ * in blocks protected by the suspend and resume commands.
+ */
+interface Tasklet
+{
+ /**
+ * This method is executed atomically.
+ */
+ tasklet_async event void run();
+
+ /**
+ * Makes sure that the run event is called at least once more. If the
+ * run event is currently not executing, then it is called immediately
+ * and this command returns only after the completion of the run event.
+ * If the run event is currently executed, then this method returns at
+ * once, and makes sure that the run event is called once more when
+ * it is finished. If this method is called from a task, then by the
+ * above rules, the run event will be called from a task as well.
+ */
+ async command void schedule();
+
+ /**
+ * Enters a critical section of the code and meakes sure that the
+ * run event is not called while in this section. No long running
+ * computation should be called from the critical session, and
+ * in particular no user event should be fired. This call is only
+ * possible from task context, otherwise we cannot guarantee that
+ * the run event is not currently running. The suspend calls
+ * can be nested. It is very important that the same number of
+ * resume commands must be called in all control paths, e.g. be very
+ * careful with the return and break commands.
+ */
+ command void suspend();
+
+ /**
+ * Leaves the critical section. This call is conly possible from
+ * task context. If there were scheduled executions of the run
+ * event, then those will be called before this command returns.
+ */
+ command void resume();
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <RadioAssert.h>
+
+module TaskletC
+{
+ provides interface Tasklet;
+}
+
+implementation
+{
+#ifdef TASKLET_IS_TASK
+
+ task void tasklet()
+ {
+ signal Tasklet.run();
+ }
+
+ inline async command void Tasklet.schedule()
+ {
+ post tasklet();
+ }
+
+ inline command void Tasklet.suspend()
+ {
+ }
+
+ inline command void Tasklet.resume()
+ {
+ }
+
+#else
+
+ /**
+ * The lower 7 bits contain the number of suspends plus one if the run
+ * event is currently beeing executed. The highest bit is set if the run
+ * event needs to be called again when the suspend count goes down to zero.
+ */
+ uint8_t state;
+
+ void doit()
+ {
+ for(;;)
+ {
+ signal Tasklet.run();
+
+ atomic
+ {
+ if( state == 1 )
+ {
+ state = 0;
+ return;
+ }
+
+ ASSERT( state == 0x81 );
+ state = 1;
+ }
+ }
+ }
+
+ inline command void Tasklet.suspend()
+ {
+ atomic ++state;
+ }
+
+ command void Tasklet.resume()
+ {
+ atomic
+ {
+ if( --state != 0x80 )
+ return;
+
+ state = 1;
+ }
+
+ doit();
+ }
+
+ async command void Tasklet.schedule()
+ {
+ atomic
+ {
+ if( state != 0 )
+ {
+ state |= 0x80;
+ return;
+ }
+
+ state = 1;
+ }
+
+ doit();
+ }
+
+#endif
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface TrafficMonitorConfig
+{
+ /**
+ * Returns the frequency (in milliseconds) when the traffic averages
+ * should be updated.
+ */
+ async command uint16_t getUpdatePeriod();
+
+ /**
+ * Returns the amount of time this message has occupied the channel.
+ */
+ async command uint16_t getChannelTime(message_t* msg);
+
+ /**
+ * Returns the sender address of the message so we can calculate the
+ * average number of neighbors that send messages per update period.
+ */
+ async command am_addr_t getSender(message_t* msg);
+
+ /**
+ * This event should be fired if we notice some anomalies in the operation
+ * of the channel, such as not receiving acknowledgements, missing
+ * sequence numbers or packets with corrupted CRC.
+ */
+ tasklet_async event void channelError();
+
+ /**
+ * Returns the averaged (exponential decay) transmit channel time
+ * during one update period.
+ */
+ tasklet_async event uint16_t getTransmitAverage();
+
+ /**
+ * Returns the averaged (exponential decay) receive channel time
+ * during one update period.
+ */
+ tasklet_async event uint16_t getReceiveAverage();
+
+ /**
+ * Returns the averaged (exponential decay) number of neighbors
+ * whose messages this component receives during one update period.
+ */
+ tasklet_async event uint8_t getNeighborAverage();
+
+ /**
+ * Returns the averaged error events during one update period.
+ */
+ tasklet_async event uint8_t getErrorAverage();
+
+ /**
+ * This command is periodically called when the timer is fired and
+ * the averages are updated
+ */
+ tasklet_async command void timerTick();
+}
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, reportS, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+/*
+ * You have to make sure that the maximum channel time in one report
+ * period times (1 << TRAFFIC_MONITOR_DECAY) is less than 65535.
+ */
+#ifndef TRAFFIC_MONITOR_DECAY
+#define TRAFFIC_MONITOR_DECAY 3
+#endif
+
+module TrafficMonitorLayerP
+{
+ provides
+ {
+ interface RadioSend;
+ interface RadioReceive;
+ interface RadioState;
+ }
+
+ uses
+ {
+ interface TrafficMonitorConfig;
+ interface RadioSend as SubSend;
+ interface RadioReceive as SubReceive;
+ interface RadioState as SubState;
+ interface Timer<TMilli> as Timer;
+ interface Neighborhood;
+ interface NeighborhoodFlag;
+ interface Tasklet;
+#ifdef RF230_DEBUG
+ interface DiagMsg;
+#endif
+ }
+}
+
+implementation
+{
+ tasklet_norace message_t *txMsg;
+ tasklet_norace uint8_t neighborCount;
+
+ tasklet_norace uint16_t txAverage;
+ tasklet_norace uint16_t rxAverage;
+ tasklet_norace uint8_t neighborAverage;
+ tasklet_norace uint8_t errorAverage;
+
+ enum
+ {
+ // the maximum average value
+ TRAFFIC_MONITOR_UINT8_MAX = 1 << (7-TRAFFIC_MONITOR_DECAY),
+
+ // the unsignificant bits of the averaged values
+ TRAFFIC_MONITOR_MASK = (1 << TRAFFIC_MONITOR_DECAY) - 1,
+
+ // to get the ceiling integer value
+ TRAFFIC_MONITOR_ROUND_UP = (1 << TRAFFIC_MONITOR_DECAY) - 1,
+ };
+
+ tasklet_async event void SubSend.ready()
+ {
+ signal RadioSend.ready();
+ }
+
+ tasklet_async command error_t RadioSend.send(message_t* msg)
+ {
+ txMsg = msg;
+ return call SubSend.send(msg);
+ }
+
+ tasklet_async event void SubSend.sendDone(error_t error)
+ {
+ if( error == SUCCESS )
+ txAverage += call TrafficMonitorConfig.getChannelTime(txMsg);
+
+ signal RadioSend.sendDone(error);
+ }
+
+ tasklet_async event bool SubReceive.header(message_t* msg)
+ {
+ return signal RadioReceive.header(msg);
+ }
+
+ tasklet_async event message_t* SubReceive.receive(message_t* msg)
+ {
+ uint8_t index;
+
+ rxAverage += call TrafficMonitorConfig.getChannelTime(msg);
+
+ index = call Neighborhood.insertNode(call TrafficMonitorConfig.getSender(msg));
+ if( ! call NeighborhoodFlag.get(index) )
+ {
+ if( neighborCount < TRAFFIC_MONITOR_UINT8_MAX )
+ {
+ ++neighborCount;
+ call NeighborhoodFlag.set(index);
+ }
+ }
+
+ return signal RadioReceive.receive(msg);
+ }
+
+ tasklet_async event void TrafficMonitorConfig.channelError()
+ {
+ if( errorAverage < 255 )
+ ++errorAverage;
+ }
+
+ uint8_t debugCounter;
+
+ event void Timer.fired()
+ {
+ uint8_t fraction;
+
+ call Tasklet.suspend();
+
+ txAverage -= (txAverage >> TRAFFIC_MONITOR_DECAY);
+ rxAverage -= (rxAverage >> TRAFFIC_MONITOR_DECAY);
+ errorAverage -= (errorAverage >> TRAFFIC_MONITOR_DECAY);
+
+ // we could get stuck in the [1,7] range with no neighbors, so be more precise
+ fraction = neighborAverage >> TRAFFIC_MONITOR_DECAY;
+ if( fraction == neighborCount && (neighborAverage & TRAFFIC_MONITOR_MASK) != 0 )
+ --neighborAverage;
+ else
+ neighborAverage += neighborCount - fraction;
+
+ call NeighborhoodFlag.clearAll();
+ neighborCount = 0;
+
+ call TrafficMonitorConfig.timerTick();
+
+ call Tasklet.resume();
+
+#ifdef RF230_DEBUG
+ if( ++debugCounter >= 10 && call DiagMsg.record() )
+ {
+ debugCounter = 0;
+
+ call DiagMsg.str("traffic");
+ call DiagMsg.uint16(signal TrafficMonitorConfig.getTransmitAverage());
+ call DiagMsg.uint16(signal TrafficMonitorConfig.getReceiveAverage());
+ call DiagMsg.uint8(signal TrafficMonitorConfig.getNeighborAverage());
+ call DiagMsg.uint8(signal TrafficMonitorConfig.getErrorAverage());
+ call DiagMsg.send();
+ }
+#endif
+ }
+
+ tasklet_async event void Tasklet.run()
+ {
+ }
+
+ tasklet_async event uint16_t TrafficMonitorConfig.getTransmitAverage()
+ {
+ return txAverage >> TRAFFIC_MONITOR_DECAY;
+ }
+
+ tasklet_async event uint16_t TrafficMonitorConfig.getReceiveAverage()
+ {
+ return rxAverage >> TRAFFIC_MONITOR_DECAY;
+ }
+
+ tasklet_async event uint8_t TrafficMonitorConfig.getNeighborAverage()
+ {
+ return (neighborAverage + TRAFFIC_MONITOR_ROUND_UP) >> TRAFFIC_MONITOR_DECAY;
+ }
+
+ tasklet_async event uint8_t TrafficMonitorConfig.getErrorAverage()
+ {
+ return errorAverage >> TRAFFIC_MONITOR_DECAY;
+ }
+
+ tasklet_async event void Neighborhood.evicted(uint8_t index) { }
+
+ enum
+ {
+ RADIO_CMD_NONE = 0,
+ RADIO_CMD_TURNON = 1,
+ RADIO_CMD_TURNOFF = 2,
+ };
+ tasklet_norace uint8_t radioCmd;
+
+ tasklet_async command error_t RadioState.turnOff()
+ {
+ radioCmd = RADIO_CMD_TURNOFF;
+ return call SubState.turnOff();
+ }
+
+ tasklet_async command error_t RadioState.standby()
+ {
+ radioCmd = RADIO_CMD_TURNOFF;
+ return call SubState.standby();
+ }
+
+ tasklet_async command error_t RadioState.turnOn()
+ {
+ radioCmd = RADIO_CMD_TURNON;
+ return call SubState.turnOn();
+ }
+
+ tasklet_async command error_t RadioState.setChannel(uint8_t channel)
+ {
+ radioCmd = RADIO_CMD_NONE;
+ return call SubState.setChannel(channel);
+ }
+
+ task void startStopTimer()
+ {
+ if( radioCmd == RADIO_CMD_TURNON )
+ call Timer.startPeriodic(call TrafficMonitorConfig.getUpdatePeriod());
+ else if( radioCmd == RADIO_CMD_TURNOFF )
+ call Timer.stop();
+ }
+
+ tasklet_async event void SubState.done()
+ {
+ post startStopTimer();
+ signal RadioState.done();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+
+interface UniqueConfig
+{
+ /**
+ * Returns the sequence number of the packet.
+ */
+ async command uint8_t getSequenceNumber(message_t* msg);
+
+ /**
+ * Returns the sender of the packet.
+ */
+ async command am_addr_t getSender(message_t* msg);
+
+ /**
+ * Sets the sequence number of the packet.
+ */
+ async command void setSequenceNumber(message_t*msg, uint8_t number);
+
+ /**
+ * This command is called when the unqiue layer detects a missing (jump
+ * in the data sequence number) or a duplicate packet.
+ */
+ tasklet_async command void reportChannelError();
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <Tasklet.h>
+#include <Neighborhood.h>
+
+module UniqueLayerP
+{
+ provides
+ {
+ interface Send;
+ interface RadioReceive;
+
+ interface Init;
+ }
+
+ uses
+ {
+ interface Send as SubSend;
+ interface RadioReceive as SubReceive;
+
+ interface UniqueConfig;
+ interface Neighborhood;
+ interface NeighborhoodFlag;
+ }
+}
+
+implementation
+{
+ uint8_t sequenceNumber;
+
+ command error_t Init.init()
+ {
+ sequenceNumber = TOS_NODE_ID << 4;
+ return SUCCESS;
+ }
+
+ command error_t Send.send(message_t* msg, uint8_t len)
+ {
+ call UniqueConfig.setSequenceNumber(msg, ++sequenceNumber);
+ return call SubSend.send(msg, len);
+ }
+
+ command error_t Send.cancel(message_t* msg)
+ {
+ return call SubSend.cancel(msg);
+ }
+
+ event void SubSend.sendDone(message_t* msg, error_t error)
+ {
+ signal Send.sendDone(msg, error);
+ }
+
+ command uint8_t Send.maxPayloadLength()
+ {
+ return call SubSend.maxPayloadLength();
+ }
+
+ command void* Send.getPayload(message_t* msg, uint8_t len)
+ {
+ return call SubSend.getPayload(msg, len);
+ }
+
+ tasklet_async event bool SubReceive.header(message_t* msg)
+ {
+ // we could scan here, but better be lazy
+ return signal RadioReceive.header(msg);
+ }
+
+ tasklet_norace uint8_t receivedNumbers[NEIGHBORHOOD_SIZE];
+
+ tasklet_async event message_t* SubReceive.receive(message_t* msg)
+ {
+ uint8_t index = call Neighborhood.insertNode(call UniqueConfig.getSender(msg));
+ uint8_t dsn = call UniqueConfig.getSequenceNumber(msg);
+
+ if( call NeighborhoodFlag.get(index) )
+ {
+ uint8_t diff = dsn - receivedNumbers[index];
+
+ if( diff == 0 )
+ {
+ call UniqueConfig.reportChannelError();
+ return msg;
+ }
+ }
+ else
+ call NeighborhoodFlag.set(index);
+
+ receivedNumbers[index] = dsn;
+
+ return signal RadioReceive.receive(msg);
+ }
+
+ tasklet_async event void Neighborhood.evicted(uint8_t index) { }
+}
--- /dev/null
+
+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.
--- /dev/null
+/*
+ * 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__
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+/**
+ * The DiagMsg interface allows messages to be sent back to the base station
+ * containing several values and their type information, like in
+ * <code>printf(...)</code>. The base station must be connected to a PC using
+ * a serial cable. On the PC a Java application (net.tinyos.util.DiagMsg)
+ * decodes the message and displays its content using the correct type
+ * information. See the implementation for the format of the message.
+ */
+interface DiagMsg
+{
+ /**
+ * Initiates the recording of a new DiagMsg. It returns FALSE if
+ * the component is busy recording or sending another message.
+ */
+ async command bool record();
+
+ /**
+ * Adds a new value to the end of the message. If the message
+ * cannot hold more information, then the new value is simply dropped.
+ */
+ async command void int8(int8_t value);
+ async command void uint8(uint8_t value);
+ async command void hex8(uint8_t value);
+ async command void int16(int16_t value);
+ async command void uint16(uint16_t value);
+ async command void hex16(uint16_t value);
+ async command void int32(int32_t value);
+ async command void int64(int64_t value);
+ async command void uint64(uint64_t value);
+ async command void uint32(uint32_t value);
+ async command void hex32(uint32_t value);
+ async command void real(float value);
+ async command void chr(char value);
+
+ /**
+ * Adds an array of values to the end of the message.
+ * The maximum length of the array is <code>15</code>.
+ * If the message cannot hold all elements of the array,
+ * then no value is stored.
+ */
+ async command void int8s(const int8_t *value, uint8_t len);
+ async command void uint8s(const uint8_t *value, uint8_t len);
+ async command void hex8s(const uint8_t *value, uint8_t len);
+ async command void int16s(const int16_t *value, uint8_t len);
+ async command void uint16s(const uint16_t *value, uint8_t len);
+ async command void hex16s(const uint16_t *value, uint8_t len);
+ async command void int32s(const int32_t *value, uint8_t len);
+ async command void uint32s(const uint32_t *value, uint8_t len);
+ async command void hex32s(const uint32_t *value, uint8_t len);
+ async command void int64s(const int64_t *value, uint8_t len);
+ async command void uint64s(const uint64_t *value, uint8_t len);
+ async command void reals(const float *value, uint8_t len);
+ async command void chrs(const char *value, uint8_t len);
+
+ /**
+ * This is a shorthand method for <code>chrs</code>
+ */
+ async command void str(const char* value);
+
+ /**
+ * Initiates the sending of the recorded message.
+ */
+ async command void send();
+}
--- /dev/null
+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.
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <message.h>
+
+module DiagMsgM
+{
+ provides
+ {
+ interface DiagMsg;
+ interface Init;
+ }
+
+ uses
+ {
+ interface AMSend;
+ interface Packet;
+ }
+}
+
+#ifndef DIAGMSG_BASE_STATION
+#define DIAGMSG_BASE_STATION AM_BROADCAST_ADDR
+#endif
+
+#ifndef DIAGMSG_RETRY_COUNT
+#define DIAGMSG_RETRY_COUNT 2
+#endif
+
+#ifndef DIAGMSG_RECORDED_MSGS
+#define DIAGMSG_RECORDED_MSGS 10
+#endif
+
+implementation
+{
+ enum
+ {
+ STATE_READY = 1,
+ STATE_RECORDING_FIRST = 2, // recording the first 4-bit descriptor
+ STATE_RECORDING_SECOND = 3, // recording the second 4-bit descriptor
+ STATE_MSG_FULL = 4,
+ STATE_BUFFER_FULL = 5,
+ };
+
+ norace volatile uint8_t state; // the state of the recording
+
+ message_t msgs[DIAGMSG_RECORDED_MSGS]; // circular buffer of messages
+
+ norace message_t *recording; // the message that is beeing or going to be recorded
+ message_t *sending; // the message that is beeing sent, or the null pointer
+
+ norace uint8_t nextData; // points to the next unsued byte
+ norace uint8_t prevType; // points to the type descriptor
+ norace uint8_t retries; // number of remaining retries
+
+ command error_t Init.init()
+ {
+ state = STATE_READY;
+ recording = msgs;
+ sending = 0;
+
+ return SUCCESS;
+ }
+
+ // two type fields are stored in on byte
+ enum
+ {
+ TYPE_END = 0,
+ TYPE_INT8 = 1,
+ TYPE_UINT8 = 2,
+ TYPE_HEX8 = 3,
+ TYPE_INT16 = 4,
+ TYPE_UINT16 = 5,
+ TYPE_HEX16 = 6,
+ TYPE_INT32 = 7,
+ TYPE_UINT32 = 8,
+ TYPE_HEX32 = 9,
+ TYPE_FLOAT = 10,
+ TYPE_CHAR = 11,
+ TYPE_INT64 = 12,
+ TYPE_UINT64 = 13,
+ TYPE_ARRAY = 15,
+ };
+
+/*
+ The format of the payload is as follows:
+
+ Each value has an associated data type descriptor. The descriptor takes 4-bits,
+ and two descriptors are packed into one byte. The double-descriptor is followed
+ by the data bytes needed to store the corresponding value. Two sample layouts are:
+
+ [D2, D1] [V1] ... [V1] [V2] ... [V2]
+ [D2, D1] [V1] ... [V1] [V2] ... [V2] [0, D3] [V3] ... [V3]
+
+ where D1, D2, D3 denotes the data type descriptors, and V1, V2 and V3
+ denotes the bytes where the corresponding values are stored. If there is an odd
+ number of data descriptors, then a zero data descriptor <code>TYPE_END</code>
+ is inserted.
+
+ Each data type (except arrays) uses a fixed number of bytes to store the value.
+ For arrays, the first byte of the array holds the data type of the array (higer
+ 4 bits) and the length of the array (lower 4 bits). The actual data follows
+ this first byte.
+*/
+
+ async command bool DiagMsg.record()
+ {
+ atomic
+ {
+ // currently recording or no more space
+ if( state != STATE_READY )
+ return FALSE;
+
+ state = STATE_RECORDING_FIRST;
+ nextData = 0;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Allocates space in the message for <code>size</code> bytes
+ * and sets the type information to <code>type</code>.
+ * Returns the index in <code>msg.data</code> where the data
+ * should be stored or <code>-1</code> if no more space is avaliable.
+ */
+ int8_t allocate(uint8_t size, uint8_t type)
+ {
+ int8_t ret = -1;
+
+ if( state == STATE_RECORDING_FIRST )
+ {
+ if( nextData + 1 + size <= TOSH_DATA_LENGTH )
+ {
+ state = STATE_RECORDING_SECOND;
+
+ prevType = nextData++;
+ ((uint8_t*) &(recording->data))[prevType] = type;
+ ret = nextData;
+ nextData += size;
+ }
+ else
+ state = STATE_MSG_FULL;
+ }
+ else if( state == STATE_RECORDING_SECOND )
+ {
+ if( nextData + size <= TOSH_DATA_LENGTH )
+ {
+ state = STATE_RECORDING_FIRST;
+
+ ((uint8_t*) &(recording->data))[prevType] += (type << 4);
+ ret = nextData;
+ nextData += size;
+ }
+ else
+ state = STATE_MSG_FULL;
+ }
+
+ return ret;
+ }
+
+#define IMPLEMENT(NAME, TYPE, TYPE2) \
+ async command void DiagMsg.NAME(TYPE value) \
+ { \
+ int8_t start = allocate(sizeof(TYPE), TYPE2); \
+ if( start >= 0 ) \
+ *(TYPE*)((uint8_t*) &(recording->data) + start) = value; \
+ } \
+ async command void DiagMsg.NAME##s(const TYPE *value, uint8_t len) \
+ { \
+ int8_t start; \
+ if( len > 15 ) len = 15; \
+ start = allocate(sizeof(TYPE)*len + 1, TYPE_ARRAY); \
+ if( start >= 0 ) \
+ { \
+ ((uint8_t*) &(recording->data))[start++] = (TYPE2 << 4) + len; \
+ while( len-- != 0 ) \
+ ((TYPE*)((uint8_t*) &(recording->data) + start))[len] = value[len]; \
+ } \
+ }
+
+ IMPLEMENT(int8, int8_t, TYPE_INT8)
+ IMPLEMENT(uint8, uint8_t, TYPE_UINT8)
+ IMPLEMENT(hex8, uint8_t, TYPE_HEX8)
+ IMPLEMENT(int16, int16_t, TYPE_INT16)
+ IMPLEMENT(uint16, uint16_t, TYPE_UINT16)
+ IMPLEMENT(hex16, uint16_t, TYPE_HEX16)
+ IMPLEMENT(int32, int32_t, TYPE_INT32)
+ IMPLEMENT(uint32, uint32_t, TYPE_UINT32)
+ IMPLEMENT(hex32, uint32_t, TYPE_HEX32)
+ IMPLEMENT(int64, int64_t, TYPE_INT64)
+ IMPLEMENT(uint64, uint64_t, TYPE_UINT64)
+ IMPLEMENT(real, float, TYPE_FLOAT)
+ IMPLEMENT(chr, char, TYPE_CHAR)
+
+ async command void DiagMsg.str(const char* str)
+ {
+ int8_t len = 0;
+ while( str[len] != 0 && len < 15 )
+ ++len;
+
+ call DiagMsg.chrs(str, len);
+ }
+
+ // TODO: this is a hack because setPayloadLength should be async
+ inline void setPayloadLength(message_t* msg, uint8_t length)
+ {
+ (*(uint8_t*) &(msg->header)) = length;
+ }
+
+ inline uint8_t getPayloadLength(message_t* msg)
+ {
+ return *(uint8_t*) &(msg->header);
+ }
+
+ task void send()
+ {
+ message_t* msg;
+
+ atomic msg = sending;
+
+ if( call AMSend.send(DIAGMSG_BASE_STATION, msg, getPayloadLength(msg)) != SUCCESS )
+ post send();
+ }
+
+ // calculates the next message_t pointer in the <code>msgs</code> circular buffer
+ static inline message_t* nextPointer(message_t* ptr)
+ {
+ if( ++ptr >= msgs + DIAGMSG_RECORDED_MSGS )
+ return msgs;
+ else
+ return ptr;
+ }
+
+ async command void DiagMsg.send()
+ {
+ // no message recorded
+ if( state == STATE_READY )
+ return;
+
+ // store the length
+ setPayloadLength(recording, nextData);
+
+ atomic
+ {
+ if( sending == 0 )
+ {
+ sending = recording;
+ retries = DIAGMSG_RETRY_COUNT;
+ post send();
+ }
+
+ recording = nextPointer(recording);
+
+ if( recording == sending )
+ state = STATE_BUFFER_FULL;
+ else
+ state = STATE_READY;
+ }
+ }
+
+ event void AMSend.sendDone(message_t* p, error_t error)
+ {
+ atomic
+ {
+ // retry if not successful
+ if( error != SUCCESS && --retries > 0 )
+ post send();
+ else
+ {
+ p = nextPointer(sending);
+ if( p != recording )
+ {
+ sending = p;
+ retries = DIAGMSG_RETRY_COUNT;
+ post send();
+ }
+ else
+ {
+ sending = 0;
+
+ if( state == STATE_BUFFER_FULL )
+ {
+ state = STATE_READY;
+ if( call DiagMsg.record() )
+ {
+ call DiagMsg.str("DiagMsgOverflow");
+ call DiagMsg.send();
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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() { }
+}
--- /dev/null
+#
+# 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;
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright (c) 2006 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#include <MicaTimer.h>
+#include <scale.h>
+
+/**
+ * Measure cpu clock frequency at boot time. Provides an Atm128Calibrate
+ * interface so that other components can adjust their calibration as
+ * needed.
+ *
+ * @author David Gay
+ * @author Janos Sallai
+ */
+
+module MeasureClockC {
+ provides {
+ /**
+ * This code MUST be called from PlatformP only, hence the exactlyonce.
+ */
+ interface Init @exactlyonce();
+ interface Atm128Calibrate;
+ }
+}
+implementation
+{
+ enum {
+ /* This is expected number of cycles per jiffy at the platform's
+ specified MHz. Assumes PLATFORM_MHZ == 1, 2, 4, 8 or 16. */
+ MAGIC = 488 / (16 / PLATFORM_MHZ)
+ };
+
+ uint16_t cycles;
+
+ command error_t Init.init() {
+ /* Measure clock cycles per Jiffy (1/32768s) */
+ /* This code doesn't use the HPL to avoid timing issues when compiling
+ with debugging on */
+ atomic
+ {
+ uint8_t now, wraps;
+ uint16_t start;
+
+ /* Setup timer2 to count 32 jiffies, and timer1 cpu cycles */
+ TCCR1B = 1 << CS10;
+ ASSR = 1 << AS2;
+ TCCR2B = 1 << CS21 | 1 << CS20;
+
+ /* Wait for 1s for counter to stablilize after power-up (yes, it
+ really does take that long). That's 122 wrap arounds of timer 1
+ at 8MHz. */
+ start = TCNT1;
+ for (wraps = MAGIC / 2; wraps; )
+ {
+ uint16_t next = TCNT1;
+
+ if (next < start)
+ wraps--;
+ start = next;
+ }
+
+ /* Wait for a TCNT0 change */
+ now = TCNT2;
+ while (TCNT2 == now) ;
+
+ /* Read cpu cycles and wait for next TCNT2 change */
+ start = TCNT1;
+ now = TCNT2;
+ while (TCNT2 == now) ;
+ cycles = TCNT1;
+
+ cycles = (cycles - start + 16) >> 5;
+
+ /* Reset to boot state */
+ ASSR = TCCR1B = TCCR2B = 0;
+ TCNT2 = 0;
+ TCNT1 = 0;
+ TIFR1 = TIFR2 = 0xff;
+ while (ASSR & (1 << TCN2UB | 1 << OCR2BUB | 1 << TCR2BUB))
+ ;
+ }
+ return SUCCESS;
+ }
+
+ async command uint16_t Atm128Calibrate.cyclesPerJiffy() {
+ return cycles;
+ }
+
+ async command uint32_t Atm128Calibrate.calibrateMicro(uint32_t n) {
+ return scale32(n + MAGIC / 2, cycles, MAGIC);
+ }
+
+ async command uint32_t Atm128Calibrate.actualMicro(uint32_t n) {
+ return scale32(n + (cycles >> 1), MAGIC, cycles);
+ }
+
+ async command uint8_t Atm128Calibrate.adcPrescaler() {
+ /* This is also log2(cycles/3.05). But that's a pain to compute */
+ if (cycles >= 390)
+ return ATM128_ADC_PRESCALE_128;
+ if (cycles >= 195)
+ return ATM128_ADC_PRESCALE_64;
+ if (cycles >= 97)
+ return ATM128_ADC_PRESCALE_32;
+ if (cycles >= 48)
+ return ATM128_ADC_PRESCALE_16;
+ if (cycles >= 24)
+ return ATM128_ADC_PRESCALE_8;
+ if (cycles >= 12)
+ return ATM128_ADC_PRESCALE_4;
+ return ATM128_ADC_PRESCALE_2;
+ }
+
+ async command uint16_t Atm128Calibrate.baudrateRegister(uint32_t baudrate) {
+ // value is (cycles*32768) / (8*baudrate) - 1
+ return ((uint32_t)cycles << 12) / baudrate - 1;
+ }
+}
--- /dev/null
+// $Id$
+/*
+ * Copyright (c) 2005-2006 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef MICATIMER_H
+#define MICATIMER_H
+
+/* This file defines the rates at which the mica family's atmega1281 timer 1
+ and 3 timers run at. The goal is to present the user with microsend and
+ 32khz timers, but it may not be possible to run the timers at these rates
+ (because of the limited prescaler selection).
+
+ So TinyOS picks a prescaler (based on the selected processor MHz) for
+ each of these timers, and builds corresponding 16-bit alarms&counters
+ (AlarmOne16C, AlarmThree16C, CounterOne16C, CounterThree16C) over
+ hardware timers 1 and 3. TinyOS then divides these hardware timers by
+ the appropriate power of 2 to get approximate 32-bit 32kHz and 1MHz
+ alarms and counters (Alarm32khz32C, AlarmMicro32C, Counter32khz32C,
+ CounterMicro32C).
+
+ The constants and typedefs for all this configuration are defined here,
+ based on the value of the MHZ preprocessor symbol, which shoud approximate
+ the platform's MHZ rate.
+
+ Note that the timers thus obtained will not be exactly at 32768Hz or
+ 1MHz, because the clock doesn't divide by a power of two to those
+ frequencies, and/or the clock frequency is not accurate. If you need
+ more accurate timing, you should use the calibration functions
+ offered by the Atm128Calibrate interface provided by PlatformC.
+
+ This file also defines EXT_STANDBY_T0_THRESHOLD, a threshold on
+ remaining time till the next timer 0 interrupt under which the mote
+ should sleep in ext standby rather than power save. This is only
+ important when not using the internal oscillator. Wake up from power
+ save takes 65536 cycles (6 cycles for ext standby), which is, e.g.,
+ ~9.4ms at 7Mhz.
+*/
+
+#include <Timer.h>
+#include <Atm128Timer.h>
+
+/* Some types for the non-standard rates that mica timers might be running
+ at.
+ */
+typedef struct { } T64khz;
+typedef struct { } T128khz;
+typedef struct { } T2mhz;
+typedef struct { } T4mhz;
+
+/* TX is the typedef for the rate of timer X,
+ MICA_PRESCALER_X is the prescaler for timer X,
+ MICA_DIVIDER_X_FOR_Y_LOG2 is the number of bits to shift timer X by
+ to get rate Y,
+ counter_X_overflow_t is uint16_t if MICA_DIVIDER_X_FOR_Y_LOG2 is 0,
+ uint32_t otherwise.
+*/
+
+#if MHZ == 1
+typedef T128khz TOne;
+typedef TMicro TThree;
+typedef uint32_t counter_one_overflow_t;
+typedef uint16_t counter_three_overflow_t;
+
+enum {
+ MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_8,
+ MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 2,
+ MICA_PRESCALER_THREE = ATM128_CLK16_NORMAL,
+ MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 0,
+ EXT_STANDBY_T0_THRESHOLD = 80,
+};
+
+#elif MHZ == 2
+typedef T32khz TOne;
+typedef T2mhz TThree;
+typedef uint16_t counter_one_overflow_t;
+typedef uint32_t counter_three_overflow_t;
+
+enum {
+ MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_64,
+ MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 0,
+ MICA_PRESCALER_THREE = ATM128_CLK16_NORMAL,
+ MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 1,
+ EXT_STANDBY_T0_THRESHOLD = 40
+};
+
+#elif MHZ == 4
+typedef T64khz TOne;
+typedef T4mhz TThree;
+typedef uint32_t counter_one_overflow_t;
+typedef uint32_t counter_three_overflow_t;
+
+enum {
+ MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_64,
+ MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 1,
+ MICA_PRESCALER_THREE = ATM128_CLK16_NORMAL,
+ MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 2,
+ EXT_STANDBY_T0_THRESHOLD = 24
+};
+
+#elif MHZ == 8
+/*
+typedef T32khz TOne;
+typedef TMicro TThree;
+typedef uint16_t counter_one_overflow_t;
+typedef uint16_t counter_three_overflow_t;
+
+enum {
+ MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_256,
+ MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 0,
+ MICA_PRESCALER_THREE = ATM128_CLK16_DIVIDE_8,
+ MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 0,
+ EXT_STANDBY_T0_THRESHOLD = 12
+};
+*/
+
+// get a 1MHz (1 microsecond resolution) timer for debugging purposes
+
+typedef TMilli TOne;
+typedef TMicro TThree;
+typedef uint32_t counter_one_overflow_t;
+typedef uint16_t counter_three_overflow_t;
+enum {
+ MICA_PRESCALER_ONE = ATM128_CLK16_DIVIDE_8,
+ MICA_DIVIDE_ONE_FOR_32KHZ_LOG2 = 5,
+ MICA_PRESCALER_THREE = ATM128_CLK16_DIVIDE_8,
+ MICA_DIVIDE_THREE_FOR_MICRO_LOG2 = 0,
+ EXT_STANDBY_T0_THRESHOLD = 12,
+};
+
+#else
+#error "Unknown clock rate. MHZ must be defined to one of 1, 2, 4, or 8."
+#endif
+
+enum {
+ PLATFORM_MHZ = MHZ
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#ifndef __HPLRF230_H__
+#define __HPLRF230_H__
+
+#include <RF230.h>
+
+enum
+{
+ /**
+ * This is the value of the TRX_CTRL_0 register
+ * which configures the output pin currents and the CLKM clock
+ */
+ RF230_TRX_CTRL_0_VALUE = 0,
+
+ /**
+ * This is the default value of the CCA_MODE field in the PHY_CC_CCA register
+ * which is used to configure the default mode of the clear channel assesment
+ */
+ RF230_CCA_MODE_VALUE = RF230_CCA_MODE_3,
+
+ /**
+ * This is the value of the CCA_THRES register that controls the
+ * energy levels used for clear channel assesment
+ */
+ RF230_CCA_THRES_VALUE = 0xC7,
+};
+
+/**
+ * This is the timer type of the RF230 alarm interface
+ */
+typedef TOne TRF230;
+
+/**
+ * The number of alarm ticks per one microsecond (0.9216)
+ */
+#define RF230_ALARM_MICROSEC ((7.3728 / MHZ / 32.0) * (1 << MICA_DIVIDE_ONE_FOR_32KHZ_LOG2))
+
+#endif//__HPLRF230_H__
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <HplRF230.h>
+
+configuration HplRF230C
+{
+ provides
+ {
+ interface GeneralIO as SELN;
+ interface Resource as SpiResource;
+ interface SpiByte;
+
+ interface GeneralIO as SLP_TR;
+ interface GeneralIO as RSTN;
+
+ interface GpioCapture as IRQ;
+ interface Alarm<TRF230, uint16_t> as Alarm;
+
+ interface HplRF230;
+ }
+}
+
+implementation
+{
+ components HplRF230P;
+ IRQ = HplRF230P.IRQ;
+
+ HplRF230P.PortCLKM -> IO.PortD6;
+ HplRF230P.PortIRQ -> IO.PortD4;
+
+ // TODO: Ask why the HplAtm128SpiC does SlaveSelect via PortB0
+ // TODO: Remove the unused started field from Atm128SpiP
+ components Atm128SpiC as SpiC;
+ SpiResource = SpiC.Resource[unique("Atm128SpiC.Resource")];
+ SpiByte = SpiC;
+
+ HplRF230 = HplRF230P;
+
+ components HplAtm128GeneralIOC as IO;
+ SLP_TR = IO.PortB7;
+ RSTN = IO.PortA6;
+ SELN = IO.PortB0;
+
+ components HplAtm128Timer1C as TimerC;
+ HplRF230P.Capture -> TimerC.Capture;
+
+ components new AlarmOne16C() as AlarmC;
+ Alarm = AlarmC;
+
+ // TODO: do these from PlatformC
+ components RealMainP, RF230LayerC;
+ RealMainP.PlatformInit -> HplRF230P.PlatformInit;
+ RealMainP.PlatformInit -> RF230LayerC.PlatformInit;
+}
--- /dev/null
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Author: Miklos Maroti
+ */
+
+#include <util/crc16.h>
+#include "Atm128Spi.h"
+
+module HplRF230P
+{
+ provides
+ {
+ interface GpioCapture as IRQ;
+ interface Init as PlatformInit;
+
+ interface HplRF230;
+ }
+
+ uses
+ {
+ interface HplAtm128Capture<uint16_t> as Capture;
+ interface GeneralIO as PortCLKM;
+ interface GeneralIO as PortIRQ;
+ }
+}
+
+implementation
+{
+ command error_t PlatformInit.init()
+ {
+ call PortCLKM.makeInput();
+ call PortCLKM.clr();
+ call PortIRQ.makeInput();
+ call PortIRQ.clr();
+ call Capture.stop();
+
+ return SUCCESS;
+ }
+
+ async event void Capture.captured(uint16_t time)
+ {
+ time = call Capture.get(); // TODO: ask Cory why time is not the captured time
+ signal IRQ.captured(time);
+ }
+
+ default async event void IRQ.captured(uint16_t time)
+ {
+ }
+
+ async command error_t IRQ.captureRisingEdge()
+ {
+ call Capture.setEdge(TRUE);
+ call Capture.reset();
+ call Capture.start();
+
+ return SUCCESS;
+ }
+
+ async command error_t IRQ.captureFallingEdge()
+ {
+ // falling edge comes when the IRQ_STATUS register of the RF230 is read
+ return FAIL;
+ }
+
+ async command void IRQ.disable()
+ {
+ call Capture.stop();
+ }
+
+ // TODO: Check why the default crcByte implementation is in a different endianness
+ inline async command uint16_t HplRF230.crcByte(uint16_t crc, uint8_t data)
+ {
+ return _crc_ccitt_update(crc, data);
+ }
+
+ inline async command void HplRF230.spiSplitWrite(uint8_t data)
+ {
+ // the SPI must have been started, so do not waste time here
+ // SET_BIT(SPCR, SPE);
+
+ SPDR = data;
+ }
+
+ inline async command uint8_t HplRF230.spiSplitRead()
+ {
+ while( !( SPSR & 0x80 ) )
+ ;
+ return SPDR;
+ }
+
+ inline async command uint8_t HplRF230.spiSplitReadWrite(uint8_t data)
+ {
+ uint8_t b;
+
+ while( !( SPSR & 0x80 ) )
+ ;
+ b = SPDR;
+ SPDR = data;
+
+ return b;
+ }
+
+ inline async command uint8_t HplRF230.spiWrite(uint8_t data)
+ {
+ // the SPI must have been started, so do not waste time here
+ // SET_BIT(SPCR, SPE);
+
+ SPDR = data;
+ while( !( SPSR & 0x80 ) )
+ ;
+
+ return SPDR;
+ }
+}
--- /dev/null
+/* $Id$
+ * "Copyright (c) 2005 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2005 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * Copyright (c) 2007, Vanderbilt University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+/**
+ * Defining the platform-independently named packet structures to be the
+ * chip-specific CC1000 packet structures.
+ *
+ * @author Philip Levis
+ * @date May 16 2005
+ * Revision: $Revision$
+ */
+
+
+#ifndef PLATFORM_MESSAGE_H
+#define PLATFORM_MESSAGE_H
+
+#include <DefaultMac.h>
+#include <Serial.h>
+
+typedef union message_header {
+ defaultmac_header_t rf230;
+ serial_header_t serial;
+} message_header_t;
+
+typedef union message_footer {
+} message_footer_t;
+
+typedef union message_metadata {
+ defaultmac_metadata_t rf230;
+} message_metadata_t;
+
+#endif
--- /dev/null
+#
+# 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;
+