In this article, we go through a couple of example usecases and their setups using the Multi-PHY radio configurator. If you haven't already, please read Introduction to Multi-PHY and Multiprotocol first to understand the various Multi-PHY and Multiprotocol capabilities of the Wireless Geckos. Some basic understanding of radio configs and the radio configurator is also required.
You can find related tutorials on the table of contents site.
This tutorial includes videos (without audio) to guide you through the setup on the Configurator GUI.
The main idea behind Channel-based Multi-PHY is to create channel groups, each of which can have different PHYs. Changing between these channel groups is handled by RAIL: from the RAIL API, you can load the required PHY just by selecting a channel.
Channel groups can be created with the icon. By default, these new channel groups have no PHY configuration.
A PHY configuration can be added using the icon. A PHY configuration exposes elements of the radio configurator for each of the channel groups in the selected protocol. The PHY applied to any specific channel group can then be customized by changing the values for each element present in the PHY configuration.
Once you add something to the channel-based configs (as described above), the protocol-based setup will be disabled.
Let's say you need to work on the same 915MHz frequency, but on both 100kb/s and 500kb/s (with deviation 50kHz and 250kHz, respectively). Typically, this is used as an extension of a protocol which originally only supported the lower bitrate: The default bitrate is 100k, but it's possible to switch to 500k after a handshake.
In the above setup, channel 0 uses 100kb/s bitrate, while channel 1 uses 500 kb/s. Note that the channels are on the exact same frequency, but their configuration is slightly different - you might call these virtual channels. From RAIL, you can change between these virtual channels just as regular channels: If you call
RAIL_StartRx(railHandle, 0, NULL) it will search for 100k packets, while
RAIL_StartRx(railHandle, 1, NULL) will search for 500k packets.
Let's say your protocol defines a variable length data packet (1st byte is length) and a fixed, 2B long ACK packet.
In the above setup channel 0 is for data packets, while channel 1 is for ACK packets (both Tx and Rx) - on the same frequency, so these are virtual channels just like in the previous example. A transmitting device would send a data packet on channel 0, then start listening on channel 1 for ACK, while a receiving device would receive on channel 0, and transmit an ACK on channel 1 after successful reception.
Note that the only difference between the PHYs are the length decoding algorithm itself. This is because the configurator can keep a complete fixed length and a variable length configuration, and changing between those is possible by just changing the the frame length algorithm.
Wireless M-Bus T mode defines a very different protocol based on the direction:
The above example implements the "Other device" (typically collector): It receives M2O on channel 0 and transmits O2M on channel 1.
Transmitting modeT M2O messages requires other tricks, see AN1119 for details
Some regulatory standards also standardize the bandwidth for CSMA/CA, but your protocol would have better sensitivity with a narrower bandwidth. The trick here is to understand that this is actually a subset of the Asymmetric protocol usecase: Since CSMA/CA will listen on the same channel that you will use for transmit and the bandwidth setting in the configurator only affects receive performance, you can define a virtual channel with your setup with the required wider bandwidth:
In the above example, channel 0 uses the bandwidth recommended by the configurator, while channel 1 has the fixed, wide bandwidth. You would receive on channel 0 with high sensitivity, and transmit on channel 1. The CSMA/CA preceding the transmit would also happen on channel 1 using the fixed, wide bandwidth.
You can check the bandwidth configured for channel 0 in the
efr32_radio_configurator_log.txt file: It's 4.8kHz.
Channel groups can be used in "single-PHY" mode as well: one example for that is setting up uneven channel spacing. Let's say you have to receive on 868.0MHz, 868.33MHz and 868.4MHz - so the channel spacing is 330kHz and 70kHz at the same time - You obviously can't configure this with a single channel spacing field, but you can with channel groups:
With the above setup, you will have channels 0, 1 and 2 on the required frequencies.
This is still a "single-PHY" usecase: Let's say you have to receive on 40 channels, starting at 2.402GHz with channel spacing of 1MHz. However, to meet regulatory standards, you must lower the transmit power on the first and last channel to 16dBm.
The above setup meets the requirements. Note that channel 0 and 39 are both defined twice. First as limited power, then the same as the other 38 channels. The order of channel groups are important: RAIL always loads the first channel group which includes the requested channel.
Channel number offset was used in the above video. The frequency of a given channel is calculated as follows:
channelFrequency = baseFrequency + channelSpacing * ( channelNumber - channelNumberOffset )
Channel number offset is the same as First channel number if it's disabled. This is useful for uneven channel spacing, since you want the channel group to start on the selected base frequency, and not offset by
firstChannelNumber*channelSpacing. However, setting it to 0 is useful for overrides: This way, the power limited channel 39 in the above config will be exactly the same as in the original channel group. See understanding RAIL config files tutorial for more details.
You also have to keep in mind that the actual output power depends on your board and antenna design. The recommended way to solve this problem is to create a PA conversion curve documented in AN1127, and enable the PA conversions plugin with the generated header:
Simplicity Studio ships with conversion curve headers for Silicon Labs boards - if you create a project for a Silicon Labs board, simply enable the PA Conversions plugin to include the correct header for your board.
Note that RAIL only lowers and limits the output power on channel change, it won't increase it back if you switch to an unlimited channel from a limited one.
See the Multi-PHY capabilities chapter in the Understanding RAIL config files tutorial.
In general, you should disable all advanced settings if you change much in a configuration - the same guidance applies for Multi-PHY. What makes this advice even more important for Multi-PHY is that it's easy to miss a problem if something misconfigured under the protocol setup makes your channel group misbehave.
When you add an element to the channel-based configuration, it will initially inherit a value from the root protocol - and that is the only time this inheritance happens. If you later change the root protocol (ex: switch to a pre-configured PHY), doing so won't update the channel-based config properties for any channel groups, even if you hadn't changed the value inherited from the original protocol. This behavior is depicted in the following video:
If you have significant differences between channel groups, channel changing that involves a channel group change will take somewhat longer - in most cases, this is not too significant, but you should measure and calculate with it if you need short channel switch times (PRS channels can be used for measuring this time, see the tutorial about debugging).
Also, if you have 3 channel groups, and only a single field is different between A and B, but C is very different compared to the other two, channel change between A and B will take the same time as channel change between C and A or C and B.
If you have a lot of channel groups in the protocol, this could also cause a small but measurable delay during channel change: it takes some time for RAIL to look up the channel group which includes the requested channel.
All of these delays are a result of the implementation in RAIL, see the Understanding RAIL config files tutorial for more details.
In some cases, it's possible to work around these problems by combining channel-based and protocol-based Multi-PHYs:
The main idea behind Protocol-based Multi-PHY is to create multiple - completely independent - configs, and use
RAIL_ConfigChannels() to select the required one.
Protocols can be created with the icon.
The order of protocols will be used in the generated
channelConfigs array, i.e. the first protocol in the list will have index 0 and so on.
Let's say your device operates on the 868MHz 500kb/s pre-configured PHY in Europe, and on the 915MHz 100kb/s pre-configured PHY in North America.
With the above setup, calling
RAIL_ConfigChannels(railHandle, channelConfigs, NULL) will load the European config, while
RAIL_ConfigChannels(railHandle, channelConfigs, NULL) will load the North American config.
Protocol-based Multi-PHY is also useful if you want to test multiple configuration setups using RAILTest: You can change between protocols using the
setConfigIndex RAILTest command.
The above setup can be also used in a Dynamic Multiprotocol setup: You'll need two rail handles, let's call them railHandle868 and railHandle915. During the initialization of the 868MHz protocol, you'll call
RAIL_ConfigChannels(railHandle868, channelConfigs, NULL), and during the initialization of the 915MHz protocol, you'll call
RAIL_ConfigChannels(railHandle915, channelConfigs, NULL). From this point, RAIL will automatically load the required config using the RAIL scheduler.
RAIL will automatically change everything needed for Multi-PHY during channel or protocol change, except one thing: The PA (power amplifier) configuration. On Wireless Geckos, changing the PA is needed if you change between a sub-GHz and a 2.4GHz config (or maybe between a low power and high power 2.4GHz config).
To solve this, you should pass a function pointer as the last parameter of
RAIL_ConfigChannels. In the examples, we call it
RAILCb_RadioConfigChanged and it will be called when RAIL switches between channel groups, with the
RAIL_ChannelConfigEntry_t as an argument. You can use that argument to figure out if you need to change the PA or not, and call
RAIL_ConfigTxPower if needed.
This is implemented in both RAILTest and in SimpleTRX-MultiPHY.
The Connect stack has some limitations on Multi-PHY features: