Contiki 3.x
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  */
30 
31 #include <stdio.h>
32 #include <string.h>
33 
34 #include "contiki.h"
35 
36 #include "sys/cooja_mt.h"
37 #include "lib/simEnvChange.h"
38 
39 #include "net/packetbuf.h"
40 #include "net/rime/rimestats.h"
41 #include "net/netstack.h"
42 
43 #include "dev/radio.h"
44 #include "dev/cooja-radio.h"
45 
46 #define COOJA_RADIO_BUFSIZE PACKETBUF_SIZE
47 #define CCA_SS_THRESHOLD -95
48 
49 #define WITH_TURNAROUND 1
50 #define WITH_SEND_CCA 1
51 
52 const struct simInterface radio_interface;
53 
54 /* COOJA */
55 char simReceiving = 0;
56 char simInDataBuffer[COOJA_RADIO_BUFSIZE];
57 int simInSize = 0;
58 char simOutDataBuffer[COOJA_RADIO_BUFSIZE];
59 int simOutSize = 0;
60 char simRadioHWOn = 1;
61 int simSignalStrength = -100;
62 int simLastSignalStrength = -100;
63 char simPower = 100;
64 int simRadioChannel = 26;
65 int simLQI = 105;
66 
67 static const void *pending_data;
68 
69 PROCESS(cooja_radio_process, "cooja radio process");
70 
71 /*---------------------------------------------------------------------------*/
72 void
73 radio_set_channel(int channel)
74 {
75  simRadioChannel = channel;
76 }
77 /*---------------------------------------------------------------------------*/
78 void
79 radio_set_txpower(unsigned char power)
80 {
81  /* 1 - 100: Number indicating output power */
82  simPower = power;
83 }
84 /*---------------------------------------------------------------------------*/
85 int
86 radio_signal_strength_last(void)
87 {
88  return simLastSignalStrength;
89 }
90 /*---------------------------------------------------------------------------*/
91 int
92 radio_signal_strength_current(void)
93 {
94  return simSignalStrength;
95 }
96 /*---------------------------------------------------------------------------*/
97 int
98 radio_LQI(void)
99 {
100  return simLQI;
101 }
102 /*---------------------------------------------------------------------------*/
103 static int
104 radio_on(void)
105 {
106  simRadioHWOn = 1;
107  return 1;
108 }
109 /*---------------------------------------------------------------------------*/
110 static int
111 radio_off(void)
112 {
113  simRadioHWOn = 0;
114  return 1;
115 }
116 /*---------------------------------------------------------------------------*/
117 static void
118 doInterfaceActionsBeforeTick(void)
119 {
120  if(!simRadioHWOn) {
121  simInSize = 0;
122  return;
123  }
124  if(simReceiving) {
125  simLastSignalStrength = simSignalStrength;
126  return;
127  }
128 
129  if(simInSize > 0) {
130  process_poll(&cooja_radio_process);
131  }
132 }
133 /*---------------------------------------------------------------------------*/
134 static void
135 doInterfaceActionsAfterTick(void)
136 {
137 }
138 /*---------------------------------------------------------------------------*/
139 static int
140 radio_read(void *buf, unsigned short bufsize)
141 {
142  int tmp = simInSize;
143 
144  if(simInSize == 0) {
145  return 0;
146  }
147  if(bufsize < simInSize) {
148  simInSize = 0; /* rx flush */
149  RIMESTATS_ADD(toolong);
150  return 0;
151  }
152 
153  memcpy(buf, simInDataBuffer, simInSize);
154  simInSize = 0;
155  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, simSignalStrength);
156  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, simLQI);
157 
158  return tmp;
159 }
160 /*---------------------------------------------------------------------------*/
161 static int
162 channel_clear(void)
163 {
164  if(simSignalStrength > CCA_SS_THRESHOLD) {
165  return 0;
166  }
167  return 1;
168 }
169 /*---------------------------------------------------------------------------*/
170 static int
171 radio_send(const void *payload, unsigned short payload_len)
172 {
173  int radiostate = simRadioHWOn;
174 
175  /* Simulate turnaround time of 2ms for packets, 1ms for acks*/
176 #if WITH_TURNAROUND
177  simProcessRunValue = 1;
178  cooja_mt_yield();
179  if(payload_len > 3) {
180  simProcessRunValue = 1;
181  cooja_mt_yield();
182  }
183 #endif /* WITH_TURNAROUND */
184 
185  if(!simRadioHWOn) {
186  /* Turn on radio temporarily */
187  simRadioHWOn = 1;
188  }
189  if(payload_len > COOJA_RADIO_BUFSIZE) {
190  return RADIO_TX_ERR;
191  }
192  if(payload_len == 0) {
193  return RADIO_TX_ERR;
194  }
195  if(simOutSize > 0) {
196  return RADIO_TX_ERR;
197  }
198 
199  /* Transmit on CCA */
200 #if WITH_SEND_CCA
201  if(!channel_clear()) {
202  return RADIO_TX_COLLISION;
203  }
204 #endif /* WITH_SEND_CCA */
205 
206  /* Copy packet data to temporary storage */
207  memcpy(simOutDataBuffer, payload, payload_len);
208  simOutSize = payload_len;
209 
210  /* Transmit */
211  while(simOutSize > 0) {
212  cooja_mt_yield();
213  }
214 
215  simRadioHWOn = radiostate;
216  return RADIO_TX_OK;
217 }
218 /*---------------------------------------------------------------------------*/
219 static int
220 prepare_packet(const void *data, unsigned short len)
221 {
222  pending_data = data;
223  return 0;
224 }
225 /*---------------------------------------------------------------------------*/
226 static int
227 transmit_packet(unsigned short len)
228 {
229  int ret = RADIO_TX_ERR;
230  if(pending_data != NULL) {
231  ret = radio_send(pending_data, len);
232  }
233  return ret;
234 }
235 /*---------------------------------------------------------------------------*/
236 static int
237 receiving_packet(void)
238 {
239  return simReceiving;
240 }
241 /*---------------------------------------------------------------------------*/
242 static int
243 pending_packet(void)
244 {
245  return !simReceiving && simInSize > 0;
246 }
247 /*---------------------------------------------------------------------------*/
248 PROCESS_THREAD(cooja_radio_process, ev, data)
249 {
250  int len;
251 
252  PROCESS_BEGIN();
253 
254  while(1) {
255  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
256 
257  packetbuf_clear();
258  len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
259  if(len > 0) {
261  NETSTACK_RDC.input();
262  }
263  }
264 
265  PROCESS_END();
266 }
267 /*---------------------------------------------------------------------------*/
268 static int
269 init(void)
270 {
271  process_start(&cooja_radio_process, NULL);
272  return 1;
273 }
274 /*---------------------------------------------------------------------------*/
275 static radio_result_t
276 get_value(radio_param_t param, radio_value_t *value)
277 {
278  return RADIO_RESULT_NOT_SUPPORTED;
279 }
280 /*---------------------------------------------------------------------------*/
281 static radio_result_t
282 set_value(radio_param_t param, radio_value_t value)
283 {
284  return RADIO_RESULT_NOT_SUPPORTED;
285 }
286 /*---------------------------------------------------------------------------*/
287 static radio_result_t
288 get_object(radio_param_t param, void *dest, size_t size)
289 {
290  return RADIO_RESULT_NOT_SUPPORTED;
291 }
292 /*---------------------------------------------------------------------------*/
293 static radio_result_t
294 set_object(radio_param_t param, const void *src, size_t size)
295 {
296  return RADIO_RESULT_NOT_SUPPORTED;
297 }
298 /*---------------------------------------------------------------------------*/
299 const struct radio_driver cooja_radio_driver =
300 {
301  init,
302  prepare_packet,
303  transmit_packet,
304  radio_send,
305  radio_read,
309  radio_on,
310  radio_off,
311  get_value,
312  set_value,
313  get_object,
314  set_object
315 };
316 /*---------------------------------------------------------------------------*/
317 SIM_INTERFACE(radio_interface,
318  doInterfaceActionsBeforeTick,
319  doInterfaceActionsAfterTick);
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
Header file for the radio API
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(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:249
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
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:246
#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
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Definition: radio.h:243
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
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:65
Header file for Rime statistics
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
Include file for the Contiki low-layer network stack (NETSTACK)