From db1fc96ffe977e071c7f8d3f9e2e45a41491a1ac Mon Sep 17 00:00:00 2001 From: Milan Babel Date: Thu, 2 May 2013 08:45:47 +0200 Subject: [PATCH] added driver for cc2420 also added cc2420 to transceiver and added cc2420 shell commands --- drivers/Makefile | 3 + drivers/cc2420/Makefile | 13 ++ drivers/cc2420/cc2420.c | 179 +++++++++++++++++ drivers/cc2420/cc2420_rx.c | 73 +++++++ drivers/cc2420/cc2420_spi.c | 104 ++++++++++ drivers/cc2420/cc2420_tx.c | 112 +++++++++++ drivers/cc2420/include/cc2420.h | 241 +++++++++++++++++++++++ drivers/cc2420/include/cc2420_arch.h | 123 ++++++++++++ drivers/cc2420/include/cc2420_settings.h | 107 ++++++++++ drivers/cc2420/include/cc2420_spi.h | 92 +++++++++ sys/include/transceiver.h | 11 +- sys/net/ieee802154/ieee802154_frame.c | 33 ++-- sys/shell/commands/Makefile | 4 + sys/shell/commands/sc_cc2420.c | 115 +++++++++++ sys/shell/commands/shell_commands.c | 19 ++ sys/transceiver/Makefile | 2 +- sys/transceiver/transceiver.c | 166 ++++++++++++++-- 17 files changed, 1367 insertions(+), 30 deletions(-) create mode 100644 drivers/cc2420/Makefile create mode 100644 drivers/cc2420/cc2420.c create mode 100644 drivers/cc2420/cc2420_rx.c create mode 100644 drivers/cc2420/cc2420_spi.c create mode 100644 drivers/cc2420/cc2420_tx.c create mode 100644 drivers/cc2420/include/cc2420.h create mode 100644 drivers/cc2420/include/cc2420_arch.h create mode 100644 drivers/cc2420/include/cc2420_settings.h create mode 100644 drivers/cc2420/include/cc2420_spi.h create mode 100644 sys/shell/commands/sc_cc2420.c diff --git a/drivers/Makefile b/drivers/Makefile index 273d1e0027..d4371e5b0b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -4,6 +4,9 @@ DIRS= ifneq (,$(findstring powermon,$(USEMODULE))) DIRS += powermon endif +ifneq (,$(findstring cc2420,$(USEMODULE))) + DIRS += cc2420 +endif ifneq (,$(findstring sht11,$(USEMODULE))) DIRS += sht11 endif diff --git a/drivers/cc2420/Makefile b/drivers/cc2420/Makefile new file mode 100644 index 0000000000..e7df7ad5ad --- /dev/null +++ b/drivers/cc2420/Makefile @@ -0,0 +1,13 @@ +INCLUDES = -I$(RIOTBASE)/sys/include -I../../net -I../include -I../../lib -I../../../.. -I../../../cpu/ -I$(RIOTBASE)/core/include -I../../ -Iinclude/ -I$(RIOTBASE)/sys/net/ieee802154/ +MODULE =cc2420 + +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/cc2420/cc2420.c b/drivers/cc2420/cc2420.c new file mode 100644 index 0000000000..0e877b7439 --- /dev/null +++ b/drivers/cc2420/cc2420.c @@ -0,0 +1,179 @@ +/** + * cc2420.c - Implementation of cc2420 functions. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include +#include +#include +#include +#include + +//#define ENABLE_DEBUG +#include + +static uint16_t radio_channel; +static uint16_t radio_address; +static uint64_t radio_address_long; +static uint16_t radio_pan; + +/* Radio driver API */ + +int transceiver_pid; + +void cc2420_init(int tpid) +{ + uint16_t reg; + transceiver_pid = tpid; + + cc2420_spi_init(); + hwtimer_wait(CC2420_WAIT_TIME); + cc2420_reset(); + + cc2420_strobe(CC2420_STROBE_XOSCON); //enable crystal + + while((cc2420_strobe(NOBYTE) & 0x40) == 0); //wait for crystal to be stable + hwtimer_wait(CC2420_WAIT_TIME); + + reg = cc2420_read_reg(CC2420_REG_MDMCTRL0); + reg |= CC2420_ADR_DECODE; //enable adr decode + reg |= CC2420_AUTOACK; //enable auto ack + reg |= CC2420_AUTOCRC; //enable auto crc + reg &= ~(CC2420_RES_FRM_MODE); //disable reserved frames + cc2420_write_reg(CC2420_REG_MDMCTRL0, reg); + + /* Change default values as recomended in the data sheet, */ + /* RX bandpass filter = 1.3uA. */ + reg = cc2420_read_reg(CC2420_REG_RXCTRL1); + reg |= CC2420_RXBPF_LOCUR; + cc2420_write_reg(CC2420_REG_RXCTRL1, reg); + + /* Set the FIFOP threshold to maximum. */ + cc2420_write_reg(CC2420_REG_IOCFG0, 127); + + /* Turn off "Security enable" (page 32). */ + reg = cc2420_read_reg(CC2420_REG_SECCTRL0); + reg &= ~CC2420_RXFIFO_PROTECTION; + cc2420_write_reg(CC2420_REG_SECCTRL0, reg); + + /* set output power to 0dbm */ + cc2420_write_reg(CC2420_REG_TXCTRL, 0xA0FF); + + cc2420_set_channel(CC2420_DEFAULT_CHANNR); + cc2420_set_pan(0x1111); + DEBUG("CC2420 initialized and set to channel %i and pan %i\n", radio_channel, radio_pan); + cc2420_init_interrupts(); + cc2420_switch_to_rx(); + +} + +void cc2420_switch_to_rx(void) { + cc2420_strobe(CC2420_STROBE_RFOFF); + cc2420_strobe(CC2420_STROBE_FLUSHRX); + cc2420_strobe(CC2420_STROBE_FLUSHRX); + cc2420_strobe(CC2420_STROBE_RXON); +} + +void cc2420_rxoverflow_irq(void) +{ + cc2420_strobe(CC2420_STROBE_FLUSHRX); + //Datasheets says do this twice... + cc2420_strobe(CC2420_STROBE_FLUSHRX); +} + +void cc2420_rx_irq(void) +{ + cc2420_rx_handler(); +} + +void cc2420_set_monitor(uint8_t mode) +{ + uint16_t reg; + reg = cc2420_read_reg(CC2420_REG_MDMCTRL0); + if(mode) { + reg &= ~CC2420_ADR_DECODE; + } else { + reg |= CC2420_ADR_DECODE; + } + cc2420_write_reg(CC2420_REG_MDMCTRL0, reg); +} + +int16_t cc2420_set_channel(uint16_t chan) +{ + if(chan < 11 || chan > 26) { + DEBUG("Invalid channel %i set. Valid channels are 11 through 26\n",chan); + return -1; + } + radio_channel = chan; + chan = 357 + (5 * (radio_channel-11)); //calculation from p.50 + cc2420_write_reg(CC2420_REG_FSCTRL, chan); + return radio_channel; +} + +uint16_t cc2420_get_channel(void) +{ + return radio_channel; +} + +uint16_t cc2420_set_address(uint16_t addr) +{ + uint8_t buf[2]; + radio_address = addr; + buf[0] = (uint8_t)(addr & 0xFF); + buf[1] = (uint8_t)(addr >> 8); + cc2420_write_ram(CC2420_RAM_SHORTADR, buf, 2); + cc2420_set_address_long(0x00FF & addr); + return radio_address; +} + +uint64_t cc2420_set_address_long(uint64_t addr) +{ + uint8_t buf[8]; + radio_address_long = addr; + buf[0] = (uint8_t)(addr & 0xFF); + buf[1] = (uint8_t)(addr >> 8); + buf[2] = (uint8_t)(addr >> 16); + buf[3] = (uint8_t)(addr >> 24); + buf[4] = (uint8_t)(addr >> 32); + buf[5] = (uint8_t)(addr >> 40); + buf[6] = (uint8_t)(addr >> 48); + buf[7] = (uint8_t)(addr >> 56); + cc2420_write_ram(CC2420_RAM_IEEEADR, buf, 8); + return radio_address_long; +} + +uint16_t cc2420_get_address(void) +{ + return radio_address; +} + +uint64_t cc2420_get_address_long(void) +{ + return radio_address_long; +} + +uint16_t cc2420_set_pan(uint16_t pan) +{ + uint8_t buf[2]; + radio_pan = pan; + buf[0] = (uint8_t)(pan & 0xFF); + buf[1] = (uint8_t)(pan >> 8); + cc2420_write_ram(CC2420_RAM_PANID, buf, 2); + return radio_pan; +} + +uint16_t cc2420_get_pan(void) +{ + return radio_pan; +} + +void cc2420_swap_fcf_bytes(uint8_t *buf) +{ + uint8_t tmp; + tmp = buf[0]; + buf[0] = buf[1]; + buf[1] = tmp; +} diff --git a/drivers/cc2420/cc2420_rx.c b/drivers/cc2420/cc2420_rx.c new file mode 100644 index 0000000000..51b6c1801b --- /dev/null +++ b/drivers/cc2420/cc2420_rx.c @@ -0,0 +1,73 @@ +/** + * cc2420_rx.c - Implementation of receiving cc2420 functions. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +cc2420_packet_t cc2420_rx_buffer[CC2420_RX_BUF_SIZE]; +volatile uint8_t rx_buffer_next; + +void cc2420_rx_handler(void) +{ + uint8_t rssi_crc_lqi[2]; + + /* read length */ + cc2420_read_fifo(&cc2420_rx_buffer[rx_buffer_next].length, 1); + + /* read packet without rssi, crc and lqi */ + uint8_t buf[cc2420_rx_buffer[rx_buffer_next].length-2]; + cc2420_read_fifo(buf, cc2420_rx_buffer[rx_buffer_next].length-2); + + cc2420_swap_fcf_bytes(buf); + /* read rssi, lqi and crc */ + cc2420_read_fifo(rssi_crc_lqi, 2); + + /* build package */ + cc2420_rx_buffer[rx_buffer_next].rssi = (int8_t)(rssi_crc_lqi[0]); + cc2420_rx_buffer[rx_buffer_next].lqi = (uint8_t)(rssi_crc_lqi[1] & 0x7F); + cc2420_rx_buffer[rx_buffer_next].crc = (uint8_t)((rssi_crc_lqi[1] & 0x80) >> 7); + + if(cc2420_rx_buffer[rx_buffer_next].crc == 0) { + DEBUG("Got packet with invalid crc.\n"); + return; + } + read_802154_frame(buf, + &cc2420_rx_buffer[rx_buffer_next].frame, + cc2420_rx_buffer[rx_buffer_next].length-2); + if(cc2420_rx_buffer[rx_buffer_next].frame.fcf.frame_type != 2) { +#ifdef DEBUG + print_802154_fcf_frame(&cc2420_rx_buffer[rx_buffer_next].frame); +#endif + /* notify transceiver thread if any */ + if (transceiver_pid) { + msg_t m; + m.type = (uint16_t) RCV_PKT_CC2420; + m.content.value = rx_buffer_next; + msg_send_int(&m, transceiver_pid); + } + } else { +#ifdef DEBUG + DEBUG("GOT ACK for SEQ %u\n", cc2420_rx_buffer[rx_buffer_next].frame.seq_nr); + print_802154_fcf_frame(&cc2420_rx_buffer[rx_buffer_next].frame); +#endif + } + + /* shift to next buffer element */ + if (++rx_buffer_next == CC2420_RX_BUF_SIZE) { + rx_buffer_next = 0; + } +} diff --git a/drivers/cc2420/cc2420_spi.c b/drivers/cc2420/cc2420_spi.c new file mode 100644 index 0000000000..653955a9ca --- /dev/null +++ b/drivers/cc2420/cc2420_spi.c @@ -0,0 +1,104 @@ +/** + * cc2420_spi.c - Implementation of SPI cc2420 functions. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include +#include + +#include +#include + +/* reg */ +void cc2420_write_reg(uint8_t addr, uint16_t value) { + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + cc2420_txrx(addr | CC2420_WRITE_ACCESS); + cc2420_txrx((uint8_t) (value >> 8)); + cc2420_txrx((uint8_t) (value & 0xFF)); + cc2420_spi_unselect(); + restoreIRQ(cpsr); +} + +uint16_t cc2420_read_reg(uint8_t addr) { + uint16_t result; + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + cc2420_txrx(addr | CC2420_READ_ACCESS); + result = cc2420_txrx(NOBYTE); + result = result << 8; + result = cc2420_txrx(NOBYTE); + cc2420_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +uint8_t cc2420_strobe(uint8_t c) { + uint8_t result; + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + result = cc2420_txrx(c); + cc2420_spi_unselect(); + restoreIRQ(cpsr); + return result; +} + +/* ram */ +uint16_t cc2420_read_ram(uint16_t addr, uint8_t* buffer, uint16_t len) { + uint16_t i; + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + cc2420_txrx(CC2420_RAM_ACCESS | (addr & 0x7F)); + cc2420_txrx(((addr >> 1) & 0xC0) | CC2420_RAM_READ_ACCESS); + for (i = 0; i < len; i++) { + buffer[i] = cc2420_txrx(NOBYTE); + } + cc2420_spi_unselect(); + restoreIRQ(cpsr); + return i; +} + +uint16_t cc2420_write_ram(uint16_t addr, uint8_t* buffer, uint16_t len) { + uint16_t i; + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + cc2420_txrx(CC2420_RAM_ACCESS | (addr & 0x7F)); + cc2420_txrx(((addr >> 1) & 0xC0) | CC2420_RAM_WRITE_ACCESS); + for (i = 0; i < len; i++) { + cc2420_txrx(buffer[i]); + } + cc2420_spi_unselect(); + restoreIRQ(cpsr); + return i; +} + +/* fifo */ + +uint16_t cc2420_write_fifo(uint8_t* data, uint16_t data_length) { + uint16_t i; + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + cc2420_txrx(CC2420_REG_TXFIFO | CC2420_WRITE_ACCESS); + for (i = 0; i < data_length; i++) { + cc2420_txrx(data[i]); + } + cc2420_spi_unselect(); + restoreIRQ(cpsr); + return i; +} + +uint16_t cc2420_read_fifo(uint8_t* data, uint16_t data_length) { + uint16_t i; + unsigned int cpsr = disableIRQ(); + cc2420_spi_select(); + cc2420_txrx(CC2420_REG_RXFIFO | CC2420_READ_ACCESS); + for (i = 0; i < data_length; i++) { + data[i] = cc2420_txrx(NOBYTE); + } + cc2420_spi_unselect(); + restoreIRQ(cpsr); + return i; +} diff --git a/drivers/cc2420/cc2420_tx.c b/drivers/cc2420/cc2420_tx.c new file mode 100644 index 0000000000..e97418468b --- /dev/null +++ b/drivers/cc2420/cc2420_tx.c @@ -0,0 +1,112 @@ +/** + * cc2420_rx.c - Implementation of transmitting cc2420 functions. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +static void cc2420_gen_pkt(uint8_t *buf, cc2420_packet_t *packet); + +static uint8_t sequenz_nr; + +int16_t cc2420_send(cc2420_packet_t *packet) +{ + volatile uint32_t abort_count; + + /* 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)(cc2420_get_address() >> 8); + packet->frame.src_addr[0] = (uint8_t)(cc2420_get_address() & 0xFF); + } else if (packet->frame.fcf.src_addr_m == 3) { + packet->frame.src_addr[7] = (uint8_t)(cc2420_get_address_long() >> 56); + packet->frame.src_addr[6] = (uint8_t)(cc2420_get_address_long() >> 48); + packet->frame.src_addr[5] = (uint8_t)(cc2420_get_address_long() >> 40); + packet->frame.src_addr[4] = (uint8_t)(cc2420_get_address_long() >> 32); + packet->frame.src_addr[3] = (uint8_t)(cc2420_get_address_long() >> 24); + packet->frame.src_addr[2] = (uint8_t)(cc2420_get_address_long() >> 16); + packet->frame.src_addr[1] = (uint8_t)(cc2420_get_address_long() >> 8); + packet->frame.src_addr[0] = (uint8_t)(cc2420_get_address_long() & 0xFF); + } + packet->frame.src_pan_id = cc2420_get_pan(); + packet->frame.seq_nr = sequenz_nr; + + sequenz_nr += 1; + + /* calculate size of the package (header + payload + fcs) */ + packet->length = get_802154_hdr_len(&packet->frame) + packet->frame.payload_len + 2; + + if(packet->length > CC2420_MAX_PKT_LENGTH) { + return -1; + } + /* FCS is added in hardware */ + uint8_t pkt[packet->length-2]; + + /* generate pkt */ + cc2420_gen_pkt(pkt, packet); + + /* idle & flush tx */ + cc2420_strobe(CC2420_STROBE_RFOFF); + cc2420_strobe(CC2420_STROBE_FLUSHTX); + + /* write length and packet to fifo */ + cc2420_write_fifo(&packet->length, 1); + cc2420_write_fifo(pkt, packet->length-2); + + unsigned int cpsr = disableIRQ(); + cc2420_strobe(CC2420_STROBE_TXON); + + // Wait for SFD to be set -> sync word transmitted + while (cc2420_get_sfd() == 0) { + abort_count++; + if (abort_count > CC2420_SYNC_WORD_TX_TIME) { + // Abort waiting. CC2420 maybe in wrong mode + // e.g. sending preambles for always + puts("[CC2420 TX] fatal error\n"); + packet->length = 0; + break; + } + } + printf("SEQ: %u\n", packet->frame.seq_nr); + restoreIRQ(cpsr); + + /* wait for packet to be send */ + while (cc2420_get_sfd() != 0); + + cc2420_switch_to_rx(); + return packet->length; +} + +/** + * @brief Static function to generate byte array from cc2420 packet. + * + */ + +static void cc2420_gen_pkt(uint8_t *buf, cc2420_packet_t *packet) +{ + uint8_t index, offset; + index = init_802154_frame(&packet->frame, buf); + offset = index; + while(index < packet->length-2) { + buf[index] = packet->frame.payload[index-offset]; + index += 1; + } + cc2420_swap_fcf_bytes(buf); +} diff --git a/drivers/cc2420/include/cc2420.h b/drivers/cc2420/include/cc2420.h new file mode 100644 index 0000000000..e6c69140cb --- /dev/null +++ b/drivers/cc2420/include/cc2420.h @@ -0,0 +1,241 @@ +/** + * cc2420.h - Definitions for CC2420 functions. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + + +/** + * @ingroup CC2420 + * @{ + * @file + * @brief Definitions for CC2420 functions + * @author Milan Babel + * + */ + +/** + * @brief Definition of the cc2420 layer 0 protocol + *
+---------------------------------------------------------------------------
+|        |         |          |         |         |            |          |
+| Length |   FCF   |  Seq No. |Address  | PhySrc  |    Data    |    FCS   |
+|        |         |          |         |         |            |          |
+---------------------------------------------------------------------------
+ 1 byte    2 bytes     1 byte  2/8 bytes  2/8 bytes  <=118 bytes  2 bytes
+
+A 5 byte SHR will be generated and added in hardware.
+SHR contains a preable sequence and a start of delimiter,
+
+Length does not contain SHR and Length,
+first bit of length has to be 0 (length has only 7bit)
+
+Address fields can be in total between 4 and 20 bytes
+FCS contain a hardware generated CRC sum with the polynom x^16+x^12+x^5+1
+When receiving a package FCS will be checked by hardware, the first FCS byte will be replaced by RSSI,
+followed by a CRC OK bit and the unsigned 7 bit correlation value.
+FCF:
+		Bit | Meaning
+		--------------------
+		0-2	| Frame Type
+		  3 | Security Enabled
+		  4 | Frame Pending
+		  5 | Acknowledge request
+		  6 | PAN ID Compression Field
+		7-9 | Reserved
+	  10-11 | Destination addressing mode
+	  12-13 | Reserved
+	  14-15 | Source addressing mode
+
+For the cc2420 bit 0 is the most right bit and bit 15 is the most left bit.
+But the 2 FCF bytes have to be transmitted littel endian (byte 15 to 8 first than 7 to 0)
+
+Addressing mode value:
+
+       Bit | Meaning
+       ---------------------
+        00 | PAN identifier and address field are not present.
+        01 | Reserved.
+        10 | Address field contains a 16 bit short address.
+        11 | Address field contains a 64 bit extended address.
+
+Frame type value:
+
+       Bit | Meaning
+       ---------------------
+       000 | Beacon
+       001 | Data
+       010 | Acknowledgment
+       011 | MAC command
+       1xx | Reserved
+  
+*/ + +#ifndef CC2420_H +#define CC2420_H + +#include +#include + +#define CC2420_MAX_PKT_LENGTH 127 +#define CC2420_MAX_DATA_LENGTH (118) + +#define CC2420_BROADCAST_ADDRESS (0xFFFF) + +#define CC2420_MAX_UID (0xFFFE) +#define CC2420_MIN_UID (0x0000) + +/** + * Structure to represent a cc2420 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 */ + /* @} */ +} cc2420_packet_t; + +/** + * @brief Init the cc2420. + * + * @param[in] tpid The PID of the transceiver thread. + */ + +void cc2420_init(int tpid); + +/** + * @brief Turns monitor mode on off. + * + * @param[in] mode The desired mode, 1 for on; 0 for off. + */ +void cc2420_set_monitor(uint8_t mode); + +/** + * @brief Switchs the cc2420 into receive mode. + * + */ +void cc2420_switch_to_rx(void); + +/** + * @brief Set the channel of the cc2420. + * + * @param[in] chan The desired channel, valid channels are from 11 to 26. + * + * @return The tuned channel after calling, or -1 on error. + */ +int16_t cc2420_set_channel(uint16_t chan); + +/** + * @brief Get the channel of the cc2420. + * + * @return The tuned channel. + */ +uint16_t cc2420_get_channel(void); + +/** + * @brief Sets the short address of the cc2420. + * + * @param[in] addr The desired address. + * + * @return The set address after calling. + */ +uint16_t cc2420_set_address(uint16_t addr); + +/** + * @brief Gets the current short address of the cc2420. + * + * @return The current short address. + * + */ +uint16_t cc2420_get_address(void); + +/** + * @brief Sets the IEEE long address of the cc2420. + * + * @param[in] addr The desired address. + * + * @return The set address after calling. + */ +uint64_t cc2420_set_address_long(uint64_t addr); + +/** + * @brief Gets the current IEEE long address of the cc2420. + * + * @return The current IEEE long address. + * + */ +uint64_t cc2420_get_address_long(void); + +/** + * @brief Sets the pan ID of the cc2420. + * + * @param[in] pan The desired pan ID. + * + * @return The set pan ID after calling. + */ +uint16_t cc2420_set_pan(uint16_t pan); + +/** + * @brief Gets the current IEEE long address of the cc2420. + * + * @return The current IEEE long address. + * + */ +uint16_t cc2420_get_pan(void); + + +/** + * @brief Interrupt handler, gets fired when a RX overflow happens. + * + */ +void cc2420_rxoverflow_irq(void); + +/** + * @brief Interrupt handler, gets fired when bytes in the RX FIFO are present. + * + */ +void cc2420_rx_irq(void); + + +/** + * @brief RX handler, process data from the RX FIFO. + * + */ +void cc2420_rx_handler(void); + +/** + * @brief Send function, sends a cc2420_packet_t over the air. + * + * @param[in] *packet The Packet which will be send. + * + * @return The count of bytes which are send or -1 on error + * + */ +int16_t cc2420_send(cc2420_packet_t *packet); + +/** + * @brief Changes the byte order of the two fcf bytes in a buffer. + * + * @param[in] *buf The Packet to swap. + * + */ +void cc2420_swap_fcf_bytes(uint8_t *buf); + +/** + * The PID of the transceiver thread. + */ +extern int transceiver_pid; + +/* + * RX Packet Buffer, read from the transceiver, filled by the cc2420_rx_handler. + */ +extern cc2420_packet_t cc2420_rx_buffer[CC2420_RX_BUF_SIZE]; + + +#endif + diff --git a/drivers/cc2420/include/cc2420_arch.h b/drivers/cc2420/include/cc2420_arch.h new file mode 100644 index 0000000000..a206ecb399 --- /dev/null +++ b/drivers/cc2420/include/cc2420_arch.h @@ -0,0 +1,123 @@ +/****************************************************************************** +Copyright 2013, Freie Universitaet Berlin (FUB). All rights reserved. + +These sources were developed at the Freie Universitaet Berlin, Computer Systems +and Telematics group (http://cst.mi.fu-berlin.de). +------------------------------------------------------------------------------- +This file is part of RIOT. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free Software +Foundation version 2 of the License. + +RIOT is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along with +this program. If not, see http://www.gnu.org/licenses/ . +-------------------------------------------------------------------------------- +For further information and questions please use the web site + http://scatterweb.mi.fu-berlin.de +and the mailinglist (subscription via web site) + scatterweb@lists.spline.inf.fu-berlin.de +*******************************************************************************/ + +/** + * @file + * @ingroup CC2420 + * @brief CC2420 dependend functions + * + * @author Freie Universität Berlin, Computer Systems & Telematics + * @author Heiko Will + * @author Milan Babel + * @version $Revision: 1775 $ + * + * @note $Id: arch_cc110x.h 1775 2010-01-26 09:37:03Z hillebra $ + */ + +#include + +/** + * @brief SPI tx and rx function. + * + * @param[in] c byte which should be transmitted. + * + * @return Byte which was received after transmitting. + * + */ +uint8_t cc2420_txrx(uint8_t c); + +/** + * @brief Gets the status of the sfd pin. + * + * @return Status of the sfd pin. + * + */ +uint8_t cc2420_get_sfd(void); + +/** + * @brief Does a hardware reset of the cc2420. + * + */ +void cc2420_reset(void); + +/** + * @brief Init the SPI interface. + * + */ +void cc2420_spi_init(void); + +/** + * @brief Selects the cc2420 on the spi bus. + * + */ +void cc2420_spi_select(void); + +/** + * @brief Unselects the cc2420 on the spi bus. + * + */ +void cc2420_spi_unselect(void); + +/** + * @brief Enable interrupts on the GDO0 pin. + * + */ +void cc2420_gdo0_enable(void); + +/** + * @brief Disable interrupts on the GDO0 pin. + * + */ +void cc2420_gdo0_disable(void); + +/** + * @brief Enable interrupts on the GDO2 pin. + * + */ +void cc2420_gdo2_enable(void); + +/** + * @brief Disable interrupts on the GDO2 pin. + * + */ +void cc2420_gdo2_disable(void); + +/** + * @brief Init interrupts. + * + */ +void cc2420_init_interrupts(void); + +/** + * @brief Function called before send to disable interrupts. + * + */ +void cc2420_before_send(void); + +/** + * @brief Function called after send to reenable interrupts. + * + */ +void cc2420_after_send(void); diff --git a/drivers/cc2420/include/cc2420_settings.h b/drivers/cc2420/include/cc2420_settings.h new file mode 100644 index 0000000000..18fcf3ac22 --- /dev/null +++ b/drivers/cc2420/include/cc2420_settings.h @@ -0,0 +1,107 @@ +/** + * cc2420_settings.h - Definitions and settings for the CC2420. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + + +/** + * @ingroup CC2420 + * @{ + * @file + * @brief Definitions and settings for the CC2420 + * @author Milan Babel + * + */ +#ifndef CC2420_SETTINGS_H +#define CC2420_SETTINGS_H + +/* Access addresses */ +#define CC2420_READ_ACCESS 0x40 +#define CC2420_WRITE_ACCESS 0x00 + +#define CC2420_RAM_ACCESS 0x80 +#define CC2420_RAM_READ_ACCESS 0x20 +#define CC2420_RAM_WRITE_ACCESS 0x00 + +#define CC2420_REG_TXFIFO 0x3E +#define CC2420_REG_RXFIFO 0x3F + +/* RAM addresses */ +#define CC2420_RAM_SHORTADR 0x16A +#define CC2420_RAM_PANID 0x168 +#define CC2420_RAM_IEEEADR 0x160 + +/* Strobe command addresses */ +#define CC2420_STROBE_NOP 0x00 +#define CC2420_STROBE_XOSCON 0x01 +#define CC2420_STROBE_TXCAL 0x02 +#define CC2420_STROBE_RXON 0x03 +#define CC2420_STROBE_TXON 0x04 +#define CC2420_STROBE_TXONCCA 0x05 +#define CC2420_STROBE_RFOFF 0x06 +#define CC2420_STROBE_XOSCOFF 0x07 +#define CC2420_STROBE_FLUSHRX 0x08 +#define CC2420_STROBE_FLUSHTX 0x09 +#define CC2420_STROBE_ACK 0x0A +#define CC2420_STROBE_ACKPEND 0x0B +#define CC2420_STROBE_RXDEC 0x0C +#define CC2420_STROBE_TXENC 0x0D +#define CC2420_STROBE_AES 0x0E + +/* Register command addresses */ +#define CC2420_REG_MAIN 0x10 +#define CC2420_REG_MDMCTRL0 0x11 + #define CC2420_ADR_DECODE 0x800 + #define CC2420_RES_FRM_MODE 0x2000 + #define CC2420_PAN_COORD 0x1000 + #define CC2420_AUTOCRC 0x20 + #define CC2420_AUTOACK 0x10 +#define CC2420_REG_MDMCTRL1 0x12 +#define CC2420_REG_RSSI 0x13 + #define CC2420_CCATHR_MASK 0xFF00 + #define CC2420_RSSI_MASK 0xFF +#define CC2420_REG_SYNCWORD 0x14 +#define CC2420_REG_TXCTRL 0x15 + #define CC2420_PALEVEL_MASK 0x1F +#define CC2420_REG_RXCTRL0 0x16 +#define CC2420_REG_RXCTRL1 0x17 + #define CC2420_RXBPF_LOCUR 0x2000 +#define CC2420_REG_FSCTRL 0x18 + #define CC2420_FREQ_MASK 0x3FF +#define CC2420_REG_SECCTRL0 0x19 + #define CC2420_RXFIFO_PROTECTION 0x200 +#define CC2420_REG_SECCTRL1 0x1A +#define CC2420_REG_BATTMON 0x1B +#define CC2420_REG_IOCFG0 0x1C + #define CC2420_FIFOPTHR_MASK 0x7F +#define CC2420_REG_IOCFG1 0x1D +#define CC2420_REG_MANFIDL 0x1E +#define CC2420_REG_MANFIDH 0x1F +#define CC2420_REG_FSMTC 0x20 +#define CC2420_REG_MANAND 0x21 +#define CC2420_REG_MANOR 0x22 +#define CC2420_REG_AGCCTRL 0x23 +#define CC2420_REG_AGCTST0 0x24 +#define CC2420_REG_AGCTST1 0x25 +#define CC2420_REG_AGCTST2 0x26 +#define CC2420_REG_FSTST0 0x27 +#define CC2420_REG_FSTST1 0x28 +#define CC2420_REG_FSTST2 0x29 +#define CC2420_REG_FSTST3 0x2A +#define CC2420_REG_RXBPFTST 0x2B +#define CC2420_REG_FSMSTATE 0x2C +#define CC2420_REG_ADCTST 0x2D +#define CC2420_REG_DACTST 0x2E +#define CC2420_REG_TOPTST 0x2F + +#define NOBYTE 0x0 + +/* Settings */ +#define CC2420_DEFAULT_CHANNR 18 +#define CC2420_SYNC_WORD_TX_TIME 900000 +#define CC2420_RX_BUF_SIZE 3 +#define CC2420_WAIT_TIME 500 +#endif diff --git a/drivers/cc2420/include/cc2420_spi.h b/drivers/cc2420/include/cc2420_spi.h new file mode 100644 index 0000000000..b590b7908c --- /dev/null +++ b/drivers/cc2420/include/cc2420_spi.h @@ -0,0 +1,92 @@ +/** + * cc2420_spi.h - Definition of CC2420 SPI functions. + * Copyright (C) 2013 Milan Babel + * + * This source code is licensed under the GNU Lesser General Public License, + * Version 2. See the file LICENSE for more details. + */ + + +/** + * @ingroup CC2420 + * @{ + * @file + * @brief Definition of CC2420 SPI functions + * @author Milan Babel + * + */ +#ifndef CC2420_SPI_H +#define CC2420_SPI_H + +#include + +/** + * @brief Writes a byte to the cc2420 register. + * + * @param[in] addr The address of the register to write. + * @param[in] value The value to write in the register. + */ +void cc2420_write_reg(uint8_t addr, uint16_t value); + +/** + * @brief Reads a byte from the cc2420 register. + * + * @param[in] addr The address of the register to read. + * + * @return The value in the register. + */ +uint16_t cc2420_read_reg(uint8_t addr); + +/** + * @brief Sends a strobe command to the cc2420. + * + * @param[in] c The strobe command to send. + * + * @return The result of the strobe command. + */ +uint8_t cc2420_strobe(uint8_t c); + + +/** + * @brief Reads multiple bytes from the cc2420 ram. + * + * @param[in] addr The ram address to read. + * @param[out] buffer A buffer to store the value of the ram. + * @param[in] len The count of bytes which should be read. + * + * @return The number of bytes read. + */ +uint16_t cc2420_read_ram(uint16_t addr, uint8_t* buffer, uint16_t len); + +/** + * @brief Writes multiple bytes to the cc2420 ram. + * + * @param[in] addr The ram address to write. + * @param[in] buffer A buffer with the value to write to the ram. + * @param[in] len The count of bytes which should be written. + * + * @return The number of bytes written. + */ +uint16_t cc2420_write_ram(uint16_t addr, uint8_t* buffer, uint16_t len); + +/** + * @brief Writes multiple bytes to the cc2420 fifo. + * + * @param[in] data A buffer with the value to write to the fifo. + * @param[in] data_length The count of bytes which should be written. + * + * @return The number of bytes written. + */ +uint16_t cc2420_write_fifo(uint8_t* data, uint16_t data_length); + +/** + * @brief Reads multiple bytes from the cc2420 fifo. + * + * @param[out] data A buffer to store the value of the fifo. + * @param[in] data_length The count of bytes which should be read. + * + * @return The number of bytes read. + */ +uint16_t cc2420_read_fifo(uint8_t* data, uint16_t data_length); + +#endif diff --git a/sys/include/transceiver.h b/sys/include/transceiver.h index 9d2732baf0..4be56a4427 100644 --- a/sys/include/transceiver.h +++ b/sys/include/transceiver.h @@ -10,8 +10,11 @@ #define TRANSCEIVER_STACK_SIZE (512) #endif +#ifdef MODULE_CC2420 +#define PAYLOAD_SIZE (118) +#else #define PAYLOAD_SIZE (58) - +#endif /* The maximum of threads to register */ #define TRANSCEIVER_MAX_REGISTERED (4) @@ -26,6 +29,7 @@ enum transceiver_msg_type_t { /* Message types for driver <-> transceiver communication */ RCV_PKT_CC1020, ///< packet was received by CC1020 transceiver RCV_PKT_CC1100, ///< packet was received by CC1100 transceiver + RCV_PKT_CC2420, ///< packet was received by CC2420 transceiver /* Message types for transceiver <-> upper layer communication */ PKT_PENDING, ///< packet pending in transceiver buffer @@ -38,6 +42,8 @@ enum transceiver_msg_type_t { GET_ADDRESS, ///< Get the radio address SET_ADDRESS, ///< Set the radio address SET_MONITOR, ///< Set transceiver to monitor mode (disable address checking) + GET_PAN, ///< Get current pan + SET_PAN, ///< Set a new pan /* debug message types */ DBG_IGN, ///< add a physical address to the ignore list @@ -52,7 +58,8 @@ enum transceiver_msg_type_t { typedef enum { TRANSCEIVER_NONE, ///< Invalid TRANSCEIVER_CC1100, ///< CC110X transceivers - TRANSCEIVER_CC1020 ///< CC1020 transceivers + TRANSCEIVER_CC1020, ///< CC1020 transceivers + TRANSCEIVER_CC2420 ///< CC2420 transceivers } transceiver_type_t; /** diff --git a/sys/net/ieee802154/ieee802154_frame.c b/sys/net/ieee802154/ieee802154_frame.c index 65ee2f1d2e..70927eeb49 100644 --- a/sys/net/ieee802154/ieee802154_frame.c +++ b/sys/net/ieee802154/ieee802154_frame.c @@ -10,15 +10,16 @@ uint8_t init_802154_frame(ieee802154_frame_t *frame, uint8_t *buf){ /* Frame Control Field - 802.15.4 - 2006 - 7.2.1.1 */ uint8_t index = 0; - buf[index] = ((frame->fcf.frame_type << 5) | - (frame->fcf.sec_enb << 4) | - (frame->fcf.frame_pend << 3) | - (frame->fcf.ack_req << 2) | - (frame->fcf.panid_comp << 1)); + buf[index] = ((frame->fcf.dest_addr_m << 2) | + (frame->fcf.frame_ver << 4) | + (frame->fcf.src_addr_m << 6)); + index++; - buf[index] = ((frame->fcf.dest_addr_m << 4) | - (frame->fcf.frame_ver << 2) | - (frame->fcf.src_addr_m)); + buf[index] = ((frame->fcf.frame_type) | + (frame->fcf.sec_enb << 3) | + (frame->fcf.frame_pend << 4) | + (frame->fcf.ack_req << 5) | + (frame->fcf.panid_comp << 6)); index++; /* Sequence Number - 802.15.4 - 2006 - 7.2.1.2 */ @@ -118,17 +119,17 @@ uint8_t read_802154_frame(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len){ uint8_t index = 0; uint8_t hdrlen; - frame->fcf.frame_type = (buf[index] >> 5) & 0x07; - frame->fcf.sec_enb = (buf[index] >> 4) & 0x01; - frame->fcf.frame_pend = (buf[index] >> 3) & 0x01; - frame->fcf.ack_req = (buf[index] >> 2) & 0x01; - frame->fcf.panid_comp = (buf[index] >> 1) & 0x01; + frame->fcf.dest_addr_m = (buf[index] >> 2) & 0x03; + frame->fcf.frame_ver = (buf[index] >> 4) & 0x03; + frame->fcf.src_addr_m = (buf[index] >> 6) & 0x03; index++; - frame->fcf.dest_addr_m = (buf[index] >> 4) & 0x03; - frame->fcf.frame_ver = (buf[index] >> 2) & 0x03; - frame->fcf.src_addr_m = buf[index] & 0x03; + frame->fcf.frame_type = (buf[index]) & 0x07; + frame->fcf.sec_enb = (buf[index] >> 3) & 0x01; + frame->fcf.frame_pend = (buf[index] >> 4) & 0x01; + frame->fcf.ack_req = (buf[index] >> 5) & 0x01; + frame->fcf.panid_comp = (buf[index] >> 6) & 0x01; //print_802154_fcf_frame(frame); diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index c14ee9bcef..784308da10 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -5,6 +5,10 @@ ifneq (,$(findstring cc110x_ng,$(USEMODULE))) INCLUDES += -I$(RIOTBASE)/drivers/cc110x_ng/include/ SRC += sc_cc110x_ng.c endif +ifneq (,$(findstring cc2420,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/drivers/cc2420/include/ -I$(RIOTBASE)/sys/net/ieee802154/ + SRC += sc_cc2420.c +endif ifneq (,$(findstring cc110x,$(USEMODULE))) INCLUDES += -I$(RIOTBASE)/drivers/cc110x/ SRC += sc_cc1100.c diff --git a/sys/shell/commands/sc_cc2420.c b/sys/shell/commands/sc_cc2420.c new file mode 100644 index 0000000000..7da2dd7176 --- /dev/null +++ b/sys/shell/commands/sc_cc2420.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include + +#define TEXT_SIZE CC2420_MAX_DATA_LENGTH + +char text_msg[TEXT_SIZE]; +msg_t mesg; +transceiver_command_t tcmd; + +void _cc2420_get_set_address_handler(char *addr) { + uint16_t a; + + tcmd.transceivers = TRANSCEIVER_CC2420; + tcmd.data = &a; + mesg.content.ptr = (char*) &tcmd; + a = atoi(addr+5); + if (strlen(addr) > 5) { + printf("[cc2420] Trying to set address %i\n", a); + mesg.type = SET_ADDRESS; + } + else { + mesg.type = GET_ADDRESS; + } + msg_send_receive(&mesg, &mesg, transceiver_pid); + printf("[cc2420] Got address: %i\n", a); +} + +void _cc2420_get_set_channel_handler(char *chan) { + int16_t c; + + tcmd.transceivers = TRANSCEIVER_CC2420; + tcmd.data = &c; + mesg.content.ptr = (char*) &tcmd; + c = atoi(chan+5); + if (strlen(chan) > 5) { + printf("[cc2420] Trying to set channel %i\n", c); + mesg.type = SET_CHANNEL; + } + else { + mesg.type = GET_CHANNEL; + } + msg_send_receive(&mesg, &mesg, transceiver_pid); + printf("[cc2420] Got channel: %i\n", c); +} + +void _cc2420_get_set_pan_handler(char *pan) { + uint16_t p; + + tcmd.transceivers = TRANSCEIVER_CC2420; + tcmd.data = &p; + mesg.content.ptr = (char*) &tcmd; + p = atoi(pan+4); + if (strlen(pan) > 4) { + printf("[cc2420] Trying to set pan %i\n", p); + mesg.type = SET_PAN; + } + else { + mesg.type = GET_PAN; + } + msg_send_receive(&mesg, &mesg, transceiver_pid); + printf("[cc2420] Got pan: %i\n", p); +} + +void _cc2420_send_handler(char *pkt) { + radio_packet_t p; + uint32_t response; + uint16_t addr; + char *tok; + + tcmd.transceivers = TRANSCEIVER_CC2420; + tcmd.data = &p; + + tok = strtok(pkt+7, " "); + if (tok) { + addr = atoi(tok); + tok = strtok(NULL, " "); + if (tok) { + memset(text_msg, 0, TEXT_SIZE); + memcpy(text_msg, tok, strlen(tok)); + /* if (sscanf(pkt, "txtsnd %hu %s", &(addr), text_msg) == 2) {*/ + p.data = (uint8_t*) text_msg; + p.length = strlen(text_msg) + 1; + p.dst = addr; + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + printf("[cc2420] Sending packet of length %u to %u: %s\n", p.length, p.dst, (char*) p.data); + msg_send_receive(&mesg, &mesg, transceiver_pid); + response = mesg.content.value; + printf("[cc2420] Packet sent: %lu\n", response); + return; + } + } + puts("Usage:\ttxtsnd "); +} + +void _cc2420_monitor_handler(char *mode) { + unsigned int m; + + tcmd.transceivers = TRANSCEIVER_CC2420; + tcmd.data = &m; + mesg.content.ptr = (char*) &tcmd; + m = atoi(mode+8); + if (strlen(mode) > 8) { + printf("Setting monitor mode: %u\n", m); + mesg.type = SET_MONITOR; + msg_send(&mesg, transceiver_pid, 1); + } + else { + puts("Usage:\nmonitor "); + } +} diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index 037045a288..cd74d31ecb 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -43,6 +43,16 @@ extern void _cc110x_ng_monitor_handler(char *mode); #endif #endif +#ifdef MODULE_TRANSCEIVER +#ifdef MODULE_CC2420 +extern void _cc2420_get_set_address_handler(char *addr); +extern void _cc2420_get_set_channel_handler(char *chan); +extern void _cc2420_get_set_pan_handler(char *pan); +extern void _cc2420_send_handler(char *pkt); +extern void _cc2420_monitor_handler(char *mode); +#endif +#endif + #ifdef MODULE_MCI extern void _get_sectorsize(char *unused); extern void _get_blocksize(char* unused); @@ -87,6 +97,15 @@ const shell_command_t _shell_command_list[] = { {"monitor", "Enables or disables address checking for the CC1100 transceiver", _cc110x_ng_monitor_handler}, #endif #endif +#ifdef MODULE_TRANSCEIVER +#ifdef MODULE_CC2420 + {"addr", "Gets or sets the address for the CC2420 transceiver", _cc2420_get_set_address_handler}, + {"chan", "Gets or sets the channel for the CC2420 transceiver", _cc2420_get_set_channel_handler}, + {"pan", "Gets or sets the pan id for the CC2420 transceiver", _cc2420_get_set_pan_handler}, + {"txtsnd", "Sends a text message to a given node via the C2420 transceiver", _cc2420_send_handler}, + {"monitor", "Enables or disables address checking for the CC2420 transceiver", _cc2420_monitor_handler}, +#endif +#endif #ifdef MODULE_MCI {DISK_READ_SECTOR_CMD, "Reads the specified sector of inserted memory card", _read_sector}, {DISK_READ_BYTES_CMD, "Reads the specified bytes from inserted memory card", _read_bytes}, diff --git a/sys/transceiver/Makefile b/sys/transceiver/Makefile index 3d01f44b6d..f3718a1d15 100644 --- a/sys/transceiver/Makefile +++ b/sys/transceiver/Makefile @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I$(RIOTBAE)/drivers/include -I$(RIOTBASE)/drivers/cc110x_ng/include -I../lib -I$(RIOTCPU)/$(CPU)/include -I../net -I../../core/include +INCLUDES = -I../include -I$(RIOTBAE)/drivers/include -I$(RIOTBASE)/drivers/cc110x_ng/include -I../lib -I$(RIOTCPU)/$(CPU)/include -I../net -I../../core/include -I$(RIOTBASE)/drivers/cc2420/include -I$(RIOTBASE)/sys/net/ieee802154/ MODULE =transceiver include $(MAKEBASE)/Makefile.base diff --git a/sys/transceiver/transceiver.c b/sys/transceiver/transceiver.c index aff05018da..ed23fe8c1e 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -25,6 +25,14 @@ #endif #endif +#ifdef MODULE_CC2420 +#include +#if (CC2420_MAX_DATA_LENGTH > PAYLOAD_SIZE) + #undef PAYLOAD_SIZE + #define PAYLOAD_SIZE (CC2420_MAX_DATA_LENGTH) +#endif +#endif + //#define ENABLE_DEBUG (1) #include @@ -69,12 +77,17 @@ static void receive_cc110x_packet(radio_packet_t *trans_p); #elif MODULE_CC110X void cc1100_packet_monitor(void* payload, int payload_size, protocol_t protocol, packet_info_t* packet_info); void receive_cc1100_packet(radio_packet_t *trans_p); +#elif MODULE_CC2420 +static void receive_cc2420_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); static int16_t get_address(transceiver_type_t t); static int16_t set_address(transceiver_type_t t, void *address); +static uint16_t get_pan(transceiver_type_t t); +static uint16_t set_pan(transceiver_type_t t, void *pan); + static void set_monitor(transceiver_type_t t, void *mode); static void powerdown(transceiver_type_t t); static void switch_to_rx(transceiver_type_t t); @@ -96,7 +109,7 @@ void transceiver_init(transceiver_type_t t) { reg[i].transceivers = TRANSCEIVER_NONE; reg[i].pid = 0; } - if (t & TRANSCEIVER_CC1100) { + if (t & (TRANSCEIVER_CC1100 || TRANSCEIVER_CC2420)) { transceivers |= t; } else { @@ -110,15 +123,23 @@ int transceiver_start(void) { if (transceiver_pid < 0) { puts("Error creating transceiver thread"); } +#ifdef MODULE_CC110X_NG else if (transceivers & TRANSCEIVER_CC1100) { DEBUG("Transceiver started for CC1100\n"); -#ifdef MODULE_CC110X_NG cc110x_init(transceiver_pid); -#else + } +#elif MODULE_CC110X + else if (transceivers & TRANSCEIVER_CC1100) { + DEBUG("Transceiver started for CC1100\n"); cc1100_init(); cc1100_set_packet_monitor(cc1100_packet_monitor); -#endif } +#elif MODULE_CC2420 + else if(transceivers & TRANSCEIVER_CC2420) { + DEBUG("Transceiver started for CC2420\n"); + cc2420_init(transceiver_pid); + } +#endif return transceiver_pid; } @@ -164,6 +185,9 @@ void run(void) { case RCV_PKT_CC1100: receive_packet(m.type, m.content.value); break; + case RCV_PKT_CC2420: + receive_packet(m.type, m.content.value); + break; case SND_PKT: response = send_packet(cmd->transceivers, cmd->data); m.content.value = response; @@ -194,6 +218,14 @@ void run(void) { case SWITCH_RX: switch_to_rx(cmd->transceivers); break; + case GET_PAN: + *((int16_t*) cmd->data) = get_pan(cmd->transceivers); + msg_reply(&m, &m); + break; + case SET_PAN: + *((int16_t*) cmd->data) = set_pan(cmd->transceivers, cmd->data); + msg_reply(&m, &m); + break; #ifdef DBG_IGNORE case DBG_IGN: printf("Transceiver PID: %i (%p), rx_buffer_next: %u\n", transceiver_pid, &transceiver_pid, rx_buffer_next); @@ -238,6 +270,9 @@ static void receive_packet(uint16_t type, uint8_t pos) { case RCV_PKT_CC1100: t = TRANSCEIVER_CC1100; break; + case RCV_PKT_CC2420: + t = TRANSCEIVER_CC2420; + break; default: t = TRANSCEIVER_NONE; break; @@ -263,8 +298,13 @@ static void receive_packet(uint16_t type, uint8_t pos) { if (type == RCV_PKT_CC1100) { #ifdef MODULE_CC110X_NG receive_cc110x_packet(trans_p); -#else +#elif MODULE_CC110X receive_cc1100_packet(trans_p); +#endif + } + else if (type == RCV_PKT_CC2420) { +#ifdef MODULE_CC2420 + receive_cc2420_packet(trans_p); #endif } else { @@ -328,7 +368,26 @@ void receive_cc1100_packet(radio_packet_t *trans_p) { } #endif - + +#ifdef MODULE_CC2420 +void receive_cc2420_packet(radio_packet_t *trans_p) { + DEBUG("Handling CC2420 packet\n"); + dINT(); + cc2420_packet_t p = cc2420_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, CC2420_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 * CC2420_MAX_DATA_LENGTH]); + DEBUG("Content: %s\n", trans_p->data); +} +#endif + /*------------------------------------------------------------------------------------*/ /* * @brief Sends a radio packet to the receiver @@ -349,6 +408,10 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) { cc110x_packet_t cc110x_pkt; #endif +#ifdef MODULE_CC2420 + cc2420_packet_t cc2420_pkt; +#endif + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG @@ -357,7 +420,7 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) { cc110x_pkt.flags = 0; memcpy(cc110x_pkt.data, p.data, p.length); res = cc110x_send(&cc110x_pkt); -#else +#elif MODULE_CC110X memcpy(cc1100_pkt, p.data, p.length); if ((snd_ret = cc1100_send_csmaca(p.dst, 4, 0, (char*) cc1100_pkt, p.length)) < 0) { DEBUG("snd_ret (%u) = %i\n", p.length, snd_ret); @@ -368,6 +431,22 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) { } #endif break; +#ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: + cc2420_pkt.frame.payload_len = p.length; + cc2420_pkt.frame.dest_addr[1] = (uint8_t)(p.dst >> 8); + cc2420_pkt.frame.dest_addr[0] = (uint8_t)(p.dst & 0xFF); + cc2420_pkt.frame.dest_pan_id = cc2420_get_pan(); + cc2420_pkt.frame.fcf.dest_addr_m = 2; + cc2420_pkt.frame.fcf.src_addr_m = 2; + cc2420_pkt.frame.fcf.ack_req = 0; + cc2420_pkt.frame.fcf.sec_enb = 0; + cc2420_pkt.frame.fcf.frame_type = 1; + cc2420_pkt.frame.fcf.frame_pend = 0; + cc2420_pkt.frame.payload = p.data; + res = cc2420_send(&cc2420_pkt); + break; +#endif default: puts("Unknown transceiver"); break; @@ -390,8 +469,12 @@ static int16_t set_channel(transceiver_type_t t, void *channel) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_set_channel(c); -#else +#elif MODULE_CC110X return cc1100_set_channel(c); +#endif + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + return cc2420_set_channel(c); #endif default: return -1; @@ -410,8 +493,51 @@ static int16_t get_channel(transceiver_type_t t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_get_channel(); -#else +#elif MODULE_CC110X return cc1100_get_channel(); +#endif + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + return cc2420_get_channel(); +#endif + default: + return -1; + } +} + +/*------------------------------------------------------------------------------------*/ +/* + * @brief Sets the pan for the CC2420 transceiver device + * + * @param t The transceiver device + * @param channel The channel to be set + * + * @return The pan AFTER calling the set command, -1 on error + */ +static uint16_t set_pan(transceiver_type_t t, void *pan) { + uint16_t c = *((uint16_t*) pan); + switch (t) { + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + return cc2420_set_pan(c); +#endif + default: + return -1; + } +} + +/* + * @brief Get the pan for the cc2420 transceiver device + * + * @param t The transceiver device + * + * @return The current pan of the transceiver, -1 on error + */ +static uint16_t get_pan(transceiver_type_t t) { + switch (t) { + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + return cc2420_get_pan(); #endif default: return -1; @@ -430,8 +556,12 @@ static int16_t get_address(transceiver_type_t t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_get_address(); -#else +#elif MODULE_CC110X return cc1100_get_address(); +#endif + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + return cc2420_get_address(); #endif default: return -1; @@ -452,8 +582,12 @@ static int16_t set_address(transceiver_type_t t, void *address) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_set_address(addr); -#else +#elif MODULE_CC110X return cc1100_set_address(addr); +#endif + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + return cc2420_set_address(addr); #endif default: return -1; @@ -471,6 +605,11 @@ static void set_monitor(transceiver_type_t t, void *mode) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG cc110x_set_monitor(*((uint8_t*) mode)); +#endif + break; + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + cc2420_set_monitor(*((uint8_t*) mode)); #endif break; default: @@ -496,6 +635,11 @@ static void switch_to_rx(transceiver_type_t t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG cc110x_switch_to_rx(); +#endif + break; + case TRANSCEIVER_CC2420: +#ifdef MODULE_CC2420 + cc2420_switch_to_rx(); #endif break; default: