diff --git a/drivers/at86rf231/at86rf231.c b/drivers/at86rf231/at86rf231.c index 5bba3ebb90d607be2491bfb8b55d87c334e93f81..aa2a42f20dd4a932dd305d4943279df41166c031 100644 --- a/drivers/at86rf231/at86rf231.c +++ b/drivers/at86rf231/at86rf231.c @@ -1,5 +1,4 @@ /* - * at86rf231.c - Implementation of at86rf231 functions. * Copyright (C) 2013 Alaeddine Weslati <alaeddine.weslati@inria.fr> * * This file is subject to the terms and conditions of the GNU Lesser @@ -7,15 +6,12 @@ * directory for more details. */ -#include "kernel_types.h" -#include "transceiver.h" - /** * @ingroup drivers_at86rf231 * @{ * - * @file at86rf231.c - * @brief Driver implementation for at86rf231 chip + * @file + * @brief Driver implementation of the AT86RF231 device driver * * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> @@ -24,8 +20,13 @@ */ #include "at86rf231.h" -#include "at86rf231_arch.h" #include "at86rf231_spi.h" +#include "board.h" +#include "periph/gpio.h" +#include "periph/spi.h" +#include "kernel_types.h" +#include "transceiver.h" +#include "vtimer.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -37,6 +38,11 @@ static uint64_t radio_address_long; uint8_t driver_state; +uint8_t at86rf231_get_status(void); +void at86rf231_gpio_spi_interrupts_init(void); +void at86rf231_reset(void); + + void at86rf231_init(kernel_pid_t tpid) { transceiver_pid = tpid; @@ -71,7 +77,8 @@ void at86rf231_init(kernel_pid_t tpid) void at86rf231_switch_to_rx(void) { - at86rf231_disable_interrupts(); + gpio_irq_disable(AT86RF231_INT); + // Send a FORCE TRX OFF command at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__FORCE_TRX_OFF); @@ -82,7 +89,7 @@ void at86rf231_switch_to_rx(void) at86rf231_reg_read(AT86RF231_REG__IRQ_STATUS); // Enable IRQ interrupt - at86rf231_enable_interrupts(); + gpio_irq_enable(AT86RF231_INT); // Start RX at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__RX_ON); @@ -104,8 +111,10 @@ void at86rf231_switch_to_rx(void) while ((status & AT86RF231_TRX_STATUS_MASK__TRX_STATUS) != AT86RF231_TRX_STATUS__RX_ON); } -void at86rf231_rx_irq(void) +void at86rf231_rx_irq(void *arg) { + (void)arg; + /* check if we are in sending state */ if (driver_state == AT_DRIVER_STATE_SENDING) { /* Read IRQ to clear it */ @@ -202,3 +211,51 @@ void at86rf231_set_monitor(uint8_t mode) (void) mode; // TODO } + +void at86rf231_gpio_spi_interrupts_init(void) +{ + /* SPI init */ + spi_init_master(AT86RF231_SPI, SPI_CONF_FIRST_RISING, SPI_SPEED_5MHZ); + /* IRQ0 */ + gpio_init_int(AT86RF231_INT, GPIO_NOPULL, GPIO_RISING, at86rf231_rx_irq, NULL); + /* CS */ + gpio_init_out(AT86RF231_CS, GPIO_NOPULL); + /* SLEEP */ + gpio_init_out(AT86RF231_SLEEP, GPIO_NOPULL); + /* RESET */ + gpio_init_out(AT86RF231_RESET, GPIO_NOPULL); +} + +void at86rf231_reset(void) +{ + /* force reset */ + gpio_clear(AT86RF231_RESET); + + /* put pins to default values */ + gpio_set(AT86RF231_CS); + gpio_clear(AT86RF231_SLEEP); + + /* additional waiting to comply to min rst pulse width */ + uint8_t delay = 50; + while (delay--){} + + gpio_set(AT86RF231_RESET); + + /* Send a FORCE TRX OFF command */ + at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__FORCE_TRX_OFF); + + /* busy wait for TRX_OFF state */ + uint8_t status; + uint8_t max_wait = 100; + + do { + status = at86rf231_get_status(); + + if (!--max_wait) { + printf("at86rf231 : ERROR : could not enter TRX_OFF mode\n"); + break; + } + } while ((status & AT86RF231_TRX_STATUS_MASK__TRX_STATUS) + != AT86RF231_TRX_STATUS__TRX_OFF); +} + diff --git a/drivers/at86rf231/at86rf231_rx.c b/drivers/at86rf231/at86rf231_rx.c index 469e531477c3d7080b32b3d9ba9f438cac7fefea..725310c0be9d7f8d9a882a30a87e20fb40a05029 100644 --- a/drivers/at86rf231/at86rf231_rx.c +++ b/drivers/at86rf231/at86rf231_rx.c @@ -6,8 +6,20 @@ * directory for more details. */ +/** + * @ingroup drivers_at86rf231 + * @{ + * + * @file + * @brief RX related functionality for the AT86RF231 device driver + * + * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> + * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * @} + */ + #include "at86rf231.h" -#include "at86rf231_arch.h" #include "at86rf231_spi.h" #include "kernel_types.h" diff --git a/drivers/at86rf231/at86rf231_spi.c b/drivers/at86rf231/at86rf231_spi.c index d72d74c33af9b60ab6c77ce8f5c09ce452b1e07a..73c25bb0284266f61e7d7884d184def9104d68af 100644 --- a/drivers/at86rf231/at86rf231_spi.c +++ b/drivers/at86rf231/at86rf231_spi.c @@ -6,68 +6,72 @@ * directory for more details. */ +/** + * @ingroup drivers_at86rf231 + * @{ + * + * @file + * @brief Register access functions for the AT86RF231 device driver + * + * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> + * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * @} + */ + #include "at86rf231_spi.h" -#include "at86rf231_arch.h" #include "at86rf231.h" +#include "board.h" +#include "periph/spi.h" +#include "periph/gpio.h" void at86rf231_reg_write(uint8_t addr, uint8_t value) { - // Start the SPI transfer - at86rf231_spi_select(); - - // Send first byte being the command and address - at86rf231_spi_transfer_byte(AT86RF231_ACCESS_REG | AT86RF231_ACCESS_WRITE | addr); - - // Send value - at86rf231_spi_transfer_byte(value); - - // End the SPI transfer - at86rf231_spi_unselect(); + /* Start the SPI transfer */ + gpio_clear(AT86RF231_CS); + /* write to register */ + spi_transfer_reg(AT86RF231_SPI, AT86RF231_ACCESS_REG | AT86RF231_ACCESS_WRITE | addr, value, 0); + /* End the SPI transfer */ + gpio_set(AT86RF231_CS); } uint8_t at86rf231_reg_read(uint8_t addr) { - uint8_t value; - - // Start the SPI transfer - at86rf231_spi_select(); - - // Send first byte being the command and address - at86rf231_spi_transfer_byte(AT86RF231_ACCESS_REG | AT86RF231_ACCESS_READ | addr); - - // Send value - value = at86rf231_spi_transfer_byte(0); - - // End the SPI transfer - at86rf231_spi_unselect(); - - return value; + char value; + + /* Start the SPI transfer */ + gpio_clear(AT86RF231_CS); + /* read from register */ + spi_transfer_reg(AT86RF231_SPI, AT86RF231_ACCESS_REG | AT86RF231_ACCESS_READ | addr, 0, &value); + /* End the SPI transfer */ + gpio_set(AT86RF231_CS); + return (uint8_t)value; } void at86rf231_read_fifo(uint8_t *data, radio_packet_length_t length) { - // Start the SPI transfer - at86rf231_spi_select(); - - // Send Frame Buffer Write access - at86rf231_spi_transfer_byte(AT86RF231_ACCESS_FRAMEBUFFER | AT86RF231_ACCESS_READ); - - at86rf231_spi_transfer(0, data, length); - - // End the SPI transfer - at86rf231_spi_unselect(); + /* Start the SPI transfer */ + gpio_clear(AT86RF231_CS); + /* Read a number of bytes from the devices frame buffer */ + spi_transfer_regs(AT86RF231_SPI, AT86RF231_ACCESS_FRAMEBUFFER | AT86RF231_ACCESS_READ, + 0, (char*)data, length); + /* End the SPI transfer */ + gpio_set(AT86RF231_CS); } void at86rf231_write_fifo(const uint8_t *data, radio_packet_length_t length) { - // Start the SPI transfer - at86rf231_spi_select(); - - // Send Frame Buffer Write access - at86rf231_spi_transfer_byte(AT86RF231_ACCESS_FRAMEBUFFER | AT86RF231_ACCESS_WRITE); - - at86rf231_spi_transfer(data, 0, length); + /* Start the SPI transfer */ + gpio_clear(AT86RF231_CS); + /* Send Frame Buffer Write access */ + spi_transfer_regs(AT86RF231_SPI, AT86RF231_ACCESS_FRAMEBUFFER | AT86RF231_ACCESS_WRITE, + (char*)data, 0, length); + /* End the SPI transfer */ + gpio_set(AT86RF231_CS); +} - // End the SPI transfer - at86rf231_spi_unselect(); +uint8_t at86rf231_get_status(void) +{ + return at86rf231_reg_read(AT86RF231_REG__TRX_STATUS) + & AT86RF231_TRX_STATUS_MASK__TRX_STATUS; } diff --git a/drivers/at86rf231/at86rf231_tx.c b/drivers/at86rf231/at86rf231_tx.c index 8f7072093753c21871f28cfaab58f45f64ca5e5c..1d1068c1e6e3c06e2dc2697951ec0c015992a245 100644 --- a/drivers/at86rf231/at86rf231_tx.c +++ b/drivers/at86rf231/at86rf231_tx.c @@ -6,9 +6,22 @@ * directory for more details. */ +/** + * @ingroup drivers_at86rf231 + * @{ + * + * @file + * @brief RX related functionality for the AT86RF231 device driver + * + * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> + * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> + * + * @} + */ + #include "at86rf231.h" -#include "at86rf231_arch.h" #include "at86rf231_spi.h" +#include "vtimer.h" #define ENABLE_DEBUG (0) #include "debug.h" diff --git a/drivers/at86rf231/include/at86rf231_arch.h b/drivers/at86rf231/include/at86rf231_arch.h deleted file mode 100644 index ec19ee23f3f1588b89751fdcd74c812202b8d80c..0000000000000000000000000000000000000000 --- a/drivers/at86rf231/include/at86rf231_arch.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef AT86RF231_ARCH_H_ -#define AT86RF231_ARCH_H_ - -#include <stdint.h> - -#include "vtimer.h" - -void at86rf231_gpio_spi_interrupts_init(void); - -void at86rf231_reset(void); -uint8_t at86rf231_get_status(void); - -void at86rf231_spi_select(void); -void at86rf231_spi_unselect(void); - -void at86rf231_spi_transfer(const uint8_t *data_out, uint8_t *data_in, radio_packet_length_t length); -uint8_t at86rf231_spi_transfer_byte(uint8_t byte); - -void at86rf231_init_interrupts(void); -void at86rf231_enable_interrupts(void); -void at86rf231_disable_interrupts(void); -#endif diff --git a/drivers/at86rf231/include/at86rf231_spi.h b/drivers/at86rf231/include/at86rf231_spi.h index 6ddae54960c2cf56a1f7ef7db0e002002d34e1ea..da01aa77e19f437f4c2d983dee9e501719bd05dd 100644 --- a/drivers/at86rf231/include/at86rf231_spi.h +++ b/drivers/at86rf231/include/at86rf231_spi.h @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup drivers_at86rf231 + * @{ + * + * @file + * @brief Register access function definitions for the AT86RF231 device driver + * + * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> + * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> + */ + #ifndef AT86RF231_SPI_H_ #define AT86RF231_SPI_H_ @@ -10,4 +29,8 @@ void at86rf231_reg_write(uint8_t addr, uint8_t value); void at86rf231_read_fifo(uint8_t *data, radio_packet_length_t length); void at86rf231_write_fifo(const uint8_t *data, radio_packet_length_t length); -#endif + +uint8_t at86rf231_get_status(void); + +#endif /* AT86RF231_SPI_H_ */ +/** @} */ diff --git a/drivers/include/at86rf231.h b/drivers/include/at86rf231.h index 64fc0475d194b462da2b25dce4ed3e85e18b17e0..36a4b1426be02e53e7f61757cf7cfca2f5961b43 100644 --- a/drivers/include/at86rf231.h +++ b/drivers/include/at86rf231.h @@ -6,6 +6,19 @@ * directory for more details. */ +/** + * @defgroup drivers_at86rf231 + * @ingroup drivers + * @brief Device driver for the Atmel AT86RF231 radio + * @{ + * + * @file + * @brief Interface definition for the AT86RF231 device driver + * + * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> + * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> + */ + #ifndef AT86RF231_H_ #define AT86RF231_H_ @@ -13,21 +26,20 @@ #include <stdint.h> #include "kernel_types.h" - #include "board.h" #include "radio/types.h" - #include "ieee802154_frame.h" - #include "at86rf231/at86rf231_settings.h" +#include "periph/gpio.h" -#define AT86RF231_MAX_PKT_LENGTH 127 -#define AT86RF231_MAX_DATA_LENGTH 118 +#define AT86RF231_MAX_PKT_LENGTH 127 +#define AT86RF231_MAX_DATA_LENGTH 118 /** * Structure to represent a at86rf231 packet. */ -typedef struct __attribute__((packed)) +typedef struct __attribute__((packed)) /* TODO: do we need the packed here? it leads to an + unaligned pointer -> trouble for M0 systems... */ { /* @{ */ uint8_t length; /** < the length of the frame of the frame including fcs*/ @@ -53,10 +65,10 @@ extern volatile kernel_pid_t transceiver_pid; extern uint8_t driver_state; void at86rf231_init(kernel_pid_t tpid); -//void at86rf231_reset(void); +/* void at86rf231_reset(void); */ void at86rf231_rx(void); void at86rf231_rx_handler(void); -void at86rf231_rx_irq(void); +void at86rf231_rx_irq(void *arg); int16_t at86rf231_send(at86rf231_packet_t *packet); @@ -84,4 +96,5 @@ enum { extern at86rf231_packet_t at86rf231_rx_buffer[AT86RF231_RX_BUF_SIZE]; -#endif +#endif /* AT86RF231_H_ */ +/** @} */ diff --git a/drivers/include/at86rf231/at86rf231_settings.h b/drivers/include/at86rf231/at86rf231_settings.h index ab427bd6f1170df243ce587ff82d67e5a32e4170..56ccdac04fbfa598198551fdc09c25e8c1eaa755 100644 --- a/drivers/include/at86rf231/at86rf231_settings.h +++ b/drivers/include/at86rf231/at86rf231_settings.h @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2014 INRIA + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_at86rf231 + * @{ + * + * @file + * @brief Register and command definitions for the AT86RF231 radio + * + * @author Alaeddine Weslati <alaeddine.weslati@inria.fr> + */ + #ifndef AT86AT86RF231_SETTINGS_H #define AT86AT86RF231_SETTINGS_H