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:
4:c609cc7c9ea7
Parent:
2:2a447e8e50b8
Child:
5:d22a8885800b
--- a/CC1200.h	Mon Aug 10 01:47:24 2020 -0700
+++ b/CC1200.h	Fri Aug 28 15:39:31 2020 -0700
@@ -236,8 +236,10 @@
 	 * Enqueue a packet to be sent over the radio.  It will be sent the next time the radio is in
 	 * transmit state.
 	 *
-	 * The length of a packet is variable, from 1 byte to 127 bytes.  The length will be transmitted
-	 * along with the packet data.
+	 * In variable length mode, the length of a packet is variable, from 1 byte to 127 bytes.
+	 * The length will be transmitted along with the packet data.
+	 *
+	 * In fixed length mode, the length should be the fixed packet length.
 	 *
 	 * Also reads the radio's state.
 	 *
@@ -345,6 +347,54 @@
 	 */
 	void configureFIFOMode();
 
+	enum class PacketMode : uint8_t
+	{
+		/// Use fixed length packets.
+		VARIABLE_LENGTH = 0b1,
+		/// Use variable length packets, the length is encoded in the first byte of the packet.
+		FIXED_LENGTH = 0b0
+	};
+
+	/**
+	 * Set the packet mode that the system will use
+	 * @param mode
+	 */
+	void setPacketMode(PacketMode mode);
+
+	/**
+	 * Set the packet length when in fixed length packet mode.
+	 * The bit length parameter can be used to send only the x most significant bits of the final byte.
+	 * For example, if your packets are 20 bits long, you should set length to 2 bytes and bitLength to
+	 * 4 bytes, so that 2 complete bytes + 4 extra bits are transmitted.  Buffers used for sending and receiving packets
+	 * should then be 3 bytes long.
+	 * @param length
+	 */
+	void setPacketLength(uint8_t length, uint8_t bitLength = 0);
+
+private:
+	// current packet mode
+	PacketMode _packetMode;
+
+	// current packet length when in fixed length packet mode
+	uint8_t _packetTotalLength = 0; // length in bytes including final partial byte
+	uint8_t _packetByteLength = 0; // length in whole bytes
+	uint8_t _packetBitLength = 0; // extra bit length at end
+
+public:
+
+	/**
+	 * Set whether the CRC check is enabled.  This driver enables it by default.
+	 * Enabling CRC will cause a 16 bit checksum to be transmitted along with the packet.
+	 * It will be automatically checked by the receiving CC1200, and the packet will be discarded if the CRC
+	 * doesn't match.
+	 *
+	 * NOTE: it is not recommended to disable the CRC when using variable length mode.
+	 * If the length byte is corrupted and the CRC doesn't check this, then the driver could read
+	 * too little or too much from the chip's FIFO and cause the chip to enter the FIFO underflow state.
+	 * @param enabled
+	 */
+	void setCRCEnabled(bool enabled);
+
 	enum class ModFormat : uint8_t
 	{
 		FSK_2 = 0x0,
@@ -380,6 +430,18 @@
 	 */
 	void setOutputPower(float outPower);
 
+	// min power to use to turn the radio completely off
+	const static float ASK_MIN_POWER_OFF;
+
+	/**
+	 * Set the high and low output powers when transmitting in ASK mode.
+	 * Overrides the setOutputPower() power setting.
+	 * @param maxPower High output power.  Must be between -16dBm and +14dBm.
+	 * @param minPower Low output power.  Must be between maxPower and -17.5dBm.  -17.5dBm gives completely off,
+	 *     so OOK modulation instead of ASK.
+	 */
+	void setASKPowers(float maxPower, float minPower);
+
 	// Radio band for the chip to operate on.
 	// See user guide description for FS_CFG register.
 	enum class Band : uint8_t
@@ -514,8 +576,9 @@
 	};
 
 	/**
-	 * Set the length and shape of the power amplifier ramp-up curve.
+	 * Enable the the power amplifier ramp-up curve and set its shape and time.
 	 * See section 7.1 for details.
+	 * This is also used to set the ASK ramping between different power levels.
 	 *
 	 * 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,
@@ -523,6 +586,11 @@
 	 */
 	void setPARampRate(uint8_t firstRampLevel, uint8_t secondRampLevel, RampTime rampTime);
 
+	/**
+	 * Disable the power amplifier ramp-up curve.
+	 */
+	void disablePARamping();
+
 	// Automatic Gain Control (AGC) Config
 	// ------------------------------------------------------------------------------
 
@@ -682,6 +750,11 @@
 	 */
 	void startRX() { sendCommand(Command::RX); }
 
+	/**
+	 * Send the radio into idle mode.  Stops a currently running tx or rx.
+	 */
+	void idle() { sendCommand(Command::IDLE); }
+
 private:
 
 	/**