diff --git a/cpu/avr/radio/rf230bb/Makefile.rf230bb b/cpu/avr/radio/rf230bb/Makefile.rf230bb new file mode 100644 index 000000000..3794c3b47 --- /dev/null +++ b/cpu/avr/radio/rf230bb/Makefile.rf230bb @@ -0,0 +1,6 @@ + +CONTIKI_TARGET_SOURCEFILES += rf230bb.c halbb.c +# timer.c + +APPDIRS += $(CONTIKI)/cpu/avr/radio/rf230bb + diff --git a/cpu/avr/radio/rf230bb/at86rf230_registermap.h b/cpu/avr/radio/rf230bb/at86rf230_registermap.h new file mode 100644 index 000000000..94e4e1769 --- /dev/null +++ b/cpu/avr/radio/rf230bb/at86rf230_registermap.h @@ -0,0 +1,351 @@ +/** + * @file + * @brief This file contains the register definitions for the AT86RF230. + * $Id: at86rf230_registermap.h,v 1.1 2009/07/08 16:17:07 dak664 Exp $ + */ +/* Copyright (c) 2008, Swedish Institute of Computer Science + All rights reserved. + + Additional fixes for AVR contributed by: + + Colin O'Flynn coflynn@newae.com + Eric Gnoske egnoske@gmail.com + Blake Leverett bleverett@gmail.com + Mike Vidales mavida404@gmail.com + Kevin Brown kbrown3@uccs.edu + Nate Bohlmann nate@elfwerks.com + + 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 copyright holders nor the names of + 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 COPYRIGHT OWNER OR 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. +*/ + +#ifndef PHY230_REGISTERMAP_EXTERNAL_H +#define PHY230_REGISTERMAP_EXTERNAL_H + +#define HAVE_REGISTER_MAP (1) +/** Offset for register TRX_STATUS */ +#define RG_TRX_STATUS (0x01) +/** Access parameters for sub-register CCA_DONE in register @ref RG_TRX_STATUS */ +#define SR_CCA_DONE 0x01, 0x80, 7 +/** Access parameters for sub-register CCA_STATUS in register @ref RG_TRX_STATUS */ +#define SR_CCA_STATUS 0x01, 0x40, 6 +#define SR_reserved_01_3 0x01, 0x20, 5 +/** Access parameters for sub-register TRX_STATUS in register @ref RG_TRX_STATUS */ +#define SR_TRX_STATUS 0x01, 0x1f, 0 +/** Constant P_ON for sub-register @ref SR_TRX_STATUS */ +#define P_ON (0) +/** Constant BUSY_RX for sub-register @ref SR_TRX_STATUS */ +#define BUSY_RX (1) +/** Constant BUSY_TX for sub-register @ref SR_TRX_STATUS */ +#define BUSY_TX (2) +/** Constant RX_ON for sub-register @ref SR_TRX_STATUS */ +#define RX_ON (6) +/** Constant TRX_OFF for sub-register @ref SR_TRX_STATUS */ +#define TRX_OFF (8) +/** Constant PLL_ON for sub-register @ref SR_TRX_STATUS */ +#define PLL_ON (9) +/** Constant SLEEP for sub-register @ref SR_TRX_STATUS */ +#define SLEEP (15) +/** Constant BUSY_RX_AACK for sub-register @ref SR_TRX_STATUS */ +#define BUSY_RX_AACK (17) +/** Constant BUSY_TX_ARET for sub-register @ref SR_TRX_STATUS */ +#define BUSY_TX_ARET (18) +/** Constant RX_AACK_ON for sub-register @ref SR_TRX_STATUS */ +#define RX_AACK_ON (22) +/** Constant TX_ARET_ON for sub-register @ref SR_TRX_STATUS */ +#define TX_ARET_ON (25) +/** Constant RX_ON_NOCLK for sub-register @ref SR_TRX_STATUS */ +#define RX_ON_NOCLK (28) +/** Constant RX_AACK_ON_NOCLK for sub-register @ref SR_TRX_STATUS */ +#define RX_AACK_ON_NOCLK (29) +/** Constant BUSY_RX_AACK_NOCLK for sub-register @ref SR_TRX_STATUS */ +#define BUSY_RX_AACK_NOCLK (30) +/** Offset for register TRX_STATE */ +#define RG_TRX_STATE (0x02) +/** Access parameters for sub-register TRAC_STATUS in register @ref RG_TRX_STATE */ +#define SR_TRAC_STATUS 0x02, 0xe0, 5 +/** Access parameters for sub-register TRX_CMD in register @ref RG_TRX_STATE */ +#define SR_TRX_CMD 0x02, 0x1f, 0 +/** Constant CMD_NOP for sub-register @ref SR_TRX_CMD */ +#define CMD_NOP (0) +/** Constant CMD_TX_START for sub-register @ref SR_TRX_CMD */ +#define CMD_TX_START (2) +/** Constant CMD_FORCE_TRX_OFF for sub-register @ref SR_TRX_CMD */ +#define CMD_FORCE_TRX_OFF (3) +/** Constant CMD_RX_ON for sub-register @ref SR_TRX_CMD */ +#define CMD_RX_ON (6) +/** Constant CMD_TRX_OFF for sub-register @ref SR_TRX_CMD */ +#define CMD_TRX_OFF (8) +/** Constant CMD_PLL_ON for sub-register @ref SR_TRX_CMD */ +#define CMD_PLL_ON (9) +/** Constant CMD_RX_AACK_ON for sub-register @ref SR_TRX_CMD */ +#define CMD_RX_AACK_ON (22) +/** Constant CMD_TX_ARET_ON for sub-register @ref SR_TRX_CMD */ +#define CMD_TX_ARET_ON (25) +/** Offset for register TRX_CTRL_0 */ +#define RG_TRX_CTRL_0 (0x03) +/** Offset for register TRX_CTRL_1 */ +#define RG_TRX_CTRL_1 (0x04) +/** Access parameters for sub-register PAD_IO in register @ref RG_TRX_CTRL_0 */ +#define SR_PAD_IO 0x03, 0xc0, 6 +/** Access parameters for sub-register PAD_IO_CLKM in register @ref RG_TRX_CTRL_0 */ +#define SR_PAD_IO_CLKM 0x03, 0x30, 4 +/** Constant CLKM_2mA for sub-register @ref SR_PAD_IO_CLKM */ +#define CLKM_2mA (0) +/** Constant CLKM_4mA for sub-register @ref SR_PAD_IO_CLKM */ +#define CLKM_4mA (1) +/** Constant CLKM_6mA for sub-register @ref SR_PAD_IO_CLKM */ +#define CLKM_6mA (2) +/** Constant CLKM_8mA for sub-register @ref SR_PAD_IO_CLKM */ +#define CLKM_8mA (3) +/** Access parameters for sub-register CLKM_SHA_SEL in register @ref RG_TRX_CTRL_0 */ +#define SR_CLKM_SHA_SEL 0x03, 0x08, 3 +/** Access parameters for sub-register CLKM_CTRL in register @ref RG_TRX_CTRL_0 */ +#define SR_CLKM_CTRL 0x03, 0x07, 0 +/** Constant CLKM_no_clock for sub-register @ref SR_CLKM_CTRL */ +#define CLKM_no_clock (0) +/** Constant CLKM_1MHz for sub-register @ref SR_CLKM_CTRL */ +#define CLKM_1MHz (1) +/** Constant CLKM_2MHz for sub-register @ref SR_CLKM_CTRL */ +#define CLKM_2MHz (2) +/** Constant CLKM_4MHz for sub-register @ref SR_CLKM_CTRL */ +#define CLKM_4MHz (3) +/** Constant CLKM_8MHz for sub-register @ref SR_CLKM_CTRL */ +#define CLKM_8MHz (4) +/** Constant CLKM_16MHz for sub-register @ref SR_CLKM_CTRL */ +#define CLKM_16MHz (5) +/** Offset for register PHY_TX_PWR */ +#define RG_PHY_TX_PWR (0x05) +/** Access parameters for sub-register TX_AUTO_CRC_ON in register @ref RG_PHY_TX_PWR */ +#define SR_TX_AUTO_CRC_ON 0x05, 0x80, 7 +#define SR_reserved_05_2 0x05, 0x70, 4 +/** Access parameters for sub-register TX_PWR in register @ref RG_PHY_TX_PWR */ +#define SR_TX_PWR 0x05, 0x0f, 0 +/** Offset for register PHY_RSSI */ +#define RG_PHY_RSSI (0x06) +#define SR_reserved_06_1 0x06, 0xe0, 5 +/** Access parameters for sub-register RSSI in register @ref RG_PHY_RSSI */ +#define SR_RSSI 0x06, 0x1f, 0 +/** Offset for register PHY_ED_LEVEL */ +#define RG_PHY_ED_LEVEL (0x07) +/** Access parameters for sub-register ED_LEVEL in register @ref RG_PHY_ED_LEVEL */ +#define SR_ED_LEVEL 0x07, 0xff, 0 +/** Offset for register PHY_CC_CCA */ +#define RG_PHY_CC_CCA (0x08) +/** Access parameters for sub-register CCA_REQUEST in register @ref RG_PHY_CC_CCA */ +#define SR_CCA_REQUEST 0x08, 0x80, 7 +/** Access parameters for sub-register CCA_MODE in register @ref RG_PHY_CC_CCA */ +#define SR_CCA_MODE 0x08, 0x60, 5 +/** Access parameters for sub-register CHANNEL in register @ref RG_PHY_CC_CCA */ +#define SR_CHANNEL 0x08, 0x1f, 0 +/** Offset for register CCA_THRES */ +#define RG_CCA_THRES (0x09) +/** Access parameters for sub-register CCA_CS_THRES in register @ref RG_CCA_THRES */ +#define SR_CCA_CS_THRES 0x09, 0xf0, 4 +/** Access parameters for sub-register CCA_ED_THRES in register @ref RG_CCA_THRES */ +#define SR_CCA_ED_THRES 0x09, 0x0f, 0 +/** Offset for register IRQ_MASK */ +#define RG_IRQ_MASK (0x0e) +/** Access parameters for sub-register IRQ_MASK in register @ref RG_IRQ_MASK */ +#define SR_IRQ_MASK 0x0e, 0xff, 0 +/** Offset for register IRQ_STATUS */ +#define RG_IRQ_STATUS (0x0f) +/** Access parameters for sub-register IRQ_7_BAT_LOW in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_7_BAT_LOW 0x0f, 0x80, 7 +/** Access parameters for sub-register IRQ_6_TRX_UR in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_6_TRX_UR 0x0f, 0x40, 6 +/** Access parameters for sub-register IRQ_5 in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_5 0x0f, 0x20, 5 +/** Access parameters for sub-register IRQ_4 in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_4 0x0f, 0x10, 4 +/** Access parameters for sub-register IRQ_3_TRX_END in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_3_TRX_END 0x0f, 0x08, 3 +/** Access parameters for sub-register IRQ_2_RX_START in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_2_RX_START 0x0f, 0x04, 2 +/** Access parameters for sub-register IRQ_1_PLL_UNLOCK in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_1_PLL_UNLOCK 0x0f, 0x02, 1 +/** Access parameters for sub-register IRQ_0_PLL_LOCK in register @ref RG_IRQ_STATUS */ +#define SR_IRQ_0_PLL_LOCK 0x0f, 0x01, 0 +/** Offset for register VREG_CTRL */ +#define RG_VREG_CTRL (0x10) +/** Access parameters for sub-register AVREG_EXT in register @ref RG_VREG_CTRL */ +#define SR_AVREG_EXT 0x10, 0x80, 7 +/** Access parameters for sub-register AVDD_OK in register @ref RG_VREG_CTRL */ +#define SR_AVDD_OK 0x10, 0x40, 6 +/** Access parameters for sub-register AVREG_TRIM in register @ref RG_VREG_CTRL */ +#define SR_AVREG_TRIM 0x10, 0x30, 4 +/** Constant AVREG_1_80V for sub-register @ref SR_AVREG_TRIM */ +#define AVREG_1_80V (0) +/** Constant AVREG_1_75V for sub-register @ref SR_AVREG_TRIM */ +#define AVREG_1_75V (1) +/** Constant AVREG_1_84V for sub-register @ref SR_AVREG_TRIM */ +#define AVREG_1_84V (2) +/** Constant AVREG_1_88V for sub-register @ref SR_AVREG_TRIM */ +#define AVREG_1_88V (3) +/** Access parameters for sub-register DVREG_EXT in register @ref RG_VREG_CTRL */ +#define SR_DVREG_EXT 0x10, 0x08, 3 +/** Access parameters for sub-register DVDD_OK in register @ref RG_VREG_CTRL */ +#define SR_DVDD_OK 0x10, 0x04, 2 +/** Access parameters for sub-register DVREG_TRIM in register @ref RG_VREG_CTRL */ +#define SR_DVREG_TRIM 0x10, 0x03, 0 +/** Constant DVREG_1_80V for sub-register @ref SR_DVREG_TRIM */ +#define DVREG_1_80V (0) +/** Constant DVREG_1_75V for sub-register @ref SR_DVREG_TRIM */ +#define DVREG_1_75V (1) +/** Constant DVREG_1_84V for sub-register @ref SR_DVREG_TRIM */ +#define DVREG_1_84V (2) +/** Constant DVREG_1_88V for sub-register @ref SR_DVREG_TRIM */ +#define DVREG_1_88V (3) +/** Offset for register BATMON */ +#define RG_BATMON (0x11) +#define SR_reserved_11_1 0x11, 0xc0, 6 +/** Access parameters for sub-register BATMON_OK in register @ref RG_BATMON */ +#define SR_BATMON_OK 0x11, 0x20, 5 +/** Access parameters for sub-register BATMON_HR in register @ref RG_BATMON */ +#define SR_BATMON_HR 0x11, 0x10, 4 +/** Access parameters for sub-register BATMON_VTH in register @ref RG_BATMON */ +#define SR_BATMON_VTH 0x11, 0x0f, 0 +/** Offset for register XOSC_CTRL */ +#define RG_XOSC_CTRL (0x12) +/** Offset for register RX_SYN */ +#define RG_RX_SYN 0x15 +/** Offset for register XAH_CTRL_1 */ +#define RG_XAH_CTRL_1 0x17 +/** Access parameters for sub-register XTAL_MODE in register @ref RG_XOSC_CTRL */ +#define SR_XTAL_MODE 0x12, 0xf0, 4 +/** Access parameters for sub-register XTAL_TRIM in register @ref RG_XOSC_CTRL */ +#define SR_XTAL_TRIM 0x12, 0x0f, 0 +/** Offset for register FTN_CTRL */ +#define RG_FTN_CTRL (0x18) +/** Access parameters for sub-register FTN_START in register @ref RG_FTN_CTRL */ +#define SR_FTN_START 0x18, 0x80, 7 +#define SR_reserved_18_2 0x18, 0x40, 6 +/** Access parameters for sub-register FTNV in register @ref RG_FTN_CTRL */ +#define SR_FTNV 0x18, 0x3f, 0 +/** Offset for register PLL_CF */ +#define RG_PLL_CF (0x1a) +/** Access parameters for sub-register PLL_CF_START in register @ref RG_PLL_CF */ +#define SR_PLL_CF_START 0x1a, 0x80, 7 +#define SR_reserved_1a_2 0x1a, 0x70, 4 +/** Access parameters for sub-register PLL_CF in register @ref RG_PLL_CF */ +#define SR_PLL_CF 0x1a, 0x0f, 0 +/** Offset for register PLL_DCU */ +#define RG_PLL_DCU (0x1b) +/** Access parameters for sub-register PLL_DCU_START in register @ref RG_PLL_DCU */ +#define SR_PLL_DCU_START 0x1b, 0x80, 7 +#define SR_reserved_1b_2 0x1b, 0x40, 6 +/** Access parameters for sub-register PLL_DCUW in register @ref RG_PLL_DCU */ +#define SR_PLL_DCUW 0x1b, 0x3f, 0 +/** Offset for register PART_NUM */ +#define RG_PART_NUM (0x1c) +/** Access parameters for sub-register PART_NUM in register @ref RG_PART_NUM */ +#define SR_PART_NUM 0x1c, 0xff, 0 +/** Constant RF230 for sub-register @ref SR_PART_NUM */ +#define RF230 (2) +/** Offset for register VERSION_NUM */ +#define RG_VERSION_NUM (0x1d) +/** Access parameters for sub-register VERSION_NUM in register @ref RG_VERSION_NUM */ +#define SR_VERSION_NUM 0x1d, 0xff, 0 +/** Offset for register MAN_ID_0 */ +#define RG_MAN_ID_0 (0x1e) +/** Access parameters for sub-register MAN_ID_0 in register @ref RG_MAN_ID_0 */ +#define SR_MAN_ID_0 0x1e, 0xff, 0 +/** Offset for register MAN_ID_1 */ +#define RG_MAN_ID_1 (0x1f) +/** Access parameters for sub-register MAN_ID_1 in register @ref RG_MAN_ID_1 */ +#define SR_MAN_ID_1 0x1f, 0xff, 0 +/** Offset for register SHORT_ADDR_0 */ +#define RG_SHORT_ADDR_0 (0x20) +/** Access parameters for sub-register SHORT_ADDR_0 in register @ref RG_SHORT_ADDR_0 */ +#define SR_SHORT_ADDR_0 0x20, 0xff, 0 +/** Offset for register SHORT_ADDR_1 */ +#define RG_SHORT_ADDR_1 (0x21) +/** Access parameters for sub-register SHORT_ADDR_1 in register @ref RG_SHORT_ADDR_1 */ +#define SR_SHORT_ADDR_1 0x21, 0xff, 0 +/** Offset for register PAN_ID_0 */ +#define RG_PAN_ID_0 (0x22) +/** Access parameters for sub-register PAN_ID_0 in register @ref RG_PAN_ID_0 */ +#define SR_PAN_ID_0 0x22, 0xff, 0 +/** Offset for register PAN_ID_1 */ +#define RG_PAN_ID_1 (0x23) +/** Access parameters for sub-register PAN_ID_1 in register @ref RG_PAN_ID_1 */ +#define SR_PAN_ID_1 0x23, 0xff, 0 +/** Offset for register IEEE_ADDR_0 */ +#define RG_IEEE_ADDR_0 (0x24) +/** Access parameters for sub-register IEEE_ADDR_0 in register @ref RG_IEEE_ADDR_0 */ +#define SR_IEEE_ADDR_0 0x24, 0xff, 0 +/** Offset for register IEEE_ADDR_1 */ +#define RG_IEEE_ADDR_1 (0x25) +/** Access parameters for sub-register IEEE_ADDR_1 in register @ref RG_IEEE_ADDR_1 */ +#define SR_IEEE_ADDR_1 0x25, 0xff, 0 +/** Offset for register IEEE_ADDR_2 */ +#define RG_IEEE_ADDR_2 (0x26) +/** Access parameters for sub-register IEEE_ADDR_2 in register @ref RG_IEEE_ADDR_2 */ +#define SR_IEEE_ADDR_2 0x26, 0xff, 0 +/** Offset for register IEEE_ADDR_3 */ +#define RG_IEEE_ADDR_3 (0x27) +/** Access parameters for sub-register IEEE_ADDR_3 in register @ref RG_IEEE_ADDR_3 */ +#define SR_IEEE_ADDR_3 0x27, 0xff, 0 +/** Offset for register IEEE_ADDR_4 */ +#define RG_IEEE_ADDR_4 (0x28) +/** Access parameters for sub-register IEEE_ADDR_4 in register @ref RG_IEEE_ADDR_4 */ +#define SR_IEEE_ADDR_4 0x28, 0xff, 0 +/** Offset for register IEEE_ADDR_5 */ +#define RG_IEEE_ADDR_5 (0x29) +/** Access parameters for sub-register IEEE_ADDR_5 in register @ref RG_IEEE_ADDR_5 */ +#define SR_IEEE_ADDR_5 0x29, 0xff, 0 +/** Offset for register IEEE_ADDR_6 */ +#define RG_IEEE_ADDR_6 (0x2a) +/** Access parameters for sub-register IEEE_ADDR_6 in register @ref RG_IEEE_ADDR_6 */ +#define SR_IEEE_ADDR_6 0x2a, 0xff, 0 +/** Offset for register IEEE_ADDR_7 */ +#define RG_IEEE_ADDR_7 (0x2b) +/** Access parameters for sub-register IEEE_ADDR_7 in register @ref RG_IEEE_ADDR_7 */ +#define SR_IEEE_ADDR_7 0x2b, 0xff, 0 +/** Offset for register XAH_CTRL */ +#define RG_XAH_CTRL_0 (0x2c) +/** Access parameters for sub-register MAX_FRAME_RETRIES in register @ref RG_XAH_CTRL_0 */ +#define SR_MAX_FRAME_RETRIES 0x2c, 0xf0, 4 +/** Access parameters for sub-register MAX_CSMA_RETRIES in register @ref RG_XAH_CTRL_0 */ +#define SR_MAX_CSMA_RETRIES 0x2c, 0x0e, 1 +#define SR_reserved_2c_3 0x2c, 0x01, 0 +/** Offset for register CSMA_SEED_0 */ +#define RG_CSMA_SEED_0 (0x2d) +/** Access parameters for sub-register CSMA_SEED_0 in register @ref RG_CSMA_SEED_0 */ +#define SR_CSMA_SEED_0 0x2d, 0xff, 0 +/** Offset for register CSMA_SEED_1 */ +#define RG_CSMA_SEED_1 (0x2e) +/** Offset for register CSMA_BE */ +#define RG_CSMA_BE 0x2f +/** Access parameters for sub-register MIN_BE in register @ref RG_CSMA_SEED_1 */ +#define SR_MIN_BE 0x2e, 0xc0, 6 +#define SR_reserved_2e_2 0x2e, 0x30, 4 +/** Access parameters for sub-register I_AM_COORD in register @ref RG_CSMA_SEED_1 */ +#define SR_I_AM_COORD 0x2e, 0x08, 3 +/** Access parameters for sub-register CSMA_SEED_1 in register @ref RG_CSMA_SEED_1 */ +#define SR_CSMA_SEED_1 0x2e, 0x07, 0 +#endif /* PHY230_REGISTERMAP_EXTERNAL_H */ diff --git a/cpu/avr/radio/rf230bb/hal.h b/cpu/avr/radio/rf230bb/hal.h new file mode 100644 index 000000000..582e9fe9d --- /dev/null +++ b/cpu/avr/radio/rf230bb/hal.h @@ -0,0 +1,374 @@ +/* Copyright (c) 2008, Swedish Institute of Computer Science + * All rights reserved. + * + * Additional fixes for AVR contributed by: + * + * Colin O'Flynn coflynn@newae.com + * Eric Gnoske egnoske@gmail.com + * Blake Leverett bleverett@gmail.com + * Mike Vidales mavida404@gmail.com + * Kevin Brown kbrown3@uccs.edu + * Nate Bohlmann nate@elfwerks.com + * + * 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 copyright holders nor the names of + * 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 COPYRIGHT OWNER OR 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. + */ + +/** + * \addtogroup hal + * @{ + */ + +/** + * \file + * \brief This file contains low-level radio driver code. + * + * $Id: hal.h,v 1.1 2009/07/08 16:17:07 dak664 Exp $ +*/ + +#ifndef HAL_AVR_H +#define HAL_AVR_H +/*============================ INCLUDE =======================================*/ +#include +#include +#include +#include +#include +#include "contiki-conf.h" +/*============================ MACROS ========================================*/ + +// TEST CODE +#define TRIG1 DDRB |= 0x04, PINB |= 0x04 +#define TRIG2 DDRD |= 0x80, PIND |= 0x80 + +/** \name This is the list of pin configurations needed for a given platform. + * \brief Change these values to port to other platforms. + * \{ + */ +/* Define all possible revisions here */ +// RAVEN_D : Raven kit with LCD display +// RAVENUSB_C : used for USB key or Raven card +// RCB_B : RZ200 kit from Atmel based on 1281V +// ZIGBIT : Zigbit module from Meshnetics +#define RAVEN_D 0 +#define RAVENUSB_C 1 +#define RCB_B 2 +#define ZIGBIT 3 + + + + +#if RCB_REVISION == RCB_B +/* 1281 rcb */ +# define SSPORT B +# define SSPIN (0x00) +# define SPIPORT B +# define MOSIPIN (0x02) +# define MISOPIN (0x03) +# define SCKPIN (0x01) +# define RSTPORT B +# define RSTPIN (0x05) +# define IRQPORT D +# define IRQPIN (0x04) +# define SLPTRPORT B +# define SLPTRPIN (0x04) +# define USART 1 +# define USARTVECT USART1_RX_vect +# define TICKTIMER 3 +# define HAS_SPARE_TIMER + +#elif HARWARE_REVISION == ZIGBIT +/* 1281V Zigbit */ +# define SSPORT B +# define SSPIN (0x00) +# define SPIPORT B +# define MOSIPIN (0x02) +# define MISOPIN (0x03) +# define SCKPIN (0x01) +# define RSTPORT A +# define RSTPIN (0x07) +# define IRQPORT E +# define IRQPIN (0x05) +# define SLPTRPORT B +# define SLPTRPIN (0x04) +# define TXCWPORT B +# define TXCWPIN (0x07) +# define USART 1 +# define USARTVECT USART1_RX_vect +//# define TICKTIMER 3 +//# define HAS_SPARE_TIMER // Not used + + +#elif RAVEN_REVISION == RAVEN_D +/* 1284 raven */ +# define SSPORT B +# define SSPIN (0x04) +# define SPIPORT B +# define MOSIPIN (0x05) +# define MISOPIN (0x06) +# define SCKPIN (0x07) +# define RSTPORT B +# define RSTPIN (0x01) +# define IRQPORT D +# define IRQPIN (0x06) +# define SLPTRPORT B +# define SLPTRPIN (0x03) +# define TXCWPORT B +# define TXCWPIN (0x00) +# define USART 1 +# define USARTVECT USART1_RX_vect +# define TICKTIMER 3 +# define HAS_CW_MODE +# define HAS_SPARE_TIMER + +#elif RAVEN_REVISION == RAVENUSB_C +/* 1287USB raven */ +# define SSPORT B +# define SSPIN (0x00) +# define SPIPORT B +# define MOSIPIN (0x02) +# define MISOPIN (0x03) +# define SCKPIN (0x01) +# define RSTPORT B +# define RSTPIN (0x05) +# define IRQPORT D +# define IRQPIN (0x04) +# define SLPTRPORT B +# define SLPTRPIN (0x04) +# define TXCWPORT B +# define TXCWPIN (0x07) +# define USART 1 +# define USARTVECT USART1_RX_vect +# define TICKTIMER 3 +# define HAS_CW_MODE +# define HAS_SPARE_TIMER + +#else + +#error "Platform undefined in hal.h" + +#endif + +/** \} */ + +/** + * \name Macros used to generate read register names from platform-specific definitions of ports. + * \brief The various CAT macros (DDR, PORT, and PIN) are used to + * assign port/pin/DDR names to various macro variables. The + * variables are assigned based on the specific connections made in + * the hardware. For example TCCR(TICKTIMER,A) can be used in place of TCCR0A + * if TICKTIMER is defined as 0. + * \{ + */ +#define CAT(x, y) x##y +#define CAT2(x, y, z) x##y##z +#define DDR(x) CAT(DDR, x) +#define PORT(x) CAT(PORT, x) +#define PIN(x) CAT(PIN, x) +#define UCSR(num, let) CAT2(UCSR,num,let) +#define RXEN(x) CAT(RXEN,x) +#define TXEN(x) CAT(TXEN,x) +#define TXC(x) CAT(TXC,x) +#define RXC(x) CAT(RXC,x) +#define RXCIE(x) CAT(RXCIE,x) +#define UCSZ(x,y) CAT2(UCSZ,x,y) +#define UBRR(x,y) CAT2(UBRR,x,y) +#define UDRE(x) CAT(UDRE,x) +#define UDRIE(x) CAT(UDRIE,x) +#define UDR(x) CAT(UDR,x) +#define TCNT(x) CAT(TCNT,x) +#define TIMSK(x) CAT(TIMSK,x) +#define TCCR(x,y) CAT2(TCCR,x,y) +#define COM(x,y) CAT2(COM,x,y) +#define OCR(x,y) CAT2(OCR,x,y) +#define CS(x,y) CAT2(CS,x,y) +#define WGM(x,y) CAT2(WGM,x,y) +#define OCIE(x,y) CAT2(OCIE,x,y) +#define COMPVECT(x) CAT2(TIMER,x,_COMPA_vect) +#define UDREVECT(x) CAT2(USART,x,_UDRE_vect) +#define RXVECT(x) CAT2(USART,x,_RX_vect) +/** \} */ + +/** + * \name Pin macros + * \brief These macros convert the platform-specific pin defines into names and functions + * that the source code can directly use. + * \{ + */ +#define SLP_TR SLPTRPIN /**< Pin number that corresponds to the SLP_TR pin. */ +#define DDR_SLP_TR DDR( SLPTRPORT ) /**< Data Direction Register that corresponds to the port where SLP_TR is connected. */ +#define PORT_SLP_TR PORT( SLPTRPORT ) /**< Port (Write Access) where SLP_TR is connected. */ +#define PIN_SLP_TR PIN( SLPTRPORT ) /**< Pin (Read Access) where SLP_TR is connected. */ +#define hal_set_slptr_high( ) ( PORT_SLP_TR |= ( 1 << SLP_TR ) ) /**< This macro pulls the SLP_TR pin high. */ +#define hal_set_slptr_low( ) ( PORT_SLP_TR &= ~( 1 << SLP_TR ) ) /**< This macro pulls the SLP_TR pin low. */ +#define hal_get_slptr( ) ( ( PIN_SLP_TR & ( 1 << SLP_TR ) ) >> SLP_TR ) /**< Read current state of the SLP_TR pin (High/Low). */ +#define RST RSTPIN /**< Pin number that corresponds to the RST pin. */ +#define DDR_RST DDR( RSTPORT ) /**< Data Direction Register that corresponds to the port where RST is */ +#define PORT_RST PORT( RSTPORT ) /**< Port (Write Access) where RST is connected. */ +#define PIN_RST PIN( RSTPORT ) /**< Pin (Read Access) where RST is connected. */ +#define hal_set_rst_high( ) ( PORT_RST |= ( 1 << RST ) ) /**< This macro pulls the RST pin high. */ +#define hal_set_rst_low( ) ( PORT_RST &= ~( 1 << RST ) ) /**< This macro pulls the RST pin low. */ +#define hal_get_rst( ) ( ( PIN_RST & ( 1 << RST ) ) >> RST ) /**< Read current state of the RST pin (High/Low). */ +#define HAL_SS_PIN SSPIN /**< The slave select pin. */ +#define HAL_PORT_SPI PORT( SPIPORT ) /**< The SPI module is located on PORTB. */ +#define HAL_DDR_SPI DDR( SPIPORT ) /**< Data Direction Register for PORTB. */ +#define HAL_DD_SS SSPIN /**< Data Direction bit for SS. */ +#define HAL_DD_SCK SCKPIN /**< Data Direction bit for SCK. */ +#define HAL_DD_MOSI MOSIPIN /**< Data Direction bit for MOSI. */ +#define HAL_DD_MISO MISOPIN /**< Data Direction bit for MISO. */ +/** \} */ + + +#define HAL_SS_HIGH( ) (HAL_PORT_SPI |= ( 1 << HAL_SS_PIN )) /**< MACRO for pulling SS high. */ +#define HAL_SS_LOW( ) (HAL_PORT_SPI &= ~( 1 << HAL_SS_PIN )) /**< MACRO for pulling SS low. */ + +/** \brief Macros defined for HAL_TIMER1. + * + * These macros are used to define the correct setupt of the AVR's Timer1, and + * to ensure that the hal_get_system_time function returns the system time in + * symbols (16 us ticks). + */ + +#if ( F_CPU == 16000000UL ) + #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS12 ) ) + #define HAL_US_PER_SYMBOL ( 1 ) + #define HAL_SYMBOL_MASK ( 0xFFFFffff ) +#elif ( F_CPU == 8000000UL ) + #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS11 ) | ( 1 << CS10 ) ) + #define HAL_US_PER_SYMBOL ( 2 ) + #define HAL_SYMBOL_MASK ( 0x7FFFffff ) +#elif ( F_CPU == 4000000UL ) + #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS11 ) | ( 1 << CS10 ) ) + #define HAL_US_PER_SYMBOL ( 1 ) + #define HAL_SYMBOL_MASK ( 0xFFFFffff ) +#elif ( F_CPU == 1000000UL ) + #define HAL_TCCR1B_CONFIG ( ( 1 << ICES1 ) | ( 1 << CS11 ) ) + #define HAL_US_PER_SYMBOL ( 2 ) + #define HAL_SYMBOL_MASK ( 0x7FFFffff ) +#else + #error "Clock speed not supported." +#endif + +#if HARWARE_REVISION == ZIGBIT +// IRQ E5 for Zigbit example +#define RADIO_VECT INT5_vect +#define HAL_ENABLE_RADIO_INTERRUPT( ) { ( EIMSK |= ( 1 << INT5 ) ) ; EICRB |= 0x0C ; PORTE &= ~(1< + +#include "hal.h" +#include "at86rf230_registermap.h" +/*============================ MACROS ========================================*/ + +/* + * Macros defined for the radio transceiver's access modes. + * + * These functions are implemented as macros since they are used very often. + */ +#define HAL_DUMMY_READ (0x00) /**< Dummy value for the SPI. */ + +#define HAL_TRX_CMD_RW (0xC0) /**< Register Write (short mode). */ +#define HAL_TRX_CMD_RR (0x80) /**< Register Read (short mode). */ +#define HAL_TRX_CMD_FW (0x60) /**< Frame Transmit Mode (long mode). */ +#define HAL_TRX_CMD_FR (0x20) /**< Frame Receive Mode (long mode). */ +#define HAL_TRX_CMD_SW (0x40) /**< SRAM Write. */ +#define HAL_TRX_CMD_SR (0x00) /**< SRAM Read. */ +#define HAL_TRX_CMD_RADDRM (0x7F) /**< Register Address Mask. */ + +#define HAL_CALCULATED_CRC_OK (0) /**< CRC calculated over the frame including the CRC field should be 0. */ +/*============================ TYPDEFS =======================================*/ +/*============================ VARIABLES =====================================*/ +/** \brief This is a file internal variable that contains the 16 MSB of the + * system time. + * + * The system time (32-bit) is the current time in microseconds. For the + * AVR microcontroller implementation this is solved by using a 16-bit + * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is + * incremented when the 16-bit timer overflows, representing the 16 MSB. + * The timer value it self (TCNT1) is then the 16 LSB. + * + * \see hal_get_system_time + */ +static uint16_t hal_system_time = 0; + +/*Flag section.*/ +//static uint8_t volatile hal_bat_low_flag; /**< BAT_LOW flag. */ +//static uint8_t volatile hal_pll_lock_flag; /**< PLL_LOCK flag. */ + +/*Callbacks.*/ + +/** \brief This function is called when a rx_start interrupt is signaled. + * + * If this function pointer is set to something else than NULL, it will + * be called when a RX_START event is signaled. The function takes two + * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and + * frame length. The event handler will be called in the interrupt domain, + * so the function must be kept short and not be blocking! Otherwise the + * system performance will be greatly degraded. + * + * \see hal_set_rx_start_event_handler + */ +//static hal_rx_start_isr_event_handler_t rx_start_callback; + +/** \brief This function is called when a trx_end interrupt is signaled. + * + * If this function pointer is set to something else than NULL, it will + * be called when a TRX_END event is signaled. The function takes one + * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution). + * The event handler will be called in the interrupt domain, + * so the function must not block! + * + * \see hal_set_trx_end_event_handler + */ +//static hal_trx_end_isr_event_handler_t trx_end_callback; +/*============================ PROTOTYPES ====================================*/ +/*============================ IMPLEMENTATION ================================*/ + +/** \brief This function initializes the Hardware Abstraction Layer. + */ +void +hal_init(void) +{ + /*Reset variables used in file.*/ + hal_system_time = 0; +// hal_reset_flags(); + + /*IO Specific Initialization.*/ + DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */ + DDR_RST |= (1 << RST); /* Enable RST as output. */ + + /*SPI Specific Initialization.*/ + /* Set SS, CLK and MOSI as output. */ + HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI); + HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */ + /* Run SPI at max speed */ + SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */ + SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */ + + /*TIMER1 Specific Initialization.*/ + TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */ + TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */ + HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */ + hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */ +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function reset the interrupt flags and interrupt event handlers + * (Callbacks) to their default value. + */ +//void +//hal_reset_flags(void) +//{ +// AVR_ENTER_CRITICAL_REGION(); + + /* Reset Flags. */ +// hal_bat_low_flag = 0; +// hal_pll_lock_flag = 0; + + /* Reset Associated Event Handlers. */ +// rx_start_callback = NULL; +// trx_end_callback = NULL; + +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function returns the current value of the BAT_LOW flag. + * + * The BAT_LOW flag is incremented each time a BAT_LOW event is signaled from the + * radio transceiver. This way it is possible for the end user to poll the flag + * for new event occurances. + */ +//uint8_t +//hal_get_bat_low_flag(void) +//{ +// return hal_bat_low_flag; +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function clears the BAT_LOW flag. + */ +//void +//hal_clear_bat_low_flag(void) +//{ +// AVR_ENTER_CRITICAL_REGION(); +// hal_bat_low_flag = 0; +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function is used to set new TRX_END event handler, overriding + * old handler reference. + */ +//hal_trx_end_isr_event_handler_t +//hal_get_trx_end_event_handler(void) +//{ +// return trx_end_callback; +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function is used to set new TRX_END event handler, overriding + * old handler reference. + */ +//void +//hal_set_trx_end_event_handler(hal_trx_end_isr_event_handler_t trx_end_callback_handle) +//{ +// AVR_ENTER_CRITICAL_REGION(); +// trx_end_callback = trx_end_callback_handle; +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief Remove event handler reference. + */ +//void +//hal_clear_trx_end_event_handler(void) +//{ +// AVR_ENTER_CRITICAL_REGION(); +// trx_end_callback = NULL; +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function returns the active RX_START event handler + * + * \return Current RX_START event handler registered. + */ +//hal_rx_start_isr_event_handler_t +//hal_get_rx_start_event_handler(void) +//{ +// return rx_start_callback; +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function is used to set new RX_START event handler, overriding + * old handler reference. + */ +//void +//hal_set_rx_start_event_handler(hal_rx_start_isr_event_handler_t rx_start_callback_handle) +//{ +// AVR_ENTER_CRITICAL_REGION(); +// rx_start_callback = rx_start_callback_handle; +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief Remove event handler reference. + */ +//void +//hal_clear_rx_start_event_handler(void) +//{ +// AVR_ENTER_CRITICAL_REGION(); +// rx_start_callback = NULL; +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function returns the current value of the PLL_LOCK flag. + * + * The PLL_LOCK flag is incremented each time a PLL_LOCK event is signaled from the + * radio transceiver. This way it is possible for the end user to poll the flag + * for new event occurances. + */ +//uint8_t +//hal_get_pll_lock_flag(void) +//{ +// return hal_pll_lock_flag; +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function clears the PLL_LOCK flag. + */ +//void +//hal_clear_pll_lock_flag(void) +//{ +// AVR_ENTER_CRITICAL_REGION(); +// hal_pll_lock_flag = 0; +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief This function reads data from one of the radio transceiver's registers. + * + * \param address Register address to read from. See datasheet for register + * map. + * + * \see Look at the at86rf230_registermap.h file for register address definitions. + * + * \returns The actual value of the read register. + */ +uint8_t +hal_register_read(uint8_t address) +{ + /* Add the register read command to the register address. */ + address &= HAL_TRX_CMD_RADDRM; + address |= HAL_TRX_CMD_RR; + + uint8_t register_value = 0; + + AVR_ENTER_CRITICAL_REGION(); + + HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ + + /*Send Register address and read register content.*/ + SPDR = address; + while ((SPSR & (1 << SPIF)) == 0) {;} + register_value = SPDR; + + SPDR = register_value; + while ((SPSR & (1 << SPIF)) == 0) {;} + register_value = SPDR; + + HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ + + AVR_LEAVE_CRITICAL_REGION(); + + return register_value; +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function writes a new value to one of the radio transceiver's + * registers. + * + * \see Look at the at86rf230_registermap.h file for register address definitions. + * + * \param address Address of register to write. + * \param value Value to write. + */ +void +hal_register_write(uint8_t address, uint8_t value) +{ + /* Add the Register Write command to the address. */ + address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address); + + AVR_ENTER_CRITICAL_REGION(); + + HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ + + /*Send Register address and write register content.*/ + SPDR = address; + while ((SPSR & (1 << SPIF)) == 0) {;} + uint8_t dummy_read = SPDR; + + SPDR = value; + while ((SPSR & (1 << SPIF)) == 0) {;} + dummy_read = SPDR; + + HAL_SS_HIGH(); /* End the transaction by pulling the Slave Slect High. */ + + AVR_LEAVE_CRITICAL_REGION(); +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function reads the value of a specific subregister. + * + * \see Look at the at86rf230_registermap.h file for register and subregister + * definitions. + * + * \param address Main register's address. + * \param mask Bit mask of the subregister. + * \param position Bit position of the subregister + * \retval Value of the read subregister. + */ +uint8_t +hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position) +{ + /* Read current register value and mask out subregister. */ + uint8_t register_value = hal_register_read(address); + register_value &= mask; + register_value >>= position; /* Align subregister value. */ + + return register_value; +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function writes a new value to one of the radio transceiver's + * subregisters. + * + * \see Look at the at86rf230_registermap.h file for register and subregister + * definitions. + * + * \param address Main register's address. + * \param mask Bit mask of the subregister. + * \param position Bit position of the subregister + * \param value Value to write into the subregister. + */ +void +hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, + uint8_t value) +{ + /* Read current register value and mask area outside the subregister. */ + uint8_t register_value = hal_register_read(address); + register_value &= ~mask; + + /* Start preparing the new subregister value. shift in place and mask. */ + value <<= position; + value &= mask; + + value |= register_value; /* Set the new subregister value. */ + + /* Write the modified register value. */ + hal_register_write(address, value); +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function will upload a frame from the radio transceiver's frame + * buffer. + * + * If the frame currently available in the radio transceiver's frame buffer + * is out of the defined bounds. Then the frame length, lqi value and crc + * be set to zero. This is done to indicate an error. + * This version is optimized for use with contiki RF230BB driver + * + * \param rx_frame Pointer to the data structure where the frame is stored. + * \param rx_callback Pointer to callback function for receiving one byte at a time. + */ +void +hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback) +{ + uint8_t *rx_data=0; + + /* check that we have either valid frame pointer or callback pointer */ +// if (!rx_frame && !rx_callback) +// return; + + AVR_ENTER_CRITICAL_REGION(); + + HAL_SS_LOW(); + + /*Send frame read command.*/ + SPDR = HAL_TRX_CMD_FR; + while ((SPSR & (1 << SPIF)) == 0) {;} + uint8_t frame_length = SPDR; + + /*Read frame length.*/ + SPDR = frame_length; + while ((SPSR & (1 << SPIF)) == 0) {;} + frame_length = SPDR; + + /*Check for correct frame length.*/ + if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){ + uint16_t crc = 0; +// if (rx_frame){ + rx_data = (rx_frame->data); + rx_frame->length = frame_length; +// } else { +// rx_callback(frame_length); +// } + /*Upload frame buffer to data pointer. Calculate CRC.*/ + SPDR = frame_length; + while ((SPSR & (1 << SPIF)) == 0) {;} + + do{ + uint8_t tempData = SPDR; + SPDR = 0; /* dummy write */ + +// if (rx_frame){ + *rx_data++ = tempData; +// } else { +// rx_callback(tempData); +// } + + crc = _crc_ccitt_update(crc, tempData); + + while ((SPSR & (1 << SPIF)) == 0) {;} + + } while (--frame_length > 0); + + /*Read LQI value for this frame.*/ +// if (rx_frame){ + rx_frame->lqi = SPDR; +// } else { +// rx_callback(SPDR); +// } + + HAL_SS_HIGH(); + + /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/ +// if (rx_frame){ + rx_frame->crc = (crc == HAL_CALCULATED_CRC_OK); +// } else { +// rx_callback(crc != HAL_CALCULATED_CRC_OK); +// } + } else { + HAL_SS_HIGH(); + +// if (rx_frame){ + rx_frame->length = 0; + rx_frame->lqi = 0; + rx_frame->crc = false; +// } + } + + AVR_LEAVE_CRITICAL_REGION(); +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function will download a frame to the radio transceiver's frame + * buffer. + * + * \param write_buffer Pointer to data that is to be written to frame buffer. + * \param length Length of data. The maximum length is 127 bytes. + */ +void +hal_frame_write(uint8_t *write_buffer, uint8_t length) +{ + length &= HAL_TRX_CMD_RADDRM; /* Truncate length to maximum frame length. */ + + AVR_ENTER_CRITICAL_REGION(); + + HAL_SS_LOW(); /* Initiate the SPI transaction. */ + + /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/ + SPDR = HAL_TRX_CMD_FW; + while ((SPSR & (1 << SPIF)) == 0) {;} + uint8_t dummy_read = SPDR; + + SPDR = length; + while ((SPSR & (1 << SPIF)) == 0) {;} + dummy_read = SPDR; + + /* Download to the Frame Buffer. */ + do{ + SPDR = *write_buffer++; + --length; + + while ((SPSR & (1 << SPIF)) == 0) {;} + + dummy_read = SPDR; + } while (length > 0); + + HAL_SS_HIGH(); /* Terminate SPI transaction. */ + + AVR_LEAVE_CRITICAL_REGION(); +} + +/*----------------------------------------------------------------------------*/ +/** \brief Read SRAM + * + * This function reads from the SRAM of the radio transceiver. + * + * \param address Address in the TRX's SRAM where the read burst should start + * \param length Length of the read burst + * \param data Pointer to buffer where data is stored. + */ +//void +//hal_sram_read(uint8_t address, uint8_t length, uint8_t *data) +//{ +// AVR_ENTER_CRITICAL_REGION(); + +// HAL_SS_LOW(); /* Initiate the SPI transaction. */ + + /*Send SRAM read command.*/ +// SPDR = HAL_TRX_CMD_SR; +// while ((SPSR & (1 << SPIF)) == 0) {;} +// uint8_t dummy_read = SPDR; + + /*Send address where to start reading.*/ +// SPDR = address; +// while ((SPSR & (1 << SPIF)) == 0) {;} + +// dummy_read = SPDR; + + /*Upload the chosen memory area.*/ +// do{ +// SPDR = HAL_DUMMY_READ; +// while ((SPSR & (1 << SPIF)) == 0) {;} +// *data++ = SPDR; +// } while (--length > 0); + +// HAL_SS_HIGH(); + +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/** \brief Write SRAM + * + * This function writes into the SRAM of the radio transceiver. + * + * \param address Address in the TRX's SRAM where the write burst should start + * \param length Length of the write burst + * \param data Pointer to an array of bytes that should be written + */ +//void +//hal_sram_write(uint8_t address, uint8_t length, uint8_t *data) +//{ +// AVR_ENTER_CRITICAL_REGION(); + +// HAL_SS_LOW(); + + /*Send SRAM write command.*/ +// SPDR = HAL_TRX_CMD_SW; +// while ((SPSR & (1 << SPIF)) == 0) {;} +// uint8_t dummy_read = SPDR; + + /*Send address where to start writing to.*/ +// SPDR = address; +// while ((SPSR & (1 << SPIF)) == 0) {;} +// dummy_read = SPDR; + + /*Upload the chosen memory area.*/ +// do{ +// SPDR = *data++; +// while ((SPSR & (1 << SPIF)) == 0) {;} +// dummy_read = SPDR; +// } while (--length > 0); + +// HAL_SS_HIGH(); + +// AVR_LEAVE_CRITICAL_REGION(); +//} + +/*----------------------------------------------------------------------------*/ +/* This #if compile switch is used to provide a "standard" function body for the */ +/* doxygen documentation. */ +#if defined(DOXYGEN) +/** \brief ISR for the radio IRQ line, triggered by the input capture. + * This is the interrupt service routine for timer1.ICIE1 input capture. + * It is triggered of a rising edge on the radio transceivers IRQ line. + */ +void RADIO_VECT(void); +#else /* !DOXYGEN */ +/* These link to the RF230BB driver in rf230.c */ +void rf230_interrupt(void); +extern hal_rx_frame_t rxframe; + +#define DEBUG 0 +#if DEBUG +volatile int rf230_interrupt_flag=0; +#define INTERRUPTDEBUG(arg) rf230_interrupt_flag=arg +#else +#define INTERRUPTDEBUG(arg) +#endif + +ISR(RADIO_VECT) +{ + /*The following code reads the current system time. This is done by first + reading the hal_system_time and then adding the 16 LSB directly from the + TCNT1 register. + */ + uint32_t isr_timestamp = hal_system_time; + isr_timestamp <<= 16; + isr_timestamp |= TCNT1; + volatile uint8_t state; + + INTERRUPTDEBUG(1); + + /*Read Interrupt source.*/ + HAL_SS_LOW(); + + /*Send Register address and read register content.*/ + SPDR = RG_IRQ_STATUS | HAL_TRX_CMD_RR; + + /* This is the second part of the convertion of system time to a 16 us time + base. The division is moved here so we can spend less time waiting for SPI + data. + */ + isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */ + isr_timestamp &= HAL_SYMBOL_MASK; + + while ((SPSR & (1 << SPIF)) == 0) {;} + uint8_t interrupt_source = SPDR; /* The interrupt variable is used as a dummy read. */ + + SPDR = interrupt_source; + while ((SPSR & (1 << SPIF)) == 0) {;} + interrupt_source = SPDR; /* The interrupt source is read. */ + + HAL_SS_HIGH(); + + /*Handle the incomming interrupt. Prioritized.*/ + if ((interrupt_source & HAL_RX_START_MASK)){ + INTERRUPTDEBUG(10); +// if(rx_start_callback != NULL){ +// /* Read Frame length and call rx_start callback. */ +// HAL_SS_LOW(); + +// SPDR = HAL_TRX_CMD_FR; +// while ((SPSR & (1 << SPIF)) == 0) {;} +// uint8_t frame_length = SPDR; + +// SPDR = frame_length; /* frame_length used for dummy data */ +// while ((SPSR & (1 << SPIF)) == 0) {;} +// frame_length = SPDR; + +// HAL_SS_HIGH(); + +// rx_start_callback(isr_timestamp, frame_length); +// } + } else if (interrupt_source & HAL_TRX_END_MASK){ + INTERRUPTDEBUG(11); +// if(trx_end_callback != NULL){ +// INTERRUPTDEBUG(12); +// trx_end_callback(isr_timestamp); +// } + + state = hal_subregister_read(SR_TRX_STATUS); + if((state == BUSY_RX_AACK) || (state == RX_ON) || (state == BUSY_RX) || (state == RX_AACK_ON)){ + /* Received packet interrupt */ + /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */ +// if (rxframe.length) break; //toss packet if last one not processed yet + hal_frame_read(&rxframe, NULL); + rf230_interrupt(); +// trx_end_callback(isr_timestamp); + /* Enable reception of next packet */ + hal_subregister_write(SR_TRX_CMD, RX_AACK_ON); + } + + } else if (interrupt_source & HAL_TRX_UR_MASK){ + INTERRUPTDEBUG(13); + ; + } else if (interrupt_source & HAL_PLL_UNLOCK_MASK){ + INTERRUPTDEBUG(14); + ; + } else if (interrupt_source & HAL_PLL_LOCK_MASK){ + INTERRUPTDEBUG(15); +// hal_pll_lock_flag++; + ; + } else if (interrupt_source & HAL_BAT_LOW_MASK){ + /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */ + /* will continously be asserted while the supply voltage is less than the */ + /* user-defined voltage threshold. */ + uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK); + trx_isr_mask &= ~HAL_BAT_LOW_MASK; + hal_register_write(RG_IRQ_MASK, trx_isr_mask); +// hal_bat_low_flag++; /* Increment BAT_LOW flag. */ + INTERRUPTDEBUG(16); + ; + } else { + INTERRUPTDEBUG(99); + ; + } +} +# endif /* defined(DOXYGEN) */ + +/*----------------------------------------------------------------------------*/ +/* This #if compile switch is used to provide a "standard" function body for the */ +/* doxygen documentation. */ +#if defined(DOXYGEN) +/** \brief Timer Overflow ISR + * This is the interrupt service routine for timer1 overflow. + */ +void TIMER1_OVF_vect(void); +#else /* !DOXYGEN */ +ISR(TIMER1_OVF_vect) +{ + hal_system_time++; +} +#endif + +/** @} */ +/** @} */ + +/*EOF*/ diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c new file mode 100644 index 000000000..6b7e555c9 --- /dev/null +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -0,0 +1,979 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE OR 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. + * + * + * $Id: rf230bb.c,v 1.1 2009/07/08 16:17:07 dak664 Exp $ +*/ + +/** + * \brief This module contains radio driver code for the Atmel + * AT86RF230. It is modified to use the contiki core MAC layer. + * + * \author Blake Leverett + * Mike Vidales + * Eric Gnoske + * David Kopf + * +*/ + +/** \addtogroup wireless + * @{ + */ + +/** + * \defgroup radiorf230 RF230 interface + * @{ + */ +/** + * \file + * This file contains "barebones" radio driver code for use with the + * contiki core MAC layer. + * + */ + + +#include +#include + +#include "contiki.h" + +//#if defined(__AVR__) +#include +#include +#include +//#elif defined(__MSP430__) +//#include +//#endif + +#include "dev/leds.h" +#include "dev/spi.h" +#include "rf230bb.h" +#include "hal.h" +//#include "frame.h" +#include "radio.h" + +#include "net/rime/packetbuf.h" +#include "net/rime/rimestats.h" + +#include "sys/timetable.h" + +#define WITH_SEND_CCA 0 + + +#if RF230_CONF_TIMESTAMPS +#include "net/rime/timesynch.h" +#define TIMESTAMP_LEN 3 +#else /* RF230_CONF_TIMESTAMPS */ +#define TIMESTAMP_LEN 0 +#endif /* RF230_CONF_TIMESTAMPS */ +#define FOOTER_LEN 2 + +#ifndef RF230_CONF_CHECKSUM +#define RF230_CONF_CHECKSUM 0 +#endif /* RF230_CONF_CHECKSUM */ + +#if RF230_CONF_CHECKSUM +#include "lib/crc16.h" +#define CHECKSUM_LEN 2 +#else +#define CHECKSUM_LEN 0 +#endif /* RF230_CONF_CHECKSUM */ + +#define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN) + +struct timestamp { + uint16_t time; + uint8_t authority_level; +}; + + +#define FOOTER1_CRC_OK 0x80 +#define FOOTER1_CORRELATION 0x7f + +#define DEBUG 0 +#if DEBUG +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTF(...) do {} while (0) +#endif + +/* XXX hack: these will be made as Chameleon packet attributes */ +rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure; + +int rf230_authority_level_of_sender; + +#if RF230_CONF_TIMESTAMPS +static rtimer_clock_t setup_time_for_transmission; +static unsigned long total_time_for_transmission, total_transmission_len; +static int num_transmissions; +#endif /* RF230_CONF_TIMESTAMPS */ + +/* RF230 hardware delay times, from datasheet */ +typedef enum{ + TIME_TO_ENTER_P_ON = 510, /**< Transition time from VCC is applied to P_ON. */ + TIME_P_ON_TO_TRX_OFF = 510, /**< Transition time from P_ON to TRX_OFF. */ + TIME_SLEEP_TO_TRX_OFF = 880, /**< Transition time from SLEEP to TRX_OFF. */ + TIME_RESET = 6, /**< Time to hold the RST pin low during reset */ + TIME_ED_MEASUREMENT = 140, /**< Time it takes to do a ED measurement. */ + TIME_CCA = 140, /**< Time it takes to do a CCA. */ + TIME_PLL_LOCK = 150, /**< Maximum time it should take for the PLL to lock. */ + TIME_FTN_TUNING = 25, /**< Maximum time it should take to do the filter tuning. */ + TIME_NOCLK_TO_WAKE = 6, /**< Transition time from *_NOCLK to being awake. */ + TIME_CMD_FORCE_TRX_OFF = 1, /**< Time it takes to execute the FORCE_TRX_OFF command. */ + TIME_TRX_OFF_TO_PLL_ACTIVE = 180, /**< Transition time from TRX_OFF to: RX_ON, PLL_ON, TX_ARET_ON and RX_AACK_ON. */ + TIME_STATE_TRANSITION_PLL_ACTIVE = 1, /**< Transition time from PLL active state to another. */ +}radio_trx_timing_t; + +/*---------------------------------------------------------------------------*/ +PROCESS(rf230_process, "RF230 receiver"); +/*---------------------------------------------------------------------------*/ + +int rf230_send(const void *data, unsigned short len); +int rf230_read(void *buf, unsigned short bufsize); +void rf230_set_receiver(void (* recv)(const struct radio_driver *d)); +int rf230_on(void); +int rf230_off(void); + +const struct radio_driver rf230_driver = + { + rf230_send, + rf230_read, + rf230_set_receiver, + rf230_on, + rf230_off, + }; + +static void (* receiver_callback)(const struct radio_driver *); + +//signed char rf230_last_rssi; +//uint8_t rf230_last_correlation; + +static uint8_t receive_on; +//static uint8_t rssi_val; +uint8_t rx_mode; +/* Radio stuff in network byte order. */ +//static uint16_t pan_id; + +//static int channel; + + +/*----------------------------------------------------------------------------*/ +/** \brief This function return the Radio Transceivers current state. + * + * \retval P_ON When the external supply voltage (VDD) is + * first supplied to the transceiver IC, the + * system is in the P_ON (Poweron) mode. + * \retval BUSY_RX The radio transceiver is busy receiving a + * frame. + * \retval BUSY_TX The radio transceiver is busy transmitting a + * frame. + * \retval RX_ON The RX_ON mode enables the analog and digital + * receiver blocks and the PLL frequency + * synthesizer. + * \retval TRX_OFF In this mode, the SPI module and crystal + * oscillator are active. + * \retval PLL_ON Entering the PLL_ON mode from TRX_OFF will + * first enable the analog voltage regulator. The + * transceiver is ready to transmit a frame. + * \retval BUSY_RX_AACK The radio was in RX_AACK_ON mode and received + * the Start of Frame Delimiter (SFD). State + * transition to BUSY_RX_AACK is done if the SFD + * is valid. + * \retval BUSY_TX_ARET The radio transceiver is busy handling the + * auto retry mechanism. + * \retval RX_AACK_ON The auto acknowledge mode of the radio is + * enabled and it is waiting for an incomming + * frame. + * \retval TX_ARET_ON The auto retry mechanism is enabled and the + * radio transceiver is waiting for the user to + * send the TX_START command. + * \retval RX_ON_NOCLK The radio transceiver is listening for + * incomming frames, but the CLKM is disabled so + * that the controller could be sleeping. + * However, this is only true if the controller + * is run from the clock output of the radio. + * \retval RX_AACK_ON_NOCLK Same as the RX_ON_NOCLK state, but with the + * auto acknowledge module turned on. + * \retval BUSY_RX_AACK_NOCLK Same as BUSY_RX_AACK, but the controller + * could be sleeping since the CLKM pin is + * disabled. + * \retval STATE_TRANSITION The radio transceiver's state machine is in + * transition between two states. + */ +uint8_t +radio_get_trx_state(void) +{ + return hal_subregister_read(SR_TRX_STATUS); +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function checks if the radio transceiver is sleeping. + * + * \retval true The radio transceiver is in SLEEP or one of the *_NOCLK + * states. + * \retval false The radio transceiver is not sleeping. + */ +bool radio_is_sleeping(void) +{ + bool sleeping = false; + + /* The radio transceiver will be at SLEEP or one of the *_NOCLK states only if */ + /* the SLP_TR pin is high. */ + if (hal_get_slptr() != 0){ + sleeping = true; + } + + return sleeping; +} + +/*----------------------------------------------------------------------------*/ +/** \brief This function will reset the state machine (to TRX_OFF) from any of + * its states, except for the SLEEP state. + */ +void +radio_reset_state_machine(void) +{ + hal_set_slptr_low(); + delay_us(TIME_NOCLK_TO_WAKE); + hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF); + delay_us(TIME_CMD_FORCE_TRX_OFF); +} +/*----------------------------------------------------------------------------*/ +/** \brief This function will change the current state of the radio + * transceiver's internal state machine. + * + * \param new_state Here is a list of possible states: + * - RX_ON Requested transition to RX_ON state. + * - TRX_OFF Requested transition to TRX_OFF state. + * - PLL_ON Requested transition to PLL_ON state. + * - RX_AACK_ON Requested transition to RX_AACK_ON state. + * - TX_ARET_ON Requested transition to TX_ARET_ON state. + * + * \retval RADIO_SUCCESS Requested state transition completed + * successfully. + * \retval RADIO_INVALID_ARGUMENT Supplied function parameter out of bounds. + * \retval RADIO_WRONG_STATE Illegal state to do transition from. + * \retval RADIO_BUSY_STATE The radio transceiver is busy. + * \retval RADIO_TIMED_OUT The state transition could not be completed + * within resonable time. + */ +radio_status_t +radio_set_trx_state(uint8_t new_state) +{ + uint8_t original_state; + + /*Check function paramter and current state of the radio transceiver.*/ + if (!((new_state == TRX_OFF) || + (new_state == RX_ON) || + (new_state == PLL_ON) || + (new_state == RX_AACK_ON) || + (new_state == TX_ARET_ON))){ + return RADIO_INVALID_ARGUMENT; + } + + if (radio_is_sleeping() == true){ + return RADIO_WRONG_STATE; + } + + // Wait for radio to finish previous operation + for(;;) + { + original_state = radio_get_trx_state(); + if (original_state != BUSY_TX_ARET && + original_state != BUSY_RX_AACK && + original_state != BUSY_RX && + original_state != BUSY_TX) + break; + } + + if (new_state == original_state){ + return RADIO_SUCCESS; + } + + + /* At this point it is clear that the requested new_state is: */ + /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON. */ + + /* The radio transceiver can be in one of the following states: */ + /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON, TX_ARET_ON. */ + if(new_state == TRX_OFF){ + radio_reset_state_machine(); /* Go to TRX_OFF from any state. */ + } else { + /* It is not allowed to go from RX_AACK_ON or TX_AACK_ON and directly to */ + /* TX_AACK_ON or RX_AACK_ON respectively. Need to go via RX_ON or PLL_ON. */ + if ((new_state == TX_ARET_ON) && + (original_state == RX_AACK_ON)){ + /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */ + /* The final state transition to TX_ARET_ON is handled after the if-else if. */ + hal_subregister_write(SR_TRX_CMD, PLL_ON); + delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE); + } else if ((new_state == RX_AACK_ON) && + (original_state == TX_ARET_ON)){ + /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */ + /* The final state transition to RX_AACK_ON is handled after the if-else if. */ + hal_subregister_write(SR_TRX_CMD, RX_ON); + delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE); + } + + /* Any other state transition can be done directly. */ + hal_subregister_write(SR_TRX_CMD, new_state); + + /* When the PLL is active most states can be reached in 1us. However, from */ + /* TRX_OFF the PLL needs time to activate. */ + if (original_state == TRX_OFF){ + delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE); + } else { + delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE); + } + } /* end: if(new_state == TRX_OFF) ... */ + + /*Verify state transition.*/ + radio_status_t set_state_status = RADIO_TIMED_OUT; + + if (radio_get_trx_state() == new_state){ + set_state_status = RADIO_SUCCESS; + /* set rx_mode flag based on mode we're changing to */ + if (new_state == RX_ON || + new_state == RX_AACK_ON){ + rx_mode = true; + } else { + rx_mode = false; + } + } + + return set_state_status; +} + +/*---------------------------------------------------------------------------*/ +void +rf230_waitidle(void) +{ +// PRINTF("rf230_waitidle"); + uint8_t radio_state; + + for(;;) + { + radio_state = hal_subregister_read(SR_TRX_STATUS); + if (radio_state != BUSY_TX_ARET && + radio_state != BUSY_RX_AACK && + radio_state != BUSY_RX && + radio_state != BUSY_TX) + break; + PRINTF("."); + } +} + +/*---------------------------------------------------------------------------*/ +static uint8_t locked, lock_on, lock_off; + +static void +on(void) +{ + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + PRINTF("rf230 internal on\n"); + receive_on = 1; + + hal_set_slptr_low(); +//radio_is_waking=1;//can test this before tx instead of delaying + delay_us(TIME_SLEEP_TO_TRX_OFF); + delay_us(TIME_SLEEP_TO_TRX_OFF);//extra delay for now + + radio_set_trx_state(RX_AACK_ON); +// flushrx(); +} +static void +off(void) +{ + PRINTF("rf230 internal off\n"); + receive_on = 0; + + /* Wait for transmission to end before turning radio off. */ + rf230_waitidle(); + + /* Force the device into TRX_OFF. */ + radio_reset_state_machine(); + + /* Sleep Radio */ + hal_set_slptr_high(); + + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); +} +/*---------------------------------------------------------------------------*/ +#define GET_LOCK() locked = 1 +static void RELEASE_LOCK(void) { + if(lock_on) { + on(); + lock_on = 0; + } + if(lock_off) { + off(); + lock_off = 0; + } + locked = 0; +} +/*---------------------------------------------------------------------------*/ +void +rf230_set_receiver(void (* recv)(const struct radio_driver *)) +{ +//PRINTF("rf230_set receiver\n"); + receiver_callback = recv; +} + +/*---------------------------------------------------------------------------*/ +int +rf230_off(void) +{ +// PRINTF("rf230_off\n"); + /* Don't do anything if we are already turned off. */ + if(receive_on == 0) { + return 1; + } + + /* If we are called when the driver is locked, we indicate that the + radio should be turned off when the lock is unlocked. */ + if(locked) { + lock_off = 1; + return 1; + } + off(); + + return 1; +} +/*---------------------------------------------------------------------------*/ +int +rf230_on(void) +{ +//PRINTF("rf230_on\n"); + if(receive_on) { + return 1; + } + if(locked) { + lock_on = 1; + return 1; + } + on(); + + return 1; +} +/*---------------------------------------------------------------------------*/ +int +rf230_get_channel(void) +{ + return hal_subregister_read(SR_CHANNEL); +// return channel; +} +/*---------------------------------------------------------------------------*/ +void +rf230_set_channel(int c) +{ + /* Wait for any transmission to end. */ + rf230_waitidle(); + +//channel=c; + hal_subregister_write(SR_CHANNEL, c); + +} +/*---------------------------------------------------------------------------*/ +void +rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr) +{ + PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr); + + uint8_t abyte; + abyte = pan & 0xFF; + hal_register_write(RG_PAN_ID_0,abyte); + abyte = (pan >> 8*1) & 0xFF; + hal_register_write(RG_PAN_ID_1, abyte); + + abyte = addr & 0xFF; + hal_register_write(RG_SHORT_ADDR_0, abyte); + abyte = (addr >> 8*1) & 0xFF; + hal_register_write(RG_SHORT_ADDR_1, abyte); + + if (ieee_addr != NULL) { + PRINTF("MAC=%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++); + PRINTF(":%x",*ieee_addr); + hal_register_write(RG_IEEE_ADDR_0, *ieee_addr); + PRINTF("\n"); + } + +} + +/*---------------------------------------------------------------------------*/ +/* Process to handle input packets + * Receive interrupts cause this process to be polled + * It calls the core MAC layer which calls rf230_read to get the packet +*/ +PROCESS_THREAD(rf230_process, ev, data) +{ + PROCESS_BEGIN(); + + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + +#if RF230_TIMETABLE_PROFILING + TIMETABLE_TIMESTAMP(rf230_timetable, "poll"); +#endif /* RF230_TIMETABLE_PROFILING */ + + if(receiver_callback != NULL) { + receiver_callback(&rf230_driver); +#if RF230_TIMETABLE_PROFILING + TIMETABLE_TIMESTAMP(rf230_timetable, "end"); + timetable_aggregate_compute_detailed(&aggregate_time, + &rf230_timetable); + timetable_clear(&rf230_timetable); +#endif /* RF230_TIMETABLE_PROFILING */ + } else { + PRINTF("rf230_process not receiving function\n"); +// flushrx(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/* + * This routine is called by the radio receive interrupt in hal.c + * It just sets the poll flag for the rf230 process. + */ +#if RF230_CONF_TIMESTAMPS +static volatile rtimer_clock_t interrupt_time; +static volatile int interrupt_time_set; +#endif /* RF230_CONF_TIMESTAMPS */ +#if RF230_TIMETABLE_PROFILING +#define rf230_timetable_size 16 +TIMETABLE(rf230_timetable); +TIMETABLE_AGGREGATE(aggregate_time, 10); +#endif /* RF230_TIMETABLE_PROFILING */ +void +rf230_interrupt(void) +{ +#if RF230_CONF_TIMESTAMPS + interrupt_time = timesynch_time(); + interrupt_time_set = 1; +#endif /* RF230_CONF_TIMESTAMPS */ + + process_poll(&rf230_process); +#if RF230_TIMETABLE_PROFILING + timetable_clear(&rf230_timetable); + TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt"); +#endif /* RF230_TIMETABLE_PROFILING */ + return; +} +/* The frame is buffered to rxframe in the interrupt routine in hal.c */ + hal_rx_frame_t rxframe; +/*---------------------------------------------------------------------------*/ +int +rf230_read(void *buf, unsigned short bufsize) +{ + + uint8_t *framep; + // uint8_t footer[2]; + uint8_t len; +#if RF230_CONF_CHECKSUM + uint16_t checksum; +#endif /* RF230_CONF_CHECKSUM */ +#if RF230_CONF_TIMESTAMPS + struct timestamp t; +#endif /* RF230_CONF_TIMESTAMPS */ + + PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe.length,rxframe.lqi,rxframe.crc); +#if DEBUG>1 + for (len=0;len RF230_MAX_PACKET_LEN) { +// // Oops, we must be out of sync. +// flushrx(); +// RIMESTATS_ADD(badsynch); +// RELEASE_LOCK(); +// return 0; +// } + +//hal returns two extra bytes containing the checksum +//below works because auxlen is 2 + len = rxframe.length; + if(len <= AUX_LEN) { + // flushrx(); + RIMESTATS_ADD(tooshort); + RELEASE_LOCK(); + return 0; + } + + if(len - AUX_LEN > bufsize) { +// flushrx(); + RIMESTATS_ADD(toolong); + RELEASE_LOCK(); + return 0; + } + /* Transfer the frame, stripping the checksum */ + framep=&(rxframe.data[0]); + memcpy(buf,framep,len-2); + /* Clear the length field to allow buffering of the next packet */ + rxframe.length=0; + // framep+=len-AUX_LEN+2; + + +#if RF230_CONF_CHECKSUM +bomb + memcpy(&checksum,framep,CHECKSUM_LEN); + framep+=CHECKSUM_LEN; +#endif /* RF230_CONF_CHECKSUM */ +#if RF230_CONF_TIMESTAMPS +bomb + memcpy(&t,framep,TIMESTAMP_LEN); + framep+=TIMESTAMP_LEN; +#endif /* RF230_CONF_TIMESTAMPS */ +// memcpy(&footer,framep,FOOTER_LEN); + +#if RF230_CONF_CHECKSUM +bomb + if(checksum != crc16_data(buf, len - AUX_LEN, 0)) { + PRINTF("rf230: checksum failed 0x%04x != 0x%04x\n", + checksum, crc16_data(buf, len - AUX_LEN, 0)); + } + + if(footer[1] & FOOTER1_CRC_OK && + checksum == crc16_data(buf, len - AUX_LEN, 0)) { +#else + if (rxframe.crc) { +#endif /* RF230_CONF_CHECKSUM */ + +/* + packetbuf_copyfrom(parsed_frame->payload, parsed_frame->payload_length); + packetbuf_set_datalen(parsed_frame->payload_length); + + memcpy(dest_reversed, (uint8_t *)parsed_frame->dest_addr, UIP_LLADDR_LEN); + memcpy(src_reversed, (uint8_t *)parsed_frame->src_addr, UIP_LLADDR_LEN); + + //Change addresses to expected byte order + byte_reverse((uint8_t *)dest_reversed, UIP_LLADDR_LEN); + byte_reverse((uint8_t *)src_reversed, UIP_LLADDR_LEN); + + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (const rimeaddr_t *)dest_reversed); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const rimeaddr_t *)src_reversed); + + */ + + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, hal_subregister_read( SR_RSSI )); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rxframe.lqi); + + RIMESTATS_ADD(llrx); + +#if RF230_CONF_TIMESTAMPS +bomb + rf230_time_of_departure = + t.time + + setup_time_for_transmission + + (total_time_for_transmission * (len - 2)) / total_transmission_len; + + rf230_authority_level_of_sender = t.authority_level; + + packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time); +#endif /* RF230_CONF_TIMESTAMPS */ + + } else { + PRINTF("rf230: Bad CRC\n"); + RIMESTATS_ADD(badcrc); + len = AUX_LEN; + } +// if (?) + /* Another packet has been received and needs attention. */ +// process_poll(&rf230_process); +// } + + RELEASE_LOCK(); + + if(len < AUX_LEN) { + return 0; + } + + return len - AUX_LEN; +} +/*---------------------------------------------------------------------------*/ +void +rf230_set_txpower(uint8_t power) +{ + if (power > TX_PWR_17_2DBM){ + power=TX_PWR_17_2DBM; + } + if (radio_is_sleeping() ==true) { + PRINTF("rf230_set_txpower:Sleeping"); + } else { + hal_subregister_write(SR_TX_PWR, power); + } + +} +/*---------------------------------------------------------------------------*/ +int +rf230_get_txpower(void) +{ + if (radio_is_sleeping() ==true) { + PRINTF("rf230_get_txpower:Sleeping"); + return 0; + } else { + return hal_subregister_read(SR_TX_PWR); + } +} +/*---------------------------------------------------------------------------*/ +int +rf230_rssi(void) +{ + int rssi; + int radio_was_off = 0; + + /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/ + if(!receive_on) { + radio_was_off = 1; + rf230_on(); + } + + rssi = (int)((signed char)hal_subregister_read(SR_RSSI)); + + if(radio_was_off) { + rf230_off(); + } + return rssi; +} +/*---------------------------------------------------------------------------*/ +int +rf230_send(const void *payload, unsigned short payload_len) +{ +// int i; + uint8_t total_len,buffer[RF230_MAX_TX_FRAME_LENGTH],*pbuf; +#if RF230_CONF_TIMESTAMPS + struct timestamp timestamp; +#endif /* RF230_CONF_TIMESTAMPS */ +#if RF230_CONF_CHECKSUM + uint16_t checksum; +#endif /* RF230_CONF_CHECKSUM */ + + GET_LOCK(); + + if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) { + rf230_set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1); + } else { + rf230_set_txpower(TX_PWR_17_2DBM); + } + + RIMESTATS_ADD(lltx); + +#if RF230_CONF_CHECKSUM + checksum = crc16_data(payload, payload_len, 0); +#endif /* RF230_CONF_CHECKSUM */ + total_len = payload_len + AUX_LEN; + /*Check function parameters and current state.*/ + if (total_len > RF230_MAX_TX_FRAME_LENGTH){ + return -1; + } + pbuf=&buffer[0]; + memcpy(pbuf,payload,payload_len); + pbuf+=payload_len; + +#if RF230_CONF_CHECKSUM + memcpy(pbuf,&checksum,CHECKSUM_LEN); + pbuf+=CHECKSUM_LEN; +#endif /* RF230_CONF_CHECKSUM */ + +#if RF230_CONF_TIMESTAMPS + timestamp.authority_level = timesynch_authority_level(); + timestamp.time = timesynch_time(); + memcpy(pbuf,×tamp,TIMESTAMP_LEN); + pbuf+=TIMESTAMP_LEN; +#endif /* RF230_CONF_TIMESTAMPS */ + +/*Below comments were for cc240 radio, don't know how they apply to rf230 - DAK */ + /* The TX FIFO can only hold one packet. Make sure to not overrun + * FIFO by waiting for transmission to start here and synchronizing + * with the RF230_TX_ACTIVE check in rf230_send. + * + * Note that we may have to wait up to 320 us (20 symbols) before + * transmission starts. + */ +//#ifdef TMOTE_SKY +//#define LOOP_20_SYMBOLS 400 /* 326us (msp430 @ 2.4576MHz) */ +//#elif __AVR__ +//#define LOOP_20_SYMBOLS 500 /* XXX */ +//#endif +#define LOOP_20_SYMBOLS 500 + + /* Wait for any previous transmission to finish. */ + rf230_waitidle(); + + hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF); + delay_us(TIME_P_ON_TO_TRX_OFF); + + radio_set_trx_state(TX_ARET_ON); //enable auto ack +//#if WITH_SEND_CCA +// radio_set_trx_state(TX_ARET_ON); //enable auto ack +//#endif /* WITH_SEND_CCA */ + + /* Toggle the SLP_TR pin to initiate the frame transmission. */ + + PRINTF("rf230: sending %d bytes\n", payload_len); + hal_set_slptr_high(); + hal_set_slptr_low(); + hal_frame_write(buffer, total_len); + +// for(i = LOOP_20_SYMBOLS; i > 0; i--) {//dak was working with this + + if(1) { +#if RF230_CONF_TIMESTAMPS + rtimer_clock_t txtime = timesynch_time(); +#endif /* RF230_CONF_TIMESTAMPS */ + + if(receive_on) { + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + } + ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); + + /* We wait until transmission has ended so that we get an + accurate measurement of the transmission time.*/ + rf230_waitidle(); + radio_set_trx_state(RX_AACK_ON);//Re-enable receive mode +#if RF230_CONF_TIMESTAMPS + setup_time_for_transmission = txtime - timestamp.time; + + if(num_transmissions < 10000) { + total_time_for_transmission += timesynch_time() - txtime; + total_transmission_len += total_len; + num_transmissions++; + } +#endif /* RF230_CONF_TIMESTAMPS */ + +#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS + ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower()); +#endif + ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); + if(receive_on) { + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + } + + RELEASE_LOCK(); + return 0; + } +// } + + /* If we are using WITH_SEND_CCA, we get here if the packet wasn't + transmitted because of other channel activity. */ + RIMESTATS_ADD(contentiondrop); + PRINTF("rf230: do_send() transmission never started\n"); + RELEASE_LOCK(); + return -3; /* Transmission never started! */ +}/*---------------------------------------------------------------------------*/ +void +rf230_init(void) +{ + /* Wait in case VCC just applied */ + delay_us(TIME_TO_ENTER_P_ON); + + /* Calibrate oscillator */ +// calibrate_rc_osc_32k(); + + /* Initialize Hardware Abstraction Layer. */ + hal_init(); + + /* Do full rf230 Reset */ + hal_set_rst_low(); + hal_set_slptr_low(); + delay_us(TIME_RESET); + hal_set_rst_high(); + + /* Force transition to TRX_OFF. */ + hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF); + delay_us(TIME_P_ON_TO_TRX_OFF); + + /* Verify that it is a supported version */ + uint8_t tvers = hal_register_read(RG_VERSION_NUM); + uint8_t tmanu = hal_register_read(RG_MAN_ID_0); + + if ((tvers != RF230_REVA) && (tvers != RF230_REVB)) + PRINTF("rf230: Unsupported version %u\n",tvers); + if (tmanu != SUPPORTED_MANUFACTURER_ID) + PRINTF("rf230: Unsupported manufacturer ID %u\n",tmanu); + + PRINTF("rf230: Version %u, ID %u\n",tvers,tmanu); + hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK); + + /* Turn off address decoding. */ +// reg = getreg(RF230_MDMCTRL0); +// reg &= ~ADR_DECODE; +// setreg(RF230_MDMCTRL0, reg); + + /* Change default values as recomended in the data sheet, */ + /* correlation threshold = 20, RX bandpass filter = 1.3uA. */ +// setreg(RF230_MDMCTRL1, CORR_THR(20)); +// reg = getreg(RF230_RXCTRL1); +// reg |= RXBPF_LOCUR; +// setreg(RF230_RXCTRL1, reg); + + /* Set the FIFOP threshold to maximum. */ + // setreg(RF230_IOCFG0, FIFOP_THR(127)); + + /* Turn off "Security enable" (page 32). */ +// reg = getreg(RF230_SECCTRL0); +// reg &= ~RXFIFO_PROTECTION; +// setreg(RF230_SECCTRL0, reg); + + // rf230_set_pan_addr(0xffff, 0x0000, NULL); + // rf230_set_channel(24); + /* Set up the radio for auto mode operation. */ + hal_subregister_write(SR_MAX_FRAME_RETRIES, 2 ); + hal_subregister_write(SR_TX_AUTO_CRC_ON, 1); + hal_subregister_write(SR_TRX_CMD, CMD_RX_AACK_ON); + + /* Start the packet receive process */ + process_start(&rf230_process, NULL); +} \ No newline at end of file diff --git a/cpu/avr/radio/rf230bb/rf230bb.h b/cpu/avr/radio/rf230bb/rf230bb.h new file mode 100644 index 000000000..3422c8054 --- /dev/null +++ b/cpu/avr/radio/rf230bb/rf230bb.h @@ -0,0 +1,233 @@ +/* Copyright (c) 2008, Swedish Institute of Computer Science + * All rights reserved. + * + * Additional fixes for AVR contributed by: + * + * Colin O'Flynn coflynn@newae.com + * Eric Gnoske egnoske@gmail.com + * Blake Leverett bleverett@gmail.com + * Mike Vidales mavida404@gmail.com + * Kevin Brown kbrown3@uccs.edu + * Nate Bohlmann nate@elfwerks.com + * + * 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 copyright holders nor the names of + * 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 COPYRIGHT OWNER OR 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. + */ +/** + * \addtogroup radiorf230 + * @{ + */ +/** + * \file + * \brief This file contains radio driver code. + * + * $Id: rf230bb.h,v 1.1 2009/07/08 16:17:07 dak664 Exp $ + */ + +#ifndef RADIO_H +#define RADIO_H +/*============================ INCLUDE =======================================*/ +#include +#include +#include "at86rf230_registermap.h" +#include "hal.h" + +/*============================ MACROS ========================================*/ +#define SUPPORTED_PART_NUMBER ( 2 ) +#define RF230_REVA ( 1 ) +#define RF230_REVB ( 2 ) +#define SUPPORTED_MANUFACTURER_ID ( 31 ) +#define RF230_SUPPORTED_INTERRUPT_MASK ( 0x0C ) + +#define RF230_MIN_CHANNEL ( 11 ) +#define RF230_MAX_CHANNEL ( 26 ) +#define RF230_MIN_ED_THRESHOLD ( 0 ) +#define RF230_MAX_ED_THRESHOLD ( 15 ) +#define RF230_MAX_TX_FRAME_LENGTH ( 127 ) /**< 127 Byte PSDU. */ + +#define TX_PWR_3DBM ( 0 ) +#define TX_PWR_17_2DBM ( 15 ) + +#define BATTERY_MONITOR_HIGHEST_VOLTAGE ( 15 ) +#define BATTERY_MONITOR_VOLTAGE_UNDER_THRESHOLD ( 0 ) +#define BATTERY_MONITOR_HIGH_VOLTAGE ( 1 ) +#define BATTERY_MONITOR_LOW_VOLTAGE ( 0 ) + +#define FTN_CALIBRATION_DONE ( 0 ) +#define PLL_DCU_CALIBRATION_DONE ( 0 ) +#define PLL_CF_CALIBRATION_DONE ( 0 ) + +#define RC_OSC_REFERENCE_COUNT_MAX (1.005*F_CPU*31250UL/8000000UL) +#define RC_OSC_REFERENCE_COUNT_MIN (0.995*F_CPU*31250UL/8000000UL) + +#ifndef RF_CHANNEL +#define RF_CHANNEL 26 +#endif +/*============================ TYPEDEFS ======================================*/ + +/** \brief This macro defines the start value for the RADIO_* status constants. + * + * It was chosen to have this macro so that the user can define where + * the status returned from the TAT starts. This can be useful in a + * system where numerous drivers are used, and some range of status codes + * are occupied. + * + * \see radio_status_t + */ +#define RADIO_STATUS_START_VALUE ( 0x40 ) + +/** \brief This enumeration defines the possible return values for the TAT API + * functions. + * + * These values are defined so that they should not collide with the + * return/status codes defined in the IEEE 802.15.4 standard. + * + */ +typedef enum{ + RADIO_SUCCESS = RADIO_STATUS_START_VALUE, /**< The requested service was performed successfully. */ + RADIO_UNSUPPORTED_DEVICE, /**< The connected device is not an Atmel AT86RF230. */ + RADIO_INVALID_ARGUMENT, /**< One or more of the supplied function arguments are invalid. */ + RADIO_TIMED_OUT, /**< The requested service timed out. */ + RADIO_WRONG_STATE, /**< The end-user tried to do an invalid state transition. */ + RADIO_BUSY_STATE, /**< The radio transceiver is busy receiving or transmitting. */ + RADIO_STATE_TRANSITION_FAILED, /**< The requested state transition could not be completed. */ + RADIO_CCA_IDLE, /**< Channel is clear, available to transmit a new frame. */ + RADIO_CCA_BUSY, /**< Channel busy. */ + RADIO_TRX_BUSY, /**< Transceiver is busy receiving or transmitting data. */ + RADIO_BAT_LOW, /**< Measured battery voltage is lower than voltage threshold. */ + RADIO_BAT_OK, /**< Measured battery voltage is above the voltage threshold. */ + RADIO_CRC_FAILED, /**< The CRC failed for the actual frame. */ + RADIO_CHANNEL_ACCESS_FAILURE, /**< The channel access failed during the auto mode. */ + RADIO_NO_ACK, /**< No acknowledge frame was received. */ +}radio_status_t; + + +/** + * \name Transaction status codes + * \{ + */ +#define TRAC_SUCCESS 0 +#define TRAC_SUCCESS_DATA_PENDING 1 +#define TRAC_SUCCESS_WAIT_FOR_ACK 2 +#define TRAC_CHANNEL_ACCESS_FAILURE 3 +#define TRAC_NO_ACK 5 +#define TRAC_INVALID 7 +/** \} */ + + +/** \brief This enumeration defines the possible modes available for the + * Clear Channel Assessment algorithm. + * + * These constants are extracted from the datasheet. + * + */ +typedef enum{ + CCA_ED = 0, /**< Use energy detection above threshold mode. */ + CCA_CARRIER_SENSE = 1, /**< Use carrier sense mode. */ + CCA_CARRIER_SENSE_WITH_ED = 2 /**< Use a combination of both energy detection and carrier sense. */ +}radio_cca_mode_t; + + +/** \brief This enumeration defines the possible CLKM speeds. + * + * These constants are extracted from the RF230 datasheet. + * + */ +typedef enum{ + CLKM_DISABLED = 0, + CLKM_1MHZ = 1, + CLKM_2MHZ = 2, + CLKM_4MHZ = 3, + CLKM_8MHZ = 4, + CLKM_16MHZ = 5 +}radio_clkm_speed_t; + +typedef void (*radio_rx_callback) (uint16_t data); +extern uint8_t rxMode; +/*============================ PROTOTYPES ====================================*/ +const struct radio_driver rf230_driver; +void rf230_init(void); +int rf230_get_channel(void); +void rf230_set_channel(int c); +void rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr); +void rf230_set_txpower(uint8_t power); +int rf230_get_txpower(void); + +//radio_status_t radio_init(bool cal_rc_osc, +// hal_rx_start_isr_event_handler_t rx_event, +// hal_trx_end_isr_event_handler_t trx_end_event, +// radio_rx_callback rx_callback); +//uint8_t radio_get_saved_rssi_value(void); +//uint8_t radio_get_operating_channel( void ); +//radio_status_t radio_set_operating_channel( uint8_t channel ); +//uint8_t radio_get_tx_power_level( void ); +//radio_status_t radio_set_tx_power_level( uint8_t power_level ); + +//uint8_t radio_get_cca_mode( void ); +//uint8_t radio_get_ed_threshold( void ); +//radio_status_t radio_set_cca_mode( uint8_t mode, uint8_t ed_threshold ); +//radio_status_t radio_do_cca( void ); +//radio_status_t radio_get_rssi_value( uint8_t *rssi ); + +//uint8_t radio_batmon_get_voltage_threshold( void ); +//uint8_t radio_batmon_get_voltage_range( void ); +//radio_status_t radio_batmon_configure( bool range, uint8_t voltage_threshold ); +//radio_status_t radio_batmon_get_status( void ); + +//uint8_t radio_get_clock_speed( void ); +//radio_status_t radio_set_clock_speed( bool direct, uint8_t clock_speed ); +//radio_status_t radio_calibrate_filter( void ); +//radio_status_t radio_calibrate_pll( void ); + +//uint8_t radio_get_trx_state( void ); +//radio_status_t radio_set_trx_state( uint8_t new_state ); +//radio_status_t radio_enter_sleep_mode( void ); +//radio_status_t radio_leave_sleep_mode( void ); +//void radio_reset_state_machine( void ); +//void radio_reset_trx( void ); + +//void radio_use_auto_tx_crc( bool auto_crc_on ); +//radio_status_t radio_send_data( uint8_t data_length, uint8_t *data ); + +//uint8_t radio_get_device_role( void ); +//void radio_set_device_role( bool i_am_coordinator ); +//uint16_t radio_get_pan_id( void ); +//void radio_set_pan_id( uint16_t new_pan_id ); +//uint16_t radio_get_short_address( void ); +//void radio_set_short_address( uint16_t new_short_address ); +//void radio_get_extended_address( uint8_t *extended_address ); +//void radio_set_extended_address( uint8_t *extended_address ); +//radio_status_t radio_configure_csma( uint8_t seed0, uint8_t be_csma_seed1 ); +//bool calibrate_rc_osc_clkm(void); +//void calibrate_rc_osc_32k(void); +//uint8_t * radio_frame_data(void); +//uint8_t radio_frame_length(void); +#define delay_us( us ) ( _delay_loop_2( ( F_CPU / 4000000UL ) * ( us ) ) ) + +#endif +/** @} */ +/*EOF*/