Hello friends, I hope you are doing well. In today's tutorial, I am going to share our CC1101 Proteus Library. With this library, we can place two CC1101 RF modules in one Proteus design, connect each module to an Arduino Uno and send messages from one board to the other at 433.92 MHz. The receiver prints every message with its signal strength, and a row of distance buttons lets us test how far the link can reach.

We will start with the basics of the module, install the library files and wire the circuit. After that, we will run the supplied two-Arduino simulation, change the distance between the radios and understand both Arduino sketches. We will also calculate the signal strength values shown on the Virtual Terminal. The download includes the wired project, two compiled HEX files, both sketches and the Arduino driver.

This tutorial uses our V1.0 package, the TEP Arduino UNO V3 and a 16 MHz clock. The package notes record a test of the supplied project in Proteus 8.5 SP0. In the running screenshot below, the transmitter is on the left and the receiver is on the right. Four messages have been sent and received, and the signal strength of the last message is lower because the distance was increased.

Figure: The transmitter on the left has sent four messages. The receiver on the right shows -75 dBm for the first three and -87 dBm after the distance was changed to 250 m.

What Is the CC1101 RF Module?

The CC1101 is a radio transceiver from Texas Instruments for frequencies below 1 GHz. A transceiver can both transmit and receive, so we use the same module on each side of a wireless link. The microcontroller configures the chip and exchanges data with it through SPI. Texas Instruments describes the chip in the CC1101 datasheet.

Main Features of the CC1101

  • It works in the 300 to 348 MHz, 387 to 464 MHz and 779 to 928 MHz bands. The common frequencies are 315, 433, 868 and 915 MHz.
  • It supports 2-FSK, GFSK, 4-FSK, MSK, OOK and ASK modulation.
  • Its data rate is programmable from 0.6 to 600 kbps.
  • Its output power is programmable up to +12 dBm.
  • Its supply range is 1.8 to 3.6 V.
  • It builds and checks data packets by itself, including the sync word and the CRC.

Important Terms

  • dBm: a unit of signal power. A value of 0 dBm is 1 mW, and negative values are weaker signals.
  • RSSI: the received signal strength indicator. It tells us how strong the signal was at the receiver.
  • Sensitivity: the weakest signal that the receiver can still decode.
  • LQI: the link quality indicator. For the CC1101, a lower value means a better link.
  • Sync word: a fixed pattern at the start of a packet. The receiver accepts only packets with its own sync word.
  • CRC: an error-checking code at the end of a packet.

Features of Our Proteus Model

  • The component is named CC1101TEP and has eight pins.
  • Every radio placed in the same design shares one virtual band, so no wire is needed between the two sides.
  • A control panel beside each module shows its live settings, counters and the last packet.
  • Eight distance buttons, from 10 m to 5 km, set the distance to the other radios.
  • The Arduino communicates with the model through real SPI commands and registers.

Keep one distinction in mind. This is a functional model with a simple range calculation. It does not simulate antennas, buildings, reflections or interference. The distance buttons are useful for learning how power, data rate and distance are related, but they do not predict the range of a real installation.

Download the CC1101 Library for Proteus

First of all, download the V1.0 package using the button below. Extract the complete ZIP into a normal folder before opening the project, and keep the files of the simulation folder together.

Download CC1101 Proteus Library V1.0 and Arduino Simulation
Contents of the CC1101 Proteus package
Folder or fileContents and purpose
Proteus Library FilesTEPCC1101.LIB for the radio module, and the TEP Arduino UNO V3 LIB/IDX files.
Proteus Model FilesTEPCC1101.DLL, which provides the module's simulated behavior.
Proteus SimulationCC1101-ArduinoUnoV3.pdsprj, CC1101_Transmitter.hex, CC1101_Receiver.hex and a local copy of the DLL.
Arduino CodeBoth sketches, the SmartRC-CC1101 3.0.2 driver, the AVR core archive and a firmware rebuild script.
Model SourceThe chip model, SPI transport, shared radio band and Proteus adapter.
DocumentationModel notes, third-party notices and a preview of the board artwork.
README.txt and SHA256SUMS.txtQuick-start instructions and checksums of the packaged files.

The Proteus library and the Arduino library have different jobs. The LIB file defines the component that we place on the schematic, and the DLL gives it its behavior. The SmartRC-CC1101 Arduino library gives our sketch the functions for talking to the radio. Installing the Arduino library alone will not make CC1101TEP appear in Proteus.

How to Install the CC1101 Proteus Library

Copy the Library and Model Files

Save your work and close Proteus before copying the files. Then follow these steps:

  1. Open the extracted Proteus Library Files folder.
  2. Copy TEPCC1101.LIB into the library directory configured for your Proteus installation.
  3. Copy ArduinoV3TEP.LIB and ArduinoV3TEP.IDX from the same folder if our TEP Arduino UNO V3 library is not installed already.
  4. Open Proteus Model Files and copy TEPCC1101.DLL into your configured Proteus MODELS directory.
  5. Restart Proteus, open Pick Devices and search for CC1101TEP.
  6. Place the module on the schematic, or open the supplied project to use the completed circuit.

Points to Remember

  • Use the library and model folders that your installation actually searches. Their locations differ between installations.
  • The module is supplied as a LIB file without a separate IDX. The included IDX belongs to the Arduino board.
  • Keep the extra DLL beside the project in the Proteus Simulation folder.
  • The two HEX files are programs for the two Arduino boards. The radio module does not need a HEX file.
  • Compatibility with Proteus 7 has not been established.

The Arduino board in this project comes from our Arduino Library for Proteus V3.0. Start with the supplied project, so that the boards, wiring and firmware match the demonstration.

CC1101 Pinout and Arduino Uno Wiring

The TEP module has eight pins along its lower edge. From left to right, they are VCC, GND, SCK, MISO, MOSI, CSN, GDO2 and GDO0. Start each wire at the exposed pin endpoint below the board artwork.

Connections used on both Arduino boards
Module pinConnectionPurpose
VCCPositive supply terminalPowers the digital model.
GNDGroundProvides the shared reference.
SCKArduino Uno D13SPI clock from the Arduino.
MISOArduino Uno D12Data from the module to the Arduino.
MOSIArduino Uno D11Data from the Arduino to the module.
CSNArduino Uno D10Selects the module for an SPI command. It is active low.
GDO2Arduino Uno D9General output of the chip. The supplied sketches do not use it.
GDO0Arduino Uno D2Goes high at the sync word and low at the end of a packet.
Figure: The stopped circuit connects SCK, MISO, MOSI and CSN to D13, D12, D11 and D10, GDO0 to D2 and GDO2 to D9 on both boards.

Both boards use the same wiring. The Arduino named ARD1 works with module U1 as the transmitter, and ARD2 works with U2 as the receiver. The GDO0 wire is important. Both sketches watch this pin to find out when a packet has been sent or received.

Virtual Terminal Connections

  • Connect Arduino D1/TX to RXD on the Virtual Terminal of each board.
  • Set both terminals to 9600 baud, eight data bits, no parity and one stop bit.
  • The return connection to D0/RX is shown in the circuit, but these sketches do not read typed commands.

Notes for Physical Hardware

  • The real CC1101 is a 3.3 V part with a supply range of 1.8 to 3.6 V. Connecting its supply to 5 V can damage it.
  • The model does not check the supply voltage, so a working simulation does not prove that your hardware supply is correct.
  • Check the logic levels required by your module before connecting a 5 V Arduino.
  • The header order of hardware modules varies. Follow the labels printed on your module.
  • Use only the frequencies and power levels that are permitted in your country.

Run the Two-Arduino Simulation

Start the Simulation

  1. Open Proteus Simulation/CC1101-ArduinoUnoV3.pdsprj from the extracted package.
  2. Keep both HEX files and TEPCC1101.DLL in that folder.
  3. Double-click ARD1 and confirm that its Program File is CC1101_Transmitter.hex.
  4. Double-click ARD2 and confirm that its Program File is CC1101_Receiver.hex.
  5. Confirm the 16 MHz clock on both boards and 9600 baud on both terminals.
  6. Press Run. If the two terminal windows open on top of each other, drag them apart.

Read the Terminal Output

The transmitter terminal prints its heading and then CC1101 ready: 433.92 MHz, 2-FSK, 100 kBaud, CRC on. After that, it prints one line every two seconds, such as Sent: Hello TEP #0. The receiver terminal prints Listening: 433.92 MHz, 2-FSK, 100 kBaud, CRC on, followed by a line for every message:

Received: Hello TEP #0 RSSI -75 dBm LQI 12

In the running screenshot at the top, messages 0 to 2 arrived with an RSSI of -75 dBm and an LQI of 12. These are the values for the default distance of 100 m. Before message 3, the distance on the transmitter's panel was changed to 250 m. That message arrived with -87 dBm and an LQI of 35. The signal is weaker, and the higher LQI shows a link of lower quality.

Understand the CC1101 Control Panel

The control panel is the most interesting part of this library. It shows what the radio is doing at every moment, and its distance buttons let us test the link without changing the code. Let us go through the panel from top to bottom.

The State Banner and Its Colors

The colored bar at the top shows the present state of the radio. The color tells us the kind of state at a glance.

States shown on the banner of the control panel
Banner textColorMeaning
IDLEBlueThe radio is on, but it is neither sending nor listening.
RXGreenThe radio is listening for packets.
TX - SENDINGOrangeA packet is being sent.
FSTXONBlueThe frequency synthesizer is running, and the radio is ready to send quickly.
SLEEPBlueThe sketch has put the radio into its power-saving mode.
XOFFBlueThe crystal oscillator is switched off.
RX FIFO OVERFLOWRedThe receive buffer is full, because the sketch did not read the packets.
TX FIFO UNDERFLOWRedThe transmit buffer became empty during a transmission.
NO POWER - CHECK VCC / GNDRedThe module is not powered.
OUT OF BAND, with the frequencyRedThe selected frequency is outside the bands of the CC1101. Nothing is sent or received.
  • In our example, the receiver's banner is green and shows RX, because it listens all the time.
  • The transmitter's banner is blue and shows IDLE. One transmission lasts about 2.4 ms and the sketch then waits for two seconds, so you will rarely see the orange banner.
  • The word (ASYNC) after the state means that the radio works in asynchronous serial mode. The driver selects this mode when a sketch does not call setCCMode(1).

The Two Settings Lines

The next two lines show the radio settings. They are read from the registers of the chip, so they show what the sketch has really written.

Values on the two settings lines
Value in our exampleMeaningDriver function
433.920 MHzCarrier frequencysetMHZ()
CH 0Channel number, which is added to the base frequencysetChannel()
2-FSKModulation: 2-FSK, GFSK, ASK/OOK, 4-FSK or MSKsetModulation()
100.0 kBaudData ratesetDRate()
SYNC D391Sync word as four hexadecimal digitssetSyncWord()
CRC ONCRC setting, ON or OFFsetCrc()
VAR LENLength mode: VAR LEN, FIXED LEN or INFINITEsetLengthConfig()
+10 dBmOutput powersetPA()

VAR LEN means that the packet length is variable and is sent as the first byte of every packet. In asynchronous serial mode, the second line shows ASYNC SERIAL: DATA ON GDO0 instead of the packet settings.

These lines are the quickest way to find a configuration mistake. Put the two panels side by side and compare them:

  • The frequency, the modulation and the data rate must be the same on both panels.
  • The sync word and the length mode must be the same.
  • The output power may be different. Only the power of the sending radio matters for a packet.

The stopped circuit in the wiring section already shows 433.920 MHz, 2-FSK, 100.0 kBaud, SYNC D391 and +10 dBm. When the simulation runs, the panels show the values written by the sketches.

The Counters

  • SENT counts the packets that have left this radio. It increases even when no radio receives the packet.
  • RECEIVED counts the packets that this radio has received with a correct CRC.
  • TOO WEAK counts the packets that matched the settings of this radio but were weaker than its sensitivity.
  • CRC ERR appears at the end of the line after the first packet with a CRC error.

A packet with different settings is not counted by the receiver at all. We can use this to find the reason for a missing message.

How to read the counters while the transmitter's SENT counter increases
Receiver panelMeaning
RECEIVED increases.The link works.
TOO WEAK increases.The settings match, but the distance is too large for the power and the data rate.
CRC ERR appears.The signal is at the edge of the sensitivity, or the CRC settings are different.
No counter changes.The settings are different, or the receiver is not in RX.

The Last Packet Lines

Before the first packet arrives, the panel shows LAST PACKET RECEIVED with a dash below it. After that, the first line shows the RSSI and the LQI of the latest packet. The second line shows the payload in quotation marks, followed by its length. In the running screenshot, the receiver shows "Hello TEP #3" with 12 bytes. A payload that is not readable text is shown as hexadecimal bytes.

The Distance Buttons and the Prediction Line

Below the heading DISTANCE TO THE OTHER RADIOS, there are eight buttons: 10 m, 50 m, 100 m, 250 m, 500 m, 1 km, 2 km and 5 km. The selected button is blue, and the default is 100 m. Click a button while the simulation runs.

The line below the buttons is a prediction. At the start, it reads AT 100 m: -75 dBm, 100 kBaud NEEDS -99 dBm -> OK. It has three parts:

  1. AT 100 m: -75 dBm is the signal strength that a packet from this radio has at the selected distance.
  2. 100 kBaud NEEDS -99 dBm is the sensitivity at the present data rate.
  3. OK or TOO WEAK is the result of comparing the two values.

The prediction uses the settings of its own panel only. The Simulation Log records every distance change, the first packet sent and received, and the first packet that was too weak.

Panel Combinations: Distance, Data Rate and Power

Now comes the exciting part. The result of a transmission depends on several settings together. We will take the combinations one by one. The values for 100 m, 250 m and 500 m at 100 kBaud agree with the screenshots of this tutorial. The other values are calculated with the formulas of the model, which we will work through after the code.

Combination 1: The Distances on the Two Panels

Each radio has its own distance buttons. For a packet between two radios, the model uses the larger of the two selected distances.

Link distance for different selections at +10 dBm and 100 kBaud
Transmitter panelReceiver panelLink distanceRSSILQIResult
100 m100 m100 m-75 dBm12Received
250 m100 m250 m-87 dBm35Received
250 m500 m500 m-96 dBm54Received
10 m1 km1 km-105 dBmNoneToo weak
1 km10 m1 km-105 dBmNoneToo weak

The second row is the running screenshot at the top of this tutorial. The transmitter is set to 250 m and the receiver to 100 m, and message 3 arrived with -87 dBm. This rule has three consequences:

  • To move the radios apart, one click on either panel is enough.
  • To bring them together again, both panels must show a short distance.
  • The prediction line of one panel can show OK while the packets are too weak, because the other panel has a larger distance. The LAST PACKET line always shows the real value.

Try the Distance Buttons

  1. Let the simulation run at 100 m and note the RSSI and the LQI.
  2. Click 250 m on one panel and wait for the next message.
  3. Click 500 m and compare the values again.
  4. Click 1 km. The receiver stops printing, and its TOO WEAK counter increases.
  5. Click a shorter distance to restore the link.
Figure: Messages 15 and 16 were too weak and are missing on the receiver. At 500 m, messages 20 and 21 arrive with -96 dBm and an LQI of 54.

In this screenshot, the receiver has printed messages 8 to 14 and then 17 to 21. Messages 15 and 16 are missing. During those two messages, the distance was too large for the data rate, and the receiver's panel shows TOO WEAK 2. Messages 20 and 21 arrived with -96 dBm and an LQI of 54. The receiver is set to 500 m and the transmitter to 250 m, so the link distance is 500 m.

The counters agree with the terminals. The transmitter's panel shows SENT 22, which are messages 0 to 21. The receiver's panel shows RECEIVED 20 and TOO WEAK 2, and 20 + 2 = 22.

Notice that the transmitter printed Sent: for messages 15 and 16 as well. The sketch does not use acknowledgements, so the transmitter cannot know whether a message has arrived.

Combination 2: Distance and Data Rate

The hint on the panel says that a lower kBaud value reaches further. A slower data rate has a better sensitivity, so the same signal can be decoded at a larger distance.

Reception at 433.92 MHz and +10 dBm for five data rates
DistanceRSSI1.2 kBaud38.4 kBaud100 kBaud250 kBaud500 kBaud
10 m-45 dBmReceivedReceivedReceivedReceivedReceived
50 m-66 dBmReceivedReceivedReceivedReceivedReceived
100 m-75 dBmReceivedReceivedReceivedReceivedReceived
250 m-87 dBmReceivedReceivedReceivedReceivedToo weak
500 m-96 dBmReceivedReceivedReceivedToo weakToo weak
1 km-105 dBmReceivedToo weakToo weakToo weakToo weak
2 km-114 dBmToo weakToo weakToo weakToo weakToo weak
5 km-126 dBmToo weakToo weakToo weakToo weakToo weak

The price of a larger range is time. The same packet stays on the air much longer at a low data rate.

Sensitivity, range and air time of a 12-character message
Data rateSensitivityLargest distanceAir time
1.2 kBaud-112 dBm1 km126.7 ms
38.4 kBaud-104 dBm500 m4.0 ms
100 kBaud-99.4 dBm500 m1.5 ms
250 kBaud-95 dBm250 m0.6 ms
500 kBaud-86 dBm100 m0.3 ms
  • To change the data rate, add ELECHOUSE_cc1101.setDRate(1.2); after setCCMode(1). The order matters, because setCCMode(1) writes the data rate of 100 kBaud.
  • Use the same data rate in both sketches. The model accepts a difference of up to 10 percent.
  • After the change, the first settings line shows the new data rate, and the prediction line shows the new sensitivity.
  • In real hardware, a different data rate also needs a suitable receiver bandwidth and frequency deviation. The model does not check these two settings against the data rate.

Combination 3: Distance and Output Power

The output power moves every RSSI value up or down by the same amount. At 433 MHz, the driver offers eight power steps.

Output power steps at 433.92 MHz and 100 kBaud
Output powerRSSI at 100 mLargest distance with reception
+10 dBm-75 dBm500 m
+7 dBm-78 dBm250 m
+5 dBm-80 dBm250 m
0 dBm-85 dBm250 m
-10 dBm-95 dBm100 m
-15 dBm-100 dBm50 m
-20 dBm-105 dBm50 m
-30 dBm-115 dBm10 m
  • To change the power, add ELECHOUSE_cc1101.setPA(0); to the transmitter sketch. The panel then shows +0 dBm.
  • A value between two steps selects the next higher step. Values above 10 give +10 dBm at 433 MHz.
  • For a packet, only the power of the sending radio matters. The power shown on the receiver's panel is used for its own prediction line and for packets that it sends itself.

Combination 4: The CRC Error Zone

Between a good packet and a packet that is too weak, there is a small zone. When the signal is less than 1.5 dB above the sensitivity, the model delivers the packet with a CRC error.

We can reach this zone with +7 dBm at 500 m and 100 kBaud. The RSSI is 7 - 106.2 = -99.2 dBm, and the sensitivity is -99.4 dBm. The signal is only 0.2 dB above the limit. The receiver's terminal prints Packet with CRC error discarded, and CRC ERR appears on its panel. The RECEIVED counter does not increase.

Combination 5: Modulation

  • 2-FSK and GFSK can be mixed. A 2-FSK transmitter is received by a GFSK receiver in the model.
  • All other modulations must be the same on both sides.
  • For ASK/OOK, the sensitivity is 4 dB worse. At 100 kBaud, it becomes -95.4 dBm, so 500 m with -96 dBm is too weak and the largest distance is 250 m.

Combination 6: Frequency Band

A higher frequency has a higher path loss. The driver also uses a different highest power step in each band.

Frequency bands with the driver's default power at 100 kBaud
FrequencyLoss of the first metreDefault powerRSSI at 100 mLargest distance
315 MHz22.4 dB+10 dBm-72 dBm500 m
433.92 MHz25.2 dB+10 dBm-75 dBm500 m
868 MHz31.2 dB+12 dBm-79 dBm250 m
915 MHz31.7 dB+11 dBm-81 dBm250 m

Use the same setMHZ() value in both sketches. The two frequencies must agree within half of the receiver's bandwidth, which is about 100 kHz for the supplied settings.

Arduino Code for the CC1101 Transmitter

The following is the exact transmitter sketch included in the download. It uses the bundled SmartRC-CC1101-Driver-Lib, version 3.0.2. Use the supplied copy for your first build, so that your firmware matches the packaged HEX file.

// TEP CC1101 Transmitter Demo v1.0
// The Engineering Projects - www.TheEngineeringProjects.com
//
// Sends "Hello TEP #n" every 2 seconds on 433.92 MHz (2-FSK, 100 kBaud, CRC on).
// SendData() waits on GDO0: it goes high when the sync word has been sent and low
// at the end of the packet. Pair it with CC1101_Receiver on a second Arduino.
//
// Wiring (Arduino UNO): VCC -> 3.3V, GND -> GND, SCK -> D13, MISO -> D12, MOSI -> D11,
//                       CSN -> D10, GDO0 -> D2, GDO2 -> D9 (not used by this sketch)
// Library: SmartRC-CC1101-Driver-Lib by LSatan (Arduino Library Manager: "SmartRC-CC1101-Driver-Lib")

#include <ELECHOUSE_CC1101_SRC_DRV.h>

const byte GDO0_PIN = 2;
int counter = 0;

void setup() {
  Serial.begin(9600);
  Serial.println(F("TEP CC1101 Transmitter Demo v1.0"));
  ELECHOUSE_cc1101.Init();                 // Init() first: it sets up the SPI pins that getCC1101() uses
  if (!ELECHOUSE_cc1101.getCC1101()) {
    Serial.println(F("CC1101 not responding - check the SPI wiring and power"));
    while (true) {}
  }
  ELECHOUSE_cc1101.setGDO0(GDO0_PIN);
  ELECHOUSE_cc1101.setCCMode(1);           // packet mode
  ELECHOUSE_cc1101.setModulation(0);       // 2-FSK
  ELECHOUSE_cc1101.setMHZ(433.92);
  ELECHOUSE_cc1101.setSyncMode(2);         // 16/16 sync word bits
  ELECHOUSE_cc1101.setCrc(1);
  Serial.println(F("CC1101 ready: 433.92 MHz, 2-FSK, 100 kBaud, CRC on"));
}

void loop() {
  char message[32];
  snprintf(message, sizeof message, "Hello TEP #%d", counter++);
  ELECHOUSE_cc1101.SendData(message);      // returns when GDO0 signals the end of the packet
  Serial.print(F("Sent: "));
  Serial.println(message);
  delay(2000);
}

Initialize the Radio in the Correct Order

  1. Init() sets up the SPI pins, resets the chip and writes the driver's default settings.
  2. getCC1101() reads the chip's version register. If no valid value comes back, the sketch prints CC1101 not responding and stops.
  3. setGDO0(GDO0_PIN) tells the driver that GDO0 is connected to D2.

The order of the first two calls matters. In this driver version, the SPI pins are set up inside Init(). If getCC1101() is called first, it can report an error although the module is connected correctly. The SPI pins D10 to D13 are chosen by the driver for the Arduino Uno, so the sketch does not name them.

Configure the Radio

Radio settings of both sketches
Function callSetting
setCCMode(1)Packet mode. The chip builds complete packets, and the data rate becomes 100 kBaud.
setModulation(0)2-FSK modulation.
setMHZ(433.92)Carrier frequency of 433.92 MHz.
setSyncMode(2)All 16 bits of the sync word must match.
setCrc(1)CRC is added by the transmitter and checked by the receiver.

The output power is not set by the sketch. The driver's default value gives +10 dBm at 433 MHz, which is the value shown on the panel. Both sketches must use the same settings. A difference in frequency, modulation, data rate or sync word stops the reception.

Send a Message

Inside loop, snprintf writes the text and the counter into a buffer. The counter is increased after it is used, so the first message is number 0. The call SendData(message) does the following work:

  1. It writes the length of the text and then the text into the transmit buffer of the chip.
  2. It starts the transmission.
  3. It waits until GDO0 goes high, which means the sync word has been sent.
  4. It waits until GDO0 goes low again, which means the packet is complete.

Each wait is limited to 500 ms. If GDO0 is not connected to D2, the function waits for the full time and the sketch becomes slow. After sending, the sketch prints the message and waits for two seconds.

Arduino Code for the CC1101 Receiver

The setup part of the receiver is the same as in the transmitter. Here is the exact sketch from the package:

// TEP CC1101 Receiver Demo v1.0
// The Engineering Projects - www.TheEngineeringProjects.com
//
// Listens on 433.92 MHz (2-FSK, 100 kBaud, CRC on) and prints every packet with
// its RSSI and LQI. CheckReceiveFlag() watches GDO0: high when a sync word is
// received, low at the end of the packet. Pair it with CC1101_Transmitter.
//
// Wiring (Arduino UNO): VCC -> 3.3V, GND -> GND, SCK -> D13, MISO -> D12, MOSI -> D11,
//                       CSN -> D10, GDO0 -> D2, GDO2 -> D9 (not used by this sketch)
// Library: SmartRC-CC1101-Driver-Lib by LSatan (Arduino Library Manager: "SmartRC-CC1101-Driver-Lib")

#include <ELECHOUSE_CC1101_SRC_DRV.h>

const byte GDO0_PIN = 2;
byte buffer[61];

void setup() {
  Serial.begin(9600);
  Serial.println(F("TEP CC1101 Receiver Demo v1.0"));
  ELECHOUSE_cc1101.Init();                 // Init() first: it sets up the SPI pins that getCC1101() uses
  if (!ELECHOUSE_cc1101.getCC1101()) {
    Serial.println(F("CC1101 not responding - check the SPI wiring and power"));
    while (true) {}
  }
  ELECHOUSE_cc1101.setGDO0(GDO0_PIN);
  ELECHOUSE_cc1101.setCCMode(1);           // packet mode
  ELECHOUSE_cc1101.setModulation(0);       // 2-FSK
  ELECHOUSE_cc1101.setMHZ(433.92);
  ELECHOUSE_cc1101.setSyncMode(2);         // 16/16 sync word bits
  ELECHOUSE_cc1101.setCrc(1);
  Serial.println(F("Listening: 433.92 MHz, 2-FSK, 100 kBaud, CRC on"));
}

void loop() {
  if (ELECHOUSE_cc1101.CheckReceiveFlag()) {       // a packet has just been received
    if (ELECHOUSE_cc1101.CheckCRC()) {
      int rssi = ELECHOUSE_cc1101.getRssi();         // read before ReceiveData() restarts RX
      byte lqi = ELECHOUSE_cc1101.getLqi() & 0x7F;
      byte length = ELECHOUSE_cc1101.ReceiveData(buffer);
      buffer[length] = '\0';
      Serial.print(F("Received: "));
      Serial.print((char *)buffer);
      Serial.print(F("   RSSI "));
      Serial.print(rssi);
      Serial.print(F(" dBm  LQI "));
      Serial.println(lqi);
    } else {
      Serial.println(F("Packet with CRC error discarded"));
    }
  }
}

Wait for a Packet

The function CheckReceiveFlag() puts the radio into receive mode when needed and reads GDO0. When the pin is high, a sync word has been received. The function then waits until the pin goes low at the end of the packet and returns 1.

Check the CRC and Read the Values

  1. CheckCRC() reads the CRC flag of the chip. If the CRC is wrong, the packet is removed and the sketch prints a message.
  2. getRssi() reads the signal strength and converts it to dBm.
  3. getLqi() reads the link quality. The sketch keeps the lower seven bits, because the highest bit of this register is the CRC flag.
  4. ReceiveData(buffer) copies the payload into the buffer and returns its length. It also starts the receiver again.

The sketch reads RSSI and LQI before it reads the data, because the last step restarts the receiver. It then adds a zero after the last character, so that the buffer can be printed as text. The buffer has 61 bytes, which is enough for the longest payload that fits into the chip's buffer together with the length and status bytes.

Calculate the Link Budget

A link budget tells us whether the signal at the receiver is strong enough. The model uses three steps, and we can repeat them with a calculator.

Step 1: Calculate the Path Loss

The model uses the free-space loss for the first metre, and then a loss that grows with 30 dB for every ten-fold increase in distance:

Path loss in dB = 20 × log10(4 × pi × f / c) + 30 × log10(distance in metres)

Here, f is the frequency in Hz and c is the speed of light. At 433.92 MHz, the first part is 25.2 dB. For 100 m, the second part is 30 × 2 = 60 dB. The path loss at 100 m is therefore 85.2 dB.

Step 2: Calculate the RSSI

RSSI = output power - path loss

  • 100 m: +10 - 85.2 = -75.2 dBm, which is displayed as -75 dBm.
  • 250 m: the path loss is 25.2 + 71.9 = 97.1 dB, so the RSSI is -87.1 dBm.
  • 500 m: the path loss is 25.2 + 81.0 = 106.2 dB, so the RSSI is -96.2 dBm.
  • 1 km: the path loss is 25.2 + 90 = 115.2 dB, so the RSSI is -105.2 dBm.

Step 3: Compare with the Sensitivity

A slower data rate can be received at a weaker signal. The model uses four sensitivity values based on the datasheet and interpolates between them.

Sensitivity values used by the model for 2-FSK and GFSK
Data rateSensitivity
1.2 kBaud-112 dBm
38.4 kBaud-104 dBm
100 kBaud, interpolated-99.4 dBm
250 kBaud-95 dBm
500 kBaud-86 dBm

For our example, the panel shows that 100 kBaud needs -99 dBm. At 500 m, the RSSI of -96.2 dBm is stronger than -99.4 dBm, so the packet is received. At 1 km, -105.2 dBm is weaker, so the packet is counted as too weak. For ASK and OOK modulation, the model uses values that are 4 dB worse.

Calculate the LQI

The difference between the RSSI and the sensitivity is called the margin. The model calculates LQI = 60 - 2 × margin and limits the result to the range 0 to 127.

  • 100 m: the margin is -75.2 + 99.4 = 24.2 dB, so the LQI is 60 - 48.4 = 11.6, which is rounded to 12.
  • 250 m: the margin is 12.3 dB, so the LQI is 60 - 24.5 = 35.5, which is displayed as 35.
  • 500 m: the margin is 3.2 dB, so the LQI is 60 - 6.5 = 53.5, which is displayed as 54.

This formula belongs to our model. It gives a value that becomes higher when the link becomes worse, as the real register does, but a real chip measures its LQI from the received signal.

Convert the RSSI Register to dBm

The chip stores the RSSI as one byte. The datasheet gives the conversion, and the driver's getRssi() function uses it with an offset of 74:

  • If the value is 128 or more: RSSI in dBm = (value - 256) / 2 - 74
  • Otherwise: RSSI in dBm = value / 2 - 74

At 250 m, the register holds 230. The result is (230 - 256) / 2 - 74 = -13 - 74 = -87 dBm. This is the value printed on the terminal.

Calculate the Frequency Setting

The chip uses a 26 MHz crystal and stores the frequency as a 24-bit number. One step is 26 MHz / 65536 = 396.7 Hz. For 433.92 MHz, the driver calculates 433.92 × 65536 / 26 = 1,093,745 and writes this number into three registers. The result is within a few hundred hertz of the requested frequency, and the panel shows 433.920 MHz.

Calculate the Air Time of One Message

In packet mode, the driver selects a data rate of 99,976 Baud, which the panel shows as 100.0 kBaud. One bit lasts about 10 microseconds. The message "Hello TEP #0" has 12 characters.

Packet length for a 12-character message
Packet fieldSizeBits
Preamble2 bytes16
Sync word2 bytes16
Length byte1 byte8
Payload12 bytes96
CRC2 bytes16
Total19 bytes152

The packet needs 152 bits, which take about 1.52 ms on the air. Before the packet starts, the model adds about 0.9 ms for the calibration and settling of the radio. The complete transmission therefore takes about 2.4 ms.

Experiments to Try in Proteus

Change one thing at a time and predict the result before you press Run. The results below follow from the model's rules. The supplied project and the distance buttons were tested in Proteus. The package notes list the other cases as tests of the model on a PC, so check them in your own simulation.

Suggested experiments and their expected results
ChangeExpected result
Click 1 km on either panel.The receiver prints nothing, and its TOO WEAK counter increases.
Add setDRate(1.2) after setCCMode(1) in both sketches.The link works at 1 km, because the sensitivity is now -112 dBm.
Add setPA(0) to the transmitter.Every RSSI value is 10 dB lower, and 500 m becomes too weak.
Use setMHZ(434.92) in one sketch only.Nothing is received, because the frequencies do not match.
Use setCrc(0) in the transmitter only.The receiver prints Packet with CRC error discarded.
Change delay(2000) to delay(500) in the transmitter.About two messages are sent each second.

After each experiment, compare both panels before reading the code again. A difference in frequency, modulation, data rate or sync word is usually visible there.

Compile and Load Your Own Arduino Changes

  1. Open Arduino Code/CC1101_Transmitter/CC1101_Transmitter.ino or the receiver sketch in Arduino IDE.
  2. Install the SmartRC-CC1101-Driver-Lib library. For the same version as the example, copy Arduino Code/libraries/SmartRC-CC1101-Driver-Lib into your sketchbook's libraries folder.
  3. Select Arduino Uno as the board.
  4. Compile the sketch and use the Export Compiled Binary command.
  5. Select the new application HEX in the Program File property of the correct Arduino.
  6. Restart the simulation.

Remember that the project has two programs. If you change a radio setting, rebuild both sketches and load each HEX into its own board. The package also contains a rebuild script and the AVR core source archive.

Common Problems and Their Solutions

Troubleshooting the CC1101 Proteus simulation
ProblemWhat to check
CC1101TEP is missing from Pick Devices.Check that TEPCC1101.LIB is in the active library folder and restart Proteus.
The module is placed, but its model cannot load.Check TEPCC1101.DLL in MODELS and beside the project.
The terminal prints CC1101 not responding.Check SCK, MISO, MOSI and CSN, then VCC and GND. Check that Init() is called before getCC1101().
Sending is slow and nothing arrives.Check the GDO0 wire to D2 and that the sketch uses setCCMode(1).
No packets are received.Compare frequency, modulation, data rate and sync word on both panels. Check that the receiver shows RX.
The TOO WEAK counter increases.Select a shorter distance, raise the power or lower the data rate.
The panel shows OUT OF BAND.Use a frequency inside the bands of the CC1101.
A terminal is blank or unreadable.Check the Program File, the 16 MHz clock, D1/TX to RXD and 9600 baud.

If a problem remains, return to the unmodified project and change one thing at a time. When you ask for help, include both terminal windows and a screenshot of both control panels.

Practical Review and Model Limitations

This library is useful for learning how a sub-1 GHz link is configured and how distance, power and data rate work together. The two panels show the settings of both radios side by side, and the distance buttons turn the link budget into an experiment that we can repeat.

What the Model Supports

  • The configuration registers, command strobes, status registers and 64-byte buffers of the chip.
  • The packet engine with preamble, sync word, length byte, address check and CRC.
  • RSSI and LQI values, which are also added to each received packet.
  • A range calculation from output power, frequency, distance and data rate.
  • The asynchronous serial mode, which simple 433 MHz remote controls use.

What the Model Does Not Simulate

  • Real antennas, terrain, reflections and interference.
  • Collisions between transmitters that send at the same moment.
  • Wake-on-radio and the clock outputs of the GDO pins.
  • Frequency errors between two crystals.
  • The supply voltage and the current of the module.

Treat the range values as teaching examples. The range of real hardware depends on the antenna, its height, the surroundings and the local rules for the frequency band, so it must be measured with the actual devices.

More Proteus Libraries of This Series

This library belongs to a series of wireless and RFID libraries for Proteus. Every library has its own control panel and its own tutorial:

Frequently Asked Questions

Do I Need Two Arduino Boards in the Simulation?

Yes, for a complete link. One board runs the transmitter sketch and the other runs the receiver sketch.

Why Does the Transmitter Print Sent When Nothing Is Received?

The sketch sends a packet without asking for an answer. The transmitter only knows that the packet has left the radio. If you need a confirmation, the receiver must send a reply packet, and the transmitter must wait for it.

Is a Lower LQI Better or Worse?

For the CC1101, a lower LQI means a better link. In our example, the LQI is 12 at 100 m and 54 at 500 m.

Can I Use 868 MHz or 915 MHz?

Yes. Use setMHZ() with the same frequency in both sketches. The model accepts the bands of the CC1101 and shows OUT OF BAND for other frequencies. The path loss is higher at a higher frequency, so the RSSI values change.

Can I Place More Than Two Radios?

Yes. Every CC1101TEP in the design shares the same band. The supplied project demonstrates two radios, and the model does not simulate collisions between simultaneous transmissions.

Do I Need to Connect GDO2?

Not for the supplied sketches. They use GDO0 only. GDO2 is wired to D9 in the project, so that it is ready for your own experiments.

Do I Need Arduino IDE to Run the Supplied Circuit?

No. Both compiled HEX files are included. You need Arduino IDE, or the documented build tools, only when you change a sketch.

That completes our CC1101 Proteus Library tutorial. Start with the supplied project, watch both panels and then change the distance step by step. Once the RSSI values make sense, change the data rate or the power and compare the results with your own calculation. Share your questions and simulation results in the comments below.