Contiki 2.5
cooja-radio.c
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science.
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  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $Id: cooja-radio.c,v 1.15 2010/06/14 19:19:17 adamdunkels Exp $
30  */
31 
32 #include <stdio.h>
33 #include <string.h>
34 
35 #include "contiki.h"
36 
37 #include "sys/cooja_mt.h"
38 #include "lib/simEnvChange.h"
39 
40 #include "net/packetbuf.h"
41 #include "net/rime/rimestats.h"
42 #include "net/netstack.h"
43 
44 #include "dev/radio.h"
45 #include "dev/cooja-radio.h"
46 
47 #define COOJA_RADIO_BUFSIZE PACKETBUF_SIZE
48 
49 #define CCA_SS_THRESHOLD -95
50 
51 const struct simInterface radio_interface;
52 
53 /* COOJA */
54 char simReceiving = 0;
55 char simInDataBuffer[COOJA_RADIO_BUFSIZE];
56 int simInSize = 0;
57 char simOutDataBuffer[COOJA_RADIO_BUFSIZE];
58 int simOutSize = 0;
59 char simRadioHWOn = 1;
60 int simSignalStrength = -100;
61 int simLastSignalStrength = -100;
62 char simPower = 100;
63 int simRadioChannel = 26;
64 
65 static const void *pending_data;
66 
67 PROCESS(cooja_radio_process, "cooja radio process");
68 
69 /*---------------------------------------------------------------------------*/
70 void
71 radio_set_channel(int channel)
72 {
73  simRadioChannel = channel;
74 }
75 /*---------------------------------------------------------------------------*/
76 void
77 radio_set_txpower(unsigned char power)
78 {
79  /* 1 - 100: Number indicating output power */
80  simPower = power;
81 }
82 /*---------------------------------------------------------------------------*/
83 int
84 radio_signal_strength_last(void)
85 {
86  return simLastSignalStrength;
87 }
88 /*---------------------------------------------------------------------------*/
89 int
90 radio_signal_strength_current(void)
91 {
92  return simSignalStrength;
93 }
94 /*---------------------------------------------------------------------------*/
95 static int
96 radio_on(void)
97 {
98  simRadioHWOn = 1;
99  return 1;
100 }
101 /*---------------------------------------------------------------------------*/
102 static int
103 radio_off(void)
104 {
105  simRadioHWOn = 0;
106  return 1;
107 }
108 /*---------------------------------------------------------------------------*/
109 static void
110 doInterfaceActionsBeforeTick(void)
111 {
112  if (!simRadioHWOn) {
113  simInSize = 0;
114  return;
115  }
116  if (simReceiving) {
117  simLastSignalStrength = simSignalStrength;
118  return;
119  }
120 
121  if (simInSize > 0) {
122  process_poll(&cooja_radio_process);
123  }
124 }
125 /*---------------------------------------------------------------------------*/
126 static void
127 doInterfaceActionsAfterTick(void)
128 {
129 }
130 /*---------------------------------------------------------------------------*/
131 static int
132 radio_read(void *buf, unsigned short bufsize)
133 {
134  int tmp = simInSize;
135 
136  if (simInSize == 0) {
137  return 0;
138  }
139  if(bufsize < simInSize) {
140  simInSize = 0; /* rx flush */
141  RIMESTATS_ADD(toolong);
142  return 0;
143  }
144 
145  memcpy(buf, simInDataBuffer, simInSize);
146  simInSize = 0;
147  return tmp;
148 }
149 /*---------------------------------------------------------------------------*/
150 static int
151 radio_send(const void *payload, unsigned short payload_len)
152 {
153  int radiostate = simRadioHWOn;
154 
155  if(!simRadioHWOn) {
156  /* Turn on radio temporarily */
157  simRadioHWOn = 1;
158  }
159  if(payload_len > COOJA_RADIO_BUFSIZE) {
160  return RADIO_TX_ERR;
161  }
162  if(payload_len == 0) {
163  return RADIO_TX_ERR;
164  }
165  if(simOutSize > 0) {
166  return RADIO_TX_ERR;
167  }
168 
169  /* Copy packet data to temporary storage */
170  memcpy(simOutDataBuffer, payload, payload_len);
171  simOutSize = payload_len;
172 
173  /* Transmit */
174  while(simOutSize > 0) {
175  cooja_mt_yield();
176  }
177 
178  simRadioHWOn = radiostate;
179  return RADIO_TX_OK;
180 }
181 /*---------------------------------------------------------------------------*/
182 static int
183 prepare_packet(const void *data, unsigned short len)
184 {
185  pending_data = data;
186  return 0;
187 }
188 /*---------------------------------------------------------------------------*/
189 static int
190 transmit_packet(unsigned short len)
191 {
192  int ret = RADIO_TX_ERR;
193  if(pending_data != NULL) {
194  ret = radio_send(pending_data, len);
195  }
196  return ret;
197 }
198 /*---------------------------------------------------------------------------*/
199 static int
200 receiving_packet(void)
201 {
202  return simReceiving;
203 }
204 /*---------------------------------------------------------------------------*/
205 static int
206 pending_packet(void)
207 {
208  return !simReceiving && simInSize > 0;
209 }
210 /*---------------------------------------------------------------------------*/
211 static int
212 channel_clear(void)
213 {
214  if(simSignalStrength > CCA_SS_THRESHOLD) {
215  return 0;
216  }
217  return 1;
218 }
219 /*---------------------------------------------------------------------------*/
220 PROCESS_THREAD(cooja_radio_process, ev, data)
221 {
222  int len;
223 
224  PROCESS_BEGIN();
225 
226  while(1) {
227  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
228 
229  packetbuf_clear();
230  len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
231  if(len > 0) {
233  NETSTACK_RDC.input();
234  }
235  }
236 
237  PROCESS_END();
238 }
239 /*---------------------------------------------------------------------------*/
240 static int
241 init(void)
242 {
243  process_start(&cooja_radio_process, NULL);
244  return 1;
245 }
246 /*---------------------------------------------------------------------------*/
247 const struct radio_driver cooja_radio_driver =
248 {
249  init,
250  prepare_packet,
251  transmit_packet,
252  radio_send,
253  radio_read,
257  radio_on,
258  radio_off,
259 };
260 /*---------------------------------------------------------------------------*/
261 SIM_INTERFACE(radio_interface,
262  doInterfaceActionsBeforeTick,
263  doInterfaceActionsAfterTick);