Contiki-Inga 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  int idx = 0;
210  for(idx = 0; idx < payload_len; idx++) {
211  if (idx % 8 == 0) {
212  printf("\n");
213  }
214  printf("%02x ", simOutDataBuffer[idx] & 0xFF);
215  }
216  printf("\n");
217 
218  /* Transmit */
219  while(simOutSize > 0) {
220  cooja_mt_yield();
221  }
222 
223  simRadioHWOn = radiostate;
224  return RADIO_TX_OK;
225 }
226 /*---------------------------------------------------------------------------*/
227 static int
228 prepare_packet(const void *data, unsigned short len)
229 {
230  pending_data = data;
231  return 0;
232 }
233 /*---------------------------------------------------------------------------*/
234 static int
235 transmit_packet(unsigned short len)
236 {
237  int ret = RADIO_TX_ERR;
238  if(pending_data != NULL) {
239  ret = radio_send(pending_data, len);
240  }
241  return ret;
242 }
243 /*---------------------------------------------------------------------------*/
244 static int
245 receiving_packet(void)
246 {
247  return simReceiving;
248 }
249 /*---------------------------------------------------------------------------*/
250 static int
251 pending_packet(void)
252 {
253  return !simReceiving && simInSize > 0;
254 }
255 /*---------------------------------------------------------------------------*/
256 PROCESS_THREAD(cooja_radio_process, ev, data)
257 {
258  int len;
259 
260  PROCESS_BEGIN();
261 
262  while(1) {
263  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
264 
265  packetbuf_clear();
266  len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
267  if(len > 0) {
269  NETSTACK_RDC.input();
270  }
271  }
272 
273  PROCESS_END();
274 }
275 /*---------------------------------------------------------------------------*/
276 static int
277 init(void)
278 {
279  process_start(&cooja_radio_process, NULL);
280  return 1;
281 }
282 /*---------------------------------------------------------------------------*/
283 const struct radio_driver cooja_radio_driver =
284 {
285  init,
286  prepare_packet,
287  transmit_packet,
288  radio_send,
289  radio_read,
293  radio_on,
294  radio_off,
295 };
296 /*---------------------------------------------------------------------------*/
297 SIM_INTERFACE(radio_interface,
298  doInterfaceActionsBeforeTick,
299  doInterfaceActionsAfterTick);