Add ADuCRF101 radio driver
This commit is contained in:
parent
5673b46e86
commit
b7373edf8c
|
@ -39,7 +39,7 @@
|
||||||
@date May 08th 2013
|
@date May 08th 2013
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "include.h"
|
#include "aducrf101-include.h"
|
||||||
|
|
||||||
// 1.0 of the Engine
|
// 1.0 of the Engine
|
||||||
#define RIE_ENGINE_MAJOR_VERSION 1UL
|
#define RIE_ENGINE_MAJOR_VERSION 1UL
|
||||||
|
|
|
@ -89,6 +89,10 @@ ifdef __STACK_SIZE
|
||||||
CFLAGS += -D__STACK_SIZE=$(__STACK_SIZE)
|
CFLAGS += -D__STACK_SIZE=$(__STACK_SIZE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef RF_CHANNEL
|
||||||
|
CFLAGS += -DRF_CHANNEL=$(RF_CHANNEL)
|
||||||
|
endif
|
||||||
|
|
||||||
# HSI internal oscillator by default
|
# HSI internal oscillator by default
|
||||||
CFLAGS += -DF_CPU=16000000
|
CFLAGS += -DF_CPU=16000000
|
||||||
|
|
||||||
|
@ -102,9 +106,11 @@ CONTIKI_CPU_DIRS += dev
|
||||||
CONTIKI_SOURCEFILES += uart.c
|
CONTIKI_SOURCEFILES += uart.c
|
||||||
CONTIKI_SOURCEFILES += clock.c
|
CONTIKI_SOURCEFILES += clock.c
|
||||||
CONTIKI_SOURCEFILES += watchdog.c
|
CONTIKI_SOURCEFILES += watchdog.c
|
||||||
|
CONTIKI_SOURCEFILES += radio.c
|
||||||
|
|
||||||
CONTIKI_CPU_DIRS += Common
|
CONTIKI_CPU_DIRS += Common
|
||||||
CONTIKI_SOURCEFILES += system_ADuCRF101.c
|
CONTIKI_SOURCEFILES += system_ADuCRF101.c
|
||||||
|
CONTIKI_SOURCEFILES += radioeng.c
|
||||||
|
|
||||||
ASFLAGS += -c $(CFLAGS)
|
ASFLAGS += -c $(CFLAGS)
|
||||||
|
|
||||||
|
|
347
cpu/arm/aducrf101/dev/radio.c
Normal file
347
cpu/arm/aducrf101/dev/radio.c
Normal file
|
@ -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 <jim.paris@rigado.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <aducrf101-contiki.h>
|
||||||
|
#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,
|
||||||
|
};
|
|
@ -60,7 +60,7 @@
|
||||||
#define NETSTACK_CONF_NETWORK sicslowpan_driver
|
#define NETSTACK_CONF_NETWORK sicslowpan_driver
|
||||||
#define NETSTACK_CONF_MAC nullmac_driver
|
#define NETSTACK_CONF_MAC nullmac_driver
|
||||||
#define NETSTACK_CONF_RDC nullrdc_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_FRAMER framer_802154
|
||||||
|
|
||||||
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
#define NETSTACK_CONF_NETWORK rime_driver
|
#define NETSTACK_CONF_NETWORK rime_driver
|
||||||
#define NETSTACK_CONF_MAC csma_driver
|
#define NETSTACK_CONF_MAC csma_driver
|
||||||
#define NETSTACK_CONF_RDC nullrdc_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_FRAMER framer_802154
|
||||||
|
|
||||||
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
#define PACKETBUF_CONF_ATTRS_INLINE 1
|
#define PACKETBUF_CONF_ATTRS_INLINE 1
|
||||||
|
|
||||||
#ifndef RF_CHANNEL
|
#ifndef RF_CHANNEL
|
||||||
#define RF_CHANNEL 26
|
#define RF_CHANNEL 868000000
|
||||||
#endif /* RF_CHANNEL */
|
#endif /* RF_CHANNEL */
|
||||||
|
|
||||||
#define CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT 0
|
#define CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT 0
|
||||||
|
|
|
@ -64,8 +64,8 @@ SENSORS(&button_sensor);
|
||||||
#define SERIAL_ID { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
|
#define SERIAL_ID { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t serial_id[] = SERIAL_ID;
|
uint8_t serial_id[] = SERIAL_ID;
|
||||||
static uint16_t node_id = 0x1122;
|
uint16_t node_id = 0x0102;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -95,6 +95,15 @@ set_rime_addr(void)
|
||||||
printf("%d\n", addr.u8[i]);
|
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;
|
int contiki_argc = 0;
|
||||||
char **contiki_argv;
|
char **contiki_argv;
|
||||||
|
|
||||||
|
@ -126,6 +135,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
queuebuf_init();
|
queuebuf_init();
|
||||||
|
|
||||||
|
set_rf_params();
|
||||||
netstack_init();
|
netstack_init();
|
||||||
printf("MAC %s RDC %s NETWORK %s\n",
|
printf("MAC %s RDC %s NETWORK %s\n",
|
||||||
NETSTACK_MAC.name, NETSTACK_RDC.name, NETSTACK_NETWORK.name);
|
NETSTACK_MAC.name, NETSTACK_RDC.name, NETSTACK_NETWORK.name);
|
||||||
|
|
Loading…
Reference in a new issue