42e4b2b02a
Bug fix for Issue #88
403 lines
16 KiB
C
403 lines
16 KiB
C
/* 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
|
|
* David Kopf dak664@embarqmail.com
|
|
* Ivan Delamer delamer@ieee.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.
|
|
*
|
|
*/
|
|
|
|
#ifndef HAL_AVR_H
|
|
#define HAL_AVR_H
|
|
/*============================ INCLUDE =======================================*/
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
//#include <util/crc16.h>
|
|
#include "contiki-conf.h"
|
|
/*============================ MACROS ========================================*/
|
|
|
|
/** \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 platform types/revisions here. */
|
|
// Don't use zero, it will match if undefined!
|
|
// RAVEN_D : Raven kit with LCD display
|
|
// RAVENUSB_C : used for RZRAVEN USB key
|
|
// RCB_B : RZ200 kit from Atmel based on 1281V
|
|
// ZIGBIT : Zigbit module from Meshnetics
|
|
// ATMEGA128RFA1 : Bare chip with internal radio
|
|
// IRIS : IRIS Mote from MEMSIC
|
|
#define RAVENUSB_C 1
|
|
#define RAVEN_D 2
|
|
#define RCB_B 3
|
|
#define ZIGBIT 4
|
|
#define IRIS 5
|
|
#define ATMEGA128RFA1 6
|
|
|
|
#if PLATFORM_TYPE == RCB_B
|
|
/* 1281 rcb */
|
|
# define SSPORT B
|
|
# define SSPIN (0x00)
|
|
# define SPIPORT B
|
|
# define MOSIPIN (0x02)
|
|
# define MISOPIN (0x03)
|
|
# define SCKPIN (0x01)
|
|
# define RSTPORT B
|
|
# define RSTPIN (0x05)
|
|
# define IRQPORT D
|
|
# define IRQPIN (0x04)
|
|
# define SLPTRPORT B
|
|
# define SLPTRPIN (0x04)
|
|
|
|
#elif PLATFORM_TYPE == ZIGBIT
|
|
/* 1281V Zigbit */
|
|
# define SSPORT B
|
|
# define SSPIN (0x00)
|
|
# define SPIPORT B
|
|
# define MOSIPIN (0x02)
|
|
# define MISOPIN (0x03)
|
|
# define SCKPIN (0x01)
|
|
# define RSTPORT A
|
|
# define RSTPIN (0x07)
|
|
# define IRQPORT E
|
|
# define IRQPIN (0x05)
|
|
# define SLPTRPORT B
|
|
# define SLPTRPIN (0x04)
|
|
|
|
|
|
#elif PLATFORM_TYPE == 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)
|
|
|
|
#elif PLATFORM_TYPE == 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)
|
|
|
|
#elif PLATFORM_TYPE == ATMEGA128RFA1
|
|
/* ATmega1281 with internal AT86RF231 radio */
|
|
# define SLPTRPORT TRXPR
|
|
# define SLPTRPIN 1
|
|
|
|
#elif CONTIKI_TARGET_MULLE
|
|
/* mulle 5.2 (TODO: move to platform specific) */
|
|
# define SSPORT 3
|
|
# define SSPIN 5
|
|
# define MOSIPORT 1
|
|
# define MOSIPIN 1
|
|
# define MISOPORT 1
|
|
# define MISOPIN 0
|
|
# define SCKPORT 3
|
|
# define SCKPIN 3
|
|
# define RSTPORT 4
|
|
# define RSTPIN 3
|
|
# define IRQPORT 8
|
|
# define IRQPIN 3
|
|
# define SLPTRPORT 0
|
|
# define SLPTRPIN 7
|
|
|
|
#elif PLATFORM_TYPE == IRIS
|
|
/* 1281 IRIS */
|
|
# define SSPORT B
|
|
# define SSPIN (0x00)
|
|
# define SPIPORT B
|
|
# define MOSIPIN (0x02)
|
|
# define MISOPIN (0x03)
|
|
# define SCKPIN (0x01)
|
|
# define RSTPORT A
|
|
# define RSTPIN (0x06)
|
|
# define IRQPORT D
|
|
# define IRQPIN (0x04)
|
|
# define SLPTRPORT B
|
|
# define SLPTRPIN (0x07)
|
|
#else
|
|
|
|
#error "PLATFORM_TYPE undefined in hal.h"
|
|
|
|
#endif
|
|
|
|
/* For architectures that have all SPI signals on the same port */
|
|
#ifndef SSPORT
|
|
#define SSPORT SPIPORT
|
|
#endif
|
|
|
|
#ifndef SCKPORT
|
|
#define SCKPORT SPIPORT
|
|
#endif
|
|
|
|
#ifndef MOSIPORT
|
|
#define MOSIPORT SPIPORT
|
|
#endif
|
|
|
|
#ifndef MISOPORT
|
|
#define MISOPORT SPIPORT
|
|
#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.
|
|
* \{
|
|
*/
|
|
#if defined(__AVR__)
|
|
#define CAT(x, y) x##y
|
|
#define DDR(x) CAT(DDR, x)
|
|
#define PORT(x) CAT(PORT, x)
|
|
#define PIN(x) CAT(PIN, x)
|
|
#endif
|
|
|
|
/* TODO: Move to CPU specific */
|
|
#if defined(CONTIKI_TARGET_MULLE)
|
|
#define CAT(x, y) x##y.BYTE
|
|
#define DDR(x) CAT(PD, x)
|
|
#define PORT(x) CAT(P, x)
|
|
#define PIN(x) CAT(P, x)
|
|
#endif
|
|
|
|
/** \} */
|
|
|
|
/**
|
|
* \name Pin macros
|
|
* \brief These macros convert the platform-specific pin defines into names and functions
|
|
* that the source code can directly use.
|
|
* \{
|
|
*/
|
|
#if defined(__AVR_ATmega128RFA1__)
|
|
|
|
#define hal_set_rst_low( ) ( TRXPR &= ~( 1 << TRXRST ) ) /**< This macro pulls the RST pin low. */
|
|
#define hal_set_rst_high( ) ( TRXPR |= ( 1 << TRXRST ) ) /**< This macro pulls the RST pin high. */
|
|
#define hal_set_slptr_high( ) ( TRXPR |= ( 1 << SLPTR ) ) /**< This macro pulls the SLP_TR pin high. */
|
|
#define hal_set_slptr_low( ) ( TRXPR &= ~( 1 << SLPTR ) ) /**< This macro pulls the SLP_TR pin low. */
|
|
#define hal_get_slptr( ) ( TRXPR & ( 1 << SLPTR ) ) /**< Read current state of the SLP_TR pin (High/Low). */
|
|
|
|
#else
|
|
#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 ) ) /**< 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 /* BUG? */) /**< 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_SCK_PIN SCKPIN /**< Data bit for SCK. */
|
|
#define HAL_MOSI_PIN MOSIPIN
|
|
#define HAL_MISO_PIN MISOPIN
|
|
#define HAL_PORT_SPI PORT( SPIPORT ) /**< The SPI module is located on PORTB. */
|
|
#define HAL_PORT_SS PORT( SSPORT )
|
|
#define HAL_PORT_SCK PORT( SCKPORT )
|
|
#define HAL_PORT_MOSI PORT( MOSIPORT ) /**< The SPI module uses GPIO might be split on different ports. */
|
|
#define HAL_PORT_MISO PORT( MISOPORT ) /**< The SPI module uses GPIO might be split on different ports. */
|
|
#define HAL_DDR_SPI DDR( SPIPORT ) /**< Data Direction Register for PORTB. */
|
|
#define HAL_DDR_SS DDR( SSPORT ) /**< Data Direction Register for MISO GPIO pin. */
|
|
#define HAL_DDR_SCK DDR( SCKPORT ) /**< Data Direction Register for MISO GPIO pin. */
|
|
#define HAL_DDR_MOSI DDR( MOSIPORT ) /**< Data Direction Register for MISO GPIO pin. */
|
|
#define HAL_DDR_MISO DDR( MISOPORT ) /**< Data Direction Register for MOSI GPIO pin. */
|
|
#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. */
|
|
#endif /* defined(__AVR_ATmega128RFA1__) */
|
|
|
|
/** \} */
|
|
|
|
|
|
#define HAL_SS_HIGH( ) (HAL_PORT_SS |= ( 1 << HAL_SS_PIN )) /**< MACRO for pulling SS high. */
|
|
#define HAL_SS_LOW( ) (HAL_PORT_SS &= ~( 1 << HAL_SS_PIN )) /**< MACRO for pulling SS low. */
|
|
|
|
#if defined(__AVR__)
|
|
|
|
#if PLATFORM_TYPE == ZIGBIT
|
|
// IRQ E5 for Zigbit example
|
|
#define RADIO_VECT INT5_vect
|
|
#define HAL_ENABLE_RADIO_INTERRUPT( ) { ( EIMSK |= ( 1 << INT5 ) ) ; EICRB |= 0x0C ; PORTE &= ~(1<<PE5); DDRE &= ~(1<<DDE5); }
|
|
#define HAL_DISABLE_RADIO_INTERRUPT( ) ( EIMSK &= ~( 1 << INT5 ) )
|
|
#else
|
|
#define RADIO_VECT TIMER1_CAPT_vect
|
|
// Raven and Jackdaw
|
|
#define HAL_ENABLE_RADIO_INTERRUPT( ) { TCCR1B = ( 1 << ICES1 ) | ( 1 << CS10 ); TIFR1 |= (1 << ICF1); TIMSK1 |= ( 1 << ICIE1 ) ; }
|
|
#define HAL_DISABLE_RADIO_INTERRUPT( ) ( TIMSK1 &= ~( 1 << ICIE1 ) )
|
|
#endif
|
|
|
|
#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 HAL_ENTER_CRITICAL_REGION( ) {uint8_t volatile saved_sreg = SREG; cli( )
|
|
|
|
/** This macro must always be used in conjunction with HAL_ENTER_CRITICAL_REGION
|
|
so that interrupts are enabled again.*/
|
|
#define HAL_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;}
|
|
|
|
#else /* MULLE */
|
|
|
|
#define HAL_ENABLE_RADIO_INTERRUPT( ) ( INT1IC.BYTE |= 1 )
|
|
#define HAL_DISABLE_RADIO_INTERRUPT( ) ( INT1IC.BYTE &= ~(1) )
|
|
|
|
#define HAL_ENABLE_OVERFLOW_INTERRUPT( ) ( TB4IC.BYTE = 1 )
|
|
#define HAL_DISABLE_OVERFLOW_INTERRUPT( ) ( TB4IC.BYTE = 0 )
|
|
|
|
/** This macro will protect the following code from interrupts.*/
|
|
#define HAL_ENTER_CRITICAL_REGION( ) MULLE_ENTER_CRITICAL_REGION( )
|
|
|
|
/** This macro must always be used in conjunction with HAL_ENTER_CRITICAL_REGION
|
|
so that interrupts are enabled again.*/
|
|
#define HAL_LEAVE_CRITICAL_REGION( ) MULLE_LEAVE_CRITICAL_REGION( )
|
|
|
|
#endif /* !__AVR__ */
|
|
|
|
|
|
/** \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;
|
|
|
|
|
|
/*============================ PROTOTYPES ====================================*/
|
|
void hal_init( void );
|
|
|
|
/* Hack for atmega128rfa1 with integrated radio. Access registers directly, not through SPI */
|
|
#if defined(__AVR_ATmega128RFA1__)
|
|
//#define hal_register_read(address) _SFR_MEM8((uint16_t)address)
|
|
#define hal_register_read(address) address
|
|
uint8_t hal_subregister_read( uint16_t address, uint8_t mask, uint8_t position );
|
|
void hal_subregister_write( uint16_t address, uint8_t mask, uint8_t position,
|
|
uint8_t value );
|
|
|
|
//#define hal_register_write(address, value) _SFR_MEM8((uint16_t)address)=value
|
|
#define hal_register_write(address, value) address=value
|
|
//#define hal_subregister_read( address, mask, position ) (_SFR_MEM8((uint16_t)address)&mask)>>position
|
|
//#define hal_subregister_read1( address, mask, position ) (address&mask)>>position
|
|
//#define hal_subregister_write( address, mask, position, value ) address=(address<<position)&mask
|
|
#else
|
|
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 );
|
|
#endif
|
|
|
|
|
|
|
|
void hal_frame_read(hal_rx_frame_t *rx_frame);
|
|
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 );
|
|
/* Number of receive buffers in RAM. */
|
|
#ifndef RF230_CONF_RX_BUFFERS
|
|
#define RF230_CONF_RX_BUFFERS 1
|
|
#endif
|
|
|
|
#endif
|
|
/** @} */
|
|
/*EOF*/
|