Driver for TI's CC1200 radio ICs. Forget hardcoded register settings -- this driver calculates everything from scratch!

Dependents:   CC1200-MorseEncoder CC1200-Examples

CC1200 Driver

by Jamie Smith / USC Rocket Propulsion Lab

After months of work, we are proud to present our driver for Texas Instruments' CC1200 digital radio IC! This driver has been written from scratch to be an easy and flexible way of using this radio transceiver. For our application, we needed to be able to tune each and every setting of the radio to try and eke that last bit of performance of our system - so using premade configurations alone wasn't going to cut it! Instead, this driver calculates each parameter of the radio using the equations and instructions given in the datasheet. So, you can tweak parameters to your heart's content, and you shouldn't have to do any math yourself!

Features

  • Automatic calculation of correct register values for:
    • RF frequency
    • FSK deviation
    • Symbol rate
    • Output power
    • RX filter bandwidth (this one's harder than it looks!)
  • Easy handling of data packets
  • GPIO configuration
  • Preamble and sync word configuration
  • RTOS compatible (always locks SPI bus during transactions)
  • Two debug levels available
  • RSSI and LQI support

Not Supported

  • Transparent mode
  • FM mode
  • ASK parameter configuration
  • Frequency offsets

Examples

  • See the example project here for an example of how to use the driver.
  • Another example (using a more exotic configuration) is the CC1200-MorseEncoder.

Changelog

Version 1.2 May 3 2021

  • Added unfinished infinite length packet support via the readStream() and writeStream() functions. The API is complete and basic usage works but there's still a bug I haven't been able to track down yet where incorrect data is transmitted at the end of a stream. Use with caution!
  • Added preferHigherCICDec parameter to setRXFilterBandwidth
  • Removed setIFMixCFG() (which takes a byte parameter) and replaced it with setIFCfg(), which takes documented enum class values.
  • Added setAGCSettleWait(), which per my testing is needed for correct 430MHz operation.
  • Added support for reading RSSI and LQI values, both from packet appended status bytes and from the registers.
  • Update 430MHz black box registers based on SmartRF values
  • Removed setIQMismatchCompensationEnabled(). This call has been replaced by the new 2nd parameter to setIFCfg().

Version 1.1 Aug 28 2020

  • Add fixed length packet support and other features needed for Morse support.
  • Fix bug causing weird behavior with low sample rates (<1ksps).

NOTE: you must now call setPacketMode() when configuring the radio.

Version 1.0 Aug 10 2020

Initial Release

Revision:
1:98af824b145e
Parent:
0:0c3532738887
Child:
2:2a447e8e50b8
--- a/CC1200.h	Tue Jun 30 02:26:28 2020 -0700
+++ b/CC1200.h	Sun Aug 09 23:39:21 2020 -0700
@@ -174,7 +174,7 @@
 private:
 	// chip data variables
 	bool chipReady = false;
-	State state;
+	State state = State::IDLE;
 	bool isCC1201;
 
 	// current state variables
@@ -284,10 +284,10 @@
 
 	/**
 	 * Set what state the radio will enter when a packet is sent.
-	 * @param state State when a packet is transmitted.
+	 * @param txState State when a packet is transmitted.
 	 * Accepts State::TX, State::IDLE, State::FAST_TX_ON, and State::RX.
 	 */
-	void setOnTransmitState(State state);
+	void setOnTransmitState(State txState);
 
 	enum class FSCalMode : uint8_t
 	{
@@ -406,10 +406,17 @@
 	 * NOTE: The symbol rate and the RX filter bandwidth must be compatible with each other.
 	 * See the user guide for details.
 	 *
+	 * A number of different registers must be configured in order to properly configure the radio for a given bandwidth.
+	 * This call currently sets the following register fields:
+	 * - CHAN_BW.ADC_CIC_DECFACT
+	 * - CHAN_BW.BB_CIC_DECFACT
+	 * - MDMCFG1.DVGA_GAIN
+	 * - MDMCFG0.DATA_FILTER_EN
+	 * - SYNC_CFG0.RX_CONFIG_LIMITATION
+	 *
 	 * @param bandwidthHz the bandwidth in Hz
-	 * @param isCC1201 whether the current chip is a CC1201 instead of a CC1200.  The CC1201 has a more limited set of valid bandwidth settings.
 	 */
-	void setRXFilterBandwidth(float bandwidthHz, bool isCC1201 = false);
+	void setRXFilterBandwidth(float bandwidthHz);
 
 	/**
 	 * Get the ADC CIC decimation that was calculated by the most recent setRXFilterBandwidth() call.
@@ -492,6 +499,90 @@
 	 */
 	void configurePreamble(uint8_t preambleLengthCfg, uint8_t preambleFormatCfg);
 
+	/**
+	 * Enum for different PA ramp times.
+	 */
+	enum class RampTime : uint8_t
+	{
+		RAMP_3_8_SYMBOL = 0b0,
+		RAMP_3_2_SYMBOL = 0b1,
+		RAMP_3_SYMBOL = 0b10,
+		RAMP_6_SYMBOL = 0b11
+	};
+
+	/**
+	 * Set the length and shape of the power amplifier ramp-up curve.
+	 * See section 7.1 for details.
+	 *
+	 * The PA will gradually ramp from off to full amplitude in rampTime relative to the
+	 * symbol rate.  At 1/3 of rampTime it will have ramped to (firstRampLevel / 16) * full amplitude,
+	 * and at 2/3 of rampTime it will have ramped to ((secondRampLevel + 7) / 16) * full amplitude.
+	 */
+	void setPARampRate(uint8_t firstRampLevel, uint8_t secondRampLevel, RampTime rampTime);
+
+	// Automatic Gain Control (AGC) Config
+	// ------------------------------------------------------------------------------
+
+	/**
+	 * Set the AGC reference level which is the internal target power level that
+	 * the AGC tries to adjust to.
+	 *
+	 * The user manual section 6.4 gives a rough formula to calculate this, but I've just used the SmartRF values.
+	 *
+	 * @param level Internal power level in dB.
+	 */
+	void setAGCReferenceLevel(uint8_t level);
+
+	/**
+	 * Enum for possible AGC actions after is a sync word detection.
+	 * See AGC_CFG3 register description for more info.
+	 */
+	enum class SyncBehavior : uint8_t
+	{
+		FREEZE_NONE = 0b000,
+		FREEZE_GAIN = 0b001,
+		AGC_SLOWMODE = 0b010,
+		FREEZE_BOTH = 0b011
+	};
+
+	/**
+	 * Set the AGC behavior after a sync word is detected.
+	 * @param behavior
+	 */
+	void setAGCSyncBehavior(SyncBehavior behavior);
+
+	/**
+	 * Enum for possible gain tables to use.
+	 * See AGC_CFG2 register description for more info.
+	 */
+	enum class GainTable : uint8_t
+	{
+		OPTIMIZED_LINEARITY = 0b00,
+		NORMAL = 0b01,
+		LOW_POWER = 0b10,
+		ZERO_IF = 0b11
+	};
+
+	/**
+	 * Set the gain table and min and max values within that table to use.
+	 * Min and max values are indexes into the current selected table.
+	 */
+	void setAGCGainTable(GainTable table, uint8_t minGainIndex, uint8_t maxGainIndex);
+
+	/**
+	 * Configure the change in input signal power that must be sensed before the AGC starts to adjust itself.
+	 * See the register description for AGC_CFG0.AGC_HYST_LEVEL
+	 * @param hysteresisCfg
+	 */
+	void setAGCHysteresis(uint8_t hysteresisCfg);
+
+	/**
+	 * Configure the rate that the AGC changes the receive gain.
+	 * See the register description for AGC_CFG0.AGC_SLEWRATE_LIMIT
+	 * @param slewrateCfg
+	 */
+	void setAGCSlewRate(uint8_t slewrateCfg);
+
 	// Register level functions
 	// ------------------------------------------------------------------------------