CC1100/CC1100e/CC1101 Sub-GHz transceiver driver

This module contains the driver for the TI CC1100/CC110e/CC1101 Sub-GHz transceivers. More...

Detailed Description

This module contains the driver for the TI CC1100/CC110e/CC1101 Sub-GHz transceivers.

How the CC1100/CC1101 operate can be configured quite sophistically. This has the drawback, that configurations breaking laws and rules are complete possible. Please make sure that the configured output power, duty cycle, frequency range, etc. conform to the rules, standards and laws that apply in your use case.

Supported Hardware and how to obtain

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.)

Packet Format

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
| Preamble (4 bytes, handled by hardware, see MDMCFG1) |
| Sync Word (4 bytes, handled by hardware, see MDMCFG2) |
| Length Field | Destination | Source | Payload...
... (see Length Field) | CRC (handled by hardware) |
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.

Layer-2 Addresses

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 providing an implementation of cc1xxx_eui_get.

Base Band, Data Rate, Channel Bandwidth and Channel Map Configuration

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.

Calibration of the Frequency Generator

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.


The Driver Does Not Initialize Properly

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.

The Driver Initializes, but Communication Is Impossible

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.


 CC1100/CC1100e/CC1101 Sub-GHz transceiver driver compile configuration


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...


#define CC110X_MAX_FRAME_SIZE   0xFF
 Length of a layer 2 frame. More...
 Maximum (layer 2) payload size supported by the driver.
#define CC110X_MAX_CHANNELS   8
 Maximum number of channels supported by the driver.
 Default protocol for data that is coming in.


enum  cc110x_state_t {
  CC110X_STATE_IDLE = 0x00, CC110X_STATE_FRAME_READY = 0x08, CC110X_STATE_OFF = 0x10, CC110X_STATE_RX_MODE = 0x01,
 The state of the CC1100/CC1101 transceiver. More...
enum  cc110x_tx_power_t {
 Enumeration over the possible TX power settings the driver offers. More...


int cc110x_setup (cc110x_t *dev, const cc110x_params_t *params, uint8_t index)
 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...

Macro Definition Documentation


#define CC110X_MAX_FRAME_SIZE   0xFF

Length of a layer 2 frame.

This does not include the preamble, sync word, CRC field, and length field.

Definition at line 216 of file cc110x.h.

Enumeration Type Documentation

◆ 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.


IDLE state.


Frame received, waiting for upper layer to retrieve it.

Transceiver is in IDLE state.


Frame received, waiting for upper layer to retrieve it.

Transceiver is in SLEEP state. There is no matching representation in the status byte, as reading the status byte will power up the transceiver in bring it in the IDLE state. Thus, we set the three least significant bits to the IDLE state


Listening for frames.


Receiving a frame just now.

Transceiver is in RX state.


Transmit mode.


Waiting for transceiver to complete outgoing transmission.

Transceiver is in TX state


Fast TX ready.


Device is calibrating.


PLL is settling.


RX FIFO overflown.


TX FIFO underflown.

Definition at line 257 of file cc110x.h.

◆ cc110x_tx_power_t

Enumeration over the possible TX power settings the driver offers.


-30 dBm


-20 dBm


-15 dBm


-10 dBm


0 dBm


5 dBm


7 dBm


10 dBm


Number of TX power options.

Definition at line 298 of file cc110x.h.

Function Documentation

◆ cc110x_apply_config()

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.

devDevice descriptor of the transceiver
confConfiguration to apply or NULL to only change channel map
chanmapChannel map to apply (must be compatible with conf)
channelThe channel to tune in after applying the config
Return values
-EINVALCalled with invalid argument
-EIOCommunication with the transceiver failed
-ERANGEChannel out of range or not supported by channel map
The application developer checked in the documentation that the channel map in 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.

◆ cc110x_full_calibration()

int cc110x_full_calibration ( cc110x_t dev)

Perform a calibration of the frequency generator for each supported channel.

devDevice descriptor of the transceiver
Return values
-EINVALCalled with invalid argument
-EAGAINCurrent state prevents deliberate calibration
-EIOCommunication 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.

◆ cc110x_set_channel()

int cc110x_set_channel ( cc110x_t dev,
uint8_t  channel 

Hops to the specified channel.

devDevice descriptor of the transceiver
channelChannel to hop to
Return values
-EINVALCalled with NULL as dev
-ERANGEChannel out of range or not supported by channel map
-EAGAINCurrently in a state that does not allow hopping, e.g. sending/receiving a packet, calibrating or handling transmission errors
-EIOCommunication 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.

◆ cc110x_set_tx_power()

int cc110x_set_tx_power ( cc110x_t dev,
cc110x_tx_power_t  power 

Set the TX power to the specified value.

devDevice descriptor of the transceiver
powerOutput power to apply
Return values
-EINVALCalled with NULL as dev
-ERANGECalled with an invalid value for power
-EAGAINChanging the TX power is in the current state not possible
-EIOCommunication with the transceiver failed

◆ cc110x_setup()

int cc110x_setup ( cc110x_t dev,
const cc110x_params_t params,
uint8_t  index 

Setup the CC1100/CC1101 driver, but perform no initialization.

netdev_driver_t::init can be used after this call to initialize the transceiver.

devDevice descriptor to use
paramsParameter of the device to setup
indexIndex of params in a global parameter struct array. If initialized manually, pass a unique identifier instead.
Return values
0Device successfully set up
-EINVALdev or params is NULL, or params is invalid