Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: CC1200-MorseEncoder CC1200-Examples
CC1200.h
00001 // 00002 // Created by jamie on 3/27/2020. 00003 // 00004 00005 #ifndef LIGHTSPEEDRANGEFINDER_CC1200_H 00006 #define LIGHTSPEEDRANGEFINDER_CC1200_H 00007 00008 #include <mbed.h> 00009 #include <Stream.h> 00010 00011 #include <cstdint> 00012 00013 /** 00014 * Base driver for the CC1200 radio communications IC. 00015 * This class provides basic functions and register level IO with the chip. 00016 */ 00017 class CC1200 00018 { 00019 // connections to chip 00020 SPI spi; 00021 DigitalOut rst; 00022 00023 // Output to print debug messages to 00024 Stream * debugStream; 00025 00026 public: 00027 00028 // register definitions 00029 enum class Register : uint8_t 00030 { 00031 IOCFG3 = 0x00, 00032 IOCFG2 = 0x01, 00033 IOCFG1 = 0x02, 00034 IOCFG0 = 0x03, 00035 SYNC3 = 0x4, 00036 SYNC2 = 0x5, 00037 SYNC1 = 0x6, 00038 SYNC0 = 0x7, 00039 SYNC_CFG1 = 0x8, 00040 SYNC_CFG0 = 0x9, 00041 DEVIATION_M = 0xA, 00042 MODCFG_DEV_E = 0xB, 00043 DCFILT_CFG = 0xC, 00044 PREAMBLE_CFG1 = 0xD, 00045 PREAMBLE_CFG0 = 0xE, 00046 IQIC = 0xF, 00047 CHAN_BW = 0x10, 00048 MDMCFG1 = 0x11, 00049 MDMCFG0 = 0x12, 00050 SYMBOL_RATE2 = 0x13, 00051 SYMBOL_RATE1 = 0x14, 00052 SYMBOL_RATE0 = 0x15, 00053 AGC_REF = 0x16, 00054 AGC_CS_THR = 0x17, 00055 AGC_GAIN_ADJUST = 0x18, 00056 AGC_CFG3 = 0x19, 00057 AGC_CFG2 = 0x1A, 00058 AGC_CFG1 = 0x1B, 00059 AGC_CFG0 = 0x1C, 00060 FIFO_CFG = 0x1D, 00061 DEV_ADDR = 0x1E, 00062 SETTLING_CFG = 0x1F, 00063 FS_CFG = 0x20, 00064 WOR_CFG1 = 0x21, 00065 WOR_CFG0 = 0x22, 00066 WOR_EVENT0_MSB = 0x23, 00067 WOR_EVENT0_LSB = 0x24, 00068 RXDCM_TIME = 0x25, 00069 PKT_CFG2 = 0x26, 00070 PKT_CFG1 = 0x27, 00071 PKT_CFG0 = 0x28, 00072 RFEND_CFG1 = 0x29, 00073 RFEND_CFG0 = 0x2A, 00074 PA_CFG1 = 0x2B, 00075 PA_CFG0 = 0x2C, 00076 ASK_CFG = 0x2D, 00077 PKT_LEN = 0x2E 00078 }; 00079 00080 // extended register definitions 00081 enum class ExtRegister : uint8_t 00082 { 00083 IF_MIX_CFG = 0x0, 00084 FREQOFF_CFG = 0x1, 00085 TOC_CFG = 0x2, 00086 //... 00087 MDMCFG2 = 0x5, 00088 //... 00089 FREQOFF1 = 0xA, 00090 FREQOFF2 = 0xB, 00091 FREQ2 = 0xC, 00092 FREQ1 = 0xD, 00093 FREQ0 = 0xE, 00094 IF_ADC2 = 0xF, 00095 IF_ADC1 = 0x10, 00096 IF_ADC0 = 0x11, 00097 FS_DIG1 = 0x12, 00098 FS_DIG0 = 0x13, 00099 //... 00100 FS_CAL1 = 0x16, 00101 FS_CAL0 = 0x17, 00102 FS_CHP = 0x18, 00103 FS_DIVTWO = 0x19, 00104 FS_DSM1 = 0x1A, 00105 FS_DSM0 = 0x1B, 00106 FS_DVC1 = 0x1C, 00107 FS_DVC0 = 0x1D, 00108 FS_LBI = 0x1E, 00109 FS_PFD = 0x1F, 00110 FS_PRE = 0x20, 00111 FS_REG_DIV_CML = 0x21, 00112 FS_SPARE = 0x22, 00113 FS_VCO4 = 0x23, 00114 FS_VCO3 = 0x24, 00115 FS_VCO2 = 0x25, 00116 FS_VCO1 = 0x26, 00117 FS_VCO0 = 0x27, 00118 //... 00119 IFAMP = 0x2F, 00120 //.. 00121 XOSC5 = 0x32, 00122 XOSC4 = 0x33, 00123 XOSC3 = 0x34, 00124 XOSC2 = 0x35, 00125 XOSC1 = 0x36, 00126 XOSC0 = 0x37, 00127 //... 00128 RSSI1 = 0x71, 00129 RSSI0 = 0x72, 00130 MARCSTATE = 0x73, 00131 LQI_VAL = 0x74, 00132 //... 00133 FREQOFF_EST1 = 0x77, 00134 FREQOFF_EST2 = 0x78, 00135 //... 00136 FSCAL_CTRL = 0x8D, 00137 PARTNUMBER = 0x8F, 00138 PARTVERSION = 0x90, 00139 //... 00140 RXFIRST = 0xD2, 00141 TXFIRST = 0xD3, 00142 RXLAST = 0xD4, 00143 TXLAST = 0xD5, 00144 NUM_TXBYTES = 0xD6, 00145 NUM_RXBYTES = 0xD7, 00146 //... 00147 RXFIFO_PRE_BUF = 0xDA 00148 }; 00149 00150 // Command strobe definitions. See user guide section 3.2.2 00151 enum class Command : uint8_t 00152 { 00153 SOFT_RESET = 0x30, 00154 FAST_TX_ON = 0x31, 00155 OSC_OFF = 0x32, 00156 CAL_FREQ_SYNTH = 0x33, 00157 RX = 0x34, 00158 TX = 0x35, 00159 IDLE = 0x36, 00160 AUTO_FREQ_COMP = 0x37, 00161 WAKE_ON_RADIO = 0x38, 00162 SLEEP = 0x39, 00163 FLUSH_RX = 0x3A, 00164 FLUSH_TX = 0x3B, 00165 WOR_RESET = 0x3C, 00166 NOP = 0x3D 00167 }; 00168 00169 // State of the radio chip. See user guide Figure 2. 00170 enum class State : uint8_t 00171 { 00172 IDLE = 0x0, 00173 RX = 0x1, 00174 TX = 0x2, 00175 FAST_ON = 0x3, 00176 CALIBRATE = 0x4, 00177 SETTLING = 0x5, 00178 RX_FIFO_ERROR = 0x6, 00179 TX_FIFO_ERROR = 0x7 00180 }; 00181 00182 private: 00183 // chip data variables 00184 bool chipReady = false; 00185 State state = State::IDLE; 00186 bool isCC1201; 00187 00188 // current state variables 00189 00190 // current symbol rate of the radio 00191 float symbolRateSps = 0; 00192 00193 // current RX filter params 00194 uint8_t adcCicDecimation = 0; 00195 float currentRXFilterBW = 0; 00196 00197 // current RF params 00198 float radioFreqHz; 00199 00200 00201 public: 00202 00203 /** 00204 * Construct a CC1200 radio driver from the given set of pins. 00205 * 00206 * @param misoPin 00207 * @param mosiPin 00208 * @param sclkPin 00209 * @param csPin 00210 * @param rstPin 00211 * @param _debugStream Stream to print error/debug information on. 00212 * @param isCC1201 True if the chip is a CC1201, false if it is a CC1200. The CC1201 is a cheaper option that lacks low bandwidth settings but is otherwise identical. 00213 */ 00214 CC1200(PinName mosiPin, PinName misoPin, PinName sclkPin, PinName csPin, PinName rstPin, Stream * _debugStream, bool _isCC1201 = false); 00215 00216 /** 00217 * Reset the chip and attempt to connect to it. 00218 * Returns whether the chip could be contacted. 00219 * @return 00220 */ 00221 bool begin(); 00222 00223 /** 00224 * Get the radio's most recently known state. 00225 * State is updated whenever registers are read or commands are sent, or when you call updateState. 00226 * @return 00227 */ 00228 State getState() { return state; } 00229 00230 // Data tx & rx functions 00231 // ------------------------------------------------------------------------------ 00232 00233 /** 00234 * Get the number of bytes currently in the TX FIFO 00235 * @return 00236 */ 00237 size_t getTXFIFOLen(); 00238 00239 /** 00240 * Get the number of bytes currently in the RX FIFO 00241 * @return 00242 */ 00243 size_t getRXFIFOLen(); 00244 00245 /** 00246 * Enqueue a packet to be sent over the radio. It will be sent the next time the radio is in 00247 * transmit state. 00248 * 00249 * In variable length mode, the length of a packet is variable, from 1 byte to 127 bytes. 00250 * The length will be transmitted along with the packet data. 00251 * 00252 * In fixed length mode, the length should be the fixed packet length. 00253 * 00254 * The function is not for use with infinite-length mode, use writeStream() instead. 00255 * 00256 * Also reads the radio's state. 00257 * 00258 * @param data 00259 * @param len 00260 * 00261 * @return Whether the packet was enqueued. Could return false if there was not enough FIFO 00262 * space to enqueue the packet, or if the packet is too long. 00263 */ 00264 bool enqueuePacket(char const * data, size_t len); 00265 00266 /** 00267 * Check whether there is at least one complete packet in the RX FIFO. 00268 * In infinite length mode, this returns true if any data is present at all. 00269 * NOTE: An alternate way to do this using hardware is to configure one 00270 * of the CC1200's GPIOs as PKT_SYNC_RXTX, then set a falling edge interrupt to receive a packet. 00271 * @return 00272 */ 00273 bool hasReceivedPacket(); 00274 00275 /** 00276 * Receive a packet from the radio. Only packets that pass CRC check are received into the FIFO; 00277 * those which do not pass checksum will be discarded. 00278 * 00279 * This function assumes that there is a packet in the buffer. You should only call it after 00280 * hasReceivedPacket() is true or a PKT_SYNC_RXTX pulse is received. If there is not a packet 00281 * in the FIFO, *undefined behavior* can occur. An arbitrary amount of data will be read from 00282 * the FIFO and garbage may be returned. 00283 * 00284 * The function is not for use with infinite-length mode, use readStream() instead. 00285 * 00286 * NOTE: A null terminator is NOT added unless it was present in the transmitted data. 00287 * Be careful when treating the returned data as a string! 00288 * 00289 * @param buffer Buffer to store received bytes in. 00290 * @param bufferLen Length of the buffer supplied. If the packet is longer than this buffer, then 00291 * the full packet will be read from the FIFO but only a buffer's worth will be stored. 00292 * @return Number of bytes actually received. 00293 */ 00294 size_t receivePacket(char * buffer, size_t bufferLen); 00295 00296 // Infinite length tx & rx functions 00297 // ------------------------------------------------------------------------------ 00298 00299 /* 00300 * How to use infinite length from the TX side: 00301 * 1. Place up to 128 bytes of data in the TX FIFO for transmission using writeStream(). 00302 * 2. Enable TX mode using startTX() 00303 * 3. Keep streaming in data using writeStream() writeStreamBlocking() or at least as fast as it is transmitted. 00304 * 4. Disable TX mode when done using idle(). 00305 * 00306 * Take care that the TX fifo never runs completely out of data, or the chip will go into TX FIFO ERROR state. 00307 */ 00308 00309 /* 00310 * How to use infinite length from the RX side: 00311 * 1. Enable RX mode using startRX(). I'm pretty sure that if sync words are enabled, you must start RX before the transmitter starts transmitting. 00312 * 2. Wait for data to arrive using hasReceivedPacket(). 00313 * 3. Start streaming out data using readStream() or readStreamBlocking(). 00314 * 4. Disable RX mode when done using idle(). 00315 * 00316 * Take care that the RX fifo doesn't become full, or the chip will go into RX FIFO ERROR state. 00317 */ 00318 00319 /** 00320 * Write a stream of data to the chip. This function is only for use in infinite-length mode. 00321 * As many bytes from the given buffer will be written as can fit in the chip's FIFO. 00322 * If the FIFO is full, this function does nothing. 00323 * 00324 * @param buffer 00325 * @param count 00326 * @return Number of bytes written. 00327 */ 00328 size_t writeStream(const char* buffer, size_t count); 00329 00330 /** 00331 * Write a stream of data to the chip. This function is only for use in infinite-length mode. 00332 * Will block until all bytes in the given buffer have been written to the TX FIFO, or an error has been 00333 * detected (the radio switches to any state other than TX). 00334 * 00335 * @param buffer 00336 * @param count 00337 * @return True if successful, false if there was an error. 00338 */ 00339 bool writeStreamBlocking(const char* buffer, size_t count); 00340 00341 /** 00342 * Read up to maxLen bytes into buffer. 00343 * @param buffer 00344 * @param maxLen 00345 * @return How many bytes were actually read. 0 if the RX FIFO was empty. 00346 */ 00347 size_t readStream(char* buffer, size_t maxLen); 00348 00349 /** 00350 * Read a stream of data from the chip. This function is only for use in infinite-length mode. 00351 * Will block until the buffer was filled, an error has been 00352 * detected (the radio switches to any state other than RX), or the timeout expires. 00353 * 00354 * If false is returned, some data may have been written to the buffer, and the rest will not have been modified. 00355 * 00356 * Note: if using a zero timeout, this function could cause a hang if the transmitter stops transmitting. 00357 * 00358 * @param buffer 00359 * @param count 00360 * @param timeout Timeout, or 0us to disable timeout. 00361 * @return True iff the buffer was completely filled. 00362 */ 00363 bool readStreamBlocking(char* buffer, size_t count, std::chrono::microseconds timeout=0us); 00364 00365 // State transition configuration 00366 // ------------------------------------------------------------------------------ 00367 00368 /** 00369 * Set what state the radio will enter when a packet is received. 00370 * @param goodPacket State when a good (CRC pass) packet is received. 00371 * Accepts State::TX, State::IDLE, State::FAST_TX_ON, and State::RX. 00372 * @param badPacket State when a bad (CRC fail) packet is received. 00373 * Accepts State::RX and State::IDLE 00374 */ 00375 void setOnReceiveState(State goodPacket, State badPacket); 00376 00377 /** 00378 * Set what state the radio will enter when a packet is sent. 00379 * @param txState State when a packet is transmitted. 00380 * Accepts State::TX, State::IDLE, State::FAST_TX_ON, and State::RX. 00381 */ 00382 void setOnTransmitState(State txState); 00383 00384 enum class FSCalMode : uint8_t 00385 { 00386 NONE = 0b00, // never calibrate the FS automatically 00387 FROM_IDLE = 0b01, // calibrate the FS when going from idle to TX, RX, or fast TX on 00388 TO_IDLE = 0b10, // calibrate the FS when going from TX, RX, or fast TX on to idle 00389 TO_IDLE_1_4 = 0b11 // calibrate the FS 1/4 of the time when going from TX, RX, or fast TX on to idle 00390 }; 00391 00392 /** 00393 * Set when the radio calibrates its frequency synthesizer. 00394 * 00395 * Per https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/375189 00396 * it looks like the FS can drift with changes in supply voltage and/or temperature, 00397 * so it is good to continually calibrate it in case these change. 00398 */ 00399 void setFSCalMode(FSCalMode mode); 00400 00401 // GPIO configuration 00402 // ------------------------------------------------------------------------------ 00403 00404 /** 00405 * Enum for all possible GPIO modes. 00406 * Note: Some modes do different things depending on which GPIOs they're assigned to. 00407 * Duplicate enum values have been intentionally defined for this. 00408 */ 00409 enum class GPIOMode : uint8_t 00410 { 00411 RXFIFO_THR_PKT = 1, 00412 PKT_SYNC_RXTX = 6, 00413 RSSI_UPDATE = 14, // GPIO3 and GPIO2 00414 AGC_HOLD = 14, // GPIO1 00415 AGC_UPDATE = 14, // GPIO0 00416 SYNC_EVENT = 41, // GPIO2 00417 HIGHZ = 48, 00418 HW0 = 51 00419 }; 00420 00421 /** 00422 * Configure a CC1200 GPIO pin. 00423 * @param gpioNumber Pin number, from 0-3. 00424 * @param mode Mode to set the pin to. 00425 * @param outputInvert Whether to invert the output of the pin. 00426 */ 00427 void configureGPIO(uint8_t gpioNumber, GPIOMode mode, bool outputInvert = false); 00428 00429 // RF configuration 00430 // ------------------------------------------------------------------------------ 00431 00432 /** 00433 * Set up the radio for FIFO mode. 00434 */ 00435 void configureFIFOMode(); 00436 00437 enum class PacketMode : uint8_t 00438 { 00439 /// Use infinite length transmissions (streaming mode). 00440 INFINITE_LENGTH = 0b10, 00441 /// Use fixed length packets. 00442 VARIABLE_LENGTH = 0b1, 00443 /// Use variable length packets, the length is encoded in the first byte of the packet. 00444 FIXED_LENGTH = 0b0 00445 }; 00446 00447 /** 00448 * Set the packet mode that the system will use. 00449 * @param mode 00450 * @param appendStatus Have the radio append a status byte to each packet received. This takes up 00451 * 2 bytes per packet in the RX FIFO, but provides status information about each packet. 00452 */ 00453 void setPacketMode(PacketMode mode, bool appendStatus = false); 00454 00455 /** 00456 * Set the packet length when in fixed length packet mode. 00457 * The bit length parameter can be used to send only the x most significant bits of the final byte. 00458 * For example, if your packets are 20 bits long, you should set length to 2 bytes and bitLength to 00459 * 4 bytes, so that 2 complete bytes + 4 extra bits are transmitted. Buffers used for sending and receiving packets 00460 * should then be 3 bytes long. 00461 * 00462 * When appendStatus is disabled, the max length is 256 bytes. When it is enabled, the max length is 254 bytes. 00463 * @param length 00464 */ 00465 void setPacketLength(uint16_t length, uint8_t bitLength = 0); 00466 00467 private: 00468 // current packet mode 00469 PacketMode _packetMode; 00470 00471 // current packet length when in fixed length packet mode 00472 uint16_t _packetTotalLength = 0; // length in bytes including final partial byte 00473 uint16_t _packetByteLength = 0; // length in whole bytes 00474 uint8_t _packetBitLength = 0; // extra bit length at end 00475 00476 // Whether the two status bytes are included in each received packet 00477 bool appendStatusEnabled = true; 00478 00479 public: 00480 00481 /** 00482 * Set whether the CRC check is enabled. This driver enables it by default. 00483 * Enabling CRC will cause a 16 bit checksum to be transmitted along with the packet. 00484 * It will be automatically checked by the receiving CC1200, and the packet will be discarded if the CRC 00485 * doesn't match. 00486 * 00487 * NOTE: it is not recommended to disable the CRC when using variable length mode. 00488 * If the length byte is corrupted and the CRC doesn't check this, then the driver could read 00489 * too little or too much from the chip's FIFO and cause the chip to enter the FIFO underflow state. 00490 * @param enabled 00491 */ 00492 void setCRCEnabled(bool enabled); 00493 00494 enum class ModFormat : uint8_t 00495 { 00496 FSK_2 = 0x0, 00497 GFSK_2 = 0x1, 00498 ASK = 0x3, 00499 FSK_4 = 0x4, 00500 GFSK_4 = 0x5 00501 }; 00502 00503 /** 00504 * Set the modulation format of the radio. 00505 * @param format 00506 */ 00507 void setModulationFormat(ModFormat format); 00508 00509 /** 00510 * Set the frequency deviation from the center frequency in Hz. 00511 * See user guide section 5.2.1 for details, and cc1200 datasheet section 4.10.2 for example values. 00512 */ 00513 void setFSKDeviation(float deviation); 00514 00515 /** 00516 * Set the RF symbol rate in Hz. If this radio is to be used in receive mode you must call 00517 * setRXFilterBandwidth() after calling this function. 00518 * @param symbolRateHz 00519 */ 00520 void setSymbolRate(float symbolRateHz); 00521 00522 /** 00523 * Set the approximate output power in dBm. 00524 * Must be between -16dBm and +14dBm. 00525 * @param outPower 00526 */ 00527 void setOutputPower(float outPower); 00528 00529 // min power to use to turn the radio completely off 00530 const static float ASK_MIN_POWER_OFF; 00531 00532 /** 00533 * Set the high and low output powers when transmitting in ASK mode. 00534 * Overrides the setOutputPower() power setting. 00535 * @param maxPower High output power. Must be between -16dBm and +14dBm. 00536 * @param minPower Low output power. Must be between maxPower and -17.5dBm. -17.5dBm gives completely off, 00537 * so OOK modulation instead of ASK. 00538 */ 00539 void setASKPowers(float maxPower, float minPower); 00540 00541 // Radio band for the chip to operate on. 00542 // See user guide description for FS_CFG register. 00543 enum class Band : uint8_t 00544 { 00545 BAND_820_960MHz = 0x2, 00546 BAND_410_480MHz = 0x4, 00547 BAND_273_320MHz = 0x6, 00548 BAND_205_240MHz = 0x8, 00549 BAND_164_192MHz = 0xA, 00550 BAND_136_160MHz = 0xB 00551 }; 00552 00553 /** 00554 * Set the radio band and specific frequency. See user guide section 9.12 for details. 00555 * Note: Frequency offsets are not currently implemented, so the frequency can't be 00556 * set at the finest resolution. However, the resolution should be fine for most applications. 00557 * (at 900MHz this function has a resolution of 152.5Hz) 00558 * @param band 00559 * @param frequencyHz 00560 */ 00561 void setRadioFrequency(Band band, float frequencyHz); 00562 00563 /** 00564 * Set the the RX filter bandwidth. You must call this AFTER setting the symbol rate. 00565 * See user guide section 6.1 for details. 00566 * 00567 * NOTE: The symbol rate and the RX filter bandwidth must be compatible with each other. 00568 * See the user guide for details. 00569 * 00570 * A number of different registers must be configured in order to properly configure the radio for a given bandwidth. 00571 * This call currently sets the following register fields: 00572 * - CHAN_BW.ADC_CIC_DECFACT 00573 * - CHAN_BW.BB_CIC_DECFACT 00574 * - MDMCFG1.DVGA_GAIN 00575 * - MDMCFG0.DATA_FILTER_EN 00576 * - SYNC_CFG0.RX_CONFIG_LIMITATION 00577 * 00578 * @param bandwidthHz the bandwidth in Hz 00579 * @param preferHigherCICDec If there are multiple register value choices, prefer the one with higher CIC decimation 00580 * and lower BB decimation. This is the recommendation of the datasheet but it actually causes transmission to fail in some cases. 00581 */ 00582 void setRXFilterBandwidth(float bandwidthHz, bool preferHigherCICDec = true); 00583 00584 /** 00585 * Get the ADC CIC decimation that was calculated by the most recent setRXFilterBandwidth() call. 00586 * This is used for certain other calculations such as the DC offset. 00587 * @return 00588 */ 00589 uint8_t getADCCICDecimation() { return adcCicDecimation; } 00590 00591 /** 00592 * Configure the radio's automatic DC offset removal algorithm as enabled. 00593 * DC offset correction must be enabled when using zero IF mode, and in my testing 00594 * it seems to be important when staying in TX mode for a long time at 00595 * higher sample rates. 00596 * 00597 * See the datasheet register description for DCFILT_CFG for explanations of what these values do. 00598 * Maybe you'll actually be able to make some sense out of what it says... I sure couldn't. 00599 * 00600 * @param enableAutoFilter Whether automatic filtering is enabled. 00601 * @param settlingCfg Settling time configuration bits. 00602 * @param cutoffCfg Cutoff frequency configuration bits. 00603 */ 00604 void configureDCFilter(bool enableAutoFilter, uint8_t settlingCfg, uint8_t cutoffCfg); 00605 00606 /** 00607 * Possible intermediate frequency values. 00608 * For right now it seems like you have to get these from SmartRF. 00609 * See the user guide section on IF_MIX_CFG.CMIX_CFG for details. 00610 */ 00611 enum class IFCfg : uint8_t 00612 { 00613 ZERO = 0, // Zero IF. From what I can find, this means samples are taken at the radio frequency. 00614 NEGATIVE_DIV_4 = 0b001, 00615 NEGATIVE_DIV_6 = 0b010, 00616 NEGATIVE_DIV_8 = 0b011, 00617 POSITIVE_DIV_4 = 0b101, 00618 POSITIVE_DIV_6 = 0b110, 00619 POSITIVE_DIV_8 = 0b111 00620 }; 00621 00622 /** 00623 * Set the receiver IF mixing configuration. 00624 * See the user guide section on IF_MIX_CFG.CMIX_CFG for details. 00625 * 00626 * You must call *both* setRXFilterBandwidth() and setRadioFrequency() before calling this function. 00627 * 00628 * @param value Divider value to use, or zero-IF 00629 * @param enableIQIC Whether to enable the ImageExtinct IQ mismatch compensation when supported 00630 * (when if IF > RX filter bandwidth). 00631 */ 00632 void setIFCfg(IFCfg value, bool enableIQIC); 00633 00634 /** 00635 * Mode describing the size and setup of the sync word. 00636 * See user guide register description for SYNC_CFG1 00637 */ 00638 enum class SyncMode : uint8_t 00639 { 00640 SYNC_NONE = 0, 00641 SYNC_11_BITS = 0b1, 00642 SYNC_16_BITS = 0b10, 00643 SYNC_18_BITS = 0b11, 00644 SYNC_24_BITS = 0b100, 00645 SYNC_32_BITS = 0b101, 00646 SYNC_16_BITS_HIGH_BYTE = 0b110, 00647 SYNC_16_BITS_DUAL = 0b111 00648 }; 00649 00650 /** 00651 * Configure the sync word settings of the radio. The sync word is the bit string sent before each packet -- the 00652 * radio knows to switch into receive mode when it detects it. Specific values with low autocorrelation should 00653 * be used for the sync word. 00654 * 00655 * @param syncWord Sync word value. 00656 * @param mode Sync word mode. Configures how many bits of the value are significant. 00657 * @param syncThreshold Correspondance threshold before the radio switches into receive mode. 00658 */ 00659 void configureSyncWord(uint32_t syncWord, SyncMode mode, uint8_t syncThreshold); 00660 00661 /** 00662 * Check whether the frequency synthesizer is locked on to the correct frequency. 00663 * If not, then the correct RF frequency is not being used. 00664 * If the FS is not locking then check that the correct black box FS registers are applied 00665 * and that the FS has been calibrated. 00666 * @return 00667 */ 00668 bool isFSLocked(); 00669 00670 /** 00671 * Configure the preamble that the radio is configured to send/receive. The main purpose of the preamble is to 00672 * provide receiving radios with a chance to calibrate their RX gain. However, you can also require that receiving 00673 * radios see a valid preamble before they can detect the sync word (this is not on by default). 00674 * 00675 * @param preambleLengthCfg Bits that determine the length of the preamble. See the PREAMBLE_CFG1 register description for details. Set to 0 disable transmitting a preamble. 00676 * @param preambleFormatCfg Bits that determine the format of the preamble. See the PREAMBLE_CFG1 register description for details. 00677 */ 00678 void configurePreamble(uint8_t preambleLengthCfg, uint8_t preambleFormatCfg); 00679 00680 /** 00681 * Enum for different PA ramp times. 00682 */ 00683 enum class RampTime : uint8_t 00684 { 00685 RAMP_3_8_SYMBOL = 0b0, 00686 RAMP_3_2_SYMBOL = 0b1, 00687 RAMP_3_SYMBOL = 0b10, 00688 RAMP_6_SYMBOL = 0b11 00689 }; 00690 00691 /** 00692 * Enable the the power amplifier ramp-up curve and set its shape and time. 00693 * See section 7.1 for details. 00694 * This is also used to set the ASK ramping between different power levels. 00695 * 00696 * The PA will gradually ramp from off to full amplitude in rampTime relative to the 00697 * symbol rate. At 1/3 of rampTime it will have ramped to (firstRampLevel / 16) * full amplitude, 00698 * and at 2/3 of rampTime it will have ramped to ((secondRampLevel + 7) / 16) * full amplitude. 00699 */ 00700 void setPARampRate(uint8_t firstRampLevel, uint8_t secondRampLevel, RampTime rampTime); 00701 00702 /** 00703 * Disable the power amplifier ramp-up curve. 00704 */ 00705 void disablePARamping(); 00706 00707 // Automatic Gain Control (AGC) Config 00708 // ------------------------------------------------------------------------------ 00709 00710 /** 00711 * Set the AGC reference level which is the internal target power level that 00712 * the AGC tries to adjust to. 00713 * 00714 * The user manual section 6.4 gives a rough formula to calculate this, but I've just used the SmartRF values. 00715 * 00716 * @param level Internal power level in dB. 00717 */ 00718 void setAGCReferenceLevel(uint8_t level); 00719 00720 /** 00721 * Enum for possible AGC actions after is a sync word detection. 00722 * See AGC_CFG3 register description for more info. 00723 */ 00724 enum class SyncBehavior : uint8_t 00725 { 00726 FREEZE_NONE = 0b000, 00727 FREEZE_GAIN = 0b001, 00728 AGC_SLOWMODE = 0b010, 00729 FREEZE_BOTH = 0b011 00730 }; 00731 00732 /** 00733 * Set the AGC behavior after a sync word is detected. 00734 * @param behavior 00735 */ 00736 void setAGCSyncBehavior(SyncBehavior behavior); 00737 00738 /** 00739 * Enum for possible gain tables to use. 00740 * See AGC_CFG2 register description for more info. 00741 */ 00742 enum class GainTable : uint8_t 00743 { 00744 OPTIMIZED_LINEARITY = 0b00, 00745 NORMAL = 0b01, 00746 LOW_POWER = 0b10, 00747 ZERO_IF = 0b11 00748 }; 00749 00750 /** 00751 * Set the gain table and min and max values within that table to use. 00752 * Min and max values are indexes into the current selected table. 00753 */ 00754 void setAGCGainTable(GainTable table, uint8_t minGainIndex, uint8_t maxGainIndex); 00755 00756 /** 00757 * Configure the change in input signal power that must be sensed before the AGC starts to adjust itself. 00758 * See the register description for AGC_CFG0.AGC_HYST_LEVEL 00759 * @param hysteresisCfg 00760 */ 00761 void setAGCHysteresis(uint8_t hysteresisCfg); 00762 00763 /** 00764 * Configure the rate that the AGC changes the receive gain. 00765 * See the register description for AGC_CFG0.AGC_SLEWRATE_LIMIT 00766 * @param slewrateCfg 00767 */ 00768 void setAGCSlewRate(uint8_t slewrateCfg); 00769 00770 /** 00771 * Configure the time that the AGC takes to settle. 00772 * See the register description for AGC_CFG1.AGC_SETTLE_WAIT 00773 * @param settleWaitCfg bytes to write to AGC_CFG1.AGC_SETTLE_WAIT 00774 */ 00775 void setAGCSettleWait(uint8_t settleWaitCfg); 00776 00777 // Received Signal Strength Indicator (RSSI) and Link Quality Indicator (LQI) functions 00778 // ------------------------------------------------------------------------------ 00779 00780 private: 00781 // data from packet status bytes 00782 int8_t lastRSSI; 00783 uint8_t lastLQI; 00784 00785 public: 00786 00787 /** 00788 * Get the RSSI as of the last packet received. 00789 * Only provides valid data if appendStatus is enabled. 00790 * @return RSSI in dBm, or -128 if no valid RSSI measurement exists. 00791 */ 00792 int8_t getLastRSSI() {return lastRSSI;} 00793 00794 /** 00795 * Get the current RSSI from the RSSI register. Note: I think 00796 * this might only work while the radio is actively receiving. 00797 * 00798 * @return RSSI in dBm, or NaN if no valid RSSI measurement exists. 00799 */ 00800 float getRSSIRegister(); 00801 00802 /** 00803 * Set the RSSI gain adjustment. This value is added to the reported RSSI, and also used 00804 * in the calculation of the Carrier Sense (CS) line. 00805 * You have to calibrate this in a lab by feeding in a known amplitude signal, 00806 * see the user manual section 6.9 for details. 00807 */ 00808 void setRSSIOffset(int8_t adjust); 00809 00810 /** 00811 * Get the LQI from the LQI_VAL register. 00812 * This is a qualitative estimate from 1-128 of how easily a packet can be demodulated. 00813 * Lower is better, but 0 indicates invalid. 00814 * @return 00815 */ 00816 uint8_t getLQIRegister(); 00817 00818 /** 00819 * Get the LQI as of the last packet received. 00820 * Only provides valid data if appendStatus is enabled. 00821 * This is a qualitative estimate from 1-128 of how easily a packet can be demodulated. 00822 * Lower is better, but 0 indicates invalid. 00823 */ 00824 uint8_t getLastLQI() {return lastLQI;} 00825 00826 // Register level functions 00827 // ------------------------------------------------------------------------------ 00828 00829 /** 00830 * Read a register and return the byte value. Also reads the radio's state. 00831 */ 00832 uint8_t readRegister(Register reg); 00833 00834 /** 00835 * Write a register with a byte value. Also reads the radio's state. 00836 */ 00837 void writeRegister(Register reg, uint8_t value); 00838 00839 /** 00840 * Write a series of consecutive registers with byte values. Also reads the radio's state. 00841 */ 00842 void writeRegisters(CC1200::Register startReg, uint8_t const *values, size_t numRegisters); 00843 00844 /** 00845 * Write a series of consecutive registers with byte values. Also reads the radio's state. 00846 * Template version that takes an std::array. 00847 */ 00848 template<size_t numRegisters> 00849 void writeRegisters(CC1200::Register startReg, std::array<uint8_t, numRegisters> const & values) 00850 { 00851 writeRegisters(startReg, values.data(), values.size()); 00852 } 00853 00854 /** 00855 * Read an extended register and return the byte value. Also reads the radio's state. 00856 */ 00857 uint8_t readRegister(ExtRegister reg); 00858 00859 /** 00860 * Write an extended register with a byte value. Also reads the radio's state. 00861 */ 00862 void writeRegister(ExtRegister reg, uint8_t value); 00863 00864 /** 00865 * Write a series of consecutive extended registers with byte values. Also reads the radio's state. 00866 */ 00867 void writeRegisters(CC1200::ExtRegister startReg, uint8_t const *values, size_t numRegisters); 00868 00869 /** 00870 * Write a series of consecutive registers with byte values. Also reads the radio's state. 00871 * Template version that takes an std::array. 00872 */ 00873 template<size_t numRegisters> 00874 void writeRegisters(CC1200::ExtRegister startReg, std::array<uint8_t, numRegisters> const & values) 00875 { 00876 writeRegisters(startReg, values.data(), values.size()); 00877 } 00878 00879 00880 /** 00881 * Send a command. Also reads the radio's state. 00882 * @param command 00883 */ 00884 void sendCommand(Command command); 00885 00886 /** 00887 * Update the current known state of the radio. 00888 */ 00889 void updateState() { sendCommand(Command::NOP); } 00890 00891 /** 00892 * Get a byte from the RX FIFO. 00893 * @param address The byte address, from 0-127. 00894 */ 00895 uint8_t readRXFIFOByte(uint8_t address); 00896 00897 // State change functions 00898 // ------------------------------------------------------------------------------ 00899 00900 /** 00901 * Send the STX strobe to change the radio into TX state. 00902 * Valid when the radio is in IDLE, FAST_TX_ON, and RX. 00903 * A calibration will be performed if needed. 00904 * 00905 * The radio will stay in TX state until it is commanded to a different state, or a packet is 00906 * transmitted and it is configured to change states when this happens, or a FIFO error occurs (which 00907 * shouldn't be possible with the current configuration). 00908 */ 00909 void startTX() { sendCommand(Command::TX); } 00910 00911 /** 00912 * Send the SRX strobe to change the radio into TX state. 00913 * Valid when the radio is in IDLE, FAST_TX_ON, and TX. 00914 * A calibration will be performed if needed. 00915 * 00916 * The radio will stay in RX state until it is commanded to a different state, or a packet is 00917 * received and it configured to change states when this happens, or a FIFO overflow occurs 00918 * (because the host is not reading data out fast enough). 00919 */ 00920 void startRX() { sendCommand(Command::RX); } 00921 00922 /** 00923 * Send the radio into idle mode. Stops a currently running tx or rx. 00924 */ 00925 void idle() { sendCommand(Command::IDLE); } 00926 00927 private: 00928 00929 /** 00930 * Called whenever we get a status byte from another operation. Saves the info from it to member variables. 00931 * @param status 00932 */ 00933 void loadStatusByte(uint8_t status); 00934 }; 00935 00936 00937 #endif //LIGHTSPEEDRANGEFINDER_CC1200_H
Generated on Wed Jul 13 2022 05:17:38 by
1.7.2
CC1200