This module contains the driver for the TI CC1100/CC110e/CC1101 Sub-GHz transceivers.
This driver has been developed for the CC1101 and the older CC1100 transceiver and tested for both. However, it should work with the CC1100e as well - but this has NOT been tested at all.
It is suggested to go for the CC1101 when considering to buy one of the supported transceivers. The easiest way is to obtain CC1101 break out boards with a complete antenna circuit & antenna that can be connected via jumper wires using an 8 pin DIP pin header. These are sold in various flavours start from less than 2€ at quantity one at your favourite Far East store. Beware that while the CC1101 chip can operate a various base frequencies, the antenna circuit will only work for a single frequency band. Most break out boards will operate at 433 MHz, which is license free in many countries (but verify that for your country before buying!). EU citizens might prefer the 868 MHz band over the 433 MHz, as more license free bandwidth is available in the 868 MHz band in the EU. (But when deploying only a few dozens of devices, the 433 MHz band is also fine for EU citizens.) US citizens should go for the 900 MHz band (as 868 MHz is not license free in the USA), which even contains more bandwidth than the 868 MHz band. (However, the 900 MHz band has not been tested, as using it would be illegal in the EU.)
Field | Description |
---|---|
Preamble | 4 bytes, handled by hardware |
Sync Word | 4 bytes, handled by hardware |
Length Field | Handled by software & hardware, length of payload + 2 |
Destination | Handled by software & hardware, destination MAC address |
Source | Handled by software only, source MAC address |
Payload | Handled by software only, the payload to send |
CRC | 2 bytes, handled by hardware |
The Length Field contains the length of the driver supplied data in bytes, not counting the Length Field. Thus, it contains the length of the payload plus the length of the Destination and Source address.
The layer 2 addresses of the CC110x transceivers is a single byte long and the special value 0x00
for the destination address is used in broadcast transmissions. The transceiver is configured by this driver to ignore all packets unless the destination address matches the address of the transceiver or the destination address is 0x00
.
Please note that the layer 2 address by default is derived from the CPU ID. Due to the birthday paradox with only 20 devices the probability of a collision is already bigger than 50%. Thus, manual address assignment is supported by defining C110X_PARAM_L2ADDR
.
This driver allows to configure the base band, the data rate and the channel bandwidth using an cc110x_config_t data structure. Default configurations are supplied and name using the following scheme: cc110x_config_<BASE-BAND>_<DATA-RATE>_<CHANNEL-BANDWIDTH>
. (E.g. cc110x_config_868mhz_250kbps_300khz is the default configuration used by the MSB-A2 and the MSB-IoT boards.)
Using the cc110x_chanmap_t data structure the channel layout can be defined. This map contains 8 entries, each defines the offset from the base frequency defined in the cc110x_config_t data structure for each channel in steps of 50kHz. E.g. cc110x_chanmap_868mhz_lora provides the LoRa channels 10 to 17 in the 868MHz band. (The RIOT channel numbers will always start from 0, and currently only up to eight channels are supported. A special value of 255 as offset from the base frequency in the channel map is used mark the channel as disabled. This can be used if less than 8 non-overlapping channels are possible in the license free band.)
Please note that the channel map (cc110x_chanmap_t) must match the base configuration (cc110x_config_t), as the channel map is relative to the configured base frequency. Also, the distance between the channels in the channel map should match the channel bandwidth of the configuration, as otherwise channels could overlap.
Both configuration and matching channel map can be applied using cc110x_apply_config. Please consider this as a slow operation, as the transceiver needs to be calibrated for each channel in the channel map.
The CC110x transceivers use a voltage controlled oscillator (VCO) and a phase locked loop (PLL) for frequency generation. However, they need to be calibrated to work correctly with the given supply voltage and the current temperature. The driver will perform this calibration during startup, but when the supply voltage or the temperature is not stable, a recalibration is required whenever the supply voltage of temperature has changed too much since the last calibration. This can be done by calling cc110x_full_calibration. It is left to the application developer to perform this calibration when needed. During a test of about 2 hours of operation in an in-door environment with a stable temperature the CC1101 has worked reliable without any calibration at all (except for the automatic calibration at start up). So there are use cases which do not require any recalibration at all.
Set ENABLE_DEBUG
in cc110x_netdev.c
to 1
to get debug output, which will likely tell you what is going wrong. There are basically two things that can fail:
Upon initialization the driver will read out the part number and version of the transceiver. If those do not match the ones expected for the CC1100, CC1100E, or the CC1101 the driver will refuse to initialize. If this fails, most likely incorrect values are read out and the SPI communication does not work correctly. However, future revisions of the CC110X transceivers might be produced and might have different values for the part number or version. If this should happen and they remain compatible with the driver, their part number & revision needs to be added to the driver.
After uploading the configuration, the driver will read back the configuration to verify it. If the SPI communication is not reliable (e.g. sporadically bits flip), this will fail from time to time. E.g. on the MSB-IoT boards this is the case when the SPI interface operates at a clock of 5MHz, but it becomes reliable when clocked at 1MHz.
If two transceivers are too close to each other and TX power is at maximum, the signal is just too strong to be received correctly. Reducing TX power or increasing the distance (about half a meter should be fine) will solve this issue.
While the chips can operate at any base frequency offered by the driver, the circuit the chip is connected to and the antenna are build for a single base band. Check if your configuration matches the frequency range the board is build for. E.g. most break out boards operate at 433MHz, but there are also boards for 868MHz.
Modules | |
CC1100/CC1100e/CC1101 Sub-GHz transceiver driver compile configuration | |
Files | |
file | cc110x_calibration.h |
Calibration related functions of the CC110x transceiver driver. | |
file | cc110x_communication.h |
Functions to communicate with the CC1100/CC1101 transceiver. | |
file | cc110x_constants.h |
Constants for the CC1100/CC1101 driver. | |
file | cc110x_internal.h |
Internal functions of the CC110x transceiver driver. | |
file | cc110x_netdev.h |
Functions related to the netdev interface of the CC110x driver. | |
file | cc110x_params.h |
cc110x board specific configuration | |
file | cc110x_rx_tx.h |
Functions to related to RX/TX of the CC110x transceiver driver. | |
file | cc110x_settings.h |
Default settings of the TI CC1100/CC1101 transceiver. | |
file | cc110x.h |
Interface definition for the CC1100/CC1101 driver. | |
Data Structures | |
struct | cc110x_patable_t |
Structure that holds the PATABLE, which allows to configure the 8 available output power levels using a magic number for each level. More... | |
struct | cc110x_config_t |
Configuration of the transceiver to use. More... | |
struct | cc110x_chanmap_t |
Structure to hold mapping between virtual and physical channel numbers. More... | |
struct | cc110x_params_t |
Structure holding all parameter for driver initialization. More... | |
struct | cc110x_fs_calibration_t |
Structure holding the calibration data of the frequency synthesizer. More... | |
struct | cc110x_framebuf_t |
Buffer to temporary store incoming/outgoing packet. More... | |
struct | cc110x_t |
Device descriptor for CC1100/CC1101 transceivers. More... | |
Macros | |
#define | CC110X_MAX_FRAME_SIZE 0xFF |
Length of a layer 2 frame. More... | |
#define | CC110X_MAX_PAYLOAD_SIZE (CC110X_MAX_FRAME_SIZE - CC1XXX_HEADER_SIZE) |
Maximum (layer 2) payload size supported by the driver. | |
#define | CC110X_MAX_CHANNELS 8 |
Maximum number of channels supported by the driver. | |
#define | CC110X_L2ADDR_AUTO 0x00 |
Special value to indicate that layer 2 address should be derived from the CPU-ID. | |
#define | CC110X_DEFAULT_PROTOCOL (GNRC_NETTYPE_SIXLOWPAN) |
Default protocol for data that is coming in. | |
Enumerations | |
enum | cc110x_state_t { CC110X_STATE_IDLE = 0x00, CC110X_STATE_FRAME_READY = 0x08, CC110X_STATE_OFF = 0x10, CC110X_STATE_RX_MODE = 0x01, CC110X_STATE_RECEIVING = 0x09, CC110X_STATE_TX_MODE = 0x02, CC110X_STATE_TX_COMPLETING = 0x0A, CC110X_STATE_FSTXON = 0x03, CC110X_STATE_CALIBRATE = 0x04, CC110X_STATE_SETTLING = 0x05, CC110X_STATE_RXFIFO_OVERFLOW = 0x06, CC110X_STATE_TXFIFO_UNDERFLOW = 0x07 } |
The state of the CC1100/CC1101 transceiver. More... | |
enum | cc110x_tx_power_t { CC110X_TX_POWER_MINUS_30_DBM, CC110X_TX_POWER_MINUS_20_DBM, CC110X_TX_POWER_MINUS_15_DBM, CC110X_TX_POWER_MINUS_10_DBM, CC110X_TX_POWER_0_DBM, CC110X_TX_POWER_PLUS_5_DBM, CC110X_TX_POWER_PLUS_7_DBM, CC110X_TX_POWER_PLUS_10_DBM, CC110X_TX_POWER_NUMOF } |
Enumeration over the possible TX power settings the driver offers. More... | |
Functions | |
int | cc110x_setup (cc110x_t *dev, const cc110x_params_t *params) |
Setup the CC1100/CC1101 driver, but perform no initialization. More... | |
int | cc110x_apply_config (cc110x_t *dev, const cc110x_config_t *conf, const cc110x_chanmap_t *chanmap, uint8_t channel) |
Apply the given configuration and the given channel map and performs a recalibration. More... | |
int | cc110x_full_calibration (cc110x_t *dev) |
Perform a calibration of the frequency generator for each supported channel. More... | |
int | cc110x_set_channel (cc110x_t *dev, uint8_t channel) |
Hops to the specified channel. More... | |
int | cc110x_set_tx_power (cc110x_t *dev, cc110x_tx_power_t power) |
Set the TX power to the specified value. More... | |
#define CC110X_MAX_FRAME_SIZE 0xFF |
enum cc110x_state_t |
The state of the CC1100/CC1101 transceiver.
The three least significant bytes match the representation of the matching transceiver state given in the status byte of the hardware. See Table 32 on page 31 in the data sheet for the possible states in the status byte.
enum cc110x_tx_power_t |
Enumeration over the possible TX power settings the driver offers.
int cc110x_apply_config | ( | cc110x_t * | dev, |
const cc110x_config_t * | conf, | ||
const cc110x_chanmap_t * | chanmap, | ||
uint8_t | channel | ||
) |
Apply the given configuration and the given channel map and performs a recalibration.
dev | Device descriptor of the transceiver |
conf | Configuration to apply or NULL to only change channel map |
chanmap | Channel map to apply (must be compatible with conf ) |
channel | The channel to tune in after applying the config |
0 | Success |
-EINVAL | Called with invalid argument |
-EIO | Communication with the transceiver failed |
-ERANGE | Channel out of range or not supported by channel map |
chanmap
is compatible with the configuration in conf
Because the configuration (potentially) changes the channel bandwidth, the old channel map is rendered invalid. This API therefore asks for both to make sure an application developer does not forget to update the channel map. Because the old calibration data is also rendered invalid, cc110x_full_calibration is called to update it.
int cc110x_full_calibration | ( | cc110x_t * | dev | ) |
Perform a calibration of the frequency generator for each supported channel.
dev | Device descriptor of the transceiver |
0 | Success |
-EINVAL | Called with invalid argument |
-EAGAIN | Current state prevents deliberate calibration |
-EIO | Communication with the transceiver failed |
Tunes in each supported channel and calibrates the transceiver. The calibration data is stored so that cc110x_set_channel can skip the calibration phase and use the stored calibration data instead.
int cc110x_set_channel | ( | cc110x_t * | dev, |
uint8_t | channel | ||
) |
Hops to the specified channel.
dev | Device descriptor of the transceiver |
channel | Channel to hop to |
0 | Success |
-EINVAL | Called with NULL as dev |
-ERANGE | Channel out of range or not supported by channel map |
-EAGAIN | Currently in a state that does not allow hopping, e.g. sending/receiving a packet, calibrating or handling transmission errors |
-EIO | Communication with the transceiver failed |
This function implements the fact channel hopping approach outlined in section 28.2 on page 64 in the data sheet, which skips the calibration phase by storing the calibration date for each channel in the driver.
int cc110x_set_tx_power | ( | cc110x_t * | dev, |
cc110x_tx_power_t | power | ||
) |
Set the TX power to the specified value.
dev | Device descriptor of the transceiver |
power | Output power to apply |
0 | Success |
-EINVAL | Called with NULL as dev |
-ERANGE | Called with an invalid value for power |
-EAGAIN | Changing the TX power is in the current state not possible |
-EIO | Communication with the transceiver failed |
int cc110x_setup | ( | cc110x_t * | dev, |
const cc110x_params_t * | params | ||
) |
Setup the CC1100/CC1101 driver, but perform no initialization.
netdev_driver_t::init can be used after this call to initialize the transceiver.
dev | Device descriptor to use |
params | Parameter of the device to setup |
0 | Device successfully set up |
-EINVAL | dev or params is NULL , or params is invalid |