📄 cpmmodelc.nc
字号:
/*
* "Copyright (c) 2005 Stanford University. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose, without fee, and without written
* agreement is hereby granted, provided that the above copyright
* notice, the following two paragraphs and the author appear in all
* copies of this software.
*
* IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
* PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY
* HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS."
*/
/**
*
* CPM (closest-pattern matching) is a wireless noise simulation model
* based on statistical extraction from empirical noise data. This
* model provides far more precise software simulation environment by
* exploiting time-correlated noise characteristics. For details,
* please refer to the paper
*
* "Improving Wireless Simulation through Noise Modeling." HyungJune
* Lee and Philip Levis, IPSN 2007. You can find a copy at
* http://sing.stanford.edu.
*
* @author Hyungjune Lee, Philip Levis
* @date Oct 12 2006
*/
#include <sim_gain.h>
#include <sim_noise.h>
#include <randomlib.h>
module CpmModelC {
provides interface GainRadioModel as Model;
}
implementation {
message_t* outgoing; // If I'm sending, this is my outgoing packet
bool requestAck;
bool receiving = 0; // Whether or not I think I'm receiving a packet
bool transmitting = 0; // Whether or not I think I'm tranmitting a packet
sim_time_t transmissionEndTime; // to check pending transmission
struct receive_message;
typedef struct receive_message receive_message_t;
struct receive_message {
int source;
sim_time_t start;
sim_time_t end;
double power;
double reversePower;
int8_t strength;
bool lost;
bool ack;
message_t* msg;
receive_message_t* next;
};
receive_message_t* outstandingReceptionHead = NULL;
receive_message_t* allocate_receive_message();
void free_receive_message(receive_message_t* msg);
sim_event_t* allocate_receive_event(sim_time_t t, receive_message_t* m);
bool shouldReceive(double SNR);
bool checkReceive(receive_message_t* msg);
double packetNoise(receive_message_t* msg);
double checkPrr(receive_message_t* msg);
double timeInMs() {
sim_time_t ftime = sim_time();
int hours, minutes, seconds;
sim_time_t secondBillionths;
int temp_time;
double ms_time;
secondBillionths = (ftime % sim_ticks_per_sec());
if (sim_ticks_per_sec() > (sim_time_t)1000000000) {
secondBillionths /= (sim_ticks_per_sec() / (sim_time_t)1000000000);
}
else {
secondBillionths *= ((sim_time_t)1000000000 / sim_ticks_per_sec());
}
temp_time = (int)(secondBillionths/10000);
if (temp_time % 10 >= 5) {
temp_time += (10-(temp_time%10));
}
else {
temp_time -= (temp_time%10);
}
ms_time = (float)(temp_time/100.0);
seconds = (int)(ftime / sim_ticks_per_sec());
minutes = seconds / 60;
hours = minutes / 60;
seconds %= 60;
minutes %= 60;
ms_time += (hours*3600+minutes*60+seconds)*1000;
return ms_time;
}
//Generate a CPM noise reading
double noise_hash_generation() {
double CT = timeInMs();
uint32_t quotient = ((sim_time_t)(CT*10))/10;
uint8_t remain = (uint8_t)(((sim_time_t)(CT*10))%10);
double noise_val;
uint16_t node_id = sim_node();
dbg("CpmModelC", "IN: noise_hash_generation()\n");
if (5 <= remain && remain < 10) {
noise_val = (double)sim_noise_generate(node_id, quotient+1);
}
else {
noise_val = (double)sim_noise_generate(node_id, quotient);
}
dbg("CpmModelC,Tal", "%s: OUT: noise_hash_generation(): %lf\n", sim_time_string(), noise_val);
return noise_val;
}
double packetSnr(receive_message_t* msg) {
double signalStr = msg->power;
double noise = noise_hash_generation();
return (signalStr - noise);
}
double arr_estimate_from_snr(double SNR) {
double beta1 = 0.9794;
double beta2 = 2.3851;
double X = SNR-beta2;
double PSE = 0.5*erfc(beta1*X/sqrt(2));
double prr_hat = pow(1-PSE, 23*2);
dbg("CpmModelC,SNRLoss", "SNR is %lf, ARR is %lf\n", SNR, prr_hat);
if (prr_hat > 1)
prr_hat = 1.1;
else if (prr_hat < 0)
prr_hat = -0.1;
return prr_hat;
}
int shouldAckReceive(double snr) {
double prr = arr_estimate_from_snr(snr);
double coin = RandomUniform();
if ( (prr >= 0) && (prr <= 1) ) {
if (coin < prr)
prr = 1.0;
else
prr = 0.0;
}
return (int)prr;
}
void sim_gain_ack_handle(sim_event_t* evt) {
// Four conditions must hold for an ack to be issued:
// 1) Transmitter is still sending a packet (i.e., not cancelled)
// 2) The packet requested an acknowledgment
// 3) The transmitter is on
// 4) The packet passes the SNR/ARR curve
if (requestAck && // This
outgoing != NULL &&
sim_mote_is_on(sim_node())) {
receive_message_t* rcv = (receive_message_t*)evt->data;
double power = rcv->reversePower;
double noise = packetNoise(rcv);
double snr = power - noise;
if (shouldAckReceive(snr)) {
signal Model.acked(outgoing);
}
}
free_receive_message((receive_message_t*)evt->data);
}
sim_event_t receiveEvent;
// This clear threshold comes from the CC2420 data sheet
double clearThreshold = -72.0;
bool collision = FALSE;
message_t* incoming = NULL;
int incomingSource;
command void Model.setClearValue(double value) {
clearThreshold = value;
dbg("CpmModelC", "Setting clear threshold to %f\n", clearThreshold);
}
command bool Model.clearChannel() {
dbg("CpmModelC", "Checking clear channel @ %s: %f <= %f \n", sim_time_string(), (double)packetNoise(NULL), clearThreshold);
return packetNoise(NULL) < clearThreshold;
}
void sim_gain_schedule_ack(int source, sim_time_t t, receive_message_t* r) {
sim_event_t* ackEvent = (sim_event_t*)malloc(sizeof(sim_event_t));
ackEvent->mote = source;
ackEvent->force = 1;
ackEvent->cancelled = 0;
ackEvent->time = t;
ackEvent->handle = sim_gain_ack_handle;
ackEvent->cleanup = sim_queue_cleanup_event;
ackEvent->data = r;
sim_queue_insert(ackEvent);
}
double prr_estimate_from_snr(double SNR) {
// Based on CC2420 measurement by Kannan.
// The updated function below fixes the problem of non-zero PRR
// at very low SNR. With this function PRR is 0 for SNR <= 3.
double beta1 = 0.9794;
double beta2 = 2.3851;
double X = SNR-beta2;
double PSE = 0.5*erfc(beta1*X/sqrt(2));
double prr_hat = pow(1-PSE, 23*2);
dbg("CpmModelC,SNR", "SNR is %lf, PRR is %lf\n", SNR, prr_hat);
if (prr_hat > 1)
prr_hat = 1.1;
else if (prr_hat < 0)
prr_hat = -0.1;
return prr_hat;
}
bool shouldReceive(double SNR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -