IEEE802154A.cc

00001 /* -*- mode:c++ -*- ********************************************************
00002  * file:        IEEE802154A.cc
00003  *
00004  * author:      Jerome Rousselot <jerome.rousselot@csem.ch>
00005  *
00006  * copyright:   (C) 2008 Centre Suisse d'Electronique et Microtechnique (CSEM) SA
00007  *        Systems Engineering
00008  *              Real-Time Software and Networking
00009  *              Jaquet-Droz 1, CH-2002 Neuchatel, Switzerland.
00010  *
00011  *              This program is free software; you can redistribute it
00012  *              and/or modify it under the terms of the GNU General Public
00013  *              License as published by the Free Software Foundation; either
00014  *              version 2 of the License, or (at your option) any later
00015  *              version.
00016  *              For further information see file COPYING
00017  *              in the top level directory
00018  * description: this class holds constants specified in IEEE 802.15.4A UWB-IR Phy
00019  * acknowledgment: this work was supported (in part) by the National Competence
00020  *          Center in Research on Mobile Information and Communication Systems
00021  *        NCCR-MICS, a center supported by the Swiss National Science
00022  *        Foundation under grant number 5005-67322.
00023  ***************************************************************************/
00024 
00025 #include "IEEE802154A.h"
00026 #include <cassert>
00027 
00028 // bit rate (850 kbps)
00029 const int IEEE802154A::mandatory_bitrate = 850000;
00030 // mandatory data symbol length (1.025 ms)
00031 const_simtime_t IEEE802154A::mandatory_symbol = 0.00000102364; //102564
00032 // 0.5 * mandatory_symbol (0.5 ms)
00033 const_simtime_t IEEE802154A::mandatory_timeShift = 0.00000051282;
00034 // mandatory pulse duration ( = 1 / bandwidth = 2 ns)
00035 const_simtime_t IEEE802154A::mandatory_pulse = 0.000000002003203125;
00036 // burst duration (32 ns)
00037 const_simtime_t IEEE802154A::mandatory_burst = 0.00000003205;
00038 // number of consecutive pulses forming a burst
00039 const int IEEE802154A::mandatory_pulses_per_burst = 16;
00040 // Center frequency of band 3 in UWB lower band (500 MHz wide channel)
00041 const double IEEE802154A::mandatory_centerFreq = 4498; // MHz
00042 // default sync preamble length
00043 const_simtime_t IEEE802154A::mandatory_preambleLength = 0.0000715; // Tpre=71.5 µs
00044 // Normalized pulse envelope peak
00045 const double IEEE802154A::maxPulse = 1;
00046 // Duration of a sync preamble symbol
00047 const_simtime_t IEEE802154A::Tpsym = 0.001 * 0.001 * 0.001 * 993.6; // 993.6 ns
00048 
00049 const_simtime_t IEEE802154A::tFirstSyncPulseMax = IEEE802154A::mandatory_pulse/2;
00050 
00051 // Ci values
00052 const short IEEE802154A::C31[8][31] = {
00053 // C1
00054     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00055         0, 0, 0, 0, 0, 0, 0, 0 },
00056     // C2
00057     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00058         0, 0, 0, 0, 0, 0, 0, 0 },
00059     // C3
00060     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00061         0, 0, 0, 0, 0, 0, 0, 0 },
00062     // C4
00063     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00064         0, 0, 0, 0, 0, 0, 0, 0 },
00065     // C5
00066     { -1, 0, +1, -1, 0, 0, +1, +1, +1, -1, +1, 0, 0, 0, -1, +1, 0, +1, +1,
00067         +1, 0, -1, 0, +1, 0, 0, 0, 0, -1, 0, 0 },
00068     // C6
00069     { +1, +1, 0, 0, +1, 0, 0, -1, -1, -1, +1, -1, 0, +1, +1, -1, 0, 0, 0,
00070         +1, 0, +1, 0, -1, +1, 0, +1, 0, 0, 0, 0 },
00071     // C7
00072     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00073         0, 0, 0, 0, 0, 0, 0, 0 },
00074     // C8
00075     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00076         0, 0, 0, 0, 0, 0, 0, 0 },
00077 
00078 };
00079 
00080 const short IEEE802154A::shortSFD[8] = { 0, 1, 0, -1, 1, 0, 0, -1 };
00081 
00082 short IEEE802154A::s_array[maxS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
00083     0, 0, 0 };
00084 int IEEE802154A::last_s = 15;
00085 
00086 double IEEE802154A::signalStart = 0;
00087 
00088 int IEEE802154A::psduLength = 0;
00089 
00090 //const_simtime_t IEEE802154A::MaxFrameDuration = IEEE802154A::MaxPSDULength*IEEE802154A::mandatory_symbol + IEEE802154A::mandatory_preambleLength;
00091 
00092 const IEEE802154A::config IEEE802154A::cfg_mandatory_16M = {
00093     3,          // channel
00094     NOMINAL_16_M,     // PRF
00095     NON_RANGING,    // Frame type
00096     PSR_DEFAULT,    // preamble length (number of preamble symbols)
00097     31,         // Spreading code length
00098     16,         // spreading delta L
00099     16,         // chips per burst
00100     850000,       // bit rate (bps)
00101     16,         // pulses per data burst
00102     993.6E-9,     // preamble symbol duration
00103     1023.64E-9,     // data symbol duration
00104     512.82E-9,      // burst time shift duration
00105     2.003E-9,     // pulse duration (chip)
00106     32.05E-9,     // burst duration (pulses per data burst * chip)
00107     71.5E-6,      // synchronization preamble duration
00108     4498        // center frequency
00109 };
00110 
00111 const IEEE802154A::config IEEE802154A::cfg_mandatory_4M = {
00112     3,          // channel
00113     NOMINAL_4_M,    // PRF
00114     NON_RANGING,    // Frame type
00115     PSR_DEFAULT,    // preamble length (number of preamble symbols)
00116     31,         // Spreading code length
00117     64,         // spreading delta L
00118     4,          // chips per burst
00119     850000,       // bit rate (bps)
00120     4,          // pulses per data burst
00121     3974.36E-9,     // preamble symbol duration
00122     1023.64E-9,     // data symbol duration
00123     512.82E-9,      // burst time shift duration
00124     2.003E-9,     // pulse duration (chip)
00125     8.01E-9,      // burst duration (pulses per data burst * chip)
00126     286.2E-6,     // synchronization preamble duration
00127     4498        // center frequency
00128 };
00129 
00130 IEEE802154A::config IEEE802154A::cfg = IEEE802154A::cfg_mandatory_16M;
00131 
00132 void IEEE802154A::setConfig(config newCfg) {
00133   cfg = newCfg;
00134 }
00135 
00136 void IEEE802154A::setPSDULength(int _psduLength) {
00137   //assert(_psduLength < IEEE802154A::MaxPSDULength+1);
00138   IEEE802154A::psduLength = _psduLength;
00139 }
00140 
00141 simtime_t IEEE802154A::getMaxFrameDuration() {
00142   return IEEE802154A::MaxPSDULength*cfg.data_symbol_duration + cfg.preambleLength;
00143 }
00144 
00145 IEEE802154A::signalAndData IEEE802154A::generateIEEE802154AUWBSignal(
00146     simtime_t signalStart, bool allZeros) {
00147   // 48 R-S parity bits, the 2 symbols phy header is not modeled as it includes its own parity bits
00148   // and is thus very robust
00149   unsigned int nbBits = IEEE802154A::psduLength * 8 + 48;
00150   IEEE802154A::signalStart = signalStart.dbl();  // use the signalStart time value as a global offset for all Mapping values
00151   simtime_t signalLength = cfg.preambleLength;
00152   signalLength += static_cast<double> (nbBits) * cfg.data_symbol_duration;
00153   Signal* s = new Signal(signalStart, signalLength);
00154   vector<bool>* bitValues = new vector<bool> ();
00155 
00156   signalAndData res;
00157   int bitValue;
00158   // data start time relative to signal->getSignalStart();
00159   simtime_t dataStart = cfg.preambleLength; // = Tsync + Tsfd
00160   TimeMapping<Linear>* mapping = new TimeMapping<Linear> ();
00161   Argument* arg = new Argument();
00162   setBitRate(s);
00163 
00164   generateSyncPreamble(mapping, arg);
00165   generateSFD(mapping, arg);
00166   //generatePhyHeader(mapping, arg);
00167 
00168   // generate bit values and modulates them according to
00169   // the IEEE 802.15.4A specification
00170   simtime_t symbolStart = dataStart;
00171   simtime_t burstPos;
00172   for (unsigned int burst = 0; burst < nbBits; burst++) {
00173     if(allZeros) {
00174       bitValue = 0;
00175     } else {
00176       bitValue = intuniform(0, 1, 0);
00177     }
00178     bitValues->push_back(static_cast<bool>(bitValue));
00179     burstPos = symbolStart + bitValue*cfg.shift_duration + getHoppingPos(burst)*cfg.burst_duration;
00180     generateBurst(mapping, arg, burstPos, +1);
00181     symbolStart = symbolStart + cfg.data_symbol_duration;
00182   }
00183   //assert(uwbirMacPkt->getBitValuesArraySize() == dataLength);
00184   //assert(bitValues->size() == nbBits);
00185 
00186   // associate generated pulse energies to the signal
00187   s->setTransmissionPower(mapping);
00188   delete arg;
00189 
00190   res.first = s;
00191   res.second = bitValues;
00192   return res;
00193 }
00194 
00195 void IEEE802154A::generateSyncPreamble(Mapping* mapping, Argument* arg) {
00196   // NSync repetitions of the Si symbol
00197   for (short n = 0; n < cfg.NSync; n = n + 1) {
00198     for (short pos = 0; pos < cfg.CLength; pos = pos + 1) {
00199       if (C31[Ci - 1][pos] != 0) {
00200         if(n==0 && pos==0) {
00201           // we slide the first pulse slightly in time to get the first point "inside" the signal
00202           arg->setTime(1E-12 + n * cfg.sync_symbol_duration + pos * cfg.spreadingdL * cfg.pulse_duration);
00203         } else {
00204           arg->setTime(n * cfg.sync_symbol_duration + pos * cfg.spreadingdL * cfg.pulse_duration);
00205         }
00206         //generatePulse(mapping, arg, C31[Ci - 1][pos],
00207         //    IEEE802154A::maxPulse, IEEE802154A::mandatory_pulse);
00208         generatePulse(mapping, arg, 1,      // always positive polarity
00209             IEEE802154A::maxPulse, cfg.pulse_duration);
00210       }
00211     }
00212   }
00213 }
00214 
00215 void IEEE802154A::generateSFD(Mapping* mapping, Argument* arg) {
00216   double sfdStart = NSync * Tpsym;
00217   for (short n = 0; n < 8; n = n + 1) {
00218     if (IEEE802154A::shortSFD[n] != 0) {
00219       for (short pos = 0; pos < cfg.CLength; pos = pos + 1) {
00220         if (C31[Ci - 1][pos] != 0) {
00221           arg->setTime(sfdStart + n*cfg.sync_symbol_duration + pos*cfg.spreadingdL*cfg.pulse_duration);
00222           //generatePulse(mapping, arg, C31[Ci - 1][pos] * shortSFD[n]); // change pulse polarity
00223           generatePulse(mapping, arg, 1); // always positive polarity
00224         }
00225       }
00226     }
00227   }
00228 }
00229 
00230 void IEEE802154A::generatePhyHeader(Mapping* mapping, Argument* arg) {
00231   // not implemented
00232 }
00233 
00234 void IEEE802154A::generatePulse(Mapping* mapping, Argument* arg,
00235     short polarity, double peak, simtime_t chip) {
00236   assert(polarity == -1 || polarity == +1);
00237   arg->setTime(arg->getTime() + IEEE802154A::signalStart);  // adjust argument so that we use absolute time values in Mapping
00238   mapping->setValue(*arg, 0);
00239   arg->setTime(arg->getTime() + chip / 2);
00240   // Maximum point at symbol half (triangular pulse)
00241   mapping->setValue(*arg, peak * polarity);
00242   arg->setTime(arg->getTime() + chip / 2);
00243   mapping->setValue(*arg, 0);
00244 }
00245 
00246 void IEEE802154A::generateBurst(Mapping* mapping, Argument* arg,
00247     simtime_t burstStart, short polarity) {
00248   assert(burstStart < cfg.preambleLength+(psduLength*8+48+2)*cfg.data_symbol_duration);
00249   // 1. Start point = zeros
00250   simtime_t offset = burstStart;
00251   for (int pulse = 0; pulse < cfg.nbPulsesPerBurst; pulse++) {
00252     arg->setTime(offset);
00253     generatePulse(mapping, arg, 1);
00254     offset = offset + cfg.pulse_duration;
00255   }
00256 }
00257 
00258 void IEEE802154A::setBitRate(Signal* s) {
00259   Argument arg = Argument();
00260   // set a constant value for bitrate
00261   TimeMapping<Linear>* bitrate = new TimeMapping<Linear> ();
00262   arg.setTime(IEEE802154A::signalStart); // absolute time (required for compatibility with MiXiM base RSAM code)
00263   bitrate->setValue(arg, cfg.bitrate);
00264   arg.setTime(s->getSignalLength());
00265   bitrate->setValue(arg, cfg.bitrate);
00266   s->setBitrate(bitrate);
00267 }
00268 
00269 simtime_t IEEE802154A::getThdr() {
00270   switch (cfg.channel) {
00271   default:
00272     switch (cfg.prf) {
00273     case NOMINAL_4_M:
00274       //error("This optional mode is not implemented.");
00275       return 0;
00276       break;
00277     case NOMINAL_16_M:
00278       return 16.4E-6;
00279     case NOMINAL_64_M:
00280       return 16.8E-6;
00281     case PRF_OFF:
00282       return 0;
00283     }
00284   }
00285   return 0;
00286 }
00287 
00288 int IEEE802154A::s(int n) {
00289 
00290   assert(n < maxS);
00291 
00292   for (; last_s < n; last_s = last_s + 1) {
00293     // compute missing values as necessary
00294     s_array[last_s] = (s_array[last_s - 14] + s_array[last_s - 15]) % 2;
00295   }
00296   assert(s_array[n] == 0 || s_array[n] == 1);
00297   return s_array[n];
00298 
00299 }
00300 
00301 int IEEE802154A::getHoppingPos(int sym) {
00302   //int m = 3;  // or 5 with 4M
00303   int pos = 0;
00304   int kNcpb = 0;
00305   switch(cfg.prf) {
00306   case NOMINAL_4_M:
00307     kNcpb = sym * cfg.Ncpb;
00308     pos = s(kNcpb) + 2*s(1+kNcpb) + 4*s(2+kNcpb) + 8*s(3+kNcpb) + 16*s(4+kNcpb);
00309     break;
00310   case NOMINAL_16_M:
00311     pos = s(kNcpb) + 2*s(1+kNcpb) + 4*s(2+kNcpb);
00312     break;
00313   case NOMINAL_64_M:
00314   case PRF_OFF:
00315   default:
00316     assert(0==1);  // unimplemented or invalid PRF value
00317   }
00318   // assert(pos > -1 && pos < 8); // TODO: update to reflect number of hopping pos for current config
00319   return pos;
00320 }
00321 
00322 simtime_t IEEE802154A::getPhyMaxFrameDuration() {
00323   simtime_t phyMaxFrameDuration = 0;
00324   simtime_t TSHR, TPHR, TPSDU, TCCApreamble;
00325   TSHR = IEEE802154A::getThdr();
00326   TPHR = IEEE802154A::getThdr();
00327   phyMaxFrameDuration = phyMaxFrameDuration + TSHR;
00328   return phyMaxFrameDuration;
00329 }