|
1 | 1 | # SmartCC1101
|
2 | 2 | This driver library offers a simple access to data transfer using the cc1101 module. It gives access to many configuration options without need to use RFStudio.
|
| 3 | +## Basic Function |
| 4 | +This library was mainly implemented to efficiently send data from decentral battery powered sensors to a central hub. Howwever it may as well be used for bi-directional communication between several nodes. |
| 5 | +The maximum amount of data which can be be sent in a single transfer is limited to the size of the internal buffer of the CC1101, leading to a possible payload of 61 bytes. |
| 6 | +The code was designed to have a small memory footprint and runs fine on an Arduino Pro Mini (ATMega328p). However, for a single caclulation, floating point math is needed, excluding platforms like ATTiny. In a future version, I might re-implement the offending algortihm to integer math tpo remove the restriction. Besides that, no specific platform-dependant code is used and the library should behave well everywhere else (although it is only explicitely testetd on Arduino Pro Mini and ESP8266). |
| 7 | +## Wiring |
| 8 | +I promise I will add some drawings later on, but for now, I'll stick with the pin numbers - which are standard pins for SPI connections on the boards mentioneed. |
| 9 | + |
| 10 | +### CC1101 |
| 11 | +If the module lays with the antenna connectors to the top, on the lower connection pins are from left to right: |
| 12 | ++ VCC |
| 13 | ++ GND |
| 14 | ++ COPI (may also be called MOSI) |
| 15 | ++ SCK (or SCLK) |
| 16 | ++ CIPO (or MISO) |
| 17 | ++ GDO2 (unused) |
| 18 | ++ GDO0 (unused) |
| 19 | ++ CS (or CSN) |
| 20 | + |
| 21 | +The modules usually support voltages from 1.8V to 3.6V, so please use a level converter when connecting to a 5V CPU board. Also, be careful when soldering the connections, I have grilled several CC1101 modules... |
| 22 | + |
| 23 | +### Processor boards |
| 24 | +**Arduino Pro Mini (ATMega328p)** |
| 25 | ++ SCK 13 |
| 26 | ++ CIPO 12 |
| 27 | ++ COPI 11 |
| 28 | ++ CS 10 |
| 29 | + |
| 30 | +**ESP8266** |
| 31 | ++ SCK 14 |
| 32 | ++ CIPO 12 |
| 33 | ++ COPI 13 |
| 34 | ++ CS 15 |
| 35 | + |
| 36 | +**ESP32** |
| 37 | ++ SCK 18 |
| 38 | ++ CIPO 19 |
| 39 | ++ COPI 23 |
| 40 | ++ CS 5 |
| 41 | + |
| 42 | +**Arduino** |
| 43 | ++ SCK 13 |
| 44 | ++ CIPO 12 |
| 45 | ++ COPI 11 |
| 46 | ++ CS 10 |
| 47 | + |
| 48 | +For ESP32 and (to a limited extent) ESP8266 support custom SPI pinout. These differnt configurations need to be hardcoded in the library though. Later versions may support user-specified SPI configurations. |
| 49 | + |
| 50 | +## Programming |
| 51 | +The following code implements a simple sender and is available in the examples folder. |
| 52 | +**Please note:** Nearly all settings are redundant and just replicate the default values (see comments). They are shown for illustration. Settings where sender and receiver need to match are marked in the comments. |
| 53 | + |
| 54 | +The settings are not limited to the `setup()` and may be changed anytime in the `loop()` if needed. |
| 55 | + |
| 56 | +```C++ |
| 57 | + |
| 58 | +#include <SmartCC1101.h> |
| 59 | + |
| 60 | +void setup() { |
| 61 | + Serial.begin(115200); |
| 62 | + |
| 63 | + Smartcc1101.init(); // must be called first to initialize the CC1101 |
| 64 | + |
| 65 | + if (Smartcc1101.getCC1101()) { // Check the CC1101 SPI connection. |
| 66 | + Serial.println(F("[I] CC1101 connected.")); |
| 67 | + } else { |
| 68 | + Serial.println(F("[E] *** CC1101 connection Error ***")); |
| 69 | + delay(20000); |
| 70 | + } |
| 71 | + |
| 72 | + // Most of the settings repeat standard settings and are here for illustration |
| 73 | + Smartcc1101.setDCFilterOff(false); // Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud. The recommended IF frequency changes when the DC blocking is disabled. true = Disable (current optimized), false = Enable (better sensitivity). |
| 74 | + Smartcc1101.setModulation(SmartCC1101::mod_2FSK); // set modulation mode. Possible values: mod_2FSK (default), mod_GFSK, mod_ASKOOK, mod_4FSK, mod_MSK |
| 75 | + Smartcc1101.setCarrierFrequency(868350000); // Set tranmsision frequency in Hz. Default = 868.35 MHz). The cc1101 can use 300-348 MHZ, 387-464MHZ and 779-928MHZ. More info in the datasheet. |
| 76 | + Smartcc1101.setPA(12); // Set TXPower. The following settings are possible depending on the frequency band. (-30 -20 -15 -10 -6 0 5 7 10 11 12) Default is max! |
| 77 | + Smartcc1101.setDeviation(47608); // Set the Frequency deviation in Hz. Value from 1586 to 380850. Default is 47607 kHz. Note: the algorithm rounds down. On exact interval limits, the next lower value might be taken (that's why here 47608 is used) |
| 78 | + Smartcc1101.setRXBandWitdth(SmartCC1101::bw_812kHz); // Set the Receive Bandwidth in kHz. Possible values: bw_58kHz = 58kHz, bw_68kHz, bw_81kHz, bw_102kHz,bw_116kHz, bw_135kHz, bw_162kHz, bw_203kHz (default), bw_232kHz, bw_270kHz, bw_325kHz, bw_406kHz, bw_464kHz, bw_541kHz, bw_650kHz, bw_812kHz = 812kHz |
| 79 | + Smartcc1101.setSymbolRate(100000); // Set the Data Rate in Baud. Value from 20 to 1621830 Default is 115051 Baud |
| 80 | + Smartcc1101.setSyncWord(0xD3, 0x91); // Set sync word. Must match in sender and receiver. (Syncword high, Syncword low). Values given are default values |
| 81 | + Smartcc1101.setSyncMode(SmartCC1101::sync_1616); // Combined sync-word qualifier mode. sync_NONE = No preamble/sync. sync_1516 = 15/16 sync word bits detected. sync_1616 = 16/16 sync word bits detected (default). sync_3032 = 30/32 sync word bits detected (sync word sent twice). |
| 82 | + // sync_NONECS = No preamble/sync, carrier-sense above threshold. sync_1516CS = 15/16 + carrier-sense above threshold. sync_1516CS = 15/16 + carrier-sense above threshold. sync_1616CS = 16/16 + carrier-sense above threshold. sync_3032CS = 30/32 (sync word sent twice). + carrier-sense above threshold. |
| 83 | + Smartcc1101.setPRE(SmartCC1101::pre_4); // Sets the minimum number of preamble bytes to be transmitted. Possible values: pre_2 : 2, pre_3 : 3, pre_4 : 4 (default), pre_6 : 6, pre_8 : 8, pre_12 : 12, pre_16 : 16, pre_24 : 24 |
| 84 | + Smartcc1101.setPQT(0); // Preamble quality estimator threshold. 0 is the derfault. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted. |
| 85 | + Smartcc1101.setAdrChk(SmartCC1101::adc_NO); // Controls address check configuration of received packages. adc_NO = No address check (default). adc_YESNOBC = Address check, no broadcast. adc_YES0BC = Address check and 0 (0x00) broadcast. adc_YES0FFBC = Address check and 0 (0x00) and 255 (0xFF) broadcast. |
| 86 | + Smartcc1101.setAddr(0); // Address used for packet filtration. 0 is default. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). |
| 87 | + Smartcc1101.setManchester(true); // Enables Manchester encoding/decoding. false = Disable (default), true = Enable. |
| 88 | + Smartcc1101.setWhiteData(true); // Turn data whitening on / off. false = Whitening off (default). true = Whitening on. |
| 89 | + Smartcc1101.setPktFormat(SmartCC1101::pktf_NORMAL); // Format of RX and TX data. pktf_NORMAL = Normal mode, use FIFOs for RX and TX (default). pktf_RANDOMTX = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. |
| 90 | + Smartcc1101.setLengthConfig(SmartCC1101::pktl_VARIABLE); // pktl_FIXED = Fixed packet length mode. pktl_VARIABLE = Variable packet length mode (default). |
| 91 | + Smartcc1101.setPacketLength(61); // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed. 61 is maximum allowed value in this implementation |
| 92 | + Smartcc1101.setFEC(false); // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. false = Disable (default), true = Enable. |
| 93 | + Smartcc1101.setCRCCheck(true); // true = CRC calculation in TX and CRC check in RX enabled. false = CRC disabled for TX and RX (default). |
| 94 | + Smartcc1101.setCRC_AF(false); // Enable automatic flush of RX FIFO when CRC is not OK. (Default: false) |
| 95 | +} |
| 96 | + |
| 97 | +void loop() { |
| 98 | + |
| 99 | + const char messageText[] = "Hello world!"; |
| 100 | + // Send data. Returns when data is actually sent. |
| 101 | + Smartcc1101.sendData(messageText); |
| 102 | + |
| 103 | + // Wait a moment untill next data sent. |
| 104 | + delay(1000); |
| 105 | +} |
| 106 | + |
| 107 | +``` |
| 108 | + |
| 109 | +The Corresponding receiver is also available: |
| 110 | + |
| 111 | +```C++ |
| 112 | + |
| 113 | +#include <SmartCC1101.h> |
| 114 | + |
| 115 | +void setup() { |
| 116 | + Serial.begin(115200); |
| 117 | + |
| 118 | + Smartcc1101.init(); // must be called first to initialize the CC1101 |
| 119 | + |
| 120 | + if (Smartcc1101.getCC1101()) { // Check the CC1101 SPI connection. |
| 121 | + Serial.println(F("[I] CC1101 connected.")); |
| 122 | + } else { |
| 123 | + Serial.println(F("[E] *** CC1101 connection Error ***")); |
| 124 | + delay(20000); |
| 125 | + } |
| 126 | + |
| 127 | + // Most of the settings repeat standard settings and are here for illustration |
| 128 | + Smartcc1101.setModulation(SmartCC1101::mod_2FSK); // set modulation mode. Possible values: mod_2FSK (default), mod_GFSK, mod_ASKOOK, mod_4FSK, mod_MSK |
| 129 | + Smartcc1101.setCarrierFrequency(868350000); // Set tranmsision frequency in Hz. Default = 868.35 MHz). The cc1101 can use 300-348 MHZ, 387-464MHZ and 779-928MHZ. More info in the datasheet. |
| 130 | + Smartcc1101.setDeviation(47608); // Set the Frequency deviation in Hz. Value from 1586 to 380850. Default is 47607 kHz. Note: the algorithm rounds down. On exact interval limits, the next lower value might be taken (that's why here 47608 is used) |
| 131 | + Smartcc1101.setRXBandWitdth(SmartCC1101::bw_812kHz); // Set the Receive Bandwidth in kHz. Possible values: bw_58kHz = 58kHz, bw_68kHz, bw_81kHz, bw_102kHz,bw_116kHz, bw_135kHz, bw_162kHz, bw_203kHz (default), bw_232kHz, bw_270kHz, bw_325kHz, bw_406kHz, bw_464kHz, bw_541kHz, bw_650kHz, bw_812kHz = 812kHz |
| 132 | + Smartcc1101.setSymbolRate(100000); // Set the Data Rate in Baud. Value from 20 to 1621830 Default is 115051 Baud |
| 133 | + Smartcc1101.setSyncWord(0xD3,0x91); // Set sync word. Must match in sender and receiver. (Syncword high, Syncword low). Values given are default values |
| 134 | + Smartcc1101.setSyncMode(SmartCC1101::sync_1616); // Combined sync-word qualifier mode. sync_NONE = No preamble/sync. sync_1516 = 15/16 sync word bits detected. sync_1616 = 16/16 sync word bits detected (default). sync_3032 = 30/32 sync word bits detected (sync word sent twice). |
| 135 | + // sync_NONECS = No preamble/sync, carrier-sense above threshold. sync_1516CS = 15/16 + carrier-sense above threshold. sync_1516CS = 15/16 + carrier-sense above threshold. sync_1616CS = 16/16 + carrier-sense above threshold. sync_3032CS = 30/32 (sync word sent twice). + carrier-sense above threshold. |
| 136 | + Smartcc1101.setPRE(SmartCC1101::pre_4); // Sets the minimum number of preamble bytes to be transmitted. Possible values: pre_2 : 2, pre_3 : 3, pre_4 : 4 (default), pre_6 : 6, pre_8 : 8, pre_12 : 12, pre_16 : 16, pre_24 : 24 |
| 137 | + Smartcc1101.setPQT(0); // Preamble quality estimator threshold. 0 is the derfault. The preamble quality estimator increases an internal counter by one each time a bit is received that is different from the previous bit, and decreases the counter by 8 each time a bit is received that is the same as the last bit. A threshold of 4∙PQT for this counter is used to gate sync word detection. When PQT=0 a sync word is always accepted. |
| 138 | + Smartcc1101.setAdrChk(SmartCC1101::adc_NO); // Controls address check configuration of received packages. adc_NO = No address check (default). adc_YESNOBC = Address check, no broadcast. adc_YES0BC = Address check and 0 (0x00) broadcast. adc_YES0FFBC = Address check and 0 (0x00) and 255 (0xFF) broadcast. |
| 139 | + Smartcc1101.setAddr(0); // Address used for packet filtration. 0 is default. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). |
| 140 | + Smartcc1101.setManchester(true); // Enables Manchester encoding/decoding. false = Disable (default), true = Enable. |
| 141 | + Smartcc1101.setWhiteData(true); // Turn data whitening on / off. false = Whitening off (default). true = Whitening on. |
| 142 | + Smartcc1101.setPktFormat(SmartCC1101::pktf_NORMAL); // Format of RX and TX data. pktf_NORMAL = Normal mode, use FIFOs for RX and TX (default). pktf_RANDOMTX = Random TX mode; sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX. |
| 143 | + Smartcc1101.setLengthConfig(SmartCC1101::pktl_VARIABLE); // pktl_FIXED = Fixed packet length mode. pktl_VARIABLE = Variable packet length mode (default). |
| 144 | + Smartcc1101.setPacketLength(61); // Indicates the packet length when fixed packet length mode is enabled. If variable packet length mode is used, this value indicates the maximum packet length allowed. 61 is maximum allowed value in this implementation |
| 145 | + Smartcc1101.setFEC(false); // Enable Forward Error Correction (FEC) with interleaving for packet payload (Only supported for fixed packet length mode. false = Disable (default), true = Enable. |
| 146 | + Smartcc1101.setCRCCheck(true); // true = CRC calculation in TX and CRC check in RX enabled. false = CRC disabled for TX and RX (default). |
| 147 | + Smartcc1101.setCRC_AF(false); // Enable automatic flush of RX FIFO when CRC is not OK. (Default: false) |
| 148 | +} |
| 149 | + |
| 150 | + |
| 151 | +void loop() { |
| 152 | + uint8_t buffer[61]{ 0 }; // buffer for the data received by CC1101 |
| 153 | + |
| 154 | + int len = Smartcc1101.receiveData(buffer); |
| 155 | + // len will be 0 if nothing is yet received. |
| 156 | + if (len > 0) { |
| 157 | + Serial.print(len); |
| 158 | + Serial.println(" bytes received."); |
| 159 | + |
| 160 | + // check transfer quality parameters |
| 161 | + int8_t RSSI = Smartcc1101.getRSSI(); |
| 162 | + bool CRC = Smartcc1101.checkCRC(); |
| 163 | + uint8_t LQI = Smartcc1101.getLQI(); |
| 164 | + |
| 165 | + // will try to interpret the buffer received as character array, just make sure it's sero-terminated. |
| 166 | + // if it was actually sent from a character arry, this is not necessary |
| 167 | + buffer[len] = 0; |
| 168 | + |
| 169 | + // check if crc is correct |
| 170 | + if (CRC) { |
| 171 | + Serial.println("CRC ok. RSSI: "); |
| 172 | + Serial.print(RSSI); |
| 173 | + Serial.print("dB, LQI "); |
| 174 | + Serial.println(LQI); |
| 175 | + Serial.println("Data:"); |
| 176 | + Serial.println((char *)buffer); |
| 177 | + } else { |
| 178 | + Serial.print("CRC Error. RSSI: "); |
| 179 | + Serial.print(RSSI); |
| 180 | + Serial.print("dB, LQI "); |
| 181 | + Serial.println(LQI); |
| 182 | + } |
| 183 | + } |
| 184 | +} |
| 185 | + |
| 186 | +``` |
| 187 | + |
| 188 | +## Funtion reference |
| 189 | + |
| 190 | +`bool getCC1101(void)` checks for the presence of a CC1101 module on the SPI bus. |
| 191 | + |
| 192 | +`void init(void)` must be called prijor to using any other funtion. Will establish the necessary setup of the CC1101 chip. Onyl exception: `gtCC1101()` |
| 193 | + |
| 194 | +`void sleep(void)` Sets the CC1101 to sleep mode, reducing power consumption. The next access will wake the chip up again, no special procedure is needed. |
| 195 | + |
| 196 | + `void setDCFilterOff(bool dcf)` Disable digital DC blocking filter before demodulator. Only for data rates ≤ 250 kBaud. The recommended IF frequency changes when the DC blocking is disabled. true = Disable (current optimized), false = Enable (better sensitivity). |
| 197 | + |
| 198 | + `void setCarrierFrequency(uint32_t freq)` Set tranmsision frequency in Hz. Default = 868.35 MHz). The cc1101 can use 300-348 MHZ, 387-464MHZ and 779-928MHZ. More info in the datasheet. Must match sender and receiver |
| 199 | + |
| 200 | + `void setRXBandWitdth(rx_BandWidth bw)` Set the Receive Bandwidth. Value can be cosen from predefined list of values: |
| 201 | +| Bandwidth | Value | |
| 202 | +|----------|---------| |
| 203 | +| 58KHz | bw_58kHz | |
| 204 | +| 68kHz | bw_68kHz | |
| 205 | +| 81kHz | bw_81kHz | |
| 206 | +| 102kHz | bw_102kHz | |
| 207 | +| 116kHz | bw_116kHz | |
| 208 | +| 135kHz | bw_135kHz | |
| 209 | +| 203kHz | bw_203kHz | |
| 210 | +| 232kHz | bw_232kHz | |
| 211 | +| 270kHz | bw_270kHz | |
| 212 | +| 325kHz | bw_325kHz | |
| 213 | +| 406kHz | bw_406kHz | |
| 214 | +| 464kHz | bw_464kHz | |
| 215 | +| 541kHz | bw_541kHz | |
| 216 | +| 650kHz | bw_650kHz | |
| 217 | +| 812kHz | bw_812kHz | |
| 218 | + |
| 219 | + |
| 220 | + `void setModulation(Modulation m)` Set modulation mode. Should match sender and receiver. I nearly exclusively use 2FSK modulation. |
| 221 | +| Value | Modulation | |
| 222 | +|------------|-------| |
| 223 | +|mod_2FSK| 2FSK modulation| |
| 224 | +|mod_GFSK| GFSK modulation| |
| 225 | +|mod_ASKOOK| ASK/OOK modulation (untested)| |
| 226 | +|mod_4FSK| 4FSK modulation| |
| 227 | +|mod_MSK| MFSK modulation| |
| 228 | + |
| 229 | + `void setPA(int8_t pa)` Set TXPower in dB. The following settings are possible depending on the frequency band: -30, -20, -15, -10, -6, 0, 5, 7, 10, 11, 12. Default is max. |
| 230 | + |
| 231 | + |
| 232 | + void setDeviation(uint32_t deviation); |
| 233 | + enum sync_Mode : uint8_t { |
| 234 | + sync_NONE = 0b000, // No preamble/sync |
| 235 | + sync_1516 = 0b001, // 15/16 sync word bits detected |
| 236 | + sync_1616 = 0b010, // 16/16 sync word bits detected |
| 237 | + sync_3032 = 0b011, // 30/32 sync word bits detected |
| 238 | + sync_NONECS = 0b100, // No preamble/sync, carrier-sense above threshold |
| 239 | + sync_1516CS = 0b101, // 15/16 + carrier-sense above threshold |
| 240 | + sync_1616CS = 0b110, // 16/16 + carrier-sense above threshold |
| 241 | + sync_3032CS = 0b111 // 30/32 + carrier-sense above threshold |
| 242 | + }; |
| 243 | + void setSyncMode(sync_Mode syncm); |
| 244 | + void setSyncWord(uint8_t sh, uint8_t sl); |
| 245 | + enum preamble_Bytes : uint8_t { |
| 246 | + pre_2 = 0b00000000, // 2 preamble bytes |
| 247 | + pre_3 = 0b00010000, // 3 preamble bytes |
| 248 | + pre_4 = 0b00100000, // 4 preamble bytes |
| 249 | + pre_6 = 0b00110000, // 6 preamble bytes |
| 250 | + pre_8 = 0b01000000, // 8 preamble bytes |
| 251 | + pre_12 = 0b01010000, // 12 preamble bytes |
| 252 | + pre_16 = 0b01100000, // 16 preamble bytes |
| 253 | + pre_24 = 0b01110000 // 24 preamble bytes |
| 254 | + }; |
| 255 | + void setPRE(preamble_Bytes pre); |
| 256 | + void setPQT(uint8_t pqt); |
| 257 | + enum AddressCheck : uint8_t { |
| 258 | + adc_NO, // No address check |
| 259 | + adc_YESNOBC, // Address check, no broadcast |
| 260 | + adc_YES0BC, // Address check and 0 (0x00) broadcast |
| 261 | + adc_YES0FFBC // Address check and 0 (0x00) and 255 (0xFF) broadcast |
| 262 | + }; |
| 263 | + void setAdrChk(AddressCheck adc); |
| 264 | + void setAddr(uint8_t addr); |
| 265 | + enum PacketFormat : uint8_t { |
| 266 | + /* |
| 267 | +* @note Synchronous serial mode and Asynchronous serial mode are unsupported |
| 268 | +*/ |
| 269 | + pktf_NORMAL = 0b00000000, // Normal mode, use FIFOs for RX and TX |
| 270 | + pktf_RANDOMTX = 0b00100000 // sends random data using PN9 generator. Used for test. Works as normal mode, setting 0 (00), in RX |
| 271 | + }; |
| 272 | + void setPktFormat(PacketFormat pktf); |
| 273 | + void setCRCCheck(bool crcc); |
| 274 | + void setCRC_AF(bool af); |
| 275 | + void setFEC(bool fec); |
| 276 | + enum PacketLengthConfig : uint8_t { |
| 277 | + /** |
| 278 | +* @note CC1101 also supports infinite packet lenth mode, but this is not implemented. |
| 279 | +*/ |
| 280 | + pktl_FIXED, |
| 281 | + pktl_VARIABLE |
| 282 | + |
| 283 | + }; |
| 284 | + void setLengthConfig(PacketLengthConfig pktl); |
| 285 | + void setPacketLength(uint8_t len); |
| 286 | + void setWhiteData(bool white); |
| 287 | + void setManchester(bool menc); |
| 288 | + void setSymbolRate(double symbolRate); |
| 289 | + |
| 290 | + void sendData(const char *txBuffer); |
| 291 | + void sendData(const uint8_t *txBuffer, uint8_t size); |
| 292 | + |
| 293 | + int8_t getRSSI(void); |
| 294 | + bool checkCRC(void); |
| 295 | + uint8_t getLQI(void); |
| 296 | + void setRX(void); |
| 297 | + uint8_t receiveData(uint8_t *rxBuffer); |
| 298 | + |
| 299 | + |
| 300 | + void setDelayFunction(void delayFunc(uint8_t)); |
| 301 | + void smartDelay(uint8_t ms); |
| 302 | + |
0 commit comments