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
CC1200.cpp@0:0c3532738887, 2020-06-30 (annotated)
- 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?
User | Revision | Line number | New 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 |