From 11bb09b7f81c58ca50b3a7cef52fa64a31fa0307 Mon Sep 17 00:00:00 2001 From: Alaeddine WESLATI Date: Fri, 12 Jul 2013 12:31:16 +0200 Subject: [PATCH] started adding at86rf231 driver at86rf231 TX and RX driver is using vtimer instead of hwtimer_ functions, TO CHECK vtimer debug function prototype fix --- Makefile.dep | 7 + Makefile.include | 3 + drivers/Makefile | 3 + drivers/at86rf231/Makefile | 13 ++ drivers/at86rf231/at86rf231.c | 160 +++++++++++++ drivers/at86rf231/at86rf231_rx.c | 74 ++++++ drivers/at86rf231/at86rf231_spi.c | 66 ++++++ drivers/at86rf231/at86rf231_tx.c | 106 +++++++++ drivers/at86rf231/include/at86rf231.h | 64 +++++ drivers/at86rf231/include/at86rf231_arch.h | 21 ++ .../at86rf231/include/at86rf231_settings.h | 221 ++++++++++++++++++ drivers/at86rf231/include/at86rf231_spi.h | 9 + sys/include/transceiver.h | 12 +- sys/include/vtimer.h | 2 +- sys/transceiver/transceiver.c | 102 +++++++- 15 files changed, 855 insertions(+), 8 deletions(-) create mode 100644 drivers/at86rf231/Makefile create mode 100644 drivers/at86rf231/at86rf231.c create mode 100644 drivers/at86rf231/at86rf231_rx.c create mode 100644 drivers/at86rf231/at86rf231_spi.c create mode 100644 drivers/at86rf231/at86rf231_tx.c create mode 100644 drivers/at86rf231/include/at86rf231.h create mode 100644 drivers/at86rf231/include/at86rf231_arch.h create mode 100644 drivers/at86rf231/include/at86rf231_settings.h create mode 100644 drivers/at86rf231/include/at86rf231_spi.h diff --git a/Makefile.dep b/Makefile.dep index b3f0f1ca11..9635e7346a 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -35,6 +35,13 @@ ifneq (,$(findstring cc2420,$(USEMODULE))) endif endif +ifneq (,$(findstring at86rf231,$(USEMODULE))) + ifeq (,$(findstring transceiver,$(USEMODULE))) + USEMODULE += transceiver + USEMODULE += ieee802154 + endif +endif + ifneq (,$(findstring sixlowpan,$(USEMODULE))) ifeq (,$(findstring ieee802154,$(USEMODULE))) USEMODULE += ieee802154 diff --git a/Makefile.include b/Makefile.include index 011aae4972..6b066c8d30 100644 --- a/Makefile.include +++ b/Makefile.include @@ -92,3 +92,6 @@ term: doc: make -BC $(RIOTBASE) doc + +debug: + $(DEBUGGER) $(DEBUGGER_FLAGS) diff --git a/drivers/Makefile b/drivers/Makefile index d4371e5b0b..29c950887a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -20,6 +20,9 @@ ifneq (,$(findstring cc110x,$(USEMODULE))) DIRS += cc110x endif endif +ifneq (,$(findstring at86rf231,$(USEMODULE))) + DIRS += at86rf231 +endif ifneq (,$(findstring gps_ublox,$(USEMODULE))) DIRS += gps_ublox endif diff --git a/drivers/at86rf231/Makefile b/drivers/at86rf231/Makefile new file mode 100644 index 0000000000..8c93d5b5c3 --- /dev/null +++ b/drivers/at86rf231/Makefile @@ -0,0 +1,13 @@ +INCLUDES = -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/sys/net -I$(RIOTBASE)/core/include -Iinclude/ -I$(RIOTBASE)/sys/net/ieee802154/ +MODULE =at86rf231 + +DIRS = + +all: $(BINDIR)$(MODULE).a + @for i in $(DIRS) ; do $(MAKE) -C $$i ; done ; + +include $(RIOTBASE)/Makefile.base + +clean:: + @for i in $(DIRS) ; do $(MAKE) -C $$i clean ; done ; + diff --git a/drivers/at86rf231/at86rf231.c b/drivers/at86rf231/at86rf231.c new file mode 100644 index 0000000000..8fcf119371 --- /dev/null +++ b/drivers/at86rf231/at86rf231.c @@ -0,0 +1,160 @@ +/** + * at86rf231.c - Implementation of at86rf231 functions. + * Copyright (C) 2013 Alaeddine Weslati + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include + +//#define ENABLE_DEBUG +#include + +static uint16_t radio_pan; +static uint8_t radio_channel; +static uint16_t radio_address; +static uint64_t radio_address_long; + +int transceiver_pid; + +void at86rf231_init(int tpid) +{ + transceiver_pid = tpid; + + at86rf231_gpio_spi_interrupts_init(); + + at86rf231_reset(); + + // TODO : Enable addr decode, auto ack, auto crc + // and configure security, power, channel, pan + + at86rf231_switch_to_rx(); +} + +void at86rf231_switch_to_rx(void) +{ + at86rf231_disable_interrupts(); + // Send a FORCE TRX OFF command + at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__FORCE_TRX_OFF); + + // Reset IRQ to TRX END only + at86rf231_reg_write(AT86RF231_REG__IRQ_MASK, AT86RF231_IRQ_STATUS_MASK__TRX_END); + + // Read IRQ to clear it + at86rf231_reg_read(AT86RF231_REG__IRQ_STATUS); + + // Enable IRQ interrupt + at86rf231_enable_interrupts(); + + // Start RX + at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__RX_ON); + + // wait until it is on RX_ON state + uint8_t status; + uint8_t max_wait = 100; // TODO : move elsewhere, this is in 10us + + do + { + status = at86rf231_get_status(); + + vtimer_usleep(10); + + if (!--max_wait) + { + printf("at86rf231 : ERROR : could not enter RX_ON mode"); + break; + } + } + while ((status & AT86RF231_TRX_STATUS_MASK__TRX_STATUS) != AT86RF231_TRX_STATUS__RX_ON); +} + +void at86rf231_rx_irq(void) +{ + at86rf231_rx_handler(); +} + +uint16_t at86rf231_set_address(uint16_t address) +{ + radio_address = address; + + at86rf231_reg_write(AT86RF231_REG__SHORT_ADDR_0, (uint8_t)(0x0F & radio_address)); + at86rf231_reg_write(AT86RF231_REG__SHORT_ADDR_1, (uint8_t)(radio_address >> 8)); + + return radio_address; +} + +uint16_t at86rf231_get_address(void) +{ + return radio_address; +} + +uint64_t at86rf231_set_address_long(uint64_t address) +{ + radio_address_long = address; + + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_0, (uint8_t)(0x0F & radio_address)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_1, (uint8_t)(radio_address >> 8)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_2, (uint8_t)(radio_address >> 16)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_3, (uint8_t)(radio_address >> 24)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_4, (uint8_t)(radio_address >> 32)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_5, (uint8_t)(radio_address >> 40)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_6, (uint8_t)(radio_address >> 48)); + at86rf231_reg_write(AT86RF231_REG__IEEE_ADDR_7, (uint8_t)(radio_address >> 56)); + + return radio_address_long; +} + +uint64_t at86rf231_get_address_long(void) +{ + return radio_address_long; +} + +uint16_t at86rf231_set_pan(uint16_t pan) +{ + radio_pan = pan; + + at86rf231_reg_write(AT86RF231_REG__PAN_ID_0, (uint8_t)(0x0F & radio_pan)); + at86rf231_reg_write(AT86RF231_REG__PAN_ID_1, (uint8_t)(radio_pan >> 8)); + + return radio_pan; +} + +uint16_t at86rf231_get_pan(void) +{ + return radio_pan; +} + +uint8_t at86rf231_set_channel(uint8_t channel) +{ + radio_channel = channel; + + if (channel < RF86RF231_MIN_CHANNEL || + channel > RF86RF231_MAX_CHANNEL) { + radio_channel = RF86RF231_MAX_CHANNEL; + } + + at86rf231_reg_write(AT86RF231_REG__PHY_CC_CCA, AT86RF231_PHY_CC_CCA_DEFAULT__CCA_MODE | radio_channel); + + return radio_channel; +} + +uint8_t at86rf231_get_channel(void) +{ + return radio_channel; + //return at86rf231_reg_read(AT86RF231_REG__PHY_CC_CCA) & 0x0F; +} + +void at86rf231_set_monitor(uint8_t mode) +{ + // TODO +} + +void at86rf231_swap_fcf_bytes(uint8_t *buf) +{ + uint8_t tmp; + tmp = buf[1]; + buf[1] = buf[2]; + buf[2] = tmp; +} + diff --git a/drivers/at86rf231/at86rf231_rx.c b/drivers/at86rf231/at86rf231_rx.c new file mode 100644 index 0000000000..7756e71f01 --- /dev/null +++ b/drivers/at86rf231/at86rf231_rx.c @@ -0,0 +1,74 @@ + +#include +#include + +#include +#include + +//#define ENABLE_DEBUG +#include + +at86rf231_packet_t at86rf231_rx_buffer[AT86RF231_RX_BUF_SIZE]; +uint8_t buffer[AT86RF231_RX_BUF_SIZE][AT86RF231_MAX_PKT_LENGTH]; +volatile uint8_t rx_buffer_next; + +void at86rf231_rx_handler(void) +{ + uint8_t lqi, fcs_rssi; + // read packet length + at86rf231_read_fifo(&at86rf231_rx_buffer[rx_buffer_next].length, 1); + + // read psdu, read packet with length as first byte and lqi as last byte. + uint8_t *buf = buffer[rx_buffer_next]; + at86rf231_read_fifo(buf, at86rf231_rx_buffer[rx_buffer_next].length); + + at86rf231_swap_fcf_bytes(buf); + + // read lqi which is appended after the psdu + lqi = buf[at86rf231_rx_buffer[rx_buffer_next].length-1]; + + // read fcs and rssi, from a register + fcs_rssi = at86rf231_reg_read(AT86RF231_REG__PHY_RSSI); + + // build package + at86rf231_rx_buffer[rx_buffer_next].lqi = lqi; + // RSSI has no meaning here, it should be read during packet reception. + at86rf231_rx_buffer[rx_buffer_next].rssi = fcs_rssi & 0x0F; // bit[4:0] + // bit7, boolean, 1 FCS valid, 0 FCS not valid + at86rf231_rx_buffer[rx_buffer_next].crc = (fcs_rssi >> 7) & 0x01; + + if(at86rf231_rx_buffer[rx_buffer_next].crc == 0) { + DEBUG("Got packet with invalid crc.\n"); + return; + } + + read_802154_frame(&buf[1], &at86rf231_rx_buffer[rx_buffer_next].frame, + at86rf231_rx_buffer[rx_buffer_next].length-2); + + if(at86rf231_rx_buffer[rx_buffer_next].frame.fcf.frame_type != 2) { +#ifdef ENABLE_DEBUG + print_802154_fcf_frame(&at86rf231_rx_buffer[rx_buffer_next].frame); +#endif + /* notify transceiver thread if any */ + if (transceiver_pid) { + msg_t m; + m.type = (uint16_t) RCV_PKT_AT86RF231; + m.content.value = rx_buffer_next; + msg_send_int(&m, transceiver_pid); + } + } else { +#ifdef ENABLE_DEBUG + DEBUG("GOT ACK for SEQ %u\n", at86rf231_rx_buffer[rx_buffer_next].frame.seq_nr); + print_802154_fcf_frame(&at86rf231_rx_buffer[rx_buffer_next].frame); +#endif + } + + // shift to next buffer element + if (++rx_buffer_next == AT86RF231_RX_BUF_SIZE) { + rx_buffer_next = 0; + } + + // Read IRQ to clear it + at86rf231_reg_read(AT86RF231_REG__IRQ_STATUS); +} + diff --git a/drivers/at86rf231/at86rf231_spi.c b/drivers/at86rf231/at86rf231_spi.c new file mode 100644 index 0000000000..d4dabb0cfb --- /dev/null +++ b/drivers/at86rf231/at86rf231_spi.c @@ -0,0 +1,66 @@ +#include +#include +#include + +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(); +} + +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; +} + +void at86rf231_read_fifo(uint8_t* data, uint8_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(); +} + +void at86rf231_write_fifo(const uint8_t* data, uint8_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); + + // End the SPI transfer + at86rf231_spi_unselect(); +} + diff --git a/drivers/at86rf231/at86rf231_tx.c b/drivers/at86rf231/at86rf231_tx.c new file mode 100644 index 0000000000..f141bedac3 --- /dev/null +++ b/drivers/at86rf231/at86rf231_tx.c @@ -0,0 +1,106 @@ +#include +#include + +static void at86rf231_xmit(uint8_t *data, uint8_t length); +static void at86rf231_gen_pkt(uint8_t *buf, at86rf231_packet_t *packet); + +static uint8_t sequenz_nr; + +int16_t at86rf231_send(at86rf231_packet_t *packet) +{ + // Set missing frame information + packet->frame.fcf.frame_ver = 0; + if (packet->frame.src_pan_id == packet->frame.dest_pan_id) { + packet->frame.fcf.panid_comp = 1; + } else { + packet->frame.fcf.panid_comp = 0; + } + + if(packet->frame.fcf.src_addr_m == 2) { + packet->frame.src_addr[1] = (uint8_t)(at86rf231_get_address() >> 8); + packet->frame.src_addr[0] = (uint8_t)(at86rf231_get_address() & 0xFF); + } else if (packet->frame.fcf.src_addr_m == 3) { + packet->frame.src_addr[7] = (uint8_t)(at86rf231_get_address_long() >> 56); + packet->frame.src_addr[6] = (uint8_t)(at86rf231_get_address_long() >> 48); + packet->frame.src_addr[5] = (uint8_t)(at86rf231_get_address_long() >> 40); + packet->frame.src_addr[4] = (uint8_t)(at86rf231_get_address_long() >> 32); + packet->frame.src_addr[3] = (uint8_t)(at86rf231_get_address_long() >> 24); + packet->frame.src_addr[2] = (uint8_t)(at86rf231_get_address_long() >> 16); + packet->frame.src_addr[1] = (uint8_t)(at86rf231_get_address_long() >> 8); + packet->frame.src_addr[0] = (uint8_t)(at86rf231_get_address_long() & 0xFF); + } + + packet->frame.src_pan_id = at86rf231_get_pan(); + packet->frame.seq_nr = sequenz_nr; + + sequenz_nr += 1; + + // calculate size of the frame (payload + FCS) */ + packet->length = get_802154_hdr_len(&packet->frame) + packet->frame.payload_len + 2; + + if(packet->length > AT86RF231_MAX_PKT_LENGTH) { + return -1; + } + + // FCS is added in hardware + uint8_t pkt[packet->length-2]; + + /* generate pkt */ + at86rf231_gen_pkt(pkt, packet); + + // transmit packet + at86rf231_xmit(pkt, packet->length-2); +} + +static void at86rf231_xmit(uint8_t *data, uint8_t length) +{ + // Go to state PLL_ON + at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__PLL_ON); + + // wait until it is on PLL_ON state + uint8_t status; + uint8_t max_wait = 100; // TODO : move elsewhere, this is in 10us + + do + { + status = at86rf231_get_status(); + + vtimer_usleep(10); + + if (!--max_wait) + { + printf("at86rf231 : ERROR : could not enter PLL_ON mode"); + break; + } + } + while ((status & AT86RF231_TRX_STATUS_MASK__TRX_STATUS) != AT86RF231_TRX_STATUS__PLL_ON); + + // copy the packet to the radio FIFO + at86rf231_write_fifo(data, length); + + // Start TX + at86rf231_reg_write(AT86RF231_REG__TRX_STATE, AT86RF231_TRX_STATE__TX_START); +} + +/** + * @brief Static function to generate byte array from at86rf231 packet. + * + */ +static void at86rf231_gen_pkt(uint8_t *buf, at86rf231_packet_t *packet) +{ + uint8_t index, offset; + index = init_802154_frame(&packet->frame, &buf[1]); + + // add length for at86rf231 + buf[0] = packet->length; + index++; + offset = index; + + while(index < packet->length-2) { + buf[index] = packet->frame.payload[index-offset]; + index += 1; + } + + at86rf231_swap_fcf_bytes(buf); +} + diff --git a/drivers/at86rf231/include/at86rf231.h b/drivers/at86rf231/include/at86rf231.h new file mode 100644 index 0000000000..ada890f867 --- /dev/null +++ b/drivers/at86rf231/include/at86rf231.h @@ -0,0 +1,64 @@ +#ifndef AT86RF231_H_ +#define AT86RF231_H_ + +#include +#include + +#include + +#include + +#define AT86RF231_MAX_PKT_LENGTH 127 +#define AT86RF231_MAX_DATA_LENGTH 118 + +/** + * Structure to represent a at86rf231 packet. + */ +typedef struct __attribute__ ((packed)) { + /* @{ */ + uint8_t length; /** < the length of the frame of the frame including fcs*/ + ieee802154_frame_t frame; /** < the ieee802154 frame */ + int8_t rssi; /** < the rssi value */ + uint8_t crc; /** < 1 if crc was successfull, 0 otherwise */ + uint8_t lqi; /** < the link quality indicator */ + /* @} */ +} at86rf231_packet_t; + + +void at86rf231_init(int tpid); +//void at86rf231_reset(void); +void at86rf231_rx(void); +void at86rf231_rx_handler(void); + +int16_t at86rf231_send(at86rf231_packet_t *packet); + +uint8_t at86rf231_set_channel(uint8_t channel); +uint8_t at86rf231_get_channel(void); + +uint16_t at86rf231_set_pan(uint16_t pan); +uint16_t at86rf231_get_pan(void); + +uint16_t at86rf231_set_address(uint16_t address); +uint16_t at86rf231_get_address(void); +uint64_t at86rf231_get_address_long(void); +uint64_t at86rf231_set_address_long(uint64_t address); + + +void at86rf231_set_monitor(uint8_t mode); + + + +void at86rf231_swap_fcf_bytes(uint8_t *buf); + +enum +{ + RF86RF231_MAX_TX_LENGTH = 125, + RF86RF231_MAX_RX_LENGTH = 127, + RF86RF231_MIN_CHANNEL = 11, + RF86RF231_MAX_CHANNEL = 26 +}; + +extern at86rf231_packet_t at86rf231_rx_buffer[AT86RF231_RX_BUF_SIZE]; + +#endif + diff --git a/drivers/at86rf231/include/at86rf231_arch.h b/drivers/at86rf231/include/at86rf231_arch.h new file mode 100644 index 0000000000..0a42c61a73 --- /dev/null +++ b/drivers/at86rf231/include/at86rf231_arch.h @@ -0,0 +1,21 @@ +#ifndef AT86RF231_ARCH_H_ +#define AT86RF231_ARCH_H_ + +#include + +void at86rf231_gpio_spi_interrupts_init(void); + +void at86rf231_reset(void); +uint8_t at86rf231_get_status(void); + +void at86rf231_switch_to_rx(void); + +void at86rf231_spi_select(void); +void at86rf231_spi_unselect(void); + +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_settings.h b/drivers/at86rf231/include/at86rf231_settings.h new file mode 100644 index 0000000000..183514d1b0 --- /dev/null +++ b/drivers/at86rf231/include/at86rf231_settings.h @@ -0,0 +1,221 @@ +#ifndef AT86AT86RF231_SETTINGS_H +#define AT86AT86RF231_SETTINGS_H + +#define AT86RF231_RX_BUF_SIZE 3 + +enum at86rf231_access +{ + AT86RF231_ACCESS_REG = 0x80, + AT86RF231_ACCESS_FRAMEBUFFER = 0x20, + AT86RF231_ACCESS_SRAM = 0x00, + + AT86RF231_ACCESS_READ = 0x00, + AT86RF231_ACCESS_WRITE = 0x40, +}; + +enum at86rf231_register +{ + AT86RF231_REG__TRX_STATUS = 0x01, + AT86RF231_REG__TRX_STATE = 0x02, + AT86RF231_REG__TRX_CTRL_0 = 0x03, + AT86RF231_REG__TRX_CTRL_1 = 0x04, + AT86RF231_REG__PHY_TX_PWR = 0x05, + AT86RF231_REG__PHY_RSSI = 0x06, + AT86RF231_REG__PHY_ED_LEVEL = 0x07, + AT86RF231_REG__PHY_CC_CCA = 0x08, + AT86RF231_REG__CCA_THRES = 0x09, + AT86RF231_REG__RX_CTRL = 0x0A, + AT86RF231_REG__SFD_VALUE = 0x0B, + AT86RF231_REG__TRX_CTRL_2 = 0x0C, + AT86RF231_REG__ANT_DIV = 0x0D, + AT86RF231_REG__IRQ_MASK = 0x0E, + AT86RF231_REG__IRQ_STATUS = 0x0F, + AT86RF231_REG__VREG_CTRL = 0x10, + AT86RF231_REG__BATMON = 0x11, + AT86RF231_REG__XOSC_CTRL = 0x12, + + AT86RF231_REG__RX_SYN = 0x15, + + AT86RF231_REG__XAH_CTRL_1 = 0x17, + AT86RF231_REG__FTN_CTRL = 0x18, + + AT86RF231_REG__PLL_CF = 0x1A, + AT86RF231_REG__PLL_DCU = 0x1B, + AT86RF231_REG__PART_NUM = 0x1C, + AT86RF231_REG__VERSION_NUM = 0x1D, + AT86RF231_REG__MAN_ID_0 = 0x1E, + AT86RF231_REG__MAN_ID_1 = 0x1F, + AT86RF231_REG__SHORT_ADDR_0 = 0x20, + AT86RF231_REG__SHORT_ADDR_1 = 0x21, + AT86RF231_REG__PAN_ID_0 = 0x22, + AT86RF231_REG__PAN_ID_1 = 0x23, + + AT86RF231_REG__IEEE_ADDR_0 = 0x24, + AT86RF231_REG__IEEE_ADDR_1 = 0x25, + AT86RF231_REG__IEEE_ADDR_2 = 0x26, + AT86RF231_REG__IEEE_ADDR_3 = 0x27, + AT86RF231_REG__IEEE_ADDR_4 = 0x28, + AT86RF231_REG__IEEE_ADDR_5 = 0x29, + AT86RF231_REG__IEEE_ADDR_6 = 0x2A, + AT86RF231_REG__IEEE_ADDR_7 = 0x2B, + + AT86RF231_REG__XAH_CTRL_0 = 0x2C, + AT86RF231_REG__CSMA_SEED_0 = 0x2D, + AT86RF231_REG__CSMA_SEED_1 = 0x2E, + AT86RF231_REG__CSMA_BE = 0x2F, + + + AT86RF231_REG__TST_CTRL_DIGI = 0x36, +}; + +enum +{ + AT86RF231_TRX_CTRL_0_MASK__PAD_IO = 0xC0, + AT86RF231_TRX_CTRL_0_MASK__PAD_IO_CLKM = 0x30, + AT86RF231_TRX_CTRL_0_MASK__CLKM_SHA_SEL = 0x08, + AT86RF231_TRX_CTRL_0_MASK__CLKM_CTRL = 0x07, + + AT86RF231_TRX_CTRL_0_DEFAULT__PAD_IO = 0x00, + AT86RF231_TRX_CTRL_0_DEFAULT__PAD_IO_CLKM = 0x10, + AT86RF231_TRX_CTRL_0_DEFAULT__CLKM_SHA_SEL = 0x08, + AT86RF231_TRX_CTRL_0_DEFAULT__CLKM_CTRL = 0x01, + + AT86RF231_TRX_CTRL_0_CLKM_CTRL__OFF = 0x00, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__1MHz = 0x01, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__2MHz = 0x02, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__4MHz = 0x03, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__8MHz = 0x04, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__16MHz = 0x05, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__250kHz = 0x06, + AT86RF231_TRX_CTRL_0_CLKM_CTRL__62_5kHz = 0x07, +}; + +enum +{ + AT86RF231_TRX_CTRL_1_MASK__PA_EXT_EN = 0x80, + AT86RF231_TRX_CTRL_1_MASK__IRQ_2_EXT_EN = 0x40, + AT86RF231_TRX_CTRL_1_MASK__TX_AUTO_CRC_ON = 0x20, + AT86RF231_TRX_CTRL_1_MASK__RX_BL_CTRL = 0x10, + AT86RF231_TRX_CTRL_1_MASK__SPI_CMD_MODE = 0x0C, + AT86RF231_TRX_CTRL_1_MASK__IRQ_MASK_MODE = 0x02, + AT86RF231_TRX_CTRL_1_MASK__IRQ_POLARITY = 0x01, +}; + +enum +{ + AT86RF231_TRX_CTRL_2_MASK__RX_SAFE_MODE = 0x80, + AT86RF231_TRX_CTRL_2_MASK__OQPSK_DATA_RATE = 0x03, +}; + +enum +{ + AT86RF231_IRQ_STATUS_MASK__BAT_LOW = 0x80, + AT86RF231_IRQ_STATUS_MASK__TRX_UR = 0x40, + AT86RF231_IRQ_STATUS_MASK__AMI = 0x20, + AT86RF231_IRQ_STATUS_MASK__CCA_ED_DONE = 0x10, + AT86RF231_IRQ_STATUS_MASK__TRX_END = 0x08, + AT86RF231_IRQ_STATUS_MASK__RX_START = 0x04, + AT86RF231_IRQ_STATUS_MASK__PLL_UNLOCK = 0x02, + AT86RF231_IRQ_STATUS_MASK__PLL_LOCK = 0x01, +}; + +enum at86rf231_trx_status +{ + AT86RF231_TRX_STATUS_MASK__CCA_DONE = 0x80, + AT86RF231_TRX_STATUS_MASK__CCA_STATUS = 0x40, + AT86RF231_TRX_STATUS_MASK__TRX_STATUS = 0x1F, + + AT86RF231_TRX_STATUS__P_ON = 0x00, + AT86RF231_TRX_STATUS__BUSY_RX = 0x01, + AT86RF231_TRX_STATUS__BUSY_TX = 0x02, + AT86RF231_TRX_STATUS__RX_ON = 0x06, + AT86RF231_TRX_STATUS__TRX_OFF = 0x08, + AT86RF231_TRX_STATUS__PLL_ON = 0x09, + AT86RF231_TRX_STATUS__SLEEP = 0x0F, + AT86RF231_TRX_STATUS__BUSY_RX_AACK = 0x11, + AT86RF231_TRX_STATUS__BUSY_TX_ARET = 0x12, + AT86RF231_TRX_STATUS__RX_AACK_ON = 0x16, + AT86RF231_TRX_STATUS__TX_ARET_ON = 0x19, + AT86RF231_TRX_STATUS__RX_ON_NOCLK = 0x1C, + AT86RF231_TRX_STATUS__RX_AACK_ON_NOCLK = 0x1D, + AT86RF231_TRX_STATUS__BUSY_RX_AACK_NOCLK = 0x1E, + AT86RF231_TRX_STATUS__STATE_TRANSITION_IN_PROGRESS = 0x1F, +}; + +enum at86rf231_trx_state +{ + AT86RF231_TRX_STATE__NOP = 0x00, + AT86RF231_TRX_STATE__TX_START = 0x02, + AT86RF231_TRX_STATE__FORCE_TRX_OFF = 0x03, + AT86RF231_TRX_STATE__FORCE_PLL_ON = 0x04, + AT86RF231_TRX_STATE__RX_ON = 0x06, + AT86RF231_TRX_STATE__TRX_OFF = 0x08, + AT86RF231_TRX_STATE__PLL_ON = 0x09, + AT86RF231_TRX_STATE__RX_AACK_ON = 0x16, + AT86RF231_TRX_STATE__TX_ARET_ON = 0x19, +}; + +enum at86rf231_phy_cc_cca +{ + AT86RF231_PHY_CC_CCA_MASK__CCA_REQUEST = 0x80, + AT86RF231_PHY_CC_CCA_MASK__CCA_MODE = 0x60, + AT86RF231_PHY_CC_CCA_MASK__CHANNEL = 0x1F, + + AT86RF231_PHY_CC_CCA_DEFAULT__CCA_MODE = 0x20, +}; + +enum at86rf231_phy_tx_pwr +{ + AT86RF231_PHY_TX_PWR_MASK__PA_BUF_LT = 0xC0, + AT86RF231_PHY_TX_PWR_MASK__PA_LT = 0x30, + AT86RF231_PHY_TX_PWR_MASK__TX_PWR = 0x0F, + + AT86RF231_PHY_TX_PWR_DEFAULT__PA_BUF_LT = 0xC0, + AT86RF231_PHY_TX_PWR_DEFAULT__PA_LT = 0x00, + AT86RF231_PHY_TX_PWR_DEFAULT__TX_PWR = 0x00, + + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__3dBm = 0x00, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__2_8dBm = 0x01, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__2_3dBm = 0x02, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__1_8dBm = 0x03, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__1_3dBm = 0x04, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__0_7dBm = 0x05, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__0dBm = 0x06, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m1dBm = 0x07, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m2dBm = 0x08, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m3dBm = 0x09, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m4dBm = 0x0A, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m5dBm = 0x0B, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m7dBm = 0x0C, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m9dBm = 0x0D, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m12dBm = 0x0E, + AT86RF231_PHY_TX_PWR_TX_PWR_VALUE__m17dBm = 0x0F, + +}; + +enum at86rf231_phy_rssi +{ + AT86RF231_PHY_RSSI_MASK__RX_CRC_VALID = 0x80, + AT86RF231_PHY_RSSI_MASK__RND_VALUE = 0x60, + AT86RF231_PHY_RSSI_MASK__RSSI = 0x1F, +}; + +enum at86rf231_xosc_ctrl +{ + AT86RF231_XOSC_CTRL__XTAL_MODE_CRYSTAL = 0xF0, + AT86RF231_XOSC_CTRL__XTAL_MODE_EXTERNAL = 0xF0, +}; + +enum +{ + AT86RF231_TIMING__VCC_TO_P_ON = 330, + AT86RF231_TIMING__SLEEP_TO_TRX_OFF = 380, + AT86RF231_TIMING__TRX_OFF_TO_PLL_ON = 110, + AT86RF231_TIMING__TRX_OFF_TO_RX_ON = 110, + AT86RF231_TIMING__PLL_ON_TO_BUSY_TX = 16, + + AT86RF231_TIMING__RESET = 100, + AT86RF231_TIMING__RESET_TO_TRX_OFF = 37, +}; + +#endif diff --git a/drivers/at86rf231/include/at86rf231_spi.h b/drivers/at86rf231/include/at86rf231_spi.h new file mode 100644 index 0000000000..0f3dc4d5ef --- /dev/null +++ b/drivers/at86rf231/include/at86rf231_spi.h @@ -0,0 +1,9 @@ +#ifndef AT86RF231_SPI_H_ +#define AT86RF231_SPI_H_ + +#include + +uint8_t at86rf231_reg_read(uint8_t addr); +void at86rf231_reg_write(uint8_t addr, uint8_t value); + +#endif diff --git a/sys/include/transceiver.h b/sys/include/transceiver.h index 979b5bf7c1..fb7cc5c4e3 100644 --- a/sys/include/transceiver.h +++ b/sys/include/transceiver.h @@ -27,11 +27,12 @@ /** * @brief All supported transceivers */ -#define TRANSCEIVER_NONE (0x0) ///< Invalid -#define TRANSCEIVER_CC1100 (0x01) ///< CC110X transceivers -#define TRANSCEIVER_CC1020 (0x02) ///< CC1020 transceivers -#define TRANSCEIVER_CC2420 (0x04) ///< CC2420 transceivers -#define TRANSCEIVER_MC1322X (0x08) ///< MC1322X transceivers +#define TRANSCEIVER_NONE (0x0) ///< Invalid +#define TRANSCEIVER_CC1100 (0x01) ///< CC110X transceivers +#define TRANSCEIVER_CC1020 (0x02) ///< CC1020 transceivers +#define TRANSCEIVER_CC2420 (0x04) ///< CC2420 transceivers +#define TRANSCEIVER_MC1322X (0x08) ///< MC1322X transceivers +#define TRANSCEIVER_AT86RF231 (0x08) ///< AT86RF231 transceivers /** * @brief Data type for transceiver specification @@ -47,6 +48,7 @@ enum transceiver_msg_type_t { RCV_PKT_CC1100, ///< packet was received by CC1100 transceiver RCV_PKT_CC2420, ///< packet was received by CC2420 transceiver RCV_PKT_MC1322X, ///< packet was received by mc1322x transceiver + RCV_PKT_AT86RF231, ///< packet was received by AT86RF231 transceiver /* Message types for transceiver <-> upper layer communication */ PKT_PENDING, ///< packet pending in transceiver buffer diff --git a/sys/include/vtimer.h b/sys/include/vtimer.h index 741a2b4786..9eecb8a78d 100644 --- a/sys/include/vtimer.h +++ b/sys/include/vtimer.h @@ -94,7 +94,7 @@ int vtimer_remove(vtimer_t *t); /** * @brief Prints a vtimer_t */ -void vtimer_print(vtimer_t *t); +static void vtimer_print(vtimer_t *t); /** * @brief Prints the vtimer shortterm queue (use for debug purposes) diff --git a/sys/transceiver/transceiver.c b/sys/transceiver/transceiver.c index 97bdb66d79..1b7fb47199 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -50,6 +50,14 @@ #define PAYLOAD_SIZE (CC2420_MAX_DATA_LENGTH) #endif #endif + +#ifdef MODULE_AT86RF231 +#include +#if (AT86RF231_MAX_DATA_LENGTH > PAYLOAD_SIZE) + #undef PAYLOAD_SIZE + #define PAYLOAD_SIZE (AT86RF231_MAX_DATA_LENGTH) +#endif +#endif #ifdef MODULE_MC1322X #include @@ -103,6 +111,8 @@ void cc1100_packet_monitor(void *payload, int payload_size, protocol_t protocol, void receive_cc1100_packet(radio_packet_t *trans_p); #elif MODULE_CC2420 static void receive_cc2420_packet(radio_packet_t *trans_p); +#elif MODULE_AT86RF231 +void receive_at86rf231_packet(radio_packet_t *trans_p); #endif static uint8_t send_packet(transceiver_type_t t, void *pkt); static int16_t get_channel(transceiver_type_t t); @@ -139,7 +149,7 @@ void transceiver_init(transceiver_type_t t) reg[i].transceivers = TRANSCEIVER_NONE; reg[i].pid = 0; } - if (t & (TRANSCEIVER_CC1100 | TRANSCEIVER_CC2420)) { + if (t & (TRANSCEIVER_CC1100 | TRANSCEIVER_CC2420 | TRANSCEIVER_AT86RF231)) { transceivers |= t; } else if (t & TRANSCEIVER_MC1322X) { @@ -174,6 +184,11 @@ int transceiver_start(void) DEBUG("Transceiver started for CC2420\n"); cc2420_init(transceiver_pid); } +#elif MODULE_AT86RF231 + else if(transceivers & TRANSCEIVER_AT86RF231) { + DEBUG("Transceiver started for AT86RF231\n"); + at86rf231_init(transceiver_pid); + } #endif #ifdef MODULE_MC1322X else if (transceivers & TRANSCEIVER_MC1322X) { @@ -234,6 +249,9 @@ void run(void) case RCV_PKT_CC2420: receive_packet(m.type, m.content.value); break; + case RCV_PKT_AT86RF231: + receive_packet(m.type, m.content.value); + break; case SND_PKT: response = send_packet(cmd->transceivers, cmd->data); m.content.value = response; @@ -335,6 +353,9 @@ static void receive_packet(uint16_t type, uint8_t pos) case RCV_PKT_MC1322X: t = TRANSCEIVER_MC1322X; break; + case RCV_PKT_AT86RF231: + t = TRANSCEIVER_AT86RF231; + break; default: t = TRANSCEIVER_NONE; break; @@ -373,6 +394,11 @@ static void receive_packet(uint16_t type, uint8_t pos) else if (type == RCV_PKT_CC2420) { #ifdef MODULE_CC2420 receive_cc2420_packet(trans_p); +#endif + } + else if (type == RCV_PKT_AT86RF231) { +#ifdef MODULE_AT86RF231 + receive_at86rf231_packet(trans_p); #endif } else { @@ -476,7 +502,25 @@ void receive_mc1322x_packet(radio_packet_t *trans_p) { } #endif - +#ifdef MODULE_AT86RF231 +void receive_at86rf231_packet(radio_packet_t *trans_p) { + DEBUG("Handling AT86RF231 packet\n"); + dINT(); + at86rf231_packet_t p = at86rf231_rx_buffer[rx_buffer_pos]; + trans_p->src = (uint16_t)((p.frame.src_addr[1] << 8) | p.frame.src_addr[0]); + trans_p->dst = (uint16_t)((p.frame.dest_addr[1] << 8)| p.frame.dest_addr[0]); + trans_p->rssi = p.rssi; + trans_p->lqi = p.lqi; + trans_p->length = p.frame.payload_len; + memcpy((void*) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p.frame.payload, AT86RF231_MAX_DATA_LENGTH); + eINT(); + + DEBUG("Packet %p was from %u to %u, size: %u\n", trans_p, trans_p->src, trans_p->dst, trans_p->length); + trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * AT86RF231_MAX_DATA_LENGTH]); + DEBUG("Content: %s\n", trans_p->data); +} +#endif + /*------------------------------------------------------------------------------------*/ /* * @brief Sends a radio packet to the receiver @@ -505,6 +549,10 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) cc2420_packet_t cc2420_pkt; #endif +#ifdef MODULE_AT86RF231 + at86rf231_packet_t at86rf231_pkt; +#endif + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG @@ -549,6 +597,23 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) memcpy(maca_pkt->data, p.data, p.length); maca_set_tx_packet( maca_pkt ); res = 1; + break; +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + at86rf231_pkt.frame.payload_len = p.length; + at86rf231_pkt.frame.dest_addr[1] = (uint8_t)(p.dst >> 8); + at86rf231_pkt.frame.dest_addr[0] = (uint8_t)(p.dst & 0xFF); + at86rf231_pkt.frame.dest_pan_id = at86rf231_get_pan(); + at86rf231_pkt.frame.fcf.dest_addr_m = 2; + at86rf231_pkt.frame.fcf.src_addr_m = 2; + at86rf231_pkt.frame.fcf.ack_req = 0; + at86rf231_pkt.frame.fcf.sec_enb = 0; + at86rf231_pkt.frame.fcf.frame_type = 1; + at86rf231_pkt.frame.fcf.frame_pend = 0; + at86rf231_pkt.frame.payload = p.data; + res = at86rf231_send(&at86rf231_pkt); + break; #endif default: puts("Unknown transceiver"); @@ -586,6 +651,9 @@ static int16_t set_channel(transceiver_type_t t, void *channel) #ifdef MODULE_MC1322X maca_set_channel(c); return c; ///< TODO: should be changed! implement get channel + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + return at86rf231_set_channel(c); #endif default: return -1; @@ -614,6 +682,10 @@ static int16_t get_channel(transceiver_type_t t) #endif case TRANSCEIVER_MC1322X: ///< TODO:implement return maca_get_channel(); + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + return at86rf231_get_channel(); +#endif default: return -1; } @@ -634,6 +706,10 @@ static uint16_t set_pan(transceiver_type_t t, void *pan) { case TRANSCEIVER_CC2420: #ifdef MODULE_CC2420 return cc2420_set_pan(c); +#endif + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + return at86rf231_set_pan(c); #endif default: /* get rid of compiler warning about unused variable */ @@ -654,6 +730,10 @@ static uint16_t get_pan(transceiver_type_t t) { case TRANSCEIVER_CC2420: #ifdef MODULE_CC2420 return cc2420_get_pan(); +#endif + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + return at86rf231_get_pan(); #endif default: return -1; @@ -683,6 +763,10 @@ static int16_t get_address(transceiver_type_t t) #ifdef MODULE_MC1322X case TRANSCEIVER_MC1322X: return maca_get_address(); +#endif + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + return at86rf231_get_address(); #endif default: return -1; @@ -715,6 +799,10 @@ static int16_t set_address(transceiver_type_t t, void *address) #ifdef MODULE_MC1322X case TRANSCEIVER_MC1322X: return maca_set_address(addr); +#endif + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + return at86rf231_set_address(addr); #endif default: return -1; @@ -738,6 +826,10 @@ static void set_monitor(transceiver_type_t t, void *mode) case TRANSCEIVER_CC2420: #ifdef MODULE_CC2420 cc2420_set_monitor(*((uint8_t*) mode)); +#endif + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + at86rf231_set_monitor(*((uint8_t*) mode)); #endif break; default: @@ -777,6 +869,12 @@ static void switch_to_rx(transceiver_type_t t) cc2420_switch_to_rx(); #endif break; + case TRANSCEIVER_AT86RF231: +#ifdef MODULE_AT86RF231 + at86rf231_switch_to_rx(); +#endif + break; + default: break; }