For robots and stuff

Dependents:   Base Station

Committer:
jjones646
Date:
Sun Dec 28 06:27:18 2014 +0000
Revision:
0:c5afea7b9057
initial commit;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jjones646 0:c5afea7b9057 1 #include "CC1101.h"
jjones646 0:c5afea7b9057 2
jjones646 0:c5afea7b9057 3 #define DEBUG_MODE 0
jjones646 0:c5afea7b9057 4 #define ACK_SHOW 1
jjones646 0:c5afea7b9057 5
jjones646 0:c5afea7b9057 6 // 0db power
jjones646 0:c5afea7b9057 7 #define RF_DB 10
jjones646 0:c5afea7b9057 8
jjones646 0:c5afea7b9057 9 CC1101::CC1101() :
jjones646 0:c5afea7b9057 10 Radio()
jjones646 0:c5afea7b9057 11 { };
jjones646 0:c5afea7b9057 12
jjones646 0:c5afea7b9057 13 CC1101::CC1101(PinName mosi, PinName miso, PinName clk, PinName csn, PinName tx_led, PinName rx_led, PinName interpt, unsigned int xosc) :
jjones646 0:c5afea7b9057 14 Radio(_tx_led, _rx_led),
jjones646 0:c5afea7b9057 15 _crystal_freq(xosc)
jjones646 0:c5afea7b9057 16 {
jjones646 0:c5afea7b9057 17 setup_spi(mosi, miso, clk);
jjones646 0:c5afea7b9057 18 setup_pins(csn, interpt);
jjones646 0:c5afea7b9057 19 setup_chip();
jjones646 0:c5afea7b9057 20 }
jjones646 0:c5afea7b9057 21
jjones646 0:c5afea7b9057 22 // Deconstructor
jjones646 0:c5afea7b9057 23 CC1101::~CC1101()
jjones646 0:c5afea7b9057 24 {
jjones646 0:c5afea7b9057 25 if ( _spi ) {
jjones646 0:c5afea7b9057 26 delete _spi;
jjones646 0:c5afea7b9057 27 }
jjones646 0:c5afea7b9057 28 if ( _rx_int ) {
jjones646 0:c5afea7b9057 29 delete _rx_int;
jjones646 0:c5afea7b9057 30 }
jjones646 0:c5afea7b9057 31 if ( _csn ) {
jjones646 0:c5afea7b9057 32 delete _csn;
jjones646 0:c5afea7b9057 33 }
jjones646 0:c5afea7b9057 34 }
jjones646 0:c5afea7b9057 35
jjones646 0:c5afea7b9057 36 // Configuration method that is called from the constructors
jjones646 0:c5afea7b9057 37 void CC1101::setup_spi(PinName mosi, PinName miso, PinName clk)
jjones646 0:c5afea7b9057 38 {
jjones646 0:c5afea7b9057 39 if (mosi != NC & miso != NC & clk != NC) {
jjones646 0:c5afea7b9057 40 // Setup the spi for 8 bit data, high steady state clock, second edge capture
jjones646 0:c5afea7b9057 41 _so = miso;
jjones646 0:c5afea7b9057 42 _si = mosi;
jjones646 0:c5afea7b9057 43 _sck = clk;
jjones646 0:c5afea7b9057 44 _spi = new SPI(mosi, miso, clk);
jjones646 0:c5afea7b9057 45 _spi->format(8,0);
jjones646 0:c5afea7b9057 46 _spi->frequency(5000000);
jjones646 0:c5afea7b9057 47 }
jjones646 0:c5afea7b9057 48 }
jjones646 0:c5afea7b9057 49
jjones646 0:c5afea7b9057 50
jjones646 0:c5afea7b9057 51 // Configuration method that is called from the constructors
jjones646 0:c5afea7b9057 52 void CC1101::setup_pins(PinName csn, PinName int_pin)
jjones646 0:c5afea7b9057 53 {
jjones646 0:c5afea7b9057 54 if (csn != NC) {
jjones646 0:c5afea7b9057 55 _csn = new DigitalOut(csn);
jjones646 0:c5afea7b9057 56 }
jjones646 0:c5afea7b9057 57 if (int_pin != NC) {
jjones646 0:c5afea7b9057 58 InterruptIn *_rx_int = new InterruptIn(int_pin);
jjones646 0:c5afea7b9057 59 _rx_int->mode(PullDown);
jjones646 0:c5afea7b9057 60 _rx_int->rise(this, &CC1101::isr_receive); // attach member function for interrupt trigger
jjones646 0:c5afea7b9057 61 }
jjones646 0:c5afea7b9057 62 }
jjones646 0:c5afea7b9057 63
jjones646 0:c5afea7b9057 64 /*
jjones646 0:c5afea7b9057 65 // Configuration method that is called from the constructors
jjones646 0:c5afea7b9057 66 void CC1101::setup_lights(void)
jjones646 0:c5afea7b9057 67 {
jjones646 0:c5afea7b9057 68 for (int i=0; i<10; i++) {
jjones646 0:c5afea7b9057 69 _tx_led_thread.signal_set(SET_LED_TICK);
jjones646 0:c5afea7b9057 70 _rx_led_thread.signal_set(SET_LED_TICK);
jjones646 0:c5afea7b9057 71 }
jjones646 0:c5afea7b9057 72 }
jjones646 0:c5afea7b9057 73 */
jjones646 0:c5afea7b9057 74
jjones646 0:c5afea7b9057 75
jjones646 0:c5afea7b9057 76 // Configuration method that is called from the constructors
jjones646 0:c5afea7b9057 77 void CC1101::setup_chip()
jjones646 0:c5afea7b9057 78 {
jjones646 0:c5afea7b9057 79 // define an initial state of an unselected chip
jjones646 0:c5afea7b9057 80 *_csn = 1;
jjones646 0:c5afea7b9057 81
jjones646 0:c5afea7b9057 82 // frequency that radio links with another CC1101 over the air
jjones646 0:c5afea7b9057 83 _carrier_freq = _902MHZ_;
jjones646 0:c5afea7b9057 84
jjones646 0:c5afea7b9057 85 // turn off address packet filtering and assign 0 (broadcast address) to the address value
jjones646 0:c5afea7b9057 86 _pck_control.addr_check = ADDR_OFF;
jjones646 0:c5afea7b9057 87
jjones646 0:c5afea7b9057 88 // these values determine how the CC1101 will handel a packet
jjones646 0:c5afea7b9057 89 _pck_control.whitening_en = 0;
jjones646 0:c5afea7b9057 90
jjones646 0:c5afea7b9057 91 // enable CRC calculation in TX and CRC checking in RX
jjones646 0:c5afea7b9057 92 _pck_control.crc_en = 1;
jjones646 0:c5afea7b9057 93
jjones646 0:c5afea7b9057 94 // enable automatically flushing the RX buffer on a bad CRC (only works if 1 packet is in the RX buffer)
jjones646 0:c5afea7b9057 95 _pck_control.autoflush_en = 1;
jjones646 0:c5afea7b9057 96
jjones646 0:c5afea7b9057 97 // enable appending 2 status bytes to the end of every packet that includes the CRC and
jjones646 0:c5afea7b9057 98 _pck_control.status_field_en = 1;
jjones646 0:c5afea7b9057 99
jjones646 0:c5afea7b9057 100 // normal packet mode uses RX and TX buffers
jjones646 0:c5afea7b9057 101 _pck_control.format_type = FORMAT_DEFAULT;
jjones646 0:c5afea7b9057 102
jjones646 0:c5afea7b9057 103 // setup how the payload of the packet is transmitted - default to a fixed length of 61 bytes
jjones646 0:c5afea7b9057 104 _pck_control.length_type = PACKET_VARIABLE;
jjones646 0:c5afea7b9057 105
jjones646 0:c5afea7b9057 106 //_pck_control.length_type = PACKET_FIXED;
jjones646 0:c5afea7b9057 107 //_pck_control.size = 61;
jjones646 0:c5afea7b9057 108
jjones646 0:c5afea7b9057 109 // this is a preamble threshold for determining when a packet should be accepted
jjones646 0:c5afea7b9057 110 _pck_control.preamble_thresh = 2;
jjones646 0:c5afea7b9057 111
jjones646 0:c5afea7b9057 112 // these values determine how the frequency bands and channels are distributed as well as defining the modulation type
jjones646 0:c5afea7b9057 113 _modem.dc_filter_off_en = 0;
jjones646 0:c5afea7b9057 114 _modem.manchester_encode_en = 0;
jjones646 0:c5afea7b9057 115 _modem.fec_en = 0;
jjones646 0:c5afea7b9057 116
jjones646 0:c5afea7b9057 117 // bandwidth configurations
jjones646 0:c5afea7b9057 118 _modem.channel_bw = 2;
jjones646 0:c5afea7b9057 119 _modem.channel_bw_exp = 0;
jjones646 0:c5afea7b9057 120 _modem.channel_space_exp = 2;
jjones646 0:c5afea7b9057 121 _modem.data_rate_exp = 13;
jjones646 0:c5afea7b9057 122
jjones646 0:c5afea7b9057 123 _modem.mod_type = MOD_GFSK;
jjones646 0:c5afea7b9057 124 _modem.sync_mode = SYNC_HIGH_ALLOW_TWO;
jjones646 0:c5afea7b9057 125 _modem.preamble_bytes = PREAM_FOUR;
jjones646 0:c5afea7b9057 126
jjones646 0:c5afea7b9057 127 _send_count = 1;
jjones646 0:c5afea7b9057 128 _receive_count = 0;
jjones646 0:c5afea7b9057 129
jjones646 0:c5afea7b9057 130 // the values assigned here are used for the frequency synthesizer control
jjones646 0:c5afea7b9057 131 assign_if_freq(_316KHZ_);
jjones646 0:c5afea7b9057 132 assign_freq_offset(0);
jjones646 0:c5afea7b9057 133
jjones646 0:c5afea7b9057 134 // set all the configuration values into the rfSettings struct
jjones646 0:c5afea7b9057 135 set_rf_settings();
jjones646 0:c5afea7b9057 136
jjones646 0:c5afea7b9057 137 // get the chip's partnumber
jjones646 0:c5afea7b9057 138 _partnum = status(CCxxx0_PARTNUM);
jjones646 0:c5afea7b9057 139
jjones646 0:c5afea7b9057 140 // get the chip's version number and fail if different from what was expected
jjones646 0:c5afea7b9057 141 _chip_version = status(CCxxx0_VERSION);
jjones646 0:c5afea7b9057 142 uint8_t expected_version = 0x04;
jjones646 0:c5afea7b9057 143
jjones646 0:c5afea7b9057 144 if (_chip_version != expected_version) {
jjones646 0:c5afea7b9057 145
jjones646 0:c5afea7b9057 146 // write results to the log file before killing mbed from going any further
jjones646 0:c5afea7b9057 147 #if RJ_BOOT_LOG
jjones646 0:c5afea7b9057 148 FILE *fp = fopen("/local/log.txt", "a"); // Open text file for tracking boot sequence results
jjones646 0:c5afea7b9057 149 if (fp == NULL) {
jjones646 0:c5afea7b9057 150 error("Could not get file pointer to log file\r\n");
jjones646 0:c5afea7b9057 151 }
jjones646 0:c5afea7b9057 152 fprintf(fp, "FATAL ERROR: CC1101 Version Error\n");
jjones646 0:c5afea7b9057 153 fclose(fp);
jjones646 0:c5afea7b9057 154 #endif
jjones646 0:c5afea7b9057 155 // send message over serial port and kill mbed
jjones646 0:c5afea7b9057 156 error(
jjones646 0:c5afea7b9057 157 "[FATAL ERROR]\r\n"
jjones646 0:c5afea7b9057 158 " Wrong version number returned from chip's 'VERSION' register (Addr: 0x%02X)\r\n"
jjones646 0:c5afea7b9057 159 "\r\n"
jjones646 0:c5afea7b9057 160 " Expected: 0x%02X\r\n"
jjones646 0:c5afea7b9057 161 " Found: 0x%02X\r\n"
jjones646 0:c5afea7b9057 162 "\r\n"
jjones646 0:c5afea7b9057 163 " Troubleshooting Tips:\r\n"
jjones646 0:c5afea7b9057 164 " - Check that the chip is fully connected with no soldering errors\r\n"
jjones646 0:c5afea7b9057 165 " - Determine if chip is newer version & update firmware\r\n"
jjones646 0:c5afea7b9057 166 , CCxxx0_VERSION, expected_version, _chip_version);
jjones646 0:c5afea7b9057 167 }
jjones646 0:c5afea7b9057 168 }
jjones646 0:c5afea7b9057 169
jjones646 0:c5afea7b9057 170
jjones646 0:c5afea7b9057 171 void powerUp(void)
jjones646 0:c5afea7b9057 172 {
jjones646 0:c5afea7b9057 173 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 174 std::printf("[CC1101 RADIO TRANSCEIVER INITILIZATION]\r\n");
jjones646 0:c5afea7b9057 175 #endif
jjones646 0:c5afea7b9057 176 // execute a power-on-reset call to the CC1101 before writing all configuration values
jjones646 0:c5afea7b9057 177 power_on_reset();
jjones646 0:c5afea7b9057 178
jjones646 0:c5afea7b9057 179 // now send the assigned rfSettings struct to the CC1101 for full inililization
jjones646 0:c5afea7b9057 180 init();
jjones646 0:c5afea7b9057 181
jjones646 0:c5afea7b9057 182 scan();
jjones646 0:c5afea7b9057 183
jjones646 0:c5afea7b9057 184 // start the regular class operations for the thread. This should always be the last call in the constructor!
jjones646 0:c5afea7b9057 185 _transmit_thread.signal_set(START_THREAD);
jjones646 0:c5afea7b9057 186 _receive_thread.signal_set(START_THREAD);
jjones646 0:c5afea7b9057 187
jjones646 0:c5afea7b9057 188
jjones646 0:c5afea7b9057 189 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 190 uint8_t start_address = 0x00;
jjones646 0:c5afea7b9057 191 uint16_t reg_count = 46;
jjones646 0:c5afea7b9057 192 uint8_t buf[reg_count];
jjones646 0:c5afea7b9057 193
jjones646 0:c5afea7b9057 194 read_reg(start_address ,buf, reg_count);
jjones646 0:c5afea7b9057 195 std::printf("\r\nDumping CC1101 register contents\r\n ___________________\r\n | Address | Value |\r\n |===================|\r\n");
jjones646 0:c5afea7b9057 196 for (int i = 0; i<reg_count+1; i++) {
jjones646 0:c5afea7b9057 197 std::printf(" | 0x%02X | 0x%02X |\r\n", start_address + i, buf[start_address + i]);
jjones646 0:c5afea7b9057 198 }
jjones646 0:c5afea7b9057 199
jjones646 0:c5afea7b9057 200 std::printf(" |_________|_________|\r\n\r\nDumping CC1101 status register conetnts\r\n ___________________\r\n | Address | Value |\r\n |===================|\r\n");
jjones646 0:c5afea7b9057 201 for (int i = 0; i<14; i++) {
jjones646 0:c5afea7b9057 202 std::printf(" | 0x%02X | 0x%02X |\r\n", CCxxx0_PARTNUM + i, status(CCxxx0_PARTNUM + i));
jjones646 0:c5afea7b9057 203 }
jjones646 0:c5afea7b9057 204 std::printf(" |_________|_________|\r\n\r\n");
jjones646 0:c5afea7b9057 205 #endif
jjones646 0:c5afea7b9057 206
jjones646 0:c5afea7b9057 207 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 208 compute_freq();
jjones646 0:c5afea7b9057 209 std::printf(" CC1101 READY!\r\n Chip Version: %-02u\r\n Channel: %-02u\r\n Frequency: %-3.2f MHz\r\n Baud Rate: %3u kHz\r\n", _chip_version, Radio::channel(), static_cast<float>(Radio::freq()/1000000), _baud_rate/1000 );
jjones646 0:c5afea7b9057 210 #endif
jjones646 0:c5afea7b9057 211
jjones646 0:c5afea7b9057 212 }
jjones646 0:c5afea7b9057 213
jjones646 0:c5afea7b9057 214 // ===============
jjones646 0:c5afea7b9057 215 void CC1101::set_rf_settings()
jjones646 0:c5afea7b9057 216 {
jjones646 0:c5afea7b9057 217 // set rfSettings carrier frequency fields
jjones646 0:c5afea7b9057 218 freq(_carrier_freq);
jjones646 0:c5afea7b9057 219
jjones646 0:c5afea7b9057 220 // set the fields for packet controls
jjones646 0:c5afea7b9057 221 assign_packet_params();
jjones646 0:c5afea7b9057 222
jjones646 0:c5afea7b9057 223 // set the fields for the frequency limits of the modem
jjones646 0:c5afea7b9057 224 assign_modem_params();
jjones646 0:c5afea7b9057 225
jjones646 0:c5afea7b9057 226 // assign an address to the CC1101. This can be used to filter packets
jjones646 0:c5afea7b9057 227 rfSettings.ADDR = _addr;
jjones646 0:c5afea7b9057 228
jjones646 0:c5afea7b9057 229 // there can be 16 different channel numbers. The bandwidth and spacing are defined in other registers
jjones646 0:c5afea7b9057 230 rfSettings.CHANNR = _channel;
jjones646 0:c5afea7b9057 231
jjones646 0:c5afea7b9057 232 // compute the final adjusted frequency so that it will be correct after the constructor
jjones646 0:c5afea7b9057 233 compute_freq();
jjones646 0:c5afea7b9057 234
jjones646 0:c5afea7b9057 235 assign_baud_rate(250000); // 250 kBaud
jjones646 0:c5afea7b9057 236
jjones646 0:c5afea7b9057 237 assign_channel_spacing(200000); // 200kHz
jjones646 0:c5afea7b9057 238
jjones646 0:c5afea7b9057 239 // disable GDO0
jjones646 0:c5afea7b9057 240 rfSettings.IOCFG0 = 0x2E;
jjones646 0:c5afea7b9057 241
jjones646 0:c5afea7b9057 242 // setup for serial synchronous data output
jjones646 0:c5afea7b9057 243 rfSettings.IOCFG1 = 0x0C;
jjones646 0:c5afea7b9057 244
jjones646 0:c5afea7b9057 245 // setup for going HIGH when packet received and CRC is ok
jjones646 0:c5afea7b9057 246 rfSettings.IOCFG2 = 0x07;
jjones646 0:c5afea7b9057 247
jjones646 0:c5afea7b9057 248 rfSettings.DEVIATN = 0x62;
jjones646 0:c5afea7b9057 249
jjones646 0:c5afea7b9057 250 rfSettings.FREND1 = 0xB6;
jjones646 0:c5afea7b9057 251 rfSettings.FREND0 = 0x10;
jjones646 0:c5afea7b9057 252
jjones646 0:c5afea7b9057 253 bool RX_TIME_RSSI = 0;
jjones646 0:c5afea7b9057 254 bool RX_TIME_QUAL = 0;
jjones646 0:c5afea7b9057 255 uint8_t RX_TIME = 0x07; // no timeout
jjones646 0:c5afea7b9057 256
jjones646 0:c5afea7b9057 257 rfSettings.MCSM2 = (RX_TIME_RSSI<<4) | (RX_TIME_QUAL<<3) | (RX_TIME & 0x07);
jjones646 0:c5afea7b9057 258
jjones646 0:c5afea7b9057 259 uint8_t CCA_MODE = 0x00;
jjones646 0:c5afea7b9057 260 uint8_t RXOFF_MODE = 0x00; // go directly to IDLE when existing RX
jjones646 0:c5afea7b9057 261 //uint8_t RXOFF_MODE = 0x03; // stay in RX when existing RX
jjones646 0:c5afea7b9057 262 uint8_t TXOFF_MODE = 0x03; // go directly to RX when existing TX
jjones646 0:c5afea7b9057 263 // uint8_t TXOFF_MODE = 0x00; // go directly to IDLE when existing TX
jjones646 0:c5afea7b9057 264
jjones646 0:c5afea7b9057 265 rfSettings.MCSM1 = ((CCA_MODE & 0x03)<<4) | ((RXOFF_MODE & 0x03)<<2) | (TXOFF_MODE & 0x03);
jjones646 0:c5afea7b9057 266
jjones646 0:c5afea7b9057 267 uint8_t FS_AUTOCAL = 0x01; // calibrate when going from IDLE to RX or TX
jjones646 0:c5afea7b9057 268 uint8_t PO_TIMEOUT = 0x02;
jjones646 0:c5afea7b9057 269 bool PIN_CTRL_EN = 0;
jjones646 0:c5afea7b9057 270 bool XOSC_FORCE_ON = 0;
jjones646 0:c5afea7b9057 271
jjones646 0:c5afea7b9057 272 rfSettings.MCSM0 = ((FS_AUTOCAL & 0x03)<<4) | ((PO_TIMEOUT & 0x03)<<2) | (PIN_CTRL_EN<<1) | (XOSC_FORCE_ON);
jjones646 0:c5afea7b9057 273
jjones646 0:c5afea7b9057 274 bool FOC_BS_CS_GATE = 0;
jjones646 0:c5afea7b9057 275 uint8_t FOC_PRE_K = 0x03;
jjones646 0:c5afea7b9057 276 bool FOC_POST_K = 1;
jjones646 0:c5afea7b9057 277 uint8_t FOC_LIMIT = 0x01;
jjones646 0:c5afea7b9057 278
jjones646 0:c5afea7b9057 279 rfSettings.FOCCFG = 0x40 | (FOC_BS_CS_GATE<<5) | ((FOC_PRE_K & 0x03)<<3) | (FOC_POST_K<<2) | (FOC_LIMIT & 0x03);
jjones646 0:c5afea7b9057 280
jjones646 0:c5afea7b9057 281 rfSettings.BSCFG = 0x1C;
jjones646 0:c5afea7b9057 282
jjones646 0:c5afea7b9057 283 rfSettings.AGCCTRL2 = 0xC7;
jjones646 0:c5afea7b9057 284 rfSettings.AGCCTRL1 = 0x00;
jjones646 0:c5afea7b9057 285 rfSettings.AGCCTRL0 = 0xB0;
jjones646 0:c5afea7b9057 286
jjones646 0:c5afea7b9057 287 // rfSettings.FIFOTHR = 0x0F; // RXFIFO and TXFIFO thresholds.
jjones646 0:c5afea7b9057 288
jjones646 0:c5afea7b9057 289 // 33 byte TX FIFO & 32 byte RX FIFO
jjones646 0:c5afea7b9057 290 rfSettings.FIFOTHR = 0x07; // RXFIFO and TXFIFO thresholds.
jjones646 0:c5afea7b9057 291 }
jjones646 0:c5afea7b9057 292
jjones646 0:c5afea7b9057 293 #if RF_DB == 0
jjones646 0:c5afea7b9057 294 // PATABLE (0 dBm output power)
jjones646 0:c5afea7b9057 295 char paTable[] = {0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
jjones646 0:c5afea7b9057 296 #elif RF_DB == 10
jjones646 0:c5afea7b9057 297 // PATABLE (10 dBm output power)
jjones646 0:c5afea7b9057 298 char paTable[] = {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
jjones646 0:c5afea7b9057 299 #endif
jjones646 0:c5afea7b9057 300
jjones646 0:c5afea7b9057 301
jjones646 0:c5afea7b9057 302 // ===============
jjones646 0:c5afea7b9057 303 void CC1101::assign_baud_rate(uint32_t rate)
jjones646 0:c5afea7b9057 304 {
jjones646 0:c5afea7b9057 305 // update the baud rate class member
jjones646 0:c5afea7b9057 306 _baud_rate = rate;
jjones646 0:c5afea7b9057 307
jjones646 0:c5afea7b9057 308 // have to be careful with bit shifting here since it requires a large amount of shifts
jjones646 0:c5afea7b9057 309 uint32_t shift_val = 28 - (_modem.data_rate_exp & 0x0F);
jjones646 0:c5afea7b9057 310
jjones646 0:c5afea7b9057 311 // compute the register value and assign it
jjones646 0:c5afea7b9057 312 rfSettings.MDMCFG3 = ((_baud_rate)/(_crystal_freq>>shift_val)) - 256;
jjones646 0:c5afea7b9057 313 }
jjones646 0:c5afea7b9057 314
jjones646 0:c5afea7b9057 315
jjones646 0:c5afea7b9057 316 // ===============
jjones646 0:c5afea7b9057 317 void CC1101::assign_channel_spacing(uint32_t freq)
jjones646 0:c5afea7b9057 318 {
jjones646 0:c5afea7b9057 319 // update the channel spacing frequency's class member
jjones646 0:c5afea7b9057 320 _channel_spacing = freq;
jjones646 0:c5afea7b9057 321
jjones646 0:c5afea7b9057 322 // have to be careful with bit shifting here since it requires a large amount of shifts
jjones646 0:c5afea7b9057 323 uint32_t shift_val = 18 - (_modem.channel_space_exp & 0x03);
jjones646 0:c5afea7b9057 324
jjones646 0:c5afea7b9057 325 // compute the register value and assign it
jjones646 0:c5afea7b9057 326 rfSettings.MDMCFG0 = (_channel_spacing/(_crystal_freq>>shift_val)) - 256;
jjones646 0:c5afea7b9057 327 }
jjones646 0:c5afea7b9057 328
jjones646 0:c5afea7b9057 329
jjones646 0:c5afea7b9057 330 // ===============
jjones646 0:c5afea7b9057 331 void CC1101::assign_modem_params()
jjones646 0:c5afea7b9057 332 {
jjones646 0:c5afea7b9057 333 rfSettings.MDMCFG4 = (_modem.channel_bw_exp & 0x03)<<6 | (_modem.channel_bw & 0x03)<<4 | (_modem.data_rate_exp & 0x0F);
jjones646 0:c5afea7b9057 334 rfSettings.MDMCFG2 = _modem.dc_filter_off_en<<7 | (_modem.mod_type & 0x07)<<4 | _modem.manchester_encode_en<<3 | (_modem.sync_mode & 0x07);
jjones646 0:c5afea7b9057 335 rfSettings.MDMCFG1 = _modem.fec_en<<7 | (_modem.preamble_bytes & 0x07)<<4 | (_modem.channel_space_exp & 0x03);
jjones646 0:c5afea7b9057 336 }
jjones646 0:c5afea7b9057 337
jjones646 0:c5afea7b9057 338 // ===============
jjones646 0:c5afea7b9057 339 void CC1101::assign_packet_params()
jjones646 0:c5afea7b9057 340 {
jjones646 0:c5afea7b9057 341 rfSettings.PCKCTRL0 = _pck_control.whitening_en<<6 | (_pck_control.format_type & 0x3)<<4 | _pck_control.crc_en<<2 | (_pck_control.length_type & 0x3);
jjones646 0:c5afea7b9057 342 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 0:c5afea7b9057 343 rfSettings.PCKLEN = _pck_control.size;
jjones646 0:c5afea7b9057 344 }
jjones646 0:c5afea7b9057 345
jjones646 0:c5afea7b9057 346
jjones646 0:c5afea7b9057 347 void CC1101::assign_if_freq(uint32_t freq)
jjones646 0:c5afea7b9057 348 {
jjones646 0:c5afea7b9057 349 // The desired IF frequency for RX. Subtracted from FS base frequency in RX.
jjones646 0:c5afea7b9057 350 // bits 7..5 are always 0
jjones646 0:c5afea7b9057 351 _if_freq = freq;
jjones646 0:c5afea7b9057 352 rfSettings.FSCTRL1 = (_if_freq/(_crystal_freq>>10)) & 0x1F;
jjones646 0:c5afea7b9057 353 rfSettings.FSCTRL0 = 0x00; // set the initial freq calibration to 0
jjones646 0:c5afea7b9057 354 }
jjones646 0:c5afea7b9057 355
jjones646 0:c5afea7b9057 356
jjones646 0:c5afea7b9057 357 // computes the final adjusted operating frequency
jjones646 0:c5afea7b9057 358 void CC1101::compute_freq()
jjones646 0:c5afea7b9057 359 {
jjones646 0:c5afea7b9057 360 // there's no need to make this heavy computation numerous times when it rarely ever changes - that's why it has its own class method
jjones646 0:c5afea7b9057 361 uint32_t freq = (rfSettings.FREQ2<<16) | (rfSettings.FREQ1<<8) | (rfSettings.FREQ0);
jjones646 0:c5afea7b9057 362 uint32_t offset = (_channel & 0xFF)*((256 + rfSettings.MDMCFG0)<<(_modem.channel_space_exp & 0x03));
jjones646 0:c5afea7b9057 363 _freq = (_crystal_freq>>16)*(freq + offset); // set the frequency from the base class
jjones646 0:c5afea7b9057 364 }
jjones646 0:c5afea7b9057 365
jjones646 0:c5afea7b9057 366
jjones646 0:c5afea7b9057 367 // SET FREQUENCY
jjones646 0:c5afea7b9057 368 void CC1101::freq(uint32_t freq)
jjones646 0:c5afea7b9057 369 {
jjones646 0:c5afea7b9057 370 /* calculate the value that is written to the register for settings the base frequency
jjones646 0:c5afea7b9057 371 * that the CC1101 should use for sending/receiving over the air. Default value is equivalent
jjones646 0:c5afea7b9057 372 * to 901.83 MHz.
jjones646 0:c5afea7b9057 373 */
jjones646 0:c5afea7b9057 374
jjones646 0:c5afea7b9057 375 // update the class's frequency value
jjones646 0:c5afea7b9057 376 _carrier_freq = freq;
jjones646 0:c5afea7b9057 377
jjones646 0:c5afea7b9057 378 // this is split into 3 bytes that are written to 3 different registers on the CC1101
jjones646 0:c5afea7b9057 379 uint32_t reg_freq = _carrier_freq / (_crystal_freq>>16);
jjones646 0:c5afea7b9057 380
jjones646 0:c5afea7b9057 381 rfSettings.FREQ2 = (reg_freq>>16) & 0xFF; // high byte, bits 7..6 are always 0 for this register
jjones646 0:c5afea7b9057 382 rfSettings.FREQ1 = (reg_freq>>8) & 0xFF; // middle byte
jjones646 0:c5afea7b9057 383 rfSettings.FREQ0 = reg_freq & 0xFF; // low byte
jjones646 0:c5afea7b9057 384 }
jjones646 0:c5afea7b9057 385
jjones646 0:c5afea7b9057 386
jjones646 0:c5afea7b9057 387 // set the device's hardware address (8 bits)
jjones646 0:c5afea7b9057 388 void CC1101::address(uint8_t addr)
jjones646 0:c5afea7b9057 389 {
jjones646 0:c5afea7b9057 390 _addr = addr;
jjones646 0:c5afea7b9057 391 }
jjones646 0:c5afea7b9057 392
jjones646 0:c5afea7b9057 393
jjones646 0:c5afea7b9057 394 // returns the CC1101's VERSION register that specifices what exact chip version is being used
jjones646 0:c5afea7b9057 395 uint8_t CC1101::version(void)
jjones646 0:c5afea7b9057 396 {
jjones646 0:c5afea7b9057 397 return _chip_version;
jjones646 0:c5afea7b9057 398 }
jjones646 0:c5afea7b9057 399
jjones646 0:c5afea7b9057 400
jjones646 0:c5afea7b9057 401 // return's the part number for the CC1101 chip being used
jjones646 0:c5afea7b9057 402 uint8_t CC1101::partnum(void)
jjones646 0:c5afea7b9057 403 {
jjones646 0:c5afea7b9057 404 return _partnum;
jjones646 0:c5afea7b9057 405 }
jjones646 0:c5afea7b9057 406
jjones646 0:c5afea7b9057 407
jjones646 0:c5afea7b9057 408 // returns the current mode that the CC1101 is operating in
jjones646 0:c5afea7b9057 409 uint8_t CC1101::mode(void)
jjones646 0:c5afea7b9057 410 {
jjones646 0:c5afea7b9057 411 return status(CCxxx0_MARCSTATE);
jjones646 0:c5afea7b9057 412 }
jjones646 0:c5afea7b9057 413
jjones646 0:c5afea7b9057 414
jjones646 0:c5afea7b9057 415 // returns the LQI value from the most recently received packet
jjones646 0:c5afea7b9057 416 uint8_t CC1101::lqi(void)
jjones646 0:c5afea7b9057 417 {
jjones646 0:c5afea7b9057 418 return 0x3F - (_lqi & 0x3F);
jjones646 0:c5afea7b9057 419 }
jjones646 0:c5afea7b9057 420
jjones646 0:c5afea7b9057 421
jjones646 0:c5afea7b9057 422 // update the channel within the class and also update the CC1101's channel register
jjones646 0:c5afea7b9057 423 void CC1101::channel(uint8_t chan)
jjones646 0:c5afea7b9057 424 {
jjones646 0:c5afea7b9057 425 // only update channel numbers that are valid (8 bits)
jjones646 0:c5afea7b9057 426 if ( chan != _channel ) {
jjones646 0:c5afea7b9057 427 // channels start at 0 for the CC1101. this subtracts 1 before saving the channel number for the reason defined in the _channel member's getter method
jjones646 0:c5afea7b9057 428 _channel = chan;
jjones646 0:c5afea7b9057 429
jjones646 0:c5afea7b9057 430 // update the value with the CC1101's channel number register
jjones646 0:c5afea7b9057 431 write_reg(CCxxx0_CHANNR, _channel);
jjones646 0:c5afea7b9057 432
jjones646 0:c5afea7b9057 433 // recalculate the adjusted frequency value since the channel number has changed
jjones646 0:c5afea7b9057 434 compute_freq();
jjones646 0:c5afea7b9057 435
jjones646 0:c5afea7b9057 436 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 437 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 0:c5afea7b9057 438 #endif
jjones646 0:c5afea7b9057 439 }
jjones646 0:c5afea7b9057 440 }
jjones646 0:c5afea7b9057 441
jjones646 0:c5afea7b9057 442
jjones646 0:c5afea7b9057 443 // returns the RSSI value from the most recently received packet
jjones646 0:c5afea7b9057 444 uint8_t CC1101::rssi(void)
jjones646 0:c5afea7b9057 445 {
jjones646 0:c5afea7b9057 446 return _rssi;
jjones646 0:c5afea7b9057 447 }
jjones646 0:c5afea7b9057 448
jjones646 0:c5afea7b9057 449 void CC1101::rssi(uint8_t rssi_reg)
jjones646 0:c5afea7b9057 450 {
jjones646 0:c5afea7b9057 451 int8_t temp;
jjones646 0:c5afea7b9057 452
jjones646 0:c5afea7b9057 453 if (rssi_reg & 0x80) {
jjones646 0:c5afea7b9057 454 temp = (rssi_reg - 256)>>1;
jjones646 0:c5afea7b9057 455 } else {
jjones646 0:c5afea7b9057 456 temp = rssi_reg>>1; // divide by 2
jjones646 0:c5afea7b9057 457 }
jjones646 0:c5afea7b9057 458 _rssi = temp - 74;
jjones646 0:c5afea7b9057 459 }
jjones646 0:c5afea7b9057 460
jjones646 0:c5afea7b9057 461
jjones646 0:c5afea7b9057 462 // Assign the offset frequency to the class definition
jjones646 0:c5afea7b9057 463 void CC1101::assign_freq_offset(uint8_t freq)
jjones646 0:c5afea7b9057 464 {
jjones646 0:c5afea7b9057 465 _offset_freq = freq;
jjones646 0:c5afea7b9057 466 }
jjones646 0:c5afea7b9057 467
jjones646 0:c5afea7b9057 468
jjones646 0:c5afea7b9057 469 // Macro to calibrate the frequency synthesizer
jjones646 0:c5afea7b9057 470 void CC1101::calibrate()
jjones646 0:c5afea7b9057 471 {
jjones646 0:c5afea7b9057 472 // Send the calibration strobe
jjones646 0:c5afea7b9057 473 strobe(CCxxx0_SCAL);
jjones646 0:c5afea7b9057 474
jjones646 0:c5afea7b9057 475 // Wait for the radio to leave the calibration step
jjones646 0:c5afea7b9057 476 while( (mode() == 0x04) | (mode() == 0x05) );
jjones646 0:c5afea7b9057 477
jjones646 0:c5afea7b9057 478 // The radio is now is IDLE mode, so go to RX mode
jjones646 0:c5afea7b9057 479 rx_mode();
jjones646 0:c5afea7b9057 480
jjones646 0:c5afea7b9057 481 // Wait for the radio to enter back into RX mode
jjones646 0:c5afea7b9057 482 while( mode() != 0x0D );
jjones646 0:c5afea7b9057 483 }
jjones646 0:c5afea7b9057 484
jjones646 0:c5afea7b9057 485
jjones646 0:c5afea7b9057 486 // Macro to reset the CCxxx0 and wait for it to be ready
jjones646 0:c5afea7b9057 487 void CC1101::reset(void)
jjones646 0:c5afea7b9057 488 {
jjones646 0:c5afea7b9057 489 strobe(CCxxx0_SRES);
jjones646 0:c5afea7b9057 490 }
jjones646 0:c5afea7b9057 491
jjones646 0:c5afea7b9057 492
jjones646 0:c5afea7b9057 493 void CC1101::power_on_reset(void)
jjones646 0:c5afea7b9057 494 {
jjones646 0:c5afea7b9057 495 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 496 std::printf(" Starting Power-on-Reset procedure...");
jjones646 0:c5afea7b9057 497 #endif
jjones646 0:c5afea7b9057 498 delete _spi;
jjones646 0:c5afea7b9057 499
jjones646 0:c5afea7b9057 500 // make sure chip is not selected
jjones646 0:c5afea7b9057 501 *_csn = 1;
jjones646 0:c5afea7b9057 502
jjones646 0:c5afea7b9057 503 DigitalOut *SI = new DigitalOut(_si);
jjones646 0:c5afea7b9057 504 DigitalOut *SCK = new DigitalOut(_sck);
jjones646 0:c5afea7b9057 505 DigitalIn *SO = new DigitalIn(_so);
jjones646 0:c5afea7b9057 506
jjones646 0:c5afea7b9057 507 // bring SPI lines to a defined state. Reasons are outlined in CC1101 datasheet - section 11.3
jjones646 0:c5afea7b9057 508 *SI = 0;
jjones646 0:c5afea7b9057 509 *SCK = 1;
jjones646 0:c5afea7b9057 510
jjones646 0:c5afea7b9057 511 // toggle chip select and remain in high state afterwards
jjones646 0:c5afea7b9057 512 *_csn = 0;
jjones646 0:c5afea7b9057 513 *_csn = 1;
jjones646 0:c5afea7b9057 514
jjones646 0:c5afea7b9057 515 // wait at least 40us
jjones646 0:c5afea7b9057 516 wait_us(45);
jjones646 0:c5afea7b9057 517
jjones646 0:c5afea7b9057 518 // pull CSn low & wait for the serial out line to go low
jjones646 0:c5afea7b9057 519 *_csn = 0;
jjones646 0:c5afea7b9057 520
jjones646 0:c5afea7b9057 521 while(*SO);
jjones646 0:c5afea7b9057 522
jjones646 0:c5afea7b9057 523 // cleanup everything before the mbed's SPI library calls take back over
jjones646 0:c5afea7b9057 524 delete SI;
jjones646 0:c5afea7b9057 525 delete SO;
jjones646 0:c5afea7b9057 526 delete SCK;
jjones646 0:c5afea7b9057 527
jjones646 0:c5afea7b9057 528 // reestablish the SPI bus and call the reset strobe
jjones646 0:c5afea7b9057 529 setup_spi(_si, _so, _sck);
jjones646 0:c5afea7b9057 530 reset();
jjones646 0:c5afea7b9057 531
jjones646 0:c5afea7b9057 532 delete _spi;
jjones646 0:c5afea7b9057 533 // wait for the SO line to go low again. Once low, reset is complete and CC1101 is in IDLE state
jjones646 0:c5afea7b9057 534 DigitalIn *SO2 = new DigitalIn(_so);
jjones646 0:c5afea7b9057 535 while(*SO2);
jjones646 0:c5afea7b9057 536
jjones646 0:c5afea7b9057 537 // make sure chip is deselected before returning
jjones646 0:c5afea7b9057 538 *_csn = 1;
jjones646 0:c5afea7b9057 539
jjones646 0:c5afea7b9057 540 // reestablish the SPI bus for the final time after removing the DigitalIn object
jjones646 0:c5afea7b9057 541 delete SO2;
jjones646 0:c5afea7b9057 542 setup_spi(_si, _so, _sck);
jjones646 0:c5afea7b9057 543
jjones646 0:c5afea7b9057 544 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 545 std::printf("done\r\n");
jjones646 0:c5afea7b9057 546 #endif
jjones646 0:c5afea7b9057 547 }
jjones646 0:c5afea7b9057 548
jjones646 0:c5afea7b9057 549 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 550 uint8_t CC1101::status(void)
jjones646 0:c5afea7b9057 551 {
jjones646 0:c5afea7b9057 552 return strobe(CCxxx0_SNOP);
jjones646 0:c5afea7b9057 553 }
jjones646 0:c5afea7b9057 554
jjones646 0:c5afea7b9057 555 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 556 // uint8_t status(uint8_t addr)
jjones646 0:c5afea7b9057 557 //
jjones646 0:c5afea7b9057 558 // DESCRIPTION:
jjones646 0:c5afea7b9057 559 // This function reads a CCxxx0 status register.
jjones646 0:c5afea7b9057 560 //
jjones646 0:c5afea7b9057 561 // ARGUMENTS:
jjones646 0:c5afea7b9057 562 // uint8_t addr
jjones646 0:c5afea7b9057 563 // Address of the CCxxx0 status register to be accessed.
jjones646 0:c5afea7b9057 564 //
jjones646 0:c5afea7b9057 565 // RETURN VALUE:
jjones646 0:c5afea7b9057 566 // uint8_t
jjones646 0:c5afea7b9057 567 // Value of the accessed CCxxx0 status register.
jjones646 0:c5afea7b9057 568 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 569 uint8_t CC1101::status(uint8_t addr)
jjones646 0:c5afea7b9057 570 {
jjones646 0:c5afea7b9057 571 *_csn = 0;
jjones646 0:c5afea7b9057 572 _spi->write(addr | READ_BURST);
jjones646 0:c5afea7b9057 573 tiny_delay();
jjones646 0:c5afea7b9057 574 uint8_t x = _spi->write(0);
jjones646 0:c5afea7b9057 575 *_csn = 1;
jjones646 0:c5afea7b9057 576 return x;
jjones646 0:c5afea7b9057 577 }// status
jjones646 0:c5afea7b9057 578
jjones646 0:c5afea7b9057 579
jjones646 0:c5afea7b9057 580 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 581 // uint8_t strobe(uint8_t strobe)
jjones646 0:c5afea7b9057 582 //
jjones646 0:c5afea7b9057 583 // DESCRIPTION:
jjones646 0:c5afea7b9057 584 // Function for writing a strobe command to the CCxxx0
jjones646 0:c5afea7b9057 585 //
jjones646 0:c5afea7b9057 586 // ARGUMENTS:
jjones646 0:c5afea7b9057 587 // uint8_t strobe
jjones646 0:c5afea7b9057 588 // strobe command
jjones646 0:c5afea7b9057 589 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 590 uint8_t CC1101::strobe(uint8_t strobe)
jjones646 0:c5afea7b9057 591 {
jjones646 0:c5afea7b9057 592 *_csn = 0;
jjones646 0:c5afea7b9057 593 uint8_t x = _spi->write(strobe);
jjones646 0:c5afea7b9057 594 *_csn = 1;
jjones646 0:c5afea7b9057 595 return x;
jjones646 0:c5afea7b9057 596 }// strobe
jjones646 0:c5afea7b9057 597
jjones646 0:c5afea7b9057 598
jjones646 0:c5afea7b9057 599 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 600 // void put_rf_settings(rf_settings_t *pRfSettings)
jjones646 0:c5afea7b9057 601 //
jjones646 0:c5afea7b9057 602 // DESCRIPTION:
jjones646 0:c5afea7b9057 603 // This function is used to configure the CCxxx0 based on a given rf setting
jjones646 0:c5afea7b9057 604 //
jjones646 0:c5afea7b9057 605 // ARGUMENTS:
jjones646 0:c5afea7b9057 606 // rf_settings_t *pRfSettings
jjones646 0:c5afea7b9057 607 // Pointer to a struct containing rf register settings
jjones646 0:c5afea7b9057 608 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 609 void CC1101::put_rf_settings()
jjones646 0:c5afea7b9057 610 {
jjones646 0:c5afea7b9057 611 write_reg(CCxxx0_IOCFG2, rfSettings.IOCFG2);
jjones646 0:c5afea7b9057 612 write_reg(CCxxx0_IOCFG1, rfSettings.IOCFG1);
jjones646 0:c5afea7b9057 613 write_reg(CCxxx0_IOCFG0, rfSettings.IOCFG0);
jjones646 0:c5afea7b9057 614 write_reg(CCxxx0_FIFOTHR, rfSettings.FIFOTHR);
jjones646 0:c5afea7b9057 615 // SYNC1
jjones646 0:c5afea7b9057 616 // SYNC0
jjones646 0:c5afea7b9057 617 write_reg(CCxxx0_PCKLEN, rfSettings.PCKLEN);
jjones646 0:c5afea7b9057 618 write_reg(CCxxx0_PCKCTRL1, rfSettings.PCKCTRL1);
jjones646 0:c5afea7b9057 619 write_reg(CCxxx0_PCKCTRL0, rfSettings.PCKCTRL0);
jjones646 0:c5afea7b9057 620 write_reg(CCxxx0_ADDR, rfSettings.ADDR);
jjones646 0:c5afea7b9057 621 write_reg(CCxxx0_CHANNR, rfSettings.CHANNR);
jjones646 0:c5afea7b9057 622 write_reg(CCxxx0_FSCTRL1, rfSettings.FSCTRL1);
jjones646 0:c5afea7b9057 623 write_reg(CCxxx0_FSCTRL0, rfSettings.FSCTRL0);
jjones646 0:c5afea7b9057 624 write_reg(CCxxx0_FREQ2, rfSettings.FREQ2);
jjones646 0:c5afea7b9057 625 write_reg(CCxxx0_FREQ1, rfSettings.FREQ1);
jjones646 0:c5afea7b9057 626 write_reg(CCxxx0_FREQ0, rfSettings.FREQ0);
jjones646 0:c5afea7b9057 627 write_reg(CCxxx0_MDMCFG4, rfSettings.MDMCFG4);
jjones646 0:c5afea7b9057 628 write_reg(CCxxx0_MDMCFG3, rfSettings.MDMCFG3);
jjones646 0:c5afea7b9057 629 write_reg(CCxxx0_MDMCFG2, rfSettings.MDMCFG2);
jjones646 0:c5afea7b9057 630 write_reg(CCxxx0_MDMCFG1, rfSettings.MDMCFG1);
jjones646 0:c5afea7b9057 631 write_reg(CCxxx0_MDMCFG0, rfSettings.MDMCFG0);
jjones646 0:c5afea7b9057 632 write_reg(CCxxx0_DEVIATN, rfSettings.DEVIATN);
jjones646 0:c5afea7b9057 633 write_reg(CCxxx0_MCSM2 , rfSettings.MCSM2);
jjones646 0:c5afea7b9057 634 write_reg(CCxxx0_MCSM1 , rfSettings.MCSM1);
jjones646 0:c5afea7b9057 635 write_reg(CCxxx0_MCSM0 , rfSettings.MCSM0 );
jjones646 0:c5afea7b9057 636 write_reg(CCxxx0_FOCCFG, rfSettings.FOCCFG);
jjones646 0:c5afea7b9057 637 write_reg(CCxxx0_BSCFG, rfSettings.BSCFG);
jjones646 0:c5afea7b9057 638 write_reg(CCxxx0_AGCCTRL2, rfSettings.AGCCTRL2);
jjones646 0:c5afea7b9057 639 write_reg(CCxxx0_AGCCTRL1, rfSettings.AGCCTRL1);
jjones646 0:c5afea7b9057 640 write_reg(CCxxx0_AGCCTRL0, rfSettings.AGCCTRL0);
jjones646 0:c5afea7b9057 641 // WOREVT1
jjones646 0:c5afea7b9057 642 // WOREVT0
jjones646 0:c5afea7b9057 643 // WORCTRL
jjones646 0:c5afea7b9057 644 write_reg(CCxxx0_FREND1, rfSettings.FREND1);
jjones646 0:c5afea7b9057 645 write_reg(CCxxx0_FREND0, rfSettings.FREND0);
jjones646 0:c5afea7b9057 646 // FSCAL3
jjones646 0:c5afea7b9057 647 // FSCAL2
jjones646 0:c5afea7b9057 648 // FSCAL1
jjones646 0:c5afea7b9057 649 //write_reg(CCxxx0_FSCAL0, rfSettings.FSCAL0);
jjones646 0:c5afea7b9057 650 // PCCTRL1
jjones646 0:c5afea7b9057 651 // PCCTRL0
jjones646 0:c5afea7b9057 652 // FSTEST
jjones646 0:c5afea7b9057 653 // PTEST
jjones646 0:c5afea7b9057 654 // AGCTEST
jjones646 0:c5afea7b9057 655 // TEST2
jjones646 0:c5afea7b9057 656 // TEST1
jjones646 0:c5afea7b9057 657 // TEST0
jjones646 0:c5afea7b9057 658 } // put_rf_settings
jjones646 0:c5afea7b9057 659
jjones646 0:c5afea7b9057 660
jjones646 0:c5afea7b9057 661 // main ititilization
jjones646 0:c5afea7b9057 662 void CC1101::init(void)
jjones646 0:c5afea7b9057 663 {
jjones646 0:c5afea7b9057 664 // strobe(CCxxx0_SIDLE);
jjones646 0:c5afea7b9057 665 // send all configuration values to the CC1101 registers
jjones646 0:c5afea7b9057 666 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 667 std::printf(" Writing configuration registers...");
jjones646 0:c5afea7b9057 668 #endif
jjones646 0:c5afea7b9057 669 put_rf_settings();
jjones646 0:c5afea7b9057 670 write_reg(CCxxx0_PATABLE, paTable[0]);
jjones646 0:c5afea7b9057 671 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 672 std::printf("done\r\n");
jjones646 0:c5afea7b9057 673 #endif
jjones646 0:c5afea7b9057 674
jjones646 0:c5afea7b9057 675
jjones646 0:c5afea7b9057 676 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 677 std::printf(" Calibrating...");
jjones646 0:c5afea7b9057 678 #endif
jjones646 0:c5afea7b9057 679 calibrate();
jjones646 0:c5afea7b9057 680 // while( (mode() == 0x04) | (mode() == 0x05) ); // wait until it leaves calibration
jjones646 0:c5afea7b9057 681 write_reg(CCxxx0_FSCTRL0, status(CCxxx0_FREQEST));
jjones646 0:c5afea7b9057 682 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 683 std::printf("done\r\n");
jjones646 0:c5afea7b9057 684 #endif
jjones646 0:c5afea7b9057 685
jjones646 0:c5afea7b9057 686
jjones646 0:c5afea7b9057 687 // flush TX and RX buffers before beginning
jjones646 0:c5afea7b9057 688 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 689 std::printf(" Clearing TX and RX buffers...");
jjones646 0:c5afea7b9057 690 #endif
jjones646 0:c5afea7b9057 691 flush_rx();
jjones646 0:c5afea7b9057 692 flush_tx();
jjones646 0:c5afea7b9057 693 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 694 std::printf("done\r\n");
jjones646 0:c5afea7b9057 695 #endif
jjones646 0:c5afea7b9057 696
jjones646 0:c5afea7b9057 697
jjones646 0:c5afea7b9057 698 // Enter RX mode
jjones646 0:c5afea7b9057 699 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 700 std::printf(" Entering RX mode...");
jjones646 0:c5afea7b9057 701 #endif
jjones646 0:c5afea7b9057 702 rx_mode();
jjones646 0:c5afea7b9057 703 while( mode() != 0x0D ); // wait until it enters RX state
jjones646 0:c5afea7b9057 704 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 705 std::printf("done\r\n");
jjones646 0:c5afea7b9057 706 #endif
jjones646 0:c5afea7b9057 707 }
jjones646 0:c5afea7b9057 708
jjones646 0:c5afea7b9057 709
jjones646 0:c5afea7b9057 710 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 711 // uint8_t read_reg(uint8_t addr)
jjones646 0:c5afea7b9057 712 //
jjones646 0:c5afea7b9057 713 // DESCRIPTION:
jjones646 0:c5afea7b9057 714 // This function gets the value of a single specified CCxxx0 register.
jjones646 0:c5afea7b9057 715 //
jjones646 0:c5afea7b9057 716 // ARGUMENTS:
jjones646 0:c5afea7b9057 717 // uint8_t addr
jjones646 0:c5afea7b9057 718 // Address of the CCxxx0 register to be accessed.
jjones646 0:c5afea7b9057 719 //
jjones646 0:c5afea7b9057 720 // RETURN VALUE:
jjones646 0:c5afea7b9057 721 // uint8_t
jjones646 0:c5afea7b9057 722 // Value of the accessed CCxxx0 register.
jjones646 0:c5afea7b9057 723 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 724 uint8_t CC1101::read_reg(uint8_t addr)
jjones646 0:c5afea7b9057 725 {
jjones646 0:c5afea7b9057 726 *_csn = 0;
jjones646 0:c5afea7b9057 727 _spi->write(addr | READ_SINGLE);
jjones646 0:c5afea7b9057 728 uint8_t x = _spi->write(0);
jjones646 0:c5afea7b9057 729 *_csn = 1;
jjones646 0:c5afea7b9057 730
jjones646 0:c5afea7b9057 731 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 732 std::printf("\r\n== Single Register Read ==\r\n Address: 0x%02X\r\n Value: 0x%02X\r\n", addr, x);
jjones646 0:c5afea7b9057 733 #endif
jjones646 0:c5afea7b9057 734 return x;
jjones646 0:c5afea7b9057 735 } // read
jjones646 0:c5afea7b9057 736
jjones646 0:c5afea7b9057 737
jjones646 0:c5afea7b9057 738 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 739 // void read_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
jjones646 0:c5afea7b9057 740 //
jjones646 0:c5afea7b9057 741 // DESCRIPTION:
jjones646 0:c5afea7b9057 742 // This function reads multiple CCxxx0 register, using SPI burst access.
jjones646 0:c5afea7b9057 743 //
jjones646 0:c5afea7b9057 744 // ARGUMENTS:
jjones646 0:c5afea7b9057 745 // uint8_t addr
jjones646 0:c5afea7b9057 746 // Address of the first CCxxx0 register to be accessed.
jjones646 0:c5afea7b9057 747 // uint8_t *buffer
jjones646 0:c5afea7b9057 748 // Pointer to a byte array which stores the values read from a
jjones646 0:c5afea7b9057 749 // corresponding range of CCxxx0 registers.
jjones646 0:c5afea7b9057 750 // uint8_t count
jjones646 0:c5afea7b9057 751 // Number of bytes to be read from the subsequent CCxxx0 registers.
jjones646 0:c5afea7b9057 752 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 753 void CC1101::read_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
jjones646 0:c5afea7b9057 754 {
jjones646 0:c5afea7b9057 755 *_csn = 0;
jjones646 0:c5afea7b9057 756 _spi->write(addr | READ_BURST);
jjones646 0:c5afea7b9057 757 tiny_delay();
jjones646 0:c5afea7b9057 758 for (uint8_t i = 0; i < count; i++) {
jjones646 0:c5afea7b9057 759 buffer[i] = _spi->write(0);
jjones646 0:c5afea7b9057 760 tiny_delay();
jjones646 0:c5afea7b9057 761 }
jjones646 0:c5afea7b9057 762 *_csn = 1;
jjones646 0:c5afea7b9057 763
jjones646 0:c5afea7b9057 764 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 765 std::printf("\r\n== Burst Register Read ==\r\n Address: 0x%02X\r\n Bytes: %u\r\n", addr, count);
jjones646 0:c5afea7b9057 766 #endif
jjones646 0:c5afea7b9057 767 } // read
jjones646 0:c5afea7b9057 768
jjones646 0:c5afea7b9057 769
jjones646 0:c5afea7b9057 770 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 771 // void write_reg(uint8_t addr, uint8_t value)
jjones646 0:c5afea7b9057 772 //
jjones646 0:c5afea7b9057 773 // DESCRIPTION:
jjones646 0:c5afea7b9057 774 // Function for writing to a single CCxxx0 register
jjones646 0:c5afea7b9057 775 //
jjones646 0:c5afea7b9057 776 // ARGUMENTS:
jjones646 0:c5afea7b9057 777 // uint8_t addr
jjones646 0:c5afea7b9057 778 // Address of a specific CCxxx0 register to accessed.
jjones646 0:c5afea7b9057 779 // uint8_t value
jjones646 0:c5afea7b9057 780 // Value to be written to the specified CCxxx0 register.
jjones646 0:c5afea7b9057 781 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 782 void CC1101::write_reg(uint8_t addr, uint8_t value)
jjones646 0:c5afea7b9057 783 {
jjones646 0:c5afea7b9057 784 *_csn = 0;
jjones646 0:c5afea7b9057 785 _spi->write(addr);
jjones646 0:c5afea7b9057 786 _spi->write(value);
jjones646 0:c5afea7b9057 787 *_csn = 1;
jjones646 0:c5afea7b9057 788
jjones646 0:c5afea7b9057 789 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 790 std::printf("\r\n== Single Register Write ==\r\n Address: 0x%02X\r\n Value: 0x%02X\r\n", _addr, value);
jjones646 0:c5afea7b9057 791 #endif
jjones646 0:c5afea7b9057 792 } // write
jjones646 0:c5afea7b9057 793
jjones646 0:c5afea7b9057 794
jjones646 0:c5afea7b9057 795 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 796 // void write_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
jjones646 0:c5afea7b9057 797 //
jjones646 0:c5afea7b9057 798 // DESCRIPTION:
jjones646 0:c5afea7b9057 799 // This function writes to multiple CCxxx0 register, using SPI burst access.
jjones646 0:c5afea7b9057 800 //
jjones646 0:c5afea7b9057 801 // ARGUMENTS:
jjones646 0:c5afea7b9057 802 // uint8_t addr
jjones646 0:c5afea7b9057 803 // Address of the first CCxxx0 register to be accessed.
jjones646 0:c5afea7b9057 804 // uint8_t *buffer
jjones646 0:c5afea7b9057 805 // Array of bytes to be written into a corresponding range of
jjones646 0:c5afea7b9057 806 // CCxx00 registers, starting by the address specified in _addr_.
jjones646 0:c5afea7b9057 807 // uint8_t count
jjones646 0:c5afea7b9057 808 // Number of bytes to be written to the subsequent CCxxx0 registers.
jjones646 0:c5afea7b9057 809 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 810 void CC1101::write_reg(uint8_t addr, uint8_t *buffer, uint8_t count)
jjones646 0:c5afea7b9057 811 {
jjones646 0:c5afea7b9057 812 *_csn = 0;
jjones646 0:c5afea7b9057 813 _spi->write(addr | WRITE_BURST);
jjones646 0:c5afea7b9057 814 tiny_delay();
jjones646 0:c5afea7b9057 815 for (uint8_t i = 0; i < count; i++) {
jjones646 0:c5afea7b9057 816 _spi->write(buffer[i]);
jjones646 0:c5afea7b9057 817 tiny_delay();
jjones646 0:c5afea7b9057 818 }
jjones646 0:c5afea7b9057 819 *_csn = 1;
jjones646 0:c5afea7b9057 820
jjones646 0:c5afea7b9057 821 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 822 std::printf("\r\n== Burst Register Write ==\r\n Address: 0x%02X\r\n Bytes: %u\r\n", addr, count);
jjones646 0:c5afea7b9057 823 #endif
jjones646 0:c5afea7b9057 824 } // write
jjones646 0:c5afea7b9057 825
jjones646 0:c5afea7b9057 826
jjones646 0:c5afea7b9057 827 void CC1101::tiny_delay(void)
jjones646 0:c5afea7b9057 828 {
jjones646 0:c5afea7b9057 829 int i = 0;
jjones646 0:c5afea7b9057 830 while(i < 5) {
jjones646 0:c5afea7b9057 831 i++;
jjones646 0:c5afea7b9057 832 }
jjones646 0:c5afea7b9057 833 }
jjones646 0:c5afea7b9057 834
jjones646 0:c5afea7b9057 835
jjones646 0:c5afea7b9057 836
jjones646 0:c5afea7b9057 837 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 838 // void put_pck(uint8_t *txBuffer, uint8_t size)
jjones646 0:c5afea7b9057 839 //
jjones646 0:c5afea7b9057 840 // DESCRIPTION:
jjones646 0:c5afea7b9057 841 // This function can be used to transmit a packet with packet length up to 63 bytes.
jjones646 0:c5afea7b9057 842 //
jjones646 0:c5afea7b9057 843 // ARGUMENTS:
jjones646 0:c5afea7b9057 844 // uint8_t *txBuffer
jjones646 0:c5afea7b9057 845 // Pointer to a buffer containing the data that are going to be transmitted
jjones646 0:c5afea7b9057 846 //
jjones646 0:c5afea7b9057 847 // uint8_t size
jjones646 0:c5afea7b9057 848 // The size of the txBuffer
jjones646 0:c5afea7b9057 849 //
jjones646 0:c5afea7b9057 850 void CC1101::put_pck(uint8_t *txBuffer, uint8_t size)
jjones646 0:c5afea7b9057 851 {
jjones646 0:c5afea7b9057 852 // Blink the TX LED
jjones646 0:c5afea7b9057 853 _tx_led_thread.signal_set(SET_LED_TICK);
jjones646 0:c5afea7b9057 854
jjones646 0:c5afea7b9057 855 // move all values down by 1 to make room for the packet size value
jjones646 0:c5afea7b9057 856 for (uint8_t i = size; i > 0; i--)
jjones646 0:c5afea7b9057 857 txBuffer[i] = txBuffer[i-1];
jjones646 0:c5afea7b9057 858
jjones646 0:c5afea7b9057 859 // place the packet's size as the array's first value
jjones646 0:c5afea7b9057 860 txBuffer[0] = size++;
jjones646 0:c5afea7b9057 861
jjones646 0:c5afea7b9057 862 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 863 std::printf("\r\n[PACKET TRANSMITTED]\r\n Bytes: %u\r\n ACK: %sRequested\r\n", size, (ack==1 ? "":"Not ") );
jjones646 0:c5afea7b9057 864 #endif
jjones646 0:c5afea7b9057 865
jjones646 0:c5afea7b9057 866 // send the data to the CC1101
jjones646 0:c5afea7b9057 867 write_reg(CCxxx0_TXFIFO, txBuffer, size);
jjones646 0:c5afea7b9057 868
jjones646 0:c5afea7b9057 869 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 870 Timer t1;
jjones646 0:c5afea7b9057 871 #endif
jjones646 0:c5afea7b9057 872 // enter the TX state
jjones646 0:c5afea7b9057 873 strobe(CCxxx0_STX);
jjones646 0:c5afea7b9057 874
jjones646 0:c5afea7b9057 875 /* For the debug mode, this will determine how long the CC1101 takes to transmit everything in the TX buffer
jjones646 0:c5afea7b9057 876 and enter or return to the RX state.
jjones646 0:c5afea7b9057 877 */
jjones646 0:c5afea7b9057 878 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 879 t1.start();
jjones646 0:c5afea7b9057 880 float ti = t1.read();
jjones646 0:c5afea7b9057 881 #endif
jjones646 0:c5afea7b9057 882
jjones646 0:c5afea7b9057 883
jjones646 0:c5afea7b9057 884 // wait until radio enters back to the RX state. takes very few cycles, so might as well wait before returning to elimate querky errors
jjones646 0:c5afea7b9057 885 while(mode() != 0x0D);
jjones646 0:c5afea7b9057 886
jjones646 0:c5afea7b9057 887 #if DEBUG_MODE > 1
jjones646 0:c5afea7b9057 888 t1.stop();
jjones646 0:c5afea7b9057 889 std::printf(" Time: %02.4f ms\r\n", (t1.read() - ti)*1000);
jjones646 0:c5afea7b9057 890 #endif
jjones646 0:c5afea7b9057 891
jjones646 0:c5afea7b9057 892 } // put_pck
jjones646 0:c5afea7b9057 893
jjones646 0:c5afea7b9057 894
jjones646 0:c5afea7b9057 895 ///////////////////////////////////////////////////////////////////////////////////////
jjones646 0:c5afea7b9057 896 // bool get_pck(uint8_t *rxBuffer, uint8_t *length)
jjones646 0:c5afea7b9057 897 //
jjones646 0:c5afea7b9057 898 // DESCRIPTION:
jjones646 0:c5afea7b9057 899 // This function can be used to receive a packet of variable packet length (first byte in the packet
jjones646 0:c5afea7b9057 900 // must be the length byte). The packet length should not exceed the RX FIFO size.
jjones646 0:c5afea7b9057 901 //
jjones646 0:c5afea7b9057 902 // ARGUMENTS:
jjones646 0:c5afea7b9057 903 // uint8_t *rxBuffer
jjones646 0:c5afea7b9057 904 // Pointer to the buffer where the incoming data should be stored
jjones646 0:c5afea7b9057 905 // uint8_t *length
jjones646 0:c5afea7b9057 906 // Pointer to a variable containing the size of the buffer where the incoming data should be
jjones646 0:c5afea7b9057 907 // stored. After this function returns, that variable holds the packet length.
jjones646 0:c5afea7b9057 908 //
jjones646 0:c5afea7b9057 909 // RETURN VALUE:
jjones646 0:c5afea7b9057 910 // BOOL
jjones646 0:c5afea7b9057 911 // 1: CRC OK
jjones646 0:c5afea7b9057 912 // 0: CRC NOT OK (or no packet was put in the RX FIFO due to filtering)
jjones646 0:c5afea7b9057 913 //
jjones646 0:c5afea7b9057 914 bool CC1101::get_pck(uint8_t *rxBuffer, uint8_t *length)
jjones646 0:c5afea7b9057 915 {
jjones646 0:c5afea7b9057 916 // Blink the RX LED
jjones646 0:c5afea7b9057 917 _rx_led_thread.signal_set(SET_LED_TICK);
jjones646 0:c5afea7b9057 918
jjones646 0:c5afea7b9057 919 // Update the frequency offset estimate
jjones646 0:c5afea7b9057 920 write_reg(CCxxx0_FSCTRL0, status(CCxxx0_FREQEST));
jjones646 0:c5afea7b9057 921
jjones646 0:c5afea7b9057 922 // Get the packet's size
jjones646 0:c5afea7b9057 923 uint8_t rx_size;
jjones646 0:c5afea7b9057 924 read_reg(CCxxx0_RXFIFO, &rx_size, 1);
jjones646 0:c5afea7b9057 925
jjones646 0:c5afea7b9057 926 if (rx_size & BYTES_IN_RXFIFO) {
jjones646 0:c5afea7b9057 927
jjones646 0:c5afea7b9057 928 // Read data from RX FIFO and store in rxBuffer
jjones646 0:c5afea7b9057 929 if (rx_size <= *length) {
jjones646 0:c5afea7b9057 930
jjones646 0:c5afea7b9057 931 *length = rx_size;
jjones646 0:c5afea7b9057 932 read_reg(CCxxx0_RXFIFO, rxBuffer, *length);
jjones646 0:c5afea7b9057 933
jjones646 0:c5afea7b9057 934 // Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI)
jjones646 0:c5afea7b9057 935 uint8_t status_bytes[2];
jjones646 0:c5afea7b9057 936 read_reg(CCxxx0_RXFIFO, status_bytes, 2);
jjones646 0:c5afea7b9057 937
jjones646 0:c5afea7b9057 938 // update the RSSI reading
jjones646 0:c5afea7b9057 939 rssi(status_bytes[RSSI]);
jjones646 0:c5afea7b9057 940 _lqi = status_bytes[LQI] & 0x7F; // MSB of LQI is the CRC_OK bit
jjones646 0:c5afea7b9057 941
jjones646 0:c5afea7b9057 942 #if DEBUG_MODE > 0
jjones646 0:c5afea7b9057 943 std::printf("\r\n[PACKET RECEIVED]\r\n Bytes: %u\r\n", *length);
jjones646 0:c5afea7b9057 944 std::printf(" RSSI: %ddBm\r\n", _rssi);
jjones646 0:c5afea7b9057 945 std::printf(" LQI: %u\r\n", _lqi);
jjones646 0:c5afea7b9057 946 #endif
jjones646 0:c5afea7b9057 947
jjones646 0:c5afea7b9057 948 if (_p_count%5 == 0) {
jjones646 0:c5afea7b9057 949 //calibrate the frequency synthesizer
jjones646 0:c5afea7b9057 950 calibrate();
jjones646 0:c5afea7b9057 951 }
jjones646 0:c5afea7b9057 952
jjones646 0:c5afea7b9057 953 // Go back to the receiving state since CC1101 is configured for transitioning to IDLE on receiving a packet
jjones646 0:c5afea7b9057 954 rx_mode();
jjones646 0:c5afea7b9057 955 return 1;
jjones646 0:c5afea7b9057 956
jjones646 0:c5afea7b9057 957 } else {
jjones646 0:c5afea7b9057 958 *length = size;
jjones646 0:c5afea7b9057 959 }
jjones646 0:c5afea7b9057 960 }
jjones646 0:c5afea7b9057 961
jjones646 0:c5afea7b9057 962 flush_rx();
jjones646 0:c5afea7b9057 963 return 0;
jjones646 0:c5afea7b9057 964
jjones646 0:c5afea7b9057 965 } // get_pck
jjones646 0:c5afea7b9057 966
jjones646 0:c5afea7b9057 967
jjones646 0:c5afea7b9057 968 void CC1101::flush_rx(void)
jjones646 0:c5afea7b9057 969 {
jjones646 0:c5afea7b9057 970 // Make sure that the radio is in IDLE state before flushing the FIFO
jjones646 0:c5afea7b9057 971 idle();
jjones646 0:c5afea7b9057 972
jjones646 0:c5afea7b9057 973 // Flush RX FIFO
jjones646 0:c5afea7b9057 974 strobe(CCxxx0_SFRX);
jjones646 0:c5afea7b9057 975
jjones646 0:c5afea7b9057 976 // Enter back into a RX state
jjones646 0:c5afea7b9057 977 rx_mode();
jjones646 0:c5afea7b9057 978 }
jjones646 0:c5afea7b9057 979
jjones646 0:c5afea7b9057 980
jjones646 0:c5afea7b9057 981 void CC1101::flush_tx(void)
jjones646 0:c5afea7b9057 982 {
jjones646 0:c5afea7b9057 983 // Make sure that the radio is in IDLE state before flushing the FIFO
jjones646 0:c5afea7b9057 984 idle();
jjones646 0:c5afea7b9057 985
jjones646 0:c5afea7b9057 986 // Flush TX FIFO
jjones646 0:c5afea7b9057 987 strobe(CCxxx0_SFTX);
jjones646 0:c5afea7b9057 988
jjones646 0:c5afea7b9057 989 // Enter back into a RX state
jjones646 0:c5afea7b9057 990 rx_mode();
jjones646 0:c5afea7b9057 991 }
jjones646 0:c5afea7b9057 992
jjones646 0:c5afea7b9057 993
jjones646 0:c5afea7b9057 994 void CC1101::rx_mode(void)
jjones646 0:c5afea7b9057 995 {
jjones646 0:c5afea7b9057 996 //strobe(CCxxx0_SIDLE);
jjones646 0:c5afea7b9057 997 strobe(CCxxx0_SRX);
jjones646 0:c5afea7b9057 998 //while(mode() != 0x0D);
jjones646 0:c5afea7b9057 999 }
jjones646 0:c5afea7b9057 1000
jjones646 0:c5afea7b9057 1001
jjones646 0:c5afea7b9057 1002 void CC1101::tx_mode(void)
jjones646 0:c5afea7b9057 1003 {
jjones646 0:c5afea7b9057 1004 //strobe(CCxxx0_SIDLE);
jjones646 0:c5afea7b9057 1005 strobe(CCxxx0_STX);
jjones646 0:c5afea7b9057 1006 // while(mode() != 0x13);
jjones646 0:c5afea7b9057 1007 }
jjones646 0:c5afea7b9057 1008
jjones646 0:c5afea7b9057 1009 void CC1101::idle(void)
jjones646 0:c5afea7b9057 1010 {
jjones646 0:c5afea7b9057 1011 // Send the IDLE strobe
jjones646 0:c5afea7b9057 1012 strobe(CCxxx0_SIDLE);
jjones646 0:c5afea7b9057 1013 // Wait before returning
jjones646 0:c5afea7b9057 1014 // === THIS LIKELY ISN'T NEEDED ===
jjones646 0:c5afea7b9057 1015 while( mode() != 0x01);
jjones646 0:c5afea7b9057 1016 }