diff options
Diffstat (limited to 'src')
38 files changed, 471 insertions, 234 deletions
diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 8631c42..3f6f296 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -28,48 +28,72 @@ #include "Buffer.h" #include "PcDebug.h" +#include <string> #include <stdlib.h> #include <string.h> -#include <malloc.h> -#if HAVE_DECL__MM_MALLOC -# include <mm_malloc.h> -#else -# define memalign(a, b) malloc(b) -#endif - - Buffer::Buffer(size_t len, const void *data) { PDEBUG("Buffer::Buffer(%zu, %p)\n", len, data); - this->len = 0; - this->size = 0; - this->data = NULL; + m_len = 0; + m_capacity = 0; + m_data = nullptr; setData(data, len); } +Buffer::Buffer(const Buffer& other) +{ + setData(other.m_data, other.m_len); +} + +Buffer::Buffer(Buffer&& other) +{ + m_len = other.m_len; + m_capacity = other.m_capacity; + m_data = other.m_data; + + other.m_len = 0; + other.m_capacity = 0; + other.m_data = nullptr; +} + Buffer::Buffer(const std::vector<uint8_t> &vec) { PDEBUG("Buffer::Buffer(vector [%zu])\n", vec.size()); - this->len = 0; - this->size = 0; - this->data = NULL; + m_len = 0; + m_capacity = 0; + m_data = nullptr; setData(vec.data(), vec.size()); } Buffer::~Buffer() { - PDEBUG("Buffer::~Buffer() len=%zu, data=%p\n", len, data); - free(data); + PDEBUG("Buffer::~Buffer() len=%zu, data=%p\n", m_len, m_data); + if (m_data) { + free(m_data); + } } Buffer &Buffer::operator=(const Buffer ©) { - setData(copy.data, copy.len); + setData(copy.m_data, copy.m_len); + return *this; +} + +Buffer& Buffer::operator=(Buffer&& other) +{ + m_len = other.m_len; + m_capacity = other.m_capacity; + m_data = other.m_data; + + other.m_len = 0; + other.m_capacity = 0; + other.m_data = nullptr; + return *this; } @@ -81,26 +105,30 @@ Buffer &Buffer::operator=(const std::vector<uint8_t> ©) Buffer &Buffer::operator+=(const Buffer ©) { - appendData(copy.data, copy.len); + appendData(copy.m_data, copy.m_len); return *this; } void Buffer::setLength(size_t len) { - if (len > size) { - void *tmp = data; + if (len > m_capacity) { + void *tmp = m_data; /* Align to 32-byte boundary for AVX. */ - data = memalign(32, len); + const int ret = posix_memalign(&m_data, 32, len); + if (ret != 0) { + throw std::runtime_error("memory allocation failed: " + + std::to_string(ret)); + } - if (tmp != NULL) { - memcpy(data, tmp, this->len); + if (tmp != nullptr) { + memcpy(m_data, tmp, m_len); free(tmp); } - size = len; + m_capacity = len; } - this->len = len; + m_len = len; } @@ -113,10 +141,10 @@ void Buffer::setData(const void *data, size_t len) void Buffer::appendData(const void *data, size_t len) { - size_t offset = this->len; - setLength(this->len + len); - if (data != NULL) { - memcpy((char*)this->data + offset, data, len); + size_t offset = m_len; + setLength(m_len + len); + if (data != nullptr) { + memcpy((char*)m_data + offset, data, len); } } diff --git a/src/Buffer.h b/src/Buffer.h index 8c5c768..88bd442 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2017 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org @@ -41,24 +41,13 @@ * The allocation/freeing of the data is handled internally. */ class Buffer { - protected: - /* Current length of the data in the Buffer */ - size_t len; - - /* Allocated size of the Buffer */ - size_t size; - - /* Pointer to the data. Memory allocation is entirely - * handled by setLength. - */ - void *data; - public: using sptr = std::shared_ptr<Buffer>; - Buffer(const Buffer& copy) = default; - Buffer(const std::vector<uint8_t> &vec); - Buffer(size_t len = 0, const void *data = NULL); + Buffer(size_t len = 0, const void *data = nullptr); + Buffer(const Buffer& copy); + Buffer(Buffer&& other); + Buffer(const std::vector<uint8_t>& vec); ~Buffer(); /* Resize the buffer, reallocate memory if needed */ @@ -68,16 +57,29 @@ class Buffer { * Reallocates memory if needed. */ void setData(const void *data, size_t len); - Buffer &operator=(const Buffer ©); - Buffer &operator=(const std::vector<uint8_t> ©); + Buffer& operator=(const Buffer& copy); + Buffer& operator=(Buffer&& other); + Buffer& operator=(const std::vector<uint8_t>& copy); /* Concatenate the current data with the new data given. * Reallocates memory if needed. */ void appendData(const void *data, size_t len); - Buffer &operator+=(const Buffer ©); + Buffer& operator+=(const Buffer& copy); + + size_t getLength() const { return m_len; } + void* getData() const { return m_data; } + + private: + /* Current length of the data in the Buffer */ + size_t m_len; + + /* Allocated size of the Buffer */ + size_t m_capacity; + + /* Pointer to the data. Memory allocation is entirely + * handled by setLength. */ + void *m_data; - size_t getLength() const { return len; } - void *getData() const { return data; } }; diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 8facec3..0e641c0 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -161,8 +161,12 @@ static void parse_configfile( mod_settings.dabMode = pt.get("modulator.mode", mod_settings.dabMode); mod_settings.clockRate = pt.get("modulator.dac_clk_rate", (size_t)0); - mod_settings.digitalgain = pt.get("modulator.digital_gain", mod_settings.digitalgain); + mod_settings.digitalgain = pt.get("modulator.digital_gain", + mod_settings.digitalgain); + mod_settings.outputRate = pt.get("modulator.rate", mod_settings.outputRate); + mod_settings.ofdmWindowOverlap = pt.get("modulator.ofdmwindowing", + mod_settings.ofdmWindowOverlap); // FIR Filter parameters: if (pt.get("firfilter.enabled", 0) == 1) { diff --git a/src/ConfigParser.h b/src/ConfigParser.h index dd6c040..3f64883 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -79,6 +79,9 @@ struct mod_settings_t { float cfrClip = 1.0f; float cfrErrorClip = 1.0f; + // Settings for the OFDM windowing + unsigned ofdmWindowOverlap = 0; + #if defined(HAVE_OUTPUT_UHD) || defined(HAVE_SOAPYSDR) Output::SDRDeviceConfig sdr_device_config; #endif diff --git a/src/ConvEncoder.cpp b/src/ConvEncoder.cpp index 06b2e85..074898f 100644 --- a/src/ConvEncoder.cpp +++ b/src/ConvEncoder.cpp @@ -25,6 +25,7 @@ #include <stdlib.h> #include <stdio.h> #include <stdexcept> +#include <string> const static uint8_t PARITY[] = { diff --git a/src/DabMod.cpp b/src/DabMod.cpp index d29b489..4961910 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -36,6 +36,7 @@ #include "InputMemory.h" #include "OutputFile.h" #include "FormatConverter.h" +#include "FrameMultiplexer.h" #include "output/SDR.h" #include "output/UHD.h" #include "output/Soapy.h" @@ -61,13 +62,6 @@ # include <netinet/in.h> #endif -#if HAVE_DECL__MM_MALLOC -# include <mm_malloc.h> -#else -# define memalign(a, b) malloc(b) -#endif - - /* UHD requires the input I and Q samples to be in the interval * [-1.0,1.0], otherwise they get truncated, which creates very * wide-spectrum spikes. Depending on the Transmission Mode, the @@ -203,6 +197,10 @@ static shared_ptr<ModOutput> prepare_output( output = make_shared<OutputFile>(s.outputName); } + else { + throw runtime_error("File output format " + s.fileOutputFormat + + " not known"); + } } #if defined(HAVE_OUTPUT_UHD) else if (s.useUHDOutput) { @@ -451,7 +449,7 @@ int launch_modulator(int argc, char* argv[]) } } #if defined(HAVE_ZEROMQ) - else if (auto in = dynamic_pointer_cast<InputZeroMQReader>(inputReader)) { + else if (dynamic_pointer_cast<InputZeroMQReader>(inputReader)) { run_again = true; // Create a new input reader auto inputZeroMQReader = make_shared<InputZeroMQReader>(); @@ -459,7 +457,8 @@ int launch_modulator(int argc, char* argv[]) inputReader = inputZeroMQReader; } #endif - else if (auto in = dynamic_pointer_cast<InputTcpReader>(inputReader)) { + else if (dynamic_pointer_cast<InputTcpReader>(inputReader)) { + // Create a new input reader auto inputTcpReader = make_shared<InputTcpReader>(); inputTcpReader->Open(mod_settings.inputName); inputReader = inputTcpReader; @@ -535,17 +534,19 @@ run_modulator_state_t run_modulator(modulator_data& m) running = 0; ret = run_modulator_state_t::normal_end; } - } catch (zmq_input_overflow& e) { + } + catch (const zmq_input_overflow& e) { // The ZeroMQ input has overflowed its buffer etiLog.level(warn) << e.what(); ret = run_modulator_state_t::again; - } catch (std::out_of_range& e) { - // One of the DSP blocks has detected an invalid change - // or value in some settings. This can be due to a multiplex - // reconfiguration. + } + catch (const FrameMultiplexerError& e) { + // The FrameMultiplexer saw an error or a change in the size of a + // subchannel. This can be due to a multiplex reconfiguration. etiLog.level(warn) << e.what(); ret = run_modulator_state_t::reconfigure; - } catch (std::exception& e) { + } + catch (const std::exception& e) { etiLog.level(error) << "Exception caught: " << e.what(); ret = run_modulator_state_t::failure; } diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 2bd33b4..1ea06de 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -62,8 +62,7 @@ DabModulator::DabModulator(EtiSource& etiSource, myEtiSource(etiSource), myFlowgraph() { - PDEBUG("DabModulator::DabModulator(%u, %u, %u, %zu) @ %p\n", - outputRate, clockRate, dabMode, (size_t)gainMode, this); + PDEBUG("DabModulator::DabModulator() @ %p\n", this); if (m_settings.dabMode == 0) { setMode(2); @@ -205,7 +204,9 @@ int DabModulator::process(Buffer* dataOut) rcs.enrol(cifGain.get()); auto cifGuard = make_shared<GuardIntervalInserter>( - myNbSymbols, mySpacing, myNullSize, mySymSize); + myNbSymbols, mySpacing, myNullSize, mySymSize, + m_settings.ofdmWindowOverlap); + rcs.enrol(cifGuard.get()); shared_ptr<FIRFilter> cifFilter; if (not m_settings.filterTapsFilename.empty()) { diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index 0b27126..d84ed1f 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -58,7 +58,6 @@ EtiReader::EtiReader( unsigned tist_delay_stages) : state(EtiReaderStateSync), myTimestampDecoder(tist_offset_s, tist_delay_stages), - myCurrentFrame(0), eti_fc_valid(false) { rcs.enrol(&myTimestampDecoder); @@ -208,8 +207,8 @@ int EtiReader::loadEtiData(const Buffer& dataIn) if (input_size < 128) { return dataIn.getLength() - input_size; } - PDEBUG("Writting 128 bytes of FIC channel data\n"); - Buffer fic = Buffer(128, in); + PDEBUG("Writing 128 bytes of FIC channel data\n"); + Buffer fic(128, in); myFicSource->loadFicData(fic); input_size -= 128; framesize -= 128; @@ -218,8 +217,8 @@ int EtiReader::loadEtiData(const Buffer& dataIn) if (input_size < 96) { return dataIn.getLength() - input_size; } - PDEBUG("Writting 96 bytes of FIC channel data\n"); - Buffer fic = Buffer(96, in); + PDEBUG("Writing 96 bytes of FIC channel data\n"); + Buffer fic(96, in); myFicSource->loadFicData(fic); input_size -= 96; framesize -= 96; @@ -231,7 +230,7 @@ int EtiReader::loadEtiData(const Buffer& dataIn) for (size_t i = 0; i < eti_stc.size(); ++i) { unsigned size = mySources[i]->framesize(); PDEBUG("Writting %i bytes of subchannel data\n", size); - Buffer subch = Buffer(size, in); + Buffer subch(size, in); mySources[i]->loadSubchannelData(subch); input_size -= size; framesize -= size; diff --git a/src/EtiReader.h b/src/EtiReader.h index 892afb4..f3a9764 100644 --- a/src/EtiReader.h +++ b/src/EtiReader.h @@ -107,7 +107,6 @@ private: eti_TIST eti_tist; TimestampDecoder myTimestampDecoder; - size_t myCurrentFrame; bool eti_fc_valid; std::vector<std::shared_ptr<SubchannelSource> > mySources; diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp index 4296822..bc2314a 100644 --- a/src/FIRFilter.cpp +++ b/src/FIRFilter.cpp @@ -119,7 +119,7 @@ void FIRFilter::load_filter_taps(const std::string &tapsFile) int n; for (n = 0; n < n_taps; n++) { taps_fstream >> filter_taps[n]; - PDEBUG("FIRFilter: tap: %f\n", filter_taps[n] ); + PDEBUG("FIRFilter: tap: %f\n", (double)filter_taps[n] ); if (taps_fstream.eof()) { fprintf(stderr, "FIRFilter: file %s should contains %d taps, but EOF reached "\ "after %d taps !\n", tapsFile.c_str(), n_taps, n); @@ -306,9 +306,6 @@ int FIRFilter::internal_process(Buffer* const dataIn, Buffer* dataOut) void FIRFilter::set_parameter(const string& parameter, const string& value) { - stringstream ss(value); - ss.exceptions ( stringstream::failbit | stringstream::badbit ); - if (parameter == "ntaps") { throw ParameterError("Parameter 'ntaps' is read-only"); } diff --git a/src/FicSource.cpp b/src/FicSource.cpp index 92932ec..04197db 100644 --- a/src/FicSource.cpp +++ b/src/FicSource.cpp @@ -28,6 +28,7 @@ #include "PcDebug.h" #include <stdexcept> +#include <string> #include <sys/types.h> #include <stdlib.h> #include <string.h> diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp index 6ee7b81..465ef41 100644 --- a/src/Flowgraph.cpp +++ b/src/Flowgraph.cpp @@ -26,15 +26,10 @@ #include "Flowgraph.h" #include "PcDebug.h" +#include <string> #include <memory> #include <algorithm> #include <sstream> - -#if HAVE_DECL__MM_MALLOC -# include <mm_malloc.h> -#else -# define memalign(a, b) malloc(b) -#endif #include <sys/types.h> #include <stdexcept> #include <assert.h> diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp index 6826972..60c0545 100644 --- a/src/FormatConverter.cpp +++ b/src/FormatConverter.cpp @@ -29,7 +29,6 @@ #include "FormatConverter.h" #include "PcDebug.h" -#include <malloc.h> #include <sys/types.h> #include <string.h> #include <stdexcept> diff --git a/src/FrameMultiplexer.cpp b/src/FrameMultiplexer.cpp index 1cfaadd..5dc6dca 100644 --- a/src/FrameMultiplexer.cpp +++ b/src/FrameMultiplexer.cpp @@ -28,6 +28,7 @@ #include "PcDebug.h" #include <stdio.h> +#include <string> #include <stdexcept> #include <complex> #include <memory> @@ -73,7 +74,7 @@ int FrameMultiplexer::process(std::vector<Buffer*> dataIn, Buffer* dataOut) // Write subchannel const auto subchannels = m_etiSource.getSubchannels(); if (subchannels.size() != dataIn.size() - 1) { - throw std::out_of_range( + throw FrameMultiplexerError( "FrameMultiplexer detected subchannel size change from " + std::to_string(dataIn.size() - 1) + " to " + std::to_string(subchannels.size())); @@ -81,7 +82,7 @@ int FrameMultiplexer::process(std::vector<Buffer*> dataIn, Buffer* dataOut) auto subchannel = subchannels.begin(); while (in != dataIn.end()) { if ((*subchannel)->framesizeCu() * 8 != (*in)->getLength()) { - throw std::out_of_range( + throw FrameMultiplexerError( "FrameMultiplexer detected invalid subchannel size! " + std::to_string((*subchannel)->framesizeCu() * 8) + " != " + std::to_string((*in)->getLength())); diff --git a/src/FrameMultiplexer.h b/src/FrameMultiplexer.h index 680cdc7..4d68d88 100644 --- a/src/FrameMultiplexer.h +++ b/src/FrameMultiplexer.h @@ -38,12 +38,18 @@ #include <sys/types.h> +class FrameMultiplexerError : public std::runtime_error { + public: + FrameMultiplexerError(const char* msg) : + std::runtime_error(msg) {} + FrameMultiplexerError(const std::string& msg) : + std::runtime_error(msg) {} +}; class FrameMultiplexer : public ModMux { public: - FrameMultiplexer( - const EtiSource& etiSource); + FrameMultiplexer(const EtiSource& etiSource); int process(std::vector<Buffer*> dataIn, Buffer* dataOut); const char* name() { return "FrameMultiplexer"; } diff --git a/src/FrequencyInterleaver.cpp b/src/FrequencyInterleaver.cpp index 29d54bb..e76d525 100644 --- a/src/FrequencyInterleaver.cpp +++ b/src/FrequencyInterleaver.cpp @@ -24,7 +24,8 @@ #include <stdio.h> #include <stdexcept> -#include <malloc.h> +#include <string> +#include <stdlib.h> #include <complex> typedef std::complex<float> complexf; @@ -68,7 +69,11 @@ FrequencyInterleaver::FrequencyInterleaver(size_t mode) : break; } - d_indexes = (size_t*)memalign(16, d_carriers * sizeof(size_t)); + const int ret = posix_memalign((void**)(&d_indexes), 16, d_carriers * sizeof(size_t)); + if (ret != 0) { + throw std::runtime_error("memory allocation failed: " + std::to_string(ret)); + } + size_t* index = d_indexes; size_t perm = 0; PDEBUG("i: %4u, R: %4u\n", 0, 0); diff --git a/src/GainControl.cpp b/src/GainControl.cpp index 2a91b12..0411482 100644 --- a/src/GainControl.cpp +++ b/src/GainControl.cpp @@ -46,7 +46,7 @@ using namespace std; static float var_variance; GainControl::GainControl(size_t framesize, - GainMode mode, + GainMode gainMode, float digGain, float normalise, float varVariance) : @@ -60,10 +60,10 @@ GainControl::GainControl(size_t framesize, m_digGain(digGain), m_normalise(normalise), m_var_variance_rc(varVariance), - m_gainmode(mode), + m_gainmode(gainMode), m_mutex() { - PDEBUG("GainControl::GainControl(%zu, %zu) @ %p\n", framesize, (size_t)mode, this); + PDEBUG("GainControl::GainControl(%zu, %zu) @ %p\n", framesize, (size_t)m_gainmode, this); /* register the parameters that can be remote controlled */ RC_ADD_PARAMETER(digital, "Digital Gain"); @@ -532,10 +532,10 @@ void GainControl::set_parameter(const string& parameter, const string& value) } } else { - stringstream ss; - ss << "Parameter '" << parameter + stringstream ss_err; + ss_err << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name(); - throw ParameterError(ss.str()); + throw ParameterError(ss_err.str()); } } diff --git a/src/GainControl.h b/src/GainControl.h index 44c9fa9..e9eaa8c 100644 --- a/src/GainControl.h +++ b/src/GainControl.h @@ -51,7 +51,7 @@ class GainControl : public PipelinedModCodec, public RemoteControllable { public: GainControl(size_t framesize, - GainMode mode, + GainMode gainMode, float digGain, float normalise, float varVariance); diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp index 80ba900..14027d3 100644 --- a/src/GuardIntervalInserter.cpp +++ b/src/GuardIntervalInserter.cpp @@ -1,6 +1,11 @@ /* Copyright (C) 2005, 2206, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) + + Copyright (C) 2017 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://opendigitalradio.org */ /* This file is part of ODR-DabMod. @@ -21,57 +26,101 @@ #include "GuardIntervalInserter.h" #include "PcDebug.h" - - -#include <sys/types.h> #include <string.h> #include <stdexcept> #include <complex> +#include <mutex> typedef std::complex<float> complexf; - -GuardIntervalInserter::GuardIntervalInserter(size_t nbSymbols, +GuardIntervalInserter::GuardIntervalInserter( + size_t nbSymbols, size_t spacing, size_t nullSize, - size_t symSize) : + size_t symSize, + size_t windowOverlap) : ModCodec(), + RemoteControllable("guardinterval"), d_nbSymbols(nbSymbols), d_spacing(spacing), d_nullSize(nullSize), - d_symSize(symSize) + d_symSize(symSize), + d_windowOverlap(0) { - PDEBUG("GuardIntervalInserter::GuardIntervalInserter(%zu, %zu, %zu, %zu)" - " @ %p\n", nbSymbols, spacing, nullSize, symSize, this); - - if (d_nullSize) { - myHasNull = true; - } else { - myHasNull = false; + if (d_nullSize == 0) { + throw std::logic_error("NULL symbol must be present"); } -} + RC_ADD_PARAMETER(windowlen, "Window length for OFDM windowng [0 to disable]"); + + /* We use a raised-cosine window for the OFDM windowing. + * Each symbol is extended on both sides by d_windowOverlap samples. + * + * + * Sym n |####################| + * Sym n+1 |####################| + * + * We now extend the symbols by d_windowOverlap (one dash) + * + * Sym n extended -|####################|- + * Sym n+1 extended -|####################|- + * + * The windows are raised-cosine: + * ____________________ + * Sym n window / \ + * ... ____/ \___________ ... + * + * Sym n+1 window ____________________ + * / \ + * ... ________________/ \__ ... + * + * The window length is 2*d_windowOverlap. + */ + + update_window(windowOverlap); -GuardIntervalInserter::~GuardIntervalInserter() + PDEBUG("GuardIntervalInserter::GuardIntervalInserter" + "(%zu, %zu, %zu, %zu, %zu) @ %p\n", + nbSymbols, spacing, nullSize, symSize, windowOverlap, this); +} + +void GuardIntervalInserter::update_window(size_t new_window_overlap) { - PDEBUG("GuardIntervalInserter::~GuardIntervalInserter() @ %p\n", this); + std::lock_guard<std::mutex> lock(d_windowMutex); + + d_windowOverlap = new_window_overlap; + // d_window only contains the rising window edge. + d_window.resize(2*d_windowOverlap); + for (size_t i = 0; i < 2*d_windowOverlap; i++) { + d_window[i] = (float)(0.5 * (1.0 - cos(M_PI * i / (2*d_windowOverlap - 1)))); + } } +#pragma GCC optimize ("O0") int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut) { PDEBUG("GuardIntervalInserter::process(dataIn: %p, dataOut: %p)\n", dataIn, dataOut); - dataOut->setLength((d_nullSize + (d_nbSymbols * d_symSize)) - * sizeof(complexf)); + std::lock_guard<std::mutex> lock(d_windowMutex); + + // Every symbol overlaps over a length of d_windowOverlap with + // the previous symbol, and with the next symbol. First symbol + // receives no prefix window, because we don't remember the + // last symbol from the previous TF (yet). Last symbol also + // receives no suffix window, for the same reason. + // Overall output buffer length must stay independent of the windowing. + dataOut->setLength((d_nullSize + (d_nbSymbols * d_symSize)) * sizeof(complexf)); const complexf* in = reinterpret_cast<const complexf*>(dataIn->getData()); complexf* out = reinterpret_cast<complexf*>(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(complexf); - if (sizeIn != (d_nbSymbols + (myHasNull ? 1 : 0)) * d_spacing) { + const size_t num_symbols = d_nbSymbols + 1; + if (sizeIn != num_symbols * d_spacing) + { PDEBUG("Nb symbols: %zu\n", d_nbSymbols); PDEBUG("Spacing: %zu\n", d_spacing); PDEBUG("Null size: %zu\n", d_nullSize); @@ -81,24 +130,176 @@ int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut) "GuardIntervalInserter::process input size not valid!"); } - // Null symbol - if (myHasNull) { + // TODO remember the end of the last TF so that we can do some + // windowing too. + + if (d_windowOverlap) { + { + // Handle Null symbol separately because it is longer + const size_t prefixlength = d_nullSize - d_spacing; + + // end = spacing + memcpy(out, &in[d_spacing - prefixlength], + prefixlength * sizeof(complexf)); + + memcpy(&out[prefixlength], in, (d_spacing - d_windowOverlap) * sizeof(complexf)); + + // The remaining part of the symbol must have half of the window applied, + // sloping down from 1 to 0.5 + for (size_t i = 0; i < d_windowOverlap; i++) { + const size_t out_ix = prefixlength + d_spacing - d_windowOverlap + i; + const size_t in_ix = d_spacing - d_windowOverlap + i; + out[out_ix] = in[in_ix] * d_window[2*d_windowOverlap - (i+1)]; + } + + // Suffix is taken from the beginning of the symbol, and sees the other + // half of the window applied. + for (size_t i = 0; i < d_windowOverlap; i++) { + const size_t out_ix = prefixlength + d_spacing + i; + out[out_ix] = in[i] * d_window[d_windowOverlap - (i+1)]; + } + + in += d_spacing; + out += d_nullSize; + // out is now pointing to the proper end of symbol. There are + // d_windowOverlap samples ahead that were already written. + } + + // Data symbols + for (size_t sym_ix = 0; sym_ix < d_nbSymbols; sym_ix++) { + /* _ix variables are indices into in[], _ox variables are + * indices for out[] */ + const ssize_t start_rise_ox = -d_windowOverlap; + const size_t start_rise_ix = 2 * d_spacing - d_symSize - d_windowOverlap; + /* + const size_t start_real_symbol_ox = 0; + const size_t start_real_symbol_ix = 2 * d_spacing - d_symSize; + */ + const ssize_t end_rise_ox = d_windowOverlap; + const size_t end_rise_ix = 2 * d_spacing - d_symSize + d_windowOverlap; + const ssize_t end_cyclic_prefix_ox = d_symSize - d_spacing; + /* end_cyclic_prefix_ix = end of symbol + const size_t begin_fall_ox = d_symSize - d_windowOverlap; + const size_t begin_fall_ix = d_spacing - d_windowOverlap; + const size_t end_real_symbol_ox = d_symSize; + end_real_symbol_ix = end of symbol + const size_t end_fall_ox = d_symSize + d_windowOverlap; + const size_t end_fall_ix = d_spacing + d_windowOverlap; + */ + + ssize_t ox = start_rise_ox; + size_t ix = start_rise_ix; + + for (size_t i = 0; ix < end_rise_ix; i++) { + out[ox] += in[ix] * d_window.at(i); + ix++; + ox++; + } + assert(ox == end_rise_ox); + + const size_t remaining_prefix_length = end_cyclic_prefix_ox - end_rise_ox; + memcpy( &out[ox], &in[ix], + remaining_prefix_length * sizeof(complexf)); + ox += remaining_prefix_length; + assert(ox = end_cyclic_prefix_ox); + ix = 0; + + const bool last_symbol = (sym_ix + 1 >= d_nbSymbols); + if (last_symbol) { + // No windowing at all at end + memcpy(&out[ox], &in[ix], d_spacing * sizeof(complexf)); + ox += d_spacing; + } + else { + // Copy the middle part of the symbol, d_windowOverlap samples + // short of the end. + memcpy( &out[ox], + &in[ix], + (d_spacing - d_windowOverlap) * sizeof(complexf)); + ox += d_spacing - d_windowOverlap; + ix += d_spacing - d_windowOverlap; + assert(ox == (ssize_t)(d_symSize - d_windowOverlap)); + + // Apply window from 1 to 0.5 for the end of the symbol + for (size_t i = 0; ox < (ssize_t)d_symSize; i++) { + out[ox] = in[ix] * d_window[2*d_windowOverlap - (i+1)]; + ox++; + ix++; + } + assert(ix == d_spacing); + + ix = 0; + // Cyclic suffix, with window from 0.5 to 0 + for (size_t i = 0; ox < (ssize_t)(d_symSize + d_windowOverlap); i++) { + out[ox] = in[ix] * d_window[d_windowOverlap - (i+1)]; + ox++; + ix++; + } + + assert(ix == d_windowOverlap); + } + + out += d_symSize; + in += d_spacing; + // out is now pointing to the proper end of symbol. There are + // d_windowOverlap samples ahead that were already written. + } + } + else { + // Handle Null symbol separately because it is longer // end - (nullSize - spacing) = 2 * spacing - nullSize memcpy(out, &in[2 * d_spacing - d_nullSize], (d_nullSize - d_spacing) * sizeof(complexf)); memcpy(&out[d_nullSize - d_spacing], in, d_spacing * sizeof(complexf)); in += d_spacing; out += d_nullSize; - } - // Data symbols - for (size_t i = 0; i < d_nbSymbols; ++i) { - // end - (nullSize - spacing) = 2 * spacing - nullSize - memcpy(out, &in[2 * d_spacing - d_symSize], - (d_symSize - d_spacing) * sizeof(complexf)); - memcpy(&out[d_symSize - d_spacing], in, d_spacing * sizeof(complexf)); - in += d_spacing; - out += d_symSize; + + // Data symbols + for (size_t i = 0; i < d_nbSymbols; ++i) { + // end - (symSize - spacing) = 2 * spacing - symSize + memcpy(out, &in[2 * d_spacing - d_symSize], + (d_symSize - d_spacing) * sizeof(complexf)); + memcpy(&out[d_symSize - d_spacing], in, d_spacing * sizeof(complexf)); + in += d_spacing; + out += d_symSize; + } } return sizeIn; } + +void GuardIntervalInserter::set_parameter( + const std::string& parameter, + const std::string& value) +{ + using namespace std; + stringstream ss(value); + ss.exceptions ( stringstream::failbit | stringstream::badbit ); + + if (parameter == "windowlen") { + size_t new_window_overlap = 0; + ss >> new_window_overlap; + update_window(new_window_overlap); + } + else { + stringstream ss_err; + ss_err << "Parameter '" << parameter << + "' is not exported by controllable " << get_rc_name(); + throw ParameterError(ss_err.str()); + } +} + +const std::string GuardIntervalInserter::get_parameter(const std::string& parameter) const +{ + using namespace std; + stringstream ss; + if (parameter == "windowlen") { + ss << d_windowOverlap; + } + else { + ss << "Parameter '" << parameter << + "' is not exported by controllable " << get_rc_name(); + throw ParameterError(ss.str()); + } + return ss.str(); +} diff --git a/src/GuardIntervalInserter.h b/src/GuardIntervalInserter.h index 70a8fcd..7714c1a 100644 --- a/src/GuardIntervalInserter.h +++ b/src/GuardIntervalInserter.h @@ -1,6 +1,11 @@ /* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) + + Copyright (C) 2017 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://opendigitalradio.org */ /* This file is part of ODR-DabMod. @@ -25,29 +30,48 @@ # include <config.h> #endif - #include "ModPlugin.h" +#include "RemoteControl.h" +#include <stdint.h> +#include <vector> -#include <sys/types.h> +/* The GuardIntervalInserter prepends the cyclic prefix to all + * symbols in the transmission frame. + * + * If windowOverlap is non-zero, it will also add a cyclic suffix of + * that length, enlarge the cyclic prefix too, and make symbols + * overlap using a raised cosine window. + * */ +class GuardIntervalInserter : public ModCodec, public RemoteControllable +{ + public: + GuardIntervalInserter( + size_t nbSymbols, + size_t spacing, + size_t nullSize, + size_t symSize, + size_t windowOverlap = 0); + int process(Buffer* const dataIn, Buffer* dataOut); + const char* name() { return "GuardIntervalInserter"; } -class GuardIntervalInserter : public ModCodec -{ -public: - GuardIntervalInserter(size_t nbSymbols, size_t spacing, size_t nullSize, size_t symSize); - virtual ~GuardIntervalInserter(); - GuardIntervalInserter(const GuardIntervalInserter&); - GuardIntervalInserter& operator=(const GuardIntervalInserter&); - - - int process(Buffer* const dataIn, Buffer* dataOut); - const char* name() { return "GuardIntervalInserter"; } - -protected: - size_t d_nbSymbols; - size_t d_spacing; - size_t d_nullSize; - size_t d_symSize; - bool myHasNull; + /******* REMOTE CONTROL ********/ + virtual void set_parameter(const std::string& parameter, + const std::string& value); + + virtual const std::string get_parameter( + const std::string& parameter) const; + + protected: + void update_window(size_t new_window_overlap); + + size_t d_nbSymbols; + size_t d_spacing; + size_t d_nullSize; + size_t d_symSize; + + mutable std::mutex d_windowMutex; + size_t d_windowOverlap; + std::vector<float> d_window; }; diff --git a/src/MemlessPoly.cpp b/src/MemlessPoly.cpp index f223d34..ae097c9 100644 --- a/src/MemlessPoly.cpp +++ b/src/MemlessPoly.cpp @@ -38,7 +38,7 @@ #include <stdio.h> #include <stdexcept> - +#include <string> #include <future> #include <array> #include <iostream> @@ -370,9 +370,6 @@ int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut) void MemlessPoly::set_parameter(const string& parameter, const string& value) { - stringstream ss(value); - ss.exceptions ( stringstream::failbit | stringstream::badbit ); - if (parameter == "ncoefs") { throw ParameterError("Parameter 'ncoefs' is read-only"); } diff --git a/src/NullSymbol.cpp b/src/NullSymbol.cpp index 015e564..4684dfe 100644 --- a/src/NullSymbol.cpp +++ b/src/NullSymbol.cpp @@ -53,7 +53,7 @@ int NullSymbol::process(Buffer* dataOut) PDEBUG("NullSymbol::process(dataOut: %p)\n", dataOut); dataOut->setLength(myNbCarriers * 2 * sizeof(float)); - bzero(dataOut->getData(), dataOut->getLength()); + memset(dataOut->getData(), 0, dataOut->getLength()); return dataOut->getLength(); } diff --git a/src/OfdmGenerator.cpp b/src/OfdmGenerator.cpp index bac3db0..915d568 100644 --- a/src/OfdmGenerator.cpp +++ b/src/OfdmGenerator.cpp @@ -190,7 +190,7 @@ int OfdmGenerator::process(Buffer* const dataIn, Buffer* dataOut) myFftIn[0][0] = 0; myFftIn[0][1] = 0; - bzero(&myFftIn[myZeroDst], myZeroSize * sizeof(FFT_TYPE)); + memset(&myFftIn[myZeroDst], 0, myZeroSize * sizeof(FFT_TYPE)); memcpy(&myFftIn[myPosDst], &in[myPosSrc], myPosSize * sizeof(FFT_TYPE)); memcpy(&myFftIn[myNegDst], &in[myNegSrc], @@ -230,9 +230,9 @@ int OfdmGenerator::process(Buffer* const dataIn, Buffer* dataOut) */ double sum_iq = 0; double sum_delta = 0; - for (size_t i = 0; i < mySpacing; i++) { - sum_iq += (double)std::norm(before_cfr[i]); - sum_delta += (double)std::norm(symbol[i] - before_cfr[i]); + for (size_t j = 0; j < mySpacing; j++) { + sum_iq += (double)std::norm(before_cfr[j]); + sum_delta += (double)std::norm(symbol[j] - before_cfr[j]); } // Clamp to 90dB, otherwise the MER average is going to be inf @@ -362,10 +362,10 @@ void OfdmGenerator::set_parameter(const std::string& parameter, throw ParameterError("Parameter 'clip_stats' is read-only"); } else { - stringstream ss; - ss << "Parameter '" << parameter + stringstream ss_err; + ss_err << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name(); - throw ParameterError(ss.str()); + throw ParameterError(ss_err.str()); } } diff --git a/src/PrbsGenerator.cpp b/src/PrbsGenerator.cpp index 69d6af4..b159bd3 100644 --- a/src/PrbsGenerator.cpp +++ b/src/PrbsGenerator.cpp @@ -22,9 +22,10 @@ #include "PrbsGenerator.h" #include "PcDebug.h" +#include <stdexcept> +#include <string> #include <stdio.h> #include <stdlib.h> -#include <stdexcept> PrbsGenerator::PrbsGenerator(size_t framesize, uint32_t polynomial, @@ -178,8 +179,8 @@ int PrbsGenerator::process( throw std::runtime_error("PrbsGenerator::process " "input size is not equal to output size!\n"); } - for (size_t i = 0; i < dataOut[0]->getLength(); ++i) { - out[i] ^= in[i]; + for (size_t j = 0; j < dataOut[0]->getLength(); ++j) { + out[j] ^= in[j]; } } diff --git a/src/PrbsGenerator.h b/src/PrbsGenerator.h index b86bc70..9390179 100644 --- a/src/PrbsGenerator.h +++ b/src/PrbsGenerator.h @@ -53,8 +53,6 @@ private: unsigned char d_weight[256]; // PRBS polynomial generator uint32_t d_polynomial; - // PRBS generator polarity mask - unsigned char d_polarity_mask; // PRBS accumulator uint32_t d_accum; uint32_t d_accum_init; diff --git a/src/PuncturingEncoder.cpp b/src/PuncturingEncoder.cpp index 9bd9004..de4319b 100644 --- a/src/PuncturingEncoder.cpp +++ b/src/PuncturingEncoder.cpp @@ -27,6 +27,7 @@ #include "PuncturingEncoder.h" #include "PcDebug.h" +#include <string> #include <stdio.h> #include <stdexcept> #include <stdint.h> diff --git a/src/RemoteControl.cpp b/src/RemoteControl.cpp index ceae942..a050278 100644 --- a/src/RemoteControl.cpp +++ b/src/RemoteControl.cpp @@ -422,11 +422,11 @@ void RemoteControllerZmq::process() std::string msg_s = ss.str(); - zmq::message_t msg(ss.str().size()); - memcpy ((void*) msg.data(), msg_s.data(), msg_s.size()); + zmq::message_t zmsg(ss.str().size()); + memcpy ((void*) zmsg.data(), msg_s.data(), msg_s.size()); int flag = (--cohort_size > 0) ? ZMQ_SNDMORE : 0; - repSocket.send(msg, flag); + repSocket.send(zmsg, flag); } } else if (msg.size() == 2 && command == "show") { @@ -437,11 +437,11 @@ void RemoteControllerZmq::process() for (auto ¶m_val : r) { std::stringstream ss; ss << param_val[0] << ": " << param_val[1] << endl; - zmq::message_t msg(ss.str().size()); - memcpy(msg.data(), ss.str().data(), ss.str().size()); + zmq::message_t zmsg(ss.str().size()); + memcpy(zmsg.data(), ss.str().data(), ss.str().size()); int flag = (--r_size > 0) ? ZMQ_SNDMORE : 0; - repSocket.send(msg, flag); + repSocket.send(zmsg, flag); } } catch (ParameterError &e) { @@ -454,9 +454,9 @@ void RemoteControllerZmq::process() try { std::string value = rcs.get_param(module, parameter); - zmq::message_t msg(value.size()); - memcpy ((void*) msg.data(), value.data(), value.size()); - repSocket.send(msg, 0); + zmq::message_t zmsg(value.size()); + memcpy ((void*) zmsg.data(), value.data(), value.size()); + repSocket.send(zmsg, 0); } catch (ParameterError &err) { send_fail_reply(repSocket, err.what()); diff --git a/src/Resampler.cpp b/src/Resampler.cpp index 8069a61..42951c5 100644 --- a/src/Resampler.cpp +++ b/src/Resampler.cpp @@ -27,10 +27,11 @@ #include "Resampler.h" #include "PcDebug.h" -#include <malloc.h> +#include <string> +#include <stdexcept> +#include <stdlib.h> #include <sys/types.h> #include <string.h> -#include <stdexcept> #include <assert.h> #define FFT_REAL(x) x[0] @@ -81,7 +82,10 @@ Resampler::Resampler(size_t inputRate, size_t outputRate, size_t resolution) : myFactor = 1.0f / myFftSizeOut * outputRate / inputRate; } - myWindow = (float*)memalign(16, myFftSizeIn * sizeof(float)); + const int ret = posix_memalign((void**)(&myWindow), 16, myFftSizeIn * sizeof(float)); + if (ret != 0) { + throw std::runtime_error("memory allocation failed: " + std::to_string(ret)); + } for (size_t i = 0; i < myFftSizeIn; ++i) { myWindow[i] = (float)(0.5 * (1.0 - cos(2.0 * M_PI * i / (myFftSizeIn - 1)))); PDEBUG("Window[%zu] = %f\n", i, myWindow[i]); diff --git a/src/Socket.h b/src/Socket.h index f6a023d..39554ca 100644 --- a/src/Socket.h +++ b/src/Socket.h @@ -37,6 +37,7 @@ DESCRIPTION: #include <unistd.h> #include <cstdint> #include <stdexcept> +#include <string> #include <sys/socket.h> #include <netinet/ip.h> #include <errno.h> diff --git a/src/SubchannelSource.cpp b/src/SubchannelSource.cpp index 2a8dc37..b4d6750 100644 --- a/src/SubchannelSource.cpp +++ b/src/SubchannelSource.cpp @@ -28,6 +28,7 @@ #include "PcDebug.h" #include "Log.h" +#include <string> #include <stdexcept> #include <sys/types.h> #include <stdlib.h> diff --git a/src/TII.cpp b/src/TII.cpp index 4710ed4..446d9c6 100644 --- a/src/TII.cpp +++ b/src/TII.cpp @@ -190,17 +190,13 @@ int TII::process(Buffer* dataIn, Buffer* dataOut) } dataOut->setLength(m_carriers * sizeof(complexf)); - bzero(dataOut->getData(), dataOut->getLength()); + memset(dataOut->getData(), 0, dataOut->getLength()); if (m_conf.enable and m_insert) { boost::mutex::scoped_lock lock(m_enabled_carriers_mutex); complexf* in = reinterpret_cast<complexf*>(dataIn->getData()); complexf* out = reinterpret_cast<complexf*>(dataOut->getData()); - if ((m_enabled_carriers.size() % 2) != 0) { - throw std::logic_error("odd number of enabled carriers"); - } - /* Normalise the TII carrier power according to ETSI TR 101 496-3 * Clause 5.4.2.2 Paragraph 7: * @@ -213,13 +209,10 @@ int TII::process(Buffer* dataIn, Buffer* dataOut) */ const float normalise_factor = 0.14433756729740644112f; // = 1/sqrt(48) - for (size_t i = 0; i < m_enabled_carriers.size(); i+=2) { + for (size_t i = 0; i < m_enabled_carriers.size(); i++) { // See header file for an explanation of the old variant if (m_enabled_carriers[i]) { out[i] = normalise_factor * (m_conf.old_variant ? in[i+1] : in[i]); - } - - if (m_enabled_carriers[i+1]) { out[i+1] = normalise_factor * in[i+1]; } } @@ -239,10 +232,6 @@ void TII::enable_carrier(int k) { } m_enabled_carriers[ix] = true; - // NULL frequency is never enabled. - if (ix > 1 and (ix-1 != 768)) { - m_enabled_carriers[ix-1] = true; - } } void TII::prepare_pattern() { @@ -287,7 +276,7 @@ void TII::prepare_pattern() { } } - for (int k = 384; k <= 768; k++) { + for (int k = 385; k <= 768; k++) { for (int b = 0; b < 8; b++) { if ( k == 385 + 2 * comb + 48 * b and pattern_tm1_2_4[m_conf.pattern][b]) { @@ -350,10 +339,10 @@ void TII::set_parameter(const std::string& parameter, const std::string& value) ss >> m_conf.old_variant; } else { - stringstream ss; - ss << "Parameter '" << parameter << + stringstream ss_err; + ss_err << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name(); - throw ParameterError(ss.str()); + throw ParameterError(ss_err.str()); } } @@ -122,6 +122,9 @@ class TII : public ModCodec, public RemoteControllable // m_enabled_carriers is read by modulator thread, and written // to by RC thread. mutable boost::mutex m_enabled_carriers_mutex; + + // m_enabled_carriers is true only for the first carrier in the + // active pair std::vector<bool> m_enabled_carriers; }; diff --git a/src/TimeInterleaver.cpp b/src/TimeInterleaver.cpp index 3bf6339..7e19af8 100644 --- a/src/TimeInterleaver.cpp +++ b/src/TimeInterleaver.cpp @@ -23,6 +23,7 @@ #include "PcDebug.h" #include <vector> +#include <string> #include <stdint.h> diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp index ddd3fb7..26deb60 100644 --- a/src/TimestampDecoder.cpp +++ b/src/TimestampDecoder.cpp @@ -228,10 +228,10 @@ void TimestampDecoder::set_parameter( throw ParameterError("timestamp is read-only"); } else { - stringstream ss; - ss << "Parameter '" << parameter + stringstream ss_err; + ss_err << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name(); - throw ParameterError(ss.str()); + throw ParameterError(ss_err.str()); } } diff --git a/src/Utils.cpp b/src/Utils.cpp index 385253b..f113be3 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -27,7 +27,9 @@ #include "Utils.h" #include "GainControl.h" -#include <sys/prctl.h> +#if defined(HAVE_PRCTL) +# include <sys/prctl.h> +#endif #include <pthread.h> static void printHeader() @@ -160,7 +162,9 @@ int set_realtime_prio(int prio) void set_thread_name(const char *name) { +#if defined(HAVE_PRCTL) prctl(PR_SET_NAME,name,0,0,0); +#endif } double parseChannel(const std::string& chan) diff --git a/src/Utils.h b/src/Utils.h index 2bc6cb3..5d5831b 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -62,6 +62,7 @@ inline long timespecdiff_us(struct timespec& oldTime, struct timespec& time) // Set SCHED_RR with priority prio (0=lowest) int set_realtime_prio(int prio); +// Set the name of the thread void set_thread_name(const char *name); // Convert a channel like 10A to a frequency diff --git a/src/porting.c b/src/porting.c index 79523e5..f7421b0 100644 --- a/src/porting.c +++ b/src/porting.c @@ -21,19 +21,6 @@ #include "porting.h" - -#ifndef HAVE_GETTIMEOFDAY -#include <sys/timeb.h> -int gettimeofday(struct timeval* t, void* timezone) -{ - struct timeb timebuffer; - ftime(&timebuffer); - t->tv_sec=timebuffer.time; - t->tv_usec=1000*timebuffer.millitm; - return 0; -} -#endif - #ifdef _WIN32 unsigned int _CRT_fmode = _O_BINARY; #endif diff --git a/src/porting.h b/src/porting.h index 2ac9b90..1799ba7 100644 --- a/src/porting.h +++ b/src/porting.h @@ -19,25 +19,12 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PORTING_H -#define PORTING_H +#pragma once #ifdef HAVE_CONFIG_H # include <config.h> #endif -#ifndef HAVE_BZERO -# define bzero(s, n) memset(s, 0, n) -#endif - -#ifndef HAVE_GETTIMEOFDAY -#include <sys/time.h> -#ifdef __cplusplus -extern "C" -#endif -int gettimeofday(struct timeval* t, void* timezone); -#endif - #ifdef _WIN32 #include <fcntl.h> // For setting default opening mode with fopen as binary, for all files @@ -45,8 +32,3 @@ int gettimeofday(struct timeval* t, void* timezone); extern unsigned int _CRT_fmode; #endif -#ifndef HAVE_KILL -# define kill(a, b) raise(b) -#endif - -#endif // PORTING_H |