Radio and 802.15.4 MAC code for the Atmel AVR Raven board

This commit is contained in:
adamdunkels 2008-10-14 09:43:40 +00:00
parent 2e8264010b
commit db7d9bb131
16 changed files with 4957 additions and 0 deletions

View file

@ -0,0 +1,5 @@
CONTIKI_TARGET_SOURCEFILES += ieee-15-4-manager.c
APPDIRS += $(CONTIKI)/cpu/avr/radio/ieee-manager

View file

@ -0,0 +1,237 @@
/*
* Copyright (c) 2008, 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.
*
* This file is part of the Contiki operating system.
*
* $Id: ieee-15-4-manager.c,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/**
*
* \addtogroup rf230mac
* \{
*/
/**
* \file
* \brief Interfaces the 802.15.4 MAC to upper network layers.
*
* \author
* Mike Vidales <mavida404@gmail.com>
*/
#include "mac.h"
#include "radio.h"
#include "ieee-15-4-manager.h"
/*---------------------------------------------------------------------------*/
static int
wake(void)
{
/* Wake the radio. */
return radio_leave_sleep_mode();
}
/*---------------------------------------------------------------------------*/
static int
sleep(void)
{
/* Sleep the radio. */
return radio_enter_sleep_mode();
}
/*---------------------------------------------------------------------------*/
static void
set_channel(int channel)
{
/* Set the channel. */
phyCurrentChannel = channel;
radio_set_operating_channel(phyCurrentChannel);
}
/*---------------------------------------------------------------------------*/
static int
get_channel(void)
{
/* Reads the current channel. */
phyCurrentChannel = radio_get_operating_channel();
return phyCurrentChannel;
}
/*---------------------------------------------------------------------------*/
static void
set_dst_panid(int panid)
{
macDstPANId = panid;
}
/*---------------------------------------------------------------------------*/
static int
get_dst_panid(void)
{
return macDstPANId;
}
/*---------------------------------------------------------------------------*/
static void
set_src_panid(int panid)
{
/* Writes the PAN_ID to the radio. */
macSrcPANId = panid;
radio_set_pan_id(macSrcPANId);
}
/*---------------------------------------------------------------------------*/
static int
get_src_panid(void)
{
/* Gets the PAN_ID from the radio. */
macSrcPANId = radio_get_pan_id();
return macSrcPANId;
}
/*---------------------------------------------------------------------------*/
static void
set_auto_mode(bool mode)
{
autoModes = mode;
}
/*---------------------------------------------------------------------------*/
static bool
get_auto_mode(void)
{
return autoModes;
}
/*---------------------------------------------------------------------------*/
static void
set_long_addr(uint64_t address)
{
/* Set the Long address in the radio. */
macLongAddr = address;
radio_set_extended_address((uint8_t *)&macLongAddr);
}
/*---------------------------------------------------------------------------*/
static uint64_t
get_long_addr(void)
{
/* Get the Long address from the radio. */
radio_get_extended_address((uint8_t *)&macLongAddr);
return macLongAddr;
}
/*---------------------------------------------------------------------------*/
static void
set_short_addr(int address)
{
/* Set the Short address in the radio. */
macShortAddress = address;
radio_set_short_address(macShortAddress);
}
/*---------------------------------------------------------------------------*/
static int
get_short_addr(void)
{
/* Get the Short address from the radio. */
macShortAddress = radio_get_short_address();
return macShortAddress;
}
/*---------------------------------------------------------------------------*/
static void
set_iamcoord_bit(bool iamcoord)
{
/** Set the iAmCoord bit. */
iAmCoord = iamcoord;
radio_set_device_role(iAmCoord);
}
/*---------------------------------------------------------------------------*/
static bool
get_iamcoord_bit(void)
{
/** Get the iAmCoord bit. */
iAmCoord = radio_get_device_role();
return iAmCoord;
}
/*---------------------------------------------------------------------------*/
static void
set_coord_long_addr(uint64_t address)
{
macCoordExtendedAddress = address;
}
/*---------------------------------------------------------------------------*/
static uint64_t
get_coord_long_addr(void)
{
return macCoordExtendedAddress;
}
/*---------------------------------------------------------------------------*/
static void
set_coord_short_addr(int address)
{
macCoordShortAddress = address;
}
/*---------------------------------------------------------------------------*/
static int
get_coord_short_addr(void)
{
return macCoordShortAddress;
}
/*---------------------------------------------------------------------------*/
static void
set_dest_long_addr(uint64_t address)
{
macDestAddress = address;
}
/*---------------------------------------------------------------------------*/
static uint64_t
get_dest_long_addr(void)
{
return macDestAddress;
}
/*---------------------------------------------------------------------------*/
/** \brief initializes the 802.15.4 manager layer.
* \param pieee_15_4_manager Pointer to \ref ieee_15_4_manager
*/
void ieee_15_4_init(ieee_15_4_manager_t *pieee_15_4_manager)
{
/* Initialize the IEEE 15.4 manager. */
pieee_15_4_manager->wake = wake;
pieee_15_4_manager->sleep = sleep;
pieee_15_4_manager->set_channel = set_channel;
pieee_15_4_manager->get_channel = get_channel;
pieee_15_4_manager->set_dst_panid = set_dst_panid;
pieee_15_4_manager->get_dst_panid = get_dst_panid;
pieee_15_4_manager->set_src_panid = set_src_panid;
pieee_15_4_manager->get_src_panid = get_src_panid;
pieee_15_4_manager->set_auto_mode = set_auto_mode;
pieee_15_4_manager->get_auto_mode = get_auto_mode;
pieee_15_4_manager->set_long_addr = set_long_addr;
pieee_15_4_manager->get_long_addr = get_long_addr;
pieee_15_4_manager->set_short_addr = set_short_addr;
pieee_15_4_manager->get_short_addr = get_short_addr;
pieee_15_4_manager->set_iamcoord_bit = set_iamcoord_bit;
pieee_15_4_manager->get_iamcoord_bit = get_iamcoord_bit;
pieee_15_4_manager->set_coord_long_addr = set_coord_long_addr;
pieee_15_4_manager->get_coord_long_addr = get_coord_long_addr;
pieee_15_4_manager->set_coord_short_addr = set_coord_short_addr;
pieee_15_4_manager->get_coord_short_addr = get_coord_short_addr;
pieee_15_4_manager->set_dest_long_addr = set_dest_long_addr;
pieee_15_4_manager->get_dest_long_addr = get_dest_long_addr;
}
/** \} */

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2008, 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.
*
* This file is part of the Contiki operating system.
*
* $Id: ieee-15-4-manager.h,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/**
* \addtogroup rf230mac
* \{
*/
/**
* \file
* \brief Example glue code between the existing MAC code and the
* Contiki mac interface
*
* \author
* Mike Vidales <mavida404@gmail.com>
*
* \ingroup ieee_15_4
*
*/
#ifndef __IEEEMANAGER_H__
#define __IEEEMANAGER_H__
/** \brief The interface structure for the 802.15.4 quasi-MAC. */
typedef struct ieee_15_4_manager{
/** Turn the MAC layer on. */
int (* wake)(void);
/** Turn the MAC layer off. */
int (* sleep)(void);
/** Set the operating channel. */
void (* set_channel)(int channel);
/** Get the operating channel. */
int (* get_channel)(void);
/** Set the Destination PAN_ID. */
void (* set_dst_panid)(int panid);
/** Get the Destination PAN_ID. */
int (* get_dst_panid)(void);
/** Set the Source PAN_ID. */
void (* set_src_panid)(int panid);
/** Get the Source PAN_ID. */
int (* get_src_panid)(void);
/** Set the Automatic TRX modes. */
void (* set_auto_mode)(bool mode);
/** Get the current state of Automatic TRX modes. */
bool (* get_auto_mode)(void);
/** Set the Long Address. */
void (* set_long_addr)(uint64_t address);
/** Get the Long Address. */
uint64_t (* get_long_addr)(void);
/** Set the Short Address. */
void (* set_short_addr)(int address);
/** Get the short Address. */
int (* get_short_addr)(void);
/** Set the iAmCoord bit. */
void (* set_iamcoord_bit)(bool iamcoord);
/** Get the iAmCoord bit. */
bool (* get_iamcoord_bit)(void);
/** Set the Coordinator Long address. */
void (* set_coord_long_addr)(uint64_t address);
/** Get the Coordinator Long address. */
uint64_t (* get_coord_long_addr)(void);
/** Set the Coordinator Long address. */
void (* set_coord_short_addr)(int address);
/** Get the Coordinator Long address. */
int (* get_coord_short_addr)(void);
/** Set the Destination address. */
void (* set_dest_long_addr)(uint64_t address);
/** Get the Destination address. */
uint64_t (* get_dest_long_addr)(void);
} ieee_15_4_manager_t;
void ieee_15_4_init(struct ieee_15_4_manager *pieee_15_4_manager);
#endif /* __IEEEMANAGER_H__ */
/** \} */

View file

@ -0,0 +1,4 @@
CONTIKI_TARGET_SOURCEFILES += mac.c sicslowmac.c
APPDIRS += $(CONTIKI)/cpu/avr/radio/mac

193
cpu/avr/radio/mac/mac.c Normal file
View file

@ -0,0 +1,193 @@
/* 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 wireless
* @{
*/
/**
* \defgroup rf230mac RF230 MAC
* @{
*/
/**
* \file
* \brief The IEEE 802.15.4 (2003/2006) MAC utility functions.
*
* $Id: mac.c,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*
*/
/**
* \author
* Eric Gnoske <egnoske@gmail.com>
* Blake Leverett <bleverett@gmail.com>
* Mike Vidales <mavida404@gmail.com>
* Colin O'Flynn <coflynn@newae.com>
*
*/
/* Includes */
#include <stdlib.h>
#include <string.h>
#include "mac.h"
#include "radio.h"
#include "hal.h"
#include "tcpip.h"
#include "uip.h"
#include "sicslowpan.h"
#include "sicslowmac.h"
/* Globals */
/** \brief Interface structure for this module */
ieee_15_4_manager_t ieee15_4ManagerAddress;
//dataRequest_t dataRequestStructAddress;
/* Macros & Defines */
uint8_t msduHandle;
bool iAmCoord;
bool autoModes;
/** \brief The RF channel to use for all following transmissions and
* receptions (see 6.1.2). Allowable values are 0-26
*/
uint8_t phyCurrentChannel;
/** \brief The 64-bit address of the coordinator/router through which
* the network layer wishes to communicate.
*/
uint64_t macCoordExtendedAddress;
/** \brief The 16-bit short address assigned to the coordinator
* through which the network layer wishes to communicate. A value
* of 0xfffe indicates th the coordinator is only using it's 64-bit
* extended address. A value of 0xffff indicates that this value is
* unknown. The default value is 0xfff.
*/
uint16_t macCoordShortAddress;
/** \brief This address is the 64-bit address that will be used as
* the mechanism to provide a destination to the upper layers. The
* default value is 0xfff.
*/
uint64_t macDestAddress;
/** \brief The sequence number (0x00 - 0xff) added to the transmitted
* data or MAC command frame. The default is a random value within
* the range.
*/
uint8_t macDSN;
/** \brief The 16-bit identifier of the PAN on which the device is
* sending to. If this value is 0xffff, the device is not
* associated. The default value is 0xffff.
*/
uint16_t macDstPANId;
/** \brief The 16-bit identifier of the PAN on which the device is
* operating. If this value is 0xffff, the device is not
* associated. The default value is 0xffff.
*/
uint16_t macSrcPANId;
/** \brief The 16-bit address that the device uses to communicate in
* the PAN. If the device is the PAN coordinator, this value shall
* be chosen before a PAN is started. Otherwise, the address is
* allocated by a coordinator during association. A value of 0xfffe
* indicates that the device has associated but has not been
* allocated an address. A value of 0xffff indicates that the
* device does not have a short address. The default value is
* 0xffff.
*/
uint16_t macShortAddress;
/** \brief Our own long address. This needs to be read from EEPROM or
* other secure memory storage.
*/
uint64_t macLongAddr;
/* Implementation */
/** \brief Initializes the (quasi) 802.15.4 MAC. This function should
* be called only once on startup.
*/
void
mac_init(void)
{
volatile uint8_t buf[8];
sicslowmac_resetRequest(true);
/* Set up the radio for auto mode operation. */
hal_subregister_write( SR_MAX_FRAME_RETRIES, 2 );
/* Need to laod PANID for auto modes */
radio_set_pan_id(DEST_PAN_ID);
/* Buffer the uint64_t address for easy loading and debug. */
/** \todo Find a better location to load the IEEE address. */
buf[0] = macLongAddr & 0xFF;
buf[1] = (macLongAddr >> 8) & 0xFF;
buf[2] = (macLongAddr >> 16) & 0xFF;
buf[3] = (macLongAddr >> 24) & 0xFF;
buf[4] = (macLongAddr >> 32) & 0xFF;
buf[5] = (macLongAddr >> 40) & 0xFF;
buf[6] = (macLongAddr >> 48) & 0xFF;
buf[7] = (macLongAddr >> 56) & 0xFF;
/* Load the long address into the radio. This is required for auto mode */
/* operation. */
radio_set_extended_address((uint8_t *)&macLongAddr);
srand(1234 );
msduHandle = rand();
/* Ping6 debug */
memcpy(uip_lladdr.addr, &macLongAddr, 8);
/* Convert expected byte order */
byte_reverse((uint8_t *)uip_lladdr.addr, 8);
}
/** @} */
/** @} */

241
cpu/avr/radio/mac/mac.h Normal file
View file

@ -0,0 +1,241 @@
/* 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.
*/
/**
* \brief The equivalent IEEE 802.15.4 (2003/2006) header file for
* the mac primitives.
*
* $Id: mac.h,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*
*/
/**
* \addtogroup rf230mac
* @{
*/
/**
* \file
* \brief The IEEE 802.15.4 (2003/2006) MAC utility functions.
*/
#ifndef MAC_H
#define MAC_H
/* Includes */
#include <stdint.h>
#include <stdbool.h>
#include "frame.h"
#include "ieee-15-4-manager.h"
#define EEPROMMACADDRESS ((void*)0)
#define EEPROMDSTADDRESS ((void*)8)
#define EEPROMCHANADDRESS ((void*)16)
#define EEPROMPANIDADDRESS ((void*)17)
#define EEPROMROLEADDRESS ((void*)19)
#define SUCCESS (0)
#define CHANNEL_PAGE_0 (0)
/* MAC command frames codes */
/* MAC enumerations */
/** \brief Pre-defined data frame control field (FCF) values.
* \name FCF Values
* @{
*/
#define FCF_NO_ACK (0x8841)
#define FCF_ACK_REQ (0x8861)
/** @} */
/** \brief Hardcoded various "network" addresses, for use when testing.
* \name Pre-defined network addresses
* @{
*/
#define DEST_PAN_ID (0xABCD)
#define SOURCE_PAN_ID (0xABCD)
#define LONG_ADDR_1 (0xFFEEDDCCBBAA1100LL)
#define LONG_ADDR_2 (0x1122334455667788LL)
#define LONG_ADDR_3 (0xDDEEAADDBBEEEEFFLL)
#define LONG_ADDR_4 (0x0123456789ABCDEFLL)
#define SOURCE_ADDR (0x1234)
#define FCF_ACK (0x0002)
#define TX_OPTION_NOACK (0)
#define TX_OPTION_ACK (1)
#define LONG_ADDR_LEN (8)
/** @} */
#define MPDU_OVERHEAD (11) /**< This overhead includes FCF, DSN, DEST_PAN_ID, DEST_ADDR, SOURCE_ADDR, & FCS */
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
* \name FCF element values definitions
* @{
*/
#define BEACONFRAME (0x00)
#define DATAFRAME (0x01)
#define ACKFRAME (0x02)
#define CMDFRAME (0x03)
#define BEACONREQ (0x07)
#define IEEERESERVED (0x00)
#define NOADDR (0x00) /**< Only valid for ACK or Beacon frames. */
#define SHORTADDRMODE (0x02)
#define LONGADDRMODE (0x03)
#define NOBEACONS (0x0F)
#define BROADCASTADDR (0xFFFF)
#define BROADCASTPANDID (0xFFFF)
#define IEEE802154_2003 (0x00)
#define IEEE802154_2006 (0x01)
#define SECURITY_LEVEL_NONE (0)
#define SECURITY_LEVEL_128 (3)
#define PSDULEN (127)
/** @} */
/* typedef enum {TRUE, FALSE} bool; */
typedef struct dataRequest {
uint8_t srcAddrMode;
uint8_t dstAddrMode;
uint16_t dstPANId;
addr_t dstAddr;
uint8_t msduLength;
uint8_t *msdu;
uint8_t msduHandle;
uint8_t txOptions;
uint8_t securityLevel;
uint8_t keyIdMode;
uint8_t *keySource;
uint8_t keyIndex;
} dataRequest_t;
/* Macros & Defines */
extern ieee_15_4_manager_t ieee15_4ManagerAddress;
extern dataRequest_t dataRequestStructAddress;
#define ieee15_4Struct (&ieee15_4ManagerAddress)
#define dataRequestStruct (&dataRequestStructAddress)
/**
* \name Scan variables
* \brief Global variables and defines for scan.
* \{
*/
extern uint8_t msduHandle;
extern bool iAmCoord;
extern bool autoModes;
extern uint16_t macShortAddr;
extern uint64_t macLongAddr;
/** @} */
/* PHY PIB Attributes */
/* uint8_t phyCurrentChannel Integer 0-26
* The RF channel to use for all following transmissions and receptions (see6.1.2).
*/
extern uint8_t phyCurrentChannel;
/* uint64_t macCoordExtendedAddress -- no default
*
* The 64-bit address of the coordinator/router through which the network layer wishes to communicate
*/
extern uint64_t macCoordExtendedAddress;
/* uint16_t macCoordShortAddress -- default 0xffff
*
* The 16-bit short address assigned to the coordinator through which the network layer wishes
* to communicate. A value of 0xfffe indicates th the coordinator is only using it's 64-bit
* extended address. A value of 0xffff indicates that this value is unknown.
*/
extern uint16_t macCoordShortAddress;
/* uint64_t macDestAddress -- default 0xffff
*
* This address is the 64-bit address that will be used as the mechanism to
* provide a destination to the upper layers.
*/
extern uint64_t macDestAddress;
/* uint8_t macDSN -- default is random value within the range
*
* The sequence number (0x00 - 0xff) added to the transmitted data or MAC command frame.
*/
extern uint8_t macDSN;
/* uint16_t macDstPANId -- default 0xffff
*
* The 16-bit identifier of the PAN on which the device is sending to. If this value
* is 0xffff, the device is not associated.
*/
extern uint16_t macDstPANId;
/* uint16_t macSrcPANId -- default 0xffff
*
* The 16-bit identifier of the PAN on which the device is operating. If this value
* is 0xffff, the device is not associated.
*/
extern uint16_t macSrcPANId;
/* uint16_t macShortAddress -- default 0xffff
*
* The 16-bit address that the device uses to communicate in the PAN. If the device is the
* PAN coordinator, this value shall be chosen before a PAN is started. Otherwise, the
* address is allocated by a coordinator during association. A value of 0xfffe indicates
* that the device has associated but has not been allocated an address. A value of 0xffff
* indicates that the device does not have a short address.
*/
extern uint16_t macShortAddress;
/* Scan defines */
/* Protoypes */
void mac_init(void);
#endif
/** @} */

View file

@ -0,0 +1,488 @@
/*
* Copyright (c) 2008, 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.
*
* This file is part of the Contiki operating system.
*
* $Id: sicslowmac.c,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/**
* \file
* Example glue code between the existing MAC code and the
* Contiki mac interface
*
* \author
* Adam Dunkels <adam@sics.se>
* Eric Gnoske <egnoske@gmail.com>
* Blake Leverett <bleverett@gmail.com>
*
* \addtogroup rf230mac
*/
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include "net/rime/rimebuf.h"
#include "mac.h"
#include "frame.h"
#include "radio.h"
#include "tcpip.h"
#include "sicslowmac.h"
#include "sicslowpan.h"
#include "ieee-15-4-manager.h"
/* Macros */
#define DEBUG 0
#define MAX_EVENTS 10
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
/* Globals */
static mac_driver_t mac_driver;
static mac_driver_t *pmac_driver = &mac_driver;
extern ieee_15_4_manager_t ieee15_4ManagerAddress;
static parsed_frame_t *parsed_frame;
const mac_driver_t sicslowmac_driver = {
sicslowmac_dataRequest,
/* read_packet, */
/* set_receive_function, */
/* on, */
/* off, */
};
static struct {
uint8_t head;
uint8_t tail;
event_object_t event_object[MAX_EVENTS];
} event_queue;
/* Prototypes */
static void setinput(void (*r)(const mac_driver_t *d));
static void (*pinput)(const mac_driver_t *r);
/*---------------------------------------------------------------------------*/
/**
* \brief Checks for any pending events in the queue.
*
* \return True if there is a pending event, else false.
*/
uint8_t
mac_event_pending(void)
{
return (event_queue.head != event_queue.tail);
}
/*---------------------------------------------------------------------------*/
/**
* \brief Puts an event into the queue of events.
*
* \param object is a pointer to the event to add to queue.
*/
void
mac_put_event(event_object_t *object)
{
uint8_t newhead;
if ((event_queue.head + 1) % MAX_EVENTS == event_queue.tail){
/* queue full, get outta here */
return;
}
newhead = event_queue.head;
/* store in queue */
event_queue.event_object[newhead] = *object;
/* calculate new head index */
newhead++;
if (newhead >= MAX_EVENTS){
newhead = 0;
}
event_queue.head = newhead;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Pulls an event from the event queue.
* Assumes that there is an event in the queue. See mac_event_pending().
*
* \return Pointer to the event object, or NULL in the event of empty queue.
*/
event_object_t
*mac_get_event(void)
{
event_object_t *object = NULL;
volatile uint8_t newtail;
newtail = event_queue.tail;
object = &(event_queue.event_object[newtail]);
/* calculate new tail */
newtail++;
if (newtail >= MAX_EVENTS){
newtail = 0;
}
event_queue.tail = newtail;
return(object);
}
void mac_pollhandler(void)
{
mac_task(NULL, NULL);
}
/*---------------------------------------------------------------------------*/
/**
* \brief This is the main loop task for the MAC. Called by the
* main application loop.
*/
void
mac_task(process_event_t ev, process_data_t data)
{
/* check for event in queue */
event_object_t *event;
if(mac_event_pending()){
event = mac_get_event();
/* Handle events from radio */
if (event){
if (event->event == MAC_EVENT_RX){
/* got a frame, find out with kind of frame */
parsed_frame = (parsed_frame_t *)event->data;
if (parsed_frame->fcf->frameType == DATAFRAME){
sicslowmac_dataIndication();
}
/* Frame no longer in use */
parsed_frame->in_use = false;
}
if (event->event == MAC_EVENT_DROPPED){
/* Frame was dropped */
printf("sicslowmac: Frame Dropped!\n");
}
}
}
}
/*---------------------------------------------------------------------------*/
static void
setinput(void (*r)(const mac_driver_t *d))
{
pinput = r;
}
/*---------------------------------------------------------------------------*/
void
sicslowmac_dataIndication(void)
{
rimebuf_clear();
/* Finally, get the stuff into the rime buffer.... */
rimebuf_copyfrom(parsed_frame->payload, parsed_frame->payload_length);
rimebuf_set_datalen(parsed_frame->payload_length);
/* Change addresses to expected byte order */
byte_reverse((uint8_t *)parsed_frame->dest_addr, 8);
byte_reverse((uint8_t *)parsed_frame->src_addr, 8);
rimebuf_set_addr(RIMEBUF_ADDR_RECEIVER, (const rimeaddr_t *)parsed_frame->dest_addr);
rimebuf_set_addr(RIMEBUF_ADDR_SENDER, (const rimeaddr_t *)parsed_frame->src_addr);
PRINTF("sicslowmac: hand off frame to sicslowpan \n");
pinput(pmac_driver);
}
/*---------------------------------------------------------------------------*/
/**
* \brief This is the implementation of the 15.4 MAC Data Request
* primitive.
*
* \return Integer denoting success or failure.
* \retval 0 Failure.
* \retval 1 Success.
*
* The data request primitive creates the frame header based
* on static and dynamic data. The static data will be refined
* in phase II of the project. The frame payload and length are
* retrieved from the rime buffer and rime length respectively.
*
* When the header and payload are assembled into the
* frame_create_params structure, the frame is created
* by a call to frame_tx_create and then transmited via
* radio_send_data.
*/
/*---------------------------------------------------------------------------*/
int
sicslowmac_dataRequest(void)
{
/* create structure to store result. */
frame_create_params_t params;
frame_result_t result;
/* Save the msduHandle in a global variable. */
msduHandle = rimebuf_attr(RIMEBUF_ATTR_PACKET_ID);
/* Build the FCF. */
params.fcf.frameType = DATAFRAME;
params.fcf.securityEnabled = false;
params.fcf.framePending = false;
params.fcf.ackRequired = rimebuf_attr(RIMEBUF_ATTR_RELIABLE);
params.fcf.panIdCompression = false;
/* Insert IEEE 802.15.4 (2003) version bit. */
params.fcf.frameVersion = IEEE802154_2003;
/* Increment and set the data sequence number. */
params.seq = macDSN++;
/* Complete the addressing fields. */
/**
\todo For phase 1 the addresses are all long. We'll need a mechanism
in the rime attributes to tell the mac to use long or short for phase 2.
*/
params.fcf.srcAddrMode = LONGADDRMODE;
params.dest_pid = ieee15_4ManagerAddress.get_dst_panid();
/*
* If the output address is NULL in the Rime buf, then it is broadcast
* on the 802.15.4 network.
*/
if(rimeaddr_cmp(rimebuf_addr(RIMEBUF_ADDR_RECEIVER), &rimeaddr_null) ) {
/* Broadcast requires short address mode. */
params.fcf.destAddrMode = SHORTADDRMODE;
params.dest_pid = BROADCASTPANDID;
params.dest_addr.addr16 = BROADCASTADDR;
} else {
/* Phase 1.5 - end nodes send to anyone? */
memcpy(&params.dest_addr, (uint8_t *)rimebuf_addr(RIMEBUF_ADDR_RECEIVER), LONG_ADDR_LEN);
/* Hack to allow Ethernet to send us data, we have to limit addresses to have zero in upper */
/* two bytes */
/* params.dest_addr.addr64 &= 0x0000ffffffffffffUL; */
/* Phase 1 - end nodes only sends to pan coordinator node. */
/* params.dest_addr.addr64 = ieee15_4ManagerAddress.get_coord_long_addr(); */
params.fcf.destAddrMode = LONGADDRMODE;
}
/* Set the source PAN ID to the global variable. */
params.src_pid = ieee15_4ManagerAddress.get_src_panid();
/*
* Set up the source address using only the long address mode for
* phase 1.
*/
params.src_addr.addr64 = ieee15_4ManagerAddress.get_long_addr();
/* Copy the payload data. */
params.payload_len = rimebuf_datalen();
params.payload = rimebuf_dataptr();
/* Create transmission frame. */
frame_tx_create(&params, &result);
/* Retry up to this many times to send the packet if radio is busy */
uint8_t retry_count = 3;
while(retry_count) {
PRINTF("sicslowmac: sending packet of length %d to radio, result:", result.length);
/* Send data to radio. */
radio_status_t rv = radio_send_data(result.length, result.frame);
if (rv == RADIO_SUCCESS) {
PRINTF(" Success\n");
return 1; /* True says that the packet could be sent */
}
if (rv != RADIO_WRONG_STATE) {
PRINTF(" Failed\n");
return 0;
}
PRINTF(" Radio busy, retrying\n");
_delay_ms(10); //We have blocking delay here, it is safest this way
retry_count--;
}
PRINTF("sicslowmac: Unable to send packet, dropped\n");
return 0;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Stub function that will be implemented in phase 2 to cause
* end nodes to sleep.
*/
int
mac_wake(void)
{
return 1;
}
/*---------------------------------------------------------------------------*/
/**
* \brief Stub function that will be implemented in phase 2 to cause
* end nodes to sleep.
*/
int
mac_sleep(void)
{
return 1;
}
/*---------------------------------------------------------------------------*/
const mac_driver_t *
sicslowmac_init(const struct radio_driver *d)
{
/* AD: commented out the radio_driver code for now.*/
/* radio = d;
radio->set_receive_function(input_packet);
radio->on();*/
return &sicslowmac_driver;
}
/*---------------------------------------------------------------------------*/
/**
* \brief This is the implementation of the 15.4 MAC Reset Request
* primitive.
* \param setDefaultPIB True if the default PIB values should be set.
* \return Integer denoting success or failure.
* \retval 0 Failure.
* \retval 1 Success.
*
* Sets all PIB values to default.
*/
void
sicslowmac_resetRequest (bool setDefaultPIB)
{
if(setDefaultPIB){
/* initialize all of the MAC PIB variables to their default values */
macCoordShortAddress = 0xffff;
macDSN = rand() % 256;
macSrcPANId = SOURCE_PAN_ID;
macDstPANId = DEST_PAN_ID;
macShortAddress = 0xffff;
/* Setup the address of this device by reading a stored address from eeprom. */
/** \todo This might be read from the serial eeprom onboard Raven. */
AVR_ENTER_CRITICAL_REGION();
eeprom_read_block ((void *)&macLongAddr, EEPROMMACADDRESS, 8);
byte_reverse((uint8_t *) &macLongAddr, 8);
AVR_LEAVE_CRITICAL_REGION();
}
}
/*---------------------------------------------------------------------------*/
PROCESS(mac_process, "802.15.4 MAC process");
PROCESS_THREAD(mac_process, ev, data)
{
PROCESS_POLLHANDLER(mac_pollhandler());
PROCESS_BEGIN();
radio_status_t return_value;
/* init radio */
/** \todo: this screws up if calosc is set to TRUE, find out why? */
return_value = radio_init(false, NULL, NULL, NULL);
#if DEBUG
if (return_value == RADIO_SUCCESS) {
printf("Radio init successful.\n");
} else {
printf("Radio init failed with return: %d\n", return_value);
}
#endif
radio_set_operating_channel(24);
radio_use_auto_tx_crc(true);
radio_set_trx_state(TRX_OFF);
mac_init();
/* Set up MAC function pointers and sicslowpan callback. */
pmac_driver->set_receive_function = setinput;
pmac_driver->send = sicslowmac_dataRequest;
pmac_driver->wake = mac_wake;
pmac_driver->sleep = mac_sleep;
sicslowpan_init(pmac_driver);
ieee_15_4_init(&ieee15_4ManagerAddress);
radio_set_trx_state(RX_AACK_ON);
while(1) {
PROCESS_YIELD();
mac_task(ev, data);
}
PROCESS_END();
}
void byte_reverse(uint8_t * bytes, uint8_t num)
{
uint8_t tempbyte;
uint8_t i, j;
i = 0;
j = num - 1;
while(i < j) {
tempbyte = bytes[i];
bytes[i] = bytes[j];
bytes[j] = tempbyte;
j--;
i++;
}
return;
}

View file

@ -0,0 +1,112 @@
/*
* Copyright (c) 2008, 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.
*
* This file is part of the Contiki operating system.
*
* $Id: sicslowmac.h,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/**
* \file
* Example glue code between the existing MAC code and the
* Contiki mac interface
* \author
* Adam Dunkels <adam@sics.se>
* Eric Gnoske <egnoske@gmail.com>
* Blake Leverett <bleverett@gmail.com>
*/
/**
\addtogroup rf230mac
*/
#ifndef __SICSLOWMAC_H__
#define __SICSLOWMAC_H__
#include <stdbool.h>
#include <stdint.h>
#include "contiki.h"
#include "dev/radio.h"
/**
* The structure of a device driver for a radio in Contiki.
*/
typedef struct mac_driver_s{
/** Send a packet from the Rime buffer */
int (* send)(void);
/** Read a received packet into the Rime buffer. */
/* int (* read)(void); */
/** Set a function to be called when a packet has been received. */
void (* set_receive_function)(void (*f)(const struct mac_driver_s *d));
/** Wake the radio up. */
int (* wake)(void);
/** Put the radio to sleep. */
int (* sleep)(void);
}mac_driver_t;
/* Macros & Defines */
typedef enum {
MAC_EVENT_RX=0x10,
MAC_EVENT_ACK,
MAC_EVENT_NACK,
MAC_EVENT_SCAN,
MAC_EVENT_BEACON_REQ,
MAC_EVENT_DROPPED,
MAC_EVENT_TX
/* MAC_EVENT_TIMER */
} event_t;
typedef struct {
event_t event; /**< Event type, see event_t for details. */
uint8_t *data; /**< Associated data that goes with the event. Depends on event type. */
} event_object_t;
extern const mac_driver_t sicslowmac_driver;
/* Prototypes */
PROCESS_NAME(mac_process);
uint8_t mac_event_pending(void);
void mac_put_event(event_object_t *object);
event_object_t *mac_get_event(void);
void mac_task(process_event_t ev, process_data_t data);
uint8_t nwk_dataIndication(void);
const mac_driver_t *sicslowmac_init(const struct radio_driver *r);
/* void sicslowmac_input_packet(const struct radio_driver *d); */
int sicslowmac_dataRequest(void);
void sicslowmac_dataIndication(void);
void sicslowmac_resetRequest (bool setDefaultPIB);
int sicsloread(void);
void byte_reverse(uint8_t * bytes, uint8_t num);
#endif /* __SICSLOWMAC_H__ */

View file

@ -0,0 +1,6 @@
CONTIKI_TARGET_SOURCEFILES += radio.c hal.c frame.c
# timer.c
APPDIRS += $(CONTIKI)/cpu/avr/radio/rf230

View file

@ -0,0 +1,351 @@
/**
* @file
* @brief This file contains the register definitions for the AT86RF230.
* $Id: at86rf230_registermap.h,v 1.1 2008/10/14 09:43:40 adamdunkels 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 */

337
cpu/avr/radio/rf230/frame.c Normal file
View file

@ -0,0 +1,337 @@
/*
*
* 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.
*
* $Id: frame.c,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/*
* \brief This file is where the main functions that relate to frame
* manipulation will reside.
*/
/**
* \addtogroup wireless
* @{
*/
/**
* \defgroup frame RF230 Frame handling
* @{
*/
/**
* \file
* \brief 802.15.4 frame creation and parsing functions
*
* This file converts to and from a structure to a packed 802.15.4
* frame.
*/
/* Includes */
#if defined( __GNUC__ )
#include <avr/io.h>
#include <util/delay.h>
#else /* IAR */
#include <iom1284.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "at86rf230_registermap.h"
#include "radio.h"
#include "frame.h"
//#include "mac_event.h"
#include "mac.h"
#include "process.h"
#include "sicslowmac.h"
/* Macros & Defines */
/* Some version of radio chip need this set to 2, so define it in Makefile */
#ifndef AUTO_CRC_PADDING
#define AUTO_CRC_PADDING 0
#endif
/* Protoypes */
/* Globals */
/* Frame handling global variables. */
//FRAME_t rx_frame; /**< Structure that holds received frames. */
static uint8_t tx_frame_buffer[130];
/* Implementation */
/*----------------------------------------------------------------------------*/
/**
* \brief Creates a frame for transmission over the air. This function is
* meant to be called by a higher level function, that interfaces to a MAC.
*
* \param p Pointer to frame_create_params_t struct, which specifies the
* frame to send.
*
* \param frame_result Pointer to frame_result_t struct, which will
* receive the results of this function, a pointer to the frame
* created, and the length of the frame.
*
* \return Nothing directly, though the frame_result structure will be filled
* in with a pointer to the frame and the frame length.
*/
void
frame_tx_create(frame_create_params_t *p,frame_result_t *frame_result)
{
field_length_t flen;
uint8_t index=0;
/* init flen to zeros */
memset(&flen, 0, sizeof(field_length_t));
/* Determine lengths of each field based on fcf and other args */
if (p->fcf.destAddrMode){
flen.dest_pid_len = 2;
}
if (p->fcf.srcAddrMode){
flen.src_pid_len = 2;
}
/* Set PAN ID compression bit it src pan if matches dest pan id. */
if(p->fcf.destAddrMode == p->fcf.srcAddrMode){
p->fcf.panIdCompression = 1;
}
if (p->fcf.panIdCompression){
/* compressed header, only do dest pid */
flen.src_pid_len = 0;
}
/* determine address lengths */
switch (p->fcf.destAddrMode){
case 2: /* 16-bit address */
flen.dest_addr_len = 2;
break;
case 3: /* 64-bit address */
flen.dest_addr_len = 8;
break;
default:
break;
}
switch (p->fcf.srcAddrMode){
case 2: /* 16-bit address */
flen.src_addr_len = 2;
break;
case 3: /* 64-bit address */
flen.src_addr_len = 8;
break;
default:
break;
}
/* Aux security header */
if (p->fcf.securityEnabled){
switch (p->aux_hdr.security_control.key_id_mode){
case 0:
flen.aux_sec_len = 5; /* minimum value */
break;
case 1:
flen.aux_sec_len = 6;
break;
case 2:
flen.aux_sec_len = 10;
break;
case 3:
flen.aux_sec_len = 14;
break;
default:
break;
}
}
/* OK, now we have field lengths. Time to actually construct */
/* the outgoing frame, and store it in tx_frame_buffer */
*(uint16_t *)tx_frame_buffer = p->fcf.word_val; /* FCF */
index = 2;
tx_frame_buffer[index++] = p->seq; /* sequence number */
/* Destination PAN ID */
if (flen.dest_pid_len == 2){
*(uint16_t *)&tx_frame_buffer[index] = p->dest_pid;
index += 2;
}
/* Destination address */
switch (flen.dest_addr_len){
case 2: /* two-byte address */
*(uint16_t *)&tx_frame_buffer[index] = p->dest_addr.addr16;
index += 2;
break;
case 8: /* 8-byte address */
*(uint64_t *)&tx_frame_buffer[index] = p->dest_addr.addr64;
index += 8;
break;
case 0:
default:
break;
}
/* Source PAN ID */
if (flen.src_pid_len == 2){
*(uint16_t *)&tx_frame_buffer[index] = p->src_pid;
index += 2;
}
/* Source address */
switch (flen.src_addr_len){
case 2: /* two-byte address */
*(uint16_t *)&tx_frame_buffer[index] = p->src_addr.addr16;
index += 2;
break;
case 8: /* 8-byte address */
*(uint64_t *)&tx_frame_buffer[index] = p->src_addr.addr64;
index += 8;
break;
case 0:
default:
break;
}
/* Aux header */
if (flen.aux_sec_len){
memcpy((char *)&tx_frame_buffer[index],
(char *)&p->aux_hdr,
flen.aux_sec_len);
index += flen.aux_sec_len;
}
/* Frame payload */
memcpy((char *)&tx_frame_buffer[index],
(char *)p->payload,
p->payload_len);
index += p->payload_len;
/* return results */
frame_result->length = index + AUTO_CRC_PADDING;
frame_result->frame = tx_frame_buffer;
return;
}
/*----------------------------------------------------------------------------*/
/**
* \brief Parses an input frame. Scans the input frame to find each
* section, and stores the resulting addresses of each section in a
* parsed_frame_t structure.
*
* \param rx_frame The input data from the radio chip.
* \param pf The parsed_frame_t struct that stores a pointer to each
* section of the frame payload.
*/
void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf)
{
/* Pointer to start of AT86RF2xx frame */
uint8_t *p = rx_frame->data;
fcf_t *fcf = (fcf_t *)&rx_frame->data;
static uint8_t frame_dropped = 0;
/* Uh-oh... please don't overwrite me! */
if (pf->in_use) {
/* Only post this once when buffer is busy, otherwise you get many postings... */
if (!frame_dropped) {
event_object_t event;
event.event = MAC_EVENT_DROPPED;
event.data = NULL;
mac_put_event(&event);
process_post(&mac_process, event.event, event.data);
}
frame_dropped = 1;
return;
}
if (fcf->frameType == ACKFRAME)
return; /* Don't bother with ACK frames */
pf->fcf = (fcf_t *)p;
pf->seqNum = p+2;
p += 3; /* Skip first three bytes */
/* Destination PID, if any */
if (fcf->frameType != BEACONFRAME){ /* No destination addresses in Beacon frame */
pf->dest_pid = (uint16_t *)p;
p += 2;
/* Destination address */
pf->dest_addr = 0;
if (fcf->destAddrMode == SHORTADDRMODE ||
fcf->destAddrMode == LONGADDRMODE){
pf->dest_addr = (addr_t *)p;
/* Update pointer to account for possible missing addr field */
if (fcf->destAddrMode == SHORTADDRMODE){
p += 2;
}
if (fcf->destAddrMode == LONGADDRMODE){
p += 8;
}
}
}
/* Source PANID */
pf->src_pid = 0;
if (!fcf->panIdCompression){
pf->src_pid = (uint16_t *)p;
p += 2;
}
/* Source address */
pf->src_addr = (addr_t *)p;
if (fcf->srcAddrMode == SHORTADDRMODE){
p += 2;
}
if (fcf->srcAddrMode == LONGADDRMODE){
p += 8;
}
/* aux security header, not yet implemented */
pf->aux_sec_hdr = 0;
/* payload length */
pf->payload_length = rx_frame->length - (p - (uint8_t*)&rx_frame->data) - 2;
/* payload */
pf->payload = p;
pf->lqi = rx_frame->lqi;
pf->fcs = rx_frame->crc;
/* pass frame to sicslowmac layer */
event_object_t event;
event.event = MAC_EVENT_RX;
event.data = (uint8_t*)pf;
pf->in_use = 1;
mac_put_event(&event);
process_poll(&mac_process);
}
/** \} */
/** \} */

226
cpu/avr/radio/rf230/frame.h Normal file
View file

@ -0,0 +1,226 @@
/*
* 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 frame
* @{
*/
/**
* \file
* \brief 802.15.4 frame creation and parsing functions
*
* This file converts to and from a structure to a packed 802.15.4
* frame.
*
* $Id: frame.h,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/* Includes */
#ifndef FRAME_UTILS_H
#define FRAME_UTILS_H
#include "hal.h"
/* Macros & Defines */
/**
* \brief Defines the bitfields of the frame control field (FCF).
*/
typedef union{
/** \brief Structure of bitfields for the FCF */
struct{
uint8_t frameType : 3; /**< Frame type field, see 802.15.4 */
bool securityEnabled : 1; /**< True if security is used in this frame */
bool framePending : 1; /**< True if sender has more data to send */
bool ackRequired : 1; /**< Is an ack frame required? */
bool panIdCompression : 1; /**< Is this a compressed header? */
uint8_t reserved : 3; /**< Unused bits */
uint8_t destAddrMode : 2; /**< Destination address mode, see 802.15.4 */
uint8_t frameVersion : 2; /**< 802.15.4 frame version */
uint8_t srcAddrMode : 2; /**< Source address mode, see 802.15.4 */
};
uint16_t word_val; /**< A word-wide value for the entire FCF */
}fcf_t;
/**
* \brief Structure that contains the lengths of the various addressing and security fields
* in the 802.15.4 header. This structure is used in \ref frame_tx_create()
*/
typedef struct{
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
uint8_t src_addr_len; /**< Length (in bytes) of source address field */
uint8_t aux_sec_len; /**< Length (in bytes) of aux security header field */
} field_length_t;
/** \brief 802.15.4 security control bitfield. See section 7.6.2.2.1 in 802.15.4 specification */
typedef struct{
uint8_t security_level : 3; /**< security level */
uint8_t key_id_mode : 2; /**< Key identifier mode */
uint8_t reserved : 3; /**< Reserved bits */
} scf_t;
/** \brief 802.15.4 Aux security header */
typedef struct{
scf_t security_control; /**< Security control bitfield */
uint32_t frame_counter; /**< Frame counter, used for security */
uint8_t key[9]; /**< The key itself, or an index to the key */
} aux_hdr_t;
/**
* @brief Some constants for frame length calculations.
* The IEEE 802.15.4 frame has a number of constant/fixed fields that
* can be counted to make frame construction and max payload
* calculations easier.
*
* These include:
* 1. FCF - 2 bytes - Fixed
* 2. Sequence number - 1 byte - Fixed
* 3. Addressing fields - 4 - 20 bytes - Variable
* 4. Aux security header - 0 - 14 bytes - Variable
* 5. CRC - 2 bytes - Fixed
*/
#define FIXEDFRAMEOVERHEAD (5)
/** \brief A union of short and long address types. Although a node can have
* both long and short addresses a frame will contain
* only one of these. Therefore, a union is appropriate here. */
typedef union{
uint16_t shortAddr; /**< Short address, two bytes */
uint64_t longAddr; /**< Long address, eight bytes */
}ADDR_SIZE_SPEC_t;
/** \brief Structure containing a PAN ID and an address */
typedef struct{
uint16_t panId; /**< PAN ID */
ADDR_SIZE_SPEC_t addrSpec; /**< A short or long address */
}PAN_ID_ADDR_SPEC_t;
/** \brief Structure containing both source and destination addresses */
typedef struct{
PAN_ID_ADDR_SPEC_t destAddrFields; /**< Destination address */
PAN_ID_ADDR_SPEC_t srcAddrFields; /**< Source address */
}ADDR_FIELD_SPEC_t;
/** \brief Union of both short and long addresses */
typedef union{
uint16_t addr16; /**< Short address */
uint64_t addr64; /**< Long address */
} addr_t;
/** \brief Strucure used to return that status of the frame create process.
* See frame_tx_create() function.*/
typedef struct{
uint8_t *frame; /**< Pointer to created frame */
uint8_t length; /**< Length (in bytes) of created frame */
} frame_result_t;
/** \brief Parameters used by the frame_tx_create() function. These
* parameters are used in the 802.15.4 frame header. See the 802.15.4
* specification for details.
*/
typedef struct{
fcf_t fcf; /**< Frame control field */
uint8_t seq; /**< Sequence number */
uint16_t dest_pid; /**< Destination PAN ID */
addr_t dest_addr; /**< Destination address */
uint16_t src_pid; /**< Source PAN ID */
addr_t src_addr; /**< Source address */
aux_hdr_t aux_hdr; /**< Aux security header */
uint8_t *payload; /**< Pointer to 802.15.4 frame payload */
uint8_t payload_len; /**< Length of payload field */
} frame_create_params_t;
/**
* \brief 802.15.4 frame structure, including the LQI, RSSI, and frame time
* fields.
*/
/* typedef struct{ */
/* fcf_t fcf; /\**< The FCF of the frame. *\/ */
/* uint8_t seqNum; /\**< The sequence number of the frame. *\/ */
/* uint16_t dest_pid; /\**< Destination PAN ID. *\/ */
/* addr_t dest_addr; /\**< Destination address. *\/ */
/* uint16_t src_pid; /\**< PAN ID *\/ */
/* addr_t src_addr; /\**< Source address *\/ */
/* uint8_t aux_sec_hdr[14]; /\**< 802.15.4 Aux security header *\/ */
/* uint8_t payload_length; /\**< Length of payload section of frame *\/ */
/* uint8_t payload[118]; /\**< Frame payload *\/ */
/* uint8_t lqi; /\**< Link quality indication value *\/ */
/* uint8_t rssi; /\**< Received signal strength indication value *\/ */
/* uint32_t time; /\**< Time stamp of received frame *\/ */
/* bool fcs:1; /\**< True if checksum has passed *\/ */
/* bool in_use:1; /\**< Is this frame struct being used? *\/ */
/* }FRAME_t; */
typedef struct{
fcf_t * fcf; /**< The FCF of the frame. */
uint8_t * seqNum; /**< The sequence number of the frame. */
uint16_t * dest_pid; /**< Destination PAN ID. */
addr_t * dest_addr; /**< Destination address. */
uint16_t * src_pid; /**< PAN ID */
addr_t * src_addr; /**< Source address */
uint8_t * aux_sec_hdr; /**< 802.15.4 Aux security header */
uint8_t * payload; /**< Frame payload */
uint8_t payload_length; /**< Length of payload section of frame */
uint8_t lqi; /**< Link quality indication value */
uint8_t rssi; /**< Received signal strength indication value */
uint32_t time; /**< Time stamp of received frame */
bool fcs:1; /**< True if checksum has passed */
bool in_use:1; /**< Is this frame struct being used? */
} parsed_frame_t;
/* Globals */
//extern FRAME_t rx_frame;
/* Protoypes */
void frame_tx_create(frame_create_params_t *p,frame_result_t *frame_result);
void frame_rx_callback(uint16_t data);
void rx_frame_parse(hal_rx_frame_t *rx_frame, parsed_frame_t *pf);
/** @} */
#endif /* FRAME_UTILS_H */

729
cpu/avr/radio/rf230/hal.c Normal file
View file

@ -0,0 +1,729 @@
/* 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.
*
* $Id: hal.c,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
/**
* \addtogroup wireless
* @{
*/
/**
* \defgroup hal RF230 hardware level drivers
* @{
*/
/**
* \file
* This file contains low-level radio driver code.
*/
/*============================ INCLUDE =======================================*/
#include <stdlib.h>
#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.
*
* \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; /* Store 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 */
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;
/*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)){
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){
if(trx_end_callback != NULL){
trx_end_callback(isr_timestamp);
}
} else if (interrupt_source & HAL_TRX_UR_MASK){
;
} else if (interrupt_source & HAL_PLL_UNLOCK_MASK){
;
} else if (interrupt_source & HAL_PLL_LOCK_MASK){
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. */
} else {
;
}
}
# 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*/

321
cpu/avr/radio/rf230/hal.h Normal file
View file

@ -0,0 +1,321 @@
/* 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 2008/10/14 09:43:40 adamdunkels Exp $
*/
#ifndef HAL_AVR_H
#define HAL_AVR_H
/*============================ INCLUDE =======================================*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/crc16.h>
#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 */
#define RAVEN_D 0
#define RAVENUSB_C 1
#if 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 "RAVEN 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
#define RADIO_VECT TIMER1_CAPT_vect
#define HAL_ENABLE_RADIO_INTERRUPT( ) ( TIMSK1 |= ( 1 << ICIE1 ) )
#define HAL_DISABLE_RADIO_INTERRUPT( ) ( TIMSK1 &= ~( 1 << ICIE1 ) )
#define HAL_ENABLE_OVERFLOW_INTERRUPT( ) ( TIMSK1 |= ( 1 << TOIE1 ) )
#define HAL_DISABLE_OVERFLOW_INTERRUPT( ) ( TIMSK1 &= ~( 1 << TOIE1 ) )
/** This macro will protect the following code from interrupts.*/
#define AVR_ENTER_CRITICAL_REGION( ) {uint8_t volatile saved_sreg = SREG; cli( )
/** This macro must always be used in conjunction with AVR_ENTER_CRITICAL_REGION
so that interrupts are enabled again.*/
#define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;}
/** \brief Enable the interrupt from the radio transceiver.
*/
#define hal_enable_trx_interrupt( ) HAL_ENABLE_RADIO_INTERRUPT( )
/** \brief Disable the interrupt from the radio transceiver.
*
* \retval 0 if the pin is low, 1 if the pin is high.
*/
#define hal_disable_trx_interrupt( ) HAL_DISABLE_RADIO_INTERRUPT( )
/*============================ TYPDEFS =======================================*/
/*============================ PROTOTYPES ====================================*/
/*============================ MACROS ========================================*/
/** \name Macros for radio operation.
* \{
*/
#define HAL_BAT_LOW_MASK ( 0x80 ) /**< Mask for the BAT_LOW interrupt. */
#define HAL_TRX_UR_MASK ( 0x40 ) /**< Mask for the TRX_UR interrupt. */
#define HAL_TRX_END_MASK ( 0x08 ) /**< Mask for the TRX_END interrupt. */
#define HAL_RX_START_MASK ( 0x04 ) /**< Mask for the RX_START interrupt. */
#define HAL_PLL_UNLOCK_MASK ( 0x02 ) /**< Mask for the PLL_UNLOCK interrupt. */
#define HAL_PLL_LOCK_MASK ( 0x01 ) /**< Mask for the PLL_LOCK interrupt. */
#define HAL_MIN_FRAME_LENGTH ( 0x03 ) /**< A frame should be at least 3 bytes. */
#define HAL_MAX_FRAME_LENGTH ( 0x7F ) /**< A frame should no more than 127 bytes. */
/** \} */
/*============================ TYPDEFS =======================================*/
/** \struct hal_rx_frame_t
* \brief This struct defines the rx data container.
*
* \see hal_frame_read
*/
typedef struct{
uint8_t length; /**< Length of frame. */
uint8_t data[ HAL_MAX_FRAME_LENGTH ]; /**< Actual frame data. */
uint8_t lqi; /**< LQI value for received frame. */
bool crc; /**< Flag - did CRC pass for received frame? */
} hal_rx_frame_t;
/** RX_START event handler callback type. Is called with timestamp in IEEE 802.15.4 symbols and frame length. See hal_set_rx_start_event_handler(). */
typedef void (*hal_rx_start_isr_event_handler_t)(uint32_t const isr_timestamp, uint8_t const frame_length);
/** RRX_END event handler callback type. Is called with timestamp in IEEE 802.15.4 symbols and frame length. See hal_set_trx_end_event_handler(). */
typedef void (*hal_trx_end_isr_event_handler_t)(uint32_t const isr_timestamp);
typedef void (*rx_callback_t) (uint16_t data);
/*============================ PROTOTYPES ====================================*/
void hal_init( void );
void hal_reset_flags( void );
uint8_t hal_get_bat_low_flag( void );
void hal_clear_bat_low_flag( void );
hal_trx_end_isr_event_handler_t hal_get_trx_end_event_handler( void );
void hal_set_trx_end_event_handler( hal_trx_end_isr_event_handler_t trx_end_callback_handle );
void hal_clear_trx_end_event_handler( void );
hal_rx_start_isr_event_handler_t hal_get_rx_start_event_handler( void );
void hal_set_rx_start_event_handler( hal_rx_start_isr_event_handler_t rx_start_callback_handle );
void hal_clear_rx_start_event_handler( void );
uint8_t hal_get_pll_lock_flag( void );
void hal_clear_pll_lock_flag( void );
uint8_t hal_register_read( uint8_t address );
void hal_register_write( uint8_t address, uint8_t value );
uint8_t hal_subregister_read( uint8_t address, uint8_t mask, uint8_t position );
void hal_subregister_write( uint8_t address, uint8_t mask, uint8_t position,
uint8_t value );
void hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback);
void hal_frame_write( uint8_t *write_buffer, uint8_t length );
void hal_sram_read( uint8_t address, uint8_t length, uint8_t *data );
void hal_sram_write( uint8_t address, uint8_t length, uint8_t *data );
#endif
/** @} */
/*EOF*/

1373
cpu/avr/radio/rf230/radio.c Normal file

File diff suppressed because it is too large Load diff

219
cpu/avr/radio/rf230/radio.h Normal file
View file

@ -0,0 +1,219 @@
/* 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: radio.h,v 1.1 2008/10/14 09:43:40 adamdunkels Exp $
*/
#ifndef RADIO_H
#define RADIO_H
/*============================ INCLUDE =======================================*/
#include <stdint.h>
#include <stdbool.h>
#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)
/*============================ 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 ====================================*/
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);
#define delay_us( us ) ( _delay_loop_2( ( F_CPU / 4000000UL ) * ( us ) ) )
#endif
/** @} */
/*EOF*/