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
Diff: CC1200.h
- Revision:
- 5:d22a8885800b
- Parent:
- 4:c609cc7c9ea7
--- a/CC1200.h Fri Aug 28 15:39:31 2020 -0700 +++ b/CC1200.h Mon May 03 02:41:34 2021 -0700 @@ -125,6 +125,11 @@ XOSC1 = 0x36, XOSC0 = 0x37, //... + RSSI1 = 0x71, + RSSI0 = 0x72, + MARCSTATE = 0x73, + LQI_VAL = 0x74, + //... FREQOFF_EST1 = 0x77, FREQOFF_EST2 = 0x78, //... @@ -185,8 +190,13 @@ // current symbol rate of the radio float symbolRateSps = 0; - // current ADC CIC decimation of the radio + // current RX filter params uint8_t adcCicDecimation = 0; + float currentRXFilterBW = 0; + + // current RF params + float radioFreqHz; + public: @@ -241,6 +251,8 @@ * * In fixed length mode, the length should be the fixed packet length. * + * The function is not for use with infinite-length mode, use writeStream() instead. + * * Also reads the radio's state. * * @param data @@ -253,6 +265,7 @@ /** * Check whether there is at least one complete packet in the RX FIFO. + * In infinite length mode, this returns true if any data is present at all. * NOTE: An alternate way to do this using hardware is to configure one * of the CC1200's GPIOs as PKT_SYNC_RXTX, then set a falling edge interrupt to receive a packet. * @return @@ -268,6 +281,8 @@ * in the FIFO, *undefined behavior* can occur. An arbitrary amount of data will be read from * the FIFO and garbage may be returned. * + * The function is not for use with infinite-length mode, use readStream() instead. + * * NOTE: A null terminator is NOT added unless it was present in the transmitted data. * Be careful when treating the returned data as a string! * @@ -278,6 +293,78 @@ */ size_t receivePacket(char * buffer, size_t bufferLen); + // Infinite length tx & rx functions + // ------------------------------------------------------------------------------ + + /* + * How to use infinite length from the TX side: + * 1. Place up to 128 bytes of data in the TX FIFO for transmission using writeStream(). + * 2. Enable TX mode using startTX() + * 3. Keep streaming in data using writeStream() writeStreamBlocking() or at least as fast as it is transmitted. + * 4. Disable TX mode when done using idle(). + * + * Take care that the TX fifo never runs completely out of data, or the chip will go into TX FIFO ERROR state. + */ + + /* + * How to use infinite length from the RX side: + * 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. + * 2. Wait for data to arrive using hasReceivedPacket(). + * 3. Start streaming out data using readStream() or readStreamBlocking(). + * 4. Disable RX mode when done using idle(). + * + * Take care that the RX fifo doesn't become full, or the chip will go into RX FIFO ERROR state. + */ + + /** + * Write a stream of data to the chip. This function is only for use in infinite-length mode. + * As many bytes from the given buffer will be written as can fit in the chip's FIFO. + * If the FIFO is full, this function does nothing. + * + * @param buffer + * @param count + * @return Number of bytes written. + */ + size_t writeStream(const char* buffer, size_t count); + + /** + * Write a stream of data to the chip. This function is only for use in infinite-length mode. + * Will block until all bytes in the given buffer have been written to the TX FIFO, or an error has been + * detected (the radio switches to any state other than TX). + * + * @param buffer + * @param count + * @return True if successful, false if there was an error. + */ + bool writeStreamBlocking(const char* buffer, size_t count); + + /** + * Read up to maxLen bytes into buffer. + * @param buffer + * @param maxLen + * @return How many bytes were actually read. 0 if the RX FIFO was empty. + */ + size_t readStream(char* buffer, size_t maxLen); + + /** + * Read a stream of data from the chip. This function is only for use in infinite-length mode. + * Will block until the buffer was filled, an error has been + * detected (the radio switches to any state other than RX), or the timeout expires. + * + * If false is returned, some data may have been written to the buffer, and the rest will not have been modified. + * + * Note: if using a zero timeout, this function could cause a hang if the transmitter stops transmitting. + * + * @param buffer + * @param count + * @param timeout Timeout, or 0us to disable timeout. + * @return True iff the buffer was completely filled. + */ + bool readStreamBlocking(char* buffer, size_t count, std::chrono::microseconds timeout=0us); + + // State transition configuration + // ------------------------------------------------------------------------------ + /** * Set what state the radio will enter when a packet is received. * @param goodPacket State when a good (CRC pass) packet is received. @@ -349,6 +436,8 @@ enum class PacketMode : uint8_t { + /// Use infinite length transmissions (streaming mode). + INFINITE_LENGTH = 0b10, /// Use fixed length packets. VARIABLE_LENGTH = 0b1, /// Use variable length packets, the length is encoded in the first byte of the packet. @@ -356,10 +445,12 @@ }; /** - * Set the packet mode that the system will use + * Set the packet mode that the system will use. * @param mode + * @param appendStatus Have the radio append a status byte to each packet received. This takes up + * 2 bytes per packet in the RX FIFO, but provides status information about each packet. */ - void setPacketMode(PacketMode mode); + void setPacketMode(PacketMode mode, bool appendStatus = false); /** * Set the packet length when in fixed length packet mode. @@ -367,19 +458,24 @@ * 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. + * + * When appendStatus is disabled, the max length is 256 bytes. When it is enabled, the max length is 254 bytes. * @param length */ - void setPacketLength(uint8_t length, uint8_t bitLength = 0); + void setPacketLength(uint16_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 + uint16_t _packetTotalLength = 0; // length in bytes including final partial byte + uint16_t _packetByteLength = 0; // length in whole bytes uint8_t _packetBitLength = 0; // extra bit length at end + // Whether the two status bytes are included in each received packet + bool appendStatusEnabled = true; + public: /** @@ -480,8 +576,10 @@ * - SYNC_CFG0.RX_CONFIG_LIMITATION * * @param bandwidthHz the bandwidth in Hz + * @param preferHigherCICDec If there are multiple register value choices, prefer the one with higher CIC decimation + * and lower BB decimation. This is the recommendation of the datasheet but it actually causes transmission to fail in some cases. */ - void setRXFilterBandwidth(float bandwidthHz); + void setRXFilterBandwidth(float bandwidthHz, bool preferHigherCICDec = true); /** * Get the ADC CIC decimation that was calculated by the most recent setRXFilterBandwidth() call. @@ -491,7 +589,7 @@ uint8_t getADCCICDecimation() { return adcCicDecimation; } /** - * Configure the radio's automatic DC offset removal algorithm is enabled. + * Configure the radio's automatic DC offset removal algorithm as enabled. * DC offset correction must be enabled when using zero IF mode, and in my testing * it seems to be important when staying in TX mode for a long time at * higher sample rates. @@ -506,17 +604,32 @@ void configureDCFilter(bool enableAutoFilter, uint8_t settlingCfg, uint8_t cutoffCfg); /** - * Set the IF mixing configuration. + * Possible intermediate frequency values. + * For right now it seems like you have to get these from SmartRF. * See the user guide section on IF_MIX_CFG.CMIX_CFG for details. */ - void setIFMixCFG(uint8_t value); + enum class IFCfg : uint8_t + { + ZERO = 0, // Zero IF. From what I can find, this means samples are taken at the radio frequency. + NEGATIVE_DIV_4 = 0b001, + NEGATIVE_DIV_6 = 0b010, + NEGATIVE_DIV_8 = 0b011, + POSITIVE_DIV_4 = 0b101, + POSITIVE_DIV_6 = 0b110, + POSITIVE_DIV_8 = 0b111 + }; /** - * Set whether the ImageExtinct IQ mismatch compensation logic is enabled. - * This should be disabled if IF < RX filter bandwidth - * @param enabled + * Set the receiver IF mixing configuration. + * See the user guide section on IF_MIX_CFG.CMIX_CFG for details. + * + * You must call *both* setRXFilterBandwidth() and setRadioFrequency() before calling this function. + * + * @param value Divider value to use, or zero-IF + * @param enableIQIC Whether to enable the ImageExtinct IQ mismatch compensation when supported + * (when if IF > RX filter bandwidth). */ - void setIQMismatchCompensationEnabled(bool enabled); + void setIFCfg(IFCfg value, bool enableIQIC); /** * Mode describing the size and setup of the sync word. @@ -654,6 +767,62 @@ */ void setAGCSlewRate(uint8_t slewrateCfg); + /** + * Configure the time that the AGC takes to settle. + * See the register description for AGC_CFG1.AGC_SETTLE_WAIT + * @param settleWaitCfg bytes to write to AGC_CFG1.AGC_SETTLE_WAIT + */ + void setAGCSettleWait(uint8_t settleWaitCfg); + + // Received Signal Strength Indicator (RSSI) and Link Quality Indicator (LQI) functions + // ------------------------------------------------------------------------------ + +private: + // data from packet status bytes + int8_t lastRSSI; + uint8_t lastLQI; + +public: + + /** + * Get the RSSI as of the last packet received. + * Only provides valid data if appendStatus is enabled. + * @return RSSI in dBm, or -128 if no valid RSSI measurement exists. + */ + int8_t getLastRSSI() {return lastRSSI;} + + /** + * Get the current RSSI from the RSSI register. Note: I think + * this might only work while the radio is actively receiving. + * + * @return RSSI in dBm, or NaN if no valid RSSI measurement exists. + */ + float getRSSIRegister(); + + /** + * Set the RSSI gain adjustment. This value is added to the reported RSSI, and also used + * in the calculation of the Carrier Sense (CS) line. + * You have to calibrate this in a lab by feeding in a known amplitude signal, + * see the user manual section 6.9 for details. + */ + void setRSSIOffset(int8_t adjust); + + /** + * Get the LQI from the LQI_VAL register. + * This is a qualitative estimate from 1-128 of how easily a packet can be demodulated. + * Lower is better, but 0 indicates invalid. + * @return + */ + uint8_t getLQIRegister(); + + /** + * Get the LQI as of the last packet received. + * Only provides valid data if appendStatus is enabled. + * This is a qualitative estimate from 1-128 of how easily a packet can be demodulated. + * Lower is better, but 0 indicates invalid. + */ + uint8_t getLastLQI() {return lastLQI;} + // Register level functions // ------------------------------------------------------------------------------