diff --git a/Makefile.dep b/Makefile.dep index 601a08619d..53261b4a05 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 5b16ee6652..f4b6138362 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..7635e6fde7 --- /dev/null +++ b/drivers/at86rf231/at86rf231_tx.c @@ -0,0 +1,107 @@ +#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 + 1; + + if(packet->length > AT86RF231_MAX_PKT_LENGTH) { + return -1; + } + + // FCS is added in hardware + uint8_t pkt[packet->length]; + + /* generate pkt */ + at86rf231_gen_pkt(pkt, packet); + + // transmit packet + at86rf231_xmit(pkt, packet->length); +} + +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+1; + index++; + + offset = index; + + while(index < packet->length) { + buf[index] = packet->frame.payload[index-offset+1]; + 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 2df97ba816..577818db62 100644 --- a/sys/include/transceiver.h +++ b/sys/include/transceiver.h @@ -49,6 +49,10 @@ #undef PAYLOAD_SIZE #define PAYLOAD_SIZE (CC2420_MAX_DATA_LENGTH) #endif +#ifdef MODULE_AT86RF231 +#if (AT86RF231_MAX_DATA_LENGTH > PAYLOAD_SIZE) +#undef PAYLOAD_SIZE +#define PAYLOAD_SIZE (AT86RF231_MAX_DATA_LENGTH) #endif #ifdef MODULE_MC1322X #if (MC1322X_MAX_DATA_LENGTH > PAYLOAD_SIZE) @@ -71,12 +75,13 @@ /** * @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_NATIVE (0x10) ///< NATIVE 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_NATIVE (0x10) ///< NATIVE transceivers +#define TRANSCEIVER_AT86RF231 (0x20) ///< AT86RF231 transceivers /** * @brief Data type for transceiver specification @@ -92,7 +97,8 @@ 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_NATIVE, ///< packet was received by native transceiver + RCV_PKT_NATIVE, ///< packet was received by native 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 8935e8f8b7..923fea8799 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -53,6 +53,10 @@ #include "nativenet_internal.h" #endif +#ifdef MODULE_AT86RF231 +#include +#endif + #define ENABLE_DEBUG (0) #if ENABLE_DEBUG #undef TRANSCEIVER_STACK_SIZE @@ -106,6 +110,9 @@ static void receive_cc2420_packet(radio_packet_t *trans_p); #elif MODULE_NATIVENET static void receive_nativenet_packet(radio_packet_t *trans_p); #endif +#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); static int16_t set_channel(transceiver_type_t t, void *channel); @@ -142,7 +149,7 @@ void transceiver_init(transceiver_type_t t) reg[i].pid = 0; } /* check if a non defined bit is set */ - if (t & ~(TRANSCEIVER_CC1100 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X | TRANSCEIVER_NATIVE)) { + if (t & ~(TRANSCEIVER_CC1100 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X | TRANSCEIVER_NATIVE | TRANSCEIVER_AT86RF231)) { puts("Invalid transceiver type"); } else { @@ -163,18 +170,26 @@ int transceiver_start(void) DEBUG("transceiver: Transceiver started for CC1100\n"); cc110x_init(transceiver_pid); } -#elif MODULE_CC110X +#endif +#ifdef MODULE_CC110X else if (transceivers & TRANSCEIVER_CC1100) { DEBUG("transceiver: Transceiver started for CC1100\n"); cc1100_init(); cc1100_set_packet_monitor(cc1100_packet_monitor); } -#elif MODULE_CC2420 +#endif +#ifdef MODULE_CC2420 else if(transceivers & TRANSCEIVER_CC2420) { DEBUG("transceiver: Transceiver started for CC2420\n"); cc2420_init(transceiver_pid); } #endif +#ifdef MODULE_AT86RF231 + else if(transceivers & TRANSCEIVER_AT86RF231) { + DEBUG("transceiver: Transceiver started for AT86RF231\n"); + at86rf231_init(transceiver_pid); + } +#endif #ifdef MODULE_MC1322X else if (transceivers & TRANSCEIVER_MC1322X) { maca_init(); @@ -236,6 +251,7 @@ void run(void) case RCV_PKT_CC2420: case RCV_PKT_MC1322X: case RCV_PKT_NATIVE: + case RCV_PKT_AT86RF231: receive_packet(m.type, m.content.value); break; case SND_PKT: @@ -309,10 +325,36 @@ void run(void) static void receive_packet(uint16_t type, uint8_t pos) { uint8_t i = 0; + transceiver_type_t t; rx_buffer_pos = pos; msg_t m; - DEBUG("transceiver: Packet received\n"); + DEBUG("Packet received\n"); + + switch(type) { + case RCV_PKT_CC1020: + t = TRANSCEIVER_CC1020; + break; + + case RCV_PKT_CC1100: + t = TRANSCEIVER_CC1100; + break; + case RCV_PKT_CC2420: + t = TRANSCEIVER_CC2420; + break; + case RCV_PKT_MC1322X: + t = TRANSCEIVER_MC1322X; + break; + case RCV_PKT_NATIVE: + t = TRANSCEIVER_NATIVE; + break; + case RCV_PKT_AT86RF231: + t = TRANSCEIVER_AT86RF231; + break; + default: + t = TRANSCEIVER_NONE; + break; + } /* search first free position in transceiver buffer */ for (i = 0; (i < TRANSCEIVER_BUFFER_SIZE) && (transceiver_buffer[transceiver_buffer_pos].processing); i++) { @@ -325,7 +367,7 @@ static void receive_packet(uint16_t type, uint8_t pos) if (i >= TRANSCEIVER_BUFFER_SIZE) { /* inform upper layers of lost packet */ m.type = ENOBUFFER; - m.content.value = type; + m.content.value = t; } /* copy packet and handle it */ else { @@ -337,38 +379,39 @@ static void receive_packet(uint16_t type, uint8_t pos) if (type == RCV_PKT_CC1100) { #ifdef MODULE_CC110X_NG receive_cc110x_packet(trans_p); - type = TRANSCEIVER_CC1100; #elif MODULE_CC110X receive_cc1100_packet(trans_p); - type = TRANSCEIVER_CC1100; #else trans_p = NULL; - type = TRANSCEIVER_NONE; #endif } else if (type == RCV_PKT_MC1322X) { #ifdef MODULE_MC1322X receive_mc1322x_packet(trans_p); - type = TRANSCEIVER_MC1322X; #else trans_p = NULL; - type = TRANSCEIVER_NONE; #endif } else if (type == RCV_PKT_CC2420) { #ifdef MODULE_CC2420 receive_cc2420_packet(trans_p); - type = TRANSCEIVER_CC2420; #else trans_p = NULL; - type = TRANSCEIVER_NONE; #endif } + else if (type == RCV_PKT_AT86RF231) { +#ifdef MODULE_AT86RF231 + receive_at86rf231_packet(trans_p); +#else + trans_p = NULL; +#endif else if (type == RCV_PKT_NATIVE) { #ifdef MODULE_NATIVENET receive_nativenet_packet(trans_p); - type = TRANSCEIVER_NATIVE; +#else + trans_p = NULL; #endif + } else { puts("Invalid transceiver type"); @@ -381,7 +424,7 @@ static void receive_packet(uint16_t type, uint8_t pos) i = 0; while (reg[i].transceivers != TRANSCEIVER_NONE) { - if (reg[i].transceivers & type) { + if (reg[i].transceivers & t) { m.content.ptr = (char *) & (transceiver_buffer[transceiver_buffer_pos]); DEBUG("transceiver: Notify thread %i\n", reg[i].pid); @@ -492,6 +535,25 @@ void receive_nativenet_packet(radio_packet_t *trans_p) { restoreIRQ(state); } #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 @@ -520,6 +582,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 @@ -571,6 +637,22 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) case TRANSCEIVER_NATIVE: res = nativenet_send(&p); 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"); @@ -614,6 +696,10 @@ static int16_t set_channel(transceiver_type_t t, void *channel) #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: return nativenet_set_channel(c); +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + return at86rf231_set_channel(c); #endif default: return -1; @@ -649,6 +735,10 @@ static int16_t get_channel(transceiver_type_t t) #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: return nativenet_get_channel(); +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + return at86rf231_get_channel(); #endif default: return -1; @@ -674,6 +764,10 @@ static uint16_t set_pan(transceiver_type_t t, void *pan) { #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: return nativenet_set_pan(c); +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + return at86rf231_set_pan(c); #endif default: /* get rid of compiler warning about unused variable */ @@ -698,6 +792,10 @@ static uint16_t get_pan(transceiver_type_t t) { #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: return nativenet_get_pan(); +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + return at86rf231_get_pan(); #endif default: return -1; @@ -733,6 +831,10 @@ static int16_t get_address(transceiver_type_t t) #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: return nativenet_get_address(); +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + return at86rf231_get_address(); #endif default: return -1; @@ -771,6 +873,10 @@ static int16_t set_address(transceiver_type_t t, void *address) #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: return nativenet_set_address(addr); +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + return at86rf231_set_address(addr); #endif default: return -1; @@ -800,6 +906,10 @@ static void set_monitor(transceiver_type_t t, void *mode) case TRANSCEIVER_NATIVE: nativenet_set_monitor(*((uint8_t*) mode)); break; +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + at86rf231_set_monitor(*((uint8_t*) mode)); #endif default: break; @@ -851,6 +961,7 @@ static void switch_to_rx(transceiver_type_t t) #endif #ifdef MODULE_CC2420 case TRANSCEIVER_CC2420: + cc2420_switch_to_rx(); break; #endif @@ -858,6 +969,10 @@ static void switch_to_rx(transceiver_type_t t) case TRANSCEIVER_NATIVE: nativenet_switch_to_rx(); break; +#endif +#ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: + at86rf231_switch_to_rx(); #endif default: break;