For robots and stuff

Dependents:   Base Station

Committer:
jjones646
Date:
Wed Dec 31 22:16:01 2014 +0000
Revision:
2:c42a035d71ed
Parent:
1:05a48c038381
adding dummy cc1101 support

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