Demo of how to use CC1200 radios to send data.

Dependencies:   CC1200

CC1200 Example Project

This project shows how to use my Mbed OS CC1200 driver to send messages over the air. It connects to the radio chips, configures them (using a couple of different configurations converted from SmartRF), and sends a message from a transmitter chip to a receiver.

Hardware Setup

This program assumes that two CC1200s are connected to your processor's SPI bus. The CC1200s' circuit boards must be configured for the 900MHz band. Also, if you are connecting the two radios together directly with a cable, make sure to include an attenuator (-20dB should work) to prevent overloading the radios' RX inputs.

I used a custom circuit board for my testing, but you should also be able to use an Mbed board connected to two CC1200 eval kits to run the program.

Note: License free transmission on the 900MHz band is only legal in Region 2 countries (North and South America). Make sure to follow all local regulations covering radio transmissions!

Committer:
MultipleMonomials
Date:
Mon Aug 10 01:57:54 2020 -0700
Revision:
0:ea2678a73bde
Child:
1:7e7812669c9c
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MultipleMonomials 0:ea2678a73bde 1 //
MultipleMonomials 0:ea2678a73bde 2 // Test suite for the CC1200 radio driver.
MultipleMonomials 0:ea2678a73bde 3 // Provides a menu to configure radio options, and
MultipleMonomials 0:ea2678a73bde 4 // attempts to send and receive a signal using two radios connected
MultipleMonomials 0:ea2678a73bde 5 // to the processor.
MultipleMonomials 0:ea2678a73bde 6 //
MultipleMonomials 0:ea2678a73bde 7
MultipleMonomials 0:ea2678a73bde 8 #include <mbed.h>
MultipleMonomials 0:ea2678a73bde 9 #include <SerialStream.h>
MultipleMonomials 0:ea2678a73bde 10
MultipleMonomials 0:ea2678a73bde 11 #include <CC1200.h>
MultipleMonomials 0:ea2678a73bde 12 #include <cinttypes>
MultipleMonomials 0:ea2678a73bde 13
MultipleMonomials 0:ea2678a73bde 14 // Pin definitions
MultipleMonomials 0:ea2678a73bde 15 // change these to match your board setup
MultipleMonomials 0:ea2678a73bde 16 #define PIN_SPI_MOSI P0_9
MultipleMonomials 0:ea2678a73bde 17 #define PIN_SPI_MISO P0_8
MultipleMonomials 0:ea2678a73bde 18 #define PIN_SPI_SCLK P0_7
MultipleMonomials 0:ea2678a73bde 19
MultipleMonomials 0:ea2678a73bde 20 #define PIN_TX_CS P0_6
MultipleMonomials 0:ea2678a73bde 21 #define PIN_TX_RST P0_29
MultipleMonomials 0:ea2678a73bde 22
MultipleMonomials 0:ea2678a73bde 23 #define PIN_RX_CS P0_4
MultipleMonomials 0:ea2678a73bde 24 #define PIN_RX_RST P0_30
MultipleMonomials 0:ea2678a73bde 25
MultipleMonomials 0:ea2678a73bde 26 BufferedSerial serial(USBTX, USBRX, 115200);
MultipleMonomials 0:ea2678a73bde 27 SerialStream<BufferedSerial> pc(serial);
MultipleMonomials 0:ea2678a73bde 28
MultipleMonomials 0:ea2678a73bde 29 CC1200 txRadio(PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCLK, PIN_TX_CS, PIN_TX_RST, &pc);
MultipleMonomials 0:ea2678a73bde 30 CC1200 rxRadio(PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCLK, PIN_RX_CS, PIN_RX_RST, &pc);
MultipleMonomials 0:ea2678a73bde 31
MultipleMonomials 0:ea2678a73bde 32 void checkExistance()
MultipleMonomials 0:ea2678a73bde 33 {
MultipleMonomials 0:ea2678a73bde 34 pc.printf("Checking TX radio.....\n");
MultipleMonomials 0:ea2678a73bde 35 bool txSuccess = txRadio.begin();
MultipleMonomials 0:ea2678a73bde 36 pc.printf("TX radio initialized: %s\n", txSuccess ? "true" : "false");
MultipleMonomials 0:ea2678a73bde 37
MultipleMonomials 0:ea2678a73bde 38 pc.printf("Checking RX radio.....\n");
MultipleMonomials 0:ea2678a73bde 39 bool rxSuccess = rxRadio.begin();
MultipleMonomials 0:ea2678a73bde 40 pc.printf("RX radio initialized: %s\n", rxSuccess ? "true" : "false");
MultipleMonomials 0:ea2678a73bde 41 }
MultipleMonomials 0:ea2678a73bde 42
MultipleMonomials 0:ea2678a73bde 43 void checkSignalTransmit()
MultipleMonomials 0:ea2678a73bde 44 {
MultipleMonomials 0:ea2678a73bde 45 pc.printf("Initializing CC1200s.....\n");
MultipleMonomials 0:ea2678a73bde 46 txRadio.begin();
MultipleMonomials 0:ea2678a73bde 47 rxRadio.begin();
MultipleMonomials 0:ea2678a73bde 48
MultipleMonomials 0:ea2678a73bde 49 pc.printf("Configuring RF settings.....\n");
MultipleMonomials 0:ea2678a73bde 50
MultipleMonomials 0:ea2678a73bde 51 int config=-1;
MultipleMonomials 0:ea2678a73bde 52 //MENU. ADD AN OPTION FOR EACH TEST.
MultipleMonomials 0:ea2678a73bde 53 pc.printf("Select a config: \n");
MultipleMonomials 0:ea2678a73bde 54 // This is similar to the SmartRF "100ksps ARIB Standard" configuration, except it doesn't use zero-if
MultipleMonomials 0:ea2678a73bde 55 pc.printf("1. 915MHz 100ksps 2-GFSK DEV=50kHz CHF=208kHz\n");
MultipleMonomials 0:ea2678a73bde 56 // This should be identical to the SmartRF "500ksps 4-GFSK Max Throughput ARIB Standard" configuration
MultipleMonomials 0:ea2678a73bde 57 pc.printf("2. 915MHz 500ksps 4-GFSK DEV=400kHz CHF=1666kHz Zero-IF\n");
MultipleMonomials 0:ea2678a73bde 58 pc.printf("3. 915MHz 38.4ksps 2-GFSK DEV=20kHz CHF=833kHz\n");
MultipleMonomials 0:ea2678a73bde 59
MultipleMonomials 0:ea2678a73bde 60 pc.scanf("%d", &config);
MultipleMonomials 0:ea2678a73bde 61 printf("Running test with config %d:\n\n", config);
MultipleMonomials 0:ea2678a73bde 62
MultipleMonomials 0:ea2678a73bde 63 CC1200::Band band = CC1200::Band::BAND_820_960MHz;
MultipleMonomials 0:ea2678a73bde 64 float frequency = 915e6;
MultipleMonomials 0:ea2678a73bde 65 const float txPower = 0;
MultipleMonomials 0:ea2678a73bde 66 float fskDeviation;
MultipleMonomials 0:ea2678a73bde 67 float symbolRate;
MultipleMonomials 0:ea2678a73bde 68 float rxFilterBW;
MultipleMonomials 0:ea2678a73bde 69 CC1200::ModFormat modFormat;
MultipleMonomials 0:ea2678a73bde 70 uint8_t ifCfg = 0b101; // max IF
MultipleMonomials 0:ea2678a73bde 71 bool imageCompEnabled = true;
MultipleMonomials 0:ea2678a73bde 72 bool dcOffsetCorrEnabled = true;
MultipleMonomials 0:ea2678a73bde 73 uint8_t agcRefLevel;
MultipleMonomials 0:ea2678a73bde 74
MultipleMonomials 0:ea2678a73bde 75 uint8_t dcFiltSettingCfg = 1; // default chip setting
MultipleMonomials 0:ea2678a73bde 76 uint8_t dcFiltCutoffCfg = 4; // default chip setting
MultipleMonomials 0:ea2678a73bde 77
MultipleMonomials 0:ea2678a73bde 78 CC1200::SyncMode syncMode = CC1200::SyncMode::SYNC_32_BITS;
MultipleMonomials 0:ea2678a73bde 79 uint32_t syncWord = 0x930B51DE; // default sync word
MultipleMonomials 0:ea2678a73bde 80 uint8_t syncThreshold = 8; // TI seems to recommend this threshold for most configs above 100ksps
MultipleMonomials 0:ea2678a73bde 81
MultipleMonomials 0:ea2678a73bde 82 uint8_t preableLengthCfg = 5; // default chip setting
MultipleMonomials 0:ea2678a73bde 83 uint8_t preambleFormatCfg = 0; // default chip setting
MultipleMonomials 0:ea2678a73bde 84
MultipleMonomials 0:ea2678a73bde 85 if(config == 1)
MultipleMonomials 0:ea2678a73bde 86 {
MultipleMonomials 0:ea2678a73bde 87 fskDeviation = 49896;
MultipleMonomials 0:ea2678a73bde 88 symbolRate = 100000;
MultipleMonomials 0:ea2678a73bde 89 rxFilterBW = 208300;
MultipleMonomials 0:ea2678a73bde 90 modFormat = CC1200::ModFormat::GFSK_2;
MultipleMonomials 0:ea2678a73bde 91 agcRefLevel = 0x2A;
MultipleMonomials 0:ea2678a73bde 92 }
MultipleMonomials 0:ea2678a73bde 93 else if(config == 2)
MultipleMonomials 0:ea2678a73bde 94 {
MultipleMonomials 0:ea2678a73bde 95 // SmartRF "500ksps 4-GFSK ARIB standard" config
MultipleMonomials 0:ea2678a73bde 96 fskDeviation = 399169;
MultipleMonomials 0:ea2678a73bde 97 symbolRate = 500000;
MultipleMonomials 0:ea2678a73bde 98 rxFilterBW = 1666700;
MultipleMonomials 0:ea2678a73bde 99 ifCfg = 0;
MultipleMonomials 0:ea2678a73bde 100 imageCompEnabled = false;
MultipleMonomials 0:ea2678a73bde 101 dcOffsetCorrEnabled = true;
MultipleMonomials 0:ea2678a73bde 102 modFormat = CC1200::ModFormat::GFSK_4;
MultipleMonomials 0:ea2678a73bde 103 agcRefLevel = 0x2F;
MultipleMonomials 0:ea2678a73bde 104 }
MultipleMonomials 0:ea2678a73bde 105 else if(config == 3)
MultipleMonomials 0:ea2678a73bde 106 {
MultipleMonomials 0:ea2678a73bde 107 fskDeviation = 19989;
MultipleMonomials 0:ea2678a73bde 108 symbolRate = 38400;
MultipleMonomials 0:ea2678a73bde 109 rxFilterBW = 104200;
MultipleMonomials 0:ea2678a73bde 110 modFormat = CC1200::ModFormat::GFSK_2;
MultipleMonomials 0:ea2678a73bde 111 agcRefLevel = 0x27;
MultipleMonomials 0:ea2678a73bde 112 }
MultipleMonomials 0:ea2678a73bde 113 else
MultipleMonomials 0:ea2678a73bde 114 {
MultipleMonomials 0:ea2678a73bde 115 pc.printf("Invalid config number!");
MultipleMonomials 0:ea2678a73bde 116 return;
MultipleMonomials 0:ea2678a73bde 117 }
MultipleMonomials 0:ea2678a73bde 118
MultipleMonomials 0:ea2678a73bde 119 for(CC1200 & radio : {std::ref(txRadio), std::ref(rxRadio)})
MultipleMonomials 0:ea2678a73bde 120 {
MultipleMonomials 0:ea2678a73bde 121
MultipleMonomials 0:ea2678a73bde 122 radio.configureFIFOMode();
MultipleMonomials 0:ea2678a73bde 123 radio.setModulationFormat(modFormat);
MultipleMonomials 0:ea2678a73bde 124 radio.setFSKDeviation(fskDeviation);
MultipleMonomials 0:ea2678a73bde 125 radio.setSymbolRate(symbolRate);
MultipleMonomials 0:ea2678a73bde 126 radio.setOutputPower(txPower);
MultipleMonomials 0:ea2678a73bde 127 radio.setRadioFrequency(band, frequency);
MultipleMonomials 0:ea2678a73bde 128 radio.setIFMixCFG(ifCfg);
MultipleMonomials 0:ea2678a73bde 129 radio.configureDCFilter(dcOffsetCorrEnabled, dcFiltSettingCfg, dcFiltCutoffCfg);
MultipleMonomials 0:ea2678a73bde 130 radio.setIQMismatchCompensationEnabled(imageCompEnabled);
MultipleMonomials 0:ea2678a73bde 131 radio.setRXFilterBandwidth(rxFilterBW);
MultipleMonomials 0:ea2678a73bde 132 radio.configureSyncWord(syncWord, syncMode, syncThreshold);
MultipleMonomials 0:ea2678a73bde 133 radio.configurePreamble(preableLengthCfg, preambleFormatCfg);
MultipleMonomials 0:ea2678a73bde 134
MultipleMonomials 0:ea2678a73bde 135 // AGC configuration (straight from SmartRF)
MultipleMonomials 0:ea2678a73bde 136 radio.setAGCReferenceLevel(agcRefLevel);
MultipleMonomials 0:ea2678a73bde 137 radio.setAGCSyncBehavior(CC1200::SyncBehavior::FREEZE_NONE);
MultipleMonomials 0:ea2678a73bde 138 if(ifCfg == 0)
MultipleMonomials 0:ea2678a73bde 139 {
MultipleMonomials 0:ea2678a73bde 140 radio.setAGCGainTable(CC1200::GainTable::ZERO_IF, 11, 0);
MultipleMonomials 0:ea2678a73bde 141 }
MultipleMonomials 0:ea2678a73bde 142 else
MultipleMonomials 0:ea2678a73bde 143 {
MultipleMonomials 0:ea2678a73bde 144 // enable all AGC steps for NORMAL mode
MultipleMonomials 0:ea2678a73bde 145 radio.setAGCGainTable(CC1200::GainTable::NORMAL, 17, 0);
MultipleMonomials 0:ea2678a73bde 146 }
MultipleMonomials 0:ea2678a73bde 147 radio.setAGCHysteresis(0b10);
MultipleMonomials 0:ea2678a73bde 148 radio.setAGCSlewRate(0);
MultipleMonomials 0:ea2678a73bde 149 }
MultipleMonomials 0:ea2678a73bde 150
MultipleMonomials 0:ea2678a73bde 151 // configure on-transmit actions
MultipleMonomials 0:ea2678a73bde 152 txRadio.setOnTransmitState(CC1200::State::TX);
MultipleMonomials 0:ea2678a73bde 153 rxRadio.setOnReceiveState(CC1200::State::RX, CC1200::State::RX);
MultipleMonomials 0:ea2678a73bde 154
MultipleMonomials 0:ea2678a73bde 155 pc.printf("Starting transmission.....\n");
MultipleMonomials 0:ea2678a73bde 156
MultipleMonomials 0:ea2678a73bde 157 txRadio.startTX();
MultipleMonomials 0:ea2678a73bde 158 rxRadio.startRX();
MultipleMonomials 0:ea2678a73bde 159
MultipleMonomials 0:ea2678a73bde 160 const char message[] = "Hello world!";
MultipleMonomials 0:ea2678a73bde 161 char receiveBuffer[sizeof(message) + 1];
MultipleMonomials 0:ea2678a73bde 162
MultipleMonomials 0:ea2678a73bde 163 // make sure there's a null terminator even if data is corrupted
MultipleMonomials 0:ea2678a73bde 164 receiveBuffer[sizeof(receiveBuffer) - 1] = '\0';
MultipleMonomials 0:ea2678a73bde 165
MultipleMonomials 0:ea2678a73bde 166 while(true)
MultipleMonomials 0:ea2678a73bde 167 {
MultipleMonomials 0:ea2678a73bde 168 ThisThread::sleep_for(1s);
MultipleMonomials 0:ea2678a73bde 169
MultipleMonomials 0:ea2678a73bde 170 pc.printf("\n---------------------------------\n");
MultipleMonomials 0:ea2678a73bde 171
MultipleMonomials 0:ea2678a73bde 172 pc.printf("<<SENDING: %s\n", message);
MultipleMonomials 0:ea2678a73bde 173 txRadio.enqueuePacket(message, sizeof(message));
MultipleMonomials 0:ea2678a73bde 174
MultipleMonomials 0:ea2678a73bde 175
MultipleMonomials 0:ea2678a73bde 176 // update TX radio
MultipleMonomials 0:ea2678a73bde 177 pc.printf("TX radio: state = 0x%" PRIx8 ", TX FIFO len = %zu, FS lock = 0x%u\n",
MultipleMonomials 0:ea2678a73bde 178 static_cast<uint8_t>(txRadio.getState()), txRadio.getTXFIFOLen(), txRadio.readRegister(CC1200::ExtRegister::FSCAL_CTRL) & 1);
MultipleMonomials 0:ea2678a73bde 179
MultipleMonomials 0:ea2678a73bde 180 // wait a while for the packet to come in.
MultipleMonomials 0:ea2678a73bde 181 ThisThread::sleep_for(10ms);
MultipleMonomials 0:ea2678a73bde 182
MultipleMonomials 0:ea2678a73bde 183 // wait the time we expect the message to take, with a safety factor of 2
MultipleMonomials 0:ea2678a73bde 184 auto timeoutTime = std::chrono::microseconds(static_cast<int64_t>((1/symbolRate) * 1e-6f * sizeof(message) * 2));
MultipleMonomials 0:ea2678a73bde 185
MultipleMonomials 0:ea2678a73bde 186 Timer packetReceiveTimeout;
MultipleMonomials 0:ea2678a73bde 187 packetReceiveTimeout.start();
MultipleMonomials 0:ea2678a73bde 188 bool hasPacket;
MultipleMonomials 0:ea2678a73bde 189 do
MultipleMonomials 0:ea2678a73bde 190 {
MultipleMonomials 0:ea2678a73bde 191 hasPacket = rxRadio.hasReceivedPacket();
MultipleMonomials 0:ea2678a73bde 192 }
MultipleMonomials 0:ea2678a73bde 193 while(packetReceiveTimeout.elapsed_time() < timeoutTime && !hasPacket);
MultipleMonomials 0:ea2678a73bde 194
MultipleMonomials 0:ea2678a73bde 195 pc.printf("RX radio: state = 0x%" PRIx8 ", RX FIFO len = %zu\n",
MultipleMonomials 0:ea2678a73bde 196 static_cast<uint8_t>(rxRadio.getState()), rxRadio.getRXFIFOLen());
MultipleMonomials 0:ea2678a73bde 197 if(hasPacket)
MultipleMonomials 0:ea2678a73bde 198 {
MultipleMonomials 0:ea2678a73bde 199 rxRadio.receivePacket(receiveBuffer, sizeof(message));
MultipleMonomials 0:ea2678a73bde 200 pc.printf(">>RECEIVED: %s\n", receiveBuffer);
MultipleMonomials 0:ea2678a73bde 201 }
MultipleMonomials 0:ea2678a73bde 202 else
MultipleMonomials 0:ea2678a73bde 203 {
MultipleMonomials 0:ea2678a73bde 204 pc.printf(">>No packet received!\n");
MultipleMonomials 0:ea2678a73bde 205 }
MultipleMonomials 0:ea2678a73bde 206 }
MultipleMonomials 0:ea2678a73bde 207 }
MultipleMonomials 0:ea2678a73bde 208
MultipleMonomials 0:ea2678a73bde 209
MultipleMonomials 0:ea2678a73bde 210 int main()
MultipleMonomials 0:ea2678a73bde 211 {
MultipleMonomials 0:ea2678a73bde 212 pc.printf("\nCC1200 Radio Test Suite:\n");
MultipleMonomials 0:ea2678a73bde 213
MultipleMonomials 0:ea2678a73bde 214 while(1){
MultipleMonomials 0:ea2678a73bde 215 int test=-1;
MultipleMonomials 0:ea2678a73bde 216 //MENU. ADD AN OPTION FOR EACH TEST.
MultipleMonomials 0:ea2678a73bde 217 pc.printf("Select a test: \n");
MultipleMonomials 0:ea2678a73bde 218 pc.printf("1. Exit Test Suite\n");
MultipleMonomials 0:ea2678a73bde 219 pc.printf("2. Check Existence\n");
MultipleMonomials 0:ea2678a73bde 220 pc.printf("3. Check Transmitting Signal\n");
MultipleMonomials 0:ea2678a73bde 221
MultipleMonomials 0:ea2678a73bde 222 pc.scanf("%d", &test);
MultipleMonomials 0:ea2678a73bde 223 printf("Running test %d:\n\n", test);
MultipleMonomials 0:ea2678a73bde 224 //SWITCH. ADD A CASE FOR EACH TEST.
MultipleMonomials 0:ea2678a73bde 225 switch(test) {
MultipleMonomials 0:ea2678a73bde 226 case 1: pc.printf("Exiting test suite.\n"); return 0;
MultipleMonomials 0:ea2678a73bde 227 case 2: checkExistance(); break;
MultipleMonomials 0:ea2678a73bde 228 case 3: checkSignalTransmit(); break;
MultipleMonomials 0:ea2678a73bde 229 default: pc.printf("Invalid test number. Please run again.\n"); continue;
MultipleMonomials 0:ea2678a73bde 230 }
MultipleMonomials 0:ea2678a73bde 231 pc.printf("done.\r\n");
MultipleMonomials 0:ea2678a73bde 232 }
MultipleMonomials 0:ea2678a73bde 233
MultipleMonomials 0:ea2678a73bde 234 return 0;
MultipleMonomials 0:ea2678a73bde 235
MultipleMonomials 0:ea2678a73bde 236 }