Contiki-Inga 3.x
contiki-maca.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org) and Contiki.
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the Institute nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * This file is part of the Contiki OS.
32  *
33  *
34  */
35 
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <string.h>
39 
40 /* debug */
41 #define DEBUG DEBUG_ANNOTATE
42 #include "net/ip/uip-debug.h"
43 
44 /* contiki */
45 #include "radio.h"
46 #include "sys/process.h"
47 #include "net/packetbuf.h"
48 #include "net/netstack.h"
49 
50 #include "contiki-conf.h"
51 
52 /* mc1322x */
53 #include "mc1322x.h"
54 #include "config.h"
55 
56 #ifndef CONTIKI_MACA_PREPEND_BYTE
57 #define CONTIKI_MACA_PREPEND_BYTE 0xff
58 #endif
59 
60 #ifndef BLOCKING_TX
61 #define BLOCKING_TX 1
62 #endif
63 
64 unsigned short node_id = 0;
65 
66 static volatile uint8_t tx_complete;
67 static volatile uint8_t tx_status;
68 
69 /* contiki mac driver */
70 
71 int contiki_maca_init(void);
72 int contiki_maca_on_request(void);
73 int contiki_maca_off_request(void);
74 int contiki_maca_read(void *buf, unsigned short bufsize);
75 int contiki_maca_prepare(const void *payload, unsigned short payload_len);
76 int contiki_maca_transmit(unsigned short transmit_len);
77 int contiki_maca_send(const void *payload, unsigned short payload_len);
78 int contiki_maca_channel_clear(void);
79 int contiki_maca_receiving_packet(void);
80 int contiki_maca_pending_packet(void);
81 
82 const struct radio_driver contiki_maca_driver =
83 {
84  .init = contiki_maca_init,
85  .prepare = contiki_maca_prepare,
86  .transmit = contiki_maca_transmit,
87  .send = contiki_maca_send,
88  .read = contiki_maca_read,
89  .receiving_packet = contiki_maca_receiving_packet,
90  .pending_packet = contiki_maca_pending_packet,
91  .channel_clear = contiki_maca_channel_clear,
92  .on = contiki_maca_on_request,
93  .off = contiki_maca_off_request,
94 };
95 
96 static volatile uint8_t contiki_maca_request_on = 0;
97 static volatile uint8_t contiki_maca_request_off = 0;
98 
99 static process_event_t event_data_ready;
100 
101 static volatile packet_t prepped_p;
102 
103 void contiki_maca_set_mac_address(uint64_t eui) {
104  linkaddr_t addr;
105  uint8_t i;
106 
107  /* setup mac address registers in maca hardware */
108  *MACA_MACPANID = 0xcdab; /* this is the hardcoded contiki pan, register is PACKET order */
109  *MACA_MAC16ADDR = 0xffff; /* short addressing isn't used, set this to 0xffff for now */
110 
111  *MACA_MAC64HI = (uint32_t) (eui >> 32);
112  *MACA_MAC64LO = (uint32_t) eui;
113 
114  ANNOTATE("setting panid 0x%04x\n\r", *MACA_MACPANID);
115  ANNOTATE("setting short mac 0x%04x\n\r", *MACA_MAC16ADDR);
116  ANNOTATE("setting long mac 0x%08x_%08x\n\r", *MACA_MAC64HI, *MACA_MAC64LO);
117 
118  /* setup mac addresses in Contiki (RIME) */
119  linkaddr_copy(&addr, &linkaddr_null);
120 
121  for(i=0; i < LINKADDR_CONF_SIZE; i++) {
122  addr.u8[LINKADDR_CONF_SIZE - 1 - i] = (mc1322x_config.eui >> (i * 8)) & 0xff;
123  }
124 
125  node_id = (addr.u8[6] << 8 | addr.u8[7]);
126  linkaddr_set_node_addr(&addr);
127 
128 #if DEBUG_ANNOTATE
129  ANNOTATE("Rime configured with address ");
130  for(i = 0; i < sizeof(addr.u8) - 1; i++) {
131  ANNOTATE("%02X:", addr.u8[i]);
132  }
133  ANNOTATE("%02X\n", addr.u8[i]);
134 #endif
135 }
136 
137 int contiki_maca_init(void) {
138 // trim_xtal();
139 // vreg_init();
140 // contiki_maca_init();
141 // set_channel(0); /* channel 11 */
142 // set_power(0x12); /* 0x12 is the highest, not documented */
143  return 1;
144 }
145 
146 /* CCA not implemented */
147 int contiki_maca_channel_clear(void) {
148  return 1;
149 }
150 
151 /* not sure how to check if a reception is in progress */
152 int contiki_maca_receiving_packet(void) {
153  return 0;
154 }
155 
156 int contiki_maca_pending_packet(void) {
157  if (rx_head != NULL) {
158  return 1;
159  } else {
160  return 0;
161  }
162 }
163 
164 int contiki_maca_on_request(void) {
165  contiki_maca_request_on = 1;
166  contiki_maca_request_off = 0;
167  return 1;
168 }
169 
170 int contiki_maca_off_request(void) {
171  contiki_maca_request_on = 0;
172  contiki_maca_request_off = 1;
173  return 1;
174 }
175 
176 /* it appears that the mc1332x radio cannot */
177 /* receive packets where the last three bits of the first byte */
178 /* is equal to 2 --- even in promiscuous mode */
179 int contiki_maca_read(void *buf, unsigned short bufsize) {
180  volatile uint32_t i;
181  volatile packet_t *p;
182 
183  if((p = rx_packet())) {
184  PRINTF("maca read");
185 #if CONTIKI_MACA_RAW_MODE
186  /* offset + 1 and size - 1 to strip the raw mode prepended byte */
187  /* work around since maca can't receive acks bigger than five bytes */
188  PRINTF(" raw mode");
189  p->length -= 1;
190  p->offset += 1;
191 #endif
192  PRINTF(": p->length 0x%0x bufsize 0x%0x \n\r", p->length, bufsize);
193  if((p->length) < bufsize) bufsize = (p->length);
194  memcpy(buf, (uint8_t *)(p->data + p->offset), bufsize);
195  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY,p->lqi);
196  packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP,p->rx_time);
197 #if CONTIKI_MACA_DEBUG
198  for( i = p->offset ; i < (bufsize + p->offset) ; i++) {
199  PRINTF(" %02x",p->data[i]);
200  }
201 #endif
202  PRINTF("\n\r");
203  free_packet(p);
204  return bufsize;
205  } else {
206  return 0;
207  }
208 }
209 
210 /* copies a payload into the prepped packet */
211 /* transmit sends the prepped packet everytime it is called */
212 /* Contiki may call prepare once and then transmit several times to send */
213 /* the same packet repeatedly */
214 int contiki_maca_prepare(const void *payload, unsigned short payload_len) {
215  volatile int i;
216 
217  PRINTF("contiki maca prepare");
218 #if CONTIKI_MACA_RAW_MODE
219  prepped_p.offset = 1;
220  prepped_p.length = payload_len + 1;
221 #else
222  prepped_p.offset = 0;
223  prepped_p.length = payload_len;
224 #endif
225  if(payload_len > MAX_PACKET_SIZE) return RADIO_TX_ERR;
226  memcpy((uint8_t *)(prepped_p.data + prepped_p.offset), payload, payload_len);
227 #if CONTIKI_MACA_RAW_MODE
228  prepped_p.offset = 0;
229  prepped_p.data[0] = CONTIKI_MACA_PREPEND_BYTE;
230  PRINTF(" raw mode");
231 #endif
232 #if CONTIKI_MACA_DEBUG
233  PRINTF(": sending %d bytes\n\r", payload_len);
234  for(i = prepped_p.offset ; i < (prepped_p.length + prepped_p.offset); i++) {
235  PRINTF(" %02x",prepped_p.data[i]);
236  }
237  PRINTF("\n\r");
238 #endif
239 
240  return RADIO_TX_OK;
241 
242 }
243 
244 /* gets a packet from the radio (if available), */
245 /* copies the prepared packet prepped_p */
246 /* and transmits it */
247 int contiki_maca_transmit(unsigned short transmit_len) {
248  volatile packet_t *p;
249 
250  PRINTF("contiki maca transmit\n\r");
251 #if BLOCKING_TX
252  tx_complete = 0;
253 #endif
254  if(p = get_free_packet()) {
255  p->offset = prepped_p.offset;
256  p->length = prepped_p.length;
257  memcpy((uint8_t *)(p->data + p->offset),
258  (const uint8_t *)(prepped_p.data + prepped_p.offset),
259  prepped_p.length);
260  tx_packet(p);
261  } else {
262  PRINTF("couldn't get free packet for transmit\n\r");
263  return RADIO_TX_ERR;
264  }
265 
266 #if BLOCKING_TX
267  /* block until tx_complete, set by contiki_maca_tx_callback */
268  while((maca_pwr == 1) && !tx_complete && (tx_head != 0)) { continue; }
269 #endif
270 }
271 
272 int contiki_maca_send(const void *payload, unsigned short payload_len) {
273  contiki_maca_prepare(payload, payload_len);
274  contiki_maca_transmit(payload_len);
275  switch(tx_status) {
276  case SUCCESS:
277  case CRC_FAILED: /* CRC_FAILED is usually an ack */
278  PRINTF("TXOK\n\r");
279  return RADIO_TX_OK;
280  case NO_ACK:
281  PRINTF("NOACK\n\r");
282  return RADIO_TX_NOACK;
283  default:
284  PRINTF("TXERR\n\r");
285  return RADIO_TX_ERR;
286  }
287 }
288 
289 PROCESS(contiki_maca_process, "maca process");
290 PROCESS_THREAD(contiki_maca_process, ev, data)
291 {
292  volatile uint32_t i;
293  int len;
294 
295  PROCESS_BEGIN();
296 
297  while (1) {
298  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
299 
300  /* check if there is a request to turn the radio on or off */
301  if(contiki_maca_request_on == 1) {
302  contiki_maca_request_on = 0;
303 // maca_on();
304  }
305 
306  if(contiki_maca_request_off == 1) {
307  contiki_maca_request_off = 0;
308 // maca_off();
309  }
310 
311  if (rx_head != NULL) {
312  packetbuf_clear();
313  len = contiki_maca_read(packetbuf_dataptr(), PACKETBUF_SIZE);
314  if(len > 0) {
316  NETSTACK_RDC.input();
317  }
318  }
319  /* Call ourself again to handle remaining packets in the queue */
320  if (rx_head != NULL) {
321  process_poll(&contiki_maca_process);
322  }
323 
324  };
325 
326  PROCESS_END();
327 }
328 
329 void maca_rx_callback(volatile packet_t *p __attribute((unused))) {
330  process_poll(&contiki_maca_process);
331 }
332 
333 
334 #if BLOCKING_TX
335 void maca_tx_callback(volatile packet_t *p __attribute((unused))) {
336  tx_complete = 1;
337  tx_status = p->status;
338 }
339 #endif