aboutsummaryrefslogtreecommitdiffstats log msg author committer range
path: root/scenarios.tex
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377  .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */% LICENSE: see LICENCE \section{Usage Scenarios} \subsection{Experimentation} \subsubsection{Creation of Non-Realtime Multiplex} The creation of a ETI file containing two programmes, one DAB and one \dabplus{} is covered in section \ref{sec-files}. \subsubsection{Modulation of ETI for Offline Processing} The ETI file generated before can then be used with ODR-DabMod to generate a file containing I/Q samples. Here, we must chose between using the command line or the configuration file. For a very simple example, using the command line makes sense, but for more advanced features it is preferable to use a configuration file. For illustration, we will present both. To modulate the file \texttt{myfirst.eti} into \texttt{myfirst.iq}, with the default options, the command is simply \begin{lstlisting} odr-dabmod myfirst.eti -f myfirst.iq -n 1 \end{lstlisting} This will create a file containing 32-bit interleaved I/Q at $2048000$ samples per second. Where the maximal amplitude is bounded by 1.The transmission mode is defined by the ETI file. The equivalent configuration file would be \begin{lstlisting} [input] transport=file source=myfirst.eti [output] output=file [fileoutput] format=complexf normalize=1 filename=myfirst.iq \end{lstlisting} This is a very minimal file that defines only the necessary settings equivalent to the above command line options. The configuration file however supports more options that the command line, and becomes easier to manager once the set becomes more complex. It is best to use the example configuration available in the \texttt{doc/} folder. \subsection{Interfacing Hardware Devices} \subsubsection{Ettus USRP} ODR-DabMod integrates support for the UHD library that can interface with all USRP devices from Ettus. The following configuration file \texttt{mod.ini} illustrates how to send the \texttt{myfirst.eti} over a USRP B200 on channel 13C: \begin{lstlisting} [remotecontrol] telnet=1 telnetport=2121 [input] transport=file source=myfirst.eti loop=1 [modulator] gainmode=2 digital_gain=0.8 [firfilter] enabled=0 [output] output=uhd [uhdoutput] master_clock_rate=32768000 type=b200 txgain=40 channel=13C \end{lstlisting} This example also shows more options that the example for the file output: \begin{itemize} \item \texttt{remotecontrol telnet=1} enables the Telnet server that can be used to set parameters while the modulator is running. \item \texttt{loop=1} rewinds the input file when the end is reached. The same ETI file will be transmitted over and over. \item \texttt{gainmode=2} sets the GainMode to VAR, which reduces overshoots in the output. \item \texttt{digital\_gain=0.8} reduces the output sample deviation, to reduce compression in the USRP. \item \texttt{firfilter enabled=0} can be set to 1 to enable an additional FIR filter to improve the spectrum mask. This filter needs a file containing the filter taps, which can be generated using \texttt{ODR-DabMod/doc/fir-filter/generate-filter.py}. An example taps file is also available in this folder. \item \texttt{master\_clock\_rate=32768000} sets the USRP internal clock to a multiple of $2048000$, which is required if we want to use the native DAB sample rate. \item \texttt{txgain=40} Sets the analog transmit gain of the USRP to 40dB, which is specific to the B200. \end{itemize} Some of these options are not necessary for the system to work, but they improve the performance. \paragraph{Remarks concerning the USRP B200} The USRP B200 depicted in figure~\ref{fig:usrp-b200} is the device we are using most. It's performance is proven in a production environment, it supports the transmit synchronisation necessary for SFN and is robust enough for 24/7 operation. \begin{wrapfigure}{r}{13em} \centering \includegraphics[width=12em]{figures/USRP-B200.jpg} \caption{Ettus USRP B200} \label{fig:usrp-b200} \end{wrapfigure} However, care has to be taken about the host system, especially about the USB controller. Using USB~2.0 is not a problem for a DAB transmission, both USB~2.0 and USB~3.0 host controllers can therefore be used. Since USB~2.0 has been around for longer and is more mature, it is sometimes preferable because it causes less USB errors. This heavily depends on the exact model of the USB controller inside the host PC, and has to be tested for each system. The txgain on the B200 varies between $0$dB and about $90$dB. Experience shows that compression effects begin to appear at values around $85$dB. This might be different from device to device and needs to measured. Similarly, the digital gain has to optimised for a given setting. It is important that there is no digital clipping in the chain, because that leads to problematic spurious spectrum components, that can disturb or even damage a power amplifier. There are some performance measurements available on the Opendigitalradio wiki.\footnote{\url{http://wiki.opendigitalradio.org/index.php/USRP\_B200\_Measurements}} \paragraph{Remarks concerning other USRP models} We have used the USRP1, the USRP2 and the USRP B100 with the tools. The WBX is the most appropriate daughterboard for these models. The txgain setting has another range, it is best to start at $0$dB, and increase it in steps of $3$dB or smaller while measuring the output signal, until the correct power is reached. \subsubsection{Other Hardware} \label{otherhardware} ODR-DabMod supports other radio interfaces using SoapySDR or through standard output, or via a fifo -- the latter must be created prior to runtime with the \texttt{mkfifo} command. Due to limitations in the UHD driver library, \texttt{/dev/stdout} will only function correctly if ODR-DabMod is configured at compilation time with the following argument: \begin{lstlisting} --disable-output-uhd \end{lstlisting} SoapySDR\footnote{\url{https://github.com/pothosware/SoapySDR/wiki}} is a vendor neutral and platform independent library to drive SDR devices. It can be used to drive the LimeSDR board and the HackRF from Great Scott Gadgets. Installation dependencies are shown in the \texttt{INSTALL} file, and an example configuration is in \texttt{doc/example.mux}. The TX Gain setting should be chosen inside the valid range for the device being used. This range can be shown by calling \texttt{SoapySDRUtil --probe}. ODR-DabMod has been tested working with HackRF on i386 and x86\_64 architectures.\footnote{HackRF has not been tested to any degree of success with ARM-based computers at this time as they are not (yet) capable of resampling to the required higher rates as the process is highly CPU intensive.} The unit is an entry level yet versatile SDR which provides coverage between $\approx10$MHz to $6$GHz, and DAB signals been successfully generated with it in VHF Band III ($174$--$240$MHz), L-Band ($1462$--$1467.5$MHz) and even the worldwide ISM Band ($2400$--$2500$MHz). The latter (subject to local regulations) is a licence exempt band which may be useful for performing freely radiating tests at low power. Cheap MMDS converters are currently available which helpfully provide a Band III IF output providing a direct feed to the aerial input of a receiver. Before choosing a converter it is important to pay close attention to the specifications. The local oscillator phase noise performance, and the dynamic range (due to the heavy use of the band) are both particularly important. To use the HackRF through stdout (i.e.\ without SoapySDR), the output of ODR-DabMod must be set (in the configuration file) to produce 8-bit signed integers, rather than the default complex floats. HackRF has selectable baseband filters, however the lowest filter setting ($1.75$MHz) does not provide adequate image rejection at the native sampling rate of $2048$k samples per second. An appropriate rate to start with is $4096$k, and for some purposes this may well be adequate as this moves the image signals generated within the radio far enough into the stop-band of filter to attenuate them significantly. The digital gain in the ODR-DabMod configuration file should be set to a maximum of $2.4$ at this rate to avoid digital clipping on modulation peaks. Example of the settings in the \texttt{mod.ini} file suitable for use with HackRF: \begin{lstlisting} [remotecontrol] telnet=1 telnetport=2121 [input] transport=file source=myfirst.eti loop=1 [modulator] gainmode=2 digital_gain=2.4 rate=4096000 [firfilter] enabled=1 [output] output=file [fileoutput] format=s8 filename=/tmp/ofdm.fifo \end{lstlisting} The output fifo has to be created beforehand, and the \texttt{hackrf\_transfer} utility is then used to transmit the signal to the device. Depending on the capabilities of the host computer, using higher sampling rates ($6144$k, and even $8192$k) may be possible. This oversampling is desirable as it helps to produce a cleaner spectral output. At higher rates one needs to ensure that samples are not being dropped on the USB and that CPU resources are not being contended. It is also important to note that the digital gain value must also be scaled accordingly as the sampling rate is increased. Two sets of values are provided which reflect the theoretical values, and the second set given in parentheses are empirical maximum values determined while monitoring shoulder performance (measured at $970$kHz offset from the centre frequency) using a spectrum analyser in $\approx 3$ kHz resolution bandwidth. The digital gain figures for the tested sampling rates are shown below: \begin{center} \begin{tabular}{| l | c | c |} \hline Rate & Dgain & Max Dgain (Empirical) \\ \hline \hline $4096$ksps & $2.0$ & $2.25$ \\ \hline $6144$ksps & $3.0$ & $3.37$ \\ \hline $8192$ksps & $4.0$ & $4.50$ \\ \hline \end{tabular} \end{center} The shoulder performance has been measured with shoulder performance at a little better than $35$dB, which is roughly equivalent to that obtained from first generation commercial modulator equipment. This can be increased to a relatively respectable $\approx 40$dB by enabling the FIR baseband filter in ODR-DabMod, and supplying it with an appropriate coefficient (tap) file. The maximum output power available to meet these performance figures is approximately $-10$dBm RMS. Example of using ODR-DabMod with the \texttt{hackrf\_transfer} utility: \begin{lstlisting} mkfifo /tmp/ofdm.fifo odr-dabmod mod.ini & hackrf_transfer -t /tmp/ofdm.fifo -f 216928000 -x 47 \ -a 1 -s 4096000 -b 1750000 \end{lstlisting} \subsection{Advanced Signal Processing} \subsubsection{Crest Factor Reduction} ODR-DabMod contains a prototype for crest factor reduction (CFR), which allows you to reduce peak-to-average power ratio (PAPR), trading off with modulation error rate (MER). The DAB OFDM signal has a very high PAPR, which directly translates to a decrease in power amplifier efficiency. The power amplifier has to be driven such that the peaks do not drive it into compression, but the overall efficiency is calculated from the average power. Reducing the PAPR makes it possible to drive the amplifier more. The CFR algorithm works in the following way: all the generated OFDM samples go through a limiter, which clips the amplitude to a configurable value. This directly reduces PAPR, but impacts both amplitude and phase of the constellation points, thereby degrading MER. To compensate for this, a second step of the algorithm calculates the error vector for each constellation point, and clips the error to some maximum amplitude. The clipped error is then subtracted from the signal, which corrects part of the distortion created by the limiter. To summarise: a low clipping value distorts the signal more; a high error clipping value corrects the distortion again. In the constellation plot view, the first is seen as an increase in spread of the points; the second is visible because it pulls the constellation points back into a circle of radius proportional to the error clipping value. Settings and some statistics are available through the remote control. \subsubsection{Digital Pre-Distortion} An ongoing activity is the development of a method to characterise a power amplifier and predistort the I/Q samples to invert the distortion behaviour of the amplifier. More information about this work is in the \verb+dpd/README.md+ file in ODR-DabMod. \subsection{Audio Sources} Preparing a DAB multiplex with different programmes requires that we are able to read and encode several audio sources. We have seen in section~\ref{sec:between_encoder_and_multiplexer} how the encoders can be interfaced to the modulator. In this section we'll go through the different ways to carry the audio data to the encoder. \subsubsection{Local Audio Card} It is possible to use an audio card connected to the computer as source. For very simple scenarios, the ALSA input for ODR-AudioEnc is easiest to set up. This however limits the usage of a single encoder per sound-card, and will not scale well if more than one programme has to be encoded on the machine. It is however ideal for dedicated encoding machines that can contribute the encoded audio over an IP network. An alternative to using ALSA is JACK\footnote{The JACK Audio Connection Kit is a virtual audio patch, \url{http://www.jack-audio.org}} that can be used with a multi-channel sound card. JACK will expose every audio input channel, and several encoders can be launched that also connect to JACK. The input channels can be freely connected to the encoders thanks to the virtual JACK patch panel. \sidenote{It might be possible to use the libVLC input too, to be defined.} \subsubsection{Using Existing Web-Streams} \label{usingexistingwebstreams} One common scenario is to transmit radio stations that already are available as web-radio streams. For simplicity, it makes sense to get these web streams, which are most often encoded in mp3 and available through HTTP, decode them, and use them as audio source for the DAB or \dabplus encoder. The advantage of this approach is that the radio itself does not need to setup a new infrastructure if the stream is of good quality. The main disadvantage is that the audio is encoded twice, and this coding cascading degrades the audio quality. Often, web-streams are encoded in mp3 at $44100\Hz$ sample-rate, whereas DAB is most often $48000\Hz$ or sometimes $32000\Hz$. A sample-rate conversion is necessary in the stream decoder. There are many different stream decoders, and gstreamer, mpg123 and mplayer have been tested. By far the easiest way is to use the libVLC binding that can be compiled for ODR-AudioEnc. This library has the same features as the VLC audio player, but the audio data is directly passed to the encoding routines. This allows the encoder to receive all network sources VLC supports, not only HTTP web-streams but also less common setups e.g.\ encoded audio inside multicast UDP MPEG-TS. This is illustrated in Studio A'' in figure~\ref{fig:txchain-with-encoders}. We have also achieved good results with mplayer, and the dab-scripts repository\footnote{\url{http://github.com/Opendigitalradio/dab-scripts}} contains the script \texttt{encode-jack.sh} that uses mplayer, and illustrates how it is possible to encode a web-stream to \dabplus. JACK is used to interconnect the stream decoder to the \dabplus encoder. This is illustrated in Studio B''. \begin{figure}[h] \includegraphics[width=\textwidth]{figures/txchain-with-encoders.pdf} \caption{Three common ways to encode a remote audio sources.} \label{fig:txchain-with-encoders} \end{figure} The scripts are designed for production use, and also contain automatic restart logic in case of a failure. They send an email and write a message into the system log. \subsubsection{Encoders at Programme Originator Studios} In order to avoid the unavoidable encoder cascading when using mp3 web-streams, the DAB or \dabplus encoder has to be moved to the programme originator's premises, and should directly encode the audio signal coming from the studios. This is illustrated in Studio C'' in figure~\ref{fig:txchain-with-encoders}. If Studio C'' is able to prepare slides for MOT Slideshow and text to be sent as DLS, ODR-PadEnc can be used to prepare the PAD data for ODR-AudioEnc. % vim: spl=en spell tw=80 et