Contiki 3.x
mrf24j40.c
Go to the documentation of this file.
1 /*
2  * Contiki SeedEye Platform project
3  *
4  * Copyright (c) 2012,
5  * Scuola Superiore Sant'Anna (http://www.sssup.it) and
6  * Consorzio Nazionale Interuniversitario per le Telecomunicazioni
7  * (http://www.cnit.it).
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the Institute nor the names of its contributors
20  * may be used to endorse or promote products derived from this software
21  * without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 /**
38  * \addtogroup mrf24j40 MRF24J40 Driver
39  *
40  * @{
41  */
42 
43 /**
44  * \file mrf24j40.c
45  *
46  * \brief MRF24J40 Driver
47  * \author Giovanni Pellerano <giovanni.pellerano@evilaliv3.org>
48  * \date 2012-03-21
49  */
50 
51 #include "contiki.h"
52 
53 #include "mrf24j40.h"
54 #include "mrf24j40_arch.h"
55 
56 #include <pic32_spi.h>
57 #include <pic32_irq.h>
58 
59 #include "net/packetbuf.h"
60 #include "net/netstack.h"
61 
62 #define DEBUG 0
63 #if DEBUG
64 #include <stdio.h>
65 #define PRINTF(...) printf(__VA_ARGS__)
66 #else
67 #define PRINTF(...)
68 #endif
69 
70 /*---------------------------------------------------------------------------*/
71 PROCESS(mrf24j40_process, "MRF24J40 driver");
72 /*---------------------------------------------------------------------------*/
73 
74 static volatile uint8_t mrf24j40_last_lqi;
75 static volatile uint8_t mrf24j40_last_rssi;
76 static volatile uint8_t status_tx;
77 static volatile uint8_t pending;
78 static volatile uint8_t receive_on;
79 
80 /*---------------------------------------------------------------------------*/
81 static void
82 set_short_add_mem(uint8_t addr, uint8_t val)
83 {
84  const uint8_t tmp = MRF24J40_INTERRUPT_ENABLE_STAT();
85  uint8_t msg[2];
86 
87  msg[0] = (addr << 1) | 0x01;
88  msg[1] = val;
89 
90  if(tmp) {
91  MRF24J40_INTERRUPT_ENABLE_CLR();
92  }
93 
94  MRF24J40_CSn_LOW();
95  MRF24J40_SPI_PORT_WRITE(msg, 2);
96  MRF24J40_CSn_HIGH();
97 
98  if(tmp) {
99  MRF24J40_INTERRUPT_ENABLE_SET();
100  }
101 }
102 /*---------------------------------------------------------------------------*/
103 static void
104 set_long_add_mem(uint16_t addr, uint8_t val)
105 {
106  const uint8_t tmp = MRF24J40_INTERRUPT_ENABLE_STAT();
107  uint8_t msg[3];
108 
109  msg[0] = (((uint8_t)(addr >> 3)) & 0x7F) | 0x80;
110  msg[1] = (((uint8_t)(addr << 5)) & 0xE0) | 0x10;
111  msg[2] = val;
112 
113  if(tmp) {
114  MRF24J40_INTERRUPT_ENABLE_CLR();
115  }
116 
117  MRF24J40_CSn_LOW();
118  MRF24J40_SPI_PORT_WRITE(msg, 3);
119  MRF24J40_CSn_HIGH();
120 
121  if(tmp) {
122  MRF24J40_INTERRUPT_ENABLE_SET();
123  }
124 }
125 /*---------------------------------------------------------------------------*/
126 static uint8_t
127 get_short_add_mem(uint8_t addr)
128 {
129  const uint8_t tmp = MRF24J40_INTERRUPT_ENABLE_STAT();
130  uint8_t ret_val;
131 
132  addr <<= 1;
133 
134  if(tmp) {
135  MRF24J40_INTERRUPT_ENABLE_CLR();
136  }
137 
138  MRF24J40_CSn_LOW();
139  MRF24J40_SPI_PORT_WRITE(&addr, 1);
140  MRF24J40_SPI_PORT_READ(&ret_val, 1);
141  MRF24J40_CSn_HIGH();
142 
143  if(tmp) {
144  MRF24J40_INTERRUPT_ENABLE_SET();
145  }
146 
147  return ret_val;
148 }
149 /*---------------------------------------------------------------------------*/
150 static uint8_t
151 get_long_add_mem(uint16_t addr)
152 {
153  const uint8_t tmp = MRF24J40_INTERRUPT_ENABLE_STAT();
154  uint8_t ret_val;
155  uint8_t msg[2];
156 
157  msg[0] = (((uint8_t)(addr >> 3)) & 0x7F) | 0x80;
158  msg[1] = ((uint8_t)(addr << 5)) & 0xE0;
159 
160  if(tmp) {
161  MRF24J40_INTERRUPT_ENABLE_CLR();
162  }
163 
164  MRF24J40_CSn_LOW();
165  MRF24J40_SPI_PORT_WRITE(msg, 2);
166  MRF24J40_SPI_PORT_READ(&ret_val, 1);
167  MRF24J40_CSn_HIGH();
168 
169  if(tmp) {
170  MRF24J40_INTERRUPT_ENABLE_SET();
171  }
172 
173  return ret_val;
174 }
175 /*---------------------------------------------------------------------------*/
176 static void
177 reset_rf_state_machine(void)
178 {
179  /*
180  * Reset RF state machine
181  */
182 
183  const uint8_t rfctl = get_short_add_mem(MRF24J40_RFCTL);
184 
185  set_short_add_mem(MRF24J40_RFCTL, rfctl | 0b00000100);
186  set_short_add_mem(MRF24J40_RFCTL, rfctl & 0b11111011);
187 
188  clock_delay_usec(2500);
189 }
190 /*---------------------------------------------------------------------------*/
191 void
192 flush_rx_fifo(void)
193 {
194  set_short_add_mem(MRF24J40_RXFLUSH, get_short_add_mem(MRF24J40_RXFLUSH) | 0b00000001);
195 }
196 /*---------------------------------------------------------------------------*/
197 /**
198  * \brief Set the channel
199  *
200  * This routine sets the rx/tx channel
201  */
202 void
204 {
205  set_long_add_mem(MRF24J40_RFCON0, ((ch - 11) << 4) | 0b00000011);
206 
207  reset_rf_state_machine();
208 }
209 /*---------------------------------------------------------------------------*/
210 /**
211  * \brief Store MAC PAN ID
212  *
213  * This routine sets the MAC PAN ID in the MRF24J40.
214  */
215 void
216 mrf24j40_set_panid(uint16_t id)
217 {
218  set_short_add_mem(MRF24J40_PANIDL, (uint8_t)id);
219  set_short_add_mem(MRF24J40_PANIDH, (uint8_t)(id >> 8));
220 }
221 /*---------------------------------------------------------------------------*/
222 /**
223  * \brief Store short MAC address
224  *
225  * This routine sets the short MAC address in the MRF24J40.
226  */
227 void
229 {
230  set_short_add_mem(MRF24J40_SADRL, (uint8_t)addr);
231  set_short_add_mem(MRF24J40_SADRH, (uint8_t)(addr >> 8));
232 }
233 /*---------------------------------------------------------------------------*/
234 /**
235  * \brief Store extended MAC address
236  *
237  * This routine sets the extended MAC address in the MRF24J40.
238  */
239 void
241 {
242  set_short_add_mem(MRF24J40_EADR7, (uint8_t)addr);
243  set_short_add_mem(MRF24J40_EADR6, (uint8_t)(addr >> 8));
244  set_short_add_mem(MRF24J40_EADR5, (uint8_t)(addr >> 16));
245  set_short_add_mem(MRF24J40_EADR4, (uint8_t)(addr >> 24));
246  set_short_add_mem(MRF24J40_EADR3, (uint8_t)(addr >> 32));
247  set_short_add_mem(MRF24J40_EADR2, (uint8_t)(addr >> 40));
248  set_short_add_mem(MRF24J40_EADR1, (uint8_t)(addr >> 48));
249  set_short_add_mem(MRF24J40_EADR0, (uint8_t)(addr >> 56));
250 }
251 /*---------------------------------------------------------------------------*/
252 /**
253  * \brief Get short MAC address
254  *
255  * This routine gets the short MAC address stored in the MRF24J40.
256  */
257 void
259 {
260  *(((uint8_t *)& addr)) = get_short_add_mem(MRF24J40_SADRH);
261  *(((uint8_t *)& addr) + 1) = get_short_add_mem(MRF24J40_SADRL);
262 }
263 /*---------------------------------------------------------------------------*/
264 /**
265  * \brief Gets extended MAC address
266  *
267  * This routine gets the extended MAC address stored in the MRF24J40.
268  */
269 void
271 {
272  *(((uint8_t *)& addr)) = get_short_add_mem(MRF24J40_EADR7);
273  *(((uint8_t *)& addr) + 1) = get_short_add_mem(MRF24J40_EADR6);
274  *(((uint8_t *)& addr) + 2) = get_short_add_mem(MRF24J40_EADR5);
275  *(((uint8_t *)& addr) + 3) = get_short_add_mem(MRF24J40_EADR4);
276  *(((uint8_t *)& addr) + 4) = get_short_add_mem(MRF24J40_EADR3);
277  *(((uint8_t *)& addr) + 5) = get_short_add_mem(MRF24J40_EADR2);
278  *(((uint8_t *)& addr) + 6) = get_short_add_mem(MRF24J40_EADR1);
279  *(((uint8_t *)& addr) + 7) = get_short_add_mem(MRF24J40_EADR0);
280 }
281 /*---------------------------------------------------------------------------*/
282 /**
283  * \brief Set TX power
284  *
285  * This routine sets the transmission power of the MRF24J40.
286  */
287 void
289 {
290  set_long_add_mem(MRF24J40_RFCON3, pwr);
291 }
292 /*---------------------------------------------------------------------------*/
293 /**
294  * \brief Get radio status
295  *
296  * This routine returns the MRF24J40 status.
297  */
298 uint8_t
300 {
301  return get_long_add_mem(MRF24J40_RFSTATE);
302 }
303 
304 /*---------------------------------------------------------------------------*/
305 /**
306  * \brief Get the RSSI
307  *
308  * This routine returns the rssi value mesured in dbm
309  * Note: to convert the returned value to dBm, use the table 3-8 available
310  * in the MRF24J40 datasheet.
311  */
312 uint8_t
314 {
315  /*
316  * 3.6.1 RSSI FIRMWARE REQUEST (RSSI MODE1)
317  * In this mode, the host microcontroller sends a request
318  * to calculate RSSI, then waits until it is done and then
319  * reads the RSSI value. The steps are:
320  *
321  * 1.
322  * Set RSSIMODE1 0x3E<7> – Initiate RSSI
323  * calculation.
324  *
325  * 2.
326  * Wait until RSSIRDY 0x3E<0> is set to ‘1’ – RSSI
327  * calculation is complete.
328  *
329  * 3.
330  * Read RSSI 0x210<7:0> – The RSSI register
331  * contains the averaged RSSI received power
332  * level for 8 symbol periods.
333  */
334 
335  /* Initiate RSSI calculation */
336  set_short_add_mem(MRF24J40_BBREG6, get_short_add_mem(MRF24J40_BBREG6) | 0b10000000);
337 
338  /* Wait until RSSI calculation is done */
339  while(!(get_short_add_mem(MRF24J40_BBREG6) & 0b00000001)) {
340  ;
341  }
342 
343  mrf24j40_last_rssi = get_long_add_mem(MRF24J40_RSSI);
344 
345  return mrf24j40_last_rssi;
346 }
347 /*---------------------------------------------------------------------------*/
348 /**
349  * \brief Get the last read RSSI
350  *
351  * This routine returns the last rssi value mesured in dbm
352  * Note: to convert the returned value to dBm, use the table 3-8 available
353  * in the MRF24J40 datasheet.
354  */
355 uint8_t
357 {
358  return mrf24j40_last_rssi;
359 }
360 /*---------------------------------------------------------------------------*/
361 /**
362  * \brief Get the last read LQI
363  *
364  * This routine returns the last lqi
365  */
366 uint8_t
368 {
369  return mrf24j40_last_lqi;
370 }
371 /*---------------------------------------------------------------------------*/
372 /**
373  * \brief Store message
374  *
375  * This routine stores a buffer of buf_len bytes in the TX_FIFO
376  * buffer of the MRF24J40.
377  */
378 int32_t
379 mrf24j40_set_txfifo(const uint8_t *buf, uint8_t buf_len)
380 {
381  uint8_t i;
382 
383  if((buf_len == 0) || (buf_len > 128)) {
384  return -1;
385  }
386 
387  set_long_add_mem(MRF24J40_NORMAL_TX_FIFO, 0);
388 
389  set_long_add_mem(MRF24J40_NORMAL_TX_FIFO + 1, buf_len);
390 
391  for(i = 0; i < buf_len; ++i) {
392  set_long_add_mem(MRF24J40_NORMAL_TX_FIFO + 2 + i, buf[i]);
393  }
394 
395  return 0;
396 }
397 /*---------------------------------------------------------------------------*/
398 /**
399  * \brief Get message
400  *
401  * This routine is used to retrieve a message stored in the RX_FIFO
402  */
403 int32_t
404 mrf24j40_get_rxfifo(uint8_t *buf, uint8_t buf_len)
405 {
406  uint8_t i, len;
407 
408  MRF24J40_INTERRUPT_ENABLE_CLR();
409 
410  /* Disable packet reception */
411  set_short_add_mem(MRF24J40_BBREG1, 0b00000100);
412 
413  /* Get packet length discarding 2 bytes (LQI, RSSI) */
414  len = get_long_add_mem(MRF24J40_RX_FIFO) - 2;
415 
416  if(len <= buf_len) {
417  /* Get the packet */
418  for(i = 0; i < len; ++i) {
419  buf[i] = get_long_add_mem(MRF24J40_RX_FIFO + i + 1);
420  }
421 
422  /*
423  * packet len includes = header + paylod + LQI + RSSI
424  */
425 #ifdef ADD_RSSI_AND_LQI_TO_PACKET
426  mrf24j40_last_lqi = get_long_add_mem(MRF24J40_RX_FIFO + len + 3);
427  mrf24j40_last_rssi = get_long_add_mem(MRF24J40_RX_FIFO + len + 4);
428 #endif
429  } else {
430  len = 0;
431  }
432 
433  /* Enable packet reception */
434  set_short_add_mem(MRF24J40_BBREG1, 0b00000000);
435 
436  pending = 0;
437 
438 #ifdef MRF24J40_PROMISCUOUS_MODE
439  /*
440  * Flush RX FIFO as suggested by the work around 1 in
441  * MRF24J40 Silicon Errata.
442  */
443  flush_rx_fifo();
444 #endif
445 
446  MRF24J40_INTERRUPT_ENABLE_SET();
447 
448  return len == 0 ? -1 : len;
449 }
450 /*---------------------------------------------------------------------------*/
451 /**
452  * \brief Start sleep
453  *
454  * This routine puts the radio in sleep mode.
455  */
456 static void
457 put_to_sleep(void)
458 {
459  /* Prepare WAKE pin: */
460  MRF24J40_WAKE = 0;
461 
462  /* Enable Immediate Wake-up mode */
463  set_short_add_mem(MRF24J40_WAKECON, 0b10000000);
464 
465  set_short_add_mem(MRF24J40_SOFTRST, 0b00000100);
466 
467  set_short_add_mem(MRF24J40_RXFLUSH, 0b01100000);
468 
469  /* Put to sleep */
470  set_short_add_mem(MRF24J40_SLPACK, 0b10000000);
471 }
472 /*---------------------------------------------------------------------------*/
473 /**
474  * \brief Awake the radio
475  *
476  * This routine turns on and sets the radio on receiving mode.
477  * Note: After performing this routine the radio is in the receiving state.
478  */
479 static void
480 wake(void)
481 {
482  /* Wake-up */
483  MRF24J40_WAKE = 1;
484 
485  /* RF State Machine reset */
486  set_short_add_mem(MRF24J40_RFCTL, 0b00000100);
487  set_short_add_mem(MRF24J40_RFCTL, 0b00000000);
488 
489  clock_delay_usec(2500);
490 }
491 /*---------------------------------------------------------------------------*/
492 int
493 mrf24j40_on(void)
494 {
495  if(!receive_on) {
496  wake();
497 
498  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
499  receive_on = 1;
500  }
501 
502  return 1;
503 }
504 /*---------------------------------------------------------------------------*/
505 int
506 mrf24j40_off(void)
507 {
508  if(receive_on) {
509  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
510  receive_on = 0;
511 
512  put_to_sleep();
513  }
514 
515  return 1;
516 }
517 /*---------------------------------------------------------------------------*/
518 /**
519  * \brief Init transceiver
520  *
521  * This routine initializes the radio transceiver
522  */
523 int
525 {
526  uint8_t i;
527 
528  /* Set the IO pins direction */
529  MRF24J40_PINDIRECTION_INIT();
530 
531  /* Set interrupt registers and reset flags */
532  MRF24J40_INTERRUPT_INIT(6, 3);
533 
534  if(MRF24J40_SPI_PORT_INIT(10000000, SPI_DEFAULT) < 0)
535  return -1;
536 
537  PRINTF("MRF24J40 Initialization started\n");
538 
539  MRF24J40_HARDRESET_LOW();
540 
541  clock_delay_usec(2500);
542 
543  MRF24J40_HARDRESET_HIGH();
544 
545  clock_delay_usec(2500);
546 
547  /*
548  * bit 7:3 reserved: Maintain as ‘0’
549  * bit 2 RSTPWR: Power Management Reset bit
550  * 1 = Reset power management circuitry (bit is automatically cleared to ‘0’ by hardware)
551  * bit 1 RSTBB: Baseband Reset bit
552  * 1 = Reset baseband circuitry (bit is automatically cleared to ‘0’ by hardware)
553  * bit 0 RSTMAC: MAC Reset bit
554  * 1 = Reset MAC circuitry (bit is automatically cleared to ‘0’ by hardware)
555  */
556  set_short_add_mem(MRF24J40_SOFTRST, 0b00000111);
557 
558  /*
559  * wait until the radio reset is completed
560  */
561  do {
562  i = get_short_add_mem(MRF24J40_SOFTRST);
563  } while((i & 0b0000111) != 0);
564 
565  clock_delay_usec(2500);
566 
567 
568  /*
569  * bit 7 FIFOEN: FIFO Enable bit 1 = Enabled (default). Always maintain this bit as a ‘1’.
570  * bit 6 reserved: Maintain as ‘0’
571  * bit 5:2 TXONTS<3:0>: Transmitter Enable On Time Symbol bits(1)
572  * Transmitter on time before beginning of packet. Units: symbol period (16 μs).
573  * Minimum value: 0x1. Default value: 0x2 (2 * 16 μs = 32 μs). Recommended value: 0x6 (6 * 16 μs = 96 μs).
574  * bit 1:0 TXONT<8:7>: Transmitter Enable On Time Tick bits(1)
575  * Transmitter on time before beginning of packet. TXONT is a 9-bit value. TXONT<6:0> bits are located
576  * in SYMTICKH<7:1>. Units: tick (50 ns). Default value = 0x028 (40 * 50 ns = 2 μs).
577  */
578  set_short_add_mem(MRF24J40_PACON2, 0b10011000);
579 
580  mrf24j40_set_channel(MRF24J40_DEFAULT_CHANNEL);
581 
582  set_long_add_mem(MRF24J40_RFCON1, 0b00000010); /* program the RF and Baseband Register */
583  /* as suggested by the datasheet */
584 
585  set_long_add_mem(MRF24J40_RFCON2, 0b10000000); /* enable PLL */
586 
587  mrf24j40_set_tx_power(0b00000000); /* set power 0dBm (plus 20db power amplifier 20dBm)*/
588 
589  /*
590  * Set up
591  *
592  * bit 7 '1' as suggested by the datasheet
593  * bit 6:5 '00' reserved
594  * bit 4 '1' recovery from sleep 1 usec
595  * bit 3 '0' battery monitor disabled
596  * bit 2:0 '000' reserved
597  */
598  set_long_add_mem(MRF24J40_RFCON6, 0b10010000);
599 
600  set_long_add_mem(MRF24J40_RFCON7, 0b10000000); /* Sleep clock = 100kHz */
601  set_long_add_mem(MRF24J40_RFCON8, 0b00000010); /* as suggested by the datasheet */
602 
603  set_long_add_mem(MRF24J40_SLPCON1, 0b00100001); /* as suggested by the datasheet */
604 
605  /* Program CCA, RSSI threshold values */
606  set_short_add_mem(MRF24J40_BBREG2, 0b01111000); /* Recommended value by the datashet */
607  set_short_add_mem(MRF24J40_CCAEDTH, 0b01100000); /* Recommended value by the datashet */
608 
609 #ifdef MRF24J40MB
610  /* Activate the external amplifier needed by the MRF24J40MB */
611  set_long_add_mem(MRF24J40_TESTMODE, 0b0001111);
612  PRINTF("MRF24J40 Init Amplifier activated \n");
613 #endif
614 
615 #ifdef ADD_RSSI_AND_LQI_TO_PACKET
616  /* Enable the packet RSSI */
617  set_short_add_mem(MRF24J40_BBREG6, 0b01000000);
618  PRINTF("MRF24J40 Init append RSSI and LQI to packet\n");
619 #endif
620 
621  /*
622  * Wait until the radio state machine is not on rx mode
623  */
624  do {
625  i = get_long_add_mem(MRF24J40_RFSTATE);
626  } while((i & 0xA0) != 0xA0);
627 
628  i = 0;
629 
630 #ifdef MRF24J40_DISABLE_AUTOMATIC_ACK
631  i = i | 0b00100000;
632  PRINTF("MRF24J40 Init NO_AUTO_ACK\n");
633 #endif
634 
635 #ifdef MRF24J40_PAN_COORDINATOR
636  i = i | 0b00001000;
637  PRINTF("MRF24J40 Init PAN COORD\n");
638  set_short_add_mem(MRF24J40_ORDER, 0b11111111);
639 #endif
640 
641 #ifdef MRF24J40_COORDINATOR
642  i = i | 0b00000100;
643  PRINTF("MRF24J40 Init COORD\n");
644 #endif
645 
646 #ifdef MRF24J40_ACCEPT_WRONG_CRC_PKT
647  i = i | 0b00000010;
648  PRINTF("MRF24J40 Init Accept Wrong CRC\n");
649 #endif
650 
651 #ifdef MRF24J40_PROMISCUOUS_MODE
652  i = i | 0b00000001;
653  PRINTF("MRF24J40 Init PROMISCUOUS MODE\n");
654 #endif
655 
656  /*
657  * Set the RXMCR register.
658  * Default setting i = 0x00, which means:
659  * - Automatic ACK;
660  * - Device is not a PAN coordinator;
661  * - Device is not a coordinator;
662  * - Accept only packets with good CRC
663  * - Discard packet when there is a MAC address mismatch,
664  * illegal frame type, dPAN/sPAN or MAC short address mismatch.
665  */
666  set_short_add_mem(MRF24J40_RXMCR, i);
667  PRINTF("RXMCR 0x%X\n", i);
668 
669  /*
670  * Set the TXMCR register.
671  * bit 7 '0' Enable No Carrier Sense Multiple Access (CSMA) Algorithm.
672  * bit 6 '0' Disable Battery Life Extension Mode bit.
673  * bit 5 '0' Disable Slotted CSMA-CA Mode bit.
674  * bit 4:3 '11' MAC Minimum Backoff Exponent bits (macMinBE).
675  * bit 2:0 '100' CSMA Backoff bits (macMaxCSMABackoff)
676  */
677  set_short_add_mem(MRF24J40_TXMCR, 0b00011100);
678 
679  i = get_short_add_mem(MRF24J40_TXMCR);
680  PRINTF("TXMCR 0x%X\n", i);
681 
682  /*
683  * Set TX turn around time as defined by IEEE802.15.4 standard
684  */
685  set_short_add_mem(MRF24J40_TXSTBL, 0b10010101);
686  set_short_add_mem(MRF24J40_TXTIME, 0b00110000);
687 
688 #ifdef INT_POLARITY_HIGH
689  /* Set interrupt edge polarity high */
690  set_long_add_mem(MRF24J40_SLPCON0, 0b00000011);
691  PRINTF("MRF24J40 Init INT Polarity High\n");
692 #else
693  set_long_add_mem(MRF24J40_SLPCON0, 0b00000001);
694  PRINTF("MRF24J40 Init INT Polarity Low\n");
695 #endif
696 
697  PRINTF("MRF24J40 Inititialization completed\n");
698 
699  mrf24j40_last_lqi = 0;
700  mrf24j40_last_rssi = 0;
701  status_tx = MRF24J40_TX_ERR_NONE;
702  pending = 0;
703 
704  receive_on = 1;
705  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
706 
707  reset_rf_state_machine();
708 
709  /* Flush RX FIFO */
710  flush_rx_fifo();
711 
712  process_start(&mrf24j40_process, NULL);
713 
714  /*
715  *
716  * Setup interrupts.
717  *
718  * set INTCON
719  * bit 7 '1' Disables the sleep alert interrupt
720  * bit 6 '1' Disables the wake-up alert interrupt
721  * bit 5 '1' Disables the half symbol timer interrupt
722  * bit 4 '1' Disables the security key request interrupt
723  * bit 3 '0' Enables the RX FIFO reception interrupt
724  * bit 2 '1' Disables the TX GTS2 FIFO transmission interrupt
725  * bit 1 '1' Disables the TX GTS1 FIFO transmission interrupt
726  * bit 0 '0' Enables the TX Normal FIFO transmission interrupt
727  */
728  set_short_add_mem(MRF24J40_INTCON, 0b11110110);
729 
730  return 0;
731 }
732 /*---------------------------------------------------------------------------*/
733 int
734 mrf24j40_prepare(const void *data, unsigned short len)
735 {
736  PRINTF("PREPARE %u bytes\n", len);
737 
738  uint8_t receive_was_on = receive_on;
739 
740  mrf24j40_on();
741 
742  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
743 
744  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
745 
746  mrf24j40_set_txfifo(data, len);
747 
748  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
749 
750  if(!receive_was_on) {
751  mrf24j40_off();
752  } else {
753  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
754  }
755 
756  return 0;
757 }
758 /*---------------------------------------------------------------------------*/
759 int
760 mrf24j40_transmit(unsigned short len)
761 {
762  PRINTF("TRANSMIT %u bytes\n", len);
763 
764  uint8_t receive_was_on = receive_on;
765 
766  mrf24j40_on();
767 
768  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
769 
770  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
771 
772  status_tx = MRF24J40_TX_WAIT;
773 
774  set_short_add_mem(MRF24J40_TXNCON, 0b00000001);
775 
776  /* Wait until the transmission has finished. */
777  while(status_tx == MRF24J40_TX_WAIT) {
778  ;
779  }
780 
781  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
782 
783  if(!receive_was_on) {
784  mrf24j40_off();
785  } else {
786  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
787  }
788 
789  switch(status_tx) {
790  case MRF24J40_TX_ERR_NONE:
791  return RADIO_TX_OK;
792  case MRF24J40_TX_ERR_COLLISION:
793  return RADIO_TX_COLLISION;
794  case MRF24J40_TX_ERR_MAXRETRY:
795  return RADIO_TX_NOACK;
796  default:
797  return RADIO_TX_ERR;
798  }
799 }
800 /*---------------------------------------------------------------------------*/
801 int
802 mrf24j40_write(const void *data, uint16_t len)
803 {
804  int ret = -1;
805 
806  PRINTF("PREPARE & TRANSMIT %u bytes\n", len);
807 
808  if(mrf24j40_prepare(data, len))
809  return ret;
810 
811  ret = mrf24j40_transmit(len);
812 
813  return ret;
814 }
815 
816 /*---------------------------------------------------------------------------*/
817 int
818 mrf24j40_read(void *data, uint16_t len)
819 {
820  return mrf24j40_get_rxfifo(data, len);
821 }
822 /*---------------------------------------------------------------------------*/
823 int
824 mrf24j40_cca(void)
825 {
826  uint8_t ret;
827 
828  uint8_t receive_was_on = receive_on;
829 
830  mrf24j40_on();
831 
832  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
833 
834  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
835 
836  ret = mrf24j40_get_rssi() <= 95; /* -69dbm */
837 
838  if(!receive_was_on) {
839  mrf24j40_off();
840  } else {
841  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
842  }
843 
844  return ret;
845 }
846 /*---------------------------------------------------------------------------*/
847 int
848 mrf24j40_receiving_packet(void)
849 {
850  return 0;
851 }
852 /*---------------------------------------------------------------------------*/
853 int
854 mrf24j40_pending_packet(void)
855 {
856  return pending;
857 }
858 /*---------------------------------------------------------------------------*/
859 MRF24J40_ISR()
860 {
861  INT_status int_status;
862  TX_status tx_status;
863 
864  ENERGEST_ON(ENERGEST_TYPE_IRQ);
865 
866  int_status.val = get_short_add_mem(MRF24J40_INTSTAT);
867 
868  if(!int_status.val) {
869  return;
870  }
871 
872  if(int_status.bits.RXIF) {
873 
874  pending = 1;
875 
876  process_poll(&mrf24j40_process);
877 
878  }
879 
880  if(int_status.bits.TXNIF) {
881 
882  tx_status.val = get_short_add_mem(MRF24J40_TXSTAT);
883 
884  if(tx_status.bits.TXNSTAT) {
885  if(tx_status.bits.CCAFAIL) {
886  status_tx = MRF24J40_TX_ERR_COLLISION;
887  } else {
888  status_tx = MRF24J40_TX_ERR_MAXRETRY;
889  }
890  } else {
891  status_tx = MRF24J40_TX_ERR_NONE;
892  }
893  }
894 
895  MRF24J40_INTERRUPT_FLAG_CLR();
896 
897  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
898 }
899 /*---------------------------------------------------------------------------*/
900 PROCESS_THREAD(mrf24j40_process, ev, data)
901 {
902  PROCESS_BEGIN();
903 
904  uint8_t ret;
905 
906  while(1) {
907  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
908 
909  if(!pending) {
910  continue;
911  }
912 
913  packetbuf_clear();
914 
915  ret = mrf24j40_read(packetbuf_dataptr(), PACKETBUF_SIZE);
916 
918 
919 #ifdef ADD_RSSI_AND_LQI_TO_PACKET
920  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, mrf24j40_last_rssi);
921  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, mrf24j40_last_lqi);
922 #endif
923 
924  NETSTACK_RDC.input();
925  }
926 
927  PROCESS_END();
928 }
929 
930 /*---------------------------------------------------------------------------*/
931 static radio_result_t
932 get_value(radio_param_t param, radio_value_t *value)
933 {
934  return RADIO_RESULT_NOT_SUPPORTED;
935 }
936 /*---------------------------------------------------------------------------*/
937 static radio_result_t
938 set_value(radio_param_t param, radio_value_t value)
939 {
940  return RADIO_RESULT_NOT_SUPPORTED;
941 }
942 /*---------------------------------------------------------------------------*/
943 static radio_result_t
944 get_object(radio_param_t param, void *dest, size_t size)
945 {
946  return RADIO_RESULT_NOT_SUPPORTED;
947 }
948 /*---------------------------------------------------------------------------*/
949 static radio_result_t
950 set_object(radio_param_t param, const void *src, size_t size)
951 {
952  return RADIO_RESULT_NOT_SUPPORTED;
953 }
954 
955 /*---------------------------------------------------------------------------*/
956 const struct radio_driver mrf24j40_driver = {
958  mrf24j40_prepare,
959  mrf24j40_transmit,
960  mrf24j40_write,
961  mrf24j40_read,
962  mrf24j40_cca,
963  mrf24j40_receiving_packet,
964  mrf24j40_pending_packet,
965  mrf24j40_on,
966  mrf24j40_off,
967  get_value,
968  set_value,
969  get_object,
970  set_object
971 };
972 /*---------------------------------------------------------------------------*/
973 
974 /** @} */
void mrf24j40_set_short_mac_addr(uint16_t addr)
Store short MAC address.
Definition: mrf24j40.c:228
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
uint8_t mrf24j40_get_rssi(void)
Get the RSSI.
Definition: mrf24j40.c:313
SPI interface for PIC32MX (pic32mx795f512l)
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
void mrf24j40_set_tx_power(uint8_t pwr)
Set TX power.
Definition: mrf24j40.c:288
INTERRUPT interface for PIC32MX (pic32mx795f512l)
Header file for the Rime buffer (packetbuf) management
void mrf24j40_set_channel(uint16_t ch)
Set the channel.
Definition: mrf24j40.c:203
MRF24J40 Driver.
#define NULL
The null pointer.
The structure of a device driver for a radio in Contiki.
Definition: radio.h:225
int mrf24j40_init(void)
Init transceiver.
Definition: mrf24j40.c:524
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:200
uint8_t mrf24j40_get_last_rssi(void)
Get the last read RSSI.
Definition: mrf24j40.c:356
uint8_t mrf24j40_get_last_lqi(void)
Get the last read LQI.
Definition: mrf24j40.c:367
void mrf24j40_set_panid(uint16_t id)
Store MAC PAN ID.
Definition: mrf24j40.c:216
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
void mrf24j40_get_extended_mac_addr(uint64_t *addr)
Gets extended MAC address.
Definition: mrf24j40.c:270
void mrf24j40_set_extended_mac_addr(uint64_t addr)
Store extended MAC address.
Definition: mrf24j40.c:240
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:258
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:268
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void mrf24j40_get_short_mac_addr(uint16_t *addr)
Get short MAC address.
Definition: mrf24j40.c:258
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
int32_t mrf24j40_get_rxfifo(uint8_t *buf, uint8_t buf_len)
Get message.
Definition: mrf24j40.c:404
int32_t mrf24j40_set_txfifo(const uint8_t *buf, uint8_t buf_len)
Store message.
Definition: mrf24j40.c:379
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:65
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:274
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:261
MRF24J40 Specific Arch Conf.
uint8_t mrf24j40_get_status(void)
Get radio status.
Definition: mrf24j40.c:299
Include file for the Contiki low-layer network stack (NETSTACK)