diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c index 4fa9a44b4..0f11bd627 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.c +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -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. diff --git a/cpu/avr/radio/rf230bb/rf230bb.h b/cpu/avr/radio/rf230bb/rf230bb.h index 15f5b6438..42b8265fc 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.h +++ b/cpu/avr/radio/rf230bb/rf230bb.h @@ -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); diff --git a/examples/rf_environment/Makefile b/examples/rf_environment/Makefile new file mode 100644 index 000000000..75bf368af --- /dev/null +++ b/examples/rf_environment/Makefile @@ -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 + diff --git a/examples/rf_environment/README.md b/examples/rf_environment/README.md new file mode 100644 index 000000000..7d33c7178 --- /dev/null +++ b/examples/rf_environment/README.md @@ -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 + +
+             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 
+
+
\ No newline at end of file diff --git a/examples/rf_environment/project-conf.h b/examples/rf_environment/project-conf.h new file mode 100644 index 000000000..2f7691f16 --- /dev/null +++ b/examples/rf_environment/project-conf.h @@ -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_ */ diff --git a/examples/rf_environment/rf_environment.c b/examples/rf_environment/rf_environment.c new file mode 100644 index 000000000..fc7be6f4e --- /dev/null +++ b/examples/rf_environment/rf_environment.c @@ -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 +#include "dev/leds.h" + +#include +#include +#include + +#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(); +}