Contiki-NG
Loading...
Searching...
No Matches
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/netstack.h"
41#include "sys/energest.h"
42
43#include "dev/radio.h"
44#include "dev/cooja-radio.h"
45
46/*
47 * The maximum number of bytes this driver can accept from the MAC layer for
48 * transmission or will deliver to the MAC layer after reception. Includes
49 * the MAC header and payload, but not the FCS.
50 */
51#ifdef COOJA_RADIO_CONF_BUFSIZE
52#define COOJA_RADIO_BUFSIZE COOJA_RADIO_CONF_BUFSIZE
53#else
54#define COOJA_RADIO_BUFSIZE 125
55#endif
56
57#define MIN_CHANNEL 11
58#define MAX_CHANNEL 26
59#define CCA_SS_THRESHOLD -95
60
61/* The radio driver can provide Cooja these values.
62 * But at present, Cooja ignores and overrides them.
63 * */
64enum {
65 /*
66 * Tmote Sky (with CC2420 radio) gives value -100dB
67 * CC1310 gives about -110dB
68 */
69 RSSI_NO_SIGNAL = -110,
70
71 /*
72 * Tmote Sky (with CC2420 radio) gives value 105
73 * CC1310 gives about 100
74 */
75 LQI_NO_SIGNAL = 100,
76};
77
78/* COOJA */
79char simReceiving = 0;
80char simInDataBuffer[COOJA_RADIO_BUFSIZE];
81int simInSize = 0;
82rtimer_clock_t simLastPacketTimestamp = 0;
83char simOutDataBuffer[COOJA_RADIO_BUFSIZE];
84int simOutSize = 0;
85char simRadioHWOn = 1;
86int simSignalStrength = RSSI_NO_SIGNAL;
87int simLastSignalStrength = RSSI_NO_SIGNAL;
88char simPower = 100;
89int simRadioChannel = MAX_CHANNEL;
90int simLQI = LQI_NO_SIGNAL;
91int simLastLQI = LQI_NO_SIGNAL;
92
93
94
95static const void *pending_data;
96
97/* If we are in the polling mode, poll_mode is 1; otherwise 0 */
98static int poll_mode = 0; /* default 0, disabled */
99static int auto_ack = 0; /* AUTO_ACK is not supported; always 0 */
100static int addr_filter = 0; /* ADDRESS_FILTER is not supported; always 0 */
101static int send_on_cca = (COOJA_TRANSMIT_ON_CCA != 0);
102
103PROCESS(cooja_radio_process, "cooja radio process");
104/*---------------------------------------------------------------------------*/
105static void
106set_send_on_cca(uint8_t enable)
107{
108 send_on_cca = enable;
109}
110/*---------------------------------------------------------------------------*/
111static void
112set_frame_filtering(int enable)
113{
114 addr_filter = enable;
115}
116/*---------------------------------------------------------------------------*/
117static void
118set_auto_ack(int enable)
119{
120 auto_ack = enable;
121}
122/*---------------------------------------------------------------------------*/
123static void
124set_poll_mode(int enable)
125{
126 poll_mode = enable;
127}
128/*---------------------------------------------------------------------------*/
129void
130radio_set_channel(int channel)
131{
132 simRadioChannel = channel;
133}
134/*---------------------------------------------------------------------------*/
135void
136radio_set_txpower(unsigned char power)
137{
138 /* 1 - 100: Number indicating output power */
139 simPower = power;
140}
141/*---------------------------------------------------------------------------*/
142int
143radio_signal_strength_last(void)
144{
145 return simLastSignalStrength;
146}
147/*---------------------------------------------------------------------------*/
148int
149radio_signal_strength_current(void)
150{
151 return simSignalStrength;
152}
153/*---------------------------------------------------------------------------*/
154int
155radio_LQI(void)
156{
157 return simLQI;
158}
159
160static
161int radio_lqi_last(void)
162{
163 return simLastLQI;
164}
165
166/*---------------------------------------------------------------------------*/
167static int
168radio_on(void)
169{
170 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
171 simRadioHWOn = 1;
172 return 1;
173}
174/*---------------------------------------------------------------------------*/
175static int
176radio_off(void)
177{
178 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
179 simRadioHWOn = 0;
180 return 1;
181}
182/*---------------------------------------------------------------------------*/
183static void
184doInterfaceActionsBeforeTick(void)
185{
186 if(!simRadioHWOn) {
187 simInSize = 0;
188 return;
189 }
190 if(simReceiving) {
191 simLastSignalStrength = simSignalStrength;
192 simLastLQI = simLQI;
193 return;
194 }
195
196 if(simInSize > 0) {
197 process_poll(&cooja_radio_process);
198 }
199}
200/*---------------------------------------------------------------------------*/
201static int
202radio_read(void *buf, unsigned short bufsize)
203{
204 int tmp = simInSize;
205
206 if(simInSize == 0) {
207 return 0;
208 }
209 if(bufsize < simInSize) {
210 simInSize = 0; /* rx flush */
211 return 0;
212 }
213
214 memcpy(buf, simInDataBuffer, simInSize);
215 simInSize = 0;
216 if(!poll_mode) {
217 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, radio_signal_strength_last());
218 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, radio_lqi_last() );
219 }
220
221 return tmp;
222}
223/*---------------------------------------------------------------------------*/
224static int
225channel_clear(void)
226{
227 if(simSignalStrength > CCA_SS_THRESHOLD) {
228 return 0;
229 }
230 return 1;
231}
232/*---------------------------------------------------------------------------*/
233static int
234radio_send(const void *payload, unsigned short payload_len)
235{
236 int result;
237 int radio_was_on = simRadioHWOn;
238
239 if(payload_len > COOJA_RADIO_BUFSIZE) {
240 return RADIO_TX_ERR;
241 }
242 if(payload_len == 0) {
243 return RADIO_TX_ERR;
244 }
245 if(simOutSize > 0) {
246 return RADIO_TX_ERR;
247 }
248
249 if(radio_was_on) {
250 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
251 } else {
252 /* Turn on radio temporarily */
253 simRadioHWOn = 1;
254 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
255 }
256
257#if COOJA_SIMULATE_TURNAROUND
258 simProcessRunValue = 1;
259 cooja_mt_yield();
260 if(payload_len > 3) {
261 simProcessRunValue = 1;
262 cooja_mt_yield();
263 }
264#endif /* COOJA_SIMULATE_TURNAROUND */
265
266 /* Transmit on CCA */
267 if(COOJA_TRANSMIT_ON_CCA && send_on_cca && !channel_clear()) {
268 result = RADIO_TX_COLLISION;
269 } else {
270 /* Copy packet data to temporary storage */
271 memcpy(simOutDataBuffer, payload, payload_len);
272 simOutSize = payload_len;
273
274 /* Transmit */
275 while(simOutSize > 0) {
276 cooja_mt_yield();
277 }
278
279 result = RADIO_TX_OK;
280 }
281
282 if(radio_was_on) {
283 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
284 } else {
285 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
286 }
287
288 simRadioHWOn = radio_was_on;
289 return result;
290}
291/*---------------------------------------------------------------------------*/
292static int
293prepare_packet(const void *data, unsigned short len)
294{
295 if(len > COOJA_RADIO_BUFSIZE) {
296 return RADIO_TX_ERR;
297 }
298 pending_data = data;
299 return 0;
300}
301/*---------------------------------------------------------------------------*/
302static int
303transmit_packet(unsigned short len)
304{
305 int ret = RADIO_TX_ERR;
306 if(pending_data != NULL) {
307 ret = radio_send(pending_data, len);
308 }
309 return ret;
310}
311/*---------------------------------------------------------------------------*/
312static int
313receiving_packet(void)
314{
315 return simReceiving;
316}
317/*---------------------------------------------------------------------------*/
318static int
319pending_packet(void)
320{
321 return !simReceiving && simInSize > 0;
322}
323/*---------------------------------------------------------------------------*/
324PROCESS_THREAD(cooja_radio_process, ev, data)
325{
326 int len;
327
329
330 while(1) {
331 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
332 if(poll_mode) {
333 continue;
334 }
335
337 len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
338 if(len > 0) {
340 NETSTACK_MAC.input();
341 }
342 }
343
344 PROCESS_END();
345}
346/*---------------------------------------------------------------------------*/
347static int
348init(void)
349{
350 process_start(&cooja_radio_process, NULL);
351 return 1;
352}
353/*---------------------------------------------------------------------------*/
354static radio_result_t
355get_value(radio_param_t param, radio_value_t *value)
356{
357 switch(param) {
359 *value = 0;
360 if(addr_filter) {
362 }
363 if(auto_ack) {
364 *value |= RADIO_RX_MODE_AUTOACK;
365 }
366 if(poll_mode) {
367 *value |= RADIO_RX_MODE_POLL_MODE;
368 }
369 return RADIO_RESULT_OK;
371 *value = 0;
372 if(send_on_cca) {
374 }
375 return RADIO_RESULT_OK;
377 *value = radio_signal_strength_last();
378 return RADIO_RESULT_OK;
379
381 *value = radio_lqi_last();
382 return RADIO_RESULT_OK;
383
384 case RADIO_PARAM_RSSI:
385 *value = radio_signal_strength_current();
386 return RADIO_RESULT_OK;
387
388 case RADIO_CONST_MAX_PAYLOAD_LEN:
389 *value = (radio_value_t)COOJA_RADIO_BUFSIZE;
390 return RADIO_RESULT_OK;
392 *value = simRadioChannel;
393 return RADIO_RESULT_OK;
395 *value = MIN_CHANNEL;
396 return RADIO_RESULT_OK;
398 *value = MAX_CHANNEL;
399 return RADIO_RESULT_OK;
400 default:
402 }
403}
404/*---------------------------------------------------------------------------*/
405static radio_result_t
406set_value(radio_param_t param, radio_value_t value)
407{
408 switch(param) {
410 if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
413 }
414
415 /* Only disabling is acceptable for RADIO_RX_MODE_ADDRESS_FILTER */
416 if ((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0) {
418 }
419 set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
420
421 /* Only disabling is acceptable for RADIO_RX_MODE_AUTOACK */
422 if ((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0) {
424 }
425 set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
426
427 set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
428 return RADIO_RESULT_OK;
430 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
432 }
433 set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
434 return RADIO_RESULT_OK;
436 /* With channel value < 0 Cooja matches any channels:
437 * - send packets on a negative channel -> to any receiver's channels.
438 * - receive on a negative channel <- get packets from any sender's channels.
439 * So, negative channel are useful for wide-band noise generation.
440 * Or for wide-band sniffing.
441 * */
442 radio_set_channel(value);
443 return RADIO_RESULT_OK;
444 default:
446 }
447}
448/*---------------------------------------------------------------------------*/
449static radio_result_t
450get_object(radio_param_t param, void *dest, size_t size)
451{
453 if(size != sizeof(rtimer_clock_t) || !dest) {
455 }
456 *(rtimer_clock_t *)dest = (rtimer_clock_t)simLastPacketTimestamp;
457 return RADIO_RESULT_OK;
458 }
460}
461/*---------------------------------------------------------------------------*/
462static radio_result_t
463set_object(radio_param_t param, const void *src, size_t size)
464{
466}
467/*---------------------------------------------------------------------------*/
468const struct radio_driver cooja_radio_driver =
469{
470 init,
471 prepare_packet,
472 transmit_packet,
473 radio_send,
474 radio_read,
478 radio_on,
479 radio_off,
480 get_value,
481 set_value,
484};
485/*---------------------------------------------------------------------------*/
486COOJA_PRE_TICK_ACTION(COOJA_RADIO_INIT_PRIO, doInterfaceActionsBeforeTick)
Header file for the energy estimation mechanism.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition packetbuf.c:136
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition packetbuf.c:143
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition packetbuf.h:67
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition packetbuf.c:75
#define PROCESS(name, strname)
Declare a process.
Definition process.h:307
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition process.h:120
#define PROCESS_END()
Define the end of a process.
Definition process.h:131
void process_start(struct process *p, process_data_t data)
Start a process.
Definition process.c:107
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition process.h:273
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition process.h:178
void process_poll(struct process *p)
Request a process to be polled.
Definition process.c:375
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition radio.h:451
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition radio.h:461
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition radio.h:474
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
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
#define RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition radio.h:456
@ RADIO_RESULT_NOT_SUPPORTED
The parameter is not supported.
Definition radio.h:481
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
Definition radio.h:482
@ RADIO_RESULT_OK
The parameter was set/read successfully.
Definition radio.h:480
@ RADIO_PARAM_RSSI
Received signal strength indicator in dBm.
Definition radio.h:218
@ RADIO_PARAM_LAST_PACKET_TIMESTAMP
Last packet timestamp, of type rtimer_clock_t.
Definition radio.h:286
@ RADIO_PARAM_LAST_RSSI
The RSSI value of the last received packet.
Definition radio.h:226
@ RADIO_PARAM_RX_MODE
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition radio.h:173
@ RADIO_PARAM_CHANNEL
Channel used for radio communication.
Definition radio.h:134
@ RADIO_PARAM_LAST_LINK_QUALITY
Link quality indicator of the last received packet.
Definition radio.h:244
@ RADIO_CONST_CHANNEL_MAX
The highest radio channel number.
Definition radio.h:316
@ RADIO_CONST_CHANNEL_MIN
The lowest radio channel number.
Definition radio.h:311
@ RADIO_PARAM_TX_MODE
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition radio.h:180
@ RADIO_TX_COLLISION
TX failed due to a collision.
Definition radio.h:511
@ RADIO_TX_ERR
An error occurred during transmission.
Definition radio.h:506
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition radio.h:498
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for the radio API.
void(* input)(void)
Callback for getting notified of incoming packet.
Definition mac.h:78
The structure of a Contiki-NG radio device driver.
Definition radio.h:534
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition radio.h:770
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition radio.h:756
int(* init)(void)
Initialise the radio hardware.
Definition radio.h:555
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition radio.h:684
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition radio.h:787
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver's buffers.
Definition radio.h:697
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition radio.h:741
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:672