From b7373edf8c2f9298e7841a33523a01fab3246af5 Mon Sep 17 00:00:00 2001 From: Jim Paris Date: Mon, 23 Jun 2014 16:07:53 -0400 Subject: [PATCH] Add ADuCRF101 radio driver --- cpu/arm/aducrf101/Common/radioeng.c | 2 +- cpu/arm/aducrf101/Makefile.aducrf101 | 6 + cpu/arm/aducrf101/dev/radio.c | 347 +++++++++++++++++++++++ platform/ev-aducrf101mkxz/contiki-conf.h | 6 +- platform/ev-aducrf101mkxz/contiki-main.c | 14 +- 5 files changed, 369 insertions(+), 6 deletions(-) create mode 100644 cpu/arm/aducrf101/dev/radio.c diff --git a/cpu/arm/aducrf101/Common/radioeng.c b/cpu/arm/aducrf101/Common/radioeng.c index b37a68bfc..5ad2529b7 100644 --- a/cpu/arm/aducrf101/Common/radioeng.c +++ b/cpu/arm/aducrf101/Common/radioeng.c @@ -39,7 +39,7 @@ @date May 08th 2013 **/ -#include "include.h" +#include "aducrf101-include.h" // 1.0 of the Engine #define RIE_ENGINE_MAJOR_VERSION 1UL diff --git a/cpu/arm/aducrf101/Makefile.aducrf101 b/cpu/arm/aducrf101/Makefile.aducrf101 index c5b0708e2..a613fd28f 100644 --- a/cpu/arm/aducrf101/Makefile.aducrf101 +++ b/cpu/arm/aducrf101/Makefile.aducrf101 @@ -89,6 +89,10 @@ ifdef __STACK_SIZE CFLAGS += -D__STACK_SIZE=$(__STACK_SIZE) endif +ifdef RF_CHANNEL + CFLAGS += -DRF_CHANNEL=$(RF_CHANNEL) +endif + # HSI internal oscillator by default CFLAGS += -DF_CPU=16000000 @@ -102,9 +106,11 @@ CONTIKI_CPU_DIRS += dev CONTIKI_SOURCEFILES += uart.c CONTIKI_SOURCEFILES += clock.c CONTIKI_SOURCEFILES += watchdog.c +CONTIKI_SOURCEFILES += radio.c CONTIKI_CPU_DIRS += Common CONTIKI_SOURCEFILES += system_ADuCRF101.c +CONTIKI_SOURCEFILES += radioeng.c ASFLAGS += -c $(CFLAGS) diff --git a/cpu/arm/aducrf101/dev/radio.c b/cpu/arm/aducrf101/dev/radio.c new file mode 100644 index 000000000..243afccb2 --- /dev/null +++ b/cpu/arm/aducrf101/dev/radio.c @@ -0,0 +1,347 @@ +/** + * Copyright (c) 2014, Analog Devices, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted (subject to the limitations in the + * disclaimer below) provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE + * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \author Jim Paris + */ + +#include +#include + +#include +#include "radio.h" + +#define MAX_PACKET_LEN 240 + +static uint8_t tx_buf[MAX_PACKET_LEN]; + +#ifndef ADUCRF101_RADIO_BASE_CONFIG +#define ADUCRF101_RADIO_BASE_CONFIG DR_38_4kbps_Dev20kHz +#endif + +static RIE_BaseConfigs base_config = ADUCRF101_RADIO_BASE_CONFIG; +static int current_channel = 915000000; +static int current_power = 31; +static int radio_is_on = 0; + +/*---------------------------------------------------------------------------*/ +/* "Channel" is really frequency, and can be within the bands: + 431000000 Hz to 464000000 Hz + 862000000 Hz to 928000000 Hz + */ +#define MIN_CHANNEL 431000000 +#define MAX_CHANNEL 928000000 +static int +_set_channel(int freq) +{ + if(freq < 431000000) { + freq = 431000000; + } else if(freq > 464000000 && freq < 663000000) { + freq = 464000000; + } else if(freq >= 663000000 && freq < 862000000) { + freq = 862000000; + } else if(freq > 928000000) { + freq = 928000000; + } + current_channel = freq; + if(RadioSetFrequency(freq) != RIE_Success) { + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +/* "Power" covers both PA type and power level: + 0 through 15 means single-ended, power level 0 through 15 + 16 through 31 means differential, power level 0 through 15 */ +#define MIN_POWER 0 +#define MAX_POWER 31 +static int +_set_power(int power) +{ + RIE_Responses ret; + if(power < 0) { + power = 0; + } + if(power > 31) { + power = 31; + } + if(power <= 15) { + ret = RadioTxSetPA(SingleEndedPA, power); + } else { + ret = RadioTxSetPA(DifferentialPA, power - 16); + } + current_power = power; + if(ret != RIE_Success) { + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ +/** Turn the radio on. */ +static int +on(void) +{ + if(radio_is_on) { + return 1; + } + + /* Power radio on */ + if(RadioInit(base_config) != RIE_Success) { + return 0; + } + + /* Ensure channel and power are set */ + if(_set_channel(current_channel) != RADIO_RESULT_OK) { + return 0; + } + if(_set_power(current_power) != RADIO_RESULT_OK) { + return 0; + } + + /* Enter receive mode */ + RadioRxPacketVariableLen(); + + radio_is_on = 1; + return 1; +} +/*---------------------------------------------------------------------------*/ +/** Turn the radio off. */ +static int +off(void) +{ + if(!radio_is_on) { + return 1; + } + if(RadioPowerOff() != RIE_Success) { + return 0; + } + radio_is_on = 0; + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + off(); + on(); + return 1; +} +/*---------------------------------------------------------------------------*/ +/** Prepare the radio with a packet to be sent. */ +static int +prepare(const void *payload, unsigned short payload_len) +{ + /* Truncate long packets */ + if(payload_len > MAX_PACKET_LEN) { + payload_len = MAX_PACKET_LEN; + } + memcpy(tx_buf, payload, payload_len); + return 0; +} +/*---------------------------------------------------------------------------*/ +/** Send the packet that has previously been prepared. */ +static int +transmit(unsigned short transmit_len) +{ + /* Transmit the packet */ + if(transmit_len > MAX_PACKET_LEN) { + transmit_len = MAX_PACKET_LEN; + } + if(RadioTxPacketVariableLen(transmit_len, tx_buf) != RIE_Success) { + return RADIO_TX_ERR; + } + while(!RadioTxPacketComplete()) + continue; + + /* Enter receive mode immediately after transmitting a packet */ + RadioRxPacketVariableLen(); + + return RADIO_TX_OK; +} +/*---------------------------------------------------------------------------*/ +/** Prepare & transmit a packet. */ +static int +send(const void *payload, unsigned short payload_len) +{ + prepare(payload, payload_len); + return transmit(payload_len); +} +/** Read a received packet into a buffer. */ +static int +read(void *buf, unsigned short buf_len) +{ + uint8_t packet_len; + + if(buf_len > MAX_PACKET_LEN) { + buf_len = MAX_PACKET_LEN; + } + + /* Read already-received packet */ + if(RadioRxPacketRead(buf_len, &packet_len, buf, NULL) != RIE_Success) { + return 0; + } + + if(packet_len > buf_len) { + packet_len = buf_len; + } + + /* Re-enter receive mode immediately after receiving a packet */ + RadioRxPacketVariableLen(); + + return packet_len; +} +/*---------------------------------------------------------------------------*/ +/** Perform a Clear-Channel Assessment (CCA) to find out if there is + a packet in the air or not. */ +static int +channel_clear(void) +{ + /* Not implemented; assume clear */ + return 1; +} +/*---------------------------------------------------------------------------*/ +/** Check if the radio driver is currently receiving a packet */ +static int +receiving_packet(void) +{ + /* Not implemented; assume no. */ + return 0; +} +/*---------------------------------------------------------------------------*/ +/** Check if the radio driver has just received a packet */ +static int +pending_packet(void) +{ + if(RadioRxPacketAvailable()) { + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** Get a radio parameter value. */ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch(param) { + case RADIO_PARAM_RSSI: + { + int8_t dbm; + if(RadioRadioGetRSSI(&dbm) != RIE_Success) { + return RADIO_RESULT_ERROR; + } + *value = dbm; + return RADIO_RESULT_OK; + } + + case RADIO_PARAM_CHANNEL: + *value = current_channel; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MIN: + *value = MIN_CHANNEL; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = MAX_CHANNEL; + return RADIO_RESULT_OK; + + case RADIO_PARAM_TXPOWER: + *value = current_power; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MIN: + *value = MIN_POWER; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = MAX_POWER; + return RADIO_RESULT_OK; + + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +/** Set a radio parameter value. */ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + switch(param) { + case RADIO_PARAM_CHANNEL: + return _set_channel(value); + + case RADIO_PARAM_TXPOWER: + return _set_power(value); + + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +/** + * Get a radio parameter object. The argument 'dest' must point to a + * memory area of at least 'size' bytes, and this memory area will + * contain the parameter object if the function succeeds. + */ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +/** + * Set a radio parameter object. The memory area referred to by the + * argument 'src' will not be accessed after the function returns. + */ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver aducrf101_radio_driver = { + .init = init, + .prepare = prepare, + .transmit = transmit, + .send = send, + .read = read, + .channel_clear = channel_clear, + .receiving_packet = receiving_packet, + .pending_packet = pending_packet, + .on = on, + .off = off, + .get_value = get_value, + .set_value = set_value, + .get_object = get_object, + .set_object = set_object, +}; diff --git a/platform/ev-aducrf101mkxz/contiki-conf.h b/platform/ev-aducrf101mkxz/contiki-conf.h index 529afe891..98cc0084f 100644 --- a/platform/ev-aducrf101mkxz/contiki-conf.h +++ b/platform/ev-aducrf101mkxz/contiki-conf.h @@ -60,7 +60,7 @@ #define NETSTACK_CONF_NETWORK sicslowpan_driver #define NETSTACK_CONF_MAC nullmac_driver #define NETSTACK_CONF_RDC nullrdc_driver -#define NETSTACK_CONF_RADIO NEW_ADI_driver +#define NETSTACK_CONF_RADIO aducrf101_radio_driver #define NETSTACK_CONF_FRAMER framer_802154 #define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 @@ -74,7 +74,7 @@ #define NETSTACK_CONF_NETWORK rime_driver #define NETSTACK_CONF_MAC csma_driver #define NETSTACK_CONF_RDC nullrdc_driver -#define NETSTACK_CONF_RADIO NEW_AD_driver +#define NETSTACK_CONF_RADIO aducrf101_radio_driver #define NETSTACK_CONF_FRAMER framer_802154 #define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 @@ -98,7 +98,7 @@ #define PACKETBUF_CONF_ATTRS_INLINE 1 #ifndef RF_CHANNEL -#define RF_CHANNEL 26 +#define RF_CHANNEL 868000000 #endif /* RF_CHANNEL */ #define CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT 0 diff --git a/platform/ev-aducrf101mkxz/contiki-main.c b/platform/ev-aducrf101mkxz/contiki-main.c index cbf05f29c..cd4718932 100644 --- a/platform/ev-aducrf101mkxz/contiki-main.c +++ b/platform/ev-aducrf101mkxz/contiki-main.c @@ -64,8 +64,8 @@ SENSORS(&button_sensor); #define SERIAL_ID { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 } #endif -static uint8_t serial_id[] = SERIAL_ID; -static uint16_t node_id = 0x1122; +uint8_t serial_id[] = SERIAL_ID; +uint16_t node_id = 0x0102; /*---------------------------------------------------------------------------*/ static void @@ -95,6 +95,15 @@ set_rime_addr(void) printf("%d\n", addr.u8[i]); } /*---------------------------------------------------------------------------*/ +static void +set_rf_params(void) +{ + int chan; + NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, RF_CHANNEL); + NETSTACK_RADIO.get_value(RADIO_PARAM_CHANNEL, &chan); + printf("RF channel set to %d Hz\n", chan); +} +/*---------------------------------------------------------------------------*/ int contiki_argc = 0; char **contiki_argv; @@ -126,6 +135,7 @@ main(int argc, char **argv) queuebuf_init(); + set_rf_params(); netstack_init(); printf("MAC %s RDC %s NETWORK %s\n", NETSTACK_MAC.name, NETSTACK_RDC.name, NETSTACK_NETWORK.name);