Appiko
cc1101_drv.c
1 /******************************************************************************
2  * Filename: cc1101_drv.c
3  *
4  * Description: Radio driver abstraction layer, this uses the same concept
5  * as found in Contiki OS (https://github.com/contiki-os/contiki)
6  *
7  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
8  *
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  *
17  * Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  *
21  * Neither the name of Texas Instruments Incorporated nor the names of
22  * its contributors may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  ******************************************************************************/
38 #include "msp430.h"
39 #include "cc1101_def.h"
40 #include "radio_drv.h"
41 #include "hal_spi_rf.h"
42 #include "hal_timer.h"
43 #include "cc1190_drv.h"
44 
45 #ifdef USE_CC1101
46 
47 /* Select the correct XTAL frequency for the hardware */
48 #define SCALING_FREQ (float)((RF_XTAL)/65.536)
49 #define SCALING_FREQEST (unsigned long)((RF_XTAL)/16.384)
50 
51 /*******************************************************************************
52  * Globals used inside the physical layer
53  *******************************************************************************/
54 unsigned char paTable[1];
55 unsigned char rf_end_packet = 0;
56 
57 // Data format = Normal mode
58 // Whitening = false
59 // Device address = 0
60 // CRC enable = true
61 // Data rate = 1.19948
62 // Carrier frequency = 902.749786
63 // Packet length = 255
64 // Deviation = 5.157471
65 // RX filter BW = 58.035714
66 // Preamble count = 4
67 // Modulated = true
68 // Packet length mode = Fixed packet length mode. Length configured in PKTLEN register
69 // CRC autoflush = false
70 // TX power = 0
71 // Channel number = 0
72 // Address config = No address check
73 // Base frequency = 902.749786
74 // PA ramping = false
75 // Channel spacing = 99.975586
76 // Manchester enable = false
77 // Modulation format = GFSK
78 // Sync word qualifier mode = 30/32 sync word bits detected
79 
80 
81 const registerSetting_t preferredSettings_1200bps[]=
82 {
83  {IOCFG2, 0x06},
84  {IOCFG1, 0x2E},
85  {IOCFG0, 0x06},
86  {FIFOTHR, 0x47},
87  {SYNC1, 0xD3},
88  {SYNC0, 0x91},
89  {PKTLEN, 0xFF},
90  {PKTCTRL1, 0x00},
91  {PKTCTRL0, 0x05},
92  {FSCTRL1, 0x06},
93  {FREQ2, 0x22},
94  {FREQ1, 0xB8},
95  {FREQ0, 0x9D},
96  {MDMCFG4, 0xF5},
97  {MDMCFG3, 0x83},
98  {MDMCFG2, 0x13},
99  {MDMCFG1, 0x21},
100  {MDMCFG0, 0xF8},
101  {DEVIATN, 0x15},
102  {MCSM0, 0x18},
103  {FOCCFG, 0x16},
104  {WORCTRL, 0xFB},
105  {FSCAL3, 0xE9},
106  {FSCAL2, 0x2A},
107  {FSCAL1, 0x00},
108  {FSCAL0, 0x1F},
109  {TEST2, 0x81},
110  {TEST1, 0x35},
111  {TEST0, 0x09},
112 };
113 
114 
115 // Device address = 0
116 // Packet length mode = Variable packet length mode. Packet length configured by the first byte after sync word
117 // PA ramping = false
118 // RX filter BW = 101.562500
119 // Carrier frequency = 902.749786
120 // Modulated = true
121 // CRC autoflush = false
122 // Data format = Normal mode
123 // Sync word qualifier mode = 30/32 sync word bits detected
124 // CRC enable = true
125 // Preamble count = 4
126 // TX power = 11
127 // Channel number = 0
128 // Whitening = false
129 // Manchester enable = false
130 // Address config = No address check
131 // Base frequency = 902.749786
132 // Modulation format = GFSK
133 // Data rate = 38.3835
134 // Packet length = 255
135 // Deviation = 20.629883
136 // Channel spacing = 199.951172
137 
138 const registerSetting_t preferredSettings_38400bps[]=
139 {
140  {IOCFG2, 0x06},
141  {IOCFG1, 0x2E},
142  {IOCFG0, 0x06},
143  {FIFOTHR, 0x47},
144  {SYNC1, 0xD3},
145  {SYNC0, 0x91},
146  {PKTLEN, 0xFF},
147  {PKTCTRL1, 0x00},
148  {PKTCTRL0, 0x05},
149  {CHANNR, 0x00},
150  {FSCTRL1, 0x06},
151  {FREQ2, 0x22},
152  {FREQ1, 0xB8},
153  {FREQ0, 0x9D},
154  {MDMCFG4, 0xCA},
155  {MDMCFG3, 0x83},
156  {MDMCFG2, 0x13},
157  {MDMCFG1, 0x22},
158  {MDMCFG0, 0xF8},
159  {DEVIATN, 0x35},
160  {MCSM2, 0x07},
161  {MCSM1, 0x30},
162  {MCSM0, 0x18},
163  {FOCCFG, 0x16},
164  {AGCCTRL2, 0x43},
165  {WORCTRL, 0xFB},
166  {FSCAL3, 0xE9},
167  {FSCAL2, 0x2A},
168  {FSCAL1, 0x00},
169  {FSCAL0, 0x1F},
170  {TEST2, 0x81},
171  {TEST1, 0x35},
172  {TEST0, 0x09},
173 };
174 
175 // Data format = Normal mode (250kbps, FCC 15.247)
176 // Whitening = false
177 // Device address = 0
178 // CRC enable = true
179 // Data rate = 249.939
180 // Carrier frequency = 915.000000
181 // Packet length = 255
182 // Deviation = 126.953125
183 // RX filter BW = 541.666667
184 // Preamble count = 4
185 // Modulated = true
186 // Packet length mode = Variable packet length mode. Packet length configured by the first byte after sync word
187 // CRC autoflush = false
188 // TX power = 10
189 // Channel number = 0
190 // Address config = No address check
191 // Base frequency = 914.999969
192 // PA ramping = false
193 // Channel spacing = 199.951172
194 // Manchester enable = false
195 // Modulation format = GFSK
196 // Sync word qualifier mode = 30/32 sync word bits detected
197 
198 const registerSetting_t preferredSettings_250kbps[]=
199 {
200  {IOCFG2, 0x06},
201  {IOCFG1, 0x2E},
202  {IOCFG0, 0x06},
203  {SYNC1, 0xD3},
204  {SYNC0, 0x91},
205  {PKTLEN, 0xFF},
206  {PKTCTRL1, 0x00},
207  {PKTCTRL0, 0x45},
208  {FSCTRL1, 0x0C},
209  {FREQ2, 0x23},
210  {FREQ1, 0x31},
211  {FREQ0, 0x3B},
212  {MDMCFG4, 0x2D},
213  {MDMCFG3, 0x3B},
214  {MDMCFG2, 0x13},
215  {DEVIATN, 0x62},
216  {MCSM0, 0x18},
217  {FOCCFG, 0x1D},
218  {BSCFG, 0x1C},
219  {AGCCTRL2, 0xC7},
220  {AGCCTRL1, 0x00},
221  {AGCCTRL0, 0xB0},
222  {WORCTRL, 0xFB},
223  {FSCAL3, 0xEA},
224  {FSCAL2, 0x2A},
225  {FSCAL1, 0x00},
226  {FSCAL0, 0x1F},
227  {TEST2, 0x88},
228  {TEST1, 0x31},
229  {TEST0, 0x09},
230 };
231 
232 /******************************************************************************
233  * @fn radio_init
234  *
235  * @brief Initialize the radio hardware
236  *
237  *
238  * input parameters
239  *
240  * @param void
241  *
242  * output parameters
243  *
244  * @return void
245  *
246  *
247  */
248 int radio_init(unsigned char config_select) {
249 
250  unsigned char i, writeByte, preferredSettings_length;
251  int bit_rate;
252  registerSetting_t *preferredSettings;
253 
254 
255  // Configure SPI port to communicate with transciever
256  trxRfSpiInterfaceInit(4);
257 
258  // initialize a reset
259  trxSpiCmdStrobe(RF_SRES);
260 
261  //give the tranciever time enough to complete reset cycle
262  __delay_cycles(16000);
263 
264  switch (config_select) {
265  case 1:
266  preferredSettings_length = sizeof(preferredSettings_1200bps)/sizeof(registerSetting_t);
267  preferredSettings = (registerSetting_t *)preferredSettings_1200bps;
268  bit_rate = 12;
269  break;
270  case 2:
271  preferredSettings_length = sizeof(preferredSettings_38400bps)/sizeof(registerSetting_t);
272  preferredSettings = (registerSetting_t *)preferredSettings_38400bps;
273  bit_rate = 384;
274  break;
275  case 3:
276  preferredSettings_length = sizeof(preferredSettings_250kbps)/sizeof(registerSetting_t);
277  preferredSettings = (registerSetting_t *)preferredSettings_250kbps;
278  bit_rate = 2500;
279  break;
280  default:
281  preferredSettings_length = sizeof(preferredSettings_1200bps)/sizeof(registerSetting_t);
282  preferredSettings = (registerSetting_t *)preferredSettings_1200bps;
283  bit_rate = 12;
284  break;
285  }
286 
287  // Write registers to radio
288  for(i = 0; i < preferredSettings_length; i++) {
289  writeByte = preferredSettings[i].data;
290  trx8BitRegAccess(RADIO_WRITE_ACCESS, preferredSettings[i].addr, &writeByte, 1);
291  }
292 
293  paTable[0] = 0xC5; // PATABLE (10 dBm output power)
294  trx8BitRegAccess(RADIO_WRITE_ACCESS|RADIO_BURST_ACCESS, PATABLE, paTable, 1);
295 
296  return bit_rate;
297 }
298 
299 
300 /******************************************************************************
301  * @fn radio_prepare
302  *
303  * @brief Prepare the radio with a packet to be sent, but do not send
304  *
305  * input parameters
306  *
307  * @param unsigned char *payload - pointer to payload
308  * unsigned short payload_len - payload length information
309  *
310  * output parameters
311  *
312  * @return 0
313  *
314  *
315  */
316 int radio_prepare(unsigned char *payload, unsigned short payload_len) {
317 
318  trx8BitRegAccess(RADIO_WRITE_ACCESS+RADIO_BURST_ACCESS, TXFIFO, payload, payload_len);
319 
320  return 0;
321 }
322 
323 /******************************************************************************
324  * @fn radio_transmit
325  *
326  * @brief Send the packet that has previously been prepared (used for
327  * exact timing)
328  *
329  * input parameters
330  *
331  * @param unsigned char *payload - pointer to payload
332  * unsigned short payload_len - payload length information
333  *
334  * output parameters
335  *
336  * @return 0
337  *
338  *
339  */
340 int radio_transmit(void) {
341 
342  /* Range extender in TX mode */
343 #ifdef ENABLE_RANGE_EXTENDER
344  range_extender_txon();
345 #endif
346 
347  trxSpiCmdStrobe(RF_STX); // Change state to TX, initiating
348 
349  return(0);
350 }
351 
352 /******************************************************************************
353  * @fn radio_receive_on
354  *
355  * @brief Initiate the RX chain
356  *
357  * input parameters
358  *
359  * @param void
360  *
361  * output parameters
362  *
363  * @return void
364  *
365  *
366  */
367 int radio_receive_on(void) {
368 
369  /* Range extender in RX mode */
370 #ifdef ENABLE_RANGE_EXTENDER
371  range_extender_rxon();
372 #endif
373 
374  trxSpiCmdStrobe(RF_SRX); // Change state to TX, initiating
375 
376  return(0);
377 }
378 
379 /******************************************************************************
380  * @fn radio_send
381  *
382  * @brief Prepare & transmit a packet in same call
383  *
384  *
385  * input parameters
386  *
387  * @param unsigned char *payload
388  * unsigned short payload_len
389  *
390  * output parameters
391  *
392  * @return void
393  *
394  *
395  */
396 int radio_send(unsigned char *payload, unsigned short payload_len) {
397 
398  trx8BitRegAccess(RADIO_WRITE_ACCESS|RADIO_BURST_ACCESS, TXFIFO, payload, payload_len);
399 
400  /* Range extender in TX mode */
401 #ifdef ENABLE_RANGE_EXTENDER
402  range_extender_txon();
403 #endif
404 
405  trxSpiCmdStrobe(RF_STX); // Change state to TX, initiating
406  return(0);
407 }
408 
409 /******************************************************************************
410  * @fn radio_read
411  *
412  * @brief Read a received packet into a buffer
413  *
414  *
415  * input parameters
416  *
417  * @param unsigned char *buf
418  * unsigned short buf_len
419  *
420  * output parameters
421  *
422  * @return void
423  *
424  *
425  */
426 
427 int radio_read(unsigned char *buf, unsigned short *buf_len) {
428  unsigned char status;
429  unsigned char pktLen;
430 
431  /* Read number of bytes in RX FIFO */
432  trx8BitRegAccess(RADIO_READ_ACCESS|RADIO_BURST_ACCESS, RXBYTES, &pktLen, 1);
433  pktLen = pktLen & NUM_RXBYTES;
434 
435  /* make sure the packet size is appropriate, that is 1 -> buffer_size */
436  if ((pktLen > 0) && (pktLen <= *buf_len)) {
437 
438  /* retrieve the FIFO content */
439  trx8BitRegAccess(RADIO_READ_ACCESS|RADIO_BURST_ACCESS, RXFIFO, buf, pktLen);
440 
441  /* return the actual length of the FIFO */
442  *buf_len = pktLen;
443 
444  /* retrieve the CRC status information */
445  trx8BitRegAccess(RADIO_READ_ACCESS+RADIO_BURST_ACCESS, PKTSTATUS, &status, 1);
446 
447  } else {
448 
449  /* if the length returned by the transciever does not make sense, flush it */
450  *buf_len = 0; // 0
451  status = 0;
452  trxSpiCmdStrobe(RF_SFRX); // Flush RXFIFO
453  }
454 
455  /* return status information, CRC OK or NOT OK */
456  return (status & CRC_OK);
457 }
458 
459 /******************************************************************************
460  * @fn radio_channel_clear
461  *
462  * @brief Perform a Clear-Channel Assessment (CCA) to find out if
463  * channel is clear
464  *
465  *
466  * input parameters
467  *
468  * @param void
469  *
470  * output parameters
471  *
472  * @return 0 - no carrier found
473  * >0 - carrier found
474  *
475  */
476 int radio_channel_clear(void) {
477  unsigned char status;
478 
479  /* get PKTSTATUS, and return the carrier sense signal */
480  trx8BitRegAccess(RADIO_READ_ACCESS+RADIO_BURST_ACCESS, PKTSTATUS, &status, 1);
481 
482  /* return the carrier sense signal */
483  return(status & 0x40);
484 }
485 
486 /******************************************************************************
487  * @fn radio_channel_clear
488  *
489  * @brief Wait for end of packet interupt to happen
490  *
491  * Timeout is controlled by TimerA running at 8MHz
492  * 64000 = 128ms, 32000 = 64ms, 16000 = 32ms
493  * 0 = no timeout.
494  *
495  * input parameters
496  *
497  * @param max_hold : Watch dog timeout, no end of packet = 0;
498  *
499  * output parameters
500  *
501  * @return timer value: Interupt happened based on end_of_packet interupt
502  *
503  */
504 int radio_wait_for_idle(unsigned short max_hold) {
505 
506  unsigned int status;
507  unsigned char reg_status;
508 
509  /* check that we are still in RX mode before entering wait for RX end */
510  trx8BitRegAccess(RADIO_READ_ACCESS+RADIO_BURST_ACCESS, MARCSTATE, &reg_status, 1);
511 
512  /* filter out only the status section of the register values */
513  reg_status = (reg_status & 0x1F);
514 
515  /* check for not idle mode */
516  if(!(reg_status == MARCSTATE_IDLE)) {
517 
518  rf_end_packet = 0; // initialize global variable for use in this function
519 
520  RF_GDO_PxIES |= RF_GDO_PIN; // Int on falling edge (end of pkt)
521  RF_GDO_PxIFG &= ~RF_GDO_PIN; // Clear flag
522  RF_GDO_PxIE |= RF_GDO_PIN; // Enable int on end of packet
523 
524  /* wait for idle */
525  if(max_hold > 0) {
526  hal_timer_wait(max_hold); // this will timeout either with GDO or timer
527  } else {
528  // wait for radio to interupt us to continue processing
529  status = 0;
530  _BIS_SR(LPM0_bits + GIE); // Enter LPM0
531  }
532 
533  /******** Setup the GDO ports to not interupts ****************************/
534  RF_GDO_PxIE &= ~RF_GDO_PIN; // Disable int on end of packet
535 
536  }
537  /* Get timer values, however if we did not get a packet in time use 0 */
538  if(rf_end_packet == 0) {
539  status = max_hold;
540  }
541 
542 #ifdef ENABLE_RANGE_EXTENDER
543  range_extender_idle();
544 #endif
545 
546  return status;
547 }
548 
549 /******************************************************************************
550  * @fn radio_is_busy
551  *
552  * @brief Wait for radio to become idle
553  *
554  * input parameters
555  *
556  * @param void
557  *
558  * output parameters
559  *
560  * @return void
561  *
562  */
563 int radio_is_busy(void) {
564 
565  // Wait GDO0 to go hi -> sync TX'ed
566  while (!(RF_GDO_IN & RF_GDO_PIN));
567 
568  // Wait GDO0 to go low again -> sync TX'ed
569  while (RF_GDO_IN & RF_GDO_PIN);
570 
571  // Wait GDO0 to clear -> end of pkt
572  RF_GDO_PxIFG &= ~RF_GDO_PIN; // After pkt TX, this flag is set.
573 
574  return(0);
575 }
576 
577 /******************************************************************************
578  * @fn radio_pending_packet
579  *
580  * @brief Check if the radio driver has just received a packet
581  *
582  * input parameters
583  *
584  * @param void
585  *
586  * output parameters
587  *
588  * @return rf_end_packet - 1 if packet is available, 0 if no packet
589  *
590  */
591 int radio_pending_packet(void) {
592 
593  RF_GDO_PxIES |= RF_GDO_PIN; // Int on falling edge (end of pkt)
594  RF_GDO_PxIE |= RF_GDO_PIN; // Enable int on end of packet
595 
596  return rf_end_packet;
597 }
598 
599 /******************************************************************************
600  * @fn radio_clear_pending_packet
601  *
602  * @brief Clear pending packet indicator
603  *
604  * input parameters
605  *
606  * @param void
607  *
608  * output parameters
609  *
610  * @return void
611  *
612  */
613 int radio_clear_pending_packet(void) {
614 
615  RF_GDO_PxIES &= ~RF_GDO_PIN; // Int on falling edge (end of pkt)
616  RF_GDO_PxIE &= ~RF_GDO_PIN; // Enable int on end of packet
617 
618  rf_end_packet = 0;
619 
620  return 0;
621 }
622 
623 /******************************************************************************
624  * @fn radio_set_pwr
625  *
626  * @brief Set the output power of the CC1101 by looking up in table
627  *
628  * input parameters
629  *
630  * @param int tx_pwr - wanted power
631  *
632  * output parameters
633  *
634  * @return int tx_pwr - actual power chosen from lookup table
635  *
636  */
637 int radio_set_pwr(int tx_pwr) {
638  int actual_pwr, ee;
639  unsigned char reg_access;
640 
641  /* lookup table for PA power codes */
642  const unsigned char paTable_CC1101[10] =
643  {0x03, 0x0E, 0x1E, 0x27, 0x38, 0x8E, 0x84, 0xCC, 0xC3, 0xC0};
644 
645  /* lookup table for PA power values */
646  const int paOut_CC1101[10] = {-30, -20, -15, -10, -6, 0, 5, 7, 10, 12};
647 
648  /* for each entry in the power table loop */
649  for(ee=0; ee<10;ee++){
650  actual_pwr = paOut_CC1101[ee];
651 
652  /* check if requested value is less than */
653  if(tx_pwr <= actual_pwr){
654 
655  /* update the PA table entry to the newly requested power value */
656  reg_access = paTable_CC1101[ee];
657  trx8BitRegAccess(RADIO_WRITE_ACCESS | RADIO_BURST_ACCESS, PATABLE, &reg_access, 1);
658 
659  /* terminate for loop */
660  ee=10;
661  }
662  }
663 
664  return actual_pwr;
665 }
666 
667 
668 
669 /******************************************************************************
670  * @fn radio_set_freq
671  *
672  * @brief Sets the rf center frequency based on a frequency value to the
673  * nearest 1KHz. The Equation used is the following:
674  *
675  * f_c = (f_xosc/2^16) * FREQ (control word)
676  *
677  * FREQ = (f_c * 2^16)/f_osc;
678  *
679  * output parameters
680  *
681  * @return void
682  *
683  */
684 int radio_set_freq(unsigned long freq) {
685 
686  unsigned long freq_word;
687  unsigned char freq_byte[3];
688  float freq_float;
689 
690  // calculate the frequency word
691 
692  freq_float = freq*1000;
693  freq_word = (unsigned long) (freq_float * 1/(float)SCALING_FREQ);
694 
695  /* return the frequency word */
696  freq_byte[2] = ((uint8*)&freq_word)[0];
697  freq_byte[1] = ((uint8*)&freq_word)[1];
698  freq_byte[0] = ((uint8*)&freq_word)[2];
699 
700  // upload the frequency word to the transciver using a 3 byte write
701  trx8BitRegAccess(RADIO_WRITE_ACCESS | RADIO_BURST_ACCESS , FREQ2, freq_byte, 3);
702 
703  return 0;
704 }
705 
706 
707 /******************************************************************************
708  * @fn radio_idle
709  *
710  * @brief Idle the radio and flush buffers
711  *
712  * input parameters
713  *
714  * @param void
715  *
716  * output parameters
717  *
718  * @return void
719  *
720  */
721 int radio_idle(void) {
722 
723  /* Idle range extender */
724 #ifdef ENABLE_RANGE_EXTENDER
725  range_extender_idle();
726 #endif
727 
728  /* Idle range extender */
729  trxSpiCmdStrobe(RF_SIDLE);
730 
731  /* Flush the FIFO's */
732  trxSpiCmdStrobe(RF_SFRX);
733  trxSpiCmdStrobe(RF_SFTX);
734  return(0);
735 }
736 
737 /******************************************************************************
738  * @fn radio_sleep
739  *
740  * @brief Enter sleep mode
741  *
742  * input parameters
743  *
744  * @param void
745  *
746  * output parameters
747  *
748  * @return void
749  *
750  */
751 int radio_sleep(void) {
752 
753  /* Idle range extender */
754 #ifdef ENABLE_RANGE_EXTENDER
755  range_extender_idle();
756 #endif
757 
758  /* Force transciever idle state */
759  trxSpiCmdStrobe(RF_SIDLE);
760 
761  /* Enter sleep state on exit */
762  trxSpiCmdStrobe(RF_SPWD);
763 
764  return(0);
765 }
766 
767 /******************************************************************************
768  * @fn radio_wake
769  *
770  * @brief Exit sleep mode
771  *
772  * input parameters
773  *
774  * @param void
775  *
776  * output parameters
777  *
778  * @return void
779  *
780  */
781 int radio_wake(void) {
782 
783  /* Force transciever idle state */
784  trxSpiCmdStrobe(RF_SIDLE);
785 
786  /* 1 ms delay for letting RX settle */
787  __delay_cycles(1000);
788 
789 
790  return(0);
791 }
792 
793 
794 /******************************************************************************
795  * @fn radio_freq_error
796  *
797  * @brief Estimate the frequency error from two complement coded
798  * data to frequency error in Hertz
799  *
800  * input parameters
801  *
802  * @param freq_reg_error - two complement formatted data from tranceiver
803  *
804  * output parameters
805  *
806  * @return freq_error - 32 bit signed integer value representing
807  * frequency error in Hertz
808  *
809  */
810 int radio_freq_error(void) {
811 
812  long freq_error_est;
813  unsigned char regState;
814 
815  /* Read marcstate to check for frequency error estimate */
816  trx8BitRegAccess(RADIO_READ_ACCESS | RADIO_BURST_ACCESS, FREQEST, &regState, 1);
817 
818  /* Calculate the frequency error in Hz */
819  freq_error_est = regState;
820 
821  /* the incoming data is 8 bit two complement format, separate "sign" */
822  if (freq_error_est > 128) {
823  freq_error_est = freq_error_est - 256;
824  }
825 
826  /* convert the data to hertz format in two steps to avoid integer overuns */
827  freq_error_est = freq_error_est * (long)SCALING_FREQEST;
828 
829  return ((int)freq_error_est);
830 }
831 
832 
833 
834 /******************************************************************************
835  * @fn radio_isr
836  *
837  * @brief Interrupt service routine used by transciever
838  *
839  * input parameters
840  *
841  * @param void
842  *
843  * output parameters
844  *
845  * @return void
846  *
847  */
848 #pragma vector=RF_PORT_VECTOR
849 __interrupt void radio_isr(void) {
850 
851  if(RF_GDO_PxIFG & RF_GDO_PIN) {
852 
853  // Clear LPM0 bits from 0(SR)
854  __bic_SR_register_on_exit(LPM3_bits);
855 
856  // clear the interrupt flag
857  RF_GDO_PxIFG &= ~RF_GDO_PIN;
858 
859  // indicate that end of packet has been found
860  rf_end_packet = 1;
861  }
862 }
863 
864 #endif