Radio Structures in OOP

Dependencies:   mbed mbed-rtos

Committer:
jjones646
Date:
Wed Jan 14 17:46:44 2015 +0000
Revision:
5:146523a0d1f4
Parent:
3:dc7e9c6bc26c
Child:
6:4a3dbfbc30f1
wrapping up functionality of sockets"

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jjones646 2:7d523bdd2f50 1 #include "CC1101.h"
jjones646 2:7d523bdd2f50 2
jjones646 2:7d523bdd2f50 3
jjones646 2:7d523bdd2f50 4 // Default constructor
jjones646 2:7d523bdd2f50 5 CC1101::CC1101() :
jjones646 3:dc7e9c6bc26c 6 CommLink()
jjones646 2:7d523bdd2f50 7 {
jjones646 2:7d523bdd2f50 8 }
jjones646 2:7d523bdd2f50 9
jjones646 3:dc7e9c6bc26c 10 // Main constructor
jjones646 3:dc7e9c6bc26c 11 CC1101::CC1101(PinName mosi, PinName miso, PinName sck, PinName cs, PinName int_pin) :
jjones646 3:dc7e9c6bc26c 12 CommLink(mosi, miso, sck, cs, int_pin)
jjones646 3:dc7e9c6bc26c 13 {
jjones646 3:dc7e9c6bc26c 14 // [X] - 1 - Setup the chip
jjones646 3:dc7e9c6bc26c 15 setup();
jjones646 3:dc7e9c6bc26c 16
jjones646 3:dc7e9c6bc26c 17 // [X] - 2 - Call the base class method for beginning full class operation with threads
jjones646 3:dc7e9c6bc26c 18 // =================
jjones646 3:dc7e9c6bc26c 19 CommLink::ready();
jjones646 3:dc7e9c6bc26c 20 }
jjones646 2:7d523bdd2f50 21
jjones646 2:7d523bdd2f50 22 // Deconstructor
jjones646 2:7d523bdd2f50 23 CC1101::~CC1101()
jjones646 2:7d523bdd2f50 24 {
jjones646 3:dc7e9c6bc26c 25 if (_spi)
jjones646 3:dc7e9c6bc26c 26 delete _spi;
jjones646 3:dc7e9c6bc26c 27 if (_cs)
jjones646 3:dc7e9c6bc26c 28 delete _cs;
jjones646 3:dc7e9c6bc26c 29 if (_int_in)
jjones646 3:dc7e9c6bc26c 30 delete _int_in;
jjones646 3:dc7e9c6bc26c 31 }
jjones646 2:7d523bdd2f50 32
jjones646 3:dc7e9c6bc26c 33
jjones646 3:dc7e9c6bc26c 34 void CC1101::setup(void)
jjones646 3:dc7e9c6bc26c 35 {
jjones646 3:dc7e9c6bc26c 36 // [X] - 1 - Initialize the CC1101 radio transceiver for operation
jjones646 3:dc7e9c6bc26c 37 // =================
jjones646 3:dc7e9c6bc26c 38 set_init_vars();
jjones646 3:dc7e9c6bc26c 39 assign_if_freq(CCXXX1_IF_FREQUENCY);
jjones646 3:dc7e9c6bc26c 40 freq(CCXXX1_BASE_FREQUENCY);
jjones646 3:dc7e9c6bc26c 41 assign_channel_spacing(200000); // 200kHz
jjones646 3:dc7e9c6bc26c 42 datarate(250000); // 250 kBaud
jjones646 3:dc7e9c6bc26c 43 set_rf_settings();
jjones646 5:146523a0d1f4 44 init();
jjones646 3:dc7e9c6bc26c 45
jjones646 3:dc7e9c6bc26c 46 // [] - 2 - Test the interrupt pin for proper operation
jjones646 3:dc7e9c6bc26c 47 // =================
jjones646 3:dc7e9c6bc26c 48
jjones646 3:dc7e9c6bc26c 49 // [] - 3 - Check the CC1101's version register to ensure the chip is what we believe it to be
jjones646 3:dc7e9c6bc26c 50 // =================
jjones646 3:dc7e9c6bc26c 51
jjones646 3:dc7e9c6bc26c 52 }
jjones646 3:dc7e9c6bc26c 53
jjones646 3:dc7e9c6bc26c 54
jjones646 3:dc7e9c6bc26c 55 int32_t CC1101::powerUp(void)
jjones646 3:dc7e9c6bc26c 56 {
jjones646 3:dc7e9c6bc26c 57 #if CCXXX1_DEBUG_MODE > 0
jjones646 3:dc7e9c6bc26c 58 std::printf("[CC1101 RADIO TRANSCEIVER INITILIZATION]\r\n");
jjones646 3:dc7e9c6bc26c 59 #endif
jjones646 3:dc7e9c6bc26c 60
jjones646 3:dc7e9c6bc26c 61 // power_on_reset();
jjones646 3:dc7e9c6bc26c 62
jjones646 3:dc7e9c6bc26c 63 // now send the assigned rfSettings struct to the CC1101 for full inililization
jjones646 3:dc7e9c6bc26c 64 // init();
jjones646 3:dc7e9c6bc26c 65
jjones646 3:dc7e9c6bc26c 66 // scan();
jjones646 3:dc7e9c6bc26c 67
jjones646 3:dc7e9c6bc26c 68 return 0;
jjones646 2:7d523bdd2f50 69 }
jjones646 2:7d523bdd2f50 70
jjones646 2:7d523bdd2f50 71
jjones646 2:7d523bdd2f50 72 bool CC1101::isConnected(void)
jjones646 2:7d523bdd2f50 73 {
jjones646 2:7d523bdd2f50 74 // [] - 1 - Perform a check to ensure the CC1101 can provide communication with a secondary base station link
jjones646 3:dc7e9c6bc26c 75 // =================
jjones646 2:7d523bdd2f50 76 // Note: This does not necessarily mean the link must be reliable, this only needs to determine: `Can the perheripial provide communication?`
jjones646 3:dc7e9c6bc26c 77
jjones646 2:7d523bdd2f50 78 // [] - 2 - Return true/false for indicating a connected communication link
jjones646 3:dc7e9c6bc26c 79 // =================
jjones646 3:dc7e9c6bc26c 80
jjones646 2:7d523bdd2f50 81 return true;
jjones646 2:7d523bdd2f50 82 }
jjones646 2:7d523bdd2f50 83
jjones646 2:7d523bdd2f50 84
jjones646 2:7d523bdd2f50 85 uint32_t CC1101::reset(void)
jjones646 2:7d523bdd2f50 86 {
jjones646 3:dc7e9c6bc26c 87 // [X] - 1 - Perform a soft reset for the CC1101 transceiver
jjones646 3:dc7e9c6bc26c 88 // =================
jjones646 3:dc7e9c6bc26c 89 strobe(CCXXX1_SRES);
jjones646 3:dc7e9c6bc26c 90 return 0; // success
jjones646 2:7d523bdd2f50 91 }
jjones646 2:7d523bdd2f50 92
jjones646 2:7d523bdd2f50 93
jjones646 2:7d523bdd2f50 94 uint32_t CC1101::selfTest(void)
jjones646 2:7d523bdd2f50 95 {
jjones646 3:dc7e9c6bc26c 96 // [X] - 1 - Get the chip's version number and fail if different from what was expected.
jjones646 3:dc7e9c6bc26c 97 _chip_version = status(CCXXX1_VERSION);
jjones646 3:dc7e9c6bc26c 98
jjones646 3:dc7e9c6bc26c 99 if (_chip_version != CCXXX1_EXPECTED_VERSION_NUMBER) {
jjones646 3:dc7e9c6bc26c 100
jjones646 3:dc7e9c6bc26c 101 // send message over serial port
jjones646 3:dc7e9c6bc26c 102 std::printf(
jjones646 3:dc7e9c6bc26c 103 "[FATAL ERROR]\r\n"
jjones646 3:dc7e9c6bc26c 104 " Wrong version number returned from chip's 'VERSION' register (Addr: 0x%02X)\r\n"
jjones646 3:dc7e9c6bc26c 105 "\r\n"
jjones646 3:dc7e9c6bc26c 106 " Expected: 0x%02X\r\n"
jjones646 3:dc7e9c6bc26c 107 " Found: 0x%02X\r\n"
jjones646 3:dc7e9c6bc26c 108 "\r\n"
jjones646 3:dc7e9c6bc26c 109 " Troubleshooting Tips:\r\n"
jjones646 3:dc7e9c6bc26c 110 " - Check that the chip is fully connected with no soldering errors\r\n"
jjones646 3:dc7e9c6bc26c 111 " - Determine if chip is newer version & update firmware\r\n"
jjones646 3:dc7e9c6bc26c 112 , CCXXX1_VERSION, CCXXX1_EXPECTED_VERSION_NUMBER, _chip_version);
jjones646 3:dc7e9c6bc26c 113
jjones646 3:dc7e9c6bc26c 114 return 1;
jjones646 3:dc7e9c6bc26c 115 }
jjones646 3:dc7e9c6bc26c 116 return 0; // success
jjones646 3:dc7e9c6bc26c 117 }
jjones646 3:dc7e9c6bc26c 118
jjones646 5:146523a0d1f4 119
jjones646 3:dc7e9c6bc26c 120 void CC1101::set_init_vars(void)
jjones646 3:dc7e9c6bc26c 121 {
jjones646 5:146523a0d1f4 122 // define the initial state of an unselected chip
jjones646 3:dc7e9c6bc26c 123 *_cs = 1;
jjones646 3:dc7e9c6bc26c 124 _channel = 1;
jjones646 3:dc7e9c6bc26c 125 _address = 0x00;
jjones646 3:dc7e9c6bc26c 126
jjones646 3:dc7e9c6bc26c 127 // frequency that radio links with another CC1101 over the air
jjones646 3:dc7e9c6bc26c 128 _base_freq = CCXXX1_BASE_FREQUENCY;
jjones646 3:dc7e9c6bc26c 129
jjones646 3:dc7e9c6bc26c 130 // turn off address packet filtering and assign 0 (broadcast address) to the address value
jjones646 3:dc7e9c6bc26c 131 _pck_control.addr_check = ADDR_OFF;
jjones646 3:dc7e9c6bc26c 132
jjones646 3:dc7e9c6bc26c 133 // these values determine how the CC1101 will handel a packet
jjones646 3:dc7e9c6bc26c 134 _pck_control.whitening_en = false;
jjones646 3:dc7e9c6bc26c 135
jjones646 3:dc7e9c6bc26c 136 // enable CRC calculation in TX and CRC checking in RX
jjones646 3:dc7e9c6bc26c 137 _pck_control.crc_en = true;
jjones646 3:dc7e9c6bc26c 138
jjones646 3:dc7e9c6bc26c 139 // enable automatically flushing the RX buffer on a bad CRC (only works if 1 packet is in the RX buffer)
jjones646 3:dc7e9c6bc26c 140 _pck_control.autoflush_en = true;
jjones646 3:dc7e9c6bc26c 141
jjones646 3:dc7e9c6bc26c 142 // enable appending 2 status bytes to the end of every packet that includes the CRC and
jjones646 3:dc7e9c6bc26c 143 _pck_control.status_field_en = true;
jjones646 3:dc7e9c6bc26c 144
jjones646 3:dc7e9c6bc26c 145 // normal packet mode uses RX and TX buffers
jjones646 3:dc7e9c6bc26c 146 _pck_control.format_type = FORMAT_DEFAULT;
jjones646 3:dc7e9c6bc26c 147
jjones646 3:dc7e9c6bc26c 148 // setup how the payload of the packet is transmitted - default to a fixed length of 61 bytes
jjones646 3:dc7e9c6bc26c 149 _pck_control.length_type = PACKET_VARIABLE;
jjones646 3:dc7e9c6bc26c 150 //_pck_control.length_type = PACKET_FIXED;
jjones646 3:dc7e9c6bc26c 151 //_pck_control.size = 61;
jjones646 3:dc7e9c6bc26c 152
jjones646 3:dc7e9c6bc26c 153 // this is a preamble threshold for determining when a packet should be accepted
jjones646 3:dc7e9c6bc26c 154 _pck_control.preamble_thresh = 2;
jjones646 3:dc7e9c6bc26c 155
jjones646 3:dc7e9c6bc26c 156 // these values determine how the frequency bands and channels are distributed as well as defining the modulation type
jjones646 3:dc7e9c6bc26c 157 _modem.dc_filter_off_en = false;
jjones646 3:dc7e9c6bc26c 158 _modem.manchester_encode_en = false;
jjones646 3:dc7e9c6bc26c 159 _modem.fec_en = false;
jjones646 3:dc7e9c6bc26c 160
jjones646 3:dc7e9c6bc26c 161 // bandwidth configurations
jjones646 3:dc7e9c6bc26c 162 _modem.channel_bw = 2;
jjones646 3:dc7e9c6bc26c 163 _modem.channel_bw_exp = 0;
jjones646 3:dc7e9c6bc26c 164 _modem.channel_space_exp = 2;
jjones646 3:dc7e9c6bc26c 165 _modem.data_rate_exp = 13;
jjones646 3:dc7e9c6bc26c 166
jjones646 3:dc7e9c6bc26c 167 _modem.mod_type = MOD_GFSK;
jjones646 3:dc7e9c6bc26c 168 _modem.sync_mode = SYNC_HIGH_ALLOW_TWO;
jjones646 3:dc7e9c6bc26c 169 _modem.preamble_bytes = PREAM_FOUR;
jjones646 3:dc7e9c6bc26c 170
jjones646 3:dc7e9c6bc26c 171 // the values assigned here are used for the frequency synthesizer control
jjones646 3:dc7e9c6bc26c 172 // assign_if_freq(CCXXX1_IF_FREQUENCY);
jjones646 3:dc7e9c6bc26c 173
jjones646 3:dc7e9c6bc26c 174 // set all the configuration values into the rfSettings struct
jjones646 3:dc7e9c6bc26c 175 // set_rf_settings();
jjones646 3:dc7e9c6bc26c 176 }
jjones646 3:dc7e9c6bc26c 177
jjones646 3:dc7e9c6bc26c 178
jjones646 5:146523a0d1f4 179 void CC1101::put_rf_settings()
jjones646 5:146523a0d1f4 180 {
jjones646 5:146523a0d1f4 181 write_reg(CCXXX1_IOCFG2, rfSettings.IOCFG2);
jjones646 5:146523a0d1f4 182 write_reg(CCXXX1_IOCFG1, rfSettings.IOCFG1);
jjones646 5:146523a0d1f4 183 write_reg(CCXXX1_IOCFG0, rfSettings.IOCFG0);
jjones646 5:146523a0d1f4 184 write_reg(CCXXX1_FIFOTHR, rfSettings.FIFOTHR);
jjones646 5:146523a0d1f4 185 // SYNC1
jjones646 5:146523a0d1f4 186 // SYNC0
jjones646 5:146523a0d1f4 187 write_reg(CCXXX1_PCKLEN, rfSettings.PCKLEN);
jjones646 5:146523a0d1f4 188 write_reg(CCXXX1_PCKCTRL1, rfSettings.PCKCTRL1);
jjones646 5:146523a0d1f4 189 write_reg(CCXXX1_PCKCTRL0, rfSettings.PCKCTRL0);
jjones646 5:146523a0d1f4 190 write_reg(CCXXX1_ADDR, rfSettings.ADDR);
jjones646 5:146523a0d1f4 191
jjones646 5:146523a0d1f4 192 write_reg(CCXXX1_CHANNR, rfSettings.CHANNR);
jjones646 5:146523a0d1f4 193 write_reg(CCXXX1_FSCTRL1, rfSettings.FSCTRL1);
jjones646 5:146523a0d1f4 194 write_reg(CCXXX1_FSCTRL0, rfSettings.FSCTRL0);
jjones646 5:146523a0d1f4 195 write_reg(CCXXX1_FREQ2, rfSettings.FREQ2);
jjones646 5:146523a0d1f4 196
jjones646 5:146523a0d1f4 197 write_reg(CCXXX1_FREQ1, rfSettings.FREQ1);
jjones646 5:146523a0d1f4 198 write_reg(CCXXX1_FREQ0, rfSettings.FREQ0);
jjones646 5:146523a0d1f4 199 write_reg(CCXXX1_MDMCFG4, rfSettings.MDMCFG4);
jjones646 5:146523a0d1f4 200 write_reg(CCXXX1_MDMCFG3, rfSettings.MDMCFG3);
jjones646 5:146523a0d1f4 201
jjones646 5:146523a0d1f4 202 write_reg(CCXXX1_MDMCFG2, rfSettings.MDMCFG2);
jjones646 5:146523a0d1f4 203 write_reg(CCXXX1_MDMCFG1, rfSettings.MDMCFG1);
jjones646 5:146523a0d1f4 204 write_reg(CCXXX1_MDMCFG0, rfSettings.MDMCFG0);
jjones646 5:146523a0d1f4 205 write_reg(CCXXX1_DEVIATN, rfSettings.DEVIATN);
jjones646 5:146523a0d1f4 206 write_reg(CCXXX1_MCSM2 , rfSettings.MCSM2);
jjones646 5:146523a0d1f4 207 write_reg(CCXXX1_MCSM1 , rfSettings.MCSM1);
jjones646 5:146523a0d1f4 208 write_reg(CCXXX1_MCSM0 , rfSettings.MCSM0 );
jjones646 5:146523a0d1f4 209 write_reg(CCXXX1_FOCCFG, rfSettings.FOCCFG);
jjones646 5:146523a0d1f4 210 write_reg(CCXXX1_BSCFG, rfSettings.BSCFG);
jjones646 5:146523a0d1f4 211 write_reg(CCXXX1_AGCCTRL2, rfSettings.AGCCTRL2);
jjones646 5:146523a0d1f4 212 write_reg(CCXXX1_AGCCTRL1, rfSettings.AGCCTRL1);
jjones646 5:146523a0d1f4 213 write_reg(CCXXX1_AGCCTRL0, rfSettings.AGCCTRL0);
jjones646 5:146523a0d1f4 214 // WOREVT1
jjones646 5:146523a0d1f4 215 // WOREVT0
jjones646 5:146523a0d1f4 216 // WORCTRL
jjones646 5:146523a0d1f4 217 write_reg(CCXXX1_FREND1, rfSettings.FREND1);
jjones646 5:146523a0d1f4 218 write_reg(CCXXX1_FREND0, rfSettings.FREND0);
jjones646 5:146523a0d1f4 219 //write_reg(CCXXX1_FSCAL3, rfSettings.FSCAL3);
jjones646 5:146523a0d1f4 220 //write_reg(CCXXX1_FSCAL2, rfSettings.FSCAL2);
jjones646 5:146523a0d1f4 221 //write_reg(CCXXX1_FSCAL1, rfSettings.FSCAL1);
jjones646 5:146523a0d1f4 222 //write_reg(CCXXX1_FSCAL0, rfSettings.FSCAL0);
jjones646 5:146523a0d1f4 223 // PCCTRL1
jjones646 5:146523a0d1f4 224 // PCCTRL0
jjones646 5:146523a0d1f4 225 // FSTEST
jjones646 5:146523a0d1f4 226 // PTEST
jjones646 5:146523a0d1f4 227 // AGCTEST
jjones646 5:146523a0d1f4 228 //write_reg(CCXXX1_TEST2, rfSettings.TEST2);
jjones646 5:146523a0d1f4 229 //write_reg(CCXXX1_TEST1, rfSettings.TEST1);
jjones646 5:146523a0d1f4 230 //write_reg(CCXXX1_TEST0, rfSettings.TEST0);
jjones646 5:146523a0d1f4 231 } // put_rf_settings
jjones646 5:146523a0d1f4 232
jjones646 5:146523a0d1f4 233
jjones646 5:146523a0d1f4 234
jjones646 5:146523a0d1f4 235 void CC1101::power_on_reset(void)
jjones646 5:146523a0d1f4 236 {
jjones646 5:146523a0d1f4 237 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 238 std::printf(" Starting Power-on-Reset procedure...");
jjones646 5:146523a0d1f4 239 #endif
jjones646 5:146523a0d1f4 240 delete _spi;
jjones646 5:146523a0d1f4 241
jjones646 5:146523a0d1f4 242 // make sure chip is not selected
jjones646 5:146523a0d1f4 243 toggle_cs();
jjones646 5:146523a0d1f4 244
jjones646 5:146523a0d1f4 245 DigitalOut *SI = new DigitalOut(_mosi_pin);
jjones646 5:146523a0d1f4 246 DigitalOut *SCK = new DigitalOut(_sck_pin);
jjones646 5:146523a0d1f4 247 DigitalIn *SO = new DigitalIn(_miso_pin);
jjones646 5:146523a0d1f4 248
jjones646 5:146523a0d1f4 249 // bring SPI lines to a defined state. Reasons are outlined in CC1101 datasheet - section 11.3
jjones646 5:146523a0d1f4 250 *SI = 0;
jjones646 5:146523a0d1f4 251 *SCK = 1;
jjones646 5:146523a0d1f4 252
jjones646 5:146523a0d1f4 253 // toggle chip select and remain in high state afterwards
jjones646 5:146523a0d1f4 254 toggle_cs();
jjones646 5:146523a0d1f4 255 toggle_cs();
jjones646 5:146523a0d1f4 256
jjones646 5:146523a0d1f4 257 // wait at least 40us
jjones646 5:146523a0d1f4 258 wait_us(45);
jjones646 5:146523a0d1f4 259
jjones646 5:146523a0d1f4 260 // pull CSn low & wait for the serial out line to go low
jjones646 5:146523a0d1f4 261 *_cs = 0;
jjones646 5:146523a0d1f4 262
jjones646 5:146523a0d1f4 263 while(*SO);
jjones646 5:146523a0d1f4 264
jjones646 5:146523a0d1f4 265 // cleanup everything before the mbed's SPI library calls take back over
jjones646 5:146523a0d1f4 266 delete SI;
jjones646 5:146523a0d1f4 267 delete SO;
jjones646 5:146523a0d1f4 268 delete SCK;
jjones646 5:146523a0d1f4 269
jjones646 5:146523a0d1f4 270 // reestablish the SPI bus and call the reset strobe
jjones646 5:146523a0d1f4 271 setup_spi();
jjones646 5:146523a0d1f4 272 reset();
jjones646 5:146523a0d1f4 273
jjones646 5:146523a0d1f4 274 delete _spi;
jjones646 5:146523a0d1f4 275 // wait for the SO line to go low again. Once low, reset is complete and CC1101 is in IDLE state
jjones646 5:146523a0d1f4 276 DigitalIn *SO2 = new DigitalIn(_miso_pin);
jjones646 5:146523a0d1f4 277 while(*SO2);
jjones646 5:146523a0d1f4 278
jjones646 5:146523a0d1f4 279 // make sure chip is deselected before returning
jjones646 5:146523a0d1f4 280 *_cs = 1;
jjones646 5:146523a0d1f4 281
jjones646 5:146523a0d1f4 282 // reestablish the SPI bus for the final time after removing the DigitalIn object
jjones646 5:146523a0d1f4 283 delete SO2;
jjones646 5:146523a0d1f4 284 setup_spi();
jjones646 5:146523a0d1f4 285
jjones646 5:146523a0d1f4 286 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 287 std::printf("==============done\r\n");
jjones646 5:146523a0d1f4 288 #endif
jjones646 5:146523a0d1f4 289 }
jjones646 5:146523a0d1f4 290
jjones646 5:146523a0d1f4 291 // 2nd ighest level of initilization routines behind CC1101::setup();
jjones646 5:146523a0d1f4 292 void CC1101::init(void)
jjones646 5:146523a0d1f4 293 {
jjones646 5:146523a0d1f4 294
jjones646 5:146523a0d1f4 295 power_on_reset();
jjones646 5:146523a0d1f4 296
jjones646 5:146523a0d1f4 297 // send all configuration values to the CC1101 registers
jjones646 5:146523a0d1f4 298 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 299 std::printf(" Writing configuration registers...");
jjones646 5:146523a0d1f4 300 #endif
jjones646 5:146523a0d1f4 301
jjones646 5:146523a0d1f4 302 put_rf_settings();
jjones646 5:146523a0d1f4 303
jjones646 5:146523a0d1f4 304 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 305 std::printf("done\r\n");
jjones646 5:146523a0d1f4 306 #endif
jjones646 5:146523a0d1f4 307 uint8_t paTable[] = {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 10dB
jjones646 5:146523a0d1f4 308 write_reg(CCXXX1_PATABLE, paTable[0]);
jjones646 5:146523a0d1f4 309
jjones646 5:146523a0d1f4 310 // flush TX and RX buffers before beginning
jjones646 5:146523a0d1f4 311 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 312 std::printf(" Clearing TX and RX buffers...");
jjones646 5:146523a0d1f4 313 #endif
jjones646 5:146523a0d1f4 314
jjones646 5:146523a0d1f4 315 flush_rx();
jjones646 5:146523a0d1f4 316 flush_tx();
jjones646 5:146523a0d1f4 317
jjones646 5:146523a0d1f4 318 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 319 std::printf("done\r\n");
jjones646 5:146523a0d1f4 320 #endif
jjones646 5:146523a0d1f4 321
jjones646 5:146523a0d1f4 322 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 323 std::printf(" Configuring frequency offset estimate...");
jjones646 5:146523a0d1f4 324 #endif
jjones646 5:146523a0d1f4 325
jjones646 5:146523a0d1f4 326 //write_reg(CCXXX1_FSCTRL0, status(CCXXX1_FREQEST));
jjones646 5:146523a0d1f4 327
jjones646 5:146523a0d1f4 328 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 329 std::printf("done\r\n");
jjones646 5:146523a0d1f4 330 #endif
jjones646 5:146523a0d1f4 331
jjones646 5:146523a0d1f4 332 // Enter RX mode
jjones646 5:146523a0d1f4 333 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 334 std::printf(" Entering RX mode...");
jjones646 5:146523a0d1f4 335 #endif
jjones646 5:146523a0d1f4 336 rx_mode();
jjones646 5:146523a0d1f4 337 #if DEBUG_MODE > 0
jjones646 5:146523a0d1f4 338 std::printf("done\r\n");
jjones646 5:146523a0d1f4 339 #endif
jjones646 5:146523a0d1f4 340 }
jjones646 5:146523a0d1f4 341
jjones646 3:dc7e9c6bc26c 342 // returns the current mode that the CC1101 is operating in
jjones646 3:dc7e9c6bc26c 343 uint8_t CC1101::mode(void)
jjones646 3:dc7e9c6bc26c 344 {
jjones646 3:dc7e9c6bc26c 345 return status(CCXXX1_MARCSTATE);
jjones646 3:dc7e9c6bc26c 346 }
jjones646 3:dc7e9c6bc26c 347
jjones646 3:dc7e9c6bc26c 348
jjones646 3:dc7e9c6bc26c 349 int32_t CC1101::sendData(uint8_t *buf, uint8_t size)
jjones646 5:146523a0d1f4 350 {
jjones646 3:dc7e9c6bc26c 351 // [X] - 1 - Move all values down by 1 to make room for the packet's size value.
jjones646 3:dc7e9c6bc26c 352 // =================
jjones646 3:dc7e9c6bc26c 353 for (uint8_t i = size; i > 0; i--)
jjones646 3:dc7e9c6bc26c 354 buf[i] = buf[i-1];
jjones646 3:dc7e9c6bc26c 355
jjones646 3:dc7e9c6bc26c 356
jjones646 3:dc7e9c6bc26c 357 // [X] - 2 - Place the packet's size as the array's first value.
jjones646 3:dc7e9c6bc26c 358 // =================
jjones646 3:dc7e9c6bc26c 359 buf[0] = size;
jjones646 3:dc7e9c6bc26c 360
jjones646 3:dc7e9c6bc26c 361
jjones646 3:dc7e9c6bc26c 362 #if CCXXX1_DEBUG_MODE > 0
jjones646 3:dc7e9c6bc26c 363 std::printf("\r\n[PACKET TRANSMITTED]\r\n Bytes: %u\r\n", size);
jjones646 3:dc7e9c6bc26c 364 #endif
jjones646 3:dc7e9c6bc26c 365
jjones646 3:dc7e9c6bc26c 366
jjones646 3:dc7e9c6bc26c 367 // [X] - 3 - Send the data to the CC1101. Increment the size value by 1 before doing so to account for the buffer's inserted value
jjones646 3:dc7e9c6bc26c 368 // =================
jjones646 3:dc7e9c6bc26c 369 write_reg(CCXXX1_TXFIFO, buf, ++size);
jjones646 3:dc7e9c6bc26c 370
jjones646 3:dc7e9c6bc26c 371
jjones646 3:dc7e9c6bc26c 372 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 373 Timer t1;
jjones646 3:dc7e9c6bc26c 374 #endif
jjones646 3:dc7e9c6bc26c 375
jjones646 3:dc7e9c6bc26c 376
jjones646 3:dc7e9c6bc26c 377 // [X] - 4 - Enter the TX state.
jjones646 3:dc7e9c6bc26c 378 // =================
jjones646 3:dc7e9c6bc26c 379 strobe(CCXXX1_STX);
jjones646 3:dc7e9c6bc26c 380
jjones646 3:dc7e9c6bc26c 381
jjones646 3:dc7e9c6bc26c 382 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 383 /* For the debug mode, this will determine how long the CC1101 takes to transmit everything in the TX buffer
jjones646 3:dc7e9c6bc26c 384 and enter or return to the RX state.
jjones646 3:dc7e9c6bc26c 385 */
jjones646 3:dc7e9c6bc26c 386 t1.start();
jjones646 3:dc7e9c6bc26c 387 float ti = t1.read();
jjones646 3:dc7e9c6bc26c 388 #endif
jjones646 3:dc7e9c6bc26c 389
jjones646 3:dc7e9c6bc26c 390
jjones646 3:dc7e9c6bc26c 391 // [X] - 5 - Wait until radio enters back to the RX state.
jjones646 3:dc7e9c6bc26c 392 // =================
jjones646 3:dc7e9c6bc26c 393 // *Note: Takes very few cycles, so might as well wait before returning to elimate querky errors.
jjones646 3:dc7e9c6bc26c 394 while(mode() != 0x0D);
jjones646 3:dc7e9c6bc26c 395
jjones646 3:dc7e9c6bc26c 396 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 397 t1.stop();
jjones646 3:dc7e9c6bc26c 398 std::printf(" Time: %02.4f ms\r\n", (t1.read() - ti)*1000);
jjones646 3:dc7e9c6bc26c 399 #endif
jjones646 3:dc7e9c6bc26c 400
jjones646 3:dc7e9c6bc26c 401 // [] - 6 - Return any error codes if necessary.
jjones646 3:dc7e9c6bc26c 402 // =================
jjones646 3:dc7e9c6bc26c 403
jjones646 3:dc7e9c6bc26c 404 return 0; // success
jjones646 3:dc7e9c6bc26c 405 }
jjones646 3:dc7e9c6bc26c 406
jjones646 3:dc7e9c6bc26c 407
jjones646 3:dc7e9c6bc26c 408 int32_t CC1101::getData(uint8_t *buf, uint8_t *length)
jjones646 3:dc7e9c6bc26c 409 {
jjones646 3:dc7e9c6bc26c 410 // [X] - 1 - Update the frequency offset estimate.
jjones646 3:dc7e9c6bc26c 411 // =================
jjones646 3:dc7e9c6bc26c 412 write_reg(CCXXX1_FSCTRL0, status(CCXXX1_FREQEST));
jjones646 3:dc7e9c6bc26c 413
jjones646 3:dc7e9c6bc26c 414
jjones646 3:dc7e9c6bc26c 415 // [X] - 2 - Get the packet's size.
jjones646 3:dc7e9c6bc26c 416 // =================
jjones646 3:dc7e9c6bc26c 417 uint8_t rx_size;
jjones646 3:dc7e9c6bc26c 418 read_reg(CCXXX1_RXFIFO, &rx_size, 1);
jjones646 3:dc7e9c6bc26c 419
jjones646 3:dc7e9c6bc26c 420
jjones646 3:dc7e9c6bc26c 421 // [X] - 3 - Check if there are indeed bytes to be read.
jjones646 3:dc7e9c6bc26c 422 // =================
jjones646 3:dc7e9c6bc26c 423 if (rx_size & CCXXX1_RXFIFO_MASK) {
jjones646 3:dc7e9c6bc26c 424
jjones646 3:dc7e9c6bc26c 425 // [X] - 3.1 - Check if the received data will fit in the provided buffer - fill the buffer if so.
jjones646 3:dc7e9c6bc26c 426 // =================
jjones646 3:dc7e9c6bc26c 427 if (rx_size <= *length) {
jjones646 3:dc7e9c6bc26c 428
jjones646 3:dc7e9c6bc26c 429 // [X] - 3.1a - Read in received data from the CC1101 and put the contents in the provided buffer.
jjones646 3:dc7e9c6bc26c 430 *length = rx_size; // set the correct length
jjones646 3:dc7e9c6bc26c 431 read_reg(CCXXX1_RXFIFO, buf, *length);
jjones646 3:dc7e9c6bc26c 432
jjones646 3:dc7e9c6bc26c 433 /* The RSSI value takes a bit to be determined by the CC1101, so having 2 separate SPI reads gives
jjones646 3:dc7e9c6bc26c 434 the CC1101 enough time to determine the correct value.
jjones646 3:dc7e9c6bc26c 435 */
jjones646 3:dc7e9c6bc26c 436
jjones646 3:dc7e9c6bc26c 437 // [X] - 3.1b - Read the 2 appended status bytes.
jjones646 3:dc7e9c6bc26c 438 // status[0] = RSSI. status[1] = LQI.
jjones646 3:dc7e9c6bc26c 439 uint8_t status_bytes[2];
jjones646 3:dc7e9c6bc26c 440 read_reg(CCXXX1_RXFIFO, status_bytes, 2);
jjones646 3:dc7e9c6bc26c 441
jjones646 3:dc7e9c6bc26c 442 // Update the RSSI reading.
jjones646 3:dc7e9c6bc26c 443 rssi(status_bytes[0]);
jjones646 3:dc7e9c6bc26c 444 _lqi = status_bytes[1] & CCXXX1_RXFIFO_MASK; // MSB of LQI is the CRC_OK bit - The interrupt is only triggered if CRC is OK, so no need to check again.
jjones646 3:dc7e9c6bc26c 445
jjones646 3:dc7e9c6bc26c 446 #if CCXXX1_DEBUG_MODE > 0
jjones646 3:dc7e9c6bc26c 447 std::printf("\r\n[PACKET RECEIVED]\r\n Bytes: %u\r\n", *length);
jjones646 3:dc7e9c6bc26c 448 std::printf(" RSSI: %ddBm\r\n", _rssi);
jjones646 3:dc7e9c6bc26c 449 std::printf(" LQI: %u\r\n", _lqi);
jjones646 3:dc7e9c6bc26c 450 #endif
jjones646 3:dc7e9c6bc26c 451
jjones646 3:dc7e9c6bc26c 452 // [X] - 3.2c - Go back to the receiving state since CC1101 is configured for transitioning to IDLE on receiving a packet.
jjones646 3:dc7e9c6bc26c 453 rx_mode();
jjones646 3:dc7e9c6bc26c 454 return 0; // success
jjones646 3:dc7e9c6bc26c 455 } else {
jjones646 3:dc7e9c6bc26c 456 *length = rx_size;
jjones646 3:dc7e9c6bc26c 457 flush_rx();
jjones646 3:dc7e9c6bc26c 458 return -2; // passed buffer size is not large enough
jjones646 3:dc7e9c6bc26c 459 }
jjones646 3:dc7e9c6bc26c 460 }
jjones646 3:dc7e9c6bc26c 461
jjones646 3:dc7e9c6bc26c 462 flush_rx();
jjones646 3:dc7e9c6bc26c 463 return -1; // there is no new data to read
jjones646 2:7d523bdd2f50 464 }
jjones646 2:7d523bdd2f50 465
jjones646 2:7d523bdd2f50 466
jjones646 3:dc7e9c6bc26c 467 // Read Register
jjones646 3:dc7e9c6bc26c 468 uint8_t CC1101::read_reg(uint8_t addr)
jjones646 3:dc7e9c6bc26c 469 {
jjones646 5:146523a0d1f4 470 _spi->frequency(8000000);
jjones646 3:dc7e9c6bc26c 471 toggle_cs();
jjones646 3:dc7e9c6bc26c 472 _spi->write(addr | CCXXX1_READ_SINGLE);
jjones646 5:146523a0d1f4 473 //tiny_delay();
jjones646 3:dc7e9c6bc26c 474 uint8_t x = _spi->write(0);
jjones646 3:dc7e9c6bc26c 475 toggle_cs();
jjones646 3:dc7e9c6bc26c 476
jjones646 3:dc7e9c6bc26c 477 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 478 std::printf("\r\n== Single Register Read ==\r\n Address: 0x%02X\r\n Value: 0x%02X\r\n", addr, x);
jjones646 3:dc7e9c6bc26c 479 #endif
jjones646 3:dc7e9c6bc26c 480 return x;
jjones646 3:dc7e9c6bc26c 481 } // read_reg
jjones646 3:dc7e9c6bc26c 482 void CC1101::read_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
jjones646 3:dc7e9c6bc26c 483 {
jjones646 5:146523a0d1f4 484 _spi->frequency(4500000);
jjones646 3:dc7e9c6bc26c 485 toggle_cs();
jjones646 3:dc7e9c6bc26c 486 _spi->write(addr | CCXXX1_READ_BURST);
jjones646 5:146523a0d1f4 487 //tiny_delay();
jjones646 3:dc7e9c6bc26c 488 for (uint8_t i = 0; i < count; i++) {
jjones646 3:dc7e9c6bc26c 489 buffer[i] = _spi->write(0);
jjones646 5:146523a0d1f4 490 //tiny_delay();
jjones646 3:dc7e9c6bc26c 491 }
jjones646 3:dc7e9c6bc26c 492 toggle_cs();
jjones646 3:dc7e9c6bc26c 493
jjones646 3:dc7e9c6bc26c 494 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 495 std::printf("\r\n== Burst Register Read ==\r\n Address: 0x%02X\r\n Bytes: %u\r\n", addr, count);
jjones646 3:dc7e9c6bc26c 496 #endif
jjones646 3:dc7e9c6bc26c 497 } // read_reg
jjones646 3:dc7e9c6bc26c 498
jjones646 3:dc7e9c6bc26c 499
jjones646 3:dc7e9c6bc26c 500
jjones646 3:dc7e9c6bc26c 501 // Write Register
jjones646 3:dc7e9c6bc26c 502 void CC1101::write_reg(uint8_t addr, uint8_t value)
jjones646 3:dc7e9c6bc26c 503 {
jjones646 5:146523a0d1f4 504 _spi->frequency(8000000);
jjones646 3:dc7e9c6bc26c 505 toggle_cs();
jjones646 3:dc7e9c6bc26c 506 _spi->write(addr);
jjones646 5:146523a0d1f4 507 //tiny_delay();
jjones646 3:dc7e9c6bc26c 508 _spi->write(value);
jjones646 3:dc7e9c6bc26c 509 toggle_cs();
jjones646 3:dc7e9c6bc26c 510
jjones646 3:dc7e9c6bc26c 511 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 512 std::printf("\r\n== Single Register Write ==\r\n Address: 0x%02X\r\n Value: 0x%02X\r\n", addr, value);
jjones646 3:dc7e9c6bc26c 513 #endif
jjones646 3:dc7e9c6bc26c 514 } // write_reg
jjones646 3:dc7e9c6bc26c 515 void CC1101::write_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
jjones646 3:dc7e9c6bc26c 516 {
jjones646 5:146523a0d1f4 517 _spi->frequency(4500000);
jjones646 3:dc7e9c6bc26c 518 toggle_cs();
jjones646 3:dc7e9c6bc26c 519 _spi->write(addr | CCXXX1_WRITE_BURST);
jjones646 3:dc7e9c6bc26c 520 for (uint8_t i = 0; i < count; i++) {
jjones646 3:dc7e9c6bc26c 521 _spi->write(buffer[i]);
jjones646 3:dc7e9c6bc26c 522 }
jjones646 3:dc7e9c6bc26c 523 toggle_cs();
jjones646 3:dc7e9c6bc26c 524
jjones646 3:dc7e9c6bc26c 525 #if CCXXX1_DEBUG_MODE > 1
jjones646 3:dc7e9c6bc26c 526 std::printf("\r\n== Burst Register Write ==\r\n Address: 0x%02X\r\n Bytes: %u\r\n", addr, count);
jjones646 3:dc7e9c6bc26c 527 #endif
jjones646 3:dc7e9c6bc26c 528 } // write_reg
jjones646 3:dc7e9c6bc26c 529
jjones646 3:dc7e9c6bc26c 530
jjones646 3:dc7e9c6bc26c 531 // Strobe
jjones646 3:dc7e9c6bc26c 532 uint8_t CC1101::strobe(uint8_t addr)
jjones646 3:dc7e9c6bc26c 533 {
jjones646 5:146523a0d1f4 534 _spi->frequency(4500000);
jjones646 3:dc7e9c6bc26c 535 toggle_cs();
jjones646 3:dc7e9c6bc26c 536 uint8_t x = _spi->write(addr);
jjones646 3:dc7e9c6bc26c 537 toggle_cs();
jjones646 3:dc7e9c6bc26c 538 return x;
jjones646 3:dc7e9c6bc26c 539 } // strobe
jjones646 3:dc7e9c6bc26c 540
jjones646 3:dc7e9c6bc26c 541
jjones646 3:dc7e9c6bc26c 542 // Macro to calibrate the frequency synthesizer
jjones646 3:dc7e9c6bc26c 543 void CC1101::calibrate(void)
jjones646 2:7d523bdd2f50 544 {
jjones646 3:dc7e9c6bc26c 545 // Send the calibration strobe
jjones646 3:dc7e9c6bc26c 546 strobe(CCXXX1_SCAL);
jjones646 3:dc7e9c6bc26c 547
jjones646 3:dc7e9c6bc26c 548 // Wait for the radio to leave the calibration step
jjones646 5:146523a0d1f4 549 // while( (mode() == 0x04) | (mode() == 0x05) );
jjones646 3:dc7e9c6bc26c 550
jjones646 3:dc7e9c6bc26c 551 // The radio is now is IDLE mode, so go to RX mode
jjones646 3:dc7e9c6bc26c 552 rx_mode();
jjones646 3:dc7e9c6bc26c 553
jjones646 3:dc7e9c6bc26c 554 // Wait for the radio to enter back into RX mode
jjones646 5:146523a0d1f4 555 //while( mode() != 0x0D );
jjones646 3:dc7e9c6bc26c 556 }
jjones646 3:dc7e9c6bc26c 557
jjones646 3:dc7e9c6bc26c 558
jjones646 3:dc7e9c6bc26c 559 void CC1101::tiny_delay(void)
jjones646 3:dc7e9c6bc26c 560 {
jjones646 3:dc7e9c6bc26c 561 int i = 0;
jjones646 5:146523a0d1f4 562 while(i < 4) {
jjones646 3:dc7e9c6bc26c 563 i++;
jjones646 3:dc7e9c6bc26c 564 }
jjones646 3:dc7e9c6bc26c 565 }
jjones646 3:dc7e9c6bc26c 566
jjones646 3:dc7e9c6bc26c 567 void CC1101::address(uint8_t addr)
jjones646 3:dc7e9c6bc26c 568 {
jjones646 3:dc7e9c6bc26c 569 _address = addr;
jjones646 3:dc7e9c6bc26c 570 // NOW, WRITE THE ADDRESS TO THE CC1101
jjones646 3:dc7e9c6bc26c 571 }
jjones646 3:dc7e9c6bc26c 572
jjones646 3:dc7e9c6bc26c 573 uint8_t CC1101::lqi(void)
jjones646 3:dc7e9c6bc26c 574 {
jjones646 3:dc7e9c6bc26c 575 return 0x3F - (_lqi & 0x3F);
jjones646 3:dc7e9c6bc26c 576 }
jjones646 3:dc7e9c6bc26c 577
jjones646 3:dc7e9c6bc26c 578 // returns the CC1101's VERSION register that specifices what exact chip version is being used
jjones646 3:dc7e9c6bc26c 579 uint8_t CC1101::version(void)
jjones646 3:dc7e9c6bc26c 580 {
jjones646 3:dc7e9c6bc26c 581 return _chip_version;
jjones646 3:dc7e9c6bc26c 582 }
jjones646 3:dc7e9c6bc26c 583
jjones646 3:dc7e9c6bc26c 584 void CC1101::channel(uint16_t chan)
jjones646 3:dc7e9c6bc26c 585 {
jjones646 3:dc7e9c6bc26c 586 if ( chan != _channel ) {
jjones646 3:dc7e9c6bc26c 587 _channel = chan;
jjones646 3:dc7e9c6bc26c 588 write_reg(CCXXX1_CHANNR, _channel);
jjones646 3:dc7e9c6bc26c 589 /*
jjones646 3:dc7e9c6bc26c 590 #if CCXXX1_DEBUG_MODE > 0
jjones646 3:dc7e9c6bc26c 591 std::printf("\r\n[CHANNEL UPDATED]\r\n Channel: %02u\r\n Freq: %3.2f MHz\r\n", _channel, static_cast<float>(_final_freq)/1000000);
jjones646 3:dc7e9c6bc26c 592 #endif
jjones646 3:dc7e9c6bc26c 593 */
jjones646 3:dc7e9c6bc26c 594 }
jjones646 3:dc7e9c6bc26c 595 }
jjones646 3:dc7e9c6bc26c 596
jjones646 3:dc7e9c6bc26c 597 // RSSI
jjones646 3:dc7e9c6bc26c 598 int16_t CC1101::rssi(void)
jjones646 3:dc7e9c6bc26c 599 {
jjones646 3:dc7e9c6bc26c 600 return _rssi;
jjones646 3:dc7e9c6bc26c 601 }
jjones646 3:dc7e9c6bc26c 602 void CC1101::rssi(uint8_t rssi_val)
jjones646 3:dc7e9c6bc26c 603 {
jjones646 3:dc7e9c6bc26c 604 int8_t temp;
jjones646 3:dc7e9c6bc26c 605
jjones646 3:dc7e9c6bc26c 606 if (rssi_val & 0x80) {
jjones646 3:dc7e9c6bc26c 607 temp = (rssi_val - 256)>>1;
jjones646 3:dc7e9c6bc26c 608 } else {
jjones646 3:dc7e9c6bc26c 609 temp = rssi_val>>1; // divide by 2
jjones646 3:dc7e9c6bc26c 610 }
jjones646 3:dc7e9c6bc26c 611 _rssi = temp - 74;
jjones646 3:dc7e9c6bc26c 612 } // rssi
jjones646 3:dc7e9c6bc26c 613
jjones646 3:dc7e9c6bc26c 614
jjones646 3:dc7e9c6bc26c 615 void CC1101::flush_rx(void)
jjones646 3:dc7e9c6bc26c 616 {
jjones646 3:dc7e9c6bc26c 617 // Make sure that the radio is in IDLE state before flushing the FIFO
jjones646 3:dc7e9c6bc26c 618 idle();
jjones646 3:dc7e9c6bc26c 619
jjones646 3:dc7e9c6bc26c 620 // Flush RX FIFO
jjones646 3:dc7e9c6bc26c 621 strobe(CCXXX1_SFRX);
jjones646 3:dc7e9c6bc26c 622
jjones646 3:dc7e9c6bc26c 623 // Enter back into a RX state
jjones646 3:dc7e9c6bc26c 624 rx_mode();
jjones646 3:dc7e9c6bc26c 625 }
jjones646 3:dc7e9c6bc26c 626
jjones646 3:dc7e9c6bc26c 627 void CC1101::flush_tx(void)
jjones646 3:dc7e9c6bc26c 628 {
jjones646 3:dc7e9c6bc26c 629 // Make sure that the radio is in IDLE state before flushing the FIFO
jjones646 3:dc7e9c6bc26c 630 idle();
jjones646 3:dc7e9c6bc26c 631
jjones646 3:dc7e9c6bc26c 632 // Flush TX FIFO
jjones646 3:dc7e9c6bc26c 633 strobe(CCXXX1_SFTX);
jjones646 3:dc7e9c6bc26c 634
jjones646 3:dc7e9c6bc26c 635 // Enter back into a RX state
jjones646 3:dc7e9c6bc26c 636 rx_mode();
jjones646 2:7d523bdd2f50 637 }
jjones646 2:7d523bdd2f50 638
jjones646 3:dc7e9c6bc26c 639
jjones646 3:dc7e9c6bc26c 640 void CC1101::rx_mode(void)
jjones646 3:dc7e9c6bc26c 641 {
jjones646 3:dc7e9c6bc26c 642 //strobe(CCXXX1_SIDLE);
jjones646 3:dc7e9c6bc26c 643 strobe(CCXXX1_SRX);
jjones646 3:dc7e9c6bc26c 644 //while(mode() != 0x0D);
jjones646 3:dc7e9c6bc26c 645 }
jjones646 3:dc7e9c6bc26c 646
jjones646 3:dc7e9c6bc26c 647
jjones646 3:dc7e9c6bc26c 648 void CC1101::tx_mode(void)
jjones646 3:dc7e9c6bc26c 649 {
jjones646 3:dc7e9c6bc26c 650 //strobe(CCXXX1_SIDLE);
jjones646 3:dc7e9c6bc26c 651 strobe(CCXXX1_STX);
jjones646 3:dc7e9c6bc26c 652 // while(mode() != 0x13);
jjones646 3:dc7e9c6bc26c 653 }
jjones646 3:dc7e9c6bc26c 654
jjones646 3:dc7e9c6bc26c 655 void CC1101::idle(void)
jjones646 3:dc7e9c6bc26c 656 {
jjones646 3:dc7e9c6bc26c 657 // Send the IDLE strobe
jjones646 3:dc7e9c6bc26c 658 strobe(CCXXX1_SIDLE);
jjones646 3:dc7e9c6bc26c 659 // Wait before returning
jjones646 5:146523a0d1f4 660 //while( mode() != 0x01);
jjones646 3:dc7e9c6bc26c 661 }
jjones646 3:dc7e9c6bc26c 662
jjones646 3:dc7e9c6bc26c 663
jjones646 3:dc7e9c6bc26c 664 // Status byte & status of a status register
jjones646 3:dc7e9c6bc26c 665 uint8_t CC1101::status(void)
jjones646 3:dc7e9c6bc26c 666 {
jjones646 3:dc7e9c6bc26c 667 return strobe(CCXXX1_SNOP);
jjones646 3:dc7e9c6bc26c 668 }
jjones646 3:dc7e9c6bc26c 669
jjones646 3:dc7e9c6bc26c 670 uint8_t CC1101::status(uint8_t addr)
jjones646 2:7d523bdd2f50 671 {
jjones646 5:146523a0d1f4 672 _spi->frequency(800000);
jjones646 3:dc7e9c6bc26c 673 toggle_cs();
jjones646 3:dc7e9c6bc26c 674 _spi->write(addr | CCXXX1_READ_BURST);
jjones646 3:dc7e9c6bc26c 675 tiny_delay();
jjones646 3:dc7e9c6bc26c 676 uint8_t x = _spi->write(0);
jjones646 3:dc7e9c6bc26c 677 toggle_cs();
jjones646 3:dc7e9c6bc26c 678 return x;
jjones646 3:dc7e9c6bc26c 679 } // status
jjones646 3:dc7e9c6bc26c 680
jjones646 3:dc7e9c6bc26c 681
jjones646 3:dc7e9c6bc26c 682 // SET FREQUENCY
jjones646 3:dc7e9c6bc26c 683 void CC1101::freq(uint32_t freq)
jjones646 3:dc7e9c6bc26c 684 {
jjones646 3:dc7e9c6bc26c 685 /* calculate the value that is written to the register for settings the base frequency
jjones646 3:dc7e9c6bc26c 686 * that the CC1101 should use for sending/receiving over the air. Default value is equivalent
jjones646 3:dc7e9c6bc26c 687 * to 901.83 MHz.
jjones646 3:dc7e9c6bc26c 688 */
jjones646 3:dc7e9c6bc26c 689
jjones646 3:dc7e9c6bc26c 690 // this is split into 3 bytes that are written to 3 different registers on the CC1101
jjones646 3:dc7e9c6bc26c 691 uint32_t reg_freq = _base_freq / (CCXXX1_CRYSTAL_FREQUENCY>>16);
jjones646 3:dc7e9c6bc26c 692
jjones646 3:dc7e9c6bc26c 693 rfSettings.FREQ2 = (reg_freq>>16) & 0xFF; // high byte, bits 7..6 are always 0 for this register
jjones646 3:dc7e9c6bc26c 694 rfSettings.FREQ1 = (reg_freq>>8) & 0xFF; // middle byte
jjones646 3:dc7e9c6bc26c 695 rfSettings.FREQ0 = reg_freq & 0xFF; // low byte
jjones646 3:dc7e9c6bc26c 696 }
jjones646 3:dc7e9c6bc26c 697
jjones646 3:dc7e9c6bc26c 698
jjones646 3:dc7e9c6bc26c 699 void CC1101::datarate(uint32_t rate)
jjones646 3:dc7e9c6bc26c 700 {
jjones646 3:dc7e9c6bc26c 701 // update the baud rate class member
jjones646 3:dc7e9c6bc26c 702 _datarate = rate;
jjones646 3:dc7e9c6bc26c 703
jjones646 3:dc7e9c6bc26c 704 // have to be careful with bit shifting here since it requires a large amount of shifts
jjones646 3:dc7e9c6bc26c 705 uint32_t shift_val = 28 - (_modem.data_rate_exp & 0x0F);
jjones646 3:dc7e9c6bc26c 706
jjones646 3:dc7e9c6bc26c 707 // compute the register value and assign it
jjones646 3:dc7e9c6bc26c 708 rfSettings.MDMCFG3 = ((_datarate)/(CCXXX1_CRYSTAL_FREQUENCY>>shift_val)) - 256;
jjones646 2:7d523bdd2f50 709 }
jjones646 2:7d523bdd2f50 710
jjones646 3:dc7e9c6bc26c 711
jjones646 3:dc7e9c6bc26c 712 // ===============
jjones646 3:dc7e9c6bc26c 713 void CC1101::assign_modem_params()
jjones646 3:dc7e9c6bc26c 714 {
jjones646 3:dc7e9c6bc26c 715 rfSettings.MDMCFG4 = (_modem.channel_bw_exp & 0x03)<<6 | (_modem.channel_bw & 0x03)<<4 | (_modem.data_rate_exp & 0x0F);
jjones646 3:dc7e9c6bc26c 716 rfSettings.MDMCFG2 = _modem.dc_filter_off_en<<7 | (_modem.mod_type & 0x07)<<4 | _modem.manchester_encode_en<<3 | (_modem.sync_mode & 0x07);
jjones646 3:dc7e9c6bc26c 717 rfSettings.MDMCFG1 = _modem.fec_en<<7 | (_modem.preamble_bytes & 0x07)<<4 | (_modem.channel_space_exp & 0x03);
jjones646 3:dc7e9c6bc26c 718 }
jjones646 3:dc7e9c6bc26c 719 // ===============
jjones646 3:dc7e9c6bc26c 720 void CC1101::assign_packet_params()
jjones646 3:dc7e9c6bc26c 721 {
jjones646 3:dc7e9c6bc26c 722 rfSettings.PCKCTRL0 = _pck_control.whitening_en<<6 | (_pck_control.format_type & 0x3)<<4 | _pck_control.crc_en<<2 | (_pck_control.length_type & 0x3);
jjones646 3:dc7e9c6bc26c 723 rfSettings.PCKCTRL1 = (_pck_control.preamble_thresh & 0x07)<<5 | _pck_control.autoflush_en<<3 | _pck_control.status_field_en<<2 | (_pck_control.addr_check & 0x03);
jjones646 3:dc7e9c6bc26c 724 rfSettings.PCKLEN = _pck_control.size;
jjones646 3:dc7e9c6bc26c 725 }
jjones646 3:dc7e9c6bc26c 726 // ===============
jjones646 3:dc7e9c6bc26c 727 void CC1101::assign_if_freq(uint32_t freq)
jjones646 3:dc7e9c6bc26c 728 {
jjones646 3:dc7e9c6bc26c 729 // The desired IF frequency for RX. Subtracted from FS base frequency in RX.
jjones646 3:dc7e9c6bc26c 730 // bits 7..5 are always 0
jjones646 3:dc7e9c6bc26c 731 rfSettings.FSCTRL1 = (freq/(CCXXX1_CRYSTAL_FREQUENCY>>10)) & 0x1F;
jjones646 3:dc7e9c6bc26c 732 rfSettings.FSCTRL0 = 0x00; // set the initial freq calibration to 0
jjones646 3:dc7e9c6bc26c 733 }
jjones646 3:dc7e9c6bc26c 734 // ===============
jjones646 3:dc7e9c6bc26c 735 void CC1101::assign_channel_spacing(uint32_t spacing)
jjones646 3:dc7e9c6bc26c 736 {
jjones646 3:dc7e9c6bc26c 737 // have to be careful with bit shifting here since it requires a large amount of shifts
jjones646 3:dc7e9c6bc26c 738 uint32_t shift_val = 18 - (_modem.channel_space_exp & 0x03);
jjones646 3:dc7e9c6bc26c 739
jjones646 3:dc7e9c6bc26c 740 // compute the register value and assign it
jjones646 3:dc7e9c6bc26c 741 rfSettings.MDMCFG0 = (spacing/(CCXXX1_CRYSTAL_FREQUENCY>>shift_val)) - 256;
jjones646 3:dc7e9c6bc26c 742 }
jjones646 3:dc7e9c6bc26c 743 void CC1101::set_rf_settings(void)
jjones646 3:dc7e9c6bc26c 744 {
jjones646 3:dc7e9c6bc26c 745 // set the fields for packet controls
jjones646 3:dc7e9c6bc26c 746 assign_packet_params();
jjones646 3:dc7e9c6bc26c 747
jjones646 3:dc7e9c6bc26c 748 // set the fields for the frequency limits of the modem
jjones646 3:dc7e9c6bc26c 749 assign_modem_params();
jjones646 3:dc7e9c6bc26c 750
jjones646 3:dc7e9c6bc26c 751 // assign an address to the CC1101. This can be used to filter packets
jjones646 3:dc7e9c6bc26c 752 rfSettings.ADDR = _address;
jjones646 3:dc7e9c6bc26c 753
jjones646 3:dc7e9c6bc26c 754 // there can be 16 different channel numbers. The bandwidth and spacing are defined in other registers
jjones646 3:dc7e9c6bc26c 755 rfSettings.CHANNR = _channel;
jjones646 3:dc7e9c6bc26c 756
jjones646 3:dc7e9c6bc26c 757 // compute the final adjusted frequency so that it will be correct after the constructor
jjones646 3:dc7e9c6bc26c 758 // compute_freq();
jjones646 3:dc7e9c6bc26c 759
jjones646 3:dc7e9c6bc26c 760 // disable GDO0
jjones646 3:dc7e9c6bc26c 761 rfSettings.IOCFG0 = 0x2E;
jjones646 3:dc7e9c6bc26c 762
jjones646 3:dc7e9c6bc26c 763 // setup for SPI
jjones646 3:dc7e9c6bc26c 764 rfSettings.IOCFG1 = 0x0C;
jjones646 3:dc7e9c6bc26c 765
jjones646 3:dc7e9c6bc26c 766 // setup for going HIGH when packet received and CRC is ok
jjones646 3:dc7e9c6bc26c 767 rfSettings.IOCFG2 = 0x07;
jjones646 3:dc7e9c6bc26c 768
jjones646 3:dc7e9c6bc26c 769 rfSettings.DEVIATN = 0x62;
jjones646 3:dc7e9c6bc26c 770
jjones646 3:dc7e9c6bc26c 771 rfSettings.FREND1 = 0xB6;
jjones646 3:dc7e9c6bc26c 772 rfSettings.FREND0 = 0x10;
jjones646 3:dc7e9c6bc26c 773
jjones646 3:dc7e9c6bc26c 774 bool RX_TIME_RSSI = false;
jjones646 3:dc7e9c6bc26c 775 bool RX_TIME_QUAL = false;
jjones646 3:dc7e9c6bc26c 776 uint8_t RX_TIME = 0x07; // no timeout
jjones646 3:dc7e9c6bc26c 777
jjones646 3:dc7e9c6bc26c 778 rfSettings.MCSM2 = (RX_TIME_RSSI<<4) | (RX_TIME_QUAL<<3) | (RX_TIME & 0x07);
jjones646 3:dc7e9c6bc26c 779
jjones646 3:dc7e9c6bc26c 780 uint8_t CCA_MODE = 0x00;
jjones646 3:dc7e9c6bc26c 781 uint8_t RXOFF_MODE = 0x00; // go directly to IDLE when existing RX
jjones646 3:dc7e9c6bc26c 782 //uint8_t RXOFF_MODE = 0x03; // stay in RX when existing RX
jjones646 3:dc7e9c6bc26c 783 uint8_t TXOFF_MODE = 0x03; // go directly to RX when existing TX
jjones646 3:dc7e9c6bc26c 784 // uint8_t TXOFF_MODE = 0x00; // go directly to IDLE when existing TX
jjones646 3:dc7e9c6bc26c 785
jjones646 3:dc7e9c6bc26c 786 rfSettings.MCSM1 = ((CCA_MODE & 0x03)<<4) | ((RXOFF_MODE & 0x03)<<2) | (TXOFF_MODE & 0x03);
jjones646 3:dc7e9c6bc26c 787
jjones646 3:dc7e9c6bc26c 788 uint8_t FS_AUTOCAL = 0x01; // calibrate when going from IDLE to RX or TX
jjones646 3:dc7e9c6bc26c 789 uint8_t PO_TIMEOUT = 0x02;
jjones646 3:dc7e9c6bc26c 790 bool PIN_CTRL_EN = false;
jjones646 3:dc7e9c6bc26c 791 bool XOSC_FORCE_ON = false;
jjones646 3:dc7e9c6bc26c 792
jjones646 3:dc7e9c6bc26c 793 rfSettings.MCSM0 = ((FS_AUTOCAL & 0x03)<<4) | ((PO_TIMEOUT & 0x03)<<2) | (PIN_CTRL_EN<<1) | (XOSC_FORCE_ON);
jjones646 3:dc7e9c6bc26c 794
jjones646 3:dc7e9c6bc26c 795 bool FOC_BS_CS_GATE = false;
jjones646 3:dc7e9c6bc26c 796 uint8_t FOC_PRE_K = 0x03;
jjones646 3:dc7e9c6bc26c 797 bool FOC_POST_K = true;
jjones646 3:dc7e9c6bc26c 798 uint8_t FOC_LIMIT = 0x01;
jjones646 3:dc7e9c6bc26c 799
jjones646 3:dc7e9c6bc26c 800 rfSettings.FOCCFG = 0x40 | (FOC_BS_CS_GATE<<5) | ((FOC_PRE_K & 0x03)<<3) | (FOC_POST_K<<2) | (FOC_LIMIT & 0x03);
jjones646 3:dc7e9c6bc26c 801
jjones646 3:dc7e9c6bc26c 802 rfSettings.BSCFG = 0x1C;
jjones646 3:dc7e9c6bc26c 803
jjones646 3:dc7e9c6bc26c 804 rfSettings.AGCCTRL2 = 0xC7;
jjones646 3:dc7e9c6bc26c 805 rfSettings.AGCCTRL1 = 0x00;
jjones646 3:dc7e9c6bc26c 806 rfSettings.AGCCTRL0 = 0xB0;
jjones646 3:dc7e9c6bc26c 807
jjones646 3:dc7e9c6bc26c 808 // rfSettings.FIFOTHR = 0x0F; // RXFIFO and TXFIFO thresholds.
jjones646 3:dc7e9c6bc26c 809
jjones646 3:dc7e9c6bc26c 810 // 33 byte TX FIFO & 32 byte RX FIFO
jjones646 3:dc7e9c6bc26c 811 rfSettings.FIFOTHR = 0x07; // RXFIFO and TXFIFO thresholds.
jjones646 3:dc7e9c6bc26c 812 }