Contiki 2.5
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 /* contiki */
41 #include "radio.h"
42 #include "sys/process.h"
43 #include "net/packetbuf.h"
44 #include "net/netstack.h"
45 
46 #include "mc1322x.h"
47 #include "contiki-conf.h"
48 
49 #define CONTIKI_MACA_DEBUG 0
50 #if CONTIKI_MACA_DEBUG
51 #define PRINTF(...) printf(__VA_ARGS__)
52 #else
53 #define PRINTF(...)
54 #endif
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 static volatile uint8_t tx_complete;
65 static volatile uint8_t tx_status;
66 
67 /* contiki mac driver */
68 
69 int contiki_maca_init(void);
70 int contiki_maca_on_request(void);
71 int contiki_maca_off_request(void);
72 int contiki_maca_read(void *buf, unsigned short bufsize);
73 int contiki_maca_prepare(const void *payload, unsigned short payload_len);
74 int contiki_maca_transmit(unsigned short transmit_len);
75 int contiki_maca_send(const void *payload, unsigned short payload_len);
76 int contiki_maca_channel_clear(void);
77 int contiki_maca_receiving_packet(void);
78 int contiki_maca_pending_packet(void);
79 
80 const struct radio_driver contiki_maca_driver =
81 {
82  .init = contiki_maca_init,
83  .prepare = contiki_maca_prepare,
84  .transmit = contiki_maca_transmit,
85  .send = contiki_maca_send,
86  .read = contiki_maca_read,
87  .receiving_packet = contiki_maca_receiving_packet,
88  .pending_packet = contiki_maca_pending_packet,
89  .channel_clear = contiki_maca_channel_clear,
90  .on = contiki_maca_on_request,
91  .off = contiki_maca_off_request,
92 };
93 
94 static volatile uint8_t contiki_maca_request_on = 0;
95 static volatile uint8_t contiki_maca_request_off = 0;
96 
97 static process_event_t event_data_ready;
98 
99 static volatile packet_t prepped_p;
100 
101 int contiki_maca_init(void) {
102 // trim_xtal();
103 // vreg_init();
104 // contiki_maca_init();
105 // set_channel(0); /* channel 11 */
106 // set_power(0x12); /* 0x12 is the highest, not documented */
107  return 1;
108 }
109 
110 /* CCA not implemented */
111 int contiki_maca_channel_clear(void) {
112  return 1;
113 }
114 
115 /* not sure how to check if a reception is in progress */
116 int contiki_maca_receiving_packet(void) {
117  return 0;
118 }
119 
120 int contiki_maca_pending_packet(void) {
121  if (rx_head != NULL) {
122  return 1;
123  } else {
124  return 0;
125  }
126 }
127 
128 int contiki_maca_on_request(void) {
129  contiki_maca_request_on = 1;
130  contiki_maca_request_off = 0;
131  return 1;
132 }
133 
134 int contiki_maca_off_request(void) {
135  contiki_maca_request_on = 0;
136  contiki_maca_request_off = 1;
137  return 1;
138 }
139 
140 /* it appears that the mc1332x radio cannot */
141 /* receive packets where the last three bits of the first byte */
142 /* is equal to 2 --- even in promiscuous mode */
143 int contiki_maca_read(void *buf, unsigned short bufsize) {
144  volatile uint32_t i;
145  volatile packet_t *p;
146 
147  if((p = rx_packet())) {
148  PRINTF("maca read");
149 #if CONTIKI_MACA_RAW_MODE
150  /* offset + 1 and size - 1 to strip the raw mode prepended byte */
151  /* work around since maca can't receive acks bigger than five bytes */
152  PRINTF(" raw mode");
153  p->length -= 1;
154  p->offset += 1;
155 #endif
156  PRINTF(": p->length 0x%0x bufsize 0x%0x \n\r", p->length, bufsize);
157  if((p->length) < bufsize) bufsize = (p->length);
158  memcpy(buf, (uint8_t *)(p->data + p->offset), bufsize);
159  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY,p->lqi);
160  packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP,p->rx_time);
161 #if CONTIKI_MACA_DEBUG
162  for( i = p->offset ; i < (bufsize + p->offset) ; i++) {
163  PRINTF(" %02x",p->data[i]);
164  }
165 #endif
166  PRINTF("\n\r");
167  free_packet(p);
168  return bufsize;
169  } else {
170  return 0;
171  }
172 }
173 
174 /* copies a payload into the prepped packet */
175 /* transmit sends the prepped packet everytime it is called */
176 /* Contiki may call prepare once and then transmit several times to send */
177 /* the same packet repeatedly */
178 int contiki_maca_prepare(const void *payload, unsigned short payload_len) {
179  volatile int i;
180 
181  PRINTF("contiki maca prepare");
182 #if CONTIKI_MACA_RAW_MODE
183  prepped_p.offset = 1;
184  prepped_p.length = payload_len + 1;
185 #else
186  prepped_p.offset = 0;
187  prepped_p.length = payload_len;
188 #endif
189  if(payload_len > MAX_PACKET_SIZE) return RADIO_TX_ERR;
190  memcpy((uint8_t *)(prepped_p.data + prepped_p.offset), payload, payload_len);
191 #if CONTIKI_MACA_RAW_MODE
192  prepped_p.offset = 0;
193  prepped_p.data[0] = CONTIKI_MACA_PREPEND_BYTE;
194  PRINTF(" raw mode");
195 #endif
196 #if CONTIKI_MACA_DEBUG
197  PRINTF(": sending %d bytes\n\r", payload_len);
198  for(i = prepped_p.offset ; i < (prepped_p.length + prepped_p.offset); i++) {
199  PRINTF(" %02x",prepped_p.data[i]);
200  }
201  PRINTF("\n\r");
202 #endif
203 
204  return RADIO_TX_OK;
205 
206 }
207 
208 /* gets a packet from the radio (if available), */
209 /* copies the prepared packet prepped_p */
210 /* and transmits it */
211 int contiki_maca_transmit(unsigned short transmit_len) {
212  volatile packet_t *p;
213 
214  PRINTF("contiki maca transmit\n\r");
215 #if BLOCKING_TX
216  tx_complete = 0;
217 #endif
218  if(p = get_free_packet()) {
219  p->offset = prepped_p.offset;
220  p->length = prepped_p.length;
221  memcpy((uint8_t *)(p->data + p->offset),
222  (const uint8_t *)(prepped_p.data + prepped_p.offset),
223  prepped_p.length);
224  tx_packet(p);
225  } else {
226  PRINTF("couldn't get free packet for transmit\n\r");
227  return RADIO_TX_ERR;
228  }
229 
230 #if BLOCKING_TX
231  /* block until tx_complete, set by contiki_maca_tx_callback */
232  while(!tx_complete && (tx_head != 0));
233 #endif
234 }
235 
236 int contiki_maca_send(const void *payload, unsigned short payload_len) {
237  contiki_maca_prepare(payload, payload_len);
238  contiki_maca_transmit(payload_len);
239  switch(tx_status) {
240  case SUCCESS:
241  case CRC_FAILED: /* CRC_FAILED is usually an ack */
242  PRINTF("TXOK\n\r");
243  return RADIO_TX_OK;
244  case NO_ACK:
245  PRINTF("NOACK\n\r");
246  return RADIO_TX_NOACK;
247  default:
248  PRINTF("TXERR\n\r");
249  return RADIO_TX_ERR;
250  }
251 }
252 
253 PROCESS(contiki_maca_process, "maca process");
254 PROCESS_THREAD(contiki_maca_process, ev, data)
255 {
256  volatile uint32_t i;
257  int len;
258 
259  PROCESS_BEGIN();
260 
261  while (1) {
262  PROCESS_YIELD();
263 
264  /* check if there is a request to turn the radio on or off */
265  if(contiki_maca_request_on == 1) {
266  contiki_maca_request_on = 0;
267 // maca_on();
268  }
269 
270  if(contiki_maca_request_off == 1) {
271  contiki_maca_request_off = 0;
272 // maca_off();
273  }
274 
275  if (rx_head != NULL) {
276  packetbuf_clear();
277  len = contiki_maca_read(packetbuf_dataptr(), PACKETBUF_SIZE);
278  if(len > 0) {
279  packetbuf_set_datalen(len);
280  NETSTACK_RDC.input();
281  }
282  }
283  /* Call ourself again to handle remaining packets in the queue */
284  if (rx_head != NULL) {
285  process_poll(&contiki_maca_process);
286  }
287 
288  };
289 
290  PROCESS_END();
291 }
292 
293 void maca_rx_callback(volatile packet_t *p __attribute((unused))) {
294  process_poll(&contiki_maca_process);
295 }
296 
297 
298 #if BLOCKING_TX
299 void maca_tx_callback(volatile packet_t *p __attribute((unused))) {
300  tx_complete = 1;
301  tx_status = p->status;
302 }
303 #endif