Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * $Id: cooja-radio.c,v 1.15 2010/06/14 19:19:17 adamdunkels Exp $ 00030 */ 00031 00032 #include <stdio.h> 00033 #include <string.h> 00034 00035 #include "contiki.h" 00036 00037 #include "sys/cooja_mt.h" 00038 #include "lib/simEnvChange.h" 00039 00040 #include "net/packetbuf.h" 00041 #include "net/rime/rimestats.h" 00042 #include "net/netstack.h" 00043 00044 #include "dev/radio.h" 00045 #include "dev/cooja-radio.h" 00046 00047 #define COOJA_RADIO_BUFSIZE PACKETBUF_SIZE 00048 #define CCA_SS_THRESHOLD -95 00049 00050 #define WITH_TURNAROUND 1 00051 #define WITH_SEND_CCA 1 00052 00053 const struct simInterface radio_interface; 00054 00055 /* COOJA */ 00056 char simReceiving = 0; 00057 char simInDataBuffer[COOJA_RADIO_BUFSIZE]; 00058 int simInSize = 0; 00059 char simOutDataBuffer[COOJA_RADIO_BUFSIZE]; 00060 int simOutSize = 0; 00061 char simRadioHWOn = 1; 00062 int simSignalStrength = -100; 00063 int simLastSignalStrength = -100; 00064 char simPower = 100; 00065 int simRadioChannel = 26; 00066 00067 static const void *pending_data; 00068 00069 PROCESS(cooja_radio_process, "cooja radio process"); 00070 00071 /*---------------------------------------------------------------------------*/ 00072 void 00073 radio_set_channel(int channel) 00074 { 00075 simRadioChannel = channel; 00076 } 00077 /*---------------------------------------------------------------------------*/ 00078 void 00079 radio_set_txpower(unsigned char power) 00080 { 00081 /* 1 - 100: Number indicating output power */ 00082 simPower = power; 00083 } 00084 /*---------------------------------------------------------------------------*/ 00085 int 00086 radio_signal_strength_last(void) 00087 { 00088 return simLastSignalStrength; 00089 } 00090 /*---------------------------------------------------------------------------*/ 00091 int 00092 radio_signal_strength_current(void) 00093 { 00094 return simSignalStrength; 00095 } 00096 /*---------------------------------------------------------------------------*/ 00097 static int 00098 radio_on(void) 00099 { 00100 simRadioHWOn = 1; 00101 return 1; 00102 } 00103 /*---------------------------------------------------------------------------*/ 00104 static int 00105 radio_off(void) 00106 { 00107 simRadioHWOn = 0; 00108 return 1; 00109 } 00110 /*---------------------------------------------------------------------------*/ 00111 static void 00112 doInterfaceActionsBeforeTick(void) 00113 { 00114 if(!simRadioHWOn) { 00115 simInSize = 0; 00116 return; 00117 } 00118 if(simReceiving) { 00119 simLastSignalStrength = simSignalStrength; 00120 return; 00121 } 00122 00123 if(simInSize > 0) { 00124 process_poll(&cooja_radio_process); 00125 } 00126 } 00127 /*---------------------------------------------------------------------------*/ 00128 static void 00129 doInterfaceActionsAfterTick(void) 00130 { 00131 } 00132 /*---------------------------------------------------------------------------*/ 00133 static int 00134 radio_read(void *buf, unsigned short bufsize) 00135 { 00136 int tmp = simInSize; 00137 00138 if(simInSize == 0) { 00139 return 0; 00140 } 00141 if(bufsize < simInSize) { 00142 simInSize = 0; /* rx flush */ 00143 RIMESTATS_ADD(toolong); 00144 return 0; 00145 } 00146 00147 memcpy(buf, simInDataBuffer, simInSize); 00148 simInSize = 0; 00149 return tmp; 00150 } 00151 /*---------------------------------------------------------------------------*/ 00152 static int 00153 channel_clear(void) 00154 { 00155 if(simSignalStrength > CCA_SS_THRESHOLD) { 00156 return 0; 00157 } 00158 return 1; 00159 } 00160 /*---------------------------------------------------------------------------*/ 00161 static int 00162 radio_send(const void *payload, unsigned short payload_len) 00163 { 00164 int radiostate = simRadioHWOn; 00165 00166 /* Simulate turnaround time of 1ms */ 00167 #if WITH_TURNAROUND 00168 simProcessRunValue = 1; 00169 cooja_mt_yield(); 00170 #endif /* WITH_TURNAROUND */ 00171 00172 if(!simRadioHWOn) { 00173 /* Turn on radio temporarily */ 00174 simRadioHWOn = 1; 00175 } 00176 if(payload_len > COOJA_RADIO_BUFSIZE) { 00177 return RADIO_TX_ERR; 00178 } 00179 if(payload_len == 0) { 00180 return RADIO_TX_ERR; 00181 } 00182 if(simOutSize > 0) { 00183 return RADIO_TX_ERR; 00184 } 00185 00186 /* Transmit on CCA */ 00187 #if WITH_SEND_CCA 00188 if(!channel_clear()) { 00189 return RADIO_TX_COLLISION; 00190 } 00191 #endif /* WITH_SEND_CCA */ 00192 00193 /* Copy packet data to temporary storage */ 00194 memcpy(simOutDataBuffer, payload, payload_len); 00195 simOutSize = payload_len; 00196 00197 /* Transmit */ 00198 while(simOutSize > 0) { 00199 cooja_mt_yield(); 00200 } 00201 00202 simRadioHWOn = radiostate; 00203 return RADIO_TX_OK; 00204 } 00205 /*---------------------------------------------------------------------------*/ 00206 static int 00207 prepare_packet(const void *data, unsigned short len) 00208 { 00209 pending_data = data; 00210 return 0; 00211 } 00212 /*---------------------------------------------------------------------------*/ 00213 static int 00214 transmit_packet(unsigned short len) 00215 { 00216 int ret = RADIO_TX_ERR; 00217 if(pending_data != NULL) { 00218 ret = radio_send(pending_data, len); 00219 } 00220 return ret; 00221 } 00222 /*---------------------------------------------------------------------------*/ 00223 static int 00224 receiving_packet(void) 00225 { 00226 return simReceiving; 00227 } 00228 /*---------------------------------------------------------------------------*/ 00229 static int 00230 pending_packet(void) 00231 { 00232 return !simReceiving && simInSize > 0; 00233 } 00234 /*---------------------------------------------------------------------------*/ 00235 PROCESS_THREAD(cooja_radio_process, ev, data) 00236 { 00237 int len; 00238 00239 PROCESS_BEGIN(); 00240 00241 while(1) { 00242 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); 00243 00244 packetbuf_clear(); 00245 len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE); 00246 if(len > 0) { 00247 packetbuf_set_datalen(len); 00248 NETSTACK_RDC.input(); 00249 } 00250 } 00251 00252 PROCESS_END(); 00253 } 00254 /*---------------------------------------------------------------------------*/ 00255 static int 00256 init(void) 00257 { 00258 process_start(&cooja_radio_process, NULL); 00259 return 1; 00260 } 00261 /*---------------------------------------------------------------------------*/ 00262 const struct radio_driver cooja_radio_driver = 00263 { 00264 init, 00265 prepare_packet, 00266 transmit_packet, 00267 radio_send, 00268 radio_read, 00269 channel_clear, 00270 receiving_packet, 00271 pending_packet, 00272 radio_on, 00273 radio_off, 00274 }; 00275 /*---------------------------------------------------------------------------*/ 00276 SIM_INTERFACE(radio_interface, 00277 doInterfaceActionsBeforeTick, 00278 doInterfaceActionsAfterTick);