top of page

Four Antenna Diversity

Out of the box the RFD900 can support diversity on up to 2 antennas. Ideally, I would be able to do diversity on four antennas so that I could receive all the RSSI values to adjust the antennas azimuth and polar angles. The RSSI values could be measured using two separate modems as in my current set up but it would be great if this could be simplified to a single modem. In this tutorial I will introduce a RF switch manufactured by Analog Devices which can switch an input port between a total of four output ports. Using this I believe it should be possible to allow four antenna diversity using a single RFD900 Modem. In addition to this the chip which I am using as a switch is capable of sending a signal through all four antennas at the same time. In the future this could be used to further extend the gain of the antenna.

Radio Frequency Switch

The radio frequency switch which I bought was the Analog Devices EVAL-ADGM1004EBZ which is actually an evaluation board for their ADGM1004 chip. If bought separately the chip is about $50. The cost of the eval board is around $200. I hope to avoid some of these cost in the future by designing my own PCB board instead of buying the EVAL kit. That being said in past experiences the Analog Devices evaluation boards have always been extremely high quality devices which work quite well. Now that we have an RF switch we can begin the process of programming it for use with the RFD900+. To start this process we need to reference the datasheet of the EVAL board. This sheet can be found below

Primarily what we are looking for in the data sheet is the logic to redirect the input signal to each of the different ports/antennas or in the case of receiving to direct the signal from each antenna to the RFD900 modem. A quick search within the manual provides us with the table below.

Screen Shot 2019-09-20 at 12.13.52 AM.pn

In this table we can see that by using the "links" we can either turn a given port always on or we can allow the port to be controlled by an external logic. In our case we want all of the links in the Off positions which is the default. With the links in the off position we can controll the switch using digital logic. In the RF switch status column note that it states (low is off, high is on). Since this switch uses ttl logic high is 3.3v and low is 0v. Essentially all the we need to control the logic of the switch then is to be able to access the GPIO ports on the RFD900+. This can of course be done by adjusting the SIK firmware as shown below.

Untitled drawing(12).png

RFD900+ GPIO Control

Before starting this tutorial it is probably a good idea,to read through my tutorial on RFD900 Sik radio programming, as some of the concepts in that article will be mentioned here. In the following tutorial I am going to be mainly discussing changes to make to the code, to make and flash this code to the RFD900 reference the RFD900 SIK radio programming tutorial. To start this tutorial we will need to download the SIK software from GITHUB. A link is found below

Download the SIK software, using the link above. Once the download is finished locate the pins_user.c file located within the Radio directory.

Screen Shot 2019-09-20 at 8.53.49 AM.png

This section of code sets up the available user pins for each of the different radio modems, the modem we are interested in is the BOARD_rfd900p. Note that that there are a total of 6 available pins. Two of the pins are on port three and the other four are on port 1. Be sure to note the commented number next to each of the {port,pin} definitions. These numbers (0-5) are what will be used to specify the port to turn on and off within the code.

​

Now, to be able to use the pins for anything useful we can use two functions. The first function is

​

pins_user_set_io(__pdata uint8_t pin, bool in_out)

​

This function takes as input one of the pins shown in the above screenshot. Remember when inputting the pin you wish to use, input the commented number next to the {port,pin} combination above. For example if I wanted to use pin {3,4} I would input 0.

​

The input in_out is used to specify whether the port is input or output. In the file pins_user.h an enumeration is declared as shown below.

Screen Shot 2019-09-20 at 9.11.16 AM.png

This enumeration means that if we wish to make a given pin output we can use the function above as

​

pins_user_set_io(0,PIN_OUTPUT)

​

This command would set the pin 1 ({3,4}) to be an output pin.

​

The second function we are interested in using is the function

​

pins_user_set_value(__pdata uint8_t pin, bool high_low)

​

As before the variable pin is used to specify which of the GPIO pins we wish to use on the RFD900. The Boolean high_low is used to determine if the pin is high (3.3volts) or low (0volts). Again using the enumerations if we want the pin to be high we input PIN_HIGH and if we want the pin to be low we input PIN_LOW. An example use of the function would be

​

pins_user_set_value(0, PIN_HIGH)

​

This function would turn the user pin 0 to be high.

​

The last part of this tutorial is to note that within the pins_user.c file there is a function,

​

pins_user_init(void)

​

This function initializes all of the user pins and is called within the main.c file. I would suggest that in this section of code you place all of your pin_user_set_io functions. This way at the start of the program all of the pins will be configured to be input or output as needed. Finally, once this is completed you can change the output value at any point in the code. This is all that I have for now on using the Analog Devices RF Switch to allow for four antenna diversity. Currently, my issue lies in an inability to know when the RSSI measurement is complete for each antenna. I have a few potential registers that might indicate that time, but I am still exploring these options. Nevertheless I am confident I will find a solution and when I do I will post the details below.

Timing it All

Now that I have explained how to use the GPIOs of the RFD900 it is necessary to program the RFD900+ to receive data from all four antennas. To start this process begin by familiarizing yourself with some of the interrupts on the RFD900+.

​

  • IRSSI: This interrupt is triggered every time a new RSSI value is read from an antenna this interrupt is triggered.

  • IPREAVAL: This interrupt is triggered as soon as a valid preamble is detected.

  • ISWDET: This interrupt is triggered as soon as the sync word is detected.

​

These are the interrupts that will be used to control the four antenna diversity. To understand how they will be used though it is first helpful to look at a packet format for the RFD900+. This format is shown below

Screen Shot 2019-10-06 at 9.42.07 PM.png

This format describes how data is sent between modems. The preamble is a predetermined number of 1s and 0s sent in the following sequence 10101010... The receiving modem has a preamble threshold which it uses to determine how many 101010... it needs to receive before it determines it has read a valid preamble. For example if the preamble threshold was 8 bits then the receiving radio would have to receive 10101010 or 01010101, before it would determine it had received a valid preamble. Once the receiving modem receives the threshold number of bits the IPREAVAL (Preamble available) interrupt is triggered if it is enabled. The preamble will continue even after this interrupt since the length of the preamble is determined by the transmitting modem. Once the modem has finished the sync word is sent by the transmitter. Once the sync word is received by the receiving modem the ISWDET (Sync Word Detect) interrupt is triggered if it is enabled. Following this the rest of the message including the transmitted data is received. For RSSI purposes we are primarily concerned with the preamble and sync word.

​

The reason for this being that once the valid preamble is detected it does not matter if the remaining 1s and 0s in the preamble are lost, it is just necessary to ensure the sync word is detected. For this reason it is an ideal time in the message to measure RSSI. This is because when switching antennas it is easy to lose data, therefore anytime after the sync word is a bad time to read RSSI on all the antennas. In contrast since the data between the valid preamble detection and sync word is useless, it is an ideal time to read RSSI since lost data will not hurt the system.

​

The method I have come up with then is this. Upon turning on the modem inside the RFD900+ will configure itself to be triggered on the IPREAVAL and ISWDET interrupts, but not the IRSSI interrupt. During operation the interrupt service routine for the IPREAVAL will enable the IRSSI interrupt. Once this occurs the IRSSI interrupt service routine will handle the reception and storage of RSSI values as well as the switching of the antenna. Finally, once the ISWDET interrupt service routine is executed the IRSSI interrupt will be disabled. In this way it will be possible to read RSSI without interfering with the transmitted data.

Implementation

In this section I will give an overview of the implementation of the algorithm described above. All of the necessary changes will be made to the radio.c file of the SIK firmware. I have included my fork of the SIK firmware. Note that in this version of SIK I created a new firmware type: rfd900pa. Also be sure to note that SIK is a firmware meant to be used for various RFD900 boards and not just the rfd900+ that I use. This means that various parts of the code are only valid for various boards. This is why it is common to see commands like

 

#ifdef rfd900p

....

...

...

#endif

​

The # designates that this code is run at compile time. Without going into too much detail all this means is that the code included in this if statement will only be included if we are using the rfd900p (RFD900+) board. These #if(s) are then what allows the code to be configured for each individual board, making it easier to create a unified code which can be compiled for multiple boards.

​

Now with this out of the way note that virtually all of the code I suggest adding to sik should be within #if statement like the one above. Ideally it would be even better if all the code written here (assuming it is for the RFD900+) was prefaced with

​

#if defined BOARD_rfd900p && !defined BOARD_rfd900pa

​

#endif

​

Implementing these if statements will help you avoid a significant amount of headache later on

​

Now with this out of the way open up the radio.c file. Within this file find the function radio_receiver_on(void). This function is executed whenever the radio is turn on to start receiving. Use the function to turn on the ISWDET and IPREAVAL detects using the following commands.

​

register_write(EZRADIOPRO_INTERRUPT_ENABLE_2,EZRADIOPRO_ENPREAVAL|EZRADIOPRO_ENSWDET);

​

This command writes the register which enables the various interrupts for the controller. Note that all of this interrupts will actually share the same interrupt service routine, INTERRUPT_INT0. To determine which of the interrupts is triggered the program will use a status register, which essentially keeps track of which of the interrupts have been triggered and which have not. Next go down to the interrupt service routine for INTERRUPT_INT0. Find the if statement

​

if (status2 & EZRADIOPRO_IPREAVAL)

​

The lines following this statement will only be executed if the IPREAVAL interrupt has been triggered. Go to the end of the commands executed if the if statement is true and place the code. Note the below is one line not two.

​

register_write(EZRADIOPRO_INTERRUPT_STATUS_2, EZRADIOPRO_ENPREAVAL|EZRADIOPRO_ENSWDET|EZRADIOPRO_ENRSSI);

​

This statement keeps the SWDET and PREAVAL intterupts enabled but also enables the ENIRSSI.

​

Next create an if statement to be executed within the ENIRSSI interrupt. The following code should work,

​

if (status2 & EZRADIOPRO_IRSSI)

{

​

}

​

You can choose to execute whatever lines you please, to be executed by the if statement but I would strongly suggest the following code at a minimum. This code reads the RSSI value and stores it in a unit8_t variable.

​

uint8_t = register_read(EZRADIOPRO_RECEIVED_SIGNAL_STRENGTH_INDICATOR);

​

Finally, it is necessary to disable the IRSSI interrupt when the sync word is detected so add the following statements.

​

if (status2 & EZRADIOPRO_ISWDET) {
        register_write(EZRADIOPRO_INTERRUPT_STATUS_2, REGISTER_TWO_INTERRUPTS);
    }

​

Lastly, note again that all of this code should be enclosed by #if statements. For the sake of brevity I will not be including the code to actually turn the switches on and off but that can be found on my github through the link below. This page hopefully should have given you the know how to program the switches yourself or at the very least understand my implementation.

bottom of page