- OpenLST User's Guide
- Introduction
- Getting Started
- Connecting to the Demo Board
- Building and Loading the Bootloader
- Building and Loading the Application
- Basic Local Commands
- Creating a Custom Firmware Project
- Creating a Custom Hardware Project
- Frequency Selection
- Troubleshooting
- Acknowledgements
- License Info
- Disclaimers
OpenLST is an open-source, proven radio design for communicating with remote instruments, vehicles, and stations using low-cost commercial components.
OpenLST uses components that build on Planet's experience with the Dove LST (Low-Speed Transceiver) radio. Planet's Dove satellite radio, which uses similar components and software, has an extensive history of on-orbit success and reliability with over 150 satellites contributing to over 200 cumulative years of on-orbit data.
The firmware included in this release supports basic operation on the amateur 70cm band for use between OpenLST radios or similarly programed packet radios.
OpenLST is radio system that enables packet-based communication with a remote terminal using low-cost commercial parts. "LST" stands for Low-Speed Transceiver. The reference design included in this release supports packet-based communication 437MHz at 3kbps and includes forward error correction (FEC), CRC-based integrity checks, basic radio telemetry, as well as support for in-situ or over-the-air firmware updates. This reference design also supports time-of-light ranging for coarse location and trajectory estimation.
The OpenLST project consists of:
- A firmware (embedded C) repository with the source for the bootloader and application sections of the radio
- A small set of Python tools for programming and communicating with the OpenLST radio
- A reference hardware design including schematics, part specs, layout, and Gerber files using KiCad
- This user's guide
OpenLST may not be suitable on its own for all environments or use cases. The following features are not included:
- Message encryption or authentication; users who need this will need to implement it at the application or protocol layer.
- Beaconing or unrequested transmissions; users that require a beacon feature will need to implement that separately.
- Full duplex communication; while OpenLST can support separate channels for uplink and downlink, the design does not support receiving while transmitting.
OpenLST is specifically designed to make certain common customizations easy:
- Changing the uplink/downlink frequencies
- Altering the bitrate or modulation settings
- Adding additional custom command opcodes
- Channels for custom analog-digital conversion setups (custom sensors and telemetry)
See Creating a Custom Firmware Project for instructions on making these common customizations.
In common parlance, bash lines will start with either a #
or $
indicating
privilege level. The octothorpe (#
) indicates a line should be executed with
administrator privileges (for example, with sudo
), while the dollar sign
($
) indicates a line should be executed with standard user privileges.
Octothorpes in the line indicate a comment and should not be executed in the
shell.
Lines that terminate in a backslash (\
) indicate that the next line is a
continuation of the same command. Commands are sometimes split across lines as
an attempt to make them more readable.
This section describes the steps necessary to set up a development environment using an evaluation sample board.
To get started and use the sample project, you will need:
- A license to operate in the 70cm band, depending on your jurisdiction
- An OpenLST evaluation board
- A DC power supply for the evaluation board
- The Texas Instruments CC Debugger tool
- A 3.3V FTDI serial/TTL adapter
- A PC running Windows or Linux or a Mac running macOS (any OS that supports VirtualBox on a x64 host)
- An installed copy of git to clone the repository
These items are described in the sections below.
Depending on your legal jurisdiction, developers and users may be required to obtain a license for operating radio hardware in the 70cm band or any frequency bands utilized by a custom radio project. The default sample project operates at 437MHz which is in the amateur 70cm band in the United States and may require an amateur radio license to operate over the air. Licensing is outside the scope of this guide - it is up to the user to make sure they comply with all applicable regulations.
The KiCad project, Gerber files, and bill of materials for the OpenLST evaluation board are available as a git repostory:
$ git clone --recursive https://www.planet.com/open/openlst-hw.git
The Texas Instruments CC Debugger tool is used to load bootloader flash images onto the CC1110 microcontroller. This tool is not required to load new application flash binaries, however it is required for the initial bootloader load and for bootloader development.
The FTDI USB to serial cable is also recommended. The TTL 3.3V version is used for this design.
Additionally, the OpenLST development board requires a 5V 1.5A DC power supply. An oscilloscope and spectrum analyzer are also recommended for system development.
The example firmware project is located on Github at https://www.planet.com/open/openlst.git
To clone the example project, use git. For example:
$ git clone --recursive https://www.planet.com/open/openlst.git
This guide assumes you are using the included Vagrantfile/virtual machine (VM) for development and programming. It is also possible to install the toolchain and programmer tools directly if you prefer.
There is a Vagrantfile included in the sample project that creates a VM that includes:
- cctool (TI CC Debugger support software for programming)
- SDCC (the compiler toolchain)
- The included python tools for programming, signing, and testing the application
- USB passthrough support for the TI CC Debugger and evaluation board serial ports
- A shared folder with the host machine so you can use development tools on your host while running the toolchain and programmer tools in the VM
- Install VirtualBox and the Guest Extensions. Guest extensions are required to
share the USB device with the host.
- For macOS, follow the instructions on the link above
- For Ubuntu Linux, this linked guide may be useful
- Install Vagrant. Version 2.0 or later is required.
- If you have not cloned the example project yet, clone the repository (see above). There is a Vagrantfile in the example project used to set up the VM. You will need at least 2GB of RAM available to provision the VM.
- Run:
This will create and provision an Ubuntu 16.04 VM with cctool, the SDCC toolchain, and the python utilities installed. The "reload" step is required to reboot the VM and allow the vagrant user access to the USB devices.
$ cd openlst $ vagrant up $ vagrant reload
- Log into the VM using:
$ vagrant ssh
- Plugging in the CC Debugger tool and running "cc-tool" should produce the
output:
If you see an error like:
vagrant@vagrant-ubuntu-trusty-64:~$ cc-tool Programmer: CC Debugger Target: CC1110 No actions specified
You may need to reboot the VM to make sure the udev rules are applied.Error occured: libusb_open failed, Access denied (insufficient permissions)
This section is mainly targeting Linux users that want to run the toolchain on their own system. If you are using the Vagrant VM you can skip these steps.
In order to operate the CC Debugger programming device, you will need to install the cctool software. The source is available from sourceforge and from GitHub mirrors like https://github.com/dashesy/cc-tool for Linux systems (used in this guide). Building on macOS may be possible using macports.
For Windows systems, Texas Instruments provides software for using the debugger tool. Use of this tool is not covered in this guide.
OpenLST uses the Small Device C Compiler to generate bootloader and application flash images. SDCC binary images are available directly via sourceforge. Version 3.5 is recommended. Additionally some distributions (like Debian/Ubuntu) provide sdcc binaries through their package manager, installable using:
# apt-get install sdcc
On Debian Jessie or later and Ubuntu 14.04 or later. Again, SDCC version 3.5 or later is recommended. Early versions are not well tested with this codebase.
Alternatively, you can use a docker image from the Dockerfile provided in the build directory of the OpenLST repository:
$ cd build
$ docker build -t sdcc .
Then you can build using:
$ docker run --rm -v $PWD:/project sdcc bash -c "cd project && make"
If you have previously built the firmware on the same computer, and subsequently modified the firmware, clean your build environment by running:
vagrant@ubuntu-xenial:~/project$ make clean
Note: this section assumes you logged in to the Vagrant VM (via vagrant ssh)
Loading the bootloader requires the CC Debugger tool. This must be plugged in to the programming port on the Open LST board.
Run make to build the bootloader binary image for the OpenLST 437Mhz sample project:
vagrant@ubuntu-xenial:~$ cd project/
vagrant@ubuntu-xenial:~/project$ make openlst_437_bootloader
Memory usage summary for openlst_437_bootloader.hex:
Name Start End Size Max
---------------- -------- -------- -------- --------
PAGED EXT. RAM 0xf000 0xf036 55 256
EXTERNAL RAM 0x0000 0xf96d 2363 3328
ROM/EPROM/FLASH 0x0000 0x7c99 31823 32768
Stack starts at: 0x2e (sp set to 0x2d) with 210 bytes available.
The SDCC output shows a summary of the bootloader binary (Intel .hex
file).
In the example above, the bootloader's code segment starts at address 0x0000
(the bottom of flash) and extends to 0x7FFF (32768 bytes). The bootloader
actually only occupies the first page and 0x7000-0x7FFF and reserves the rest
of flash for the application.
To load the bootloader onto the development board, first make sure the CC Debugger is connected to the development board's programming header and that the board is powered off an external supply. You may need to press the reset button on the CC Debugger after first connecting (if your CC Debugger has a green/red LED, it should show green).
Run cc-tool
to make sure you are connected and the board is working:
vagrant@ubuntu-xenial:~/project$ cc-tool
Programmer: CC Debugger
Target: CC1110
No actions specified
Load the flash image using the flash_bootloader
Python utility. This script
is included in the openlst_tools
Python library in the repository. It is
installed as part of the vagrant up provisioning step if you are using the
Vagrant VM (if you're not using the Vagrant VM, you will need to install the
python package under tools/openlst_tools
locally with
pip install -e open-lst/tools
).
You will need to specify two parameters when loading the bootloader:
- A hardware identifier (HWID): This is a two-byte identifier, typically
expressed as a four-digit hex number like "01AB". Some important rules and
guidelines apply:
- Hardware IDs 8000 and above are reserved for ground/base station radios
- Hardware IDs 7FFF and below are reserved for remote radios.
- When deployed in the field, it is important that your HWIDs do not overlap with other users of the same frequency band and modulation settings. If you share allocation and are worried about overlap in HWIDs, it is recommended that you coordinate with your issuing authority and contact Planet.
- HWID 0000 is reserved for broadcast messages and should not be used
- HWID FFFF is reserved for local messages sent over the serial port to the ground/base station radio and should not be used
- For testing purposes HWIDs 0001-00FF are recommended. For this tutorial you can just use 0001.
- Signature keys for application payloads: The bootloader requires three
AES-128 (16 byte) keys. These are used to verify the authenticity of
application images. Applications must be cryptographically signed with one of
these three keys to run. Keys can either be specified at the command line (as
32 character hex strings) or from a key file (as three comma-separated 32
character hex strings).
- In production, all three keys should be set to non-trivial values (not all zeros or all ones).
- It is okay to set two or three of the keys to the same value if you don't need three distinct keys. In production it is recommended that you have at least two unique keys in order to have a backup in case the primary key is lost.
- For lab testing you can set all three keys to all ones (a value of
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
)
ubuntu@ubuntu-xenial:~/project$ flash_bootloader --keys \
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF --hwid 0001 openlst_437_bootloader.hex
This will erase the flash on the CC1110 and load the bootloader binary, encryption keys, and HWID (0001) into flash. This will also set CC1110 lock bits to prevent accidental erasure of the bootloader.
If the bootload fails with a stacktrace, make sure the CC Debugger is plugged in, press the "Reset" button, and retry.
Once the bootloader is loaded it should be running on the device. The
bootloader will reset itself roughly every second from the CC1110's internal
watchdog timer. After a reset it prints its version over UART1. You can observe
this by connecting to UART1 and using the radio_terminal
command:
vagrant@ubuntu-xenial:~$ radio_terminal
< lst ascii "OpenLST BL 1874e4b"
< lst ascii "OpenLST BL 1874e4b"
< lst ascii "OpenLST BL 1874e4b"
...
(press Ctrl+c to exit)
The message will include the git SHA of the current bootloader. In this
example the SHA is 1874e4b
, but it may be different on your terminal
depending on your version of the repo.
The application is loaded over the serial connection rather than through the CC Debugger. To program the application, the FTDI USB-serial cable must be connected to the UART1 on the board.
To build the application, run:
vagrant@ubuntu-xenial:~/project$ make openlst_437_radio
Memory usage summary for openlst_437_radio.hex:
Name Start End Size Max
---------------- -------- -------- -------- --------
PAGED EXT. RAM 0xf000 0xf066 103 256
EXTERNAL RAM 0xf067 0xf9d3 2413 3328
ROM/EPROM/FLASH 0x0400 0x1abd 5790 26592
Stack starts at: 0x48 (sp set to 0x47) with 184 bytes available.
Again, this prints out some important statistics for the radio application image. In this case the code area starts at 0x0400 (after the first page of the bootloader). It uses 5790 bytes of roughly 26KB available in the flash.
In order to program the application, it first needs to be signed using one of the keys loaded into the bootloader. Assuming you used all 1s (using the section above) for the keys, you would run:
$ sign_radio --signing-key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \
openlst_437_radio.hex openlst_437_radio.sig
This writes the 16 byte signature to the openlst_437_radio.sig
.
Once signed, the application can be loaded using:
$ bootload_radio --signature-file openlst_437_radio.sig \
-i 0001 openlst_437_radio.hex
INFO:root:Read firmware image
INFO:root:Inserted signature
DEBUG:openlst_tools.commands:Sending (0001): lst reboot
DEBUG:openlst_tools.commands:No response
DEBUG:openlst_tools.commands:Sending (0001): lst bootloader_erase
DEBUG:openlst_tools.commands:Response: lst bootloader_ack 1
DEBUG:openlst_tools.commands:Sending (0001): lst bootloader_write_page 8 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
...
...
DEBUG:openlst_tools.commands:Response: lst bootloader_ack 215
DEBUG:openlst_tools.commands:Sending (0001): lst bootloader_write_page 255
DEBUG:openlst_tools.commands:Response: lst bootloader_nack
The firmware image should boot immediately. If it fails to load the firmware
and continues to loop through reboot / no response messages, then check your
connection. Remember, the bootloader is loaded over the CC Debugger, but the
radio firmware is flashed over the UART. If you are watching with an instance
of radio_terminal
, the firmware will print its version:
< lst ascii "OpenLST 1874e4b"
As before, the firmware will print a git SHA as it's version number. That SHA may be different than the example here based on your version of the repository and firmware.
You can try querying telemetry:
$ get_telem -i 0001
DEBUG:openlst_tools.commands:Sending (0001): lst get_telem
DEBUG:openlst_tools.commands:Response: lst telem 0 179 0 0 0 0 2047 2047 2047 4092 2047 2047 2047 2047 1410 1839 -128 0 0 0 0 0 0 0 0 0 0 0 0
lst telem 0 179 0 0 0 0 2047 2047 2047 4092 2047 2047 2047 2047 1410 1839 -128 0 0 0 0 0 0 0 0 0 0 0 0
reserved 0
uptime 179
uart0_rx_count 0
uart1_rx_count 0
rx_mode 0
tx_mode 0
adc0 2047
adc1 2047
adc2 2047
adc3 4092
adc4 2047
adc5 2047
adc6 2047
adc7 2047
adc8 1410
adc9 1839
last_rssi -128
last_lqi 0
last_freqest 0
packets_sent 0
cs_count 0
packets_good 0
packets_rejected_checksum 0
packets_rejected_reserved 0
packets_rejected_other 0
reserved0 0
reserved1 0
custom0 0
custom1 0
The translator is a good resource to view possible commands available to the user. While the radio may accept commands outside of the translator, the translator is designed to interpret, validate, and parse commands and their arguments into the hexadecimal bytearrays accepted by the radio.
The terminal program provided with the radio firmware will try to parse the
translator's command structure to build a list of suggested ways the user can
complete the command (use the <TAB>
key to view it).
Packets include a few parts to help the radios direct and respond to commands appropriately:
The hardware ID (HWID) is a 2-byte serial number assigned to the radio and used
to identify the unit to which commands are addressed. Usually this is expressed
as a four-digit hexadecimal value, for instance you may have assigned the radio
the HWID 0x0001
in the examples above. Each unit you use should have a unique
HWID.
The sequence number (SEQNUM) is a 2-byte number used to match commands and
replies. Typically the sequence number will increment by one for each command
sent (and overflow without issue: ..., 0xFFFE, 0xFFFF, 0x0000, 0x0001, ...
).
The included radio_terminal
program will select a random SEQNUM at startup,
and increment it after each command. The radio will automatically send any
response with the same seqnum as the originating command.
The destination is a 1-byte number used to specify what the radio should do
with a command. Most user commands will go to lst
(the translator will map
the string to the proper byte code). The OpenLST will forward any commands
not targeted to the lst
destination.
The payload of the bytearray contains up to N-bytes that are parsed by the radio to activate different functions. The Payload may also include arguments and optional arguments depending on which command is being given.
Acknowledge (ACK) is a basic command or response used to "ping" the radio or to acknowledge certain other commands. An ack command received by the radio will trigger an ack reply.
The opposite of an ACK: this is a non/negative/no-acknowledge command. It is used by the radio to signal that while it has received a command, it cannot execute that command.
The reboot command tells the radio to reboot or schedules it for some DELAY
seconds in the future. DELAY is an optional argument: without it, the radio
will reboot immediately. By default the maximum delay duration is about one
week.
The radio collects some health telemetry that can be queried using GET_TELEM
.
The radio will reply to a GET_TELEM
command with a TELEM
reply. Fields
include:
Reserved
Uptime
Uart0_rx_count
Uart1_rx_count
Rx_mode
Tx_mode
Adc0
Acd1
...
Acd9
Last_rssi
Last_lqi
Last_freqest
Packets_sent
Cs_count
Packets_good
Packets_rejected_checksum
packets_rejected_reserved
Packets_rejected_other
Reserved0
Reserved1
Custom0
Custom1
The radio has an onboard clock in the CC1110 chip. This clock is reset upon
reboot and will start counting once time is initially set. The command returns
seconds and nanoseconds. It will return a NACK
if the time has not been set.
The radio's time can be set using SET_TIME
, then queried using GET_TIME
.
This command has two required arguments (one for seconds, one for nanoseconds).
The epoch used is seconds since J2000.
The radio can store a callsign in the persistent memory using the
set_callsign
command. The callsign is meant to ease compliance with US CFR
Part 97 (or compliance with similar laws in other countries). It is up to the
user to ensure compliance with local laws.
get_callsign
will request the callsign from the persistent memory.
callsign
is the command that the radio will use to reply to get_callsign
requests.
The radio is capable of sending basic ASCII text. It takes a string argument.
The bootloader accepts a basic ping with an ack
reply. This ping will also
reset the watchdog timeout, and can be used to deploy a reboot of the
bootloader.
The BOOTLOADER_ERASE
command is used to erase pages of the CC1110's flash
memory
The BOOTLOADER_WRITE_PAGE
command is used by the bootloader to write to the
CC1110's flash memory.
The bootloader can send acks similar to the default radio. See also:
ACK
The bootloader can send nacks similar to the default radio. See also:
NACK
The example project is a good learning resource and a great way to get started. However, any serious application is going to require frequency selection as well as some custom commands and board settings. The recommended approach is to fork the OpenLST repository and make your changes.
The sample project is laid out as follows:
openlst
- git repository, root
Vagrantfile
- file, template for a Vagrant/VirtualBox VM that includes the toolchainbuild
- directory, contains a Dockerfile useful for the SDCC toolchainopen-lst
- submodule containing the open-lst core repositoryradios
- directory containing build target makefiles and custom codeopenlst_437
- directory containing custom makefiles and code for the sample amateur radioboard.h
- configuration options for theopenlst_437
example projectboard.c
- custom initialization code for the sample boardBoard.mk
- a make include file used to describe the build targets
README.md
- general repository informationMakefile
- this makefile sources the Board.mk files from all the radio definitions
The easiest way to make your own project is to fork this repository by pushing it to your own remote, like:
$ git clone https://www.planet.com/open/openlst.git
$ cd openlst
$ git remote rename origin openlst
$ git remote add origin MY_GIT_HOST
$ git push origin master
To add a new radio target (in this example called my_radio
):
- Create a directory under "radios" for the new target:
$ mkdir radios/my_radio
- Create a
board.c
file underradios/my_radio
. To get started, it is recommended that you copy theboard.c
file fromopenlst_437
as it contains PA control and pin setup logic for the sample board:cp radios/openlst_437/board.c radios/my_radio/board.c
- Create a
board.h
file underradios/my_radio
. Again, to get started, just copy the file fromopenlst_437
as it supports the sample board:cp radios/openlst_437/board.h radios/my_radio/board.h
- Create a
Board.mk
file underradios/my_radio
. Its contents should be as follows:You can adjust these settings later (like modifying the UART enable setting), but these match well with the sample board.RADIOS += my_radio BOOTLOADERS += my_radio my_radio_DIR := $(dir $(lastword $(MAKEFILE_LIST))) # Source files my_radio_SRCS := \ $(my_radio_DIR)/board.c my_radio_CFLAGS := -DCUSTOM_BOARD_INIT -I$(my_radio_DIR) # Disable UART0 in the bootloader to save space my_radio_BOOTLOADER_CFLAGS := -DUART0_ENABLED=0
- Add an include directive to the top level (repository root) Makefile. This
should go before any other include directives as the first line of the file:
This will add your new target to the make radios and make bootloaders targets as well as adding individual targets like
include radios/my_radio/Board.mk
make my_radio_bootloader
andmake my_radio_radio
.
Now test your changes by running make from the project root. Both the radio and
bootloader images should compile successfully and produce my_radio_radio.hex
and my_radio_bootloader.hex
files in the project root.
The reference design uses a 27MHz clock for the CC1110. Modify this value if you are using a different oscillator. You must also update the flash write (FWT) frequency per page 88 of the datasheet.
#define F_CLK 27000000
#define FWT_FREQUENCY 36
The default message type for OpenLST is 0x05. This value is arbitrary and can be modified if necessary:
#define MSG_TYPE_RADIO_OUT 5
#define MSG_TYPE_RADIO_IN 5
Messages with other type codes are forwarded rather than processed.
You can set one of these values to 0 to disable the transmit or receive functionality:
#define CONFIG_CAPABLE_RF_RX 1
#define CONFIG_CAPABLE_RF_TX 1
OpenLST supports two independent UARTs. You can disable one or both of these by setting the values below to 0:
#define UART0_ENABLED 1
#define UART1_ENABLED 1
By default both UARTs operate at 115200 baud. You can reconfigure the baud rate here. Keep in mind this depends on the system clock rate. See page 155 of the datasheet for details. Both the BAUD and GCR settings contribute to define the baud rate.
#define CONFIG_UART0_BAUD 24
#define CONFIG_UART1_BAUD 24
#define CONFIG_UART0_GCR 12
#define CONFIG_UART1_GCR 12
UART1 supports flow control. By default it is enabled here:
#define CONFIG_UART1_USE_FLOW_CTRL 1
#define CONFIG_UART1_FLOW_PIN P0_3
Default UART configurations can be overridden here if you need to make hardware customizations or pin changes:
#define CONFIG_UART0_UCR ((1<<7) | (1<<1))
#define CONFIG_UART1_UCR ((1<<7) | (1<<1))
The default transmit and receive modes can be overridden. Keep in mind any
custom modes will need to be defined in board.h (you'll need to override the
lst_rf_mode_e enum
)
#define RADIO_MODE_DEFAULT_RX amateur_rf_mode_437_7k_FEC
#define RADIO_MODE_DEFAULT_TX amateur_rf_mode_437_7k_FEC
Ranging response can also be overridden:
#define RADIO_MODE_RANGING_RX amateur_rf_mode_437_10k_ranging
#define RADIO_MODE_RANGING_TX amateur_rf_mode_437_10k_ranging
The number of timer cycles between a ranging request and a ranging response can be modified here:
#define RF_PRECISE_TIMING_DELAY 3
Unless commanded otherwise, the radio defaults to rebooting every 10 minutes. That value can be adjusted here:
#define AUTO_REBOOT_SECONDS 600
The radio will reject requests to delay the reboot by more than
AUTO_REBOOT_MAX
, which is normally 1 week:
#define AUTO_REBOOT_MAX 604800
By default, the bootloader does not forward messages at all while the application does. Message forwarding can be enabled in the bootloader by setting these to 1 or disabled in the application by setting them to 0.
#define FORWARD_MESSAGES_UART1 1
#define FORWARD_MESSAGES_UART0 1
#define FORWARD_MESSAGES_RF 1
By default all utility and library functions are included. Code size can be reduced by disabling some of these functions:
#define KEEP_CODE_SMALL 0
By default all ADC channels are disabled (input disabled). You can enabled some or all of these channels using the bitmask. Keep in mind this overrides the PDIR setting for the pin.
#define ADCCFG_CONFIG 0b00000000
The bootloader enables the CC1110's hardware watchdog timer. You can adjust this timing if necessary from its default (about 1s). Be careful not to set it too short (application never boots) or too high (outside the limits of the timer).
#define COMMAND_WATCHDOG_DELAY 45000
If you just want to change the center frequency or some of the basic modulation parameters, redefining these constants may be sufficient:
For frequency customization, see the CC1110 datasheet on how to set these registers, or use SmartRF studio to derive them:
#define RF_FSCTRL1 0x06
#define RF_FSCTRL0 0x00
#define RF_FREQ2 0x10
#define RF_FREQ1 0x2F
#define RF_FREQ0 0x69
Channel bandwidth, data rates, and sync words can also be overridden here:
#define RF_SYNC_WORD1 0xD3
#define RF_SYNC_WORD0 0x91
#define RF_CHAN_BW_E 3
#define RF_CHAN_BW_M 3
#define RF_CHAN_BW_RANGING_E 3
#define RF_CHAN_BW_RANGING_M 3
#define RF_DRATE_E 8
#define RF_DRATE_M 32
#define RF_DRATE_RANGING_E 8
#define RF_DRATE_RANGING_M 132
#define RF_CHANSPC_E 3
#define RF_CHANSPC_M 185
#define RF_CHANSPC_RANGING_E 3
#define RF_CHANSPC_RANGING_M 185
#define RF_DEVIATN_E 1
#define RF_DEVIATN_M 1
#define RF_DEVIATN_RANGING_E 2
#define RF_DEVIATN_RANGING_M 4
#define RF_FSCAL3_CONFIG 201
#define RF_FSCAL2_CONFIG 10
#define RF_FSCAL1_CONFIG 0
#define RF_FSCAL0_CONFIG 31
#define RF_TEST0_CONFIG 9
The power setting can be overridden if you are using a different power amplifier or no power amplifier:
#define RF_PA_CONFIG 192
To define custom RF modes for the CC1110 set BOARD_RF_SETTINGS
to 1 in
board.h
:
#define BOARD_RF_SETTINGS 1
Also in board.h
, you will need to define an enum for each supported radio
mode you wish to create:
typedef enum {
my_radio_rf_mode_430MHz = 0,
my_radio_rf_mode_432MHz = 1
} lst_rf_mode_e;
And decide which modes are the default for receive and transmit:
#define RADIO_MODE_DEFAULT_RX my_radio_rf_mode_430MHz
#define RADIO_MODE_DEFAULT_TX my_radio_rf_mode_432MHz
These modes must then be defined in board.c
by defining a
board_apply_radio_settings
function:
uint8_t board_apply_radio_settings(uint8_t mode) {
switch (mode) {
case my_radio_rf_mode_430MHz:
...
break;
case my_radio_rf_mode_432MHz:
...
break;
default:
return RADIO_MODE_INVALID;
}
return RADIO_MODE_OK;
}
Inside each case statement, the following registers need to be set (described in the CC1110 datasheet):
PKTLEN
PKTCTRL1
PKTCTRL0
CHANNR
SYNC0
SYNC1
MDMCFG4
MDMCFG3
MDMCFG2
MDMCFG1
MDMCFG0
DEVIATN
MCSM2
MCSM1
MCSM0
FOCCFG
BSCFG
AGCCTRL2
AGCCTRL1
AGCCTRL0
FREND1
FREND0
FSCAL3
FSCAL2
FSCAL1
FSCAL0
TEST2
TEST1
TEST0
PA_TABLE0
FSCTRL1
FSCTRL0
FREQ2
FREQ1
FREQ0
The OpenLST core repository has good example settings in the board_defaults.c
file. Values for these parameters can be derived using Texas Instruments
SmartRF Studio.
- Signature verification of application binaries
- Reprogramming via UART
- Reprogramming over the air
- Locked code pages for extra safety assurance
- Real-time clock
- Time of light ranging
- Basic callsign support
- Command/message forwarding from UART to RF and vice versa
- Settable reboot timer
Custom command handlers can be added by defining CUSTOM_COMMANDS
in board.h
and providing a custom_commands
function in board.c
(with a forward definition
in board.h
), like:
uint8_t custom_commands(const __xdata command_t *cmd, uint8_t len, __xdata command_t *reply) {
switch (cmd->header.command) {
...
}
}
The OpenLST project includes an example hardware implementation. This design is largely based on the Texas Instruments reference design for the CC1110 microcontroller and is targeted for operation at 437 MHz. The design also incorporates an external power amplifier module (Qorvo RFFM6403) which which boosts transmit power to 1 W (+30 dBm). The user is of course responsible for obtaining a suitable license for operating the transmitter.
Although the reference design is intended for use at 437 MHz, it is possible to operate at other frequencies. The transmit power amplifier module is rated for operation from 405 MHz to 475 MHz. It may be necessary to adjust the balun / matching network between the CC1110 and the PA if operating more than a few megahertz away from 437 MHz. The CC1110 itself is capable of operating on a much wider span of frequencies.
The hardware reference design is implemented in the populate open-source PCB tool, KiCAD (v4.0.7). A schematic, bill of materials, component footprints, PCB layout and ready-to-fab Gerber files are included in the package. The design can also serve as a jumping off point for integrating the transceiver with other circuitry.
Care has been taken to ensure that the design can be easily replicated. A four-layer stackup has been selected that is available from many of the low-cost hobbyist board houses (e.g., OSH Park). The design has not been optimized for size, but rather to be easy to assemble. The use of surface mount components is necessary for this project, however, hand assembly is certainly feasible.
Parameter | Value | Notes |
---|---|---|
Frequency | 437 MHz | 405-475 MHz covered by power amplifier module, Split frequency operation also available with firmware mods |
RF Transmit Power | 1 W (+30 dBm) | Lower power possible by putting PA into bypass |
Modulation format | 2FSK | Variable (2FSK example project) |
User data rate | 7.4 kBaud | Variable (See CC1110 Manual and board.c file) |
Signal Bandwidth | 60 kHz | Variable (60 kHz used by example) |
Receiver Sensitivity | -112 dBm | +/- 3 dB |
Transmit harmonics | -47 dBc | |
Input Power Supply | +5 VDC | |
Size | 5x6x0.5 cm | Excludes antenna |
Mass | 20g (approx) | Excludes antenna |
Power Consumption | TX: 8.0 W | 5V at 160 mA |
RX: 800 mW | 5V at 1.6 A | |
Interface | 3.3V TTL UART (x2) | 115,200 baud, 8N1 |
Choosing a frequency can be complicated and depends on your use case. This section is not meant to be exhaustive or offer advice, but some of these links may be useful.
University and hobbyist projects may be able to use amateur radio frequencies for communications. Users of amateur frequencies cannot be paid for their time, be sure to read Part 97, expecially Section 113. While OpenLST supports the entire 420-450 MHz Amateur radio band, the digital modulation generated by OpenLST is only allowed in a a small slice of this spectrum. Use 432.1-433.0 MHz for mixed-mode, weak signal, and propogation beacons, and 435-438 MHz for satellites. See the ARRL Band Plan for more information.
For more information about Amateur radio licensing for CubeSats, check out FCC Part 97 Amateur Radio Licensing for CubeSats document from AMSAT, and the Amateur Radio Satellite Frequency Coordination document from the IARU.
Commercial companies, whether they are privately funded, venture backed, or public, must use frequencies allocated for commercial services. For United States teams, the best way to determine which service your project fits under is to look at the existing service definitions in the FCC rules.
For this OpenLST radio implementation, commercial frequencies that are in this range include the Space Research downlink from 400.15-401 MHz, Space Operation downlink from 401-402 MHz, Earth Exploration uplink from 402-403 MHz, and Fixed and Land Mobile from 450-470 MHz. See Chapter 4b of the NTIA Red Book for the frequency table. Don't forget to read all the footnotes in Chapter 4c (such as US87 for 450 MHz uplink in the United States).
To change the transmit and/or receive frequencies, see the "Simple RF Customization" section above.
For those United States teams whose project is expected to last for two years or less, consider a Part 5 Experimental License. These types of licenses are very cheap and easier to get, provided they follow the existing frequency allocations. More information in this FCC Notice.
The OpenLST RF design works across all the frequency ranges described above, from 400 to 470 MHz. The only part that will need to change is the custom SAW filter (U8, STA1120A). This filter is centered at 446 MHz with a bandwidth of 20 MHz. For those teams wanting to use lower or higher frequencies, a different SAW filter must be procured. If you want to use the existing layout, Sawtron makes a wide selection of filters in the same package. Free samples are available, but lead times can be lengthy. For operation outside 400-470 MHz, a standard mixer may be placed on the output of the CC1110, or use a different frequency range in the CC1110.
There are a few common issues you might hit, and while we can't predict all of them, this section aims to give a broad background on some of the common issues. We recommend you take a look at the dedicated resources created by the specific projects' maintainers.
Many standard Linux programs will have a "man" page or manual page associated with them. To read the page, try:
$ man make
$ # Opens man page for make
Even more ubiquitous are help queries, usually accessed by -h
or --help
.
Many of the python helper scripts included with OpenLST will include help text,
for example:
$ radio_terminal --help
usage: radio_terminal [-h] [-u {0,1}] [--rx-socket RX_SOCKET]
[--tx-socket TX_SOCKET] [--echo-socket ECHO_SOCKET]
[--hwid HWID] [--seqnum SEQNUM] [--raw]
optional arguments:
-h, --help show this help message and exit
-u {0,1}, --uart {0,1}
Select the radio UART to watch (0 or 1). The default
is UART 1.
...
The bulk of back-end message handling is done by ZMQ / 0MQ / ZeroMQ. ZMQ
creates sockets (the default setup by OpenLST is for IPC sockets in Linux's
/tmp/
directory (which is commonly mounted as a tmpfs and is usually wiped on
reboot).
ZMQ allows us to "mux" or multiplex messaging so that multiple processes or
users can communicate simultaneously to the radio. In the default example,
users will communicate with the radio_mux
, which opens the UART and handles
the actual communication with the radio.
ZMQ has a few different models, and we recommend you read the ZMQ guide if you are unfamiliar (zmq manual). The default project uses the PUB/SUB and PUSH/PULL models.
ZMQ will have issues if the proper sockets don't exist. Check for the presence
of the sockets described in radio_mux.py
. If these files don't exist, there's
most likely an issue with either the device or the radio_mux
.
Communication with the radio in the demo project relies on the radio_mux
running to handle messages. Usually it should run as a daemon handled by the
underlying operating system's process supervisor. In the demo project,
radio_mux
is handled by systemd, but you can change it or run the mux by hand
if needed.
If the ZMQ sockets don't exist, check your process supervisor and make sure the
radio_mux
process is running.
The Linux kernel relies on a "userspace device" handler (udev) to interface with devices like the OpenLST's UART. The default project includes a udev configuration to create a named device for the OpenLST.
In general, you can ask the kernel to reexamine devices and rules by running commands like:
# udevadm control --reload-rules
# udevadm trigger
This project would not have been possible without the hard work of many people at Planet over the course of many years. We would especially like to thank:
- Henry Hallam
- Alex Ray
- Rob Zimmerman
- Matt Peddie
- Helen Lurie
- Matt Ligon
- Bryan Klofas
- Ryan Kingsbury
- Rob Harvey
- Lucas Eznarriaga
- Kiruthika Devaraj
- Kyle Colton
- Steve Burt
- Joseph Breu
- Tymm Zerr
OpenLST Copyright (C) 2018 Planet Labs Inc.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/
This document may contain technology or software the export of which is or may be restricted by the Export Administration Act and the Export Administration Regulations (EAR), 15 C.F.R. parts 730-774. Diversion contrary to U.S. law is prohibited.