Jamie Smith / CC1200

Dependents:   CC1200-MorseEncoder CC1200-Examples

Files at this revision

API Documentation at this revision

Comitter:
Jamie Smith
Date:
Sun Aug 09 23:39:21 2020 -0700
Parent:
0:0c3532738887
Child:
2:2a447e8e50b8
Commit message:
Add a few new features, fix issue with reading from wrong FIFO

Changed in this revision

CC1200.cpp Show annotated file Show diff for this revision Revisions of this file
CC1200.h Show annotated file Show diff for this revision Revisions of this file
CC1200Bits.h Show annotated file Show diff for this revision Revisions of this file
--- a/CC1200.cpp	Tue Jun 30 02:26:28 2020 -0700
+++ b/CC1200.cpp	Sun Aug 09 23:39:21 2020 -0700
@@ -1,3 +1,5 @@
+#pragma clang diagnostic push
+#pragma ide diagnostic ignored "readability-magic-numbers"
 //
 // Created by jamie on 3/27/2020.
 //
@@ -283,11 +285,11 @@
 	writeRegister(Register::RFEND_CFG0, rfendCfg0);
 }
 
-void CC1200::setOnTransmitState(CC1200::State state)
+void CC1200::setOnTransmitState(CC1200::State txState)
 {
 	uint8_t rfendCfg0 = readRegister(Register::RFEND_CFG0);
 	rfendCfg0 &= ~(0b11 << RFEND_CFG0_TXOFF_MODE);
-	rfendCfg0 |= getOffModeBits(state) << RFEND_CFG0_TXOFF_MODE;
+	rfendCfg0 |= getOffModeBits(txState) << RFEND_CFG0_TXOFF_MODE;
 	writeRegister(Register::RFEND_CFG0, rfendCfg0);
 }
 
@@ -569,7 +571,7 @@
 	return CC1200_OSC_FREQ / (static_cast<float>(adcDecimation) * static_cast<float>(cicDecimation) * 2);
 }
 
-void CC1200::setRXFilterBandwidth(float bandwidthHz, bool isCC1201)
+void CC1200::setRXFilterBandwidth(float bandwidthHz)
 {
 	// settings that the chip supports
 	const uint8_t possibleADCDecimations[] = {12, 24, 48}; // indexes in this array represent the register value
@@ -629,6 +631,20 @@
 
 	writeRegister(Register::MDMCFG1, mdmCfg1Value);
 
+	// also set MDMCFG0.DATA_FILTER_EN, which should be 0b11 iff bandwidth / symbol rate > 10
+	uint8_t mdmCfg0Val = readRegister(Register::MDMCFG0);
+
+	if(bandwidthHz / symbolRateSps > 10.0f)
+	{
+		mdmCfg0Val |= 0b11 << MDMCFG0_DATA_FILTER_EN;
+	}
+	else
+	{
+		mdmCfg0Val &= ~(0b11 << MDMCFG0_DATA_FILTER_EN);
+	}
+
+	writeRegister(Register::MDMCFG0, mdmCfg0Val);
+
 	// finally, we need to set RX_CONFIG_LIMITATION.  It's not exactly clear what this does, but its setting changes
 	// based on the filter BW.
 	uint8_t syncCfg0Value = readRegister(Register::SYNC_CFG0);
@@ -716,6 +732,62 @@
 	writeRegister(Register::PREAMBLE_CFG1, preambleCfg1);
 }
 
+void CC1200::setPARampRate(uint8_t firstRampLevel, uint8_t secondRampLevel, CC1200::RampTime rampTime)
+{
+	uint8_t paCfg0Val = 0;
+	paCfg0Val |= (firstRampLevel << PA_CFG0_FIRST_IPL);
+	paCfg0Val |= (secondRampLevel << PA_CFG0_SECOND_IPL);
+	paCfg0Val |= (static_cast<uint8_t>(rampTime) << PA_CFG0_RAMP_SHAPE);
+
+	writeRegister(Register::PA_CFG0, paCfg0Val);
+}
+
+void CC1200::setAGCReferenceLevel(uint8_t level)
+{
+	writeRegister(Register::AGC_REF, level);
+}
+
+void CC1200::setAGCSyncBehavior(CC1200::SyncBehavior behavior)
+{
+	uint8_t agcCfg3Val = readRegister(Register::AGC_CFG3);
+	agcCfg3Val &= ~(0b111 << AGC_CFG3_AGC_SYNC_BEHAVIOUR);
+	agcCfg3Val |= static_cast<uint8_t>(behavior) << AGC_CFG3_AGC_SYNC_BEHAVIOUR;
+	writeRegister(Register::AGC_CFG3, agcCfg3Val);
+}
+
+void CC1200::setAGCGainTable(CC1200::GainTable table, uint8_t minGainIndex, uint8_t maxGainIndex)
+{
+	uint8_t agcCfg3Val = readRegister(Register::AGC_CFG3);
+	uint8_t agcCfg2Val = readRegister(Register::AGC_CFG2);
+
+	agcCfg3Val &= ~(0b11111 << AGC_CFG3_AGC_MIN_GAIN);
+	agcCfg2Val &= ~(0b11 << AGC_CFG2_FE_PERFORMANCE_MODE);
+	agcCfg2Val &= ~(0b11111 << AGC_CFG2_AGC_MAX_GAIN);
+
+	agcCfg3Val |= maxGainIndex << AGC_CFG3_AGC_MIN_GAIN;
+	agcCfg2Val |= static_cast<uint8_t>(table) << AGC_CFG2_FE_PERFORMANCE_MODE;
+	agcCfg2Val |= maxGainIndex << AGC_CFG2_AGC_MAX_GAIN;
+
+	writeRegister(Register::AGC_CFG3, agcCfg3Val);
+	writeRegister(Register::AGC_CFG2, agcCfg2Val);
+}
+
+void CC1200::setAGCHysteresis(uint8_t hysteresisCfg)
+{
+	uint8_t agcCfg0Val = readRegister(Register::AGC_CFG0);
+	agcCfg0Val &= ~(0b11 << AGC_CFG0_AGC_HYST_LEVEL);
+	agcCfg0Val |= hysteresisCfg << AGC_CFG0_AGC_HYST_LEVEL;
+	writeRegister(Register::AGC_CFG0, agcCfg0Val);
+}
+
+void CC1200::setAGCSlewRate(uint8_t slewrateCfg)
+{
+	uint8_t agcCfg0Val = readRegister(Register::AGC_CFG0);
+	agcCfg0Val &= ~(0b11 << AGC_CFG0_AGC_SLEWRATE_LIMIT);
+	agcCfg0Val |= slewrateCfg << AGC_CFG0_AGC_SLEWRATE_LIMIT;
+	writeRegister(Register::AGC_CFG0, agcCfg0Val);
+}
+
 void CC1200::setIFMixCFG(uint8_t value)
 {
 	uint8_t ifMixCfg = readRegister(ExtRegister::IF_MIX_CFG);
@@ -846,7 +918,7 @@
 {
 	spi.select();
 	loadStatusByte(spi.write(CC1200_READ | CC1200_MEM_ACCESS));
-	uint8_t value = spi.write(CC1200_TX_FIFO | address);
+	uint8_t value = spi.write(CC1200_RX_FIFO | address);
 	spi.deselect();
 
 #if CC1200_REGISTER_LEVEL_DEBUG
@@ -857,25 +929,4 @@
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+#pragma clang diagnostic pop
\ No newline at end of file
--- 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
 	// ------------------------------------------------------------------------------
 
--- a/CC1200Bits.h	Tue Jun 30 02:26:28 2020 -0700
+++ b/CC1200Bits.h	Sun Aug 09 23:39:21 2020 -0700
@@ -108,4 +108,20 @@
 #define PREAMBLE_CFG0_PQT_VALID_TIMEOUT 4
 #define PREAMBLE_CFG0_PQT 0
 
+#define AGC_CFG3_AGC_SYNC_BEHAVIOUR 5
+#define AGC_CFG3_AGC_MIN_GAIN 0
+
+#define AGC_CFG2_START_PREVIOUS_GAIN_EN 7
+#define AGC_CFG2_FE_PERFORMANCE_MODE 5
+#define AGC_CFG2_AGC_MAX_GAIN 0
+
+#define AGC_CFG1_RSSI_STEP_THR 6
+#define AGC_CFG1_AGC_WIN_SIZE 3
+#define AGC_CFG1_AGC_SETTLE_WAIT 0
+
+#define AGC_CFG0_AGC_HYST_LEVEL 6
+#define AGC_CFG0_AGC_SLEWRATE_LIMIT 4
+#define AGC_CFG0_RSSI_VALID_CNT 2
+#define AGC_CFG0_AGC_ASK_DECAY 0
+
 #endif //LIGHTSPEEDRANGEFINDER_CC1200BITS_H