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

Committer:
Jamie Smith
Date:
Tue Jun 30 02:26:28 2020 -0700
Revision:
0:0c3532738887
Child:
1:98af824b145e
Add initial version of driver

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jamie Smith 0:0c3532738887 1 //
Jamie Smith 0:0c3532738887 2 // Created by jamie on 3/27/2020.
Jamie Smith 0:0c3532738887 3 //
Jamie Smith 0:0c3532738887 4
Jamie Smith 0:0c3532738887 5 #include "CC1200.h"
Jamie Smith 0:0c3532738887 6 #include "CC1200Bits.h"
Jamie Smith 0:0c3532738887 7
Jamie Smith 0:0c3532738887 8 #include <cinttypes>
Jamie Smith 0:0c3532738887 9 #include <cmath>
Jamie Smith 0:0c3532738887 10
Jamie Smith 0:0c3532738887 11 // change to 1 to print debug info
Jamie Smith 0:0c3532738887 12 #define CC1200_DEBUG 1
Jamie Smith 0:0c3532738887 13
Jamie Smith 0:0c3532738887 14 // change to 1 to print register read/write level debug info
Jamie Smith 0:0c3532738887 15 #define CC1200_REGISTER_LEVEL_DEBUG 0
Jamie Smith 0:0c3532738887 16
Jamie Smith 0:0c3532738887 17 // miscellaneous constants
Jamie Smith 0:0c3532738887 18 #define CC1200_READ (1 << 7) // SPI initial byte flag indicating read
Jamie Smith 0:0c3532738887 19 #define CC1200_WRITE 0 // SPI initial byte flag indicating write
Jamie Smith 0:0c3532738887 20 #define CC1200_BURST (1 << 6) // SPI initial byte flag indicating burst access
Jamie Smith 0:0c3532738887 21
Jamie Smith 0:0c3532738887 22 // SPI commands to access data buffers. Can be used with CC1200_BURST.
Jamie Smith 0:0c3532738887 23 #define CC1200_ENQUEUE_TX_FIFO 0x3F
Jamie Smith 0:0c3532738887 24 #define CC1200_DEQUEUE_RX_FIFO 0xBF
Jamie Smith 0:0c3532738887 25
Jamie Smith 0:0c3532738887 26 // SPI command to access FIFO memory (or several other areas depending on mode)
Jamie Smith 0:0c3532738887 27 #define CC1200_MEM_ACCESS 0x3E
Jamie Smith 0:0c3532738887 28
Jamie Smith 0:0c3532738887 29 #define CC1200_RX_FIFO (1 << 7) // address flag to access RX FIFO
Jamie Smith 0:0c3532738887 30 #define CC1200_TX_FIFO 0 // address flag to access TX FIFO
Jamie Smith 0:0c3532738887 31
Jamie Smith 0:0c3532738887 32
Jamie Smith 0:0c3532738887 33 #define CC1200_PART_NUMBER ((uint8_t)0x20) // part number we expect the chip to read
Jamie Smith 0:0c3532738887 34 #define CC1201_PART_NUMBER ((uint8_t)0x21)
Jamie Smith 0:0c3532738887 35 #define CC1200_EXT_ADDR 0x2F // SPI initial byte address indicating extended register space
Jamie Smith 0:0c3532738887 36
Jamie Smith 0:0c3532738887 37 #define SPI_MODE 0
Jamie Smith 0:0c3532738887 38 #define SPI_FREQ 5000000 // hz
Jamie Smith 0:0c3532738887 39 // NOTE: the chip supports a higher frequency for most operations but reads to extended registers require a lower frequency
Jamie Smith 0:0c3532738887 40
Jamie Smith 0:0c3532738887 41 // frequency of the chip's crystal oscillator
Jamie Smith 0:0c3532738887 42 #define CC1200_OSC_FREQ 40000000 // hz
Jamie Smith 0:0c3532738887 43 #define CC1200_OSC_FREQ_LOG2 25.253496f // log2 of above number
Jamie Smith 0:0c3532738887 44
Jamie Smith 0:0c3532738887 45 // length of the TX and RX FIFOS
Jamie Smith 0:0c3532738887 46 #define CC1200_FIFO_SIZE 128
Jamie Smith 0:0c3532738887 47
Jamie Smith 0:0c3532738887 48 // maximum length of the packets we can send, including the length byte which we add.
Jamie Smith 0:0c3532738887 49 // Since the TX and RX FIFOs are 128 bytes, supporting packet lengths longer than 128 bytes
Jamie Smith 0:0c3532738887 50 // requires streaming bytes in during the transmission, which would make things complicated.
Jamie Smith 0:0c3532738887 51 #define MAX_PACKET_LENGTH 128
Jamie Smith 0:0c3532738887 52
Jamie Smith 0:0c3532738887 53 // utility function: compile-time power calculator.
Jamie Smith 0:0c3532738887 54 // Works on all signed and unsigned integer types for T.
Jamie Smith 0:0c3532738887 55 // from: http://prosepoetrycode.potterpcs.net/2015/07/a-simple-constexpr-power-function-c/
Jamie Smith 0:0c3532738887 56 template <typename T>
Jamie Smith 0:0c3532738887 57 constexpr T constexpr_pow(T num, unsigned int pow)
Jamie Smith 0:0c3532738887 58 {
Jamie Smith 0:0c3532738887 59 return pow == 0 ? 1 : num * constexpr_pow(num, pow-1);
Jamie Smith 0:0c3532738887 60 }
Jamie Smith 0:0c3532738887 61
Jamie Smith 0:0c3532738887 62 // power of two constants
Jamie Smith 0:0c3532738887 63 const float twoToThe16 = constexpr_pow(2.0f, 16);
Jamie Smith 0:0c3532738887 64 const float twoToThe20 = constexpr_pow(2.0f, 20);
Jamie Smith 0:0c3532738887 65 const float twoToThe21 = constexpr_pow(2.0f, 21);
Jamie Smith 0:0c3532738887 66 const float twoToThe22 = constexpr_pow(2.0f, 22);
Jamie Smith 0:0c3532738887 67 const float twoToThe38 = constexpr_pow(2.0f, 38);
Jamie Smith 0:0c3532738887 68 const float twoToThe39 = constexpr_pow(2.0f, 39);
Jamie Smith 0:0c3532738887 69
Jamie Smith 0:0c3532738887 70 // binary value size constants
Jamie Smith 0:0c3532738887 71 const size_t maxValue3Bits = constexpr_pow(2, 3) - 1;
Jamie Smith 0:0c3532738887 72 const size_t maxValue4Bits = constexpr_pow(2, 4) - 1;
Jamie Smith 0:0c3532738887 73 const size_t maxValue8Bits = constexpr_pow(2, 8) - 1;
Jamie Smith 0:0c3532738887 74 const size_t maxValue20Bits = constexpr_pow(2, 20) - 1;
Jamie Smith 0:0c3532738887 75 const size_t maxValue24Bits = constexpr_pow(2, 24) - 1;
Jamie Smith 0:0c3532738887 76
Jamie Smith 0:0c3532738887 77 CC1200::CC1200(PinName mosiPin, PinName misoPin, PinName sclkPin, PinName csPin, PinName rstPin, Stream * _debugStream, bool _isCC1201):
Jamie Smith 0:0c3532738887 78 spi(mosiPin, misoPin, sclkPin, csPin, use_gpio_ssel),
Jamie Smith 0:0c3532738887 79 rst(rstPin, 1),
Jamie Smith 0:0c3532738887 80 debugStream(_debugStream),
Jamie Smith 0:0c3532738887 81 isCC1201(_isCC1201)
Jamie Smith 0:0c3532738887 82 {
Jamie Smith 0:0c3532738887 83 spi.format(8, SPI_MODE);
Jamie Smith 0:0c3532738887 84 spi.frequency(SPI_FREQ);
Jamie Smith 0:0c3532738887 85 }
Jamie Smith 0:0c3532738887 86
Jamie Smith 0:0c3532738887 87 bool CC1200::begin()
Jamie Smith 0:0c3532738887 88 {
Jamie Smith 0:0c3532738887 89 chipReady = false;
Jamie Smith 0:0c3532738887 90
Jamie Smith 0:0c3532738887 91 // reset
Jamie Smith 0:0c3532738887 92 rst.write(0);
Jamie Smith 0:0c3532738887 93 wait_us(100);
Jamie Smith 0:0c3532738887 94 rst.write(1);
Jamie Smith 0:0c3532738887 95
Jamie Smith 0:0c3532738887 96 const float resetTimeout = .01f;
Jamie Smith 0:0c3532738887 97 Timer timeoutTimer;
Jamie Smith 0:0c3532738887 98 timeoutTimer.start();
Jamie Smith 0:0c3532738887 99
Jamie Smith 0:0c3532738887 100 while(!chipReady)
Jamie Smith 0:0c3532738887 101 {
Jamie Smith 0:0c3532738887 102 // datasheet specifies 240us reset time
Jamie Smith 0:0c3532738887 103 wait_us(250);
Jamie Smith 0:0c3532738887 104 updateState();
Jamie Smith 0:0c3532738887 105
Jamie Smith 0:0c3532738887 106 if(timeoutTimer.read() > resetTimeout)
Jamie Smith 0:0c3532738887 107 {
Jamie Smith 0:0c3532738887 108 debugStream->printf("Timeout waiting for ready response from CC1200\n");
Jamie Smith 0:0c3532738887 109 return false;
Jamie Smith 0:0c3532738887 110 }
Jamie Smith 0:0c3532738887 111 }
Jamie Smith 0:0c3532738887 112
Jamie Smith 0:0c3532738887 113 // read ID register
Jamie Smith 0:0c3532738887 114 uint8_t partNumber = readRegister(ExtRegister::PARTNUMBER);
Jamie Smith 0:0c3532738887 115 uint8_t partVersion = readRegister(ExtRegister::PARTVERSION);
Jamie Smith 0:0c3532738887 116
Jamie Smith 0:0c3532738887 117 uint8_t expectedPartNumber = isCC1201 ? CC1201_PART_NUMBER : CC1200_PART_NUMBER;
Jamie Smith 0:0c3532738887 118 if(partNumber != expectedPartNumber)
Jamie Smith 0:0c3532738887 119 {
Jamie Smith 0:0c3532738887 120 debugStream->printf("Read incorrect part number 0x%" PRIx8 " from CC1200, expected 0x%" PRIx8 "\n", partNumber, expectedPartNumber);
Jamie Smith 0:0c3532738887 121 return false;
Jamie Smith 0:0c3532738887 122 }
Jamie Smith 0:0c3532738887 123
Jamie Smith 0:0c3532738887 124 #if CC1200_DEBUG
Jamie Smith 0:0c3532738887 125 debugStream->printf("Detected CC1200, Part Number 0x%" PRIx8 ", Hardware Version %" PRIx8 "\n", partNumber, partVersion);
Jamie Smith 0:0c3532738887 126 #endif
Jamie Smith 0:0c3532738887 127
Jamie Smith 0:0c3532738887 128
Jamie Smith 0:0c3532738887 129 // Set packet format settings for this driver
Jamie Smith 0:0c3532738887 130 // ------------------------------------------------------------------------
Jamie Smith 0:0c3532738887 131
Jamie Smith 0:0c3532738887 132 // enable CRC but disable status bytes
Jamie Smith 0:0c3532738887 133 writeRegister(Register::PKT_CFG1, (0b01 << PKT_CFG1_CRC_CFG));
Jamie Smith 0:0c3532738887 134
Jamie Smith 0:0c3532738887 135 // configure packet length to adjustable
Jamie Smith 0:0c3532738887 136 writeRegister(Register::PKT_CFG0, (0b01 << PKT_CFG0_LENGTH_CONFIG));
Jamie Smith 0:0c3532738887 137
Jamie Smith 0:0c3532738887 138 // set max packet length
Jamie Smith 0:0c3532738887 139 writeRegister(Register::PKT_LEN, MAX_PACKET_LENGTH);
Jamie Smith 0:0c3532738887 140
Jamie Smith 0:0c3532738887 141
Jamie Smith 0:0c3532738887 142 return true;
Jamie Smith 0:0c3532738887 143 }
Jamie Smith 0:0c3532738887 144
Jamie Smith 0:0c3532738887 145 size_t CC1200::getTXFIFOLen()
Jamie Smith 0:0c3532738887 146 {
Jamie Smith 0:0c3532738887 147 return readRegister(ExtRegister::NUM_TXBYTES);
Jamie Smith 0:0c3532738887 148 }
Jamie Smith 0:0c3532738887 149
Jamie Smith 0:0c3532738887 150 size_t CC1200::getRXFIFOLen()
Jamie Smith 0:0c3532738887 151 {
Jamie Smith 0:0c3532738887 152 return readRegister(ExtRegister::NUM_RXBYTES);
Jamie Smith 0:0c3532738887 153 }
Jamie Smith 0:0c3532738887 154
Jamie Smith 0:0c3532738887 155 bool CC1200::enqueuePacket(char const * data, size_t len)
Jamie Smith 0:0c3532738887 156 {
Jamie Smith 0:0c3532738887 157 uint8_t totalLength = len + 1; // add one byte for length byte
Jamie Smith 0:0c3532738887 158
Jamie Smith 0:0c3532738887 159 if(totalLength > MAX_PACKET_LENGTH)
Jamie Smith 0:0c3532738887 160 {
Jamie Smith 0:0c3532738887 161 // packet too big
Jamie Smith 0:0c3532738887 162 return false;
Jamie Smith 0:0c3532738887 163 }
Jamie Smith 0:0c3532738887 164
Jamie Smith 0:0c3532738887 165 uint8_t txFreeBytes = CC1200_FIFO_SIZE - getTXFIFOLen();
Jamie Smith 0:0c3532738887 166 if(totalLength > txFreeBytes)
Jamie Smith 0:0c3532738887 167 {
Jamie Smith 0:0c3532738887 168 // packet doesn't fit in TX FIFO
Jamie Smith 0:0c3532738887 169 return false;
Jamie Smith 0:0c3532738887 170 }
Jamie Smith 0:0c3532738887 171
Jamie Smith 0:0c3532738887 172 // burst write to TX FIFO
Jamie Smith 0:0c3532738887 173 spi.select();
Jamie Smith 0:0c3532738887 174 loadStatusByte(spi.write(CC1200_ENQUEUE_TX_FIFO | CC1200_BURST));
Jamie Smith 0:0c3532738887 175 spi.write(len);
Jamie Smith 0:0c3532738887 176 for(size_t byteIndex = 0; byteIndex < len; ++byteIndex)
Jamie Smith 0:0c3532738887 177 {
Jamie Smith 0:0c3532738887 178 spi.write(data[byteIndex]);
Jamie Smith 0:0c3532738887 179 }
Jamie Smith 0:0c3532738887 180 spi.deselect();
Jamie Smith 0:0c3532738887 181
Jamie Smith 0:0c3532738887 182 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 183 debugStream->printf("Wrote packet of data length %zu: %" PRIx8, len, static_cast<uint8_t>(len));
Jamie Smith 0:0c3532738887 184 for(size_t byteIndex = 0; byteIndex < len; ++byteIndex)
Jamie Smith 0:0c3532738887 185 {
Jamie Smith 0:0c3532738887 186 debugStream->printf(" %" PRIx8, data[byteIndex]);
Jamie Smith 0:0c3532738887 187 }
Jamie Smith 0:0c3532738887 188 debugStream->printf("\n");
Jamie Smith 0:0c3532738887 189 #endif
Jamie Smith 0:0c3532738887 190 return true;
Jamie Smith 0:0c3532738887 191 }
Jamie Smith 0:0c3532738887 192
Jamie Smith 0:0c3532738887 193 bool CC1200::hasReceivedPacket()
Jamie Smith 0:0c3532738887 194 {
Jamie Smith 0:0c3532738887 195 size_t bytesReceived = getRXFIFOLen();
Jamie Smith 0:0c3532738887 196
Jamie Smith 0:0c3532738887 197 if(bytesReceived < 1)
Jamie Smith 0:0c3532738887 198 {
Jamie Smith 0:0c3532738887 199 // no bytes at all, can't check the length
Jamie Smith 0:0c3532738887 200 return false;
Jamie Smith 0:0c3532738887 201 }
Jamie Smith 0:0c3532738887 202
Jamie Smith 0:0c3532738887 203 // get value of first byte of the packet, which is the length
Jamie Smith 0:0c3532738887 204 uint8_t rxFirstByteAddr = readRegister(ExtRegister::RXFIRST);
Jamie Smith 0:0c3532738887 205 uint8_t packetLen = readRXFIFOByte(rxFirstByteAddr);
Jamie Smith 0:0c3532738887 206
Jamie Smith 0:0c3532738887 207 // if we have received a full packet's worth of bytes, then we have received a full packet.
Jamie Smith 0:0c3532738887 208 return bytesReceived >= static_cast<size_t>(packetLen + 1); // Add one because length field does not include itself
Jamie Smith 0:0c3532738887 209 }
Jamie Smith 0:0c3532738887 210
Jamie Smith 0:0c3532738887 211 size_t CC1200::receivePacket(char *buffer, size_t bufferLen)
Jamie Smith 0:0c3532738887 212 {
Jamie Smith 0:0c3532738887 213 // burst read from RX FIFO
Jamie Smith 0:0c3532738887 214 spi.select();
Jamie Smith 0:0c3532738887 215 loadStatusByte(spi.write(CC1200_DEQUEUE_RX_FIFO | CC1200_BURST));
Jamie Smith 0:0c3532738887 216
Jamie Smith 0:0c3532738887 217 // first read length byte
Jamie Smith 0:0c3532738887 218 uint8_t dataLen = spi.write(0);
Jamie Smith 0:0c3532738887 219
Jamie Smith 0:0c3532738887 220 for(size_t byteIndex = 0; byteIndex < dataLen; ++byteIndex)
Jamie Smith 0:0c3532738887 221 {
Jamie Smith 0:0c3532738887 222 uint8_t currByte = spi.write(0);
Jamie Smith 0:0c3532738887 223 if(byteIndex < bufferLen)
Jamie Smith 0:0c3532738887 224 {
Jamie Smith 0:0c3532738887 225 buffer[byteIndex] = currByte;
Jamie Smith 0:0c3532738887 226 }
Jamie Smith 0:0c3532738887 227 }
Jamie Smith 0:0c3532738887 228 spi.deselect();
Jamie Smith 0:0c3532738887 229
Jamie Smith 0:0c3532738887 230 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 231 debugStream->printf("Read packet of data length %" PRIu8 ": %" PRIx8, dataLen, static_cast<uint8_t>(dataLen));
Jamie Smith 0:0c3532738887 232 for(size_t byteIndex = 0; byteIndex < dataLen; ++byteIndex)
Jamie Smith 0:0c3532738887 233 {
Jamie Smith 0:0c3532738887 234 debugStream->printf(" %" PRIx8, buffer[byteIndex]);
Jamie Smith 0:0c3532738887 235 }
Jamie Smith 0:0c3532738887 236 debugStream->printf("\n");
Jamie Smith 0:0c3532738887 237 #endif
Jamie Smith 0:0c3532738887 238
Jamie Smith 0:0c3532738887 239 return dataLen;
Jamie Smith 0:0c3532738887 240 }
Jamie Smith 0:0c3532738887 241
Jamie Smith 0:0c3532738887 242 // helper function: convert a state to the bits for RXOFF_MODE and TXOFF_MODE
Jamie Smith 0:0c3532738887 243 inline uint8_t getOffModeBits(CC1200::State state)
Jamie Smith 0:0c3532738887 244 {
Jamie Smith 0:0c3532738887 245 uint8_t offBits = 0b0;
Jamie Smith 0:0c3532738887 246 if(state == CC1200::State::IDLE)
Jamie Smith 0:0c3532738887 247 {
Jamie Smith 0:0c3532738887 248 offBits = 0b0;
Jamie Smith 0:0c3532738887 249 }
Jamie Smith 0:0c3532738887 250 else if(state == CC1200::State::FAST_ON)
Jamie Smith 0:0c3532738887 251 {
Jamie Smith 0:0c3532738887 252 offBits = 0b1;
Jamie Smith 0:0c3532738887 253 }
Jamie Smith 0:0c3532738887 254 else if(state == CC1200::State::TX)
Jamie Smith 0:0c3532738887 255 {
Jamie Smith 0:0c3532738887 256 offBits = 0b10;
Jamie Smith 0:0c3532738887 257 }
Jamie Smith 0:0c3532738887 258 else if(state == CC1200::State::RX)
Jamie Smith 0:0c3532738887 259 {
Jamie Smith 0:0c3532738887 260 offBits = 0b11;
Jamie Smith 0:0c3532738887 261 }
Jamie Smith 0:0c3532738887 262 return offBits;
Jamie Smith 0:0c3532738887 263 }
Jamie Smith 0:0c3532738887 264
Jamie Smith 0:0c3532738887 265 void CC1200::setOnReceiveState(CC1200::State goodPacket, CC1200::State badPacket)
Jamie Smith 0:0c3532738887 266 {
Jamie Smith 0:0c3532738887 267 // configure good packet action via RXOFF_MODE
Jamie Smith 0:0c3532738887 268 uint8_t rfendCfg1 = readRegister(Register::RFEND_CFG1);
Jamie Smith 0:0c3532738887 269 rfendCfg1 &= ~(0b11 << RFEND_CFG1_RXOFF_MODE);
Jamie Smith 0:0c3532738887 270 rfendCfg1 |= getOffModeBits(goodPacket) << RFEND_CFG1_RXOFF_MODE;
Jamie Smith 0:0c3532738887 271 writeRegister(Register::RFEND_CFG1, rfendCfg1);
Jamie Smith 0:0c3532738887 272
Jamie Smith 0:0c3532738887 273 // configure bad packet action via TERM_ON_BAD_PACKET_EN
Jamie Smith 0:0c3532738887 274 uint8_t rfendCfg0 = readRegister(Register::RFEND_CFG0);
Jamie Smith 0:0c3532738887 275 if(badPacket == State::RX)
Jamie Smith 0:0c3532738887 276 {
Jamie Smith 0:0c3532738887 277 rfendCfg0 &= ~(1 << RFEND_CFG0_TERM_ON_BAD_PACKET_EN);
Jamie Smith 0:0c3532738887 278 }
Jamie Smith 0:0c3532738887 279 else
Jamie Smith 0:0c3532738887 280 {
Jamie Smith 0:0c3532738887 281 rfendCfg0 |= 1 << RFEND_CFG1_RXOFF_MODE;
Jamie Smith 0:0c3532738887 282 }
Jamie Smith 0:0c3532738887 283 writeRegister(Register::RFEND_CFG0, rfendCfg0);
Jamie Smith 0:0c3532738887 284 }
Jamie Smith 0:0c3532738887 285
Jamie Smith 0:0c3532738887 286 void CC1200::setOnTransmitState(CC1200::State state)
Jamie Smith 0:0c3532738887 287 {
Jamie Smith 0:0c3532738887 288 uint8_t rfendCfg0 = readRegister(Register::RFEND_CFG0);
Jamie Smith 0:0c3532738887 289 rfendCfg0 &= ~(0b11 << RFEND_CFG0_TXOFF_MODE);
Jamie Smith 0:0c3532738887 290 rfendCfg0 |= getOffModeBits(state) << RFEND_CFG0_TXOFF_MODE;
Jamie Smith 0:0c3532738887 291 writeRegister(Register::RFEND_CFG0, rfendCfg0);
Jamie Smith 0:0c3532738887 292 }
Jamie Smith 0:0c3532738887 293
Jamie Smith 0:0c3532738887 294 void CC1200::setFSCalMode(FSCalMode mode)
Jamie Smith 0:0c3532738887 295 {
Jamie Smith 0:0c3532738887 296 uint8_t settlingCfg = readRegister(Register::SETTLING_CFG);
Jamie Smith 0:0c3532738887 297 settlingCfg &= ~(0b11 << SETTLING_CFG_FS_AUTOCAL);
Jamie Smith 0:0c3532738887 298 settlingCfg |= static_cast<uint8_t>(mode) << SETTLING_CFG_FS_AUTOCAL;
Jamie Smith 0:0c3532738887 299 writeRegister(Register::SETTLING_CFG, settlingCfg);
Jamie Smith 0:0c3532738887 300 }
Jamie Smith 0:0c3532738887 301
Jamie Smith 0:0c3532738887 302 void CC1200::configureGPIO(uint8_t gpioNumber, CC1200::GPIOMode mode, bool outputInvert)
Jamie Smith 0:0c3532738887 303 {
Jamie Smith 0:0c3532738887 304 // gpio 3 is the first register, then it goes down to 0
Jamie Smith 0:0c3532738887 305 Register gpioReg = static_cast<Register>(static_cast<uint8_t>(Register::IOCFG3) + (3 - gpioNumber));
Jamie Smith 0:0c3532738887 306
Jamie Smith 0:0c3532738887 307 uint8_t gpioCfgVal = static_cast<uint8_t>(mode);
Jamie Smith 0:0c3532738887 308 if(outputInvert)
Jamie Smith 0:0c3532738887 309 {
Jamie Smith 0:0c3532738887 310 gpioCfgVal |= (1 << GPIO_INV);
Jamie Smith 0:0c3532738887 311 }
Jamie Smith 0:0c3532738887 312 writeRegister(gpioReg, gpioCfgVal);
Jamie Smith 0:0c3532738887 313 }
Jamie Smith 0:0c3532738887 314
Jamie Smith 0:0c3532738887 315 void CC1200::configureFIFOMode()
Jamie Smith 0:0c3532738887 316 {
Jamie Smith 0:0c3532738887 317 // configure packet format
Jamie Smith 0:0c3532738887 318 uint8_t pktCfg2 = readRegister(Register::PKT_CFG2);
Jamie Smith 0:0c3532738887 319 pktCfg2 &= ~(0b11 << PKT_CFG2_PKT_FORMAT);
Jamie Smith 0:0c3532738887 320 writeRegister(Register::PKT_CFG2, pktCfg2);
Jamie Smith 0:0c3532738887 321
Jamie Smith 0:0c3532738887 322 // enable fifo
Jamie Smith 0:0c3532738887 323 uint8_t mdmCfg1 = readRegister(Register::MDMCFG1);
Jamie Smith 0:0c3532738887 324 mdmCfg1 |= 1 << MDMCFG1_FIFO_EN;
Jamie Smith 0:0c3532738887 325 writeRegister(Register::MDMCFG1, mdmCfg1);
Jamie Smith 0:0c3532738887 326
Jamie Smith 0:0c3532738887 327 // make sure transparent mode is disabled
Jamie Smith 0:0c3532738887 328 uint8_t mdmCfg0 = readRegister(Register::MDMCFG0);
Jamie Smith 0:0c3532738887 329 mdmCfg0 &= ~(1 << MDMCFG0_TRANSPARENT_MODE_EN);
Jamie Smith 0:0c3532738887 330 writeRegister(Register::MDMCFG0, mdmCfg0);
Jamie Smith 0:0c3532738887 331 }
Jamie Smith 0:0c3532738887 332
Jamie Smith 0:0c3532738887 333 void CC1200::setModulationFormat(CC1200::ModFormat format)
Jamie Smith 0:0c3532738887 334 {
Jamie Smith 0:0c3532738887 335 uint8_t modcfgDevE = readRegister(Register::MODCFG_DEV_E);
Jamie Smith 0:0c3532738887 336 modcfgDevE &= ~(0b111 << MODCFG_DEV_E_MOD_FORMAT);
Jamie Smith 0:0c3532738887 337 modcfgDevE |= static_cast<uint8_t>(format) << MODCFG_DEV_E_DEV_E;
Jamie Smith 0:0c3532738887 338 writeRegister(Register::MODCFG_DEV_E, modcfgDevE);
Jamie Smith 0:0c3532738887 339 }
Jamie Smith 0:0c3532738887 340
Jamie Smith 0:0c3532738887 341 void CC1200::setFSKDeviation(float deviation)
Jamie Smith 0:0c3532738887 342 {
Jamie Smith 0:0c3532738887 343 // Deviation is set as two values, an exponent register from 0-3 and a mantissa register from 0-256.
Jamie Smith 0:0c3532738887 344 // See user guide page 81 for the original equation, this function was worked out from that
Jamie Smith 0:0c3532738887 345
Jamie Smith 0:0c3532738887 346 // First assume mantissa is zero and calculate the needed exponent
Jamie Smith 0:0c3532738887 347 float exactExponent = std::log2(deviation) - CC1200_OSC_FREQ_LOG2 + 14;
Jamie Smith 0:0c3532738887 348 uint8_t actualExponent = static_cast<uint8_t>(std::min(static_cast<float>(maxValue3Bits), exactExponent));
Jamie Smith 0:0c3532738887 349 // note: 14 comes from log2(2^22) - log2(256)
Jamie Smith 0:0c3532738887 350
Jamie Smith 0:0c3532738887 351 float exactMantissa;
Jamie Smith 0:0c3532738887 352 if(actualExponent >= 1)
Jamie Smith 0:0c3532738887 353 {
Jamie Smith 0:0c3532738887 354 exactMantissa = (std::pow(2.0f, static_cast<float>(22 - actualExponent)) * deviation)
Jamie Smith 0:0c3532738887 355 / CC1200_OSC_FREQ - 256;
Jamie Smith 0:0c3532738887 356 }
Jamie Smith 0:0c3532738887 357 else
Jamie Smith 0:0c3532738887 358 {
Jamie Smith 0:0c3532738887 359 // use alternate high-resolution formula for case where exponent = 0
Jamie Smith 0:0c3532738887 360 exactMantissa = deviation * twoToThe21 / CC1200_OSC_FREQ;
Jamie Smith 0:0c3532738887 361 }
Jamie Smith 0:0c3532738887 362
Jamie Smith 0:0c3532738887 363 // now calculate closest mantissa
Jamie Smith 0:0c3532738887 364 uint8_t actualMantissa = static_cast<uint8_t>(std::min(static_cast<float>(maxValue8Bits), exactMantissa));
Jamie Smith 0:0c3532738887 365
Jamie Smith 0:0c3532738887 366 // set exponent and mantissa
Jamie Smith 0:0c3532738887 367 writeRegister(Register::DEVIATION_M, actualMantissa);
Jamie Smith 0:0c3532738887 368
Jamie Smith 0:0c3532738887 369 uint8_t modcfgDevE = readRegister(Register::MODCFG_DEV_E);
Jamie Smith 0:0c3532738887 370 modcfgDevE &= ~(0b111 << MODCFG_DEV_E_DEV_E);
Jamie Smith 0:0c3532738887 371 modcfgDevE |= actualExponent << MODCFG_DEV_E_DEV_E;
Jamie Smith 0:0c3532738887 372 writeRegister(Register::MODCFG_DEV_E, modcfgDevE);
Jamie Smith 0:0c3532738887 373
Jamie Smith 0:0c3532738887 374 #if CC1200_DEBUG
Jamie Smith 0:0c3532738887 375 debugStream->printf("Setting FSK deviation, requested +-%.00f Hz, setting DEV_E = 0x%" PRIx8 " DEV_M = 0x%" PRIx8 "\n",
Jamie Smith 0:0c3532738887 376 deviation, actualExponent, actualMantissa);
Jamie Smith 0:0c3532738887 377
Jamie Smith 0:0c3532738887 378 float actualDeviation;
Jamie Smith 0:0c3532738887 379 if(actualExponent == 0)
Jamie Smith 0:0c3532738887 380 {
Jamie Smith 0:0c3532738887 381 actualDeviation = CC1200_OSC_FREQ * actualMantissa / twoToThe21;
Jamie Smith 0:0c3532738887 382 }
Jamie Smith 0:0c3532738887 383 else
Jamie Smith 0:0c3532738887 384 {
Jamie Smith 0:0c3532738887 385 actualDeviation = (CC1200_OSC_FREQ / twoToThe22) * (256.0f + static_cast<float>(actualMantissa)) * pow(2.0f, static_cast<float>(actualExponent));
Jamie Smith 0:0c3532738887 386 }
Jamie Smith 0:0c3532738887 387 // sanity check: calculate actual deviation
Jamie Smith 0:0c3532738887 388 debugStream->printf("This yields an actual deviation of +-%.00f Hz\n", actualDeviation);
Jamie Smith 0:0c3532738887 389 #endif
Jamie Smith 0:0c3532738887 390 }
Jamie Smith 0:0c3532738887 391
Jamie Smith 0:0c3532738887 392 void CC1200::setSymbolRate(float symbolRateHz)
Jamie Smith 0:0c3532738887 393 {
Jamie Smith 0:0c3532738887 394 // Datasheet says that the cc1200 works in ksps, but testing with SmartRF studio
Jamie Smith 0:0c3532738887 395 // shows that it actually is sps.
Jamie Smith 0:0c3532738887 396
Jamie Smith 0:0c3532738887 397 symbolRateSps = symbolRateHz;
Jamie Smith 0:0c3532738887 398
Jamie Smith 0:0c3532738887 399 // Note: these equations are given on page 29 of the user guide
Jamie Smith 0:0c3532738887 400
Jamie Smith 0:0c3532738887 401 float exactExponent = std::log2(symbolRateSps) - CC1200_OSC_FREQ_LOG2 + 19;
Jamie Smith 0:0c3532738887 402 // note: 19 comes from log2(2^39) - 20
Jamie Smith 0:0c3532738887 403 uint8_t actualExponent = static_cast<uint8_t>(std::min(static_cast<float>(maxValue4Bits), exactExponent));
Jamie Smith 0:0c3532738887 404 // note: 15 comes from the largest number storable in 4 bits
Jamie Smith 0:0c3532738887 405
Jamie Smith 0:0c3532738887 406 float exactMantissa;
Jamie Smith 0:0c3532738887 407 if(actualExponent >= 1)
Jamie Smith 0:0c3532738887 408 {
Jamie Smith 0:0c3532738887 409 exactMantissa = (std::pow(2.0f, static_cast<float>(39 - actualExponent)) * symbolRateSps)
Jamie Smith 0:0c3532738887 410 / CC1200_OSC_FREQ - twoToThe20;
Jamie Smith 0:0c3532738887 411 }
Jamie Smith 0:0c3532738887 412 else
Jamie Smith 0:0c3532738887 413 {
Jamie Smith 0:0c3532738887 414 // use alternate high-resolution formula for case where exponent = 0
Jamie Smith 0:0c3532738887 415 exactMantissa = symbolRateSps * twoToThe38 / CC1200_OSC_FREQ;
Jamie Smith 0:0c3532738887 416 }
Jamie Smith 0:0c3532738887 417
Jamie Smith 0:0c3532738887 418 // mantissa is a 20 bit number, so restrict it to that domain
Jamie Smith 0:0c3532738887 419 uint32_t actualMantissa = static_cast<uint32_t>(std::min(static_cast<float>(maxValue20Bits), exactMantissa));
Jamie Smith 0:0c3532738887 420
Jamie Smith 0:0c3532738887 421 // program symbol rate registers
Jamie Smith 0:0c3532738887 422 std::array<uint8_t, 3> symbolRateRegisters ={
Jamie Smith 0:0c3532738887 423 static_cast<uint8_t>((actualExponent << SYMBOL_RATE2_SRATE_E) | (static_cast<uint8_t>((actualMantissa >> 16) & 0xFF) << SYMBOL_RATE2_SRATE_M_19_16)),
Jamie Smith 0:0c3532738887 424 static_cast<uint8_t>((actualMantissa >> 8) & 0xFF),
Jamie Smith 0:0c3532738887 425 static_cast<uint8_t>((actualMantissa & 0xFF))
Jamie Smith 0:0c3532738887 426 };
Jamie Smith 0:0c3532738887 427 writeRegisters(Register::SYMBOL_RATE2, symbolRateRegisters);
Jamie Smith 0:0c3532738887 428
Jamie Smith 0:0c3532738887 429 // Calculate upsampler value according to the forumula in its register description
Jamie Smith 0:0c3532738887 430 float upsamplingFactor = CC1200_OSC_FREQ / (64 * symbolRateSps);
Jamie Smith 0:0c3532738887 431 uint8_t upsamplerPVal = std::floor(std::log2(upsamplingFactor));
Jamie Smith 0:0c3532738887 432
Jamie Smith 0:0c3532738887 433 uint8_t mdmcfg2 = readRegister(ExtRegister::MDMCFG2);
Jamie Smith 0:0c3532738887 434 mdmcfg2 &= ~(0b111 << MDMCFG2_UPSAMPLER_P);
Jamie Smith 0:0c3532738887 435 mdmcfg2 |= (upsamplerPVal << MDMCFG2_UPSAMPLER_P);
Jamie Smith 0:0c3532738887 436
Jamie Smith 0:0c3532738887 437 writeRegister(ExtRegister::MDMCFG2, mdmcfg2);
Jamie Smith 0:0c3532738887 438
Jamie Smith 0:0c3532738887 439 #if CC1200_DEBUG
Jamie Smith 0:0c3532738887 440 debugStream->printf("Setting symbol rate, requested %.00f Hz, setting SRATE_E = 0x%" PRIx8 " SRATE_M = 0x%" PRIx32 "\n",
Jamie Smith 0:0c3532738887 441 symbolRateHz, actualExponent, actualMantissa);
Jamie Smith 0:0c3532738887 442
Jamie Smith 0:0c3532738887 443 // sanity check: calculate actual symbol rate
Jamie Smith 0:0c3532738887 444 float actualSymbolRateKsps;
Jamie Smith 0:0c3532738887 445 if(actualExponent == 0)
Jamie Smith 0:0c3532738887 446 {
Jamie Smith 0:0c3532738887 447 actualSymbolRateKsps = (static_cast<float>(actualMantissa) * CC1200_OSC_FREQ) / twoToThe38;
Jamie Smith 0:0c3532738887 448 }
Jamie Smith 0:0c3532738887 449 else
Jamie Smith 0:0c3532738887 450 {
Jamie Smith 0:0c3532738887 451
Jamie Smith 0:0c3532738887 452 actualSymbolRateKsps = ((static_cast<float>(actualMantissa) + twoToThe20) *
Jamie Smith 0:0c3532738887 453 pow(2.0f,static_cast<float>(actualExponent)) * CC1200_OSC_FREQ)
Jamie Smith 0:0c3532738887 454 / twoToThe39;
Jamie Smith 0:0c3532738887 455 }
Jamie Smith 0:0c3532738887 456
Jamie Smith 0:0c3532738887 457 debugStream->printf("This yields an actual symbol rate of %.00f Hz\n", actualSymbolRateKsps * 1000.0f);
Jamie Smith 0:0c3532738887 458
Jamie Smith 0:0c3532738887 459 uint8_t actualUpsampling = static_cast<uint8_t>(pow(2.0f, static_cast<float>(upsamplerPVal)));
Jamie Smith 0:0c3532738887 460 debugStream->printf("Also setting upsampling factor to %" PRIu8 " via UPSAMPLER_P = %" PRIx8 "\n", actualUpsampling, upsamplerPVal);
Jamie Smith 0:0c3532738887 461 #endif
Jamie Smith 0:0c3532738887 462 }
Jamie Smith 0:0c3532738887 463
Jamie Smith 0:0c3532738887 464 void CC1200::setOutputPower(float outPower)
Jamie Smith 0:0c3532738887 465 {
Jamie Smith 0:0c3532738887 466 const float minOutputPower = -16.0f;
Jamie Smith 0:0c3532738887 467
Jamie Smith 0:0c3532738887 468 // note: datasheet says this is 14.5, but that must be a mistake: 14.5 would produce a number
Jamie Smith 0:0c3532738887 469 // too large to fit into 6 bits.
Jamie Smith 0:0c3532738887 470 const float maxOutputPower = 14.0f;
Jamie Smith 0:0c3532738887 471
Jamie Smith 0:0c3532738887 472 // clamp output power into correct range
Jamie Smith 0:0c3532738887 473 outPower = std::min(outPower, maxOutputPower);
Jamie Smith 0:0c3532738887 474 outPower = std::max(outPower, minOutputPower);
Jamie Smith 0:0c3532738887 475
Jamie Smith 0:0c3532738887 476 // this equation derived from user guide section 7.1
Jamie Smith 0:0c3532738887 477 float exactPowerRamp = (2 * outPower) + 35;
Jamie Smith 0:0c3532738887 478 uint8_t actualPowerRamp = static_cast<uint8_t>(exactPowerRamp); // round to nearest
Jamie Smith 0:0c3532738887 479
Jamie Smith 0:0c3532738887 480 uint8_t paCfg1 = readRegister(Register::PA_CFG1);
Jamie Smith 0:0c3532738887 481 paCfg1 &= ~(0b111111 << PA_CFG1_PA_POWER_RAMP);
Jamie Smith 0:0c3532738887 482 paCfg1 |= actualPowerRamp << PA_CFG1_PA_POWER_RAMP;
Jamie Smith 0:0c3532738887 483 writeRegister(Register::PA_CFG1, paCfg1);
Jamie Smith 0:0c3532738887 484 }
Jamie Smith 0:0c3532738887 485
Jamie Smith 0:0c3532738887 486 void CC1200::setRadioFrequency(CC1200::Band band, float frequencyHz)
Jamie Smith 0:0c3532738887 487 {
Jamie Smith 0:0c3532738887 488 // Frequency synthesizer configuration. This is completely opaque and it is unknown what these bits do --
Jamie Smith 0:0c3532738887 489 // they are only generated by SmartRF studio.
Jamie Smith 0:0c3532738887 490 // I manually deduplicated them since only a few change based on frequency.
Jamie Smith 0:0c3532738887 491 writeRegister(ExtRegister::IF_ADC1,0xEE);
Jamie Smith 0:0c3532738887 492 writeRegister(ExtRegister::IF_ADC0,0x10);
Jamie Smith 0:0c3532738887 493 writeRegister(ExtRegister::FS_DIG1,0x04);
Jamie Smith 0:0c3532738887 494 writeRegister(ExtRegister::FS_CAL1,0x40);
Jamie Smith 0:0c3532738887 495 writeRegister(ExtRegister::FS_CAL0,0x0E);
Jamie Smith 0:0c3532738887 496 writeRegister(ExtRegister::FS_DIVTWO,0x03);
Jamie Smith 0:0c3532738887 497 writeRegister(ExtRegister::FS_DSM0,0x33);
Jamie Smith 0:0c3532738887 498 writeRegister(ExtRegister::FS_DVC1,0xF7);
Jamie Smith 0:0c3532738887 499 writeRegister(ExtRegister::FS_PFD,0x00);
Jamie Smith 0:0c3532738887 500 writeRegister(ExtRegister::FS_PRE,0x6E);
Jamie Smith 0:0c3532738887 501 writeRegister(ExtRegister::FS_REG_DIV_CML,0x1C);
Jamie Smith 0:0c3532738887 502 writeRegister(ExtRegister::FS_SPARE,0xAC);
Jamie Smith 0:0c3532738887 503 writeRegister(ExtRegister::FS_VCO0,0xB5);
Jamie Smith 0:0c3532738887 504 writeRegister(ExtRegister::XOSC5,0x0E);
Jamie Smith 0:0c3532738887 505 writeRegister(ExtRegister::XOSC1,0x03);
Jamie Smith 0:0c3532738887 506 if(band == Band::BAND_820_960MHz)
Jamie Smith 0:0c3532738887 507 {
Jamie Smith 0:0c3532738887 508 writeRegister(ExtRegister::FS_DIG0,0x55);
Jamie Smith 0:0c3532738887 509 writeRegister(ExtRegister::FS_DVC0,0x17);
Jamie Smith 0:0c3532738887 510 writeRegister(ExtRegister::IFAMP,0x09);
Jamie Smith 0:0c3532738887 511 }
Jamie Smith 0:0c3532738887 512 else if(band == Band::BAND_410_480MHz || band == Band::BAND_164_192MHz)
Jamie Smith 0:0c3532738887 513 {
Jamie Smith 0:0c3532738887 514 writeRegister(ExtRegister::FS_DIG0,0x50);
Jamie Smith 0:0c3532738887 515 writeRegister(ExtRegister::FS_DVC0,0x0F);
Jamie Smith 0:0c3532738887 516 writeRegister(ExtRegister::IFAMP,0x0D);
Jamie Smith 0:0c3532738887 517 }
Jamie Smith 0:0c3532738887 518 else
Jamie Smith 0:0c3532738887 519 {
Jamie Smith 0:0c3532738887 520 // TI doesn't make settings public for the other radio bands.
Jamie Smith 0:0c3532738887 521 // Let's take a guess and use the 480-164MHz values.
Jamie Smith 0:0c3532738887 522 writeRegister(ExtRegister::FS_DIG0,0x50);
Jamie Smith 0:0c3532738887 523 writeRegister(ExtRegister::FS_DVC0,0x0F);
Jamie Smith 0:0c3532738887 524 writeRegister(ExtRegister::IFAMP,0x0D);
Jamie Smith 0:0c3532738887 525 }
Jamie Smith 0:0c3532738887 526
Jamie Smith 0:0c3532738887 527 // convert band to LO Divider value.
Jamie Smith 0:0c3532738887 528 // Most of the bands just multiply the register value by 2, but nooo, not BAND_136_160MHz.
Jamie Smith 0:0c3532738887 529 uint8_t loDividerValue;
Jamie Smith 0:0c3532738887 530 if(band == Band::BAND_136_160MHz)
Jamie Smith 0:0c3532738887 531 {
Jamie Smith 0:0c3532738887 532 loDividerValue = 24;
Jamie Smith 0:0c3532738887 533 }
Jamie Smith 0:0c3532738887 534 else
Jamie Smith 0:0c3532738887 535 {
Jamie Smith 0:0c3532738887 536 loDividerValue = static_cast<uint8_t>(band) * 2;
Jamie Smith 0:0c3532738887 537 }
Jamie Smith 0:0c3532738887 538
Jamie Smith 0:0c3532738887 539 // program band (also enable FS out of lock detector, which is useful for testing)
Jamie Smith 0:0c3532738887 540 writeRegister(Register::FS_CFG, (1 << FS_CFG_FS_LOCK_EN) | (static_cast<uint8_t>(band) << FS_CFG_FSD_BANDSELECT));
Jamie Smith 0:0c3532738887 541
Jamie Smith 0:0c3532738887 542 // equation derived from user guide section 9.12
Jamie Smith 0:0c3532738887 543 float exactFreqValue = (twoToThe16 * frequencyHz * static_cast<float>(loDividerValue)) / CC1200_OSC_FREQ;
Jamie Smith 0:0c3532738887 544 uint32_t actualFreqValue = static_cast<uint32_t>(std::min(static_cast<float>(maxValue24Bits), exactFreqValue));
Jamie Smith 0:0c3532738887 545
Jamie Smith 0:0c3532738887 546 // program frequency registers
Jamie Smith 0:0c3532738887 547 std::array<uint8_t, 3> freqRegisters ={
Jamie Smith 0:0c3532738887 548 static_cast<uint8_t>((actualFreqValue >> 16) & 0xFF),
Jamie Smith 0:0c3532738887 549 static_cast<uint8_t>((actualFreqValue >> 8) & 0xFF),
Jamie Smith 0:0c3532738887 550 static_cast<uint8_t>((actualFreqValue & 0xFF))
Jamie Smith 0:0c3532738887 551 };
Jamie Smith 0:0c3532738887 552 writeRegisters(ExtRegister::FREQ2, freqRegisters);
Jamie Smith 0:0c3532738887 553
Jamie Smith 0:0c3532738887 554 #if CC1200_DEBUG
Jamie Smith 0:0c3532738887 555 debugStream->printf("Setting radio frequency, requested %.00f Hz, setting FREQ = 0x%" PRIx32 "\n",
Jamie Smith 0:0c3532738887 556 frequencyHz, actualFreqValue);
Jamie Smith 0:0c3532738887 557
Jamie Smith 0:0c3532738887 558 // sanity check: calculate actual frequency
Jamie Smith 0:0c3532738887 559 float actualFrequency = (static_cast<float>(actualFreqValue) * CC1200_OSC_FREQ) / (twoToThe16 * static_cast<float>(loDividerValue));
Jamie Smith 0:0c3532738887 560
Jamie Smith 0:0c3532738887 561 debugStream->printf("This yields an actual frequency of %.00f Hz\n", actualFrequency);
Jamie Smith 0:0c3532738887 562 #endif
Jamie Smith 0:0c3532738887 563 }
Jamie Smith 0:0c3532738887 564
Jamie Smith 0:0c3532738887 565 // helper function for setRXFilterBandwidth:
Jamie Smith 0:0c3532738887 566 // calculate actual receive bandwidth from the given decimations.
Jamie Smith 0:0c3532738887 567 float calcReceiveBandwidth(uint8_t adcDecimation, uint8_t cicDecimation)
Jamie Smith 0:0c3532738887 568 {
Jamie Smith 0:0c3532738887 569 return CC1200_OSC_FREQ / (static_cast<float>(adcDecimation) * static_cast<float>(cicDecimation) * 2);
Jamie Smith 0:0c3532738887 570 }
Jamie Smith 0:0c3532738887 571
Jamie Smith 0:0c3532738887 572 void CC1200::setRXFilterBandwidth(float bandwidthHz, bool isCC1201)
Jamie Smith 0:0c3532738887 573 {
Jamie Smith 0:0c3532738887 574 // settings that the chip supports
Jamie Smith 0:0c3532738887 575 const uint8_t possibleADCDecimations[] = {12, 24, 48}; // indexes in this array represent the register value
Jamie Smith 0:0c3532738887 576 const size_t numADCDecimations = sizeof(possibleADCDecimations) / sizeof(uint8_t);
Jamie Smith 0:0c3532738887 577 const uint8_t minBBDecimation = 1;
Jamie Smith 0:0c3532738887 578
Jamie Smith 0:0c3532738887 579 // maximum supported BB decimation based on ADC decimation varies based on chip
Jamie Smith 0:0c3532738887 580 const uint8_t maxBBDecimations1201[] = {33, 16, 8};
Jamie Smith 0:0c3532738887 581 const uint8_t maxBBDecimations1200[] = {44, 44, 44};
Jamie Smith 0:0c3532738887 582 uint8_t const * maxBBDecimations = isCC1201 ? maxBBDecimations1201 : maxBBDecimations1200;
Jamie Smith 0:0c3532738887 583
Jamie Smith 0:0c3532738887 584 // the datasheet suggests to use the highest possible ADC decimation factor that will work for the requested frequency.
Jamie Smith 0:0c3532738887 585 // So, we compute the closest we can get with each ADC decimation, and if there's a tie, we choose the one with the higher ADC bandwidth
Jamie Smith 0:0c3532738887 586
Jamie Smith 0:0c3532738887 587 uint8_t actualBBDecimations[numADCDecimations];
Jamie Smith 0:0c3532738887 588
Jamie Smith 0:0c3532738887 589 for(size_t adcDecimationIndex = 0; adcDecimationIndex < numADCDecimations; ++adcDecimationIndex)
Jamie Smith 0:0c3532738887 590 {
Jamie Smith 0:0c3532738887 591 uint8_t adcDecimation = possibleADCDecimations[adcDecimationIndex];
Jamie Smith 0:0c3532738887 592
Jamie Smith 0:0c3532738887 593 // calculate BB decimation closest to the requested frequency
Jamie Smith 0:0c3532738887 594 // derived from formula in section 6.1
Jamie Smith 0:0c3532738887 595 float exactBBDecimation = CC1200_OSC_FREQ / (2 * bandwidthHz * static_cast<float>(adcDecimation));
Jamie Smith 0:0c3532738887 596 exactBBDecimation = std::max(exactBBDecimation, static_cast<float>(minBBDecimation));
Jamie Smith 0:0c3532738887 597 exactBBDecimation = std::min(exactBBDecimation, static_cast<float>(maxBBDecimations[adcDecimationIndex]));
Jamie Smith 0:0c3532738887 598
Jamie Smith 0:0c3532738887 599 actualBBDecimations[adcDecimationIndex] = static_cast<uint8_t>(exactBBDecimation);
Jamie Smith 0:0c3532738887 600 }
Jamie Smith 0:0c3532738887 601
Jamie Smith 0:0c3532738887 602 // now, choose the best of the ones we calculated
Jamie Smith 0:0c3532738887 603 uint8_t bestDecimationIndex = 0;
Jamie Smith 0:0c3532738887 604 float bestDecimationError = std::abs(bandwidthHz - calcReceiveBandwidth(possibleADCDecimations[0], actualBBDecimations[0]));
Jamie Smith 0:0c3532738887 605
Jamie Smith 0:0c3532738887 606 for(size_t adcDecimationIndex = 1; adcDecimationIndex < numADCDecimations; ++adcDecimationIndex)
Jamie Smith 0:0c3532738887 607 {
Jamie Smith 0:0c3532738887 608 float thisDecimationError = std::abs(bandwidthHz -
Jamie Smith 0:0c3532738887 609 calcReceiveBandwidth(possibleADCDecimations[adcDecimationIndex], actualBBDecimations[adcDecimationIndex]));
Jamie Smith 0:0c3532738887 610 if(thisDecimationError <= bestDecimationError)
Jamie Smith 0:0c3532738887 611 {
Jamie Smith 0:0c3532738887 612 bestDecimationError = thisDecimationError;
Jamie Smith 0:0c3532738887 613 bestDecimationIndex = adcDecimationIndex;
Jamie Smith 0:0c3532738887 614 }
Jamie Smith 0:0c3532738887 615 }
Jamie Smith 0:0c3532738887 616
Jamie Smith 0:0c3532738887 617 // now use the best value!
Jamie Smith 0:0c3532738887 618 uint8_t chanBwValue = (bestDecimationIndex << CHAN_BW_ADC_CIC_DECFACT) | (actualBBDecimations[bestDecimationIndex] << CHAN_BW_BB_CIC_DECFACT);
Jamie Smith 0:0c3532738887 619 writeRegister(Register::CHAN_BW, chanBwValue);
Jamie Smith 0:0c3532738887 620
Jamie Smith 0:0c3532738887 621 // also set DVGA_GAIN, which depends on bandwidth
Jamie Smith 0:0c3532738887 622 uint8_t mdmCfg1Value = readRegister(Register::MDMCFG1);
Jamie Smith 0:0c3532738887 623
Jamie Smith 0:0c3532738887 624 mdmCfg1Value &= ~(0b11 << MDMCFG1_DVGA_GAIN);
Jamie Smith 0:0c3532738887 625 if(bandwidthHz >= 100000)
Jamie Smith 0:0c3532738887 626 {
Jamie Smith 0:0c3532738887 627 mdmCfg1Value |= 1 << MDMCFG1_DVGA_GAIN;
Jamie Smith 0:0c3532738887 628 }
Jamie Smith 0:0c3532738887 629
Jamie Smith 0:0c3532738887 630 writeRegister(Register::MDMCFG1, mdmCfg1Value);
Jamie Smith 0:0c3532738887 631
Jamie Smith 0:0c3532738887 632 // finally, we need to set RX_CONFIG_LIMITATION. It's not exactly clear what this does, but its setting changes
Jamie Smith 0:0c3532738887 633 // based on the filter BW.
Jamie Smith 0:0c3532738887 634 uint8_t syncCfg0Value = readRegister(Register::SYNC_CFG0);
Jamie Smith 0:0c3532738887 635
Jamie Smith 0:0c3532738887 636 if(symbolRateSps < bandwidthHz / 2 || bandwidthHz > 1500000)
Jamie Smith 0:0c3532738887 637 {
Jamie Smith 0:0c3532738887 638 // clear RX_CONFIG_LIMITATION
Jamie Smith 0:0c3532738887 639 syncCfg0Value &= ~(1 << SYNC_CFG0_RX_CONFIG_LIMITATION);
Jamie Smith 0:0c3532738887 640 }
Jamie Smith 0:0c3532738887 641 else
Jamie Smith 0:0c3532738887 642 {
Jamie Smith 0:0c3532738887 643 // set RX_CONFIG_LIMITATION
Jamie Smith 0:0c3532738887 644 syncCfg0Value |= (1 << SYNC_CFG0_RX_CONFIG_LIMITATION);
Jamie Smith 0:0c3532738887 645 }
Jamie Smith 0:0c3532738887 646
Jamie Smith 0:0c3532738887 647 writeRegister(Register::SYNC_CFG0, syncCfg0Value);
Jamie Smith 0:0c3532738887 648
Jamie Smith 0:0c3532738887 649 adcCicDecimation = possibleADCDecimations[bestDecimationIndex];
Jamie Smith 0:0c3532738887 650
Jamie Smith 0:0c3532738887 651 #if CC1200_DEBUG
Jamie Smith 0:0c3532738887 652 debugStream->printf("Setting BB decimation to %" PRIu8 " and ADC decimation to %" PRIu8 "\n",
Jamie Smith 0:0c3532738887 653 actualBBDecimations[bestDecimationIndex], possibleADCDecimations[bestDecimationIndex]);
Jamie Smith 0:0c3532738887 654 debugStream->printf("This yields an actual RX filter BW of %.00f\n",
Jamie Smith 0:0c3532738887 655 calcReceiveBandwidth(possibleADCDecimations[bestDecimationIndex], actualBBDecimations[bestDecimationIndex]));
Jamie Smith 0:0c3532738887 656 #endif
Jamie Smith 0:0c3532738887 657 }
Jamie Smith 0:0c3532738887 658
Jamie Smith 0:0c3532738887 659 void CC1200::configureDCFilter(bool enableAutoFilter, uint8_t settlingCfg, uint8_t cutoffCfg)
Jamie Smith 0:0c3532738887 660 {
Jamie Smith 0:0c3532738887 661 uint8_t dcfiltCfg = 0;
Jamie Smith 0:0c3532738887 662
Jamie Smith 0:0c3532738887 663 if(!enableAutoFilter)
Jamie Smith 0:0c3532738887 664 {
Jamie Smith 0:0c3532738887 665 // set "freeze coeff" bit
Jamie Smith 0:0c3532738887 666 dcfiltCfg |= (1 << DCFILT_CFG_DCFILT_FREEZE_COEFF);
Jamie Smith 0:0c3532738887 667 }
Jamie Smith 0:0c3532738887 668
Jamie Smith 0:0c3532738887 669 dcfiltCfg |= settlingCfg << DCFILT_CFG_DCFILT_BW_SETTLE;
Jamie Smith 0:0c3532738887 670 dcfiltCfg |= cutoffCfg << DCFILT_CFG_DCFILT_BW;
Jamie Smith 0:0c3532738887 671
Jamie Smith 0:0c3532738887 672 writeRegister(Register::DCFILT_CFG, dcfiltCfg);
Jamie Smith 0:0c3532738887 673 }
Jamie Smith 0:0c3532738887 674
Jamie Smith 0:0c3532738887 675 void CC1200::setIQMismatchCompensationEnabled(bool enabled)
Jamie Smith 0:0c3532738887 676 {
Jamie Smith 0:0c3532738887 677 uint8_t iqicValue = readRegister(Register::IQIC);
Jamie Smith 0:0c3532738887 678
Jamie Smith 0:0c3532738887 679 if(enabled)
Jamie Smith 0:0c3532738887 680 {
Jamie Smith 0:0c3532738887 681 iqicValue |= (1 << IQIC_IQIC_EN);
Jamie Smith 0:0c3532738887 682 }
Jamie Smith 0:0c3532738887 683 else
Jamie Smith 0:0c3532738887 684 {
Jamie Smith 0:0c3532738887 685 iqicValue &= ~(1 << IQIC_IQIC_EN);
Jamie Smith 0:0c3532738887 686 }
Jamie Smith 0:0c3532738887 687
Jamie Smith 0:0c3532738887 688 writeRegister(Register::IQIC, iqicValue);
Jamie Smith 0:0c3532738887 689 }
Jamie Smith 0:0c3532738887 690
Jamie Smith 0:0c3532738887 691 void CC1200::configureSyncWord(uint32_t syncWord, CC1200::SyncMode mode, uint8_t syncThreshold)
Jamie Smith 0:0c3532738887 692 {
Jamie Smith 0:0c3532738887 693 // program sync word registers
Jamie Smith 0:0c3532738887 694 std::array<uint8_t, 4> syncWordRegisters ={
Jamie Smith 0:0c3532738887 695 static_cast<uint8_t>((syncWord >> 24) & 0xFF),
Jamie Smith 0:0c3532738887 696 static_cast<uint8_t>((syncWord >> 16) & 0xFF),
Jamie Smith 0:0c3532738887 697 static_cast<uint8_t>((syncWord >> 8) & 0xFF),
Jamie Smith 0:0c3532738887 698 static_cast<uint8_t>(syncWord & 0xFF)
Jamie Smith 0:0c3532738887 699 };
Jamie Smith 0:0c3532738887 700 writeRegisters(Register::SYNC3, syncWordRegisters);
Jamie Smith 0:0c3532738887 701
Jamie Smith 0:0c3532738887 702 // program sync word cfg
Jamie Smith 0:0c3532738887 703 writeRegister(Register::SYNC_CFG1, (static_cast<uint8_t>(mode) << SYNC_CFG1_SYNC_MODE) | (syncThreshold << SYNC_CFG1_SYNC_THR));
Jamie Smith 0:0c3532738887 704 }
Jamie Smith 0:0c3532738887 705
Jamie Smith 0:0c3532738887 706 bool CC1200::isFSLocked()
Jamie Smith 0:0c3532738887 707 {
Jamie Smith 0:0c3532738887 708 return readRegister(ExtRegister::FSCAL_CTRL) & (1 << FSCAL_CTRL_LOCK);
Jamie Smith 0:0c3532738887 709 }
Jamie Smith 0:0c3532738887 710
Jamie Smith 0:0c3532738887 711 void CC1200::configurePreamble(uint8_t preambleLengthCfg, uint8_t preambleFormatCfg)
Jamie Smith 0:0c3532738887 712 {
Jamie Smith 0:0c3532738887 713 uint8_t preambleCfg1 = 0;
Jamie Smith 0:0c3532738887 714 preambleCfg1 |= preambleLengthCfg << PREAMBLE_CFG1_NUM_PREAMBLE;
Jamie Smith 0:0c3532738887 715 preambleCfg1 |= preambleFormatCfg << PREAMBLE_CFG1_PREAMBLE_WORD;
Jamie Smith 0:0c3532738887 716 writeRegister(Register::PREAMBLE_CFG1, preambleCfg1);
Jamie Smith 0:0c3532738887 717 }
Jamie Smith 0:0c3532738887 718
Jamie Smith 0:0c3532738887 719 void CC1200::setIFMixCFG(uint8_t value)
Jamie Smith 0:0c3532738887 720 {
Jamie Smith 0:0c3532738887 721 uint8_t ifMixCfg = readRegister(ExtRegister::IF_MIX_CFG);
Jamie Smith 0:0c3532738887 722 ifMixCfg &= ~(0b111 << IF_MIX_CFG_CMIX_CFG);
Jamie Smith 0:0c3532738887 723 ifMixCfg |= (value << IF_MIX_CFG_CMIX_CFG);
Jamie Smith 0:0c3532738887 724 writeRegister(ExtRegister::IF_MIX_CFG, ifMixCfg);
Jamie Smith 0:0c3532738887 725 }
Jamie Smith 0:0c3532738887 726
Jamie Smith 0:0c3532738887 727 uint8_t CC1200::readRegister(CC1200::Register reg)
Jamie Smith 0:0c3532738887 728 {
Jamie Smith 0:0c3532738887 729 spi.select();
Jamie Smith 0:0c3532738887 730 loadStatusByte(spi.write(CC1200_READ | static_cast<uint8_t>(reg)));
Jamie Smith 0:0c3532738887 731 uint8_t regValue = spi.write(0);
Jamie Smith 0:0c3532738887 732 spi.deselect();
Jamie Smith 0:0c3532738887 733
Jamie Smith 0:0c3532738887 734 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 735 debugStream->printf("Read register 0x%" PRIx8 " -> 0x%" PRIx8 "\n", static_cast<uint8_t>(reg), regValue);
Jamie Smith 0:0c3532738887 736 #endif
Jamie Smith 0:0c3532738887 737
Jamie Smith 0:0c3532738887 738 return regValue;
Jamie Smith 0:0c3532738887 739 }
Jamie Smith 0:0c3532738887 740
Jamie Smith 0:0c3532738887 741 void CC1200::writeRegister(Register reg, uint8_t value)
Jamie Smith 0:0c3532738887 742 {
Jamie Smith 0:0c3532738887 743 spi.select();
Jamie Smith 0:0c3532738887 744 loadStatusByte(spi.write(CC1200_WRITE | static_cast<uint8_t>(reg)));
Jamie Smith 0:0c3532738887 745 spi.write(value);
Jamie Smith 0:0c3532738887 746 spi.deselect();
Jamie Smith 0:0c3532738887 747
Jamie Smith 0:0c3532738887 748 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 749 debugStream->printf("Wrote register 0x%" PRIx8 " <- 0x%" PRIx8 "\n", static_cast<uint8_t>(reg), value);
Jamie Smith 0:0c3532738887 750 #endif
Jamie Smith 0:0c3532738887 751 }
Jamie Smith 0:0c3532738887 752
Jamie Smith 0:0c3532738887 753 void CC1200::writeRegisters(CC1200::Register startReg, uint8_t const *values, size_t numRegisters)
Jamie Smith 0:0c3532738887 754 {
Jamie Smith 0:0c3532738887 755 spi.select();
Jamie Smith 0:0c3532738887 756 loadStatusByte(spi.write(CC1200_WRITE | CC1200_BURST | static_cast<uint8_t>(startReg)));
Jamie Smith 0:0c3532738887 757
Jamie Smith 0:0c3532738887 758 for(size_t byteIndex = 0; byteIndex < numRegisters; ++byteIndex)
Jamie Smith 0:0c3532738887 759 {
Jamie Smith 0:0c3532738887 760 spi.write(values[byteIndex]);
Jamie Smith 0:0c3532738887 761 }
Jamie Smith 0:0c3532738887 762 spi.deselect();
Jamie Smith 0:0c3532738887 763
Jamie Smith 0:0c3532738887 764 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 765 for(size_t byteIndex = 0; byteIndex < numRegisters; ++byteIndex)
Jamie Smith 0:0c3532738887 766 {
Jamie Smith 0:0c3532738887 767 debugStream->printf("Wrote register 0x%" PRIx8 " <- 0x%" PRIx8 "\n",
Jamie Smith 0:0c3532738887 768 static_cast<uint8_t>(static_cast<uint8_t>(startReg) + byteIndex),
Jamie Smith 0:0c3532738887 769 values[byteIndex]);
Jamie Smith 0:0c3532738887 770 }
Jamie Smith 0:0c3532738887 771 #endif
Jamie Smith 0:0c3532738887 772 }
Jamie Smith 0:0c3532738887 773
Jamie Smith 0:0c3532738887 774 void CC1200::loadStatusByte(uint8_t status)
Jamie Smith 0:0c3532738887 775 {
Jamie Smith 0:0c3532738887 776 chipReady = !(status >> 7);
Jamie Smith 0:0c3532738887 777 state = static_cast<State>((status >> 4) & 0x7);
Jamie Smith 0:0c3532738887 778
Jamie Smith 0:0c3532738887 779 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 780 debugStream->printf("Updated status, state = 0x%" PRIx8 " ready = %s\n", static_cast<uint8_t>(state), chipReady ? "true" : "false");
Jamie Smith 0:0c3532738887 781 #endif
Jamie Smith 0:0c3532738887 782 }
Jamie Smith 0:0c3532738887 783
Jamie Smith 0:0c3532738887 784 uint8_t CC1200::readRegister(CC1200::ExtRegister reg)
Jamie Smith 0:0c3532738887 785 {
Jamie Smith 0:0c3532738887 786 spi.select();
Jamie Smith 0:0c3532738887 787 loadStatusByte(spi.write(CC1200_READ | CC1200_EXT_ADDR));
Jamie Smith 0:0c3532738887 788 spi.write(static_cast<uint8_t>(reg));
Jamie Smith 0:0c3532738887 789 uint8_t regValue = spi.write(0);
Jamie Smith 0:0c3532738887 790 spi.deselect();
Jamie Smith 0:0c3532738887 791
Jamie Smith 0:0c3532738887 792 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 793 debugStream->printf("Read ext register 0x%" PRIx8 " -> 0x%" PRIx8 "\n", static_cast<uint8_t>(reg), regValue);
Jamie Smith 0:0c3532738887 794 #endif
Jamie Smith 0:0c3532738887 795
Jamie Smith 0:0c3532738887 796 return regValue;
Jamie Smith 0:0c3532738887 797 }
Jamie Smith 0:0c3532738887 798
Jamie Smith 0:0c3532738887 799 void CC1200::writeRegister(CC1200::ExtRegister reg, uint8_t value)
Jamie Smith 0:0c3532738887 800 {
Jamie Smith 0:0c3532738887 801 spi.select();
Jamie Smith 0:0c3532738887 802 loadStatusByte(spi.write(CC1200_WRITE | CC1200_EXT_ADDR));
Jamie Smith 0:0c3532738887 803 spi.write(static_cast<uint8_t>(reg));
Jamie Smith 0:0c3532738887 804 spi.write(value);
Jamie Smith 0:0c3532738887 805 spi.deselect();
Jamie Smith 0:0c3532738887 806
Jamie Smith 0:0c3532738887 807 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 808 debugStream->printf("Wrote ext register 0x%" PRIx8 " <- 0x%" PRIx8 "\n", static_cast<uint8_t>(reg), value);
Jamie Smith 0:0c3532738887 809 #endif
Jamie Smith 0:0c3532738887 810 }
Jamie Smith 0:0c3532738887 811
Jamie Smith 0:0c3532738887 812 void CC1200::writeRegisters(CC1200::ExtRegister startReg, uint8_t const *values, size_t numRegisters)
Jamie Smith 0:0c3532738887 813 {
Jamie Smith 0:0c3532738887 814 spi.select();
Jamie Smith 0:0c3532738887 815 loadStatusByte(spi.write(CC1200_WRITE | CC1200_BURST | CC1200_EXT_ADDR));
Jamie Smith 0:0c3532738887 816 spi.write(static_cast<uint8_t>(startReg));
Jamie Smith 0:0c3532738887 817
Jamie Smith 0:0c3532738887 818 for(size_t byteIndex = 0; byteIndex < numRegisters; ++byteIndex)
Jamie Smith 0:0c3532738887 819 {
Jamie Smith 0:0c3532738887 820 spi.write(values[byteIndex]);
Jamie Smith 0:0c3532738887 821 }
Jamie Smith 0:0c3532738887 822 spi.deselect();
Jamie Smith 0:0c3532738887 823
Jamie Smith 0:0c3532738887 824 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 825 for(size_t byteIndex = 0; byteIndex < numRegisters; ++byteIndex)
Jamie Smith 0:0c3532738887 826 {
Jamie Smith 0:0c3532738887 827 debugStream->printf("Wrote extended register 0x%" PRIx8 " <- 0x%" PRIx8 "\n",
Jamie Smith 0:0c3532738887 828 static_cast<uint8_t>(static_cast<uint8_t>(startReg) + byteIndex),
Jamie Smith 0:0c3532738887 829 values[byteIndex]);
Jamie Smith 0:0c3532738887 830 }
Jamie Smith 0:0c3532738887 831 #endif
Jamie Smith 0:0c3532738887 832 }
Jamie Smith 0:0c3532738887 833
Jamie Smith 0:0c3532738887 834 void CC1200::sendCommand(CC1200::Command command)
Jamie Smith 0:0c3532738887 835 {
Jamie Smith 0:0c3532738887 836 spi.select();
Jamie Smith 0:0c3532738887 837 loadStatusByte(spi.write(static_cast<uint8_t>(command)));
Jamie Smith 0:0c3532738887 838 spi.deselect();
Jamie Smith 0:0c3532738887 839
Jamie Smith 0:0c3532738887 840 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 841 debugStream->printf("Sent SPI command 0x%" PRIx8 "\n", static_cast<uint8_t>(command));
Jamie Smith 0:0c3532738887 842 #endif
Jamie Smith 0:0c3532738887 843 }
Jamie Smith 0:0c3532738887 844
Jamie Smith 0:0c3532738887 845 uint8_t CC1200::readRXFIFOByte(uint8_t address)
Jamie Smith 0:0c3532738887 846 {
Jamie Smith 0:0c3532738887 847 spi.select();
Jamie Smith 0:0c3532738887 848 loadStatusByte(spi.write(CC1200_READ | CC1200_MEM_ACCESS));
Jamie Smith 0:0c3532738887 849 uint8_t value = spi.write(CC1200_TX_FIFO | address);
Jamie Smith 0:0c3532738887 850 spi.deselect();
Jamie Smith 0:0c3532738887 851
Jamie Smith 0:0c3532738887 852 #if CC1200_REGISTER_LEVEL_DEBUG
Jamie Smith 0:0c3532738887 853 debugStream->printf("Read RX FIFO[0x%" PRIx8 "] -> 0x%" PRIx8 "\n", static_cast<uint8_t>(address), value);
Jamie Smith 0:0c3532738887 854 #endif
Jamie Smith 0:0c3532738887 855
Jamie Smith 0:0c3532738887 856 return value;
Jamie Smith 0:0c3532738887 857 }
Jamie Smith 0:0c3532738887 858
Jamie Smith 0:0c3532738887 859
Jamie Smith 0:0c3532738887 860
Jamie Smith 0:0c3532738887 861
Jamie Smith 0:0c3532738887 862
Jamie Smith 0:0c3532738887 863
Jamie Smith 0:0c3532738887 864
Jamie Smith 0:0c3532738887 865
Jamie Smith 0:0c3532738887 866
Jamie Smith 0:0c3532738887 867
Jamie Smith 0:0c3532738887 868
Jamie Smith 0:0c3532738887 869
Jamie Smith 0:0c3532738887 870
Jamie Smith 0:0c3532738887 871
Jamie Smith 0:0c3532738887 872
Jamie Smith 0:0c3532738887 873
Jamie Smith 0:0c3532738887 874
Jamie Smith 0:0c3532738887 875
Jamie Smith 0:0c3532738887 876
Jamie Smith 0:0c3532738887 877
Jamie Smith 0:0c3532738887 878
Jamie Smith 0:0c3532738887 879
Jamie Smith 0:0c3532738887 880
Jamie Smith 0:0c3532738887 881