This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Incorrect RSSI samples in IEEE 802.15.4 RADIO mode

Hi,

we're developing a firmware for the nRF52811 that makes exhaustive use of RSSI sampling during packet reception. While this gives reliable results for Nordic proprietary and BLE RADIO modes (both for 1 MBit/s and 2 MBit/s), we encountered incorrect RSSI samples in IEEE 802.15.4 RADIO mode during specific parts of the packet.

We could reproduce this behaviour using the minimal working example specified below. The used HAL is not from Nordic but it should be self-descriptive anyway. We measured this for two different distances between the receiving and the transmitting antenna. As you can see from the diagram below, the sampled values around bits ~10 to ~15 and ~30 to ~55 are plausible. Indeed they match measurements done in other RADIO modes for the corresponding antenna distances. However, at the beginning, somewhere in the middle and at the end of the packet we get obviously incorrect RSSI samples. Furthermore, the signal level around bits ~10 to ~15 differs from that one around ~30 to ~55.

The only part of the manual with information about RSSI samples related to IEEE 802.15.4 mode is this in chapter 6.14.13.7:

When receiving a frame the RSSI (reported as negative dB) will be measured at three points during the reception. These three values will be sorted and the middle one selected (median 3) to be remapped within the LQI range.

Does this automatic RSSI sampling corrupt the RSSI sample values manually read from RSSISAMPLE register? Is there any chance to workaround this behaviour? What about the different signal levels? Many questions...

Thanks in advance and

best regards,

Gerrit Maus.

#include <libopencm3/nrf5/radio.h>
#include <libopencm3/nrf5/clock.h>
#include <libopencm3/cm3/nvic.h>

volatile uint8_t RSS[1000];
volatile uint16_t RSSC = 0;
volatile bool goOn = true;
uint8_t packet[255];

int main(){
	
	CLOCK_TASKS_HFCLKSTART = 1;
	while(!CLOCK_EVENTS_HFCLKSTARTED);
	
	RADIO_SFD = 0xcb; // Campus network's SFD
	RADIO_MODE = RADIO_MODE_MODE_IEEE802154_250KBIT;
	RADIO_CRCCNF = RADIO_CRCCNF_LEN_VAL(2)
	             | RADIO_CRCCNF_SKIPADDR_IEEE802154;
	RADIO_CRCPOLY = UINT32_C(0x11021);
	RADIO_CRCINIT = 0;
	RADIO_PCNF0 = RADIO_PCNF0_LFLEN_VAL(8)
	            | RADIO_PCNF0_PLEN_32BITZERO
	            | RADIO_PCNF0_CRCINC_INCLUDE;
	RADIO_PCNF1 = RADIO_PCNF1_MAXLEN_VAL(255);
	RADIO_FREQUENCY = 45; // 2445 MHz
	RADIO_PACKETPTR = (uint32_t) packet;
	
	nvic_enable_irq(NVIC_RADIO_IRQ);
	
	RADIO_SHORTS = RADIO_SHORTS_READY_START_ENABLED
	             | RADIO_SHORTS_PHYEND_DISABLE_ENABLED;
	RADIO_INTENSET = RADIO_INTENSET_RSSIEND_SET
	               | RADIO_INTENSET_FRAMESTART_SET;
	RADIO_TASKS_RXEN = 1;
	
	while(!RADIO_EVENTS_PHYEND){
		
		if(goOn){
			// Start another RSSI sampling process once
			// the previous one was processed by the ISR
			goOn = false;
			RADIO_TASKS_RSSISTART = 1;
		}
	}
	
	while(1);
	return 0;
}

void radio_isr(){

	if(RADIO_EVENTS_RSSIEND){
		RADIO_EVENTS_RSSIEND = 0;
		
		if(!RADIO_EVENTS_END && !RADIO_EVENTS_CRCOK){
			// Only process if packet is still on air!
			RSS[RSSC++] = RADIO_RSSISAMPLE;
			goOn = true;
		}
		
		while(RADIO_EVENTS_RSSIEND);
	}
	if(RADIO_EVENTS_FRAMESTART){
		RADIO_EVENTS_FRAMESTART = 0;
		RADIO_TASKS_RSSISTART = 1;
		while(RADIO_EVENTS_FRAMESTART);
	}
}

Parents
  • Hi Kenneth,

    Sorry for my late reply but I needed some time for testing. The good news: I can explain the first two obviously incorrect RSSI sampling periods. Due to a mistake in the provided minimal working example, the sampling started from the moment of the RXEN TASK. Originally, we encountered obviously incorrect RSSI samples towards the end of a received IEEE 802.15.4 packet during development of our IEEE 802.15.4 stack. We then started going into the details and wrote the provided minimal working example. Unfortunately it had the mentioned mistake in it.

    However, the problem at the end still exists, is reproducible and I can provide you the questioned measurement data.

    Below you find a diagram with RSS samples starting from the FRAMESTART event (first vertical line) up to the END event (last vertical line) during reception of an IEEE 802.15.4 packet. Note, that an RSS sample is discarded once the END event occurs. Hence all samples should be valid ones. However, the last few samples are obviously incorret, i.e. below -60 dBm (intermediate vertical line).

    This behaviour doesn't change when we use the PHYEND event instead of the END event for discarding RSSI samples as you may see from the measurement below. The vertical lines are, as it is also in the previous image, GPIO toggles.

    Just for reference, the next image shows the RSSI sample behaviour when receiving a BLE 2 MBit/s packet. There are only plausible RSSI samples until the END. Note, that the received packet is a bit shorter (in time) than those packets in the IEEE 802.15.4 mode. Anyway, the measurement continued until the END event occurred.

    The source codes for both scenarios (minimal working examples) are provided below.

    Again, please excuse the misleading measurements that we provided initially. However, we still have the issue of incorrect RSSI samples during the last ~2 µs of an IEEE 802.15.4 packet. We can, of course, workaround this by stopping the measurement a little bit earlier using the bit counter or something else. But at least I would like to report this behaviour and hear your thoughts.

    #include <libopencm3/nrf5/radio.h>
    #include <libopencm3/nrf5/clock.h>
    #include <libopencm3/nrf5/gpio.h>
    #include <libopencm3/cm3/nvic.h>
    
    volatile uint8_t RSS[1000];
    volatile uint16_t RSSC = 0;
    volatile bool goOn = false;
    
    int main(){
    	
    	
    	CLOCK_TASKS_HFCLKSTART = 1;
    	while(!CLOCK_EVENTS_HFCLKSTARTED);
    	
    	GPIO_DIRSET = GPIO2;
    	GPIO_OUTSET = GPIO2;
    	
    	uint8_t packet[255];
    	
    	RADIO_SFD = 0xcb; // Campus network's SFD
    	RADIO_MODE = RADIO_MODE_MODE_IEEE802154_250KBIT;
    	RADIO_CRCCNF = RADIO_CRCCNF_LEN_VAL(2)
    	             | RADIO_CRCCNF_SKIPADDR_IEEE802154;
    	RADIO_CRCPOLY = UINT32_C(0x11021);
    	RADIO_CRCINIT = 0;
    	RADIO_PCNF0 = RADIO_PCNF0_LFLEN_VAL(8)
    	            | RADIO_PCNF0_PLEN_32BITZERO
    	            | RADIO_PCNF0_CRCINC_INCLUDE;
    	RADIO_PCNF1 = RADIO_PCNF1_MAXLEN_VAL(255);
    	RADIO_FREQUENCY = 45; // 2445 MHz
    	RADIO_PACKETPTR = (uint32_t) packet;
    	
    	nvic_enable_irq(NVIC_RADIO_IRQ);
    	
    	RADIO_SHORTS = RADIO_SHORTS_READY_START_ENABLED
    	             | RADIO_SHORTS_PHYEND_DISABLE_ENABLED;
    	RADIO_INTENSET = RADIO_INTENSET_RSSIEND_SET
    	               | RADIO_INTENSET_FRAMESTART_SET
    	               | RADIO_INTENSET_END_SET;
    	
    	RADIO_TASKS_RXEN = 1;
    	
    	while(RADIO_STATE != RADIO_STATE_STATE_DISABLED){
    		
    		if(goOn){
    			// Start another RSSI sampling process once
    			// the previous one was processed by the ISR
    			goOn = false;
    			RADIO_TASKS_RSSISTART = 1;
    		}
    	}
    	
    	while(1);
    	return 0;
    }
    
    void radio_isr(){
    	
    	if(RADIO_EVENTS_RSSIEND){
    	
    		RADIO_EVENTS_RSSIEND = 0;
    		static bool below60 = true;
    		
    		if(!RADIO_EVENTS_END){
    			// Only process if packet is still on air!
    			RSS[RSSC++] = RADIO_RSSISAMPLE;
    			goOn = true;
    			if(RADIO_RSSISAMPLE >= 60 && below60){
    				below60 = false;
    				gpio_toggle(GPIO2);
    			}
    		}
    		
    		while(RADIO_EVENTS_RSSIEND);
    	}
    	else if(RADIO_EVENTS_FRAMESTART){
    	
    		RADIO_EVENTS_FRAMESTART = 0;
    		
    		RADIO_TASKS_RSSISTART = 1;
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    		
    		while(RADIO_EVENTS_FRAMESTART);
    	}
    	else if(RADIO_EVENTS_END){
    	
    		RADIO_INTENCLR = RADIO_INTENCLR_END_CLEAR;
    		
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    	}
    }
    #include <libopencm3/nrf5/radio.h>
    #include <libopencm3/nrf5/clock.h>
    #include <libopencm3/nrf5/gpio.h>
    #include <libopencm3/cm3/nvic.h>
    
    volatile uint8_t RSS[1000];
    volatile uint16_t RSSC = 0;
    volatile bool goOn = false;
    
    int main(){
    	
    	CLOCK_TASKS_HFCLKSTART = 1;
    	while(!CLOCK_EVENTS_HFCLKSTARTED);
    	
    	GPIO_DIRSET = GPIO2;
    	GPIO_OUTSET = GPIO2;
    	
    	uint8_t packet[255];
    	
    	RADIO_MODE = RADIO_MODE_MODE_BLE_2MBIT;
    	
    	RADIO_CRCCNF = RADIO_CRCCNF_LEN_VAL(3)
    	             | RADIO_CRCCNF_SKIPADDR_SKIP;
    
    	RADIO_CRCPOLY = UINT32_C(0x65b);
    	RADIO_CRCINIT = UINT32_C(0x55555555);
    	RADIO_PCNF1 = RADIO_PCNF1_MAXLEN_VAL(255)
    	            | RADIO_PCNF1_STATLEN_VAL(0)
    	            | RADIO_PCNF1_BALEN_VAL(3)
    	            | RADIO_PCNF1_ENDIAN_LITTLE
    	            | RADIO_PCNF1_WHITEEN_ENABLED;
    	RADIO_PCNF0 = RADIO_PCNF0_LFLEN_VAL(8)
    	            | RADIO_PCNF0_S0LEN_VAL(1)
    	            | RADIO_PCNF0_S1LEN_VAL(0)
    	            | RADIO_PCNF0_S1INCL_AUTOMATIC
    	            | RADIO_PCNF0_PLEN_16BIT
    	            | RADIO_PCNF0_CRCINC_EXCLUDE
    	            | RADIO_PCNF0_TERMLEN_VAL(0);
    	
    	RADIO_PREFIX0 = (UINT32_C(0x130517cb) >> 24) & 0xff;
    	RADIO_BASE0 = UINT32_C(0x130517cb) << 8;
    	RADIO_RXADDRESSES = RADIO_RXADDRESSES_ADDR0_ENABLED;
    	
    	RADIO_DATAWHITEIV = 37;
    	
    	RADIO_FREQUENCY = 45; // 2445 MHz
    	RADIO_PACKETPTR = (uint32_t) packet;
    	
    	nvic_enable_irq(NVIC_RADIO_IRQ);
    	
    	RADIO_SHORTS = RADIO_SHORTS_READY_START_ENABLED
    	             | RADIO_SHORTS_END_DISABLE_ENABLED;
    	RADIO_INTENSET = RADIO_INTENSET_RSSIEND_SET
    	               | RADIO_INTENSET_ADDRESS_SET
    	               | RADIO_INTENSET_END_SET;
    	
    	RADIO_TASKS_RXEN = 1;
    	
    	while(RADIO_STATE != RADIO_STATE_STATE_DISABLED){
    		
    		if(goOn){
    			// Start another RSSI sampling process once
    			// the previous one was processed by the ISR
    			goOn = false;
    			RADIO_TASKS_RSSISTART = 1;
    		}
    	}
    	
    	while(1);
    	return 0;
    }
    
    void radio_isr(){
    	
    	if(RADIO_EVENTS_RSSIEND){
    	
    		RADIO_EVENTS_RSSIEND = 0;
    		static bool below60 = true;
    		
    		if(!RADIO_EVENTS_END){
    			// Only process if packet is still on air!
    			RSS[RSSC++] = RADIO_RSSISAMPLE;
    			goOn = true;
    			if(RADIO_RSSISAMPLE >= 60 && below60){
    				below60 = false;
    				gpio_toggle(GPIO2);
    			}
    		}
    		
    		while(RADIO_EVENTS_RSSIEND);
    	}
    	if(RADIO_EVENTS_ADDRESS){
    	
    		RADIO_EVENTS_ADDRESS = 0;
    		
    		RADIO_TASKS_RSSISTART = 1;
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    		
    		while(RADIO_EVENTS_ADDRESS);
    	}
    	if(RADIO_EVENTS_END){
    	
    		RADIO_INTENCLR = RADIO_INTENCLR_END_CLEAR;
    		
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    	}
    }

    Best regards,

    Gerrit.

Reply
  • Hi Kenneth,

    Sorry for my late reply but I needed some time for testing. The good news: I can explain the first two obviously incorrect RSSI sampling periods. Due to a mistake in the provided minimal working example, the sampling started from the moment of the RXEN TASK. Originally, we encountered obviously incorrect RSSI samples towards the end of a received IEEE 802.15.4 packet during development of our IEEE 802.15.4 stack. We then started going into the details and wrote the provided minimal working example. Unfortunately it had the mentioned mistake in it.

    However, the problem at the end still exists, is reproducible and I can provide you the questioned measurement data.

    Below you find a diagram with RSS samples starting from the FRAMESTART event (first vertical line) up to the END event (last vertical line) during reception of an IEEE 802.15.4 packet. Note, that an RSS sample is discarded once the END event occurs. Hence all samples should be valid ones. However, the last few samples are obviously incorret, i.e. below -60 dBm (intermediate vertical line).

    This behaviour doesn't change when we use the PHYEND event instead of the END event for discarding RSSI samples as you may see from the measurement below. The vertical lines are, as it is also in the previous image, GPIO toggles.

    Just for reference, the next image shows the RSSI sample behaviour when receiving a BLE 2 MBit/s packet. There are only plausible RSSI samples until the END. Note, that the received packet is a bit shorter (in time) than those packets in the IEEE 802.15.4 mode. Anyway, the measurement continued until the END event occurred.

    The source codes for both scenarios (minimal working examples) are provided below.

    Again, please excuse the misleading measurements that we provided initially. However, we still have the issue of incorrect RSSI samples during the last ~2 µs of an IEEE 802.15.4 packet. We can, of course, workaround this by stopping the measurement a little bit earlier using the bit counter or something else. But at least I would like to report this behaviour and hear your thoughts.

    #include <libopencm3/nrf5/radio.h>
    #include <libopencm3/nrf5/clock.h>
    #include <libopencm3/nrf5/gpio.h>
    #include <libopencm3/cm3/nvic.h>
    
    volatile uint8_t RSS[1000];
    volatile uint16_t RSSC = 0;
    volatile bool goOn = false;
    
    int main(){
    	
    	
    	CLOCK_TASKS_HFCLKSTART = 1;
    	while(!CLOCK_EVENTS_HFCLKSTARTED);
    	
    	GPIO_DIRSET = GPIO2;
    	GPIO_OUTSET = GPIO2;
    	
    	uint8_t packet[255];
    	
    	RADIO_SFD = 0xcb; // Campus network's SFD
    	RADIO_MODE = RADIO_MODE_MODE_IEEE802154_250KBIT;
    	RADIO_CRCCNF = RADIO_CRCCNF_LEN_VAL(2)
    	             | RADIO_CRCCNF_SKIPADDR_IEEE802154;
    	RADIO_CRCPOLY = UINT32_C(0x11021);
    	RADIO_CRCINIT = 0;
    	RADIO_PCNF0 = RADIO_PCNF0_LFLEN_VAL(8)
    	            | RADIO_PCNF0_PLEN_32BITZERO
    	            | RADIO_PCNF0_CRCINC_INCLUDE;
    	RADIO_PCNF1 = RADIO_PCNF1_MAXLEN_VAL(255);
    	RADIO_FREQUENCY = 45; // 2445 MHz
    	RADIO_PACKETPTR = (uint32_t) packet;
    	
    	nvic_enable_irq(NVIC_RADIO_IRQ);
    	
    	RADIO_SHORTS = RADIO_SHORTS_READY_START_ENABLED
    	             | RADIO_SHORTS_PHYEND_DISABLE_ENABLED;
    	RADIO_INTENSET = RADIO_INTENSET_RSSIEND_SET
    	               | RADIO_INTENSET_FRAMESTART_SET
    	               | RADIO_INTENSET_END_SET;
    	
    	RADIO_TASKS_RXEN = 1;
    	
    	while(RADIO_STATE != RADIO_STATE_STATE_DISABLED){
    		
    		if(goOn){
    			// Start another RSSI sampling process once
    			// the previous one was processed by the ISR
    			goOn = false;
    			RADIO_TASKS_RSSISTART = 1;
    		}
    	}
    	
    	while(1);
    	return 0;
    }
    
    void radio_isr(){
    	
    	if(RADIO_EVENTS_RSSIEND){
    	
    		RADIO_EVENTS_RSSIEND = 0;
    		static bool below60 = true;
    		
    		if(!RADIO_EVENTS_END){
    			// Only process if packet is still on air!
    			RSS[RSSC++] = RADIO_RSSISAMPLE;
    			goOn = true;
    			if(RADIO_RSSISAMPLE >= 60 && below60){
    				below60 = false;
    				gpio_toggle(GPIO2);
    			}
    		}
    		
    		while(RADIO_EVENTS_RSSIEND);
    	}
    	else if(RADIO_EVENTS_FRAMESTART){
    	
    		RADIO_EVENTS_FRAMESTART = 0;
    		
    		RADIO_TASKS_RSSISTART = 1;
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    		
    		while(RADIO_EVENTS_FRAMESTART);
    	}
    	else if(RADIO_EVENTS_END){
    	
    		RADIO_INTENCLR = RADIO_INTENCLR_END_CLEAR;
    		
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    	}
    }
    #include <libopencm3/nrf5/radio.h>
    #include <libopencm3/nrf5/clock.h>
    #include <libopencm3/nrf5/gpio.h>
    #include <libopencm3/cm3/nvic.h>
    
    volatile uint8_t RSS[1000];
    volatile uint16_t RSSC = 0;
    volatile bool goOn = false;
    
    int main(){
    	
    	CLOCK_TASKS_HFCLKSTART = 1;
    	while(!CLOCK_EVENTS_HFCLKSTARTED);
    	
    	GPIO_DIRSET = GPIO2;
    	GPIO_OUTSET = GPIO2;
    	
    	uint8_t packet[255];
    	
    	RADIO_MODE = RADIO_MODE_MODE_BLE_2MBIT;
    	
    	RADIO_CRCCNF = RADIO_CRCCNF_LEN_VAL(3)
    	             | RADIO_CRCCNF_SKIPADDR_SKIP;
    
    	RADIO_CRCPOLY = UINT32_C(0x65b);
    	RADIO_CRCINIT = UINT32_C(0x55555555);
    	RADIO_PCNF1 = RADIO_PCNF1_MAXLEN_VAL(255)
    	            | RADIO_PCNF1_STATLEN_VAL(0)
    	            | RADIO_PCNF1_BALEN_VAL(3)
    	            | RADIO_PCNF1_ENDIAN_LITTLE
    	            | RADIO_PCNF1_WHITEEN_ENABLED;
    	RADIO_PCNF0 = RADIO_PCNF0_LFLEN_VAL(8)
    	            | RADIO_PCNF0_S0LEN_VAL(1)
    	            | RADIO_PCNF0_S1LEN_VAL(0)
    	            | RADIO_PCNF0_S1INCL_AUTOMATIC
    	            | RADIO_PCNF0_PLEN_16BIT
    	            | RADIO_PCNF0_CRCINC_EXCLUDE
    	            | RADIO_PCNF0_TERMLEN_VAL(0);
    	
    	RADIO_PREFIX0 = (UINT32_C(0x130517cb) >> 24) & 0xff;
    	RADIO_BASE0 = UINT32_C(0x130517cb) << 8;
    	RADIO_RXADDRESSES = RADIO_RXADDRESSES_ADDR0_ENABLED;
    	
    	RADIO_DATAWHITEIV = 37;
    	
    	RADIO_FREQUENCY = 45; // 2445 MHz
    	RADIO_PACKETPTR = (uint32_t) packet;
    	
    	nvic_enable_irq(NVIC_RADIO_IRQ);
    	
    	RADIO_SHORTS = RADIO_SHORTS_READY_START_ENABLED
    	             | RADIO_SHORTS_END_DISABLE_ENABLED;
    	RADIO_INTENSET = RADIO_INTENSET_RSSIEND_SET
    	               | RADIO_INTENSET_ADDRESS_SET
    	               | RADIO_INTENSET_END_SET;
    	
    	RADIO_TASKS_RXEN = 1;
    	
    	while(RADIO_STATE != RADIO_STATE_STATE_DISABLED){
    		
    		if(goOn){
    			// Start another RSSI sampling process once
    			// the previous one was processed by the ISR
    			goOn = false;
    			RADIO_TASKS_RSSISTART = 1;
    		}
    	}
    	
    	while(1);
    	return 0;
    }
    
    void radio_isr(){
    	
    	if(RADIO_EVENTS_RSSIEND){
    	
    		RADIO_EVENTS_RSSIEND = 0;
    		static bool below60 = true;
    		
    		if(!RADIO_EVENTS_END){
    			// Only process if packet is still on air!
    			RSS[RSSC++] = RADIO_RSSISAMPLE;
    			goOn = true;
    			if(RADIO_RSSISAMPLE >= 60 && below60){
    				below60 = false;
    				gpio_toggle(GPIO2);
    			}
    		}
    		
    		while(RADIO_EVENTS_RSSIEND);
    	}
    	if(RADIO_EVENTS_ADDRESS){
    	
    		RADIO_EVENTS_ADDRESS = 0;
    		
    		RADIO_TASKS_RSSISTART = 1;
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    		
    		while(RADIO_EVENTS_ADDRESS);
    	}
    	if(RADIO_EVENTS_END){
    	
    		RADIO_INTENCLR = RADIO_INTENCLR_END_CLEAR;
    		
    		gpio_toggle(GPIO2);
    		gpio_toggle(GPIO2);
    	}
    }

    Best regards,

    Gerrit.

Children
Related