Contiki 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 /*---------------------------------------------------------------------------*/
83 static radio_result_t
84 get_value(radio_param_t param, radio_value_t *value)
85 {
86  return RADIO_RESULT_NOT_SUPPORTED;
87 }
88 /*---------------------------------------------------------------------------*/
89 static radio_result_t
90 set_value(radio_param_t param, radio_value_t value)
91 {
92  return RADIO_RESULT_NOT_SUPPORTED;
93 }
94 /*---------------------------------------------------------------------------*/
95 static radio_result_t
96 get_object(radio_param_t param, void *dest, size_t size)
97 {
98  return RADIO_RESULT_NOT_SUPPORTED;
99 }
100 /*---------------------------------------------------------------------------*/
101 static radio_result_t
102 set_object(radio_param_t param, const void *src, size_t size)
103 {
104  return RADIO_RESULT_NOT_SUPPORTED;
105 }
106 /*---------------------------------------------------------------------------*/
107 const struct radio_driver contiki_maca_driver =
108 {
109  .init = contiki_maca_init,
110  .prepare = contiki_maca_prepare,
111  .transmit = contiki_maca_transmit,
112  .send = contiki_maca_send,
113  .read = contiki_maca_read,
114  .receiving_packet = contiki_maca_receiving_packet,
115  .pending_packet = contiki_maca_pending_packet,
116  .channel_clear = contiki_maca_channel_clear,
117  .on = contiki_maca_on_request,
118  .off = contiki_maca_off_request,
119  .get_value = get_value,
120  .set_value = set_value,
121  .get_object = get_object,
122  .set_object = set_object
123 };
124 
125 static volatile uint8_t contiki_maca_request_on = 0;
126 static volatile uint8_t contiki_maca_request_off = 0;
127 
128 static process_event_t event_data_ready;
129 
130 static volatile packet_t prepped_p;
131 
132 void contiki_maca_set_mac_address(uint64_t eui) {
133  linkaddr_t addr;
134  uint8_t i;
135 
136  /* setup mac address registers in maca hardware */
137  *MACA_MACPANID = 0xcdab; /* this is the hardcoded contiki pan, register is PACKET order */
138  *MACA_MAC16ADDR = 0xffff; /* short addressing isn't used, set this to 0xffff for now */
139 
140  *MACA_MAC64HI = (uint32_t) (eui >> 32);
141  *MACA_MAC64LO = (uint32_t) eui;
142 
143  ANNOTATE("setting panid 0x%04x\n\r", *MACA_MACPANID);
144  ANNOTATE("setting short mac 0x%04x\n\r", *MACA_MAC16ADDR);
145  ANNOTATE("setting long mac 0x%08x_%08x\n\r", *MACA_MAC64HI, *MACA_MAC64LO);
146 
147  /* setup mac addresses in Contiki (RIME) */
148  linkaddr_copy(&addr, &linkaddr_null);
149 
150  for(i=0; i < LINKADDR_CONF_SIZE; i++) {
151  addr.u8[LINKADDR_CONF_SIZE - 1 - i] = (mc1322x_config.eui >> (i * 8)) & 0xff;
152  }
153 
154  node_id = (addr.u8[6] << 8 | addr.u8[7]);
155  linkaddr_set_node_addr(&addr);
156 
157 #if DEBUG_ANNOTATE
158  ANNOTATE("Rime configured with address ");
159  for(i = 0; i < sizeof(addr.u8) - 1; i++) {
160  ANNOTATE("%02X:", addr.u8[i]);
161  }
162  ANNOTATE("%02X\n", addr.u8[i]);
163 #endif
164 }
165 
166 int contiki_maca_init(void) {
167 // trim_xtal();
168 // vreg_init();
169 // contiki_maca_init();
170 // set_channel(0); /* channel 11 */
171 // set_power(0x12); /* 0x12 is the highest, not documented */
172  return 1;
173 }
174 
175 /* CCA not implemented */
176 int contiki_maca_channel_clear(void) {
177  return 1;
178 }
179 
180 /* not sure how to check if a reception is in progress */
181 int contiki_maca_receiving_packet(void) {
182  return 0;
183 }
184 
185 int contiki_maca_pending_packet(void) {
186  if (rx_head != NULL) {
187  return 1;
188  } else {
189  return 0;
190  }
191 }
192 
193 int contiki_maca_on_request(void) {
194  contiki_maca_request_on = 1;
195  contiki_maca_request_off = 0;
196  return 1;
197 }
198 
199 int contiki_maca_off_request(void) {
200  contiki_maca_request_on = 0;
201  contiki_maca_request_off = 1;
202  return 1;
203 }
204 
205 /* it appears that the mc1332x radio cannot */
206 /* receive packets where the last three bits of the first byte */
207 /* is equal to 2 --- even in promiscuous mode */
208 int contiki_maca_read(void *buf, unsigned short bufsize) {
209  volatile uint32_t i;
210  volatile packet_t *p;
211 
212  if((p = rx_packet())) {
213  PRINTF("maca read");
214 #if CONTIKI_MACA_RAW_MODE
215  /* offset + 1 and size - 1 to strip the raw mode prepended byte */
216  /* work around since maca can't receive acks bigger than five bytes */
217  PRINTF(" raw mode");
218  p->length -= 1;
219  p->offset += 1;
220 #endif
221  PRINTF(": p->length 0x%0x bufsize 0x%0x \n\r", p->length, bufsize);
222  if((p->length) < bufsize) bufsize = (p->length);
223  memcpy(buf, (uint8_t *)(p->data + p->offset), bufsize);
224  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY,p->lqi);
225  packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP,p->rx_time);
226 #if CONTIKI_MACA_DEBUG
227  for( i = p->offset ; i < (bufsize + p->offset) ; i++) {
228  PRINTF(" %02x",p->data[i]);
229  }
230 #endif
231  PRINTF("\n\r");
232  maca_free_packet(p);
233  return bufsize;
234  } else {
235  return 0;
236  }
237 }
238 
239 /* copies a payload into the prepped packet */
240 /* transmit sends the prepped packet everytime it is called */
241 /* Contiki may call prepare once and then transmit several times to send */
242 /* the same packet repeatedly */
243 int contiki_maca_prepare(const void *payload, unsigned short payload_len) {
244  volatile int i;
245 
246  PRINTF("contiki maca prepare");
247 #if CONTIKI_MACA_RAW_MODE
248  prepped_p.offset = 1;
249  prepped_p.length = payload_len + 1;
250 #else
251  prepped_p.offset = 0;
252  prepped_p.length = payload_len;
253 #endif
254  if(payload_len > MAX_PACKET_SIZE) return RADIO_TX_ERR;
255  memcpy((uint8_t *)(prepped_p.data + prepped_p.offset), payload, payload_len);
256 #if CONTIKI_MACA_RAW_MODE
257  prepped_p.offset = 0;
258  prepped_p.data[0] = CONTIKI_MACA_PREPEND_BYTE;
259  PRINTF(" raw mode");
260 #endif
261 #if CONTIKI_MACA_DEBUG
262  PRINTF(": sending %d bytes\n\r", payload_len);
263  for(i = prepped_p.offset ; i < (prepped_p.length + prepped_p.offset); i++) {
264  PRINTF(" %02x",prepped_p.data[i]);
265  }
266  PRINTF("\n\r");
267 #endif
268 
269  return RADIO_TX_OK;
270 
271 }
272 
273 /* gets a packet from the radio (if available), */
274 /* copies the prepared packet prepped_p */
275 /* and transmits it */
276 int contiki_maca_transmit(unsigned short transmit_len) {
277  volatile packet_t *p;
278 
279  PRINTF("contiki maca transmit\n\r");
280 #if BLOCKING_TX
281  tx_complete = 0;
282 #endif
283  if(p = get_free_packet()) {
284  p->offset = prepped_p.offset;
285  p->length = prepped_p.length;
286  memcpy((uint8_t *)(p->data + p->offset),
287  (const uint8_t *)(prepped_p.data + prepped_p.offset),
288  prepped_p.length);
289  tx_packet(p);
290  } else {
291  PRINTF("couldn't get free packet for transmit\n\r");
292  return RADIO_TX_ERR;
293  }
294 
295 #if BLOCKING_TX
296  /* block until tx_complete, set by contiki_maca_tx_callback */
297  while((maca_pwr == 1) && !tx_complete && (tx_head != 0)) { continue; }
298 #endif
299 }
300 
301 int contiki_maca_send(const void *payload, unsigned short payload_len) {
302  contiki_maca_prepare(payload, payload_len);
303  contiki_maca_transmit(payload_len);
304  switch(tx_status) {
305  case SUCCESS:
306  case CRC_FAILED: /* CRC_FAILED is usually an ack */
307  PRINTF("TXOK\n\r");
308  return RADIO_TX_OK;
309  case NO_ACK:
310  PRINTF("NOACK\n\r");
311  return RADIO_TX_NOACK;
312  default:
313  PRINTF("TXERR\n\r");
314  return RADIO_TX_ERR;
315  }
316 }
317 
318 PROCESS(contiki_maca_process, "maca process");
319 PROCESS_THREAD(contiki_maca_process, ev, data)
320 {
321  volatile uint32_t i;
322  int len;
323 
324  PROCESS_BEGIN();
325 
326  while (1) {
327  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
328 
329  /* check if there is a request to turn the radio on or off */
330  if(contiki_maca_request_on == 1) {
331  contiki_maca_request_on = 0;
332 // maca_on();
333  }
334 
335  if(contiki_maca_request_off == 1) {
336  contiki_maca_request_off = 0;
337 // maca_off();
338  }
339 
340  if (rx_head != NULL) {
341  packetbuf_clear();
342  len = contiki_maca_read(packetbuf_dataptr(), PACKETBUF_SIZE);
343  if(len > 0) {
345  NETSTACK_RDC.input();
346  }
347  }
348  /* Call ourself again to handle remaining packets in the queue */
349  if (rx_head != NULL) {
350  process_poll(&contiki_maca_process);
351  }
352 
353  };
354 
355  PROCESS_END();
356 }
357 
358 void maca_rx_callback(volatile packet_t *p __attribute((unused))) {
359  process_poll(&contiki_maca_process);
360 }
361 
362 
363 #if BLOCKING_TX
364 void maca_tx_callback(volatile packet_t *p __attribute((unused))) {
365  tx_complete = 1;
366  tx_status = p->status;
367 }
368 #endif
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
const linkaddr_t linkaddr_null
The null Rime address.
Header file for the Rime buffer (packetbuf) management
#define NULL
The null pointer.
The structure of a device driver for a radio in Contiki.
Definition: radio.h:225
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
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
Definition: linkaddr.c:60
#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
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 packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:65
void linkaddr_set_node_addr(linkaddr_t *t)
Set the address of the current node.
Definition: linkaddr.c:72
A set of debugging macros.
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
Header file for the Contiki process interface.
#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
Include file for the Contiki low-layer network stack (NETSTACK)