Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: CC1200-MorseEncoder CC1200-Examples
Diff: CC1200.cpp
- Revision:
- 4:c609cc7c9ea7
- Parent:
- 3:f464b14ce62f
- Child:
- 5:d22a8885800b
diff -r f464b14ce62f -r c609cc7c9ea7 CC1200.cpp --- a/CC1200.cpp Mon Aug 10 01:47:24 2020 -0700 +++ b/CC1200.cpp Fri Aug 28 15:39:31 2020 -0700 @@ -135,13 +135,6 @@ // enable CRC but disable status bytes writeRegister(Register::PKT_CFG1, (0b01 << PKT_CFG1_CRC_CFG)); - // configure packet length to adjustable - writeRegister(Register::PKT_CFG0, (0b01 << PKT_CFG0_LENGTH_CONFIG)); - - // set max packet length - writeRegister(Register::PKT_LEN, MAX_PACKET_LENGTH); - - return true; } @@ -175,7 +168,10 @@ // burst write to TX FIFO spi.select(); loadStatusByte(spi.write(CC1200_ENQUEUE_TX_FIFO | CC1200_BURST)); - spi.write(len); + if(_packetMode == PacketMode::VARIABLE_LENGTH) + { + spi.write(len); + } for(size_t byteIndex = 0; byteIndex < len; ++byteIndex) { spi.write(data[byteIndex]); @@ -183,10 +179,14 @@ spi.deselect(); #if CC1200_REGISTER_LEVEL_DEBUG - debugStream->printf("Wrote packet of data length %zu: %" PRIx8, len, static_cast<uint8_t>(len)); + debugStream->printf("Wrote packet of data length %zu:", len); + if(_packetMode == PacketMode::VARIABLE_LENGTH) + { + debugStream->printf(" %02" PRIx8, static_cast<uint8_t>(len)); + } for(size_t byteIndex = 0; byteIndex < len; ++byteIndex) { - debugStream->printf(" %" PRIx8, data[byteIndex]); + debugStream->printf(" %02" PRIx8, data[byteIndex]); } debugStream->printf("\n"); #endif @@ -203,16 +203,23 @@ return false; } - // get value of first byte of the packet, which is the length. + if(_packetMode == PacketMode::FIXED_LENGTH) + { + return bytesReceived >= _packetTotalLength; + } + else // _packetMode == PacketMode::VARIABLE_LENGTH + { + // get value of first byte of the packet, which is the length. - // The datasheet is wrong about this! It says that the first byte in the RX FIFO can - // be found by accessing address RXFIRST via direct fifo access. - // However, in my own testing, RXFIRST points to the second entry in the FIFO, and - // the first entry must be accessed through RXFIFO_PRE_BUF. - uint8_t packetLen = readRegister(ExtRegister::RXFIFO_PRE_BUF); + // The datasheet is wrong about this! It says that the first byte in the RX FIFO can + // be found by accessing address RXFIRST via direct fifo access. + // However, in my own testing, RXFIRST points to the second entry in the FIFO, and + // the first entry must be accessed through RXFIFO_PRE_BUF. + uint8_t packetLen = readRegister(ExtRegister::RXFIFO_PRE_BUF); - // if we have received a full packet's worth of bytes, then we have received a full packet. - return bytesReceived >= static_cast<size_t>(packetLen + 1); // Add one because length field does not include itself + // if we have received a full packet's worth of bytes, then we have received a full packet. + return bytesReceived >= static_cast<size_t>(packetLen + 1); // Add one because length field does not include itself + } } size_t CC1200::receivePacket(char *buffer, size_t bufferLen) @@ -221,8 +228,16 @@ spi.select(); loadStatusByte(spi.write(CC1200_DEQUEUE_RX_FIFO | CC1200_BURST)); - // first read length byte - uint8_t dataLen = spi.write(0); + uint8_t dataLen; + if(_packetMode == PacketMode::VARIABLE_LENGTH) + { + // first read length byte + dataLen = spi.write(0); + } + else // _packetMode == PacketMode::FIXED_LENGTH) + { + dataLen = _packetTotalLength; + } for(size_t byteIndex = 0; byteIndex < dataLen; ++byteIndex) { @@ -337,11 +352,65 @@ writeRegister(Register::MDMCFG0, mdmCfg0); } +void CC1200::setPacketMode(PacketMode mode) +{ + _packetMode = mode; + + uint8_t pktCfg0 = readRegister(Register::PKT_CFG0); + // set length config field + pktCfg0 &= ~(0b11 << PKT_CFG0_LENGTH_CONFIG); + pktCfg0 |= static_cast<uint8_t>(mode) << PKT_CFG0_LENGTH_CONFIG; + writeRegister(Register::PKT_CFG0, pktCfg0); + + if(mode == PacketMode::VARIABLE_LENGTH) + { + // disable packet length limit + writeRegister(Register::PKT_LEN, MAX_PACKET_LENGTH); + } + else + { + // reset to selected fixed lengths + setPacketLength(_packetByteLength, _packetBitLength); + } +} + +void CC1200::setPacketLength(uint8_t length, uint8_t bitLength) +{ + _packetByteLength = length; + _packetBitLength = bitLength; + _packetTotalLength = _packetByteLength; + + if(bitLength > 0) + { + // tell the driver to read the extra bits into another byte + _packetTotalLength++; + } + + writeRegister(Register::PKT_LEN, _packetByteLength); + + uint8_t pktCfg0 = readRegister(Register::PKT_CFG0); + pktCfg0 &= ~(0b111 << PKT_CFG0_PKT_BIT_LEN); + pktCfg0 |= _packetBitLength << PKT_CFG0_PKT_BIT_LEN; + writeRegister(Register::PKT_CFG0, pktCfg0); + +#if CC1200_DEBUG + debugStream->printf("Set total length to %zu, byte length = %zu, bit length = %" PRIu8 "\n", _packetTotalLength, _packetByteLength, _packetBitLength); +#endif +} + +void CC1200::setCRCEnabled(bool enabled) +{ + uint8_t pktCfg1 = readRegister(Register::PKT_CFG1); + pktCfg1 &= ~(0b11 << PKT_CFG1_CRC_CFG); + pktCfg1 |= (enabled ? 0b01 : 0b00) << PKT_CFG1_CRC_CFG; + writeRegister(Register::PKT_CFG1, pktCfg1); +} + void CC1200::setModulationFormat(CC1200::ModFormat format) { uint8_t modcfgDevE = readRegister(Register::MODCFG_DEV_E); modcfgDevE &= ~(0b111 << MODCFG_DEV_E_MOD_FORMAT); - modcfgDevE |= static_cast<uint8_t>(format) << MODCFG_DEV_E_DEV_E; + modcfgDevE |= static_cast<uint8_t>(format) << MODCFG_DEV_E_MOD_FORMAT; writeRegister(Register::MODCFG_DEV_E, modcfgDevE); } @@ -408,7 +477,6 @@ float exactExponent = std::log2(symbolRateSps) - CC1200_OSC_FREQ_LOG2 + 19; // note: 19 comes from log2(2^39) - 20 uint8_t actualExponent = static_cast<uint8_t>(std::min(static_cast<float>(maxValue4Bits), exactExponent)); - // note: 15 comes from the largest number storable in 4 bits float exactMantissa; if(actualExponent >= 1) @@ -433,10 +501,13 @@ }; writeRegisters(Register::SYMBOL_RATE2, symbolRateRegisters); - // Calculate upsampler value according to the forumula in its register description - float upsamplingFactor = CC1200_OSC_FREQ / (64 * symbolRateSps); + // Calculate upsampler value according to the formula in its register description + float upsamplingFactor = CC1200_OSC_FREQ / (64 * symbolRateSps); // 2^upsamplerPVal needs to be less than this value uint8_t upsamplerPVal = std::floor(std::log2(upsamplingFactor)); + // prevent low sampling rates from choosing a nonexistent upsampling + upsamplerPVal = std::min<uint8_t>(upsamplerPVal, 0b110); + uint8_t mdmcfg2 = readRegister(ExtRegister::MDMCFG2); mdmcfg2 &= ~(0b111 << MDMCFG2_UPSAMPLER_P); mdmcfg2 |= (upsamplerPVal << MDMCFG2_UPSAMPLER_P); @@ -444,31 +515,32 @@ writeRegister(ExtRegister::MDMCFG2, mdmcfg2); #if CC1200_DEBUG - debugStream->printf("Setting symbol rate, requested %.00f Hz, setting SRATE_E = 0x%" PRIx8 " SRATE_M = 0x%" PRIx32 "\n", + debugStream->printf("Setting symbol rate, requested %.03f Hz, setting SRATE_E = 0x%" PRIx8 " SRATE_M = 0x%" PRIx32 "\n", symbolRateHz, actualExponent, actualMantissa); // sanity check: calculate actual symbol rate - float actualSymbolRateKsps; + float actualSymbolRateSps; if(actualExponent == 0) { - actualSymbolRateKsps = (static_cast<float>(actualMantissa) * CC1200_OSC_FREQ) / twoToThe38; + actualSymbolRateSps = (static_cast<float>(actualMantissa) * CC1200_OSC_FREQ) / twoToThe38; } else { - actualSymbolRateKsps = ((static_cast<float>(actualMantissa) + twoToThe20) * - pow(2.0f,static_cast<float>(actualExponent)) * CC1200_OSC_FREQ) - / twoToThe39; + actualSymbolRateSps = ((static_cast<float>(actualMantissa) + twoToThe20) * + pow(2.0f,static_cast<float>(actualExponent)) * CC1200_OSC_FREQ) + / twoToThe39; } - debugStream->printf("This yields an actual symbol rate of %.00f Hz\n", actualSymbolRateKsps * 1000.0f); + debugStream->printf("This yields an actual symbol rate of %.02f Hz\n", actualSymbolRateSps); uint8_t actualUpsampling = static_cast<uint8_t>(pow(2.0f, static_cast<float>(upsamplerPVal))); debugStream->printf("Also setting upsampling factor to %" PRIu8 " via UPSAMPLER_P = %" PRIx8 "\n", actualUpsampling, upsamplerPVal); #endif } -void CC1200::setOutputPower(float outPower) +// helper function for power setting +inline uint8_t dBPowerToRegValue(float powerDB) { const float minOutputPower = -16.0f; @@ -477,12 +549,17 @@ const float maxOutputPower = 14.0f; // clamp output power into correct range - outPower = std::min(outPower, maxOutputPower); - outPower = std::max(outPower, minOutputPower); + powerDB = std::min(powerDB, maxOutputPower); + powerDB = std::max(powerDB, minOutputPower); // this equation derived from user guide section 7.1 - float exactPowerRamp = (2 * outPower) + 35; - uint8_t actualPowerRamp = static_cast<uint8_t>(exactPowerRamp); // round to nearest + float exactPowerRamp = (2 * powerDB) + 35; + return static_cast<uint8_t>(exactPowerRamp); // round to nearest +} + +void CC1200::setOutputPower(float outPower) +{ + uint8_t actualPowerRamp = dBPowerToRegValue(outPower); uint8_t paCfg1 = readRegister(Register::PA_CFG1); paCfg1 &= ~(0b111111 << PA_CFG1_PA_POWER_RAMP); @@ -490,6 +567,30 @@ writeRegister(Register::PA_CFG1, paCfg1); } +const float CC1200::ASK_MIN_POWER_OFF = -17.5f; + +void CC1200::setASKPowers(float maxPower, float minPower) +{ + uint8_t maxPowerValue = dBPowerToRegValue(maxPower); + + minPower = std::min(minPower, maxPower); + minPower = std::max(minPower, -17.5f); + + // calculate min power using formula derived from manual + uint8_t minPowerValue = static_cast<uint8_t>((maxPower - minPower) * 2); + + // write registers + uint8_t paCfg1 = readRegister(Register::PA_CFG1); + paCfg1 &= ~(0b111111 << PA_CFG1_PA_POWER_RAMP); + paCfg1 |= maxPowerValue << PA_CFG1_PA_POWER_RAMP; + writeRegister(Register::PA_CFG1, paCfg1); + + uint8_t askCfg = readRegister(Register::ASK_CFG); + askCfg &= ~(0b111111 << ASK_CFG_ASK_DEPTH); + askCfg |= minPowerValue << ASK_CFG_ASK_DEPTH; + writeRegister(Register::ASK_CFG, askCfg); +} + void CC1200::setRadioFrequency(CC1200::Band band, float frequencyHz) { // Frequency synthesizer configuration. This is completely opaque and it is unknown what these bits do -- @@ -739,6 +840,12 @@ void CC1200::setPARampRate(uint8_t firstRampLevel, uint8_t secondRampLevel, CC1200::RampTime rampTime) { + // enable PA ramping + uint8_t paCfg1Val = readRegister(Register::PA_CFG1); + paCfg1Val |= 1 << PA_CFG1_PA_RAMP_SHAPE_EN; + writeRegister(Register::PA_CFG1, paCfg1Val); + + // configure properties uint8_t paCfg0Val = 0; paCfg0Val |= (firstRampLevel << PA_CFG0_FIRST_IPL); paCfg0Val |= (secondRampLevel << PA_CFG0_SECOND_IPL); @@ -747,6 +854,13 @@ writeRegister(Register::PA_CFG0, paCfg0Val); } +void CC1200::disablePARamping() +{ + uint8_t paCfg1Val = readRegister(Register::PA_CFG1); + paCfg1Val &= ~(1 << PA_CFG1_PA_RAMP_SHAPE_EN); + writeRegister(Register::PA_CFG1, paCfg1Val); +} + void CC1200::setAGCReferenceLevel(uint8_t level) { writeRegister(Register::AGC_REF, level); @@ -935,4 +1049,5 @@ } -#pragma clang diagnostic pop \ No newline at end of file + +