c56531a61dd41bdbb41b25d123d9de1044f6afb3
[hackover2013-badge-firmware.git] / drivers / chibi / chb_drvr.c
1 /*******************************************************************
2 Copyright (C) 2009 FreakLabs
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. Neither the name of the the copyright holder nor the names of its contributors
15 may be used to endorse or promote products derived from this software
16 without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 SUCH DAMAGE.
29
30 Originally written by Christopher Wang aka Akiba.
31 Please post support questions to the FreakLabs forum.
32
33 *******************************************************************/
34 #include <stdio.h>
35 #include "chb.h"
36 #include "chb_drvr.h"
37 #include "chb_buf.h"
38 #include "chb_spi.h"
39 #include "chb_eeprom.h"
40
41 #include "core/systick/systick.h"
42 #include "core/timer16/timer16.h"
43
44 // store string messages in flash rather than RAM
45 const char chb_err_overflow[] = "BUFFER FULL. TOSSING INCOMING DATA\r\n";
46 const char chb_err_init[] = "RADIO NOT INITIALIZED PROPERLY\r\n";
47 /**************************************************************************/
48 /*!
49
50 */
51 /**************************************************************************/
52 static U8 chb_get_state()
53 {
54 return chb_reg_read(TRX_STATUS) & 0x1f;
55 }
56
57 /**************************************************************************/
58 /*!
59
60 */
61 /**************************************************************************/
62 static U8 chb_get_status()
63 {
64 return chb_reg_read(TRX_STATE) >> CHB_TRAC_STATUS_POS;
65 }
66
67 /**************************************************************************/
68 /*!
69 Cause a blocking delay for x microseconds
70 */
71 /**************************************************************************/
72 static void chb_delay_us(U16 usec)
73 {
74 // Determine maximum delay using a 16 bit timer
75 // ToDo: Move this to a macro or fixed value!
76 uint32_t maxus = 0xFFFF / (CFG_CPU_CCLK / 1000000);
77
78 // Check if delay can be done in one operation
79 if (usec <= maxus)
80 {
81 timer16DelayUS(0, usec);
82 return;
83 }
84
85 // Split delay into several steps (to stay within limit of 16-bit timer)
86 do
87 {
88 if (usec >= maxus)
89 {
90 timer16DelayUS(0, maxus);
91 usec -= maxus;
92 }
93 else
94 {
95 timer16DelayUS(0, usec);
96 usec = 0;
97 }
98 } while (usec > 0);
99 }
100
101 /**************************************************************************/
102 /*!
103
104 */
105 /**************************************************************************/
106 void chb_reset()
107 {
108 CHB_RST_DISABLE();
109 CHB_SLPTR_DISABLE();
110
111 // wait a bit while transceiver wakes up
112 chb_delay_us(TIME_P_ON_TO_CLKM_AVAIL);
113
114 // reset the device
115 CHB_RST_ENABLE();
116 chb_delay_us(TIME_RST_PULSE_WIDTH);
117 CHB_RST_DISABLE();
118
119 // check that we have the part number that we're expecting
120 while (1)
121 {
122 // if you're stuck in this loop, that means that you're not reading
123 // the version and part number register correctly. possible that version number
124 // changes. if so, update version num in header file
125 if ((chb_reg_read(VERSION_NUM) == CHB_AT86RF212_VER_NUM) && (chb_reg_read(PART_NUM) == CHB_AT86RF212_PART_NUM))
126 {
127 break;
128 }
129 }
130 }
131
132 /**************************************************************************/
133 /*!
134
135 */
136 /**************************************************************************/
137 U8 chb_reg_read(U8 addr)
138 {
139 U8 val = 0;
140
141 /* Add the register read command to the register address. */
142 addr |= 0x80;
143
144 CHB_ENTER_CRIT();
145 CHB_SPI_ENABLE();
146
147 /*Send Register address and read register content.*/
148 val = chb_xfer_byte(addr);
149 val = chb_xfer_byte(val);
150
151 CHB_SPI_DISABLE();
152 CHB_LEAVE_CRIT();
153
154 return val;
155 }
156
157 /**************************************************************************/
158 /*!
159
160 */
161 /**************************************************************************/
162 U16 chb_reg_read16(U8 addr)
163 {
164 U8 i;
165 U16 val = 0;
166
167 for (i=0; i<2; i++)
168 {
169 addr |= chb_reg_read(addr + i) << (8 * i);
170 }
171 return val;
172 }
173
174 /**************************************************************************/
175 /*!
176
177 */
178 /**************************************************************************/
179 void chb_reg_write(U8 addr, U8 val)
180 {
181 U8 dummy;
182
183 /* Add the Register Write command to the address. */
184 addr |= 0xC0;
185
186 CHB_ENTER_CRIT();
187 CHB_SPI_ENABLE();
188
189 /*Send Register address and write register content.*/
190 dummy = chb_xfer_byte(addr);
191 dummy = chb_xfer_byte(val);
192
193 CHB_SPI_DISABLE();
194 CHB_LEAVE_CRIT();
195 }
196
197 /**************************************************************************/
198 /*!
199
200 */
201 /**************************************************************************/
202 void chb_reg_write16(U8 addr, U16 val)
203 {
204 U8 i;
205
206 for (i=0; i<2; i++)
207 {
208 chb_reg_write(addr + i, val >> (8 * i));
209 }
210 }
211
212 /**************************************************************************/
213 /*!
214
215 */
216 /**************************************************************************/
217 void chb_reg_write64(U8 addr, U8 *val)
218 {
219 U8 i;
220
221 for (i=0; i<8; i++)
222 {
223 chb_reg_write(addr + i, *(val + i));
224 }
225 }
226
227 /**************************************************************************/
228 /*!
229
230 */
231 /**************************************************************************/
232 void chb_reg_read_mod_write(U8 addr, U8 val, U8 mask)
233 {
234 U8 tmp;
235
236 tmp = chb_reg_read(addr);
237 val &= mask; // mask off stray bits from val
238 tmp &= ~mask; // mask off bits in reg val
239 tmp |= val; // copy val into reg val
240 chb_reg_write(addr, tmp); // write back to reg
241 }
242
243 /**************************************************************************/
244 /*!
245
246 */
247 /**************************************************************************/
248 void chb_frame_write(U8 *hdr, U8 hdr_len, U8 *data, U8 data_len)
249 {
250 U8 i, dummy;
251
252 // dont allow transmission longer than max frame size
253 if ((hdr_len + data_len) > 127)
254 {
255 return;
256 }
257
258 // initiate spi transaction
259 CHB_ENTER_CRIT();
260 CHB_SPI_ENABLE();
261
262 // send fifo write command
263 dummy = chb_xfer_byte(CHB_SPI_CMD_FW);
264
265 // write hdr contents to fifo
266 for (i=0; i<hdr_len; i++)
267 {
268 dummy = chb_xfer_byte(*hdr++);
269 }
270
271 // write data contents to fifo
272 for (i=0; i<data_len; i++)
273 {
274 dummy = chb_xfer_byte(*data++);
275 }
276
277 // terminate spi transaction
278 CHB_SPI_DISABLE();
279 CHB_LEAVE_CRIT();
280 }
281
282 /**************************************************************************/
283 /*!
284
285 */
286 /**************************************************************************/
287 static void chb_frame_read()
288 {
289 U8 i, len, data;
290
291 // CHB_ENTER_CRIT();
292 CHB_SPI_ENABLE();
293
294 /*Send frame read command and read the length.*/
295 chb_xfer_byte(CHB_SPI_CMD_FR);
296 len = chb_xfer_byte(0);
297
298 /*Check for correct frame length.*/
299 if ((len >= CHB_MIN_FRAME_LENGTH) && (len <= CHB_MAX_FRAME_LENGTH))
300 {
301 // check to see if there is room to write the frame in the buffer. if not, then drop it
302 if (len < (CFG_CHIBI_BUFFERSIZE - chb_buf_get_len()))
303 {
304 chb_buf_write(len);
305
306 for (i=0; i<len; i++)
307 {
308 data = chb_xfer_byte(0);
309 chb_buf_write(data);
310 }
311 }
312 else
313 {
314 // we've overflowed the buffer. toss the data and do some housekeeping
315 chb_pcb_t *pcb = chb_get_pcb();
316
317 // read out the data and throw it away
318 for (i=0; i<len; i++)
319 {
320 data = chb_xfer_byte(0);
321 }
322
323 // Increment the overflow stat
324 pcb->overflow++;
325
326 // print the error message
327 printf(chb_err_overflow);
328 }
329 }
330
331 CHB_SPI_DISABLE();
332 CHB_LEAVE_CRIT();
333 }
334
335 /**************************************************************************/
336 /*!
337 Read directly from the SRAM on the radio. This is only used for debugging
338 purposes.
339 */
340 /**************************************************************************/
341 #ifdef CHB_DEBUG
342 void chb_sram_read(U8 addr, U8 len, U8 *data)
343 {
344 U8 i, dummy;
345
346 CHB_ENTER_CRIT();
347 CHB_SPI_ENABLE();
348
349 /*Send SRAM read command.*/
350 dummy = chb_xfer_byte(CHB_SPI_CMD_SR);
351
352 /*Send address where to start reading.*/
353 dummy = chb_xfer_byte(addr);
354
355 for (i=0; i<len; i++)
356 {
357 *data++ = chb_xfer_byte(0);
358 }
359
360 CHB_SPI_DISABLE();
361 CHB_LEAVE_CRIT();
362 }
363
364 /**************************************************************************/
365 /*!
366
367 */
368 /**************************************************************************/
369 void chb_sram_write(U8 addr, U8 len, U8 *data)
370 {
371 U8 i, dummy;
372
373 CHB_ENTER_CRIT();
374 CHB_SPI_ENABLE();
375
376 /*Send SRAM write command.*/
377 dummy = chb_xfer_byte(CHB_SPI_CMD_SW);
378
379 /*Send address where to start writing to.*/
380 dummy = chb_xfer_byte(addr);
381
382 for (i=0; i<len; i++)
383 {
384 dummy = chb_xfer_byte(*data++);
385 }
386
387 CHB_SPI_DISABLE();
388 CHB_LEAVE_CRIT();
389 }
390 #endif
391
392 /**************************************************************************/
393 /*!
394 Set the channel mode, BPSK, OQPSK, etc...
395 */
396 /**************************************************************************/
397 void chb_set_mode(U8 mode)
398 {
399 switch (mode)
400 {
401 case OQPSK_868MHZ:
402 chb_reg_read_mod_write(TRX_CTRL_2, 0x08, 0x3f); // 802.15.4-2006, channel page 2, channel 0 (868 MHz, Europe)
403 chb_reg_read_mod_write(RF_CTRL_0, CHB_OQPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
404 break;
405 case OQPSK_915MHZ:
406 chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f); // 802.15.4-2006, channel page 2, channels 1-10 (915 MHz, US)
407 chb_reg_read_mod_write(RF_CTRL_0, CHB_OQPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
408 break;
409 case OQPSK_780MHZ:
410 chb_reg_read_mod_write(TRX_CTRL_2, 0x1c, 0x3f); // 802.15.4-2006, channel page 5, channel 0-3 (780 MHz, China)
411 chb_reg_read_mod_write(RF_CTRL_0, CHB_OQPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
412 break;
413 case BPSK40_915MHZ:
414 chb_reg_read_mod_write(TRX_CTRL_2, 0x00, 0x3f); // 802.15.4-2006, BPSK, 40 kbps
415 chb_reg_read_mod_write(RF_CTRL_0, CHB_BPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
416 break;
417 case BPSK20_868MHZ:
418 chb_reg_read_mod_write(TRX_CTRL_2, 0x00, 0x3f); // 802.15.4-2006, BPSK, 20 kbps
419 chb_reg_read_mod_write(RF_CTRL_0, CHB_BPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
420 break;
421 }
422 }
423
424 /**************************************************************************/
425 /*!
426
427 */
428 /**************************************************************************/
429 U8 chb_set_channel(U8 channel)
430 {
431 U8 state;
432
433 #if (CHB_CHINA == 1)
434
435 // this if for China only which uses a 780 MHz frequency band
436 if ((chb_reg_read(TRX_CTRL2) & 0x3f) != 0x1c)
437 {
438 chb_reg_read_mod_write(TRX_CTRL2, 0x1c, 0x3f);
439 }
440
441 if (channel > 3)
442 {
443 channel = 0;
444 }
445
446 channel = (channel << 1) + 11;
447
448 chb_reg_read_mod_write(CC_CTRL_1, 0x4, 0x7); // set 769 MHz base frequency for China
449 chb_reg_write(CC_CTRL_0, channel); // set the center frequency for the channel
450
451 #else
452 //if (channel == 0)
453 //{
454 // // Channel 0 is for European use only. make sure we are using channel page 2,
455 // // channel 0 settings for 100 kbps
456 // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x08)
457 // {
458 // chb_reg_read_mod_write(TRX_CTRL_2, 0x08, 0x3f);
459 // }
460 //}
461 //else if (channel > 10)
462 //{
463 // // if the channel is out of bounds for page 2, then default to channel 1 and
464 // // assume we're on the US frequency of 915 MHz
465 // channel = 1;
466 // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x0c)
467 // {
468 // chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f);
469 // }
470 //}
471 //else
472 //{
473 // // Channels 1-10 are for US frequencies of 915 MHz
474 // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x0c)
475 // {
476 // chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f);
477 // }
478 //}
479
480 chb_reg_read_mod_write(PHY_CC_CCA, channel, 0x1f);
481 #endif
482
483 // add a delay to allow the PLL to lock if in active mode.
484 state = chb_get_state();
485 if ((state == RX_ON) || (state == PLL_ON))
486 {
487 chb_delay_us(TIME_PLL_LOCK_TIME);
488 }
489
490 return ((chb_reg_read(PHY_CC_CCA) & 0x1f) == channel) ? RADIO_SUCCESS : RADIO_TIMED_OUT;
491 }
492
493 /**************************************************************************/
494 /*!
495 Set the power level
496 */
497 /**************************************************************************/
498 void chb_set_pwr(U8 val)
499 {
500 chb_reg_write(PHY_TX_PWR, val);
501 }
502
503 /**************************************************************************/
504 /*!
505 Set the TX/RX state machine state. Some manual manipulation is required
506 for certain operations. Check the datasheet for more details on the state
507 machine and manipulations.
508 */
509 /**************************************************************************/
510 U8 chb_set_state(U8 state)
511 {
512 U8 curr_state, delay;
513
514 // if we're sleeping then don't allow transition
515 if (gpioGetValue(CHB_SLPTRPORT, CHB_SLPTRPIN))
516 {
517 return RADIO_WRONG_STATE;
518 }
519
520 // if we're in a transition state, wait for the state to become stable
521 curr_state = chb_get_state();
522 if ((curr_state == BUSY_TX_ARET) || (curr_state == BUSY_RX_AACK) || (curr_state == BUSY_RX) || (curr_state == BUSY_TX))
523 {
524 while (chb_get_state() == curr_state);
525 }
526
527 // At this point it is clear that the requested new_state is:
528 // TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON.
529 // we need to handle some special cases before we transition to the new state
530 switch (state)
531 {
532 case TRX_OFF:
533 /* Go to TRX_OFF from any state. */
534 CHB_SLPTR_DISABLE();
535 chb_reg_read_mod_write(TRX_STATE, CMD_FORCE_TRX_OFF, 0x1f);
536 chb_delay_us(TIME_ALL_STATES_TRX_OFF);
537 break;
538
539 case TX_ARET_ON:
540 if (curr_state == RX_AACK_ON)
541 {
542 /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */
543 chb_reg_read_mod_write(TRX_STATE, CMD_PLL_ON, 0x1f);
544 chb_delay_us(TIME_RX_ON_PLL_ON);
545 }
546 break;
547
548 case RX_AACK_ON:
549 if (curr_state == TX_ARET_ON)
550 {
551 /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */
552 chb_reg_read_mod_write(TRX_STATE, CMD_PLL_ON, 0x1f);
553 chb_delay_us(TIME_RX_ON_PLL_ON);
554 }
555 break;
556 }
557
558 /* Now we're okay to transition to any new state. */
559 chb_reg_read_mod_write(TRX_STATE, state, 0x1f);
560
561 /* When the PLL is active most states can be reached in 1us. However, from */
562 /* TRX_OFF the PLL needs time to activate. */
563 delay = (curr_state == TRX_OFF) ? TIME_TRX_OFF_PLL_ON : TIME_RX_ON_PLL_ON;
564 chb_delay_us(delay);
565
566 if (chb_get_state() == state)
567 {
568 return RADIO_SUCCESS;
569 }
570 return RADIO_TIMED_OUT;
571 }
572
573 /**************************************************************************/
574 /*!
575
576 */
577 /**************************************************************************/
578 void chb_set_ieee_addr(U8 *addr)
579 {
580 chb_eeprom_write(CFG_EEPROM_CHIBI_IEEEADDR, addr, 8);
581 chb_reg_write64(IEEE_ADDR_0, addr);
582 }
583
584 /**************************************************************************/
585 /*!
586
587 */
588 /**************************************************************************/
589 void chb_get_ieee_addr(U8 *addr)
590 {
591 chb_eeprom_read(CFG_EEPROM_CHIBI_IEEEADDR, addr, 8);
592 }
593
594 /**************************************************************************/
595 /*!
596
597 */
598 /**************************************************************************/
599 void chb_set_short_addr(U16 addr)
600 {
601 U8 *addr_ptr = (U8 *)&addr;
602 chb_pcb_t *pcb = chb_get_pcb();
603
604 chb_eeprom_write(CFG_EEPROM_CHIBI_SHORTADDR, addr_ptr, 2);
605 chb_reg_write16(SHORT_ADDR_0, addr);
606 pcb->src_addr = addr;
607 }
608
609 /**************************************************************************/
610 /*!
611
612 */
613 /**************************************************************************/
614 U16 chb_get_short_addr()
615 {
616 int16_t addr;
617
618 chb_eeprom_read(CFG_EEPROM_CHIBI_SHORTADDR, (uint8_t*)&addr, 2);
619 return addr;
620 }
621 /**************************************************************************/
622 /*!
623 Set the high gain mode pin for the CC1190
624 */
625 /**************************************************************************/
626 #if (CHB_CC1190_PRESENT)
627 void chb_set_hgm(U8 enb)
628 {
629 if (enb)
630 {
631 gpioSetValue(CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 1);
632 }
633 else
634 {
635 gpioSetValue(CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 0);
636 }
637 }
638 #endif
639
640 /**************************************************************************/
641 /*!
642 Load the data into the fifo, initiate a transmission attempt,
643 and return the status of the transmission attempt.
644 */
645 /**************************************************************************/
646 U8 chb_tx(U8 *hdr, U8 *data, U8 len)
647 {
648 U8 state = chb_get_state();
649 chb_pcb_t *pcb = chb_get_pcb();
650
651 if ((state == BUSY_TX) || (state == BUSY_TX_ARET))
652 {
653 return RADIO_WRONG_STATE;
654 }
655
656 // TODO: check why we need to transition to the off state before we go to tx_aret_on
657 chb_set_state(TRX_OFF);
658 chb_set_state(TX_ARET_ON);
659
660 // TODO: try and start the frame transmission by writing TX_START command instead of toggling
661 // sleep pin...i just feel like it's kind of weird...
662
663 // write frame to buffer. first write header into buffer (add 1 for len byte), then data.
664 chb_frame_write(hdr, CHB_HDR_SZ + 1, data, len);
665
666 //Do frame transmission
667 chb_reg_read_mod_write(TRX_STATE, CMD_TX_START, 0x1F);
668
669 // wait for the transmission to end, signalled by the TRX END flag
670 while (!pcb->tx_end);
671 pcb->tx_end = false;
672
673 // check the status of the transmission
674 return chb_get_status();
675 }
676
677 /**************************************************************************/
678 /*!
679
680 */
681 /**************************************************************************/
682 static void chb_radio_init()
683 {
684 U8 ieee_addr[8];
685
686 // reset chip
687 chb_reset();
688
689 // disable intps while we config the radio
690 chb_reg_write(IRQ_MASK, 0);
691
692 // force transceiver off while we configure the intps
693 chb_reg_read_mod_write(TRX_STATE, CMD_FORCE_TRX_OFF, 0x1F);
694
695 // make sure the transceiver is in the off state before proceeding
696 while ((chb_reg_read(TRX_STATUS) & 0x1f) != TRX_OFF);
697
698 // set radio cfg parameters
699 // **note** uncomment if these will be set to something other than default
700 //chb_reg_read_mod_write(XAH_CTRL_0, CHB_MAX_FRAME_RETRIES << CHB_MAX_FRAME_RETRIES_POS, 0xF << CHB_MAX_FRAME_RETRIES_POS);
701 //chb_reg_read_mod_write(XAH_CTRL_0, CHB_MAX_CSMA_RETRIES << CHB_MAX_CSMA_RETIRES_POS, 0x7 << CHB_MAX_CSMA_RETIRES_POS);
702 //chb_reg_read_mod_write(CSMA_SEED_1, CHB_CSMA_SEED1 << CHB_CSMA_SEED1_POS, 0x7 << CHB_CSMA_SEED1_POS);
703 //chb_ret_write(CSMA_SEED0, CHB_CSMA_SEED0);
704 //chb_reg_read_mod_write(PHY_CC_CCA, CHB_CCA_MODE << CHB_CCA_MODE_POS,0x3 << CHB_CCA_MODE_POS);
705 //chb_reg_write(CCA_THRES, CHB_CCA_ED_THRES);
706
707 // set frame version that we'll accept
708 chb_reg_read_mod_write(CSMA_SEED_1, CHB_FRM_VER << CHB_FVN_POS, 3 << CHB_FVN_POS);
709
710 // set interrupt mask
711 // re-enable intps while we config the radio
712 chb_reg_write(IRQ_MASK, (1<<IRQ_RX_START) | (1<<IRQ_TRX_END));
713
714 #if (CFG_CHIBI_PROMISCUOUS == 0)
715 // set autocrc mode
716 chb_reg_read_mod_write(TRX_CTRL_1, 1 << CHB_AUTO_CRC_POS, 1 << CHB_AUTO_CRC_POS);
717 #endif
718 // set up default phy modulation, data rate and power (Ex. OQPSK, 100 kbps, 868 MHz, 3dBm)
719 chb_set_mode(CFG_CHIBI_MODE); // Defined in projectconfig.h
720 chb_set_pwr(CFG_CHIBI_POWER); // Defined in projectconfig.h
721 chb_set_channel(CFG_CHIBI_CHANNEL); // Defined in projectconfig.h
722
723 // set fsm state
724 // put trx in rx auto ack mode
725 chb_set_state(RX_STATE);
726
727 // set pan ID
728 chb_reg_write16(PAN_ID_0, CFG_CHIBI_PANID); // Defined in projectconfig.h
729
730 // set short addr
731 // NOTE: Possibly get this from EEPROM
732 chb_reg_write16(SHORT_ADDR_0, chb_get_short_addr());
733
734 // set long addr
735 // NOTE: Possibly get this from EEPROM
736 chb_get_ieee_addr(ieee_addr);
737 chb_reg_write64(IEEE_ADDR_0, ieee_addr);
738
739 #if (CHB_CC1190_PRESENT)
740 // set high gain mode pin to output and init to zero
741 gpioSetDir (CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 1);
742 gpioSetPullup (&CHB_CC1190_HGM_IOCONREG, gpioPullupMode_Inactive);
743 gpioSetValue (CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 0);
744
745 // set external power amp on AT86RF212
746 chb_reg_read_mod_write(TRX_CTRL_1, 1<<CHB_PA_EXT_EN_POS, 1<<CHB_PA_EXT_EN_POS);
747
748 // set power to lowest level possible
749 chb_set_pwr(0xd); // set to -11 dBm
750 #endif
751
752 // set interrupt/gpio pin to input
753 gpioSetDir (CHB_EINTPORT, CHB_EINTPIN, 0);
754
755 // set internal resistor on EINT pin to inactive
756 gpioSetPullup (&CHB_EINTPIN_IOCONREG, gpioPullupMode_Inactive);
757
758 // configure pin for interrupt
759 gpioSetInterrupt (CHB_EINTPORT,
760 CHB_EINTPIN,
761 gpioInterruptSense_Edge, // Edge-sensitive
762 gpioInterruptEdge_Single, // Single edge
763 gpioInterruptEvent_ActiveHigh); // High triggers interrupt
764
765 // enable interrupt
766 gpioIntEnable (CHB_EINTPORT,
767 CHB_EINTPIN);
768
769 if (chb_get_state() != RX_STATE)
770 {
771 // ERROR occurred initializing the radio. Print out error message.
772 printf(chb_err_init);
773 }
774 }
775
776 /**************************************************************************/
777 /*!
778
779 */
780 /**************************************************************************/
781 void chb_drvr_init()
782 {
783 // ToDo: Make sure gpioInit has been called
784 // ToDo: Make sure CT32B0 has been initialised and enabled
785
786 // config SPI for at86rf230 access
787 chb_spi_init();
788
789 // Setup 16-bit timer 0 (used for us delays)
790 timer16Init(0, 0xFFFF);
791 timer16Enable(0);
792
793 // Set sleep and reset as output
794 gpioSetDir(CHB_SLPTRPORT, CHB_SLPTRPIN, 1);
795 gpioSetDir(CHB_RSTPORT, CHB_RSTPIN, 1);
796
797 // configure IOs
798 gpioSetValue(CHB_SLPTRPORT, CHB_SLPTRPIN, 1); // Set sleep high
799 gpioSetValue(CHB_RSTPORT, CHB_RSTPIN, 1); // Set reset high
800
801 // Set internal resistors
802 gpioSetPullup (&CHB_SLPTRPIN_IOCONREG, gpioPullupMode_Inactive);
803 gpioSetPullup (&CHB_RSTPIN_IOCONREG, gpioPullupMode_Inactive);
804
805 // config radio
806 chb_radio_init();
807 }
808
809 /**************************************************************************/
810 /*!
811 Enable or disable the radio's sleep mode.
812 */
813 /**************************************************************************/
814 void chb_sleep(U8 enb)
815 {
816 if (enb)
817 {
818 // first we need to go to TRX OFF state
819 chb_set_state(TRX_OFF);
820
821 // set the SLPTR pin
822 // CHB_SLPTR_PORT |= _BV(CHB_SLPTR_PIN);
823 CHB_SLPTR_ENABLE();
824 }
825 else
826 {
827 // make sure the SLPTR pin is low first
828 // CHB_SLPTR_PORT &= ~(_BV(CHB_SLPTR_PIN));
829 CHB_SLPTR_DISABLE();
830
831 // we need to allow some time for the PLL to lock
832 chb_delay_us(TIME_SLEEP_TO_TRX_OFF);
833
834 // Turn the transceiver back on
835 chb_set_state(RX_STATE);
836 }
837 }
838 /**************************************************************************/
839 /*!
840
841 */
842 /**************************************************************************/
843 void chb_ISR_Handler (void)
844 {
845 U8 dummy, state, intp_src = 0;
846 chb_pcb_t *pcb = chb_get_pcb();
847
848 CHB_ENTER_CRIT();
849
850 /*Read Interrupt source.*/
851 CHB_SPI_ENABLE();
852
853 /*Send Register address and read register content.*/
854 dummy = chb_xfer_byte(IRQ_STATUS | CHB_SPI_CMD_RR);
855 intp_src = chb_xfer_byte(0);
856
857 CHB_SPI_DISABLE();
858
859 while (intp_src)
860 {
861 /*Handle the incomming interrupt. Prioritized.*/
862 if ((intp_src & CHB_IRQ_RX_START_MASK))
863 {
864 intp_src &= ~CHB_IRQ_RX_START_MASK;
865 }
866 else if (intp_src & CHB_IRQ_TRX_END_MASK)
867 {
868 state = chb_get_state();
869
870 if ((state == RX_ON) || (state == RX_AACK_ON) || (state == BUSY_RX_AACK))
871 {
872 // get the ed measurement
873 pcb->ed = chb_reg_read(PHY_ED_LEVEL);
874
875 // get the crc
876 pcb->crc = (chb_reg_read(PHY_RSSI) & (1<<7)) ? 1 : 0;
877
878 // if the crc is not valid, then do not read the frame and set the rx flag
879 if (pcb->crc)
880 {
881 // get the data
882 chb_frame_read();
883 pcb->rcvd_xfers++;
884 pcb->data_rcv = true;
885 }
886 }
887 else
888 {
889 pcb->tx_end = true;
890 }
891 intp_src &= ~CHB_IRQ_TRX_END_MASK;
892 while (chb_set_state(RX_STATE) != RADIO_SUCCESS);
893 }
894 else if (intp_src & CHB_IRQ_TRX_UR_MASK)
895 {
896 intp_src &= ~CHB_IRQ_TRX_UR_MASK;
897 pcb->underrun++;
898 }
899 else if (intp_src & CHB_IRQ_PLL_UNLOCK_MASK)
900 {
901 intp_src &= ~CHB_IRQ_PLL_UNLOCK_MASK;
902 }
903 else if (intp_src & CHB_IRQ_PLL_LOCK_MASK)
904 {
905 intp_src &= ~CHB_IRQ_PLL_LOCK_MASK;
906 }
907 else if (intp_src & CHB_IRQ_BAT_LOW_MASK)
908 {
909 intp_src &= ~CHB_IRQ_BAT_LOW_MASK;
910 pcb->battlow++;
911 }
912 else
913 {
914 }
915 }
916 CHB_LEAVE_CRIT();
917 }
This page took 0.098711 seconds and 3 git commands to generate.