moved to /storage
[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 chb_xfer_byte(addr);
193 chb_xfer_byte(val);
194
195 CHB_SPI_DISABLE();
196 CHB_LEAVE_CRIT();
197 }
198
199 /**************************************************************************/
200 /*!
201
202 */
203 /**************************************************************************/
204 void chb_reg_write16(U8 addr, U16 val)
205 {
206 U8 i;
207
208 for (i=0; i<2; i++)
209 {
210 chb_reg_write(addr + i, val >> (8 * i));
211 }
212 }
213
214 /**************************************************************************/
215 /*!
216
217 */
218 /**************************************************************************/
219 void chb_reg_write64(U8 addr, U8 *val)
220 {
221 U8 i;
222
223 for (i=0; i<8; i++)
224 {
225 chb_reg_write(addr + i, *(val + i));
226 }
227 }
228
229 /**************************************************************************/
230 /*!
231
232 */
233 /**************************************************************************/
234 void chb_reg_read_mod_write(U8 addr, U8 val, U8 mask)
235 {
236 U8 tmp;
237
238 tmp = chb_reg_read(addr);
239 val &= mask; // mask off stray bits from val
240 tmp &= ~mask; // mask off bits in reg val
241 tmp |= val; // copy val into reg val
242 chb_reg_write(addr, tmp); // write back to reg
243 }
244
245 /**************************************************************************/
246 /*!
247
248 */
249 /**************************************************************************/
250 void chb_frame_write(U8 *hdr, U8 hdr_len, U8 *data, U8 data_len)
251 {
252 //U8 i, dummy;
253 U8 i;
254
255 // dont allow transmission longer than max frame size
256 if ((hdr_len + data_len) > 127)
257 {
258 return;
259 }
260
261 // initiate spi transaction
262 CHB_ENTER_CRIT();
263 CHB_SPI_ENABLE();
264
265 // send fifo write command
266 // dummy = chb_xfer_byte(CHB_SPI_CMD_FW);
267 chb_xfer_byte(CHB_SPI_CMD_FW);
268
269 // write hdr contents to fifo
270 for (i=0; i<hdr_len; i++)
271 {
272 // dummy = chb_xfer_byte(*hdr++);
273 chb_xfer_byte(*hdr++);
274 }
275
276 // write data contents to fifo
277 for (i=0; i<data_len; i++)
278 {
279 // dummy = chb_xfer_byte(*data++);
280 chb_xfer_byte(*data++);
281 }
282
283 // terminate spi transaction
284 CHB_SPI_DISABLE();
285 CHB_LEAVE_CRIT();
286 }
287
288 /**************************************************************************/
289 /*!
290
291 */
292 /**************************************************************************/
293 static void chb_frame_read()
294 {
295 U8 i, len, data;
296
297 // CHB_ENTER_CRIT();
298 CHB_SPI_ENABLE();
299
300 /*Send frame read command and read the length.*/
301 chb_xfer_byte(CHB_SPI_CMD_FR);
302 len = chb_xfer_byte(0);
303
304 /*Check for correct frame length.*/
305 if ((len >= CHB_MIN_FRAME_LENGTH) && (len <= CHB_MAX_FRAME_LENGTH))
306 {
307 // check to see if there is room to write the frame in the buffer. if not, then drop it
308 if (len < (CFG_CHIBI_BUFFERSIZE - chb_buf_get_len()))
309 {
310 chb_buf_write(len);
311
312 for (i=0; i<len; i++)
313 {
314 data = chb_xfer_byte(0);
315 chb_buf_write(data);
316 }
317 }
318 else
319 {
320 // we've overflowed the buffer. toss the data and do some housekeeping
321 chb_pcb_t *pcb = chb_get_pcb();
322
323 // read out the data and throw it away
324 for (i=0; i<len; i++)
325 {
326 data = chb_xfer_byte(0);
327 }
328
329 // Increment the overflow stat
330 pcb->overflow++;
331
332 // print the error message
333 printf(chb_err_overflow);
334 }
335 }
336
337 CHB_SPI_DISABLE();
338 CHB_LEAVE_CRIT();
339 }
340
341 /**************************************************************************/
342 /*!
343 Read directly from the SRAM on the radio. This is only used for debugging
344 purposes.
345 */
346 /**************************************************************************/
347 #ifdef CHB_DEBUG
348 void chb_sram_read(U8 addr, U8 len, U8 *data)
349 {
350 U8 i, dummy;
351
352 CHB_ENTER_CRIT();
353 CHB_SPI_ENABLE();
354
355 /*Send SRAM read command.*/
356 dummy = chb_xfer_byte(CHB_SPI_CMD_SR);
357
358 /*Send address where to start reading.*/
359 dummy = chb_xfer_byte(addr);
360
361 for (i=0; i<len; i++)
362 {
363 *data++ = chb_xfer_byte(0);
364 }
365
366 CHB_SPI_DISABLE();
367 CHB_LEAVE_CRIT();
368 }
369
370 /**************************************************************************/
371 /*!
372
373 */
374 /**************************************************************************/
375 void chb_sram_write(U8 addr, U8 len, U8 *data)
376 {
377 U8 i, dummy;
378
379 CHB_ENTER_CRIT();
380 CHB_SPI_ENABLE();
381
382 /*Send SRAM write command.*/
383 dummy = chb_xfer_byte(CHB_SPI_CMD_SW);
384
385 /*Send address where to start writing to.*/
386 dummy = chb_xfer_byte(addr);
387
388 for (i=0; i<len; i++)
389 {
390 dummy = chb_xfer_byte(*data++);
391 }
392
393 CHB_SPI_DISABLE();
394 CHB_LEAVE_CRIT();
395 }
396 #endif
397
398 /**************************************************************************/
399 /*!
400 Set the channel mode, BPSK, OQPSK, etc...
401 */
402 /**************************************************************************/
403 void chb_set_mode(U8 mode)
404 {
405 switch (mode)
406 {
407 case OQPSK_868MHZ:
408 chb_reg_read_mod_write(TRX_CTRL_2, 0x08, 0x3f); // 802.15.4-2006, channel page 2, channel 0 (868 MHz, Europe)
409 chb_reg_read_mod_write(RF_CTRL_0, CHB_OQPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
410 break;
411 case OQPSK_915MHZ:
412 chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f); // 802.15.4-2006, channel page 2, channels 1-10 (915 MHz, US)
413 chb_reg_read_mod_write(RF_CTRL_0, CHB_OQPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
414 break;
415 case OQPSK_780MHZ:
416 chb_reg_read_mod_write(TRX_CTRL_2, 0x1c, 0x3f); // 802.15.4-2006, channel page 5, channel 0-3 (780 MHz, China)
417 chb_reg_read_mod_write(RF_CTRL_0, CHB_OQPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
418 break;
419 case BPSK40_915MHZ:
420 chb_reg_read_mod_write(TRX_CTRL_2, 0x00, 0x3f); // 802.15.4-2006, BPSK, 40 kbps
421 chb_reg_read_mod_write(RF_CTRL_0, CHB_BPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
422 break;
423 case BPSK20_868MHZ:
424 chb_reg_read_mod_write(TRX_CTRL_2, 0x00, 0x3f); // 802.15.4-2006, BPSK, 20 kbps
425 chb_reg_read_mod_write(RF_CTRL_0, CHB_BPSK_TX_OFFSET, 0x3); // this is according to table 7-16 in at86rf212 datasheet
426 break;
427 }
428 }
429
430 /**************************************************************************/
431 /*!
432
433 */
434 /**************************************************************************/
435 U8 chb_set_channel(U8 channel)
436 {
437 U8 state;
438
439 #if (CHB_CHINA == 1)
440
441 // this if for China only which uses a 780 MHz frequency band
442 if ((chb_reg_read(TRX_CTRL2) & 0x3f) != 0x1c)
443 {
444 chb_reg_read_mod_write(TRX_CTRL2, 0x1c, 0x3f);
445 }
446
447 if (channel > 3)
448 {
449 channel = 0;
450 }
451
452 channel = (channel << 1) + 11;
453
454 chb_reg_read_mod_write(CC_CTRL_1, 0x4, 0x7); // set 769 MHz base frequency for China
455 chb_reg_write(CC_CTRL_0, channel); // set the center frequency for the channel
456
457 #else
458 //if (channel == 0)
459 //{
460 // // Channel 0 is for European use only. make sure we are using channel page 2,
461 // // channel 0 settings for 100 kbps
462 // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x08)
463 // {
464 // chb_reg_read_mod_write(TRX_CTRL_2, 0x08, 0x3f);
465 // }
466 //}
467 //else if (channel > 10)
468 //{
469 // // if the channel is out of bounds for page 2, then default to channel 1 and
470 // // assume we're on the US frequency of 915 MHz
471 // channel = 1;
472 // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x0c)
473 // {
474 // chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f);
475 // }
476 //}
477 //else
478 //{
479 // // Channels 1-10 are for US frequencies of 915 MHz
480 // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x0c)
481 // {
482 // chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f);
483 // }
484 //}
485
486 chb_reg_read_mod_write(PHY_CC_CCA, channel, 0x1f);
487 #endif
488
489 // add a delay to allow the PLL to lock if in active mode.
490 state = chb_get_state();
491 if ((state == RX_ON) || (state == PLL_ON))
492 {
493 chb_delay_us(TIME_PLL_LOCK_TIME);
494 }
495
496 return ((chb_reg_read(PHY_CC_CCA) & 0x1f) == channel) ? RADIO_SUCCESS : RADIO_TIMED_OUT;
497 }
498
499 /**************************************************************************/
500 /*!
501 Set the power level
502 */
503 /**************************************************************************/
504 void chb_set_pwr(U8 val)
505 {
506 chb_reg_write(PHY_TX_PWR, val);
507 }
508
509 /**************************************************************************/
510 /*!
511 Set the TX/RX state machine state. Some manual manipulation is required
512 for certain operations. Check the datasheet for more details on the state
513 machine and manipulations.
514 */
515 /**************************************************************************/
516 U8 chb_set_state(U8 state)
517 {
518 U8 curr_state, delay;
519
520 // if we're sleeping then don't allow transition
521 if (gpioGetValue(CHB_SLPTRPORT, CHB_SLPTRPIN))
522 {
523 return RADIO_WRONG_STATE;
524 }
525
526 // if we're in a transition state, wait for the state to become stable
527 curr_state = chb_get_state();
528 if ((curr_state == BUSY_TX_ARET) || (curr_state == BUSY_RX_AACK) || (curr_state == BUSY_RX) || (curr_state == BUSY_TX))
529 {
530 while (chb_get_state() == curr_state);
531 }
532
533 // At this point it is clear that the requested new_state is:
534 // TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON.
535 // we need to handle some special cases before we transition to the new state
536 switch (state)
537 {
538 case TRX_OFF:
539 /* Go to TRX_OFF from any state. */
540 CHB_SLPTR_DISABLE();
541 chb_reg_read_mod_write(TRX_STATE, CMD_FORCE_TRX_OFF, 0x1f);
542 chb_delay_us(TIME_ALL_STATES_TRX_OFF);
543 break;
544
545 case TX_ARET_ON:
546 if (curr_state == RX_AACK_ON)
547 {
548 /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */
549 chb_reg_read_mod_write(TRX_STATE, CMD_PLL_ON, 0x1f);
550 chb_delay_us(TIME_RX_ON_PLL_ON);
551 }
552 break;
553
554 case RX_AACK_ON:
555 if (curr_state == TX_ARET_ON)
556 {
557 /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */
558 chb_reg_read_mod_write(TRX_STATE, CMD_PLL_ON, 0x1f);
559 chb_delay_us(TIME_RX_ON_PLL_ON);
560 }
561 break;
562 }
563
564 /* Now we're okay to transition to any new state. */
565 chb_reg_read_mod_write(TRX_STATE, state, 0x1f);
566
567 /* When the PLL is active most states can be reached in 1us. However, from */
568 /* TRX_OFF the PLL needs time to activate. */
569 delay = (curr_state == TRX_OFF) ? TIME_TRX_OFF_PLL_ON : TIME_RX_ON_PLL_ON;
570 chb_delay_us(delay);
571
572 if (chb_get_state() == state)
573 {
574 return RADIO_SUCCESS;
575 }
576 return RADIO_TIMED_OUT;
577 }
578
579 /**************************************************************************/
580 /*!
581
582 */
583 /**************************************************************************/
584 void chb_set_ieee_addr(U8 *addr)
585 {
586 chb_eeprom_write(CFG_EEPROM_CHIBI_IEEEADDR, addr, 8);
587 chb_reg_write64(IEEE_ADDR_0, addr);
588 }
589
590 /**************************************************************************/
591 /*!
592
593 */
594 /**************************************************************************/
595 void chb_get_ieee_addr(U8 *addr)
596 {
597 chb_eeprom_read(CFG_EEPROM_CHIBI_IEEEADDR, addr, 8);
598 }
599
600 /**************************************************************************/
601 /*!
602
603 */
604 /**************************************************************************/
605 void chb_set_short_addr(U16 addr)
606 {
607 U8 *addr_ptr = (U8 *)&addr;
608 chb_pcb_t *pcb = chb_get_pcb();
609
610 chb_eeprom_write(CFG_EEPROM_CHIBI_SHORTADDR, addr_ptr, 2);
611 chb_reg_write16(SHORT_ADDR_0, addr);
612 pcb->src_addr = addr;
613 }
614
615 /**************************************************************************/
616 /*!
617
618 */
619 /**************************************************************************/
620 U16 chb_get_short_addr()
621 {
622 int16_t addr;
623
624 chb_eeprom_read(CFG_EEPROM_CHIBI_SHORTADDR, (uint8_t*)&addr, 2);
625 return addr;
626 }
627 /**************************************************************************/
628 /*!
629 Set the high gain mode pin for the CC1190
630 */
631 /**************************************************************************/
632 #if (CHB_CC1190_PRESENT)
633 void chb_set_hgm(U8 enb)
634 {
635 if (enb)
636 {
637 gpioSetValue(CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 1);
638 }
639 else
640 {
641 gpioSetValue(CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 0);
642 }
643 }
644 #endif
645
646 /**************************************************************************/
647 /*!
648 Load the data into the fifo, initiate a transmission attempt,
649 and return the status of the transmission attempt.
650 */
651 /**************************************************************************/
652 U8 chb_tx(U8 *hdr, U8 *data, U8 len)
653 {
654 U8 state = chb_get_state();
655 chb_pcb_t *pcb = chb_get_pcb();
656
657 if ((state == BUSY_TX) || (state == BUSY_TX_ARET))
658 {
659 return RADIO_WRONG_STATE;
660 }
661
662 // TODO: check why we need to transition to the off state before we go to tx_aret_on
663 chb_set_state(TRX_OFF);
664 chb_set_state(TX_ARET_ON);
665
666 // TODO: try and start the frame transmission by writing TX_START command instead of toggling
667 // sleep pin...i just feel like it's kind of weird...
668
669 // write frame to buffer. first write header into buffer (add 1 for len byte), then data.
670 chb_frame_write(hdr, CHB_HDR_SZ + 1, data, len);
671
672 //Do frame transmission
673 chb_reg_read_mod_write(TRX_STATE, CMD_TX_START, 0x1F);
674
675 // wait for the transmission to end, signalled by the TRX END flag
676 while (!pcb->tx_end);
677 pcb->tx_end = false;
678
679 // check the status of the transmission
680 return chb_get_status();
681 }
682
683 /**************************************************************************/
684 /*!
685
686 */
687 /**************************************************************************/
688 static void chb_radio_init()
689 {
690 U8 ieee_addr[8];
691
692 // reset chip
693 chb_reset();
694
695 // disable intps while we config the radio
696 chb_reg_write(IRQ_MASK, 0);
697
698 // force transceiver off while we configure the intps
699 chb_reg_read_mod_write(TRX_STATE, CMD_FORCE_TRX_OFF, 0x1F);
700
701 // make sure the transceiver is in the off state before proceeding
702 while ((chb_reg_read(TRX_STATUS) & 0x1f) != TRX_OFF);
703
704 // set radio cfg parameters
705 // **note** uncomment if these will be set to something other than default
706 //chb_reg_read_mod_write(XAH_CTRL_0, CHB_MAX_FRAME_RETRIES << CHB_MAX_FRAME_RETRIES_POS, 0xF << CHB_MAX_FRAME_RETRIES_POS);
707 //chb_reg_read_mod_write(XAH_CTRL_0, CHB_MAX_CSMA_RETRIES << CHB_MAX_CSMA_RETIRES_POS, 0x7 << CHB_MAX_CSMA_RETIRES_POS);
708 //chb_reg_read_mod_write(CSMA_SEED_1, CHB_CSMA_SEED1 << CHB_CSMA_SEED1_POS, 0x7 << CHB_CSMA_SEED1_POS);
709 //chb_ret_write(CSMA_SEED0, CHB_CSMA_SEED0);
710 //chb_reg_read_mod_write(PHY_CC_CCA, CHB_CCA_MODE << CHB_CCA_MODE_POS,0x3 << CHB_CCA_MODE_POS);
711 //chb_reg_write(CCA_THRES, CHB_CCA_ED_THRES);
712
713 // set frame version that we'll accept
714 chb_reg_read_mod_write(CSMA_SEED_1, CHB_FRM_VER << CHB_FVN_POS, 3 << CHB_FVN_POS);
715
716 // set interrupt mask
717 // re-enable intps while we config the radio
718 chb_reg_write(IRQ_MASK, (1<<IRQ_RX_START) | (1<<IRQ_TRX_END));
719
720 #if (CFG_CHIBI_PROMISCUOUS == 0)
721 // set autocrc mode
722 chb_reg_read_mod_write(TRX_CTRL_1, 1 << CHB_AUTO_CRC_POS, 1 << CHB_AUTO_CRC_POS);
723 #endif
724 // set up default phy modulation, data rate and power (Ex. OQPSK, 100 kbps, 868 MHz, 3dBm)
725 chb_set_mode(CFG_CHIBI_MODE); // Defined in projectconfig.h
726 chb_set_pwr(CFG_CHIBI_POWER); // Defined in projectconfig.h
727 chb_set_channel(CFG_CHIBI_CHANNEL); // Defined in projectconfig.h
728
729 // set fsm state
730 // put trx in rx auto ack mode
731 chb_set_state(RX_STATE);
732
733 // set pan ID
734 chb_reg_write16(PAN_ID_0, CFG_CHIBI_PANID); // Defined in projectconfig.h
735
736 // set short addr
737 // NOTE: Possibly get this from EEPROM
738 chb_reg_write16(SHORT_ADDR_0, chb_get_short_addr());
739
740 // set long addr
741 // NOTE: Possibly get this from EEPROM
742 chb_get_ieee_addr(ieee_addr);
743 chb_reg_write64(IEEE_ADDR_0, ieee_addr);
744
745 #if (CHB_CC1190_PRESENT)
746 // set high gain mode pin to output and init to zero
747 gpioSetDir (CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 1);
748 gpioSetPullup (&CHB_CC1190_HGM_IOCONREG, gpioPullupMode_Inactive);
749 gpioSetValue (CHB_CC1190_HGM_PORT, CHB_CC1190_HGM_PIN, 0);
750
751 // set external power amp on AT86RF212
752 chb_reg_read_mod_write(TRX_CTRL_1, 1<<CHB_PA_EXT_EN_POS, 1<<CHB_PA_EXT_EN_POS);
753
754 // set power to lowest level possible
755 chb_set_pwr(0xd); // set to -11 dBm
756 #endif
757
758 // set interrupt/gpio pin to input
759 gpioSetDir (CHB_EINTPORT, CHB_EINTPIN, 0);
760
761 // set internal resistor on EINT pin to inactive
762 gpioSetPullup (&CHB_EINTPIN_IOCONREG, gpioPullupMode_Inactive);
763
764 // configure pin for interrupt
765 gpioSetInterrupt (CHB_EINTPORT,
766 CHB_EINTPIN,
767 gpioInterruptSense_Edge, // Edge-sensitive
768 gpioInterruptEdge_Single, // Single edge
769 gpioInterruptEvent_ActiveLow); // High triggers interrupt
770
771 // enable interrupt
772 gpioIntEnable (CHB_EINTPORT,
773 CHB_EINTPIN);
774
775 if (chb_get_state() != RX_STATE)
776 {
777 // ERROR occurred initializing the radio. Print out error message.
778 printf(chb_err_init);
779 }
780 }
781
782 /**************************************************************************/
783 /*!
784
785 */
786 /**************************************************************************/
787 void chb_drvr_init()
788 {
789 // ToDo: Make sure gpioInit has been called
790 // ToDo: Make sure CT32B0 has been initialised and enabled
791
792 // config SPI for at86rf230 access
793 chb_spi_init();
794
795 // Setup 16-bit timer 0 (used for us delays)
796 timer16Init(0, 0xFFFF);
797 timer16Enable(0);
798
799 // Set sleep and reset as output
800 gpioSetDir(CHB_SLPTRPORT, CHB_SLPTRPIN, 1);
801 gpioSetDir(CHB_RSTPORT, CHB_RSTPIN, 1);
802
803 // configure IOs
804 gpioSetValue(CHB_SLPTRPORT, CHB_SLPTRPIN, 1); // Set sleep high
805 gpioSetValue(CHB_RSTPORT, CHB_RSTPIN, 1); // Set reset high
806
807 // Set internal resistors
808 gpioSetPullup (&CHB_SLPTRPIN_IOCONREG, gpioPullupMode_Inactive);
809 gpioSetPullup (&CHB_RSTPIN_IOCONREG, gpioPullupMode_Inactive);
810
811 // config radio
812 chb_radio_init();
813 }
814
815 /**************************************************************************/
816 /*!
817 Enable or disable the radio's sleep mode.
818 */
819 /**************************************************************************/
820 void chb_sleep(U8 enb)
821 {
822 if (enb)
823 {
824 // first we need to go to TRX OFF state
825 chb_set_state(TRX_OFF);
826
827 // set the SLPTR pin
828 // CHB_SLPTR_PORT |= _BV(CHB_SLPTR_PIN);
829 CHB_SLPTR_ENABLE();
830 }
831 else
832 {
833 // make sure the SLPTR pin is low first
834 // CHB_SLPTR_PORT &= ~(_BV(CHB_SLPTR_PIN));
835 CHB_SLPTR_DISABLE();
836
837 // we need to allow some time for the PLL to lock
838 chb_delay_us(TIME_SLEEP_TO_TRX_OFF);
839
840 // Turn the transceiver back on
841 chb_set_state(RX_STATE);
842 }
843 }
844 /**************************************************************************/
845 /*!
846
847 */
848 /**************************************************************************/
849 void chb_ISR_Handler (void)
850 {
851 // U8 dummy, state, intp_src = 0;
852 U8 state, intp_src = 0;
853 chb_pcb_t *pcb = chb_get_pcb();
854
855 CHB_ENTER_CRIT();
856
857 /*Read Interrupt source.*/
858 CHB_SPI_ENABLE();
859
860 /*Send Register address and read register content.*/
861 // dummy = chb_xfer_byte(IRQ_STATUS | CHB_SPI_CMD_RR);
862 chb_xfer_byte(IRQ_STATUS | CHB_SPI_CMD_RR);
863 intp_src = chb_xfer_byte(0);
864
865 CHB_SPI_DISABLE();
866
867 while (intp_src)
868 {
869 /*Handle the incomming interrupt. Prioritized.*/
870 if ((intp_src & CHB_IRQ_RX_START_MASK))
871 {
872 intp_src &= ~CHB_IRQ_RX_START_MASK;
873 }
874 else if (intp_src & CHB_IRQ_TRX_END_MASK)
875 {
876 state = chb_get_state();
877
878 if ((state == RX_ON) || (state == RX_AACK_ON) || (state == BUSY_RX_AACK))
879 {
880 // get the ed measurement
881 pcb->ed = chb_reg_read(PHY_ED_LEVEL);
882
883 // get the crc
884 pcb->crc = (chb_reg_read(PHY_RSSI) & (1<<7)) ? 1 : 0;
885
886 // if the crc is not valid, then do not read the frame and set the rx flag
887 if (pcb->crc)
888 {
889 // get the data
890 chb_frame_read();
891 pcb->rcvd_xfers++;
892 pcb->data_rcv = true;
893 }
894 }
895 else
896 {
897 pcb->tx_end = true;
898 }
899 intp_src &= ~CHB_IRQ_TRX_END_MASK;
900 while (chb_set_state(RX_STATE) != RADIO_SUCCESS);
901 }
902 else if (intp_src & CHB_IRQ_TRX_UR_MASK)
903 {
904 intp_src &= ~CHB_IRQ_TRX_UR_MASK;
905 pcb->underrun++;
906 }
907 else if (intp_src & CHB_IRQ_PLL_UNLOCK_MASK)
908 {
909 intp_src &= ~CHB_IRQ_PLL_UNLOCK_MASK;
910 }
911 else if (intp_src & CHB_IRQ_PLL_LOCK_MASK)
912 {
913 intp_src &= ~CHB_IRQ_PLL_LOCK_MASK;
914 }
915 else if (intp_src & CHB_IRQ_BAT_LOW_MASK)
916 {
917 intp_src &= ~CHB_IRQ_BAT_LOW_MASK;
918 pcb->battlow++;
919 }
920 else
921 {
922 }
923 }
924 CHB_LEAVE_CRIT();
925 }
This page took 0.111334 seconds and 5 git commands to generate.