Merge pull request #2216 from herjulf/CCA

Atmel radio; Support for RADIO_PARAM_CCA_THRESHOLD plus rf_environment example
This commit is contained in:
George Oikonomou 2017-06-02 22:40:27 +01:00 committed by GitHub
commit 3800cb18a9
6 changed files with 338 additions and 11 deletions

View file

@ -357,6 +357,35 @@ rf230_set_short_addr(uint16_t addr)
hal_register_write(RG_SHORT_ADDR_1, (addr >> 8));
}
#define RSSI_BASE_VAL (-90)
/* Returns the current CCA threshold in dBm */
static radio_value_t
rf230_get_cca_threshold()
{
radio_value_t cca_thresh = 0;
cca_thresh = hal_subregister_read(SR_CCA_ED_THRES);
cca_thresh = RSSI_BASE_VAL + 2 * cca_thresh;
return cca_thresh;
}
/* Sets the CCA threshold in dBm */
static radio_value_t
rf230_set_cca_threshold(radio_value_t cca_thresh)
{
if(cca_thresh > -60) /* RSSI_BASE_VAL - 2 * 0xF */
cca_thresh = -60;
cca_thresh = (RSSI_BASE_VAL - cca_thresh)/2;
if(cca_thresh < 0)
cca_thresh = - cca_thresh;
hal_subregister_write(SR_CCA_ED_THRES, cca_thresh);
return cca_thresh;
}
/*---------------------------------------------------------------------------*/
static radio_result_t
get_value(radio_param_t param, radio_value_t *value)
@ -367,13 +396,10 @@ get_value(radio_param_t param, radio_value_t *value)
switch(param) {
case RADIO_PARAM_POWER_MODE:
/* *value = (REG(RFCORE_XREG_RXENABLE) && RFCORE_XREG_RXENABLE_RXENMASK) == 0 )?
RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON; */
*value = rf230_is_sleeping() ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON;
return RADIO_RESULT_OK;
case RADIO_PARAM_TX_MODE:
return RADIO_RESULT_OK;
case RADIO_PARAM_CHANNEL:
*value = (radio_value_t)rf230_get_channel();
return RADIO_RESULT_OK;
@ -399,7 +425,7 @@ get_value(radio_param_t param, radio_value_t *value)
*value = rf230_get_txpower();
return RADIO_RESULT_OK;
case RADIO_PARAM_CCA_THRESHOLD:
/* *value = get_cca_threshold(); */
*value = rf230_get_cca_threshold();
return RADIO_RESULT_OK;
case RADIO_PARAM_RSSI:
*value = rf230_get_raw_rssi();
@ -468,14 +494,15 @@ set_value(radio_param_t param, radio_value_t value)
return RADIO_RESULT_OK;
case RADIO_PARAM_TXPOWER:
if(value < TX_PWR_MIN || value > TX_PWR_MAX) {
/* MIN = 15, MAX = 0 */
if(value > TX_PWR_MIN || value < TX_PWR_MAX) {
return RADIO_RESULT_INVALID_VALUE;
}
rf230_set_txpower(value);
return RADIO_RESULT_OK;
case RADIO_PARAM_CCA_THRESHOLD:
/* set_cca_threshold(value); */
rf230_set_cca_threshold(value);
return RADIO_RESULT_OK;
default:
return RADIO_RESULT_NOT_SUPPORTED;
@ -584,8 +611,7 @@ radio_get_trx_state(void)
* states.
* \retval false The radio transceiver is not sleeping.
*/
#if 0
static bool radio_is_sleeping(void)
static bool rf230_is_sleeping(void)
{
bool sleeping = false;
@ -597,7 +623,6 @@ static bool radio_is_sleeping(void)
return sleeping;
}
#endif
/*----------------------------------------------------------------------------*/
/** \brief This function will reset the state machine (to TRX_OFF) from any of
* its states, except for the SLEEP state.

View file

@ -223,7 +223,7 @@ uint8_t rf230_get_rpc(void);
void rf230_set_promiscuous_mode(bool isPromiscuous);
bool rf230_is_ready_to_send();
static bool rf230_is_sleeping(void);
extern uint8_t rf230_last_correlation,rf230_last_rssi,rf230_smallest_rssi;
uint8_t rf230_get_raw_rssi(void);

View file

@ -0,0 +1,20 @@
CONTIKI_PROJECT=rf_environment
all: $(CONTIKI_PROJECT)
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
# We use floating vars. Add library.
PRINTF_LIB_FLT = -Wl,-u,vfprintf -lprintf_flt -lm
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
PRINTF_LIB = $(PRINTF_LIB_FLT)
CLIBS = $(PRINTF_LIB)
CUSTOM_RULE_LINK = 1
%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a
$(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ $(CLIBS)
CONTIKI=../../
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1,66 @@
Non-intrusive monitoring of the RF-environment
==============================================
rf_environment runs the clear channel assessment (CCA) test over
all 802.15.4 channels and reports stats per channel. The CCA test
is run for different CCA thresholds from -60dBm to -90dBm. CCA is
a non-destructive for the rf-environment as it's just listens.
Best and worst channel is printed as average rf activity.
See example below from Uppsala Kungs-Vaksalagatan. 2017-05-08
and Electrum Stockholm. Originally developed for the Atmel avr-rss2
platform.
Probability for not passing a CCA check in percent per channel.
3-minute samples. Of course this just snapshots to illustrate
functionality
<pre>
Chan: 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
---------------------------------------------------------------------
cca_thresh=-82dBm 0 0 7 0 1 2 2 0 0 0 0 6 30 5 0 1 Best=11 Worst=23 Ave=3.09
cca_thresh=-80dBm 0 0 1 0 1 0 3 1 0 0 1 16 15 1 2 0 Best=11 Worst=22 Ave=2.31
cca_thresh=-78dBm 0 0 4 10 0 2 2 2 1 2 0 12 23 4 1 1 Best=11 Worst=23 Ave=3.65
cca_thresh=-76dBm 0 0 12 8 4 0 6 4 10 3 1 24 15 0 1 1 Best=11 Worst=22 Ave=5.37
cca_thresh=-74dBm 0 1 1 2 1 0 4 1 2 1 2 10 16 22 5 1 Best=11 Worst=24 Ave=3.96
cca_thresh=-72dBm 0 1 3 3 3 0 2 1 1 4 2 5 3 8 5 3 Best=11 Worst=24 Ave=2.26
cca_thresh=-70dBm 0 0 5 3 3 3 1 5 9 26 60 77 53 35 27 8 Best=11 Worst=22 Ave=19.40
cca_thresh=-68dBm 0 1 9 10 1 2 1 3 0 4 59 32 60 37 24 3 Best=11 Worst=23 Ave=14.89
cca_thresh=-66dBm 0 2 3 2 1 2 2 1 5 15 50 64 77 49 16 5 Best=11 Worst=23 Ave=17.87
cca_thresh=-64dBm 1 3 0 1 1 2 1 1 6 18 19 31 62 47 25 3 Best=13 Worst=23 Ave=13.35
cca_thresh=-62dBm 0 0 3 6 2 5 2 0 23 43 37 25 18 32 27 25 Best=11 Worst=20 Ave=15.14
cca_thresh=-60dBm 2 2 3 3 2 3 1 8 34 37 40 49 72 55 9 9 Best=17 Worst=23 Ave=20.17
cca_thresh=-90dBm 0 1 11 10 4 8 2 1 10 22 15 17 22 18 3 9 Best=11 Worst=20 Ave=9.06
cca_thresh=-88dBm 0 0 17 37 2 3 2 5 12 18 24 43 13 28 6 3 Best=11 Worst=22 Ave=12.90
cca_thresh=-86dBm 0 3 12 2 0 3 3 4 12 11 17 13 42 19 17 10 Best=11 Worst=23 Ave=10.05
cca_thresh=-84dBm 0 0 3 3 0 3 2 4 12 11 14 13 23 9 11 15 Best=11 Worst=23 Ave=7.33
cca_thresh=-82dBm 0 2 30 24 2 4 2 6 3 11 4 10 8 3 4 1 Best=11 Worst=13 Ave=6.66
cca_thresh=-80dBm 0 1 9 3 0 1 6 6 15 0 0 8 11 4 3 3 Best=11 Worst=19 Ave=4.05
cca_thresh=-78dBm 0 1 3 2 0 1 7 8 1 0 4 13 6 3 1 1 Best=11 Worst=22 Ave=2.79
cca_thresh=-76dBm 0 0 1 7 1 8 11 10 21 1 2 10 28 3 0 1 Best=11 Worst=23 Ave=6.15
cca_thresh=-74dBm 0 3 2 2 0 1 6 4 8 0 3 5 8 9 0 0 Best=11 Worst=24 Ave=2.77
cca_thresh=-72dBm 0 0 0 3 1 2 2 2 1 1 3 7 11 9 1 1 Best=11 Worst=23 Ave=2.40
cca_thresh=-70dBm 0 1 11 2 1 2 4 1 4 4 13 31 7 1 1 1 Best=11 Worst=22 Ave=4.69
cca_thresh=-68dBm 0 0 13 26 1 5 7 8 3 1 1 20 43 7 1 0 Best=11 Worst=23 Ave=8.21
cca_thresh=-66dBm 1 2 13 9 1 3 3 1 3 16 11 22 9 7 0 1 Best=25 Worst=22 Ave=5.79
cca_thresh=-64dBm 0 1 6 2 1 2 2 0 3 8 4 8 14 1 4 1 Best=11 Worst=23 Ave=3.10
cca_thresh=-62dBm 0 1 4 0 1 2 1 3 1 1 9 16 22 7 1 1 Best=11 Worst=23 Ave=3.91
cca_thresh=-60dBm 0 1 2 0 1 0 1 1 15 33 4 5 26 2 0 0 Best=11 Worst=20 Ave=5.34
cca_thresh=-90dBm 0 1 0 2 2 0 1 1 0 1 6 12 24 10 2 1 Best=11 Worst=23 Ave=3.64
cca_thresh=-88dBm 0 0 0 2 0 1 0 2 0 2 2 9 10 0 0 1 Best=11 Worst=23 Ave=1.54
Electrum Kista Stockolm (KTH/SICS etc)
cca_thresh=-62dBm 2 17 26 2 2 1 14 18 17 4 9 6 5 31 47 2 Best=16 Worst=25 Ave=12.07
cca_thresh=-60dBm 7 8 13 2 2 1 6 6 7 1 11 32 16 11 1 2 Best=16 Worst=22 Ave=7.54
cca_thresh=-90dBm 1 9 13 3 2 1 31 32 10 2 2 12 7 10 1 2 Best=11 Worst=18 Ave=8.17
cca_thresh=-88dBm 4 8 10 2 2 1 5 12 6 3 5 8 2 9 1 2 Best=16 Worst=18 Ave=4.45
cca_thresh=-86dBm 11 9 10 2 2 1 5 16 21 2 5 5 2 3 1 4 Best=25 Worst=19 Ave=5.88
cca_thresh=-84dBm 4 9 7 5 5 1 6 46 16 3 16 2 13 5 1 2 Best=25 Worst=18 Ave=8.38
cca_thresh=-82dBm 15 9 14 2 2 1 7 22 14 1 15 2 10 10 1 19 Best=25 Worst=18 Ave=8.68
cca_thresh=-80dBm 1 8 16 3 2 1 14 23 6 1 10 22 5 7 3 4 Best=11 Worst=18 Ave=7.38
cca_thresh=-78dBm 16 9 25 3 3 1 9 8 12 2 7 2 3 2 1 2 Best=16 Worst=13 Ave=6.13
cca_thresh=-76dBm 12 9 23 4 4 0 36 9 10 2 32 14 7 4 1 3 Best=16 Worst=17 Ave=10.13
cca_thresh=-74dBm 8 24 9 8 5 0 16 6 10 2 3 31 27 18 1 3 Best=16 Worst=22 Ave=10.32
cca_thresh=-72dBm 4 7 18 4 2 0 6 11 7 1 3 6 3 9 1 2 Best=16 Worst=13 Ave=4.80
</pre>

View file

@ -0,0 +1,11 @@
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
#define NETSTACK_CONF_RDC nullrdc_driver
#define NETSTACK_CONF_MAC nullmac_driver
#define NETSTACK_CONF_FRAMER framer_802154
#define NETSTACK_CONF_RADIO rf230_driver
#define RS232_BAUDRATE USART_BAUD_38400
#endif /* PROJECT_CONF_H_ */

View file

@ -0,0 +1,205 @@
/*
* Copyright (c) 2016, Robert Olsson KTH Royal Institute of Technology
* COS/Kista Stockholm roolss@kth.se
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 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 HOLDER 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.
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "dev/radio.h"
#include "net/netstack.h"
#include "net/packetbuf.h"
#include "sys/process.h"
#include "sys/etimer.h"
#include <dev/watchdog.h>
#include "dev/leds.h"
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#define SAMPLES 1000
#define DEBUG 1
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
PROCESS(rf_scan_process, "rf_scan process");
AUTOSTART_PROCESSES(&rf_scan_process);
/*
rf_environment runs clear channel assessment (CCA) test for over
all 802.15.4 channels and reports stats per channel. The CCA test
is run for different CCA thresholds from -60 to -190 dBm. CCA is a
non-destructive for the rf-environment it's just listens.
Best and worst channel is printed as average rf activity.
Originally developed for the Atmel avr-rss2 platform.
*/
static struct etimer et;
static int cca[16], cca_thresh, chan, i, j, k;
static uint16_t best, best_sum;
static uint16_t worst, worst_sum;
static double ave;
static radio_value_t
get_chan(void)
{
radio_value_t chan;
if(NETSTACK_RADIO.get_value(RADIO_PARAM_CHANNEL, &chan) ==
RADIO_RESULT_OK) {
return chan;
}
return 0;
}
static void
set_chan(uint8_t chan)
{
if(NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, chan) ==
RADIO_RESULT_OK) {
}
}
static radio_value_t
get_chan_min(void)
{
radio_value_t chan;
if(NETSTACK_RADIO.get_value(RADIO_CONST_CHANNEL_MIN, &chan) ==
RADIO_RESULT_OK) {
return chan;
}
return 0;
}
static radio_value_t
get_chan_max(void)
{
radio_value_t chan;
if(NETSTACK_RADIO.get_value(RADIO_CONST_CHANNEL_MAX, &chan) ==
RADIO_RESULT_OK) {
return chan;
}
return 0;
}
static radio_value_t
get_cca_thresh(void)
{
radio_value_t cca;
if(NETSTACK_RADIO.get_value(RADIO_PARAM_CCA_THRESHOLD, &cca) ==
RADIO_RESULT_OK) {
return cca;
}
return 0;
}
static radio_value_t
set_cca_thresh(radio_value_t thresh)
{
if(NETSTACK_RADIO.set_value(RADIO_PARAM_CCA_THRESHOLD, thresh) ==
RADIO_RESULT_OK) {
return RADIO_RESULT_OK;
}
return 0;
}
void
do_all_chan_cca(int *cca, int try)
{
int j;
for(j = 0; j < 16; j++) {
set_chan(j+11);
cca[j] = 0;
#ifdef CONTIKI_TARGET_AVR_RSS2
watchdog_periodic();
#endif
NETSTACK_RADIO.on();
for(i = 0; i < try; i++) {
cca[j] += NETSTACK_RADIO.channel_clear();
}
NETSTACK_RADIO.off();
}
}
PROCESS_THREAD(rf_scan_process, ev, data)
{
PROCESS_BEGIN();
leds_init();
leds_on(LEDS_RED);
leds_on(LEDS_YELLOW);
printf("Chan min=%d\n", get_chan_min());
chan = get_chan();
printf("Chan cur=%d\n", chan);
printf("Chan max=%d\n", get_chan_max());
cca_thresh = get_cca_thresh();
printf("Default CCA thresh=%d\n", cca_thresh);
etimer_set(&et, CLOCK_SECOND / 2);
while(1) {
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
for(k = -90; k <= -60; k += 2) {
set_cca_thresh(k);
do_all_chan_cca(cca, SAMPLES);
printf("cca_thresh=%-3ddBm", get_cca_thresh());
worst = 0;
worst_sum = 0xFFFF;
best = 0;
best_sum = 0;
ave = 0;
for(j = 0; j < 16; j++) {
ave += cca[j];
printf(" %3d", 100 - (100 * cca[j]) / SAMPLES);
if(cca[j] > best_sum) {
best_sum = cca[j];
best = j;
}
if(cca[j] < worst_sum) {
worst_sum = cca[j];
worst = j;
}
}
printf(" Best=%d Worst=%d Ave=%-5.2f\n", (best+11) , (worst+11), 100 - (100 * (ave / 16) / SAMPLES));
}
etimer_set(&et, CLOCK_SECOND / 2);
}
PROCESS_END();
}