diff --git a/README.md b/README.md index 7ddeda8..3f77224 100755 --- a/README.md +++ b/README.md @@ -40,6 +40,53 @@ The Library code will be set to interpret the input as being of Mode 1. ![example 3 with sdrplay input](/example-3.png?raw=true) +--------------------------------------------------------------------- +Handling TII data +--------------------------------------------------------------------- + +As (probably) known, most DAB(+) transmissions are transmitted at the +same time by more than a single transmitter. Each transmitter then +adds some encoding to the so-called NULL segment of the DAB frame, +that identifies the transmitter. + +In Qt-DAB the TII data is by default decoded and - after consulting +a databae - transformed into the name of the transmitter and some +additional data. + +As an experiment, example-2 is modified to download the database and +show some info on the transmitters begin received. + +Shown below is the output of a recording + + program KLASSIK RADIO is part of the ensemble + program RADIO BOB! is part of the ensemble + program Absolut relax is part of the ensemble + program SCHLAGERPARADIES is part of the ensemble + program Dlf is part of the ensemble + program ENERGY is part of the ensemble + program Schwarzwaldradio is part of the ensemble + program PPP-RTK-AdV is part of the ensemble + program DRadio DokDeb is part of the ensemble + there might be a DAB signal here + ensemble DR Deutschland is (10BC) recognized + program ERF Plus is part of the ensemble + 16 1 -> DE 5C DR Deutschland Hamburg/Heinrich-Hertz-Turm 53.563122 9.975833 + + 16 2 -> DE 5C DR Deutschland Hamburg/Moorfleet 53.519230 10.102853 + we try to start program radio horeb + for service radio horeb we find index 7 + startaddress = 156 + length = 36 + subChId = 5 + protection = 2 + bitrate = 48 + +It shows that two transmitters are identified, with the transmitter's name and +the coordinates + +As said, the "feature" is still experimental and further work is +being done + ---------------------------------------------------------------------- Supported devices ---------------------------------------------------------------------- diff --git a/dab-api.h b/dab-api.h index 150119e..4ba72cd 100644 --- a/dab-api.h +++ b/dab-api.h @@ -21,8 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __DAB_API__ -#define __DAB_API__ +#pragma once #include #include #include @@ -45,7 +44,7 @@ // Experimental API for controlling the dab software library // -// Version 3.0 +// Version 4.0 // Examples of the use of the DAB-API library are found in the // directories // a. C++ Example, which gives a simple command line interface to @@ -54,12 +53,16 @@ #include #include "device-handler.h" +#include "dab-constants.h" // // // This struct (a pointer to) is returned by callbacks of the type // programdata_t. It contains parameters, describing the service. typedef struct { bool defined; + std::string serviceName; + std::string shortName; + uint32_t SId; int16_t subchId; int16_t startAddr; bool shortForm; // false EEP long form @@ -77,6 +80,11 @@ typedef struct { // typedef struct { bool defined; + std::string serviceName; + std::string shortName; + uint32_t SId; + int16_t programType; + int16_t subchId; int16_t startAddr; bool shortForm; @@ -85,8 +93,6 @@ typedef struct { int16_t bitRate; int16_t ASCTy; int16_t language; - int16_t programType; - bool is_madePublic; } audiodata; //////////////////////// C A L L B A C K F U N C T I O N S /////////////// @@ -110,10 +116,11 @@ typedef struct { // // the ensemblename is sent whenever the library detects the // name of the ensemble - typedef void (*ensemblename_t)(const char *, int32_t, void *); + typedef void (*name_of_ensemble_t)(const std::string &, int32_t, void *); // // Each programname in the ensemble is sent once - typedef void (*programname_t)(const char *, int32_t, void *); + typedef void (*serviceName_t)(const std::string &, + int32_t, uint16_t, void *); // // thefib sends the time as pair of integers typedef void (*theTime_t)(int hours, int minutes, void *); @@ -154,7 +161,7 @@ typedef struct { // // tii data - if available, the tii data is passed on as a single // integer - typedef void (*tii_data_t)(int, void *); + typedef void (*tii_data_t)(tiiData *, void *); ///////////////////////////////////////////////////////////////////////// // @@ -173,8 +180,8 @@ typedef struct { uint8_t dabMode; syncsignal_t syncsignal_Handler; systemdata_t systemdata_Handler; - ensemblename_t ensemblename_Handler; - programname_t programname_Handler; + name_of_ensemble_t name_of_ensemble; + serviceName_t serviceName; fib_quality_t fib_quality_Handler; audioOut_t audioOut_Handler; dataOut_t dataOut_Handler; @@ -215,37 +222,41 @@ void DAB_API dabReset_msc (void *); // // is_audioService will return true id the main service with the // name is an audioservice -bool DAB_API is_audioService (void *, const char *); +bool DAB_API is_audioService (void *, const std::string &); // // is_dataService will return true id the main service with the // name is a dataservice -bool DAB_API is_dataService (void *, const char *); +bool DAB_API is_dataService (void *, const std::string &); // // dataforAudioService will search for the audiodata of the i-th // (sub)service with the name as given. If no such service exists, // the "defined" bit in the struct will be set to false; -void DAB_API dataforAudioService (void *, const char *, audiodata *, int); +void DAB_API dataforAudioService (void *, const std::string &, + audiodata &, int); // // dataforDataService will search for the packetdata of the i-th // (sub)service with the name as given. If no such service exists, // the "defined" bit in the struct will be set to false; -void DAB_API dataforDataService (void *, const char *, packetdata *, int); +void DAB_API dataforDataService (void *, const std::string &, + packetdata &, int); // // set-audioChannel will add - if properly defined - a handler // for handling the audiodata as described in the parameter // to the list of active handlers -void DAB_API set_audioChannel (void *, audiodata *); +void DAB_API set_audioChannel (void *, audiodata &); // // set-dataChannel will add - if properly defined - a handler // for handling the packetdata as described in the parameter // to the list of active handlers -void DAB_API set_dataChannel (void *, packetdata *); +void DAB_API set_dataChannel (void *, packetdata &); // // mapping from a name to a Service identifier is done -int32_t DAB_API dab_getSId (void *, const char*); +int32_t DAB_API dab_getSId (void *, const std::string &); // // and the other way around, mapping the service identifier to a name -void DAB_API dab_getserviceName (void *, int32_t, char *); +std::string DAB_API dab_getserviceName (void *, uint32_t /* SId */); } -#endif +// +// extract the name of the ensemble +std::string DAB_API get_ensembleName (void *); diff --git a/device-handler.h b/device-handler.h index 2c673f1..f041c45 100644 --- a/device-handler.h +++ b/device-handler.h @@ -24,8 +24,7 @@ * want the interface with different devices (including filehandling) * to be transparent */ -#ifndef __DEVICE_HANDLER__ -#define __DEVICE_HANDLER__ +#pragma once #include #include @@ -71,4 +70,4 @@ protected: int theGain; virtual void run (); }; -#endif + diff --git a/devices/hackrf-handler/hackrf-handler.h b/devices/hackrf-handler/hackrf-handler.h index 1f6b165..08af8db 100644 --- a/devices/hackrf-handler/hackrf-handler.h +++ b/devices/hackrf-handler/hackrf-handler.h @@ -21,8 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __HACKRF_HANDLER__ -#define __HACKRF_HANDLER__ +#pragma once #include "ringbuffer.h" #include @@ -62,5 +61,5 @@ private: void setLNAGain (int); void setVGAGain (int); }; -#endif + diff --git a/devices/lime-handler/lime-handler.h b/devices/lime-handler/lime-handler.h index bece5b9..98c6ff6 100644 --- a/devices/lime-handler/lime-handler.h +++ b/devices/lime-handler/lime-handler.h @@ -21,8 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __LIME_HANDLER__ -#define __LIME_HANDLER__ +#pragma once #include #include @@ -36,14 +35,14 @@ public: limeHandler (int32_t frequency, int16_t gain, std::string antenna); - ~limeHandler (void); + ~limeHandler (); bool restartReader (int32_t); - void stopReader (void); + void stopReader (); int32_t getSamples (std::complex *, int32_t); - int32_t Samples (void); - void resetBuffer (void); - int16_t bitDepth (void); + int32_t Samples (); + void resetBuffer (); + int16_t bitDepth (); private: std::atomic running; @@ -55,8 +54,7 @@ private: RingBuffer> *theBuffer; lms_stream_meta_t meta; lms_stream_t stream; - void run (void); + void run (); }; -#endif diff --git a/devices/pluto/pluto-handler.h b/devices/pluto/pluto-handler.h index 7a8e50d..ade5656 100644 --- a/devices/pluto/pluto-handler.h +++ b/devices/pluto/pluto-handler.h @@ -1,6 +1,6 @@ # /* - * Copyright (C) 2020 + * Copyright (C) 2020 .. 2025 * Jan van Katwijk (J.vanKatwijk@gmail.com) * Lazy Chair Computing * @@ -21,8 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __PLUTO_HANDLER__ -#define __PLUTO_HANDLER__ +#pragma once #include #include @@ -74,5 +73,6 @@ private: int16_t mapTable_int [DAB_RATE / DIVIDER]; float mapTable_float [DAB_RATE / DIVIDER]; }; -#endif + + diff --git a/devices/rawfiles/rawfiles.h b/devices/rawfiles/rawfiles.h index 22172f3..107b5d1 100644 --- a/devices/rawfiles/rawfiles.h +++ b/devices/rawfiles/rawfiles.h @@ -20,8 +20,7 @@ * along with DAB library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __RAW_FILES__ -#define __RAW_FILES__ +#pragma once #include "ringbuffer.h" #include "device-handler.h" @@ -61,5 +60,4 @@ virtual void run (void); int64_t currPos; }; -#endif diff --git a/devices/rtl_tcp/rtl_tcp-client.h b/devices/rtl_tcp/rtl_tcp-client.h index afb65a4..b99fbba 100644 --- a/devices/rtl_tcp/rtl_tcp-client.h +++ b/devices/rtl_tcp/rtl_tcp-client.h @@ -22,8 +22,8 @@ * */ -#ifndef __RTL_TCP_CLIENT -#define __RTL_TCP_CLIENT +#pragma once + #include #include #include @@ -81,5 +81,4 @@ virtual void run (); void sendCommand (uint8_t cmd, uint32_t param); }; -#endif diff --git a/devices/rtlsdr-handler/rtlsdr-handler.h b/devices/rtlsdr-handler/rtlsdr-handler.h index a983fc1..5806b1b 100644 --- a/devices/rtlsdr-handler/rtlsdr-handler.h +++ b/devices/rtlsdr-handler/rtlsdr-handler.h @@ -21,10 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __RTLSDR_HANDLER__ -#define __RTLSDR_HANDLER__ +#pragma once -#include +#include #include "ringbuffer.h" #include "device-handler.h" #include @@ -132,4 +131,4 @@ private: pfnrtlsdr_get_device_name rtlsdr_get_device_name; pfnrtlsdr_set_opt_string rtlsdr_set_opt_string; }; -#endif + diff --git a/devices/sdrplay-handler-v3/sdrplay-handler-v3.cpp b/devices/sdrplay-handler-v3/sdrplay-handler-v3.cpp index c09d925..2616b62 100644 --- a/devices/sdrplay-handler-v3/sdrplay-handler-v3.cpp +++ b/devices/sdrplay-handler-v3/sdrplay-handler-v3.cpp @@ -165,7 +165,7 @@ sdrplay_api_ErrT err; sdrplay_api_DeviceT devs [6]; float apiVersion; uint32_t ndev; -int lna_upperBound; +int lna_upperBound = 4; chosenDevice = nullptr; deviceParams = nullptr; diff --git a/devices/sdrplay-handler/sdrplay-handler.h b/devices/sdrplay-handler/sdrplay-handler.h index 65c244f..cc5ba33 100644 --- a/devices/sdrplay-handler/sdrplay-handler.h +++ b/devices/sdrplay-handler/sdrplay-handler.h @@ -1,6 +1,6 @@ # /* - * Copyright (C) 2014 + * Copyright (C) 2016 .. 2025 * Jan van Katwijk (J.vanKatwijk@gmail.com) * Lazy Chair programming * @@ -19,11 +19,9 @@ * You should have received a copy of the GNU General Public License * along with DAB library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ -#ifndef __SDRPLAY_HANDLER__ -#define __SDRPLAY_HANDLER__ +#pragma once #include #include @@ -87,5 +85,5 @@ private: void setup_xmlDump (); void close_xmlDump (); }; -#endif + diff --git a/devices/wavfiles/wavfiles.h b/devices/wavfiles/wavfiles.h index de89bf1..2825a54 100644 --- a/devices/wavfiles/wavfiles.h +++ b/devices/wavfiles/wavfiles.h @@ -19,8 +19,7 @@ * along with DAB library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __WAV_FILES__ -#define __WAV_FILES__ +#pragma once #include #include "ringbuffer.h" @@ -42,7 +41,7 @@ public: uint8_t myIdentity (void); int32_t Samples (void); bool restartReader (int32_t); - void stopReader (void); + void stopReader (); private: std::string fileName; @@ -51,15 +50,14 @@ private: device_eof_callback_t eofHandler; void *userData; -virtual void run (void); +virtual void run (); int32_t readBuffer (std::complex *, int32_t); RingBuffer> *_I_Buffer; std::thread workerHandle; int32_t bufferSize; SNDFILE *filePointer; std::atomic running; - int64_t currPos; + uint64_t currPos; }; -#endif diff --git a/devices/xml-filereader/xml-descriptor.h b/devices/xml-filereader/xml-descriptor.h index 9c7ab3b..a6b01b5 100644 --- a/devices/xml-filereader/xml-descriptor.h +++ b/devices/xml-filereader/xml-descriptor.h @@ -21,8 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __XML_DESCRIPTOR__ -#define __XML_DESCRIPTOR__ +#pragma once #include #include @@ -71,4 +70,3 @@ public: void add_modtoBlock (int blockno, std::string modType); }; -#endif diff --git a/devices/xml-filereader/xml-filereader.h b/devices/xml-filereader/xml-filereader.h index 2ea3591..4f37719 100644 --- a/devices/xml-filereader/xml-filereader.h +++ b/devices/xml-filereader/xml-filereader.h @@ -20,8 +20,7 @@ * along with DAB library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __XML_FILEREADER__ -#define __XML_FILEREADER__ +#pragma once #include #include @@ -54,5 +53,4 @@ private: xml_Reader *theReader; }; -#endif diff --git a/devices/xml-filereader/xml-reader.h b/devices/xml-filereader/xml-reader.h index 67198a9..d9d0f5a 100644 --- a/devices/xml-filereader/xml-reader.h +++ b/devices/xml-filereader/xml-reader.h @@ -20,8 +20,7 @@ * along with eti-cmdline; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __XML_READER__ -#define __XML_READER__ +#pragma once #include #include @@ -75,4 +74,3 @@ private: float mapTable_float [2048]; }; -#endif diff --git a/example-2/CMakeLists.txt b/example-2/CMakeLists.txt index 5547f9c..ef74508 100644 --- a/example-2/CMakeLists.txt +++ b/example-2/CMakeLists.txt @@ -2,10 +2,10 @@ cmake_minimum_required( VERSION 3.25 ) set (objectName dab_cmdline-2) #set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -flto") #set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -O3 -pg") -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") -#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -fsanitize=address") -#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") +#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -O3 -pg") +#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -g -fsanitize=address") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g -fsanitize=address") if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "/usr/local/bin" CACHE PATH "default install path" FORCE ) endif() @@ -494,6 +494,7 @@ endif () ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} . ./ + ./tii-handling ./server-thread ./audio-sink ../devices @@ -514,6 +515,10 @@ endif () set (${objectName}_HDRS ${${objectName}_HDRS} ./ringbuffer.h + ./tii-handling/tii-handler.h + ./tii-handling/tiiQueue.h + ./tii-handling/tii-reader.h + ./tii-handling/cacheElement.h ./audio-sink/audio-base.h ./audio-sink/audiosink.h ./audio-sink/filesink.h @@ -524,17 +529,21 @@ endif () ../devices/device-exceptions.h ../library/includes/dab-constants.h ../library/includes/dab-processor.h + ../library/includes/bit-extractors.h + ../library/includes/time-converter.h ../library/includes/ofdm/phasereference.h ../library/includes/ofdm/phasetable.h ../library/includes/ofdm/freq-interleaver.h ../library/includes/ofdm/timesyncer.h ../library/includes/ofdm/fic-handler.h - ../library/includes/ofdm/fib-processor.cpp + ../library/includes/ofdm/fib-table.h + ../library/includes/ofdm/ensemble.h + ../library/includes/ofdm/fib-config.h + ../library/includes/ofdm/fib-decoder.h ../library/includes/ofdm/sample-reader.h ../library/includes/ofdm/tii-detector.h ../library/includes/backend/firecode-checker.h ../library/includes/backend/backend-base.h - ../library/includes/backend/charsets.h ../library/includes/backend/galois.h ../library/includes/backend/reed-solomon.h ../library/includes/backend/msc-handler.h @@ -552,6 +561,7 @@ endif () ../library/includes/backend/data/mot/mot-object.h ../library/includes/backend/data/data-processor.h ../library/includes/support/band-handler.h + ../library/includes/support/charsets.h # ../library/includes/support/viterbi-handler.h ../library/includes/support/protTables.h ../library/includes/support/protection.h @@ -566,6 +576,9 @@ endif () set (${objectName}_SRCS ${${objectName}_SRCS} ./main.cpp + ./tii-handling/tii-handler.cpp + ./tii-handling/tiiQueue.cpp + ./tii-handling/tii-reader.cpp ./audio-sink/audio-base.cpp ./audio-sink/audiosink.cpp ./audio-sink/filesink.cpp @@ -574,18 +587,20 @@ endif () ../devices/device-handler.cpp ../library/dab-api.cpp ../library/src/dab-processor.cpp + ../library/src/time-converter.cpp ../library/src/ofdm/ofdm-decoder.cpp ../library/src/ofdm/phasereference.cpp ../library/src/ofdm/phasetable.cpp ../library/src/ofdm/freq-interleaver.cpp ../library/src/ofdm/timesyncer.cpp ../library/src/ofdm/sample-reader.cpp - ../library/src/ofdm/fib-processor.cpp ../library/src/ofdm/fic-handler.cpp + ../library/src/ofdm/ensemble.cpp + ../library/src/ofdm/fib-config.cpp + ../library/src/ofdm/fib-decoder.cpp ../library/src/ofdm/tii-detector.cpp ../library/src/backend/firecode-checker.cpp ../library/src/backend/backend-base.cpp - ../library/src/backend/charsets.cpp ../library/src/backend/galois.cpp ../library/src/backend/reed-solomon.cpp ../library/src/backend/msc-handler.cpp @@ -602,6 +617,7 @@ endif () ../library/src/backend/data/mot/mot-object.cpp ../library/src/backend/data/data-processor.cpp ../library/src/support/band-handler.cpp + ../library/src/support/charsets.cpp # ../library/src/support/viterbi-handler.cpp ../library/src/support/protTables.cpp ../library/src/support/protection.cpp diff --git a/example-2/main.cpp b/example-2/main.cpp index 1cfcbe1..ec272e7 100644 --- a/example-2/main.cpp +++ b/example-2/main.cpp @@ -36,6 +36,7 @@ #include "filesink.h" #include "dab-api.h" #include "includes/support/band-handler.h" +#include "tii-handler.h" #ifdef HAVE_SDRPLAY #include "sdrplay-handler.h" #elif HAVE_SDRPLAY_V3 @@ -77,7 +78,7 @@ static std::atomic run; static -void *theRadio = NULL; +void *theRadio = nullptr; static std::atomictimeSynced; @@ -85,6 +86,7 @@ std::atomictimeSynced; static std::atomictimesyncSet; +tiiHandler the_tiiHandler; static std::atomicensembleRecognized; @@ -116,9 +118,9 @@ void syncsignalHandler (bool b, void *userData) { // recognized, the names of the programs are in the // ensemble static -void ensemblenameHandler (const char *name, int Id, void *userData) { +void name_of_ensemble (const std::string &name, int Id, void *userData) { fprintf (stderr, "ensemble %s is (%X) recognized\n", - name, (uint32_t)Id); + name. c_str (), (uint32_t)Id); ensembleRecognized. store (true); } @@ -129,13 +131,12 @@ std::vector programSIds; std::unordered_map ensembleContents; static -void programnameHandler (const char *s, int SId, void *userdata) { - for (std::vector::iterator it = programNames.begin(); - it != programNames. end(); ++it) - if (*it == std::string (s)) +void serviceName (const std::string &s, int SId, + uint16_t subChId, void *userdata) { + for (auto it : programNames) + if (it == s) return; - ensembleContents. insert (pair (SId, - std::string (s))); + ensembleContents. insert (pair (SId, s)); programNames. push_back (std::string (s)); programSIds . push_back (SId); std::cerr << "program " << s << " is part of the ensemble\n"; @@ -157,7 +158,7 @@ void programdata_Handler (audiodata *d, void *ctx) { static void dataOut_Handler (const char * dynamicLabel, void *ctx) { (void)ctx; - std::cerr << std::string (dynamicLabel) << "\r"; +// std::cerr << std::string (dynamicLabel) << "\r"; } // // The function is called from the MOT handler, with @@ -167,16 +168,17 @@ void dataOut_Handler (const char * dynamicLabel, void *ctx) { void motdata_Handler (uint8_t *data, int size, const char *s, int d, void *ctx) { (void)s; (void)d; (void)ctx; - fprintf (stderr, "plaatje %s met lengte %d\n", s, size); +// fprintf (stderr, "plaatje %s met lengte %d\n", s, size); } -void tii_data_Handler (int s, void *p) { -// fprintf (stderr, "mainId %d, subId %d\n", s >> 8, s & 0xFF); - (void)p; +void tii_data_Handler (tiiData *theData, void *ctx) { + the_tiiHandler. add (*theData); + (void)ctx; } void timeHandler (int hours, int minutes, void *ctx) { - fprintf (stderr, "%2d:%2d\n", hours, minutes); +// fprintf (stderr, "%2d:%2d\n", hours, minutes); + (void)ctx; } // @@ -249,7 +251,7 @@ void fibQuality (int16_t q, void *ctx) { static void mscQuality (int16_t fe, int16_t rsE, int16_t aacE, void *ctx) { - fprintf (stderr, "msc quality = %d %d %d\n", fe, rsE, aacE); +// fprintf (stderr, "msc quality = %d %d %d\n", fe, rsE, aacE); } int main (int argc, char **argv) { @@ -323,9 +325,10 @@ int opt; struct sigaction sigact; bandHandler dabBand; deviceHandler *theDevice = nullptr; + bool err; int theDuration = -1; // no limit - +//tiiHandler the_tiiHandler; std::cerr << "dab_cmdline example II,\n \ Copyright 2017 J van Katwijk, Lazy Chair Computing\n"; timeSynced. store (false); @@ -648,8 +651,8 @@ int theDuration = -1; // no limit interface. dabMode = theMode; interface. syncsignal_Handler = syncsignalHandler; interface. systemdata_Handler = systemData; - interface. ensemblename_Handler = ensemblenameHandler; - interface. programname_Handler = programnameHandler; + interface. name_of_ensemble = name_of_ensemble; + interface. serviceName = serviceName; interface. fib_quality_Handler = fibQuality; interface. audioOut_Handler = pcmHandler; interface. dataOut_Handler = dataOut_Handler; @@ -728,7 +731,7 @@ int theDuration = -1; // no limit if (run. load ()) { dataforAudioService (theRadio, - programName. c_str (), &ad, 0); + programName. c_str (), ad, 0); if (!ad. defined) { std::cerr << "sorry we cannot handle service " << programName << "\n"; @@ -738,7 +741,7 @@ int theDuration = -1; // no limit if (run. load ()) { dabReset_msc (theRadio); - set_audioChannel (theRadio, &ad); + set_audioChannel (theRadio, ad); } while (run. load () && (theDuration != 0)) { diff --git a/example-2/tii-handling/cacheElement.h b/example-2/tii-handling/cacheElement.h new file mode 100644 index 0000000..af466db --- /dev/null +++ b/example-2/tii-handling/cacheElement.h @@ -0,0 +1,85 @@ +# +/* + * Copyright (C) 2015, 2023 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the dab-cmdline + * + * dab-cmdline is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * dab-cmdline is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dab-cmdline; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#pragma once + +// +// In case there is aaccess to a database, the elements of +// that database are read in and per line converted to am accessible +// struct +#include + +class cacheElement { +public: + bool valid; + std::string ensemble; + std::string country; + std::string channel; + std::string location; + uint16_t Eid; + uint8_t mainId; + uint16_t pattern; + uint8_t subId; + std::string transmitterName; + float latitude; + float longitude; + float power; + float altitude; + float height; + std::string polarization; + float frequency; + std::string direction; +// +// There are values differing per instance of the +// same transmitter + float strength; + float distance; + float azimuth; + float phase; + bool norm; + bool collision; + + cacheElement () { + valid = false; + ensemble = ""; + country = "not known"; + channel = ""; + ensemble = ""; + Eid = 0; + mainId = 255; + subId = 255; + transmitterName = "not in database"; + latitude = 0; + longitude = 0; + power = 0; + height = 0; + power = 0; + polarization = ""; + frequency = 0; + direction = ""; + phase = 0; + norm = false; + collision = false; + } + ~cacheElement () {} +}; + diff --git a/example-2/tii-handling/tii-handler.cpp b/example-2/tii-handling/tii-handler.cpp new file mode 100644 index 0000000..1bf001c --- /dev/null +++ b/example-2/tii-handling/tii-handler.cpp @@ -0,0 +1,91 @@ + +#include "tii-handler.h" + + tiiHandler::tiiHandler () { + has_dataBase = false; + std::string home_dir = getenv ("HOME"); + std::string fileName = home_dir + "/.txdata.tii"; + fprintf (stderr, "de filename = %s\n", fileName. c_str ()); + the_dataBase = theReader. readFile (fileName); + fprintf (stderr, "size %d\n", the_dataBase. size ()); + if (the_dataBase. size () > 10) + has_dataBase = true; + threadHandle = std::thread (&tiiHandler::run, this); +} + + tiiHandler::~tiiHandler () { + if (running. load ()) { + running. store (false); + threadHandle. join (); + } +} + +void tiiHandler::add (tiiData p) { + if (running. load ()) + theBuffer. push (p); +} + +void tiiHandler::run () { + running. store (true); + while (running. load ()) { + while (theBuffer. empty ()) + usleep (50000); + while (!theBuffer. empty ()) { + tiiData xx = theBuffer. pop (); + if (known (xx)) + continue; + if ((xx. ecc == 0) || (xx. EId == 0)) { + fprintf (stderr, "No further data: %d %d \n", + xx. mainId, + xx. subId); + tiiTable. push_back (xx); + continue; + } + if (!has_dataBase) { + fprintf (stderr, "No database available: %d %X %d %d\n", + xx. ecc, xx. EId, xx. mainId, xx. subId); + tiiTable. push_back (xx); + continue; + } + + cacheElement *handle = lookup (xx); // in tii database + if (handle == nullptr) + fprintf (stderr, "not found %X %d %d\n", + xx. EId, xx. mainId, xx. subId); + else + fprintf (stderr, "%d %d -> %s %s %s %s %f %f\n", + handle -> mainId, + handle -> subId, + handle -> country. c_str (), + handle -> channel. c_str (), + handle -> ensemble. c_str (), + handle -> transmitterName. c_str (), + (double)handle -> latitude, + (double)handle -> longitude); + tiiTable. push_back (xx); + } + } +} + +bool tiiHandler::known (tiiData &t) { + if (!running. load ()) + return true; + for (auto &tableElement: tiiTable) { + if ((t. mainId == tableElement. mainId) && + (t. subId == tableElement. subId)) + return true; + } + return false; +} + +cacheElement *tiiHandler::lookup (tiiData &tii) { + for (auto &ce : the_dataBase) { + if (ce. Eid != tii. EId) + continue; + if ((ce. mainId == tii. mainId) && (ce. subId == tii. subId)) { + return &ce; + } + } + return nullptr; +} + diff --git a/example-2/tii-handling/tii-handler.h b/example-2/tii-handling/tii-handler.h new file mode 100644 index 0000000..d1b4df2 --- /dev/null +++ b/example-2/tii-handling/tii-handler.h @@ -0,0 +1,36 @@ + +#pragma once + +#include +#include +#include +#include +#include +#include "dab-constants.h" +#include "tiiQueue.h" +#include "cacheElement.h" +#include "tii-reader.h" + +class tiiHandler { + +public: + tiiHandler (); + + ~tiiHandler (); +void add (tiiData theData); + +private: + + tiiReader theReader; + std::vector the_dataBase; + tiiQueue theBuffer; + std::vector tiiTable; + bool has_dataBase; + bool known (tiiData &); + void run (); + std::thread threadHandle; + std::atomic running; + cacheElement * lookup (tiiData &); +}; + + diff --git a/example-2/tii-handling/tii-reader.cpp b/example-2/tii-handling/tii-reader.cpp new file mode 100644 index 0000000..9d1ebc9 --- /dev/null +++ b/example-2/tii-handling/tii-reader.cpp @@ -0,0 +1,218 @@ +# +/* + * Copyright (C) 2014 .. 2023 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of dab-cmdline + * + * dab-cmdline is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * dab-cmdline is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dab-cmdline; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include "dab-constants.h" +#include "charsets.h" +#include "tii-reader.h" + +#define SEPARATOR ';' +#define COUNTRY 1 +#define CHANNEL 2 +#define ENSEMBLE 3 +#define EID 4 +#define TII 5 +#define LOCATION 6 +#define LATITUDE 7 +#define LONGITUDE 8 +#define ALTITUDE 9 +#define HEIGHT 10 +#define POLARIZATION 11 +#define FREQUENCY 12 +#define POWER 13 +#define DIRECTION 14 +#define NR_COLUMNS 15 + +static +std::string Trim (const std::string& src) { + return src; + if (src.empty()) + return ""; + + size_t i = 0; // first index + size_t j = src. size () - 1; // last index of src + + while (i < j && isspace (src [i])) + i++; + + while (j > i && isspace (src [j])) + j--; + + return std::string (src, i, j - 2 ); +} + + tiiReader::tiiReader () { + Rflag = true; +} + tiiReader::~tiiReader () { +} +// +std::vector tiiReader::readFile (const std::string &s) { +std::vector res; + if (s == "") { + return res; + } + + res. resize (0); + FILE *f = fopen (s. c_str (), "r+b"); + if (f == nullptr) + return res; + cacheElement ed; + res. push_back (ed); // the dummy one + int count = 1; + char buffer [1024]; + std::vector columnVector; + int shift = 0; + if (Rflag) + shift = fgetc (f); + int teller = 0; + while (eread (buffer, 1024, f, shift) != nullptr) { + cacheElement ed; + if (feof (f)) + break; + teller ++; + columnVector. resize (0); + int columns = readColumns (columnVector, buffer, NR_COLUMNS); + if (columns < NR_COLUMNS) + continue; + ed. valid = true; + ed. country = Trim (columnVector [COUNTRY]); + ed. Eid = get_Eid (columnVector [EID]); + ed. mainId = get_mainId (columnVector [TII]); + ed. subId = get_subId (columnVector [TII]); + ed. channel = Trim (columnVector [CHANNEL]); + ed. ensemble = Trim (columnVector [ENSEMBLE]); + ed. transmitterName = Trim (columnVector [LOCATION]); + ed. latitude = convert (columnVector [LATITUDE]); + ed. longitude = convert (columnVector [LONGITUDE]); + ed. power = convert (columnVector [POWER]); + ed. altitude = convert (columnVector [ALTITUDE]); + ed. height = convert (columnVector [HEIGHT]); + ed. polarization = Trim (columnVector [POLARIZATION]); + ed. frequency = convert (columnVector[FREQUENCY]); + ed. direction = Trim (columnVector [DIRECTION]); + + if ((ed. mainId == 255) ||(ed. subId == 255)) + ed. valid = false; + if ((ed. mainId == 0) || (ed. subId == 0)) + ed. valid = false; + if (ed. ensemble == "") + ed. valid = false; + if (count >= (int) res. size ()) + res. resize (res. size () + 100); + res. at (count) = ed; + count ++; + } + fclose (f); + return res; +} + +int tiiReader::readColumns (std::vector &v, char *b, int N) { +int charp = 0; +char tb [256]; +int elementCount = 0; +std::string element; + + v. resize (0); + while ((*b != 0) && (*b != '\n')) { + if (*b == SEPARATOR) { + tb [charp] = 0; + std::string ss = toStringUsingCharset (tb, (CharacterSet)0x0F); + v. push_back (ss); + charp = 0; + elementCount ++; + if (elementCount >= N) + return N; + } + else + tb [charp ++] = *b; + b ++; + } + return elementCount; +} + +// +char *tiiReader::eread (char *buffer, int amount, FILE *f, uint8_t shift) { +char *bufferP; + + if (fgets (buffer, amount, f) == nullptr) + return nullptr; + bufferP = buffer; + if (Rflag) { + while (*bufferP != 0) { + if (shift != 0xAA) + *bufferP -= shift; + else + *bufferP ^= 0xAA; + bufferP ++; + } + *bufferP = 0; + } + return buffer; +} + +float tiiReader::convert (const std::string s) { +float v; + try { + v = std::stof (Trim (s)); + } + catch (...) { + v = 0; + } + return v; +} + +uint32_t tiiReader::get_Eid (const std::string s) { +uint32_t res; + try { + res = std::stoi (s, 0, 16); + } + catch (...) { + res = 0; + } + return res; +} + +uint8_t tiiReader::get_mainId (const std::string s) { +uint16_t res; + try { + res = std::stoi (s); + } + catch (...) { + res = 0; + } + return res / 100; +} + +uint8_t tiiReader::get_subId (const std::string s) { +uint16_t res; + try { + res = std::stoi (Trim (s)); + } + catch (...) { + res = 0; + } + return res % 100; +} + diff --git a/example-2/tii-handling/tii-reader.h b/example-2/tii-handling/tii-reader.h new file mode 100644 index 0000000..2f668e4 --- /dev/null +++ b/example-2/tii-handling/tii-reader.h @@ -0,0 +1,53 @@ +# +/* + * Copyright (C) 2014 .. 2023 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of dab-cmdline + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#pragma once + +#include +#include +#include +#include +#include "dab-constants.h" +#include "cacheElement.h" + +#ifdef __MING32__ +#include +#include +#endif +class tiiReader { +public: + tiiReader (); + ~tiiReader (); +// + std::vector + readFile (const std::string &s); + int readColumns (std::vector &v, char *b, int N); + char *eread (char *buffer, int amount, + FILE *f, uint8_t shift); +private: + float convert (const std::string); + uint32_t get_Eid (const std::string); + uint8_t get_mainId (const std::string); + uint8_t get_subId (const std::string); + bool Rflag; +}; + diff --git a/example-2/tii-handling/tiiQueue.cpp b/example-2/tii-handling/tiiQueue.cpp new file mode 100644 index 0000000..3247487 --- /dev/null +++ b/example-2/tii-handling/tiiQueue.cpp @@ -0,0 +1,25 @@ + + +#include "tiiQueue.h" + + tiiQueue::tiiQueue () {} + + tiiQueue::~tiiQueue () {} + +void tiiQueue::push (tiiData item) { + std::unique_lock lock(m_mutex); + m_queue. push (item); +} + +bool tiiQueue::empty () { + std::unique_lock lock(m_mutex); + return m_queue. size () == 0; +} + +tiiData tiiQueue::pop () { + std::unique_lock lock(m_mutex); + tiiData item = m_queue.front(); + m_queue.pop(); + return item; +} + diff --git a/example-2/tii-handling/tiiQueue.h b/example-2/tii-handling/tiiQueue.h new file mode 100644 index 0000000..85ff151 --- /dev/null +++ b/example-2/tii-handling/tiiQueue.h @@ -0,0 +1,24 @@ + +#pragma once + +// C++ implementation of the threadsafe queue +#include +#include +#include +#include +#include "dab-constants.h" + +class tiiQueue { +private: + std::queue m_queue; + std::mutex m_mutex; + +public: + + tiiQueue (); + ~tiiQueue (); + void push (tiiData item); + bool empty (); + tiiData pop (); +}; + diff --git a/example-3/CMakeLists.txt b/example-3/CMakeLists.txt index 8f6c672..7eac82c 100644 --- a/example-3/CMakeLists.txt +++ b/example-3/CMakeLists.txt @@ -1,14 +1,17 @@ -cmake_minimum_required( VERSION 2.8.11 ) +cmake_minimum_required( VERSION 3.25 ) set (objectName dab_cmdline-3) #set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -flto") #set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -fsanitize=address") -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") +#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -O3 -pg") +#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -g -fsanitize=address") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g -fsanitize=address") if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "/usr/local/bin" CACHE PATH "default install path" FORCE ) endif() #set (CMAKE_INSTALL_PREFIX /usr/local/bin) + if(MINGW) add_definitions ( -municode) endif() @@ -29,19 +32,22 @@ list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) # ######################################################################## OPTION(RTLSDR "Input: RTLSDR" OFF) -OPTION(SDRPLAY "Input: SDRPlay" OFF) +OPTION(SDRPLAY "Input: SDRPLAY" OFF) OPTION(AIRSPY "Input: AirSpy" OFF) OPTION(HACKRF "Input: HACKRF" OFF) OPTION(LIMESDR "Input: LIMESDR" OFF) +OPTION(PLUTO "Input: PLUTO" OFF) OPTION(RTL_TCP "Input: RTL_TCP" OFF) OPTION(SDRPLAY_V3 "Input: SDRPlay_V3" OFF) OPTION(WAVFILES "Input: WAVFILES" OFF) OPTION(RAWFILES "Input: RAWFILES" OFF) -OPTION(SERVER "Create TDC server" OFF) +OPTION(XMLFILES "Input: XMLFILES" OFF) +OPTION(SERVER "CReate TDC server" OFF) + OPTION(X64_DEFINED "optimize for x64/SSE" OFF) OPTION(RPI_DEFINED "optimize for ARM/NEON" OFF) -if ( (NOT RTLSDR) AND (NOT SDRPLAY) AND (NOT AirSpy) AND (NOT HACKRF) AND (NOT LIMESDR) AND (NOT RTL_TCP) AND (NOT SDRPLAY_V3) AND (NOT WAVFILES) AND (NOT RAWFILES) ) +if ( (NOT RTLSDR) AND (NOT SDRPLAY) AND (NOT AirSpy) AND (NOT HACKRF) AND (NOT LIMESDR) AND (NOT RTL_TCP) AND (NOT SDRPLAY_V3) AND (NOT WAVFILES) AND (NOT RAWFILES) AND (NOT XMLFILES) ) message("None of the Input Options selected. Using default SDRPlay") set(SDRPlay ON) endif () @@ -51,7 +57,7 @@ set (objectName "") if(RTLSDR) if (objectName STREQUAL "") set(RTLSDR ON) - set(objectName dab-rtlsdr-3) + set(objectName dab-rtlsdr-2) else () message ("Ignoring second option") endif () @@ -60,7 +66,7 @@ endif () if(SDRPLAY) if (objectName STREQUAL "") set(SDRPLAY ON) - set(objectName dab-sdrplay-3) + set(objectName dab-sdrplay-2) else () message ("Ignoring second option") endif () @@ -69,7 +75,7 @@ endif () if(AIRSPY) if (objectName STREQUAL "") set(AIRSPY ON) - set(objectName dab-airspy-3) + set(objectName dab-airspy-2) else () message ("Ignoring second option") endif () @@ -78,7 +84,7 @@ endif () if(HACKRF) if (objectName STREQUAL "") set(HACKRF ON) - set(objectName dab-hackrf-3) + set(objectName dab-hackrf-2) else () message ("Ignoring second option") endif () @@ -87,7 +93,16 @@ endif () if(LIMESDR) if (objectName STREQUAL "") set(LIMESDR ON) - set(objectName dab-lime-3) + set(objectName dab-lime-2) + else () + message ("Ignoring second option") + endif () +endif () + +if(PLUTO) + if (objectName STREQUAL "") + set(PLUTOSDR ON) + set(objectName dab-pluto-2) else () message ("Ignoring second option") endif () @@ -96,7 +111,7 @@ endif () if(RTL_TCP) if (objectName STREQUAL "") set(RTL_TCP ON) - set(objectName dab-rtl_tcp-3) + set(objectName dab-rtl_tcp-2) else () message ("Ignoring second option") endif () @@ -105,7 +120,7 @@ endif () if(SDRPLAY_V3) if (objectName STREQUAL "") set(SDRPLAY_V3 ON) - set(objectName dab-sdrplay-v3) + set(objectName dab-sdrplay-2) else () message ("Ignoring second option") endif () @@ -114,7 +129,7 @@ endif () if(WAVFILES) if (objectName STREQUAL "") set(WAVFILES ON) - set(objectName dab-files-3) + set(objectName dab-files-2) else () message ("Ignoring second option") endif () @@ -123,17 +138,24 @@ endif () if(RAWFILES) if (objectName STREQUAL "") set(RAWFILES ON) - set(objectName dab-raw-3) + set(objectName dab-raw-2) else () message ("Ignoring second option") endif () endif () -if (DEFINED_SERVER) - add_definitions(-DHAVE_SERVER) +if(XMLFILES) + if (objectName STREQUAL "") + set(XMLFILES ON) + set(objectName dab-xml-2) + else () + message ("Ignoring second option") + endif () endif () -add_definitions (-DSTREAMER_OUTPUT) +if (SERVER) + add_definitions(-DHAVE_SERVER) +endif () ######################################################################### find_package (PkgConfig) @@ -142,26 +164,25 @@ add_definitions (-DSTREAMER_OUTPUT) if (NOT FFTW3F_FOUND) message(FATAL_ERROR "please install FFTW3") endif () + list(APPEND extraLibs ${FFTW3F_LIBRARIES}) find_package(Faad) if (NOT FAAD_FOUND ) message(FATAL_ERROR "please install libfaad") endif () - find_package(zlib) - if (NOT ZLIB_FOUND) - message(FATAL_ERROR "please install libz") + + find_package(LibSampleRate) + if (NOT LIBSAMPLERATE_FOUND) + message(FATAL_ERROR "please install libsamplerate") endif () - list(APPEND extraLibs ${ZLIB_LIBRARY}) - - - find_library (PTHREADS pthread) - if (NOT(PTHREADS)) - message (FATAL_ERROR "please install libpthread") - else (NOT(PTHREADS)) - set (extraLibs ${extraLibs} ${PTHREADS}) - endif (NOT(PTHREADS)) + list(APPEND extraLibs ${LIBSAMPLERATE_LIBRARY}) + find_package(Portaudio) + if (NOT PORTAUDIO_FOUND) + message(FATAL_ERROR "please install portaudio V19") + endif () + list(APPEND extraLibs ${PORTAUDIO_LIBRARIES}) ######################################################################### find_package (PkgConfig) @@ -259,23 +280,50 @@ add_definitions (-DSTREAMER_OUTPUT) list (APPEND extraLibs ${LIMELIB}) endif(NOT(LIMELIB)) - include_directories ( - ../devices/lime-handler + include_directories ( + ../devices/lime-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/lime-handler/LMS7002M_parameters.h + ../devices/lime-handler/LimeSuite.h + ../devices/lime-handler/lime-handler.h ) - set ($(objectName)_HDRS - ${${objectName}_HDRS} - ../devices/lime-handler/LMS7002M_parameters.h - ../devices/lime-handler/LimeSuite.h - ../devices/lime-handler/lime-handler.h + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/lime-handler/lime-handler.cpp + ) + + add_definitions (-DHAVE_LIME) + endif (LIMESDR) + + if (PLUTOSDR) + find_library (PLUTOLIB iio) + if(NOT(PLUTOLIB)) + message(FATAL_ERROR "please install libiio") + else(NOT(PLUTOLIB)) + list (APPEND extraLibs ${PLUTOLIB} "libad9361.so") + endif(NOT(PLUTOLIB)) + + include_directories ( + ../devices/pluto + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/pluto/dabFilter.h + ../devices/pluto/pluto-handler.h ) - set (${objectName}_SRCS - ${${objectName}_SRCS} - ../devices/lime-handler/lime-handler.cpp - ) - add_definitions (-DHAVE_LIME) - endif (LIMESDR) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/pluto/pluto-handler.cpp + ) + + add_definitions (-DHAVE_PLUTO) + endif (PLUTOSDR) if (AIRSPY) find_package(LibAIRSPY) @@ -326,47 +374,6 @@ add_definitions (-DSTREAMER_OUTPUT) add_definitions (-DHAVE_RTLSDR) endif() - if (WAVFILES) - include_directories ( - ../devices/wavfiles/ - ) - - set (${objectName}_HDRS - ${${objectName}_HDRS} - ../devices/wavfiles/wavfiles.h - ) - - set (${objectName}_SRCS - ${${objectName}_SRCS} - ../devices/wavfiles/wavfiles.cpp - ) - find_package(LibSndFile) - if (NOT LIBSNDFILE_FOUND) - message(FATAL_ERROR "please install libsndfile") - endif () - list(APPEND extraLibs ${LIBSNDFILE_LIBRARY}) - - add_definitions (-DHAVE_WAVFILES) - endif() - - if (RAWFILES) - include_directories ( - ../devices/rawfiles/ - ) - - set (${objectName}_HDRS - ${${objectName}_HDRS} - ../devices/rawfiles/rawfiles.h - ) - - set (${objectName}_SRCS - ${${objectName}_SRCS} - ../devices/rawfiles/rawfiles.cpp - ) - - add_definitions (-DHAVE_RAWFILES) - endif() - if (HACKRF) find_path (HACKLIB_INCLUDE_DIR NAMES hackrf.h @@ -400,6 +407,85 @@ add_definitions (-DSTREAMER_OUTPUT) add_definitions (-DHAVE_HACKRF) endif (HACKRF) + find_package(LibSndFile) + if (NOT LIBSNDFILE_FOUND) + message(FATAL_ERROR "please install libsndfile") + endif () + list(APPEND extraLibs ${LIBSNDFILE_LIBRARY}) + + + find_package(zlib) + if (NOT ZLIB_FOUND) + message(FATAL_ERROR "please install libz") + endif () + list(APPEND extraLibs ${ZLIB_LIBRARY}) + + find_library (PTHREADS pthread) + if (NOT(PTHREADS)) + message (FATAL_ERROR "please install libpthread") + else (NOT(PTHREADS)) + set (extraLibs ${extraLibs} ${PTHREADS}) + endif (NOT(PTHREADS)) + + if (WAVFILES) + include_directories ( + ../devices/wavfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/wavfiles/wavfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/wavfiles/wavfiles.cpp + ) + add_definitions (-DHAVE_WAVFILES) + endif() + + if (RAWFILES) + include_directories ( + ../devices/rawfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/rawfiles/rawfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rawfiles/rawfiles.cpp + ) + + add_definitions (-DHAVE_RAWFILES) + endif() + + if (XMLFILES) + include_directories ( + ../devices/xml-filereader + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/xml-filereader/rapidxml.hpp + ../devices/xml-filereader/xml-filereader.h + ../devices/xml-filereader/xmlreader.h + ../devices/xml-filereader/element-reader.h + ../devices/xml-filereader/xml-descriptor.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/xml-filereader/xml-filereader.cpp + ../devices/xml-filereader/xml-reader.cpp + ../devices/xml-filereader/xml-descriptor.cpp + ) + + add_definitions (-DHAVE_XMLFILES) + endif (XMLFILES) + ####################################################################### # # Here we really start @@ -409,8 +495,8 @@ add_definitions (-DSTREAMER_OUTPUT) . ./ ./server-thread - ../ ../devices + ../ ../library ../library/includes ../library/includes/ofdm @@ -428,23 +514,26 @@ add_definitions (-DSTREAMER_OUTPUT) ${${objectName}_HDRS} ./ringbuffer.h ./server-thread/tcp-server.h - ./streamer.h ../dab-api.h ../devices/device-handler.h ../devices/device-exceptions.h ../library/includes/dab-constants.h ../library/includes/dab-processor.h + ../library/includes/bit-extractors.h + ../library/includes/time-converter.h ../library/includes/ofdm/phasereference.h ../library/includes/ofdm/phasetable.h ../library/includes/ofdm/freq-interleaver.h ../library/includes/ofdm/timesyncer.h ../library/includes/ofdm/fic-handler.h - ../library/includes/ofdm/fib-processor.cpp + ../library/includes/ofdm/fib-table.h + ../library/includes/ofdm/ensemble.h + ../library/includes/ofdm/fib-config.h + ../library/includes/ofdm/fib-decoder.h ../library/includes/ofdm/sample-reader.h ../library/includes/ofdm/tii-detector.h ../library/includes/backend/firecode-checker.h ../library/includes/backend/backend-base.h - ../library/includes/backend/charsets.h ../library/includes/backend/galois.h ../library/includes/backend/reed-solomon.h ../library/includes/backend/msc-handler.h @@ -457,11 +546,12 @@ add_definitions (-DSTREAMER_OUTPUT) ../library/includes/backend/data/virtual-datahandler.h ../library/includes/backend/data/tdc-datahandler.h ../library/includes/backend/data/pad-handler.h + ../library/includes/backend/data/mot/mot-handler.h + ../library/includes/backend/data/mot/mot-dir.h + ../library/includes/backend/data/mot/mot-object.h ../library/includes/backend/data/data-processor.h - ../library/includes/backend/data/mot/mot-handler.h - ../library/includes/backend/data/mot/mot-dir.h - ../library/includes/backend/data/mot/mot-object.h ../library/includes/support/band-handler.h + ../library/includes/support/charsets.h # ../library/includes/support/viterbi-handler.h ../library/includes/support/protTables.h ../library/includes/support/protection.h @@ -469,30 +559,31 @@ add_definitions (-DSTREAMER_OUTPUT) ../library/includes/support/eep-protection.h ../library/includes/support/fft-handler.h ../library/includes/support/dab-params.h - ../library/includes/support/tii_table.h +# ../library/includes/support/tii_table.h ../library/includes/support/viterbi-spiral/viterbi-spiral.h ) set (${objectName}_SRCS ${${objectName}_SRCS} ./main.cpp - ./streamer.cpp ./server-thread/tcp-server.cpp ../devices/device-handler.cpp ../library/dab-api.cpp ../library/src/dab-processor.cpp + ../library/src/time-converter.cpp ../library/src/ofdm/ofdm-decoder.cpp ../library/src/ofdm/phasereference.cpp ../library/src/ofdm/phasetable.cpp ../library/src/ofdm/freq-interleaver.cpp ../library/src/ofdm/timesyncer.cpp ../library/src/ofdm/sample-reader.cpp - ../library/src/ofdm/fib-processor.cpp ../library/src/ofdm/fic-handler.cpp + ../library/src/ofdm/ensemble.cpp + ../library/src/ofdm/fib-config.cpp + ../library/src/ofdm/fib-decoder.cpp ../library/src/ofdm/tii-detector.cpp ../library/src/backend/firecode-checker.cpp ../library/src/backend/backend-base.cpp - ../library/src/backend/charsets.cpp ../library/src/backend/galois.cpp ../library/src/backend/reed-solomon.cpp ../library/src/backend/msc-handler.cpp @@ -504,11 +595,12 @@ add_definitions (-DSTREAMER_OUTPUT) ../library/src/backend/data/virtual-datahandler.cpp ../library/src/backend/data/tdc-datahandler.cpp ../library/src/backend/data/pad-handler.cpp + ../library/src/backend/data/mot/mot-handler.cpp + ../library/src/backend/data/mot/mot-dir.cpp + ../library/src/backend/data/mot/mot-object.cpp ../library/src/backend/data/data-processor.cpp - ../library/src/backend/data/mot/mot-handler.cpp - ../library/src/backend/data/mot/mot-dir.cpp - ../library/src/backend/data/mot/mot-object.cpp ../library/src/support/band-handler.cpp + ../library/src/support/charsets.cpp # ../library/src/support/viterbi-handler.cpp ../library/src/support/protTables.cpp ../library/src/support/protection.cpp @@ -516,7 +608,7 @@ add_definitions (-DSTREAMER_OUTPUT) ../library/src/support/uep-protection.cpp ../library/src/support/fft-handler.cpp ../library/src/support/dab-params.cpp - ../library/src/support/tii_table.cpp +# ../library/src/support/tii_table.cpp ../library/src/support/viterbi-spiral/viterbi-spiral.cpp ) @@ -553,9 +645,10 @@ add_definitions (-DSTREAMER_OUTPUT) ../library/src/support/viterbi-spiral/spiral-no-sse.h ) endif (X64_DEFINED) - +# include_directories ( ${FFTW_INCLUDE_DIRS} + ${PORTAUDIO_INCLUDE_DIRS} ${FAAD_INCLUDE_DIRS} ${SNDFILES_INCLUDE_DIRS} ) @@ -565,14 +658,13 @@ add_definitions (-DSTREAMER_OUTPUT) add_executable (${objectName} ${${objectName}_SRCS} ) - if (RPI_DEFINED) + if (RPI_DEFINED) # compiler options seem changed with gcc versions. gcc 8.3.0 on Raspbian didn't accept -mcpu .. # test options with "make VERBOSE=1" target_compile_options(${objectName} PRIVATE -march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ) - endif() + endif() target_link_libraries (${objectName} - ${FFTW3F_LIBRARIES} ${extraLibs} ${FAAD_LIBRARIES} ${CMAKE_DL_LIBS} diff --git a/example-3/CMakeLists.txt-old b/example-3/CMakeLists.txt-old new file mode 100644 index 0000000..2a20bdd --- /dev/null +++ b/example-3/CMakeLists.txt-old @@ -0,0 +1,598 @@ +cmake_minimum_required( VERSION 3.25 ) +set (objectName dab_cmdline-3) +#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -flto") +#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -fsanitize=address") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set (CMAKE_INSTALL_PREFIX "/usr/local/bin" CACHE PATH "default install path" FORCE ) +endif() +#set (CMAKE_INSTALL_PREFIX /usr/local/bin) + +if(MINGW) + add_definitions ( -municode) +endif() + +######################################################################## +# select the release build type by default to get optimization flags +######################################################################## +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + message(STATUS "Build type not specified: defaulting to release.") +endif(NOT CMAKE_BUILD_TYPE) +set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") + +### make sure our local CMake Modules path comes first +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) + +###################################################################### +# +######################################################################## +OPTION(RTLSDR "Input: RTLSDR" OFF) +OPTION(SDRPLAY "Input: SDRPlay" OFF) +OPTION(AIRSPY "Input: AirSpy" OFF) +OPTION(HACKRF "Input: HACKRF" OFF) +OPTION(LIMESDR "Input: LIMESDR" OFF) +OPTION(RTL_TCP "Input: RTL_TCP" OFF) +OPTION(SDRPLAY_V3 "Input: SDRPlay_V3" OFF) +OPTION(WAVFILES "Input: WAVFILES" OFF) +OPTION(RAWFILES "Input: RAWFILES" OFF) +OPTION(SERVER "Create TDC server" OFF) +OPTION(X64_DEFINED "optimize for x64/SSE" OFF) +OPTION(RPI_DEFINED "optimize for ARM/NEON" OFF) + +if ( (NOT RTLSDR) AND (NOT SDRPLAY) AND (NOT AirSpy) AND (NOT HACKRF) AND (NOT LIMESDR) AND (NOT RTL_TCP) AND (NOT SDRPLAY_V3) AND (NOT WAVFILES) AND (NOT RAWFILES) ) + message("None of the Input Options selected. Using default SDRPlay") + set(SDRPlay ON) +endif () + +set (objectName "") + +if(RTLSDR) + if (objectName STREQUAL "") + set(RTLSDR ON) + set(objectName dab-rtlsdr-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(SDRPLAY) + if (objectName STREQUAL "") + set(SDRPLAY ON) + set(objectName dab-sdrplay-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(AIRSPY) + if (objectName STREQUAL "") + set(AIRSPY ON) + set(objectName dab-airspy-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(HACKRF) + if (objectName STREQUAL "") + set(HACKRF ON) + set(objectName dab-hackrf-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(LIMESDR) + if (objectName STREQUAL "") + set(LIMESDR ON) + set(objectName dab-lime-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(RTL_TCP) + if (objectName STREQUAL "") + set(RTL_TCP ON) + set(objectName dab-rtl_tcp-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(SDRPLAY_V3) + if (objectName STREQUAL "") + set(SDRPLAY_V3 ON) + set(objectName dab-sdrplay-v3) + else () + message ("Ignoring second option") + endif () +endif () + +if(WAVFILES) + if (objectName STREQUAL "") + set(WAVFILES ON) + set(objectName dab-files-3) + else () + message ("Ignoring second option") + endif () +endif () + +if(RAWFILES) + if (objectName STREQUAL "") + set(RAWFILES ON) + set(objectName dab-raw-3) + else () + message ("Ignoring second option") + endif () +endif () + +if (DEFINED_SERVER) + add_definitions(-DHAVE_SERVER) +endif () + +add_definitions (-DSTREAMER_OUTPUT) + +######################################################################### + find_package (PkgConfig) + + find_package(FFTW3f) + if (NOT FFTW3F_FOUND) + message(FATAL_ERROR "please install FFTW3") + endif () + list(APPEND extraLibs ${FFTW3F_LIBRARIES}) + + + find_package(Faad) + if (NOT FAAD_FOUND ) + message(FATAL_ERROR "please install libfaad") + endif () + + find_package(zlib) + if (NOT ZLIB_FOUND) + message(FATAL_ERROR "please install libz") + endif () + list(APPEND extraLibs ${ZLIB_LIBRARY}) + + + find_library (PTHREADS pthread) + if (NOT(PTHREADS)) + message (FATAL_ERROR "please install libpthread") + else (NOT(PTHREADS)) + set (extraLibs ${extraLibs} ${PTHREADS}) + endif (NOT(PTHREADS)) + + +######################################################################### + find_package (PkgConfig) + +########################################################################## +# The devices +# + + if (RTL_TCP) + include_directories ( + ../devices/rtl_tcp + ) + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/rtl_tcp/rtl_tcp-client.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rtl_tcp/rtl_tcp-client.cpp + ) + + add_definitions (-DHAVE_RTL_TCP) + endif (RTL_TCP) + + if (SDRPLAY) + find_path (SDRPLAYLIB_INCLUDE_DIR + NAMES mirsdrapi-rsp.h + PATHS + /usr/local/include/ + ) + include_directories (${SDRPLAYLIB_INCLUDE_DIR}) + + find_library (SDRPLAYLIB mirsdrapi-rsp) + if(NOT(SDRPLAYLIB)) + message(FATAL_ERROR "please install -lmirsdrapi-rsp") + else(NOT(SDRPLAYLIB)) + list (APPEND extraLibs ${SDRPLAYLIB}) + endif(NOT(SDRPLAYLIB)) + + include_directories ( + ../devices/sdrplay-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/sdrplay-handler/sdrplay-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/sdrplay-handler/sdrplay-handler.cpp + ) + + add_definitions (-DHAVE_SDRPLAY) + endif (SDRPLAY) + + if (SDRPLAY_V3) + find_path (SDRPLAYLIB_INCLUDE_DIR + NAMES sdrplay_api.h + PATHS + /usr/local/include/ + ) + include_directories (${SDRPLAYLIB_INCLUDE_DIR}) + + find_library (SDRPLAYLIB sdrplay_api) + if(NOT(SDRPLAYLIB)) + message(FATAL_ERROR "please install -lsdrplay_api") + else(NOT(SDRPLAYLIB)) + list (APPEND extraLibs ${SDRPLAYLIB}) + endif(NOT(SDRPLAYLIB)) + + include_directories ( + ../devices/sdrplay-handler-v3 + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/sdrplay-handler-v3/sdrplay-handler-v3.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/sdrplay-handler-v3/sdrplay-handler-v3.cpp + ) + + add_definitions (-DHAVE_SDRPLAY_V3) + endif (SDRPLAY_V3) + + if (LIMESDR) + find_library (LIMELIB LimeSuite) + if(NOT(LIMELIB)) + message(FATAL_ERROR "please install LimeSuite") + else(NOT(LIMELIB)) + list (APPEND extraLibs ${LIMELIB}) + endif(NOT(LIMELIB)) + + include_directories ( + ../devices/lime-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/lime-handler/LMS7002M_parameters.h + ../devices/lime-handler/LimeSuite.h + ../devices/lime-handler/lime-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/lime-handler/lime-handler.cpp + ) + add_definitions (-DHAVE_LIME) + endif (LIMESDR) + + if (AIRSPY) + find_package(LibAIRSPY) + if (NOT LIBAIRSPY_FOUND) + message(FATAL_ERROR "please install airspy library") + endif () + ### include_directories (${AIRSPYLIB_INCLUDE_DIR}) + + include_directories ( + ../devices/airspy-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/airspy-handler/airspy-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/airspy-handler/airspy-handler.cpp + ) + + add_definitions (-DHAVE_AIRSPY) + endif (AIRSPY) + + + if (RTLSDR) + find_package(LibRTLSDR) + if (NOT LIBRTLSDR_FOUND) + message(FATAL_ERROR "please install librtlsdr") + endif () + ###include_directories (${RTLSDR_INCLUDE_DIR}) + + include_directories ( + ../devices/rtlsdr-handler/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/rtlsdr-handler/rtlsdr-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rtlsdr-handler/rtlsdr-handler.cpp + ) + + add_definitions (-DHAVE_RTLSDR) + endif() + + if (WAVFILES) + include_directories ( + ../devices/wavfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/wavfiles/wavfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/wavfiles/wavfiles.cpp + ) + find_package(LibSndFile) + if (NOT LIBSNDFILE_FOUND) + message(FATAL_ERROR "please install libsndfile") + endif () + list(APPEND extraLibs ${LIBSNDFILE_LIBRARY}) + + add_definitions (-DHAVE_WAVFILES) + endif() + + if (RAWFILES) + include_directories ( + ../devices/rawfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/rawfiles/rawfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rawfiles/rawfiles.cpp + ) + + add_definitions (-DHAVE_RAWFILES) + endif() + + if (HACKRF) + find_path (HACKLIB_INCLUDE_DIR + NAMES hackrf.h + PATHS + ../devices/hackrf-handler/libhackrf/ + /usr/local/include/ + ) + include_directories (${HACKLIB_INCLUDE_DIR}) + + find_library (HACKLIB hackrf) + if(NOT(HACKLIB)) + message(FATAL_ERROR "please install -lhackrf") + else(NOT(HACKLIB)) + list (APPEND extraLibs ${HACKLIB}) + endif(NOT(HACKLIB)) + + include_directories ( + ../devices/hackrf-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/hackrf-handler/hackrf-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/hackrf-handler/hackrf-handler.cpp + ) + + add_definitions (-DHAVE_HACKRF) + endif (HACKRF) + +####################################################################### +# +# Here we really start + + include_directories ( + ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + . + ./ + ./server-thread + ../ + ../devices + ../library + ../library/includes + ../library/includes/ofdm + ../library/includes/backend + ../library/includes/backend/audio + ../library/includes/backend/data + ../library/includes/backend/data/mot + ../library/includes/backend/data/journaline + ../library/includes/support + ../library/includes/support/viterbi-spiral + /usr/include/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ./ringbuffer.h + ./server-thread/tcp-server.h + ./streamer.h + ../dab-api.h + ../devices/device-handler.h + ../devices/device-exceptions.h + ../library/includes/dab-constants.h + ../library/includes/dab-processor.h + ../library/includes/ofdm/phasereference.h + ../library/includes/ofdm/phasetable.h + ../library/includes/ofdm/freq-interleaver.h + ../library/includes/ofdm/timesyncer.h + ../library/includes/ofdm/fic-handler.h + ../library/includes/ofdm/fib-table.h + ../library/includes/ofdm/ensemble.h + ../library/includes/ofdm/fib-config.h + ../library/includes/ofdm/fib-decoder.h + ../library/includes/ofdm/sample-reader.h + ../library/includes/ofdm/tii-detector.h + ../library/includes/backend/firecode-checker.h + ../library/includes/backend/backend-base.h + ../library/includes/backend/charsets.h + ../library/includes/backend/galois.h + ../library/includes/backend/reed-solomon.h + ../library/includes/backend/msc-handler.h + ../library/includes/backend/virtual-backend.h + ../library/includes/backend/audio-backend.h + ../library/includes/backend/data-backend.h + ../library/includes/backend/audio/faad-decoder.h + ../library/includes/backend/audio/mp4processor.h + ../library/includes/backend/audio/mp2processor.h + ../library/includes/backend/data/virtual-datahandler.h + ../library/includes/backend/data/tdc-datahandler.h + ../library/includes/backend/data/pad-handler.h + ../library/includes/backend/data/data-processor.h + ../library/includes/backend/data/mot/mot-handler.h + ../library/includes/backend/data/mot/mot-dir.h + ../library/includes/backend/data/mot/mot-object.h + ../library/includes/support/band-handler.h +# ../library/includes/support/viterbi-handler.h + ../library/includes/support/protTables.h + ../library/includes/support/protection.h + ../library/includes/support/uep-protection.h + ../library/includes/support/eep-protection.h + ../library/includes/support/fft-handler.h + ../library/includes/support/dab-params.h + ../library/includes/support/tii_table.h + ../library/includes/support/viterbi-spiral/viterbi-spiral.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ./main.cpp + ./streamer.cpp + ./server-thread/tcp-server.cpp + ../devices/device-handler.cpp + ../library/dab-api.cpp + ../library/src/dab-processor.cpp + ../library/src/ofdm/ofdm-decoder.cpp + ../library/src/ofdm/phasereference.cpp + ../library/src/ofdm/phasetable.cpp + ../library/src/ofdm/freq-interleaver.cpp + ../library/src/ofdm/timesyncer.cpp + ../library/src/ofdm/sample-reader.cpp + ../library/src/ofdm/ensemble.cpp + ../library/src/ofdm/fib-config.cpp + ../library/src/ofdm/fib-decoder.cpp + ../library/src/ofdm/tii-detector.cpp + ../library/src/backend/firecode-checker.cpp + ../library/src/backend/backend-base.cpp + ../library/src/backend/charsets.cpp + ../library/src/backend/galois.cpp + ../library/src/backend/reed-solomon.cpp + ../library/src/backend/msc-handler.cpp + ../library/src/backend/virtual-backend.cpp + ../library/src/backend/audio-backend.cpp + ../library/src/backend/data-backend.cpp + ../library/src/backend/audio/mp4processor.cpp + ../library/src/backend/audio/mp2processor.cpp + ../library/src/backend/data/virtual-datahandler.cpp + ../library/src/backend/data/tdc-datahandler.cpp + ../library/src/backend/data/pad-handler.cpp + ../library/src/backend/data/data-processor.cpp + ../library/src/backend/data/mot/mot-handler.cpp + ../library/src/backend/data/mot/mot-dir.cpp + ../library/src/backend/data/mot/mot-object.cpp + ../library/src/support/band-handler.cpp +# ../library/src/support/viterbi-handler.cpp + ../library/src/support/protTables.cpp + ../library/src/support/protection.cpp + ../library/src/support/eep-protection.cpp + ../library/src/support/uep-protection.cpp + ../library/src/support/fft-handler.cpp + ../library/src/support/dab-params.cpp + ../library/src/support/tii_table.cpp + ../library/src/support/viterbi-spiral/viterbi-spiral.cpp + ) + + if (X64_DEFINED) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../library/src/support/viterbi-spiral/spiral-sse.c + ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../library/src/support/viterbi-spiral/spiral-sse.h + ) + add_definitions (-DSSE_AVAILABLE) + elseif (RPI_DEFINED) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../library/src/support/viterbi-spiral/spiral-neon.c + ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../library/src/support/viterbi-spiral/spiral-neon.h + ) + add_definitions (-DNEON_AVAILABLE) + # compiler options moved below add_executable .. and target specific + #set (CMAKE_CXX_FLAGS "${CMAKE_XCC_FLAGS} -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4") + #set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4") + else (X64_DEFINED) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../library/src/support/viterbi-spiral/spiral-no-sse.c + ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../library/src/support/viterbi-spiral/spiral-no-sse.h + ) + endif (X64_DEFINED) + + include_directories ( + ${FFTW_INCLUDE_DIRS} + ${FAAD_INCLUDE_DIRS} + ${SNDFILES_INCLUDE_DIRS} + ) + +##################################################################### + + add_executable (${objectName} + ${${objectName}_SRCS} + ) + if (RPI_DEFINED) + # compiler options seem changed with gcc versions. gcc 8.3.0 on Raspbian didn't accept -mcpu .. + # test options with "make VERBOSE=1" + target_compile_options(${objectName} PRIVATE -march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ) + endif() + + target_link_libraries (${objectName} + ${extraLibs} + ${FAAD_LIBRARIES} + ${CMAKE_DL_LIBS} + ) + + INSTALL (TARGETS ${objectName} DESTINATION .) + +######################################################################## +# Create uninstall target +######################################################################## + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) diff --git a/example-3/cmake/Modules/FindFFTW3f.cmake b/example-3/cmake/Modules/FindFFTW3f.cmake index 0ee7e46..87e4440 100644 --- a/example-3/cmake/Modules/FindFFTW3f.cmake +++ b/example-3/cmake/Modules/FindFFTW3f.cmake @@ -37,5 +37,5 @@ FIND_LIBRARY( INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFTW3F DEFAULT_MSG FFTW3F_LIBRARIES FFTW3F_INCLUDE_DIRS) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFTW3f DEFAULT_MSG FFTW3F_LIBRARIES FFTW3F_INCLUDE_DIRS) MARK_AS_ADVANCED(FFTW3F_LIBRARIES FFTW3F_INCLUDE_DIRS FFTW3F_THREADS_LIBRARIES) \ No newline at end of file diff --git a/example-4/CMakeLists.txt b/example-4/CMakeLists.txt index cfa049d..d011a35 100644 --- a/example-4/CMakeLists.txt +++ b/example-4/CMakeLists.txt @@ -1,12 +1,17 @@ -cmake_minimum_required( VERSION 2.8.11 ) -set (objectName dab_cmdline-4) -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -flto") -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") +cmake_minimum_required( VERSION 3.25 ) +set (objectName dab_cmdline-2) +#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -flto") +#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") +#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -O3 -pg") +#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -g -fsanitize=address") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g -fsanitize=address") if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set (CMAKE_INSTALL_PREFIX "/usr/local/bin" CACHE PATH "default install path" FORCE ) endif() #set (CMAKE_INSTALL_PREFIX /usr/local/bin) + if(MINGW) add_definitions ( -municode) endif() @@ -27,19 +32,22 @@ list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) # ######################################################################## OPTION(RTLSDR "Input: RTLSDR" OFF) -OPTION(SDRPLAY "Input: SDRPlay" OFF) +OPTION(SDRPLAY "Input: SDRPLAY" OFF) OPTION(AIRSPY "Input: AirSpy" OFF) OPTION(HACKRF "Input: HACKRF" OFF) OPTION(LIMESDR "Input: LIMESDR" OFF) +OPTION(PLUTO "Input: PLUTO" OFF) OPTION(RTL_TCP "Input: RTL_TCP" OFF) OPTION(SDRPLAY_V3 "Input: SDRPlay_V3" OFF) OPTION(WAVFILES "Input: WAVFILES" OFF) OPTION(RAWFILES "Input: RAWFILES" OFF) +OPTION(XMLFILES "Input: XMLFILES" OFF) OPTION(SERVER "CReate TDC server" OFF) + OPTION(X64_DEFINED "optimize for x64/SSE" OFF) OPTION(RPI_DEFINED "optimize for ARM/NEON" OFF) -if ( (NOT RTLSDR) AND (NOT SDRPLAY) AND (NOT AirSpy) AND (NOT HACKRF) AND (NOT LIMESDR) AND (NOT RTL_TCP) AND (NOT SDRPLAY_V3) AND (NOT WAVFILES) AND (NOT RAWFILES) ) +if ( (NOT RTLSDR) AND (NOT SDRPLAY) AND (NOT AirSpy) AND (NOT HACKRF) AND (NOT LIMESDR) AND (NOT RTL_TCP) AND (NOT SDRPLAY_V3) AND (NOT WAVFILES) AND (NOT RAWFILES) AND (NOT XMLFILES) ) message("None of the Input Options selected. Using default SDRPlay") set(SDRPlay ON) endif () @@ -49,7 +57,7 @@ set (objectName "") if(RTLSDR) if (objectName STREQUAL "") set(RTLSDR ON) - set(objectName dab-rtlsdr-4) + set(objectName dab-rtlsdr-2) else () message ("Ignoring second option") endif () @@ -58,7 +66,7 @@ endif () if(SDRPLAY) if (objectName STREQUAL "") set(SDRPLAY ON) - set(objectName dab-sdrplay-4) + set(objectName dab-sdrplay-2) else () message ("Ignoring second option") endif () @@ -67,7 +75,7 @@ endif () if(AIRSPY) if (objectName STREQUAL "") set(AIRSPY ON) - set(objectName dab-airspy-4) + set(objectName dab-airspy-2) else () message ("Ignoring second option") endif () @@ -76,7 +84,7 @@ endif () if(HACKRF) if (objectName STREQUAL "") set(HACKRF ON) - set(objectName dab-hackrf-4) + set(objectName dab-hackrf-2) else () message ("Ignoring second option") endif () @@ -85,7 +93,16 @@ endif () if(LIMESDR) if (objectName STREQUAL "") set(LIMESDR ON) - set(objectName dab-lime-4) + set(objectName dab-lime-2) + else () + message ("Ignoring second option") + endif () +endif () + +if(PLUTO) + if (objectName STREQUAL "") + set(PLUTOSDR ON) + set(objectName dab-pluto-2) else () message ("Ignoring second option") endif () @@ -94,7 +111,7 @@ endif () if(RTL_TCP) if (objectName STREQUAL "") set(RTL_TCP ON) - set(objectName dab-rtl_tcp-4) + set(objectName dab-rtl_tcp-2) else () message ("Ignoring second option") endif () @@ -103,7 +120,7 @@ endif () if(SDRPLAY_V3) if (objectName STREQUAL "") set(SDRPLAY_V3 ON) - set(objectName dab-sdrplay-4) + set(objectName dab-sdrplay-2) else () message ("Ignoring second option") endif () @@ -112,7 +129,7 @@ endif () if(WAVFILES) if (objectName STREQUAL "") set(WAVFILES ON) - set(objectName dab-files-4) + set(objectName dab-files-2) else () message ("Ignoring second option") endif () @@ -121,7 +138,16 @@ endif () if(RAWFILES) if (objectName STREQUAL "") set(RAWFILES ON) - set(objectName dab-raw-4) + set(objectName dab-raw-2) + else () + message ("Ignoring second option") + endif () +endif () + +if(XMLFILES) + if (objectName STREQUAL "") + set(XMLFILES ON) + set(objectName dab-xml-2) else () message ("Ignoring second option") endif () @@ -131,9 +157,6 @@ if (SERVER) add_definitions(-DHAVE_SERVER) endif () -#for this version we need to define - - add_definitions(-DAAC_OUT) ######################################################################### find_package (PkgConfig) @@ -141,25 +164,15 @@ endif () if (NOT FFTW3F_FOUND) message(FATAL_ERROR "please install FFTW3") endif () + list(APPEND extraLibs ${FFTW3F_LIBRARIES}) - find_package(Faad) - if (NOT FAAD_FOUND ) - message(FATAL_ERROR "please install libfaad") + + find_package(LibSampleRate) + if (NOT LIBSAMPLERATE_FOUND) + message(FATAL_ERROR "please install libsamplerate") endif () + list(APPEND extraLibs ${LIBSAMPLERATE_LIBRARY}) - find_package(zlib) - if (NOT ZLIB_FOUND) - message(FATAL_ERROR "please install libz") - endif () - list(APPEND extraLibs ${ZLIB_LIBRARY}) - - - find_library (PTHREADS pthread) - if (NOT(PTHREADS)) - message (FATAL_ERROR "please install libpthread") - else (NOT(PTHREADS)) - set (extraLibs ${extraLibs} ${PTHREADS}) - endif (NOT(PTHREADS)) ######################################################################### find_package (PkgConfig) @@ -184,7 +197,7 @@ endif () add_definitions (-DHAVE_RTL_TCP) endif (RTL_TCP) - + if (SDRPLAY) find_path (SDRPLAYLIB_INCLUDE_DIR NAMES mirsdrapi-rsp.h @@ -217,6 +230,38 @@ endif () add_definitions (-DHAVE_SDRPLAY) endif (SDRPLAY) + if (SDRPLAY_V3) + find_path (SDRPLAYLIB_INCLUDE_DIR + NAMES sdrplay_api.h + PATHS + /usr/local/include/ + ) + include_directories (${SDRPLAYLIB_INCLUDE_DIR}) + + find_library (SDRPLAYLIB sdrplay_api) + if(NOT(SDRPLAYLIB)) + message(FATAL_ERROR "please install -lsdrplay_api") + else(NOT(SDRPLAYLIB)) + list (APPEND extraLibs ${SDRPLAYLIB}) + endif(NOT(SDRPLAYLIB)) + + include_directories ( + ../devices/sdrplay-handler-v3 + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/sdrplay-handler-v3/sdrplay-handler-v3.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/sdrplay-handler-v3/sdrplay-handler-v3.cpp + ) + + add_definitions (-DHAVE_SDRPLAY_V3) + endif (SDRPLAY_V3) + if (LIMESDR) find_library (LIMELIB LimeSuite) if(NOT(LIMELIB)) @@ -244,6 +289,32 @@ endif () add_definitions (-DHAVE_LIME) endif (LIMESDR) + if (PLUTOSDR) + find_library (PLUTOLIB iio) + if(NOT(PLUTOLIB)) + message(FATAL_ERROR "please install libiio") + else(NOT(PLUTOLIB)) + list (APPEND extraLibs ${PLUTOLIB} "libad9361.so") + endif(NOT(PLUTOLIB)) + + include_directories ( + ../devices/pluto + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/pluto/dabFilter.h + ../devices/pluto/pluto-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/pluto/pluto-handler.cpp + ) + + add_definitions (-DHAVE_PLUTO) + endif (PLUTOSDR) + if (AIRSPY) find_package(LibAIRSPY) if (NOT LIBAIRSPY_FOUND) @@ -293,29 +364,6 @@ endif () add_definitions (-DHAVE_RTLSDR) endif() - if (WAVFILES) - include_directories ( - ../devices/wavfiles/ - ) - - set (${objectName}_HDRS - ${${objectName}_HDRS} - ../devices/wavfiles/wavfiles.h - ) - - set (${objectName}_SRCS - ${${objectName}_SRCS} - ../devices/wavfiles/wavfiles.cpp - ) - find_package(LibSndFile) - if (NOT LIBSNDFILE_FOUND) - message(FATAL_ERROR "please install libsndfile") - endif () - list(APPEND extraLibs ${LIBSNDFILE_LIBRARY}) - - add_definitions (-DHAVE_WAVFILES) - endif() - if (HACKRF) find_path (HACKLIB_INCLUDE_DIR NAMES hackrf.h @@ -348,23 +396,85 @@ endif () add_definitions (-DHAVE_HACKRF) endif (HACKRF) + + find_package(LibSndFile) + if (NOT LIBSNDFILE_FOUND) + message(FATAL_ERROR "please install libsndfile") + endif () + list(APPEND extraLibs ${LIBSNDFILE_LIBRARY}) + + + find_package(zlib) + if (NOT ZLIB_FOUND) + message(FATAL_ERROR "please install libz") + endif () + list(APPEND extraLibs ${ZLIB_LIBRARY}) + + find_library (PTHREADS pthread) + if (NOT(PTHREADS)) + message (FATAL_ERROR "please install libpthread") + else (NOT(PTHREADS)) + set (extraLibs ${extraLibs} ${PTHREADS}) + endif (NOT(PTHREADS)) + + if (WAVFILES) + include_directories ( + ../devices/wavfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/wavfiles/wavfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/wavfiles/wavfiles.cpp + ) + add_definitions (-DHAVE_WAVFILES) + endif() + if (RAWFILES) - include_directories ( - ../devices/rawfiles/ - ) + include_directories ( + ../devices/rawfiles/ + ) - set (${objectName}_HDRS - ${${objectName}_HDRS} - ../devices/rawfiles/rawfiles.h - ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/rawfiles/rawfiles.h + ) - set (${objectName}_SRCS - ${${objectName}_SRCS} - ../devices/rawfiles/rawfiles.cpp - ) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rawfiles/rawfiles.cpp + ) - add_definitions (-DHAVE_RAWFILES) - endif() + add_definitions (-DHAVE_RAWFILES) + endif() + + if (XMLFILES) + include_directories ( + ../devices/xml-filereader + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/xml-filereader/rapidxml.hpp + ../devices/xml-filereader/xml-filereader.h + ../devices/xml-filereader/xmlreader.h + ../devices/xml-filereader/element-reader.h + ../devices/xml-filereader/xml-descriptor.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/xml-filereader/xml-filereader.cpp + ../devices/xml-filereader/xml-reader.cpp + ../devices/xml-filereader/xml-descriptor.cpp + ) + + add_definitions (-DHAVE_XMLFILES) + endif (XMLFILES) ####################################################################### # @@ -394,39 +504,41 @@ endif () ${${objectName}_HDRS} ./ringbuffer.h ./server-thread/tcp-server.h + ../dab-api.h ../devices/device-handler.h ../devices/device-exceptions.h - ../dab-api.h ../library/includes/dab-constants.h ../library/includes/dab-processor.h + ../library/includes/bit-extractors.h + ../library/includes/time-converter.h ../library/includes/ofdm/phasereference.h ../library/includes/ofdm/phasetable.h ../library/includes/ofdm/freq-interleaver.h ../library/includes/ofdm/timesyncer.h ../library/includes/ofdm/fic-handler.h - ../library/includes/ofdm/fib-processor.cpp + ../library/includes/ofdm/fib-table.h + ../library/includes/ofdm/ensemble.h + ../library/includes/ofdm/fib-config.h + ../library/includes/ofdm/fib-decoder.h ../library/includes/ofdm/sample-reader.h ../library/includes/ofdm/tii-detector.h ../library/includes/backend/firecode-checker.h ../library/includes/backend/backend-base.h - ../library/includes/backend/charsets.h ../library/includes/backend/galois.h ../library/includes/backend/reed-solomon.h ../library/includes/backend/msc-handler.h ../library/includes/backend/virtual-backend.h ../library/includes/backend/audio-backend.h ../library/includes/backend/data-backend.h - ../library/includes/backend/audio/faad-decoder.h - ../library/includes/backend/audio/mp4processor.h - ../library/includes/backend/audio/mp2processor.h ../library/includes/backend/data/virtual-datahandler.h ../library/includes/backend/data/tdc-datahandler.h ../library/includes/backend/data/pad-handler.h + ../library/includes/backend/data/mot/mot-handler.h + ../library/includes/backend/data/mot/mot-dir.h + ../library/includes/backend/data/mot/mot-object.h ../library/includes/backend/data/data-processor.h - ../library/includes/backend/data/mot/mot-handler.h - ../library/includes/backend/data/mot/mot-dir.h - ../library/includes/backend/data/mot/mot-object.h ../library/includes/support/band-handler.h + ../library/includes/support/charsets.h # ../library/includes/support/viterbi-handler.h ../library/includes/support/protTables.h ../library/includes/support/protection.h @@ -434,7 +546,7 @@ endif () ../library/includes/support/eep-protection.h ../library/includes/support/fft-handler.h ../library/includes/support/dab-params.h - ../library/includes/support/tii_table.h +# ../library/includes/support/tii_table.h ../library/includes/support/viterbi-spiral/viterbi-spiral.h ) @@ -445,34 +557,35 @@ endif () ../devices/device-handler.cpp ../library/dab-api.cpp ../library/src/dab-processor.cpp + ../library/src/time-converter.cpp ../library/src/ofdm/ofdm-decoder.cpp ../library/src/ofdm/phasereference.cpp ../library/src/ofdm/phasetable.cpp ../library/src/ofdm/freq-interleaver.cpp ../library/src/ofdm/timesyncer.cpp ../library/src/ofdm/sample-reader.cpp - ../library/src/ofdm/fib-processor.cpp ../library/src/ofdm/fic-handler.cpp + ../library/src/ofdm/ensemble.cpp + ../library/src/ofdm/fib-config.cpp + ../library/src/ofdm/fib-decoder.cpp ../library/src/ofdm/tii-detector.cpp ../library/src/backend/firecode-checker.cpp ../library/src/backend/backend-base.cpp - ../library/src/backend/charsets.cpp ../library/src/backend/galois.cpp ../library/src/backend/reed-solomon.cpp ../library/src/backend/msc-handler.cpp ../library/src/backend/virtual-backend.cpp ../library/src/backend/audio-backend.cpp ../library/src/backend/data-backend.cpp - ../library/src/backend/audio/mp4processor.cpp - ../library/src/backend/audio/mp2processor.cpp ../library/src/backend/data/virtual-datahandler.cpp ../library/src/backend/data/tdc-datahandler.cpp ../library/src/backend/data/pad-handler.cpp + ../library/src/backend/data/mot/mot-handler.cpp + ../library/src/backend/data/mot/mot-dir.cpp + ../library/src/backend/data/mot/mot-object.cpp ../library/src/backend/data/data-processor.cpp - ../library/src/backend/data/mot/mot-handler.cpp - ../library/src/backend/data/mot/mot-dir.cpp - ../library/src/backend/data/mot/mot-object.cpp ../library/src/support/band-handler.cpp + ../library/src/support/charsets.cpp # ../library/src/support/viterbi-handler.cpp ../library/src/support/protTables.cpp ../library/src/support/protection.cpp @@ -480,7 +593,7 @@ endif () ../library/src/support/uep-protection.cpp ../library/src/support/fft-handler.cpp ../library/src/support/dab-params.cpp - ../library/src/support/tii_table.cpp +# ../library/src/support/tii_table.cpp ../library/src/support/viterbi-spiral/viterbi-spiral.cpp ) @@ -517,9 +630,10 @@ endif () ../library/src/support/viterbi-spiral/spiral-no-sse.h ) endif (X64_DEFINED) - +# include_directories ( ${FFTW_INCLUDE_DIRS} + ${PORTAUDIO_INCLUDE_DIRS} ${FAAD_INCLUDE_DIRS} ${SNDFILES_INCLUDE_DIRS} ) @@ -529,15 +643,13 @@ endif () add_executable (${objectName} ${${objectName}_SRCS} ) - - if (RPI_DEFINED) + if (RPI_DEFINED) # compiler options seem changed with gcc versions. gcc 8.3.0 on Raspbian didn't accept -mcpu .. # test options with "make VERBOSE=1" target_compile_options(${objectName} PRIVATE -march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ) endif() target_link_libraries (${objectName} - ${FFTW3F_LIBRARIES} ${extraLibs} ${FAAD_LIBRARIES} ${CMAKE_DL_LIBS} diff --git a/example-4/CMakeLists.txt-old b/example-4/CMakeLists.txt-old new file mode 100644 index 0000000..0052e9c --- /dev/null +++ b/example-4/CMakeLists.txt-old @@ -0,0 +1,563 @@ +cmake_minimum_required( VERSION 3.25 ) +set (objectName dab_cmdline-4) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11 -flto") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set (CMAKE_INSTALL_PREFIX "/usr/local/bin" CACHE PATH "default install path" FORCE ) +endif() +#set (CMAKE_INSTALL_PREFIX /usr/local/bin) + +if(MINGW) + add_definitions ( -municode) +endif() + +######################################################################## +# select the release build type by default to get optimization flags +######################################################################## +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + message(STATUS "Build type not specified: defaulting to release.") +endif(NOT CMAKE_BUILD_TYPE) +set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") + +### make sure our local CMake Modules path comes first +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) + +###################################################################### +# +######################################################################## +OPTION(RTLSDR "Input: RTLSDR" OFF) +OPTION(SDRPLAY "Input: SDRPlay" OFF) +OPTION(AIRSPY "Input: AirSpy" OFF) +OPTION(HACKRF "Input: HACKRF" OFF) +OPTION(LIMESDR "Input: LIMESDR" OFF) +OPTION(RTL_TCP "Input: RTL_TCP" OFF) +OPTION(SDRPLAY_V3 "Input: SDRPlay_V3" OFF) +OPTION(WAVFILES "Input: WAVFILES" OFF) +OPTION(RAWFILES "Input: RAWFILES" OFF) +OPTION(SERVER "CReate TDC server" OFF) +OPTION(X64_DEFINED "optimize for x64/SSE" OFF) +OPTION(RPI_DEFINED "optimize for ARM/NEON" OFF) + +if ( (NOT RTLSDR) AND (NOT SDRPLAY) AND (NOT AirSpy) AND (NOT HACKRF) AND (NOT LIMESDR) AND (NOT RTL_TCP) AND (NOT SDRPLAY_V3) AND (NOT WAVFILES) AND (NOT RAWFILES) ) + message("None of the Input Options selected. Using default SDRPlay") + set(SDRPlay ON) +endif () + +set (objectName "") + +if(RTLSDR) + if (objectName STREQUAL "") + set(RTLSDR ON) + set(objectName dab-rtlsdr-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(SDRPLAY) + if (objectName STREQUAL "") + set(SDRPLAY ON) + set(objectName dab-sdrplay-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(AIRSPY) + if (objectName STREQUAL "") + set(AIRSPY ON) + set(objectName dab-airspy-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(HACKRF) + if (objectName STREQUAL "") + set(HACKRF ON) + set(objectName dab-hackrf-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(LIMESDR) + if (objectName STREQUAL "") + set(LIMESDR ON) + set(objectName dab-lime-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(RTL_TCP) + if (objectName STREQUAL "") + set(RTL_TCP ON) + set(objectName dab-rtl_tcp-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(SDRPLAY_V3) + if (objectName STREQUAL "") + set(SDRPLAY_V3 ON) + set(objectName dab-sdrplay-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(WAVFILES) + if (objectName STREQUAL "") + set(WAVFILES ON) + set(objectName dab-files-4) + else () + message ("Ignoring second option") + endif () +endif () + +if(RAWFILES) + if (objectName STREQUAL "") + set(RAWFILES ON) + set(objectName dab-raw-4) + else () + message ("Ignoring second option") + endif () +endif () + +if (SERVER) + add_definitions(-DHAVE_SERVER) +endif () + +#for this version we need to define + + add_definitions(-DAAC_OUT) +######################################################################### + find_package (PkgConfig) + + find_package(FFTW3f) + if (NOT FFTW3F_FOUND) + message(FATAL_ERROR "please install FFTW3") + endif () + list(APPEND extraLibs ${FFTW3F_LIBRARIES}) + + find_package(Faad) + if (NOT FAAD_FOUND ) + message(FATAL_ERROR "please install libfaad") + endif () + + find_package(zlib) + if (NOT ZLIB_FOUND) + message(FATAL_ERROR "please install libz") + endif () + list(APPEND extraLibs ${ZLIB_LIBRARY}) + + + find_library (PTHREADS pthread) + if (NOT(PTHREADS)) + message (FATAL_ERROR "please install libpthread") + else (NOT(PTHREADS)) + set (extraLibs ${extraLibs} ${PTHREADS}) + endif (NOT(PTHREADS)) + +######################################################################### + find_package (PkgConfig) + +########################################################################## +# The devices +# + + if (RTL_TCP) + include_directories ( + ../devices/rtl_tcp + ) + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/rtl_tcp/rtl_tcp-client.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rtl_tcp/rtl_tcp-client.cpp + ) + + add_definitions (-DHAVE_RTL_TCP) + endif (RTL_TCP) + + if (SDRPLAY) + find_path (SDRPLAYLIB_INCLUDE_DIR + NAMES mirsdrapi-rsp.h + PATHS + /usr/local/include/ + ) + include_directories (${SDRPLAYLIB_INCLUDE_DIR}) + + find_library (SDRPLAYLIB mirsdrapi-rsp) + if(NOT(SDRPLAYLIB)) + message(FATAL_ERROR "please install -lmirsdrapi-rsp") + else(NOT(SDRPLAYLIB)) + list (APPEND extraLibs ${SDRPLAYLIB}) + endif(NOT(SDRPLAYLIB)) + + include_directories ( + ../devices/sdrplay-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/sdrplay-handler/sdrplay-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/sdrplay-handler/sdrplay-handler.cpp + ) + + add_definitions (-DHAVE_SDRPLAY) + endif (SDRPLAY) + + if (LIMESDR) + find_library (LIMELIB LimeSuite) + if(NOT(LIMELIB)) + message(FATAL_ERROR "please install LimeSuite") + else(NOT(LIMELIB)) + list (APPEND extraLibs ${LIMELIB}) + endif(NOT(LIMELIB)) + + include_directories ( + ../devices/lime-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/lime-handler/LMS7002M_parameters.h + ../devices/lime-handler/LimeSuite.h + ../devices/lime-handler/lime-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/lime-handler/lime-handler.cpp + ) + + add_definitions (-DHAVE_LIME) + endif (LIMESDR) + + if (AIRSPY) + find_package(LibAIRSPY) + if (NOT LIBAIRSPY_FOUND) + message(FATAL_ERROR "please install airspy library") + endif () + ### include_directories (${AIRSPYLIB_INCLUDE_DIR}) + + include_directories ( + ../devices/airspy-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/airspy-handler/airspy-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/airspy-handler/airspy-handler.cpp + ) + + add_definitions (-DHAVE_AIRSPY) + endif (AIRSPY) + + + if (RTLSDR) + find_package(LibRTLSDR) + if (NOT LIBRTLSDR_FOUND) + message(FATAL_ERROR "please install librtlsdr") + endif () + ###include_directories (${RTLSDR_INCLUDE_DIR}) + + include_directories ( + ../devices/rtlsdr-handler/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/rtlsdr-handler/rtlsdr-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rtlsdr-handler/rtlsdr-handler.cpp + ) + + add_definitions (-DHAVE_RTLSDR) + endif() + + if (WAVFILES) + include_directories ( + ../devices/wavfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/wavfiles/wavfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/wavfiles/wavfiles.cpp + ) + find_package(LibSndFile) + if (NOT LIBSNDFILE_FOUND) + message(FATAL_ERROR "please install libsndfile") + endif () + list(APPEND extraLibs ${LIBSNDFILE_LIBRARY}) + + add_definitions (-DHAVE_WAVFILES) + endif() + + if (HACKRF) + find_path (HACKLIB_INCLUDE_DIR + NAMES hackrf.h + PATHS + ../devices/hackrf-handler/libhackrf/ + /usr/local/include/ + ) + include_directories (${HACKLIB_INCLUDE_DIR}) + + find_library (HACKLIB hackrf) + if(NOT(HACKLIB)) + message(FATAL_ERROR "please install -lhackrf") + else(NOT(HACKLIB)) + list (APPEND extraLibs ${HACKLIB}) + endif(NOT(HACKLIB)) + + include_directories ( + ../devices/hackrf-handler + ) + + set ($(objectName)_HDRS + ${${objectName}_HDRS} + ../devices/hackrf-handler/hackrf-handler.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/hackrf-handler/hackrf-handler.cpp + ) + + add_definitions (-DHAVE_HACKRF) + endif (HACKRF) + if (RAWFILES) + include_directories ( + ../devices/rawfiles/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../devices/rawfiles/rawfiles.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../devices/rawfiles/rawfiles.cpp + ) + + add_definitions (-DHAVE_RAWFILES) + endif() + +####################################################################### +# +# Here we really start + + include_directories ( + ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + . + ./ + ./server-thread + ../devices + ../ + ../library + ../library/includes + ../library/includes/ofdm + ../library/includes/backend + ../library/includes/backend/audio + ../library/includes/backend/data + ../library/includes/backend/data/mot + ../library/includes/backend/data/journaline + ../library/includes/support + ../library/includes/support/viterbi-spiral + /usr/include/ + ) + + set (${objectName}_HDRS + ${${objectName}_HDRS} + ./ringbuffer.h + ./server-thread/tcp-server.h + ../devices/device-handler.h + ../devices/device-exceptions.h + ../dab-api.h + ../library/includes/dab-constants.h + ../library/includes/dab-processor.h + ../library/includes/ofdm/phasereference.h + ../library/includes/ofdm/phasetable.h + ../library/includes/ofdm/freq-interleaver.h + ../library/includes/ofdm/timesyncer.h + ../library/includes/ofdm/fic-handler.h + ../library/includes/ofdm/fib-table.h + ../library/includes/ofdm/ensemble.h + ../library/includes/ofdm/fib-config.h + ../library/includes/ofdm/fib-decoder.h + ../library/includes/ofdm/sample-reader.h + ../library/includes/ofdm/tii-detector.h + ../library/includes/backend/firecode-checker.h + ../library/includes/backend/backend-base.h + ../library/includes/backend/charsets.h + ../library/includes/backend/galois.h + ../library/includes/backend/reed-solomon.h + ../library/includes/backend/msc-handler.h + ../library/includes/backend/virtual-backend.h + ../library/includes/backend/audio-backend.h + ../library/includes/backend/data-backend.h + ../library/includes/backend/audio/faad-decoder.h + ../library/includes/backend/audio/mp4processor.h + ../library/includes/backend/audio/mp2processor.h + ../library/includes/backend/data/virtual-datahandler.h + ../library/includes/backend/data/tdc-datahandler.h + ../library/includes/backend/data/pad-handler.h + ../library/includes/backend/data/data-processor.h + ../library/includes/backend/data/mot/mot-handler.h + ../library/includes/backend/data/mot/mot-dir.h + ../library/includes/backend/data/mot/mot-object.h + ../library/includes/support/band-handler.h +# ../library/includes/support/viterbi-handler.h + ../library/includes/support/protTables.h + ../library/includes/support/protection.h + ../library/includes/support/uep-protection.h + ../library/includes/support/eep-protection.h + ../library/includes/support/fft-handler.h + ../library/includes/support/dab-params.h + ../library/includes/support/tii_table.h + ../library/includes/support/viterbi-spiral/viterbi-spiral.h + ) + + set (${objectName}_SRCS + ${${objectName}_SRCS} + ./main.cpp + ./server-thread/tcp-server.cpp + ../devices/device-handler.cpp + ../library/dab-api.cpp + ../library/src/dab-processor.cpp + ../library/src/ofdm/ofdm-decoder.cpp + ../library/src/ofdm/phasereference.cpp + ../library/src/ofdm/phasetable.cpp + ../library/src/ofdm/freq-interleaver.cpp + ../library/src/ofdm/timesyncer.cpp + ../library/src/ofdm/sample-reader.cpp + ../library/src/ofdm/fic-handler.cpp + ../library/src/ofdm/ensemble.cpp + ../library/src/ofdm/fib-config.cpp + ../library/src/ofdm/fib-decoder.cpp + ../library/src/ofdm/tii-detector.cpp + ../library/src/backend/firecode-checker.cpp + ../library/src/backend/backend-base.cpp + ../library/src/backend/charsets.cpp + ../library/src/backend/galois.cpp + ../library/src/backend/reed-solomon.cpp + ../library/src/backend/msc-handler.cpp + ../library/src/backend/virtual-backend.cpp + ../library/src/backend/audio-backend.cpp + ../library/src/backend/data-backend.cpp + ../library/src/backend/audio/mp4processor.cpp + ../library/src/backend/audio/mp2processor.cpp + ../library/src/backend/data/virtual-datahandler.cpp + ../library/src/backend/data/tdc-datahandler.cpp + ../library/src/backend/data/pad-handler.cpp + ../library/src/backend/data/data-processor.cpp + ../library/src/backend/data/mot/mot-handler.cpp + ../library/src/backend/data/mot/mot-dir.cpp + ../library/src/backend/data/mot/mot-object.cpp + ../library/src/support/band-handler.cpp +# ../library/src/support/viterbi-handler.cpp + ../library/src/support/protTables.cpp + ../library/src/support/protection.cpp + ../library/src/support/eep-protection.cpp + ../library/src/support/uep-protection.cpp + ../library/src/support/fft-handler.cpp + ../library/src/support/dab-params.cpp + ../library/src/support/tii_table.cpp + ../library/src/support/viterbi-spiral/viterbi-spiral.cpp + ) + + if (X64_DEFINED) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../library/src/support/viterbi-spiral/spiral-sse.c + ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../library/src/support/viterbi-spiral/spiral-sse.h + ) + add_definitions (-DSSE_AVAILABLE) + elseif (RPI_DEFINED) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../library/src/support/viterbi-spiral/spiral-neon.c + ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../library/src/support/viterbi-spiral/spiral-neon.h + ) + add_definitions (-DNEON_AVAILABLE) + # compiler options moved below add_executable .. and target specific + #set (CMAKE_CXX_FLAGS "${CMAKE_XCC_FLAGS} -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4") + #set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4") + else (X64_DEFINED) + set (${objectName}_SRCS + ${${objectName}_SRCS} + ../library/src/support/viterbi-spiral/spiral-no-sse.c + ) + set (${objectName}_HDRS + ${${objectName}_HDRS} + ../library/src/support/viterbi-spiral/spiral-no-sse.h + ) + endif (X64_DEFINED) + + include_directories ( + ${FFTW_INCLUDE_DIRS} + ${FAAD_INCLUDE_DIRS} + ${SNDFILES_INCLUDE_DIRS} + ) + +##################################################################### + + add_executable (${objectName} + ${${objectName}_SRCS} + ) + + if (RPI_DEFINED) + # compiler options seem changed with gcc versions. gcc 8.3.0 on Raspbian didn't accept -mcpu .. + # test options with "make VERBOSE=1" + target_compile_options(${objectName} PRIVATE -march=armv7-a -mfloat-abi=hard -mfpu=neon-vfpv4 ) + endif() + + target_link_libraries (${objectName} + ${extraLibs} + ${FAAD_LIBRARIES} + ${CMAKE_DL_LIBS} + ) + + INSTALL (TARGETS ${objectName} DESTINATION .) + +######################################################################## +# Create uninstall target +######################################################################## + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) diff --git a/example-5/CMakeLists.txt b/example-5/CMakeLists.txt index dbcbd8c..4d3c1ee 100644 --- a/example-5/CMakeLists.txt +++ b/example-5/CMakeLists.txt @@ -406,7 +406,6 @@ endif () ../library/includes/ofdm/tii-detector.h ../library/includes/backend/firecode-checker.h ../library/includes/backend/backend-base.h - ../library/includes/backend/charsets.h ../library/includes/backend/galois.h ../library/includes/backend/reed-solomon.h ../library/includes/backend/msc-handler.h @@ -425,6 +424,7 @@ endif () ../library/includes/backend/data/mot/mot-dir.h ../library/includes/backend/data/mot/mot-object.h ../library/includes/support/band-handler.cpp + ../library/includes/support/charsets.h # ../library/includes/support/viterbi-handler.h ../library/includes/support/protTables.h ../library/includes/support/protection.h @@ -458,7 +458,6 @@ endif () ../library/src/ofdm/tii-detector.cpp ../library/src/backend/firecode-checker.cpp ../library/src/backend/backend-base.cpp - ../library/src/backend/charsets.cpp ../library/src/backend/galois.cpp ../library/src/backend/reed-solomon.cpp ../library/src/backend/msc-handler.cpp @@ -476,6 +475,7 @@ endif () ../library/src/backend/data/mot/mot-dir.cpp ../library/src/backend/data/mot/mot-object.cpp ../library/src/support/band-handler.cpp + ../library/src/support/charsets.cpp ../library/src/support/viterbi-handler.cpp ../library/src/support/protTables.cpp ../library/src/support/protection.cpp diff --git a/library/dab-api.cpp b/library/dab-api.cpp index 6e65cbb..894200a 100644 --- a/library/dab-api.cpp +++ b/library/dab-api.cpp @@ -1,6 +1,6 @@ # /* - * Copyright (C) 2016, 2017 + * Copyright (C) 2016, 2025 * Jan van Katwijk (J.vanKatwijk@gmail.com) * Lazy Chair Computing * @@ -58,52 +58,52 @@ void dabReset_msc (void *Handle) { ((dabProcessor *)Handle) -> reset_msc (); } -bool is_audioService (void *Handle, const char *name) { - return ((dabProcessor *)Handle) -> kindofService (std::string (name)) == +bool is_audioService (void *Handle, const std::string &name) { + return ((dabProcessor *)Handle) -> serviceType (name) == AUDIO_SERVICE; } -bool is_dataService (void *Handle, const char *name) { - return ((dabProcessor *)Handle) -> kindofService (std::string (name)) == +bool is_dataService (void *Handle, const std::string &name) { + return ((dabProcessor *)Handle) -> serviceType (name) == PACKET_SERVICE; } -void dataforAudioService (void *Handle, - const char *name, - audiodata *d, int o) { +void dataforAudioService (void *Handle, const std::string &name, + audiodata &d, int o) { ((dabProcessor *)Handle) -> dataforAudioService (name, d, o); } -void dataforDataService (void *Handle, - const char *name, packetdata *pd, int o) { +void dataforDataService (void *Handle, const std::string &name, + packetdata &pd, int o) { ((dabProcessor *)Handle) -> dataforDataService (name, pd, o); } -void set_audioChannel (void *Handle, audiodata *ad) { +void set_audioChannel (void *Handle, audiodata &ad) { ((dabProcessor *)Handle) -> set_audioChannel (ad); } -void set_dataChannel (void *Handle, packetdata *pd) { +void set_dataChannel (void *Handle, packetdata &pd) { ((dabProcessor *)Handle) -> set_dataChannel (pd); } -int32_t dab_getSId (void *Handle, const char* c_s) { - std::string s(c_s); - return ((dabProcessor *)Handle) -> get_SId (s); +int32_t dab_getSId (void *Handle, const std::string &c_s) { + return ((dabProcessor *)Handle) -> get_SId (c_s); +} +// +std::string dab_getserviceName (void *Handle, uint32_t SId) { + return ((dabProcessor *)Handle) -> get_serviceName (SId); + } -void dab_getserviceName (void *Handle, int32_t SId, char *out) { - std::string s = ((dabProcessor *)Handle) -> get_serviceName (SId); - const char * t = s. c_str (); - (void)strcpy (out, t); +std::string get_ensembleName (void *Handle) { + return ((dabProcessor *)Handle) -> get_ensembleName (); } #ifdef _MSC_VER #include extern "C" { -void usleep(int usec) -{ +void usleep(int usec) { HANDLE timer; LARGE_INTEGER ft; @@ -115,10 +115,10 @@ void usleep(int usec) CloseHandle(timer); } -void sleep(int seconds) -{ - Sleep (seconds*1000); +void sleep(int seconds) { + Sleep (seconds * 1000); +} } -} #endif + diff --git a/library/includes/backend/msc-handler.h b/library/includes/backend/msc-handler.h index 4430027..795a901 100644 --- a/library/includes/backend/msc-handler.h +++ b/library/includes/backend/msc-handler.h @@ -49,8 +49,8 @@ public: void *); ~mscHandler (); void process_mscBlock (std::vector &, int16_t); - void set_audioChannel (audiodata *); - void set_dataChannel (packetdata *); + void set_audioChannel (audiodata &); + void set_dataChannel (packetdata &); void reset (); void stop (); void start (); diff --git a/library/includes/bit-extractors.h b/library/includes/bit-extractors.h new file mode 100644 index 0000000..692ec90 --- /dev/null +++ b/library/includes/bit-extractors.h @@ -0,0 +1,156 @@ +# +/* + * Copyright (C) 2014 .. 2020 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB program + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// +// inline functions for extracting bits from the DAB data +#pragma once +#include + +static inline +uint16_t getBits (const uint8_t *d, int32_t offset, int16_t size) { +int16_t i; +uint16_t res = 0; + + for (i = 0; i < size; i ++) { + res <<= 1; + res |= (d [offset + i]) & 01; + } + return res; +} + +static inline +uint16_t getBits_1 (const uint8_t *d, int32_t offset) { + return (d [offset] & 0x01); +} + +static inline +uint16_t getBits_2 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + return res; +} + +static inline +uint16_t getBits_3 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + res <<= 1; + res |= d [offset + 2]; + return res; +} + +static inline +uint16_t getBits_4 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + res <<= 1; + res |= d [offset + 2]; + res <<= 1; + res |= d [offset + 3]; + return res; +} + +static inline +uint16_t getBits_5 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + res <<= 1; + res |= d [offset + 2]; + res <<= 1; + res |= d [offset + 3]; + res <<= 1; + res |= d [offset + 4]; + return res; +} + +static inline +uint16_t getBits_6 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + res <<= 1; + res |= d [offset + 2]; + res <<= 1; + res |= d [offset + 3]; + res <<= 1; + res |= d [offset + 4]; + res <<= 1; + res |= d [offset + 5]; + return res; +} + +static inline +uint16_t getBits_7 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + res <<= 1; + res |= d [offset + 2]; + res <<= 1; + res |= d [offset + 3]; + res <<= 1; + res |= d [offset + 4]; + res <<= 1; + res |= d [offset + 5]; + res <<= 1; + res |= d [offset + 6]; + return res; +} + +static inline +uint16_t getBits_8 (const uint8_t *d, int32_t offset) { +uint16_t res = d [offset]; + res <<= 1; + res |= d [offset + 1]; + res <<= 1; + res |= d [offset + 2]; + res <<= 1; + res |= d [offset + 3]; + res <<= 1; + res |= d [offset + 4]; + res <<= 1; + res |= d [offset + 5]; + res <<= 1; + res |= d [offset + 6]; + res <<= 1; + res |= d [offset + 7]; + return res; +} + + +static inline +uint32_t getLBits (const uint8_t *d, + int32_t offset, int16_t amount) { +uint32_t res = 0; +int16_t i; + + for (i = 0; i < amount; i ++) { + res <<= 1; + res |= (d [offset + i] & 01); + } + return res; +} + diff --git a/library/includes/dab-constants.h b/library/includes/dab-constants.h index 4c685d8..8de3e89 100644 --- a/library/includes/dab-constants.h +++ b/library/includes/dab-constants.h @@ -74,6 +74,8 @@ using namespace std; #define CURRENT_VERSION "2.0alfa" +#include +typedef std::complex Complex; #define DAB 0100 #define DAB_PLUS 0101 @@ -90,6 +92,19 @@ using namespace std; #define DIFF_LENGTH 42 #define THRESHOLD 3 +typedef struct { + uint8_t ecc; + uint32_t EId; + uint8_t mainId; + uint8_t subId; + float strength; + float phase; + bool norm; + int index; + bool collision; + uint16_t pattern; +} tiiData; + static inline bool isIndeterminate (float x) { return x != x; diff --git a/library/includes/dab-processor.h b/library/includes/dab-processor.h index 6487082..e85ff12 100644 --- a/library/includes/dab-processor.h +++ b/library/includes/dab-processor.h @@ -1,6 +1,6 @@ # /* - * Copyright (C) 2016, 2017 + * Copyright (C) 2016, 2025 * Jan van Katwijk (J.vanKatwijk@gmail.com) * Lazy Chair Computing * @@ -57,23 +57,22 @@ public: bool signalSeemsGood (); void show_Corrector (int); // inheriting from our delegates - void setSelectedService (const std::string &); - uint8_t kindofService (const std::string &); + uint8_t serviceType (const std::string &); void dataforAudioService (const std::string &, - audiodata *); + audiodata &); void dataforAudioService (const std::string &, - audiodata *, int16_t); + audiodata &, int16_t); void dataforDataService (const std::string &, - packetdata *); + packetdata &); void dataforDataService (const std::string &, - packetdata *, int16_t); + packetdata &, int16_t); int32_t get_SId (const std::string &s); std::string get_serviceName (int32_t); - void set_audioChannel (audiodata *); - void set_dataChannel (packetdata *); + void set_audioChannel (audiodata &); + void set_dataChannel (packetdata &); + void reset_msc (); std::string get_ensembleName (); void clearEnsemble (); - void reset_msc (); private: deviceHandler *inputDevice; dabParams params; @@ -92,6 +91,7 @@ private: void *userData; std::atomic running; bool isSynced; + int threshold; int snr; int32_t T_null; int32_t T_u; diff --git a/library/includes/ofdm/ensemble.h b/library/includes/ofdm/ensemble.h new file mode 100644 index 0000000..50cd98e --- /dev/null +++ b/library/includes/ofdm/ensemble.h @@ -0,0 +1,66 @@ +# +/* + * Copyright (C) 2015 .. 2025 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB and modified for dab-cmdline + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#pragma once +#include +#include +#include + +// ensemble information relates to FIG1, basically some +// general, i.e. ensemble wide, data and mapping tables for +// primary and secondary services to SId's resp (SId x SCIds) +// Itis now completely separated from the FIG1 tables +class ensemble { +public: + ensemble () { + reset (); + } + ~ensemble () { + } + + uint8_t eccByte; + uint8_t lto; + uint16_t EId; + std::string ensembleName; + bool namePresent; + typedef struct { + std::string name; + std::string shortName; + uint32_t SId; + uint8_t programType; + uint8_t SCIds; + std::vector fmFrequencies; + } service; + + bool isSynced; + std::vector primaries; + std::vector secondaries; + + void reset (); + uint32_t serviceToSId (const std::string &s); + std::string SIdToserv (uint32_t SId); + int programType (uint32_t); + std::vector fmFrequencies (uint32_t); +}; + + diff --git a/library/includes/ofdm/fib-config.h b/library/includes/ofdm/fib-config.h new file mode 100644 index 0000000..46ff070 --- /dev/null +++ b/library/includes/ofdm/fib-config.h @@ -0,0 +1,158 @@ +# +/* + * Copyright (C) 2015 .. 2025 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#pragma once +// +// Implementation of the FIG database +#include +#include + +class fibConfig { +public: + fibConfig (); + ~fibConfig (); +// The tables cannot made private (unless set functions for +// all structs and components are made) +// Most components are a direct translation of the +// FIG +// SId is a small optimization, not really needed +// of service components + typedef struct { + uint32_t SId; + std::vector comps; + uint16_t announcing; + } SId_struct; +// +// Subchannel is filled by FIG0/1 + typedef struct { + bool inUse; // will be removed after handling eti + uint16_t subChId; + int32_t Length; + int32_t startAddr; + bool shortForm; + int32_t protLevel; + int32_t bitRate; + int16_t FEC_scheme; + } subChannel; + +// service components filled by FIG0/2 +// The "C" stands for Common + typedef struct { + uint32_t SId; + uint8_t SCId; + uint8_t subChId; + uint8_t TMid; + int compNr; + uint8_t ASCTy; + uint8_t PS_flag; + } serviceComp_C; +// +// additional component information for packet data, +// the "P" stands for Packet, FIG0/3 + typedef struct { + uint16_t SCId; + uint8_t CAOrg_flag; + uint8_t DG_flag; + uint8_t DSCTy; + uint8_t subChId; + uint16_t packetAddress; + } serviceComp_P; +// +// some more general component information +// the "G" stands for General, FIG0/8 + typedef struct { + uint32_t SId; + uint8_t LS_flag; + uint8_t SCIds; + uint8_t subChId; + uint16_t SCId; + } serviceComp_G; +// +// Data for the service components Language +// FIG0/5 + typedef struct { + uint8_t LS_flag; + uint8_t subChId; + uint16_t SCId; + uint8_t language; + } SC_language; + +// +// Data for the apptype of packet components FIG0/13 + typedef struct { + uint32_t SId; + uint8_t SCIds; + uint16_t Apptype; + } AppType; +// +// Data for the program type FIG0/17 + typedef struct { + uint32_t SId; + uint8_t typeCode; + } programType; + +// +// data for the announcement support FIG0/18 + typedef struct { + uint16_t SId; + uint16_t asuFlags; + uint8_t clusterId; + } FIG18_cluster; +// +// for each type a table + std::vector SId_table; + std::vector subChannel_table; // FIG0/1 + std::vector SC_C_table; // FIG0/2 + std::vector SC_P_table; // FIG0/3 + std::vector SC_G_table; // FIG0/8 + std::vector language_table; // FIG0/5 + std::vector AppType_table; // FIG0/13 + std::vector programType_table; // FIG017 + std::vector announcement_table; // FIG0/18 + + int32_t dateTime [8]; + void reset (); + int serviceIdOf (int index); + int SCIdsOf (int index); + int subChannelOf (int index); + int startAddressOf (int index); + int lengthOf (int index); + bool shortFormOf (int index); + int16_t protLevelOf (int index); + int bitRateOf (int index); + int dabTypeOf (int index); + int languageOf (int index); + int appTypeOf (int index); + int FEC_schemeOf (int index); + int packetAddressOf (int index); + int DSCTy (int index); + int DG_flag (int index); + int findIndex_SC_P_Table (uint16_t SCId); + int findIndex_subChannel_table (uint8_t subChId); + int findIndex_languageTable (uint8_t key_1, uint16_t key_2); + int findIndexApptype_table (uint32_t SId, uint8_t SCIds); + bool compIsKnown (serviceComp_C &newComp); + + int freeSpace (); +}; + diff --git a/library/includes/ofdm/fib-decoder.h b/library/includes/ofdm/fib-decoder.h new file mode 100644 index 0000000..d44c94b --- /dev/null +++ b/library/includes/ofdm/fib-decoder.h @@ -0,0 +1,155 @@ +# +/* + * Copyright (C) 2016 .. 2023 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of Qt-DAB + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-TAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +# +#pragma once +// +#include +#include +#include "msc-handler.h" +// +#include +#include +#include +#include +#include +#include "dab-api.h" +#include "dab-constants.h" + +class fibConfig; +class ensemble; +class fibDecoder { +public: + fibDecoder (API_struct *, void *); + ~fibDecoder (); + + void clear_ensemble (); + void connect_channel (); + void disconnect_channel (); + void reset (); + bool syncReached (); + + uint16_t get_announcing (uint16_t); + uint32_t get_SId (int); + std::string get_serviceName (uint32_t /* SId */); + std::string get_ensembleName (); + uint8_t serviceType (int); + int getServiceComp (const std::string &); + int get_serviceComp (uint32_t SId, int compnr); + int getServiceComp (uint32_t, int); + int get_serviceComp_SCIds (uint32_t, int); + bool isPrimary (const std::string &); + void audioData (int, audiodata &); + void packetData (int, packetdata &); + int get_nrComps (uint32_t); + int nrChannels (); + uint8_t get_ecc (); + uint32_t get_EId (); + std::vector getFrequency (const std::string &); + int32_t get_CIFcount (); + void get_CIFcount (int16_t &, int16_t &); + uint32_t julianDate (); + int freeSpace (); + void process_FIB (uint8_t *, uint16_t); +private: + API_struct *theParameters; + name_of_ensemble_t name_of_ensemble; + serviceName_t serviceName; + void *userData; + + fibConfig *currentConfig; + fibConfig *nextConfig; + ensemble *theEnsemble; + void adjustTime (int32_t *dateTime); + + void process_FIG0 (uint8_t *); + void process_FIG1 (uint8_t *); + void FIG0Extension0 (uint8_t *); + void FIG0Extension1 (uint8_t *); + void FIG0Extension2 (uint8_t *); + void FIG0Extension3 (uint8_t *); +// void FIG0Extension4 (uint8_t *); + void FIG0Extension5 (uint8_t *); +// void FIG0Extension6 (uint8_t *); + void FIG0Extension7 (uint8_t *); + void FIG0Extension8 (uint8_t *); + void FIG0Extension9 (uint8_t *); + void FIG0Extension10 (uint8_t *); +// void FIG0Extension11 (uint8_t *); +// void FIG0Extension12 (uint8_t *); + void FIG0Extension13 (uint8_t *); + void FIG0Extension14 (uint8_t *); +// void FIG0Extension15 (uint8_t *); +// void FIG0Extension16 (uint8_t *); + void FIG0Extension17 (uint8_t *); + void FIG0Extension18 (uint8_t *); + void FIG0Extension19 (uint8_t *); +// void FIG0Extension20 (uint8_t *); + void FIG0Extension21 (uint8_t *); +// void FIG0Extension22 (uint8_t *); +// void FIG0Extension23 (uint8_t *); +// void FIG0Extension24 (uint8_t *); +// void FIG0Extension25 (uint8_t *); +// void FIG0Extension26 (uint8_t *); + + int16_t HandleFIG0Extension1 (uint8_t *, + int16_t, + uint8_t, uint8_t, uint8_t); + int16_t HandleFIG0Extension2 (uint8_t *, + int16_t, + uint8_t, uint8_t, uint8_t); + int16_t HandleFIG0Extension3 (uint8_t *, + int16_t, + uint8_t, uint8_t, uint8_t); + int16_t HandleFIG0Extension5 (uint8_t *, + uint8_t, uint8_t, uint8_t, + int16_t); + int16_t HandleFIG0Extension8 (uint8_t *, + int16_t, + uint8_t, uint8_t, uint8_t); + int16_t HandleFIG0Extension13 (uint8_t *, + int16_t, + uint8_t, uint8_t, uint8_t); + int16_t HandleFIG0Extension21 (uint8_t*, + uint8_t, uint8_t, uint8_t, + int16_t); + + void FIG1Extension0 (uint8_t *); + void FIG1Extension1 (uint8_t *); +// void FIG1Extension2 (uint8_t *); +// void FIG1Extension3 (uint8_t *); + void FIG1Extension4 (uint8_t *); + void FIG1Extension5 (uint8_t *); + void FIG1Extension6 (uint8_t *); + + mutex fibLocker; + std::atomic CIFcount; + int16_t CIFcount_hi; + int16_t CIFcount_lo; + uint32_t mjd; // julianDate + + void handle_announcement (uint16_t SId, + uint16_t flags, + uint8_t SubChId); +}; + + diff --git a/library/includes/ofdm/fib-processor.h b/library/includes/ofdm/fib-processor.h-old similarity index 100% rename from library/includes/ofdm/fib-processor.h rename to library/includes/ofdm/fib-processor.h-old diff --git a/library/includes/ofdm/fib-table.h b/library/includes/ofdm/fib-table.h new file mode 100644 index 0000000..6406907 --- /dev/null +++ b/library/includes/ofdm/fib-table.h @@ -0,0 +1,99 @@ +# +/* + * Copyright (C) 2016 .. 2023 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of Qt-DAB + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * fib decoder. Functionality is shared between fic handler, i.e. the + * one preparing the FIC blocks for processing, and the mainthread + * from which calls are coming on selecting a program + * + * + * Definition of the "configuration" as maintained during reception of + * a channel + * + * file is to be included in the source of fib-decoder + */ +// Tabelle ETSI EN 300 401 Page 50 +// Table is copied from the work of Michael Hoehn + const int ProtLevel[64][3] = {{16,5,32}, // Index 0 + {21,4,32}, + {24,3,32}, + {29,2,32}, + {35,1,32}, // Index 4 + {24,5,48}, + {29,4,48}, + {35,3,48}, + {42,2,48}, + {52,1,48}, // Index 9 + {29,5,56}, + {35,4,56}, + {42,3,56}, + {52,2,56}, + {32,5,64}, // Index 14 + {42,4,64}, + {48,3,64}, + {58,2,64}, + {70,1,64}, + {40,5,80}, // Index 19 + {52,4,80}, + {58,3,80}, + {70,2,80}, + {84,1,80}, + {48,5,96}, // Index 24 + {58,4,96}, + {70,3,96}, + {84,2,96}, + {104,1,96}, + {58,5,112}, // Index 29 + {70,4,112}, + {84,3,112}, + {104,2,112}, + {64,5,128}, + {84,4,128}, // Index 34 + {96,3,128}, + {116,2,128}, + {140,1,128}, + {80,5,160}, + {104,4,160}, // Index 39 + {116,3,160}, + {140,2,160}, + {168,1,160}, + {96,5,192}, + {116,4,192}, // Index 44 + {140,3,192}, + {168,2,192}, + {208,1,192}, + {116,5,224}, + {140,4,224}, // Index 49 + {168,3,224}, + {208,2,224}, + {232,1,224}, + {128,5,256}, + {168,4,256}, // Index 54 + {192,3,256}, + {232,2,256}, + {280,1,256}, + {160,5,320}, + {208,4,320}, // index 59 + {280,2,320}, + {192,5,384}, + {280,3,384}, + {416,1,384}}; + diff --git a/library/includes/ofdm/fic-handler.h b/library/includes/ofdm/fic-handler.h index 4d3e2b7..357906a 100644 --- a/library/includes/ofdm/fic-handler.h +++ b/library/includes/ofdm/fic-handler.h @@ -30,7 +30,7 @@ #include #include #include "viterbi-spiral.h" -#include "fib-processor.h" +#include "fib-decoder.h" #include #include #include "dab-api.h" @@ -46,19 +46,20 @@ public: void clearEnsemble (); bool syncReached (); int16_t get_ficRatio (); - std::string nameFor (int32_t); - int32_t SIdFor (const std::string &); - uint8_t kindofService (const std::string &); - void dataforDataService (const std::string &, - packetdata *, int); - void dataforAudioService (const std::string &, - audiodata *, int); -// + int get_SId (int); + std::string get_serviceName (uint32_t /* SId */); + uint8_t serviceType (int); + void audioData (int, audiodata &); + void packetData (int, packetdata &); + int getServiceComp (const std::string &); int32_t get_CIFcount (); void reset (); + uint8_t get_ecc (); + uint32_t get_EId (); + std::string get_ensembleName (); private: - fib_processor fibProcessor; + fibDecoder fibHandler; fib_quality_t fib_qualityHandler; dabParams params; void *userData; diff --git a/library/includes/ofdm/phasetable.h b/library/includes/ofdm/phasetable.h index 99d8e5d..417477d 100644 --- a/library/includes/ofdm/phasetable.h +++ b/library/includes/ofdm/phasetable.h @@ -24,7 +24,9 @@ #include #include +#include #include "dab-constants.h" +#include "dab-params.h" struct phasetableElement { int32_t kmin, kmax; @@ -37,9 +39,11 @@ class phaseTable { public: phaseTable (int16_t); ~phaseTable (); + std::vector> refTable; float get_Phi (int32_t); private: - + dabParams params; + int16_t T_u; struct phasetableElement *currentTable; int16_t Mode; int32_t h_table (int32_t i, int32_t j); diff --git a/library/includes/ofdm/tii-detector.h b/library/includes/ofdm/tii-detector.h index bfb00c0..eb03ed4 100644 --- a/library/includes/ofdm/tii-detector.h +++ b/library/includes/ofdm/tii-detector.h @@ -26,28 +26,48 @@ #include #include "dab-params.h" #include "fft-handler.h" +#include "phasetable.h" #include +#define NUM_GROUPS 8 +#define GROUPSIZE 24 + + +typedef std::complex Complex; +typedef struct { + int index; + float value; + bool norm; +} resultPair; + + class TII_Detector { public: TII_Detector (uint8_t dabMode); ~TII_Detector (); void reset (); - void addBuffer (std::vector>); - uint16_t processNULL (); + void addBuffer (const std::vector &); + std::vector processNULL (int16_t); + private: - void collapse (std::complex *, - float *); - int16_t depth; - uint8_t invTable [256]; - dabParams params; - fft_handler my_fftHandler; - int16_t T_u; - int16_t carriers; - std::complex *fft_buffer; - std::vector > theBuffer; + dabParams params; + phaseTable theTable; + std::vector table_2; + void resetBuffer (); + uint16_t getPattern (int); + uint16_t nrPatterns (); + std::vector nullSymbolBuffer; std::vector window; + int16_t T_u; + int16_t T_g; + int16_t carriers; + fft_handler my_fftHandler; + Complex decodedBuffer [768]; + void collapse (const Complex *, + Complex *, Complex *, bool); + + int tiiThreshold; }; diff --git a/library/includes/backend/charsets.h b/library/includes/support/charsets.h similarity index 100% rename from library/includes/backend/charsets.h rename to library/includes/support/charsets.h diff --git a/library/includes/support/fft-handler.h b/library/includes/support/fft-handler.h index 35c583b..0af56f1 100644 --- a/library/includes/support/fft-handler.h +++ b/library/includes/support/fft-handler.h @@ -34,6 +34,7 @@ public: fft_handler (uint8_t); ~fft_handler (); complex *getVector (); + void fft (Complex *); void do_FFT (); void do_iFFT (); private: diff --git a/library/includes/time-converter.h b/library/includes/time-converter.h new file mode 100644 index 0000000..3e1a670 --- /dev/null +++ b/library/includes/time-converter.h @@ -0,0 +1,29 @@ +# +/* + * Copyright (C) 2013 .. 2024 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#pragma once + +#include "stdint.h" + +void convertTime (uint32_t, uint16_t *); + diff --git a/library/src/backend/data/data-processor.cpp b/library/src/backend/data/data-processor.cpp index 1e387cc..437c7ab 100644 --- a/library/src/backend/data/data-processor.cpp +++ b/library/src/backend/data/data-processor.cpp @@ -252,7 +252,7 @@ int dataProcessor::addPacket (uint8_t *vec, int fillPointer) { int16_t packetLength = (getBits_2 (vec, 0) + 1) * 24; // Assert theBuffer. size () == RDIMS * FRAMESIZE + 48 - if (fillPointer + packetLength > theBuffer. size ()) { + if ((uint32_t)fillPointer + packetLength > theBuffer. size ()) { clear_FECtable (); return 0; } @@ -261,7 +261,7 @@ int dataProcessor::addPacket (uint8_t *vec, uint8_t temp = 0; for (int j = 0; j < 8; j ++) temp = (temp << 1) | (vec [i * 8 + j] == 0 ? 0 : 1); - if (fillPointer + i >= theBuffer. size ()) + if ((uint32_t)fillPointer + i >= theBuffer. size ()) fprintf (stderr, "%d is too large\n", fillPointer + i); else theBuffer [fillPointer + i] = temp; @@ -366,6 +366,7 @@ uint8_t rsOut [FRAMESIZE]; for (int i = 0; i < RSDIMS; i ++) { int xx = my_rsDecoder. dec (table [i], rsOut, 51); + (void)xx; // fprintf (stderr, "rs decoder says %d\n", xx); for (int j = 0; j < FRAMESIZE; j ++) table [i][j] = rsOut [j]; diff --git a/library/src/backend/msc-handler.cpp b/library/src/backend/msc-handler.cpp index cc3253b..5e334dd 100644 --- a/library/src/backend/msc-handler.cpp +++ b/library/src/backend/msc-handler.cpp @@ -95,19 +95,18 @@ void mscHandler::reset () { // so, a little bit of locking seems wise while // the actual changing of the settings is done in the // thread executing process_mscBlock -void mscHandler::set_audioChannel (audiodata *d) { +void mscHandler::set_audioChannel (audiodata &d) { locker. lock (); // // we could assert here that theBackend == nullptr - theBackends. push_back (new audioBackend (d, p, userData)); + theBackends. push_back (new audioBackend (&d, p, userData)); work_to_do. store (true); locker. unlock (); } - -void mscHandler::set_dataChannel (packetdata *d) { +void mscHandler::set_dataChannel (packetdata &d) { locker. lock (); - theBackends. push_back (new dataBackend (d, p, userData)); + theBackends. push_back (new dataBackend (&d, p, userData)); work_to_do. store (true); locker. unlock (); } diff --git a/library/src/dab-processor.cpp b/library/src/dab-processor.cpp index 7f41687..2eb1fc2 100644 --- a/library/src/dab-processor.cpp +++ b/library/src/dab-processor.cpp @@ -1,6 +1,6 @@ # /* - * Copyright (C) 2016, 2017 + * Copyright (C) 2016, 2025 * Jan van Katwijk (J.vanKatwijk@gmail.com) * Lazy Chair Computing * @@ -33,8 +33,10 @@ dabProcessor::dabProcessor (deviceHandler *inputDevice, API_struct *p, - RingBuffer> *spectrumBuffer, - RingBuffer> *iqBuffer, + RingBuffer> * + spectrumBuffer, + RingBuffer> * + iqBuffer, void *userData): params (p -> dabMode), myReader (this, @@ -64,6 +66,7 @@ this -> carriers = params. get_carriers (); this -> carrierDiff = params. get_carrierDiff (); this -> tii_counter = 0; + this -> threshold = 6; isSynced = false; snr = 0; running. store (false); @@ -104,12 +107,11 @@ int startIndex = -1; running. store (true); my_ficHandler. reset (); myReader. setRunning (true); -// my_mscHandler. start (); try { myReader. reset (); for (i = 0; i < T_F / 2; i ++) { - jan_abs (myReader. getSample (0)); + (void)jan_abs (myReader. getSample (0)); } notSynced: @@ -130,6 +132,7 @@ notSynced: case NO_END_OF_DIP_FOUND: goto notSynced; } + myReader. getSamples (ofdmBuffer. data (), T_u, coarseOffset + fineOffset); @@ -256,11 +259,17 @@ SyncOnPhase: if (wasSecond (my_ficHandler. get_CIFcount (), ¶ms)) { my_TII_Detector. addBuffer (ofdmBuffer); if (++tii_counter >= 4) { - uint16_t res = - my_TII_Detector. processNULL (); - if ((res != 0) && (show_tii != nullptr)) - show_tii (res, userData); - + std::vector res = + my_TII_Detector. processNULL (threshold); + if ((res. size () > 0) && (show_tii != nullptr)) { + uint8_t the_ecc = my_ficHandler. get_ecc (); + uint16_t the_EId = my_ficHandler. get_EId (); + for (auto &d : res) { + d. ecc = the_ecc; + d. EId = the_EId; + show_tii (&d, userData); + } + } tii_counter = 0; my_TII_Detector. reset (); } @@ -278,6 +287,7 @@ SyncOnPhase: } goto Check_endofNull; } + catch (int e) { fprintf (stderr, "dab processor will stop\n"); } @@ -316,48 +326,58 @@ bool dabProcessor::signalSeemsGood () { } // // to be handled by delegates -uint8_t dabProcessor::kindofService (const std::string &s) { -std::string ss = s; - return my_ficHandler. kindofService (ss); +uint8_t dabProcessor::serviceType (const std::string &s) { +int index = my_ficHandler. getServiceComp (s); + fprintf (stderr, "for service %s we find index %d\n", + s. c_str (), index); + return my_ficHandler. serviceType (index); } void dabProcessor::dataforAudioService (const std::string &s, - audiodata *dd) { -std::string ss = s; - my_ficHandler. dataforAudioService (ss, dd, 0); + audiodata &ad) { + int index = my_ficHandler. getServiceComp (s); + my_ficHandler. audioData (index, ad); } void dabProcessor::dataforAudioService (const std::string &s, - audiodata *d, int16_t c) { -std::string ss = s; - my_ficHandler. dataforAudioService (ss, d, c); + audiodata &ad, int16_t o) { + (void)o; + int index = my_ficHandler. getServiceComp (s); + my_ficHandler. audioData (index, ad); } void dabProcessor::dataforDataService (const std::string &s, - packetdata *d, int16_t c) { -std::string ss = s; - my_ficHandler. dataforDataService (ss, d, c); + packetdata &pd) { + int index = my_ficHandler. getServiceComp (s); + my_ficHandler. packetData (index, pd); +} + +void dabProcessor::dataforDataService (const std::string &s, + packetdata &pd, int16_t o) { + (void)o; + int index = my_ficHandler. getServiceComp (s); + my_ficHandler. packetData (index, pd); } int32_t dabProcessor::get_SId (const std::string &s) { -std::string ss = s; - return my_ficHandler. SIdFor (ss); +int index = my_ficHandler. getServiceComp (s); + return my_ficHandler. get_SId (index); } - +// std::string dabProcessor::get_serviceName (int32_t SId) { - return my_ficHandler. nameFor (SId); + return my_ficHandler. get_serviceName (SId); } void dabProcessor::reset_msc () { my_mscHandler. reset (); } -void dabProcessor::set_audioChannel (audiodata *d) { +void dabProcessor::set_audioChannel (audiodata &d) { my_mscHandler. set_audioChannel (d); - programdataHandler (d, userData); + programdataHandler (&d, userData); } -void dabProcessor::set_dataChannel (packetdata *d) { +void dabProcessor::set_dataChannel (packetdata &d) { my_mscHandler. set_dataChannel (d); } @@ -365,6 +385,10 @@ void dabProcessor::clearEnsemble () { my_ficHandler. reset (); } +std::string dabProcessor::get_ensembleName () { + return my_ficHandler. get_ensembleName (); +} + bool dabProcessor::wasSecond (int16_t cf, dabParams *p) { switch (p -> get_dabMode ()) { default: diff --git a/library/src/ofdm/ensemble.cpp b/library/src/ofdm/ensemble.cpp new file mode 100644 index 0000000..3d9708e --- /dev/null +++ b/library/src/ofdm/ensemble.cpp @@ -0,0 +1,67 @@ +# +/* + * Copyright (C) 2018 .. 2025 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB program and modified for dab-cmdline + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ensemble.h" + +void ensemble::reset () { + isSynced = false; + primaries. resize (0); + secondaries. resize (0); + namePresent = false; +} + +uint32_t ensemble::serviceToSId (const std::string &s) { + for (auto &serv: primaries) + if (serv. name == s) + return serv. SId; + for (auto &serv: secondaries) + if (serv. name == s) + return serv. SId; + return 0; +} + +std::string ensemble::SIdToserv (uint32_t SId) { + for (auto &serv: primaries) + if (serv. SId == SId) + return serv. name; + return " "; +} + +int ensemble::programType (uint32_t SId) { + for (auto &serv: primaries) + if (serv. SId == SId) + return serv. programType; + return -1; +} + +std::vector ensemble::fmFrequencies (uint32_t SId) { +std::vector res; + for (auto &serv: primaries) + if (serv. SId == SId) { + for (auto freq: serv. fmFrequencies) + res. push_back (freq); + return res; + } + return res; +} + diff --git a/library/src/ofdm/fib-config.cpp b/library/src/ofdm/fib-config.cpp new file mode 100644 index 0000000..e438335 --- /dev/null +++ b/library/src/ofdm/fib-config.cpp @@ -0,0 +1,259 @@ +# +/* + * Copyright (C) 2015 .. 2025 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "fib-config.h" +#include +#include +// +// Implementation of the FIG database +// +// While in previous versions I tried to "optimize" by +// adding properties to SIds and serviceNames, the code became +// messy and a few errors could not be handled properly. +// +// Here I took the easy approach: for (almost) each FIG, I added +// a table, and the interpretation is "as and when needed" +// Of course, on querying the FIG database, it needs more +// cycles, but at least the code now is (in my opinion) +// reasonable clear. + + fibConfig::fibConfig () {} + fibConfig::~fibConfig () {} + +void fibConfig::reset () { + SId_table. resize (0); + subChannel_table. resize (0); + SC_C_table. resize (0); + SC_P_table. resize (0); + SC_G_table. resize (0); + language_table. resize (0); + programType_table. resize (0); + AppType_table. resize (0); + announcement_table. resize (0); + memset (dateTime, 0, sizeof (dateTime)); +} + +int fibConfig::serviceIdOf (int index) { + return SC_C_table [index]. SId; +} + +int fibConfig::SCIdsOf (int index) { +serviceComp_C &comp = SC_C_table [index]; + if (comp. TMid == 0) { + for (int i = 0; i < (int)SC_G_table. size (); i ++) { + if (SC_G_table [i]. LS_flag != 0) + continue; + if (SC_G_table [i]. SId != comp. SId) + continue; + if (SC_G_table [i]. subChId == comp. subChId) + return SC_G_table [i]. SCIds; + } + return 0; // primary component + } + if (comp. TMid == 3) { // should be it + for (int i = 0; i < (int) SC_G_table. size (); i ++) { + if (SC_G_table [i]. LS_flag == 0) + continue; + if (SC_G_table [i]. SId != comp. SId) + continue; + if (SC_G_table [i]. SCId == comp. SCId) + return SC_G_table [i]. SCIds; + } + return 0; + } + return -1; +} + +int fibConfig::subChannelOf (int index) { +serviceComp_C &comp = SC_C_table [index]; + if (comp. TMid == 0) // audio + return comp. subChId; + int SCId_index = findIndex_SC_P_Table (comp. SCId); + if (SCId_index < 0) + return -1; + return SC_P_table [SCId_index]. subChId; +} + +int fibConfig::findIndex_subChannel_table (uint8_t subChId) { + for (int i = 0; i < (int)subChannel_table. size (); i ++) + if (subChannel_table [i]. subChId == subChId) + return i; + return -1; +} + +int fibConfig::startAddressOf (int index) { +int subChId = subChannelOf (index); +int subCh_index = findIndex_subChannel_table (subChId); + if (subCh_index < 0) + return -1; + return subChannel_table [subCh_index]. startAddr; +} + +int fibConfig::lengthOf (int index) { +int subChId = subChannelOf (index); +int subCh_index = findIndex_subChannel_table (subChId); + if (subCh_index < 0) + return -1; + return subChannel_table [subCh_index]. Length; +} + +bool fibConfig::shortFormOf (int index) { +int subChId = subChannelOf (index); +int subCh_index = findIndex_subChannel_table (subChId); + if (subCh_index < 0) + return -1; + return subChannel_table [subCh_index]. shortForm; +} + +int16_t fibConfig::protLevelOf (int index) { +int subChId = subChannelOf (index); +int subCh_index = findIndex_subChannel_table (subChId); + if (subCh_index < 0) + return -1; + return subChannel_table [subCh_index]. protLevel; +} + +int fibConfig::bitRateOf (int index) { +int16_t subChId = subChannelOf (index); +int subCh_index = findIndex_subChannel_table (subChId); + if (subCh_index < 0) + return -1; + return subChannel_table [subCh_index]. bitRate; +} + +int fibConfig::dabTypeOf (int index) { + if (SC_C_table [index]. TMid != 0) + return -1; + return SC_C_table [index]. ASCTy; +} + +int fibConfig::languageOf (int index) { + if (SC_C_table [index]. TMid == 0) { + int subChId = SC_C_table [index]. subChId; + for (auto < : language_table) + if ((lt. LS_flag == 0) && (lt. subChId == subChId)) + return lt. language; + } + if (SC_C_table [index]. TMid == 3) { // it should be + int SCId = SC_C_table [index]. SCId; + for (auto < : language_table) + if ((lt. LS_flag == 0) && (lt. SCId == SCId)) + return lt. language; + } + return -1; +} + +int fibConfig::appTypeOf (int index) { +uint32_t SId = SC_C_table [index]. SId; + int SCIds = SCIdsOf (index); + if (SCIds == -1) + return -1; + int appIndex = findIndexApptype_table (SId, SCIds); + if (appIndex < 0) + return -1; + return AppType_table [appIndex]. Apptype; +} + +int fibConfig::FEC_schemeOf (int index) { +int16_t subChId = subChannelOf (index); +int subCh_index = findIndex_subChannel_table (subChId); + if (index < 0) + return -1; + return subChannel_table [subCh_index]. FEC_scheme; +} + +int fibConfig::packetAddressOf (int index) { +serviceComp_C &comp = SC_C_table [index]; + if (comp. TMid != 3) + return -1; + int SCId_index = findIndex_SC_P_Table (comp. SCId); + if (SCId_index < 0) + return -1; + return SC_P_table [SCId_index]. packetAddress; +} + +int fibConfig::DSCTy (int index) { +serviceComp_C &comp = SC_C_table [index]; + if (comp. TMid != 3) + return -1; + int SCId_index = findIndex_SC_P_Table (comp. SCId); + if (SCId_index < 0) + return -1; + return SC_P_table [SCId_index]. DSCTy; +} + +int fibConfig::DG_flag (int index) { +serviceComp_C &comp = SC_C_table [index]; + if (comp. TMid != 3) + return -1; + int SCId_index = findIndex_SC_P_Table (comp. SCId); + if (SCId_index < 0) + return -1; + return SC_P_table [SCId_index]. DG_flag; +} + +int fibConfig::findIndex_SC_P_Table (uint16_t SCId) { + for (int i = 0; i < (int)SC_P_table. size (); i ++) + if (SC_P_table [i]. SCId == SCId) + return i; + return -1; +} + +int fibConfig::findIndex_languageTable (uint8_t key_1, uint16_t key_2) { + for (int i = 0; i < (int) language_table. size (); i ++) { + if (language_table [i]. LS_flag != key_1) + continue; + if ((key_1 == 0) && (language_table [i]. subChId == key_2)) + return i; + if ((key_1 == 1) && (language_table [i]. SCId == key_2)) + return i; + } + return -1; +} + +int fibConfig::findIndexApptype_table (uint32_t SId, uint8_t SCIds) { + for (int i = 0; i < (int)AppType_table. size (); i ++) + if ((AppType_table [i]. SId == SId) && + (AppType_table [i]. SCIds == SCIds)) + return i; + return -1; +} + +bool fibConfig::compIsKnown (serviceComp_C &newComp) { + for (auto &comp : SC_C_table) { + if (comp. SId != newComp. SId) + continue; + if (comp. compNr != newComp. compNr) + continue; + return true; + } + return false; +} + +int fibConfig::freeSpace () { +int amount = 0; + for (auto &ss: subChannel_table) + amount += ss. Length; + return 864 - amount; +} + diff --git a/library/src/ofdm/fib-decoder.cpp b/library/src/ofdm/fib-decoder.cpp new file mode 100644 index 0000000..4f924b8 --- /dev/null +++ b/library/src/ofdm/fib-decoder.cpp @@ -0,0 +1,1396 @@ +# +/* + * Copyright (C) 2018 .. 2025 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB program + * simplified for use with dab-cmdline + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * fib decoder. Functionality is shared between fic handler, i.e. the + * one preparing the FIC blocks for processing, and the mainthread + * from which calls are coming on selecting a program + */ +#include "fib-decoder.h" +#include +#include +#include "charsets.h" +#include "bit-extractors.h" +#include "fib-config.h" +#include "ensemble.h" +#include "fib-table.h" +//#include "dab-tables.h" +#include "time-converter.h" +// + + static uint32_t dateTime [8]; +// The fibDecoder was rewritten since the "old" one +// contained (a) errors and (b) was incomplete on +// some issues. +// The current one is straight forward. + fibDecoder::fibDecoder (API_struct *p, void *userData) { + this -> theParameters = p; + if (p -> name_of_ensemble == nullptr) + fprintf (stderr, "ensemblename_Handler is nullptr\n"); + this -> name_of_ensemble = p -> name_of_ensemble; + if (p -> serviceName == nullptr) + fprintf (stderr, "programname handler nullptr detected\n"); + this -> serviceName = p -> serviceName; + this -> userData = userData; + memset (dateTime, 0, 8 * sizeof (uint32_t)); + + reset (); +// +// Note that they may change "roles", + currentConfig = new fibConfig(); + nextConfig = new fibConfig(); + theEnsemble = new ensemble (); + CIFcount = 0; + mjd = 0; +} + + fibDecoder::~fibDecoder () { + delete nextConfig; + delete currentConfig; + delete theEnsemble; +} + +void fibDecoder::clear_ensemble () { + reset (); +} + + +// FIB's are segments of 256 bits. When here, we already +// passed the crc and we start unpacking into FIGs +// This is merely a dispatcher +void fibDecoder::process_FIB (uint8_t *p, uint16_t fib) { +int8_t processedBytes = 0; +uint8_t *d = p; + + fibLocker. lock(); + (void)fib; + while (processedBytes < 30) { + uint8_t FIGtype = getBits_3 (d, 0); + uint8_t FIGlength = getBits_5 (d, 3); + if ((FIGtype == 0x07) && (FIGlength == 0x3F)) + return; + + switch (FIGtype) { + case 0: + process_FIG0 (d); + break; + + case 1: + process_FIG1 (d); + break; + + case 2: // not yet implemented + break; + + case 7: + break; + + default: + break; + } +// +// Thanks to Ronny Kunze, who discovered that I used +// a p rather than a d + processedBytes += getBits_5 (d, 3) + 1; +// processedBytes += getBits (p, 3, 5) + 1; + d = p + processedBytes * 8; + } + fibLocker. unlock(); +} +// +// +void fibDecoder::process_FIG0 (uint8_t *d) { +uint8_t extension = getBits_5 (d, 8 + 3); + + switch (extension) { + case 0: // ensemble information (6.4.1) + FIG0Extension0 (d); + break; + + case 1: // sub-channel organization (6.2.1) + FIG0Extension1 (d); + break; + + case 2: // service organization (6.3.1) + FIG0Extension2 (d); + break; + + case 3: // service component in packet mode (6.3.2) + FIG0Extension3 (d); + break; + + case 4: // service component with CA (6.3.3) + break; + + case 5: // service component language (8.1.2) + FIG0Extension5 (d); + break; + + case 6: // service linking information (8.1.15) + break; + + case 7: // configuration information (6.4.2) + FIG0Extension7 (d); + break; + + case 8: // service component global definition (6.3.5) + FIG0Extension8 (d); + break; + + case 9: // country, LTO & international table (8.1.3.2) + FIG0Extension9 (d); + break; + + case 10: // date and time (8.1.3.1) + FIG0Extension10 (d); + break; + + case 11: // Reserved + break; + + case 12: // Reserved + break; + + case 13: // user application information (6.3.6) + FIG0Extension13 (d); + break; + + case 14: // FEC subchannel organization (6.2.2) + FIG0Extension14 (d); + break; + + case 15: // Reserved + break; + + case 16: // Reserved + break; + + case 17: // Program type (8.1.5) + FIG0Extension17 (d); + break; + + case 18: // announcement support (8.1.6.1) + FIG0Extension18 (d); + break; + + case 19: // announcement switching (8.1.6.2) + FIG0Extension19 (d); + break; + + case 20: // service component information (8.1.4) + break; // to be implemented + + case 21: // frequency information (8.1.8) + FIG0Extension21 (d); + break; + + case 22: // Reserved + break; + + case 23: // Reserved + break; + + case 24: // OE services (8.1.10) + break; // not implemented + + case 25: // OE announcement support (8.1.6.3) + break; // not implemented + + case 26: // OE announcement switching (8.1.6.4) + break; // not implemented + + case 27: // Reserved + case 28: // Reserved + case 29: // Reserved + case 30: // Reserved + case 31: // Reserved + break; + + default: +// fprintf (stderr, "Missed %d\n", extension); + break; + } +} +// Ensemble information, 6.4.1 +// FIG0/0 indicated a change in channel organization +// The info is MCI +void fibDecoder::FIG0Extension0 (uint8_t *d) { +uint16_t EId; +uint8_t changeFlag; +uint16_t highpart, lowpart; +int16_t occurrenceChange; +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t alarmFlag; +static uint8_t prevChangeFlag = 0; + + (void)CN_bit; + EId = getBits (d, 16, 16); + (void)EId; + changeFlag = getBits_2 (d, 16 + 16); + alarmFlag = getBits_1 (d, 16 + 16 + 2); + highpart = getBits_5 (d, 16 + 19); + lowpart = getBits_8 (d, 16 + 24); + (void)alarmFlag; + occurrenceChange = getBits_8 (d, 16 + 32); + (void)changeFlag; + (void)prevChangeFlag; + + (void)occurrenceChange; + CIFcount_hi = highpart; + CIFcount_lo = lowpart; + CIFcount. store (highpart * 250 + lowpart); +// +// for now we ignore this +} +// +// Subchannel organization 6.2.1 +// FIG0 extension 1 creates a mapping between the +// sub channel identifications and the positions in the +// relevant CIF. +void fibDecoder::FIG0Extension1 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length - 1) + used = HandleFIG0Extension1 (d, used, CN_bit, OE_bit, PD_bit); +} +// +// defining the channels +int16_t fibDecoder::HandleFIG0Extension1 (uint8_t *d, int16_t offset, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t PD_bit) { + +int16_t bitOffset = offset * 8; +int16_t subChId = getBits_6 (d, bitOffset); +int16_t startAdr = getBits (d, bitOffset + 6, 10); +int16_t tabelIndex; +int16_t option, protLevel, chanSize; +fibConfig::subChannel channel; +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; +static int table_1 [] = {12, 8, 6, 4}; +static int table_2 [] = {27, 21, 18, 15}; + + (void)OE_bit; (void)PD_bit; + channel. subChId = subChId; + channel. startAddr = startAdr; + channel. Length = 0; + channel. FEC_scheme = 0; // corrected later on + + if (getBits_1 (d, bitOffset + 16) == 0) { // short form + tabelIndex = getBits_6 (d, bitOffset + 18); + channel. Length = ProtLevel [tabelIndex][0]; + channel. shortForm = true; // short form + channel. protLevel = ProtLevel [tabelIndex][1]; + channel. bitRate = ProtLevel [tabelIndex][2]; + bitOffset += 24; + } + else { // EEP long form + channel. shortForm = false; + option = getBits_3 (d, bitOffset + 17); + if (option == 0) { // A Level protection + protLevel = getBits (d, bitOffset + 20, 2); + channel. protLevel = protLevel; + chanSize = getBits (d, bitOffset + 22, 10); + channel. Length = chanSize; + channel. bitRate = chanSize / table_1 [protLevel] * 8; + } + else // option should be 001 + if (option == 001) { // B Level protection + protLevel = getBits_2 (d, bitOffset + 20); + channel. protLevel = protLevel + (1 << 2); + chanSize = getBits (d, bitOffset + 22, 10); + channel. Length = chanSize; + channel. bitRate = chanSize / table_2 [protLevel] * 32; + } + bitOffset += 32; + } +// +// in case the subchannel data was already computed +// we merely compute the offset + if (localBase -> findIndex_subChannel_table (subChId) >= 0) + return bitOffset / 8; +// + localBase -> subChannel_table. push_back (channel); + return bitOffset / 8; // we return bytes +} +// +// Service organization, 6.3.1 +// bind channels to SIds +void fibDecoder::FIG0Extension2 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length) { + used = HandleFIG0Extension2 (d, used, CN_bit, OE_bit, PD_bit); + } +} +// +// +int16_t fibDecoder::HandleFIG0Extension2 (uint8_t *d, + int16_t offset, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t PD_bit) { +int16_t bitOffset = 8 * offset; +int16_t i; +uint8_t ecc = 0; +uint8_t cId; +uint32_t SId; +int16_t numberofComponents; + +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + + (void)OE_bit; + + if (PD_bit == 1) { // long Sid, data + ecc = getBits_8 (d, bitOffset); (void)ecc; + cId = getBits_4 (d, bitOffset + 4); + SId = getLBits (d, bitOffset, 32); + bitOffset += 32; + } + else { + cId = getBits_4 (d, bitOffset); (void)cId; + SId = getBits (d, bitOffset, 16); + bitOffset += 16; + } + + numberofComponents = getBits_4 (d, bitOffset + 4); + + fibConfig::SId_struct SId_element; + SId_element. announcing = 0; + SId_element. SId = SId; + for (auto &ss: localBase -> SId_table) { + if (ss. SId == SId) { + bitOffset += numberofComponents * 16 + 8; + return bitOffset / 8; + } + } + bitOffset += 8; + for (i = 0; i < numberofComponents; i ++) { + fibConfig::serviceComp_C comp; + comp. SId = SId; + comp. compNr = i; + + uint8_t TMid = getBits_2 (d, bitOffset); + comp. TMid = TMid; + if (TMid == 00) { // Audio + comp. ASCTy = getBits_6 (d, bitOffset + 2); + comp. subChId = getBits_6 (d, bitOffset + 8); + comp. PS_flag = getBits_1 (d, bitOffset + 14); + } + else + if (TMid == 3) { // MSC packet data + comp. SCId = getBits (d, bitOffset + 2, 12); + comp. PS_flag = getBits_1 (d, bitOffset + 14); +// uint8_t CA_flag = getBits_1 (d, bitOffset + 15); + } + else + {;} + bitOffset += 16; + if (!localBase -> compIsKnown (comp)) { + SId_element. comps. push_back (localBase -> SC_C_table. size ()); + localBase -> SC_C_table. push_back (comp); + } + } + localBase -> SId_table. push_back (SId_element); + return bitOffset / 8; // in Bytes +} + +// Service component in packet mode 6.3.2 +void fibDecoder::FIG0Extension3 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length) + used = HandleFIG0Extension3 (d, used, CN_bit, OE_bit, PD_bit); +} +// +// Note that the SCId (Service Component Identifier) is +// a unique 12 bit number in the ensemble +int16_t fibDecoder::HandleFIG0Extension3 (uint8_t *d, + int16_t used, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t PD_bit) { +int16_t SCId = getBits (d, used * 8, 12); +int16_t CAOrgflag = getBits_1 (d, used * 8 + 15); +int16_t DGflag = getBits_1 (d, used * 8 + 16); +int16_t DSCTy = getBits_6 (d, used * 8 + 18); +int16_t SubChId = getBits_6 (d, used * 8 + 24); +int16_t packetAddress = getBits (d, used * 8 + 30, 10); +uint16_t CAOrg = 0; +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + + (void)OE_bit; (void)PD_bit; + + if (CAOrgflag == 1) { + CAOrg = getBits (d, used * 8 + 40, 16); + used += 16 / 8; + } + (void)CAOrg; + used += 40 / 8; + + for (auto &comp : localBase -> SC_P_table) + if (comp. SCId == SCId) + return used; + fibConfig::serviceComp_P element; + element. SCId = SCId; + element. subChId = SubChId; + element. DSCTy = DSCTy; + element. DG_flag = DGflag; + element. packetAddress = packetAddress; + localBase -> SC_P_table. push_back (element); + return used; +} + +// Service component language 8.1.2 +void fibDecoder::FIG0Extension5 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length) { + used = HandleFIG0Extension5 (d, CN_bit, OE_bit, PD_bit, used); + } +} + +int16_t fibDecoder::HandleFIG0Extension5 (uint8_t* d, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t PD_bit, int16_t offset) { +int16_t bitOffset = offset * 8; +uint8_t LS_flag = getBits_1 (d, bitOffset); +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; +fibConfig::SC_language comp; + (void)OE_bit; + (void)PD_bit; + comp. LS_flag = LS_flag; + if (LS_flag == 0) { + comp. subChId = getBits (d, bitOffset + 2, 6); + for (int i = 0; i < (int) localBase -> language_table. size (); i ++) + if ((localBase -> language_table [i]. LS_flag == 0) && + (localBase -> language_table [i]. subChId == comp. subChId)) { + bitOffset += 16; + return bitOffset / 8; + } + comp. language = getBits (d, bitOffset + 8, 8); + bitOffset += 16; + } + else { + comp. SCId = getBits (d, bitOffset + 4, 12); + for (int i = 0; i < (int)localBase -> language_table. size (); i ++) + if ((localBase -> language_table [i]. LS_flag == 0) && + (localBase -> language_table [i]. SCId == comp. SCId)) { + bitOffset += 24; + return bitOffset / 8; + } + comp. language = getBits (d, bitOffset + 16, 8); + bitOffset += 24; + } + localBase -> language_table. push_back (comp); + return bitOffset / 8; +} +// +// FIG0/7: Configuration linking information 6.4.2, +void fibDecoder::FIG0Extension7 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + +int serviceCount = getBits_6 (d, used * 8); +int counter = getBits (d, used * 8 + 6, 10); + + (void)serviceCount; + (void)Length; + (void)CN_bit; (void)OE_bit; (void)PD_bit; +// fprintf (stderr, "services : %d\n", serviceCount); +// if (CN_bit == 0) // only current configuration for now +// nrServices (serviceCount); + (void)counter; +} + +// FIG0/8: Service Component Global Definition (6.3.5) +void fibDecoder::FIG0Extension8 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length) { + used = HandleFIG0Extension8 (d, used, CN_bit, OE_bit, PD_bit); + } +} + +int16_t fibDecoder::HandleFIG0Extension8 (uint8_t *d, + int16_t used, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t PD_bit) { +int16_t bitOffset = used * 8; +uint32_t SId = getLBits (d, bitOffset, PD_bit == 1 ? 32 : 16); +uint8_t LS_flag; +uint8_t extensionFlag; +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + +fibConfig::serviceComp_G comp; + (void)OE_bit; + bitOffset += PD_bit == 1 ? 32 : 16; + extensionFlag = getBits_1 (d, bitOffset); + uint8_t SCIds = getBits_4 (d, bitOffset + 4); + + bitOffset += 8; + LS_flag = getBits_1 (d, bitOffset); + + comp. SId = SId; + comp. SCIds = SCIds; + comp. LS_flag = LS_flag; + + if (LS_flag == 0) { // short form + comp. subChId = getBits_6 (d, bitOffset + 2); + bitOffset += 8; + } + else { // long form + comp. SCId = getBits (d, bitOffset + 4, 12); + bitOffset += 16; + } + if (extensionFlag) + bitOffset += 8; // skip Rfa + for (auto &el : localBase -> SC_G_table) + if ((el. SId == SId) && (el. SCIds == SCIds)) + return bitOffset / 8; + localBase -> SC_G_table. push_back (comp); + return bitOffset / 8; +} + +// FIG0/9 Country, LTO and International table, clause 8.1.3.2; +void fibDecoder::FIG0Extension9 (uint8_t *d) { +int16_t used = 2; // offset in bytes +//int16_t Length = getBits_5 (d, 3); +//uint8_t CN_bit = getBits_1 (d, 8 + 0); +//uint8_t OE_bit = getBits_1 (d, 8 + 1); +//uint8_t PD_bit = getBits_1 (d, 8 + 2); +// 6 indicates the number of hours + int signbit = getBits_1 (d, used * 8 + 2); + currentConfig -> dateTime [6] = (signbit == 1)? + -1 * getBits_4 (d, used * 8 + 3): + getBits_4 (d, used * 8 + 3); +// 7 indicates a possible remaining half our + currentConfig -> dateTime [7] = + (getBits_1 (d, used * 8 + 7) == 1) ? 30 : 0; + if (signbit == 1) + currentConfig -> dateTime [7] = - currentConfig -> dateTime [7]; + + uint8_t LTO = currentConfig -> dateTime [6]; + uint8_t ecc = getBits (d, used * 8 + 8, 8); + theEnsemble -> eccByte = ecc; + theEnsemble -> lto = LTO; +// lto_ecc (LTO, ecc); +} + +int monthLength [] { +31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +// +// Time in 10 is given in UTC, for other time zones +// we add (or subtract) a number of Hours (half hours) +void fibDecoder::adjustTime (int32_t *dateTime) { +// first adjust the half hour in the amount of minutes + (void)dateTime; + currentConfig -> dateTime [4] += + (currentConfig -> dateTime [7] == 1) ? 30 : 0; + if (currentConfig -> dateTime [4] >= 60) { + currentConfig -> dateTime [4] -= 60; + currentConfig -> dateTime [3] ++; + } + + if (currentConfig -> dateTime [4] < 0) { + currentConfig -> dateTime [4] += 60; + currentConfig -> dateTime [3] --; + } + + currentConfig -> dateTime [3] += currentConfig -> dateTime [6]; + if ((0 <= currentConfig -> dateTime [3]) && + (currentConfig -> dateTime [3] <= 23)) + return; + + if (currentConfig -> dateTime [3] > 23) { + currentConfig -> dateTime [3] -= 24; + currentConfig -> dateTime [2] ++; + } + + if (currentConfig -> dateTime [3] < 0) { + currentConfig -> dateTime [3] += 24; + currentConfig -> dateTime [2] --; + } + + if (currentConfig -> dateTime [2] > + monthLength [currentConfig -> dateTime [1] - 1]) { + currentConfig -> dateTime [2] = 1; + currentConfig -> dateTime [1] ++; + if (currentConfig -> dateTime [1] > 12) { + currentConfig -> dateTime [1] = 1; + currentConfig -> dateTime [0] ++; + } + } + + if (currentConfig -> dateTime [2] < 0) { + if (currentConfig -> dateTime [1] > 1) { + currentConfig -> dateTime [2] = + monthLength [currentConfig -> dateTime [1] - 1 - 1]; + currentConfig -> dateTime [1] --; + } + else { + currentConfig -> dateTime [2] = monthLength [11]; + currentConfig -> dateTime [1] = 12; + currentConfig -> dateTime [0] --; + } + } +} + +// 8.1.3.1 Date and time (d&t) +void fibDecoder::FIG0Extension10 (uint8_t *dd) { +int16_t offset = 16; +this -> mjd = getLBits (dd, offset + 1, 17); +uint16_t theTime [6]; + + convertTime (mjd, theTime); +// theTime [0] = Y; // Year +// theTime [1] = M; // Month +// theTime [2] = D; // Day + theTime [3] = getBits_5 (dd, offset + 21); // Hours + theTime [4] = getBits_6 (dd, offset + 26); // Minutes + + if (getBits_6 (dd, offset + 26) != currentConfig -> dateTime [4]) + theTime [5] = 0; // Seconds + + if (dd [offset + 20] == 1) + theTime [5] = getBits_6 (dd, offset + 32); // Seconds +// +// take care of different time zones + bool change = false; + for (int i = 0; i < 6; i ++) { + if (theTime [i] != currentConfig -> dateTime [i]) + change = true; + currentConfig -> dateTime [i] = theTime [i]; + } + (void)change; + +// int utc_hour = currentConfig -> dateTime [3]; +// int utc_minute = currentConfig -> dateTime [4]; +// int utc_seconds = currentConfig -> dateTime [5]; + adjustTime (currentConfig -> dateTime); + theParameters -> timeHandler ( + currentConfig -> dateTime [3], + currentConfig -> dateTime [4], userData); +} +// +// User Application Information 6.3.6 +void fibDecoder::FIG0Extension13 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length) + used = HandleFIG0Extension13 (d, used, CN_bit, OE_bit, PD_bit); +} +// +// section 6.3.6 User application Data +int16_t fibDecoder::HandleFIG0Extension13 (uint8_t *d, + int16_t used, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t pdBit) { +int16_t bitOffset = used * 8; +uint32_t SId = getLBits (d, bitOffset, pdBit == 1 ? 32 : 16); +uint16_t SCIds; +int16_t NoApplications; +int16_t i; +int16_t appType; +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + +fibConfig::AppType element; + (void)OE_bit; + bitOffset += pdBit == 1 ? 32 : 16; + SCIds = getBits_4 (d, bitOffset); + NoApplications = getBits_4 (d, bitOffset + 4); + bitOffset += 8; + element. SId = SId; + element. SCIds = SCIds; + + for (i = 0; i < NoApplications; i ++) { + appType = getBits (d, bitOffset, 11); + int16_t length = getBits_5 (d, bitOffset + 11); + element. Apptype = appType; + bitOffset += (11 + 5 + 8 * length); + } + for (auto &comp : localBase -> AppType_table) + if ((comp. SId == SId) && (comp. SCIds == SCIds)) + return bitOffset / 8; + localBase -> AppType_table. push_back (element); + return bitOffset / 8; +} + +// FEC sub-channel organization 6.2.2 +void fibDecoder::FIG0Extension14 (uint8_t *d) { +int16_t Length = getBits_5 (d, 3); // in Bytes +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); +int16_t used = 2; // in Bytes +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + + (void)OE_bit; (void)PD_bit; + while (used < Length) { + + int16_t subChId = getBits_6 (d, used * 8); + uint8_t FEC_scheme = getBits_2 (d, used * 8 + 6); + used = used + 1; + for (auto &subC: localBase -> subChannel_table) + if (subC. subChId == subChId) + subC. FEC_scheme = FEC_scheme; + } +} +// +// program type 8.1.5 +void fibDecoder::FIG0Extension17 (uint8_t *d) { +int16_t length = getBits_5 (d, 3); +int16_t offset = 16; + + while (offset < length * 8) { + uint16_t SId = getBits (d, offset, 16); + uint8_t typeCode = getBits_5 (d, offset + 27); + for (uint16_t i = 0; i < theEnsemble -> primaries. size (); i ++) { + if (theEnsemble -> primaries [i]. SId == SId) { + theEnsemble -> primaries [i]. programType = typeCode; + break; + } + } + offset += 32; + } +} +// +// Announcement support 8.1.6.1 +void fibDecoder::FIG0Extension18 (uint8_t *d) { +int16_t Length = getBits_5 (d, 3); // in Bytes +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); +int16_t used = 2; // in Bytes +int16_t bitOffset = used * 8; +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + + (void)OE_bit; (void)PD_bit; + + while (bitOffset < Length * 8) { + uint16_t SId = getBits (d, bitOffset, 16); + bitOffset += 16; + uint16_t asuFlags = getBits (d, bitOffset, 16); + bitOffset += 16; + (void) getBits (d, bitOffset, 5); // Rfa + uint8_t nrClusters = getBits (d, bitOffset + 5, 3); + bitOffset += 8; + + for (int i = 0; i < nrClusters; i ++) { + fibConfig::FIG18_cluster aC; + uint8_t clusterId = getBits (d, bitOffset + 8 * i, 8); + if (clusterId == 0) + continue; + bool inTable = false; + for (auto &ACe : localBase -> announcement_table) { + if ((ACe. SId == SId) && (clusterId == ACe. clusterId)) { + inTable = true; + break; + } + } + if (!inTable) { + aC. SId = SId; + aC. asuFlags = asuFlags; + aC. clusterId = clusterId; + localBase -> announcement_table. push_back (aC); + } + } + bitOffset += nrClusters * 8; + } +} + +// Announcement switching 8.1.6.2 +void fibDecoder::FIG0Extension19 (uint8_t *d) { +int16_t Length = getBits_5 (d, 3); // in Bytes +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); +int16_t used = 2; // in Bytes +int16_t bitOffset = used * 8; +fibConfig *localBase = CN_bit == 0 ? currentConfig : nextConfig; + + (void)OE_bit; (void)PD_bit; + while (bitOffset < Length * 8) { + uint8_t clusterId = getBits (d, bitOffset, 8); + bitOffset += 8; + uint16_t AswFlags = getBits (d, bitOffset, 16); + bitOffset += 16; + uint8_t newFlag = getBits (d, bitOffset, 1); + bitOffset += 1; + uint8_t Rfa = getBits (d, bitOffset, 1); + (void)Rfa; + bitOffset += 1; + uint8_t subChId = getBits (d, bitOffset, 6); + bitOffset += 6; + for (auto &ac : localBase -> announcement_table) { + if ((ac. clusterId == clusterId) && newFlag) + handle_announcement (ac. SId, + ac. asuFlags & AswFlags, subChId); + } + } + return; +} + +// Frequency information (FI) 8.1.8 +void fibDecoder::FIG0Extension21 (uint8_t *d) { +int16_t used = 2; // offset in bytes +int16_t Length = getBits_5 (d, 3); +uint8_t CN_bit = getBits_1 (d, 8 + 0); +uint8_t OE_bit = getBits_1 (d, 8 + 1); +uint8_t PD_bit = getBits_1 (d, 8 + 2); + + while (used < Length) + used = HandleFIG0Extension21 (d, CN_bit, OE_bit, PD_bit, used); +} + +int16_t fibDecoder::HandleFIG0Extension21 (uint8_t *d, + uint8_t CN_bit, + uint8_t OE_bit, + uint8_t PD_bit, + int16_t offset) { +int16_t l_offset = offset * 8; +int16_t l = getBits_5 (d, l_offset + 11); +int16_t upperLimit = l_offset + 16 + l * 8; +int16_t base = l_offset + 16; + + (void)CN_bit; (void)OE_bit, (void)PD_bit; + if (OE_bit == 1) // this ios not for use + return upperLimit / 8; + + bool newData = false; + while (base < upperLimit) { + uint16_t idField = getBits (d, base, 16); + uint8_t RandM = getBits_4 (d, base + 16); + uint8_t continuity = getBits_1 (d, base + 20); + (void)continuity; + uint8_t length = getBits_3 (d, base + 21); + if (RandM == 0x08) { + uint16_t fmFrequency_key = getBits (d, base + 24, 8); + int32_t fmFrequency = 87500 + fmFrequency_key * 100; + for (auto &serv : theEnsemble -> primaries) { + if ((serv. SId == idField)) { + bool alreadyIn = false; + for (auto freq : serv. fmFrequencies) { + if (fmFrequency == freq) { + alreadyIn = true; + break; + } + } + if (!alreadyIn) { + serv. fmFrequencies. push_back (fmFrequency); + newData = true; + } + } + } + } + base += 24 + length * 8; + } + (void)newData; +// if (newData) +// emit setFreqList (); + + return upperLimit / 8; +} +// +// FIG 1 - Cover the different possible labels, section 5.2 +void fibDecoder::process_FIG1 (uint8_t *d) { +uint8_t extension = getBits_3 (d, 8 + 5); + + switch (extension) { + case 0: // ensemble name + FIG1Extension0 (d); + break; + + case 1: // service name + FIG1Extension1 (d); + break; + + case 2: // Labels etc + break; + + case 3: // obsolete + break; + + case 4: // Service Component Label + FIG1Extension4 (d); + break; + + case 5: // Data service label + FIG1Extension5 (d); + break; + + case 6: // XPAD label - 8.1.14.4 + break; + + default: + ; + } +} +// Name of the ensemble +// +void fibDecoder::FIG1Extension0 (uint8_t *d) { +uint8_t charSet, extension; +uint8_t Rfu; +uint32_t EId = 0; +int16_t offset = 0; +char label [17]; + +// from byte 1 we deduce: + charSet = getBits_4 (d, 8); + Rfu = getBits_1 (d, 8 + 4); + extension = getBits_3 (d, 8 + 5); + label [16] = 0x00; + (void)Rfu; + (void)extension; + + EId = getBits (d, 16, 16); + offset = 32; + if ((charSet <= 16)) { // EBU Latin based repertoire + for (int i = 0; i < 16; i ++) { + label [i] = getBits_8 (d, offset + 8 * i); + } + const std::string name = toStringUsingCharset ( + (const char *) label, + (CharacterSet) charSet); + std::string realName = name; + for (int i = name. length (); i < 16; i ++) + realName. push_back (' '); + if (!theEnsemble -> namePresent) { + theEnsemble -> ensembleName = realName; + theEnsemble -> EId = EId; + theEnsemble -> namePresent = true; + if (theParameters -> name_of_ensemble != nullptr) + theParameters -> name_of_ensemble (name, EId, userData); + } + theEnsemble -> isSynced = true; + } +} +// +// Name of service +void fibDecoder::FIG1Extension1 (uint8_t *d) { +int16_t offset = 32; +char label [17]; + +// from byte 1 we deduce: + uint8_t charSet = getBits_4 (d, 8); + uint8_t Rfu = getBits_1 (d, 8 + 4); + uint8_t extension = getBits_3 (d, 8 + 5); + uint32_t SId = getBits (d, 16, 16); + label [16] = 0x00; + (void)Rfu; (void)extension; + if (charSet >= 16) // does not seem right + return; + + for (auto &serv : theEnsemble -> primaries) { + if (SId == serv. SId) + return; + } + + for (int i = 0; i < 16; i ++) + label [i] = getBits_8 (d, offset + 8 * i); + std::string dataName = toStringUsingCharset ( + (const char *) label, + (CharacterSet) charSet); + for (int i = dataName. length (); i < 16; i ++) + dataName. push_back(' '); + std::string shortName; + for (int i = 0; i < 16; i ++) + if (getBits_1 (d, offset + 16 * 8 + i) != 0) + shortName. push_back (dataName. at (i)); + + ensemble::service prim; + prim. programType = 0; + prim. name = dataName; + prim. shortName = shortName; + prim. SId = SId; + prim. fmFrequencies. resize (0); + theEnsemble -> primaries. push_back (prim); + int subChId = -1; + for (int i = 0; i < (int)(currentConfig -> SC_C_table. size ()); i ++) { + fibConfig::serviceComp_C comp = currentConfig -> SC_C_table [i]; + if ((comp. compNr == 0) && (comp. SId == SId)) + subChId = currentConfig -> subChannelOf (i); + } + if (theParameters -> serviceName != nullptr) + theParameters -> serviceName (dataName, SId, subChId, userData); + if (theEnsemble -> primaries. size () >= 2) + theEnsemble -> isSynced = true; +} + +// service component label - 32 bits 8.1.14.3 +void fibDecoder::FIG1Extension4 (uint8_t *d) { +char label [17]; +int bitOffset = 16; +uint32_t SId; + +// from byte 1 we deduce: + uint8_t charSet = getBits_4 (d, 8); + uint8_t Rfu = getBits_1 (d, 8 + 4); + uint8_t extension = getBits_3 (d, 8 + 5); + uint8_t PD_flag = getBits_1 (d, bitOffset); + uint8_t SCIds = getBits (d, bitOffset + 4, 4); + if (PD_flag) { + SId = getLBits (d, bitOffset + 8, 32); + bitOffset += 32 + 8; + } + else { + SId = getLBits (d, bitOffset + 8, 16); + bitOffset += 16 + 8; + } +// +// just a check if we already have the servicename + for (auto &serv : theEnsemble -> secondaries) + if (serv. SId == SId) + return; + for (auto &serv :theEnsemble -> primaries) + if (serv. SId == SId) + return; + + label [16] = 0x00; + (void)Rfu; + (void)extension; + if (charSet >= 16) // does not seem right + return; + + for (int i = 0; i < 16; i ++) + label [i] = getBits_8 (d, bitOffset + 8 * i); + std::string dataName = toStringUsingCharset ( + (const char *) label, + (CharacterSet) charSet); + std::string shortName; + for (int i = 0; i < 16; i ++) + if (getBits_1 (d, bitOffset + 16 * 8 + i) != 0) + shortName. push_back (dataName. at (i)); + + ensemble::service prim; + prim. name = dataName; + prim. shortName = shortName; + prim. SId = SId; + prim. SCIds = SCIds; + theEnsemble -> secondaries. push_back (prim); + if (theParameters -> serviceName != nullptr) + theParameters -> serviceName (dataName, SId, -1, userData); +} + +// Data service label - 32 bits 8.1.14.2 +void fibDecoder::FIG1Extension5 (uint8_t *d) { +char label [17]; + +uint32_t SId = getLBits (d, 16, 32); +int16_t bitOffset = 48; + +// from byte 1 we deduce: + uint8_t charSet = getBits_4 (d, 8); + uint8_t Rfu = getBits_1 (d, 8 + 4); + uint8_t extension = getBits_3 (d, 8 + 5); + label [16] = 0x00; + (void)Rfu; (void)extension; + + for (auto &serv : theEnsemble -> primaries) { + if (SId == serv. SId) + return; + } + + if (charSet > 16) + return; // something wrong + + for (int i = 0; i < 16; i ++) { + label [i] = getBits_8 (d, bitOffset + 8 * i); + } + std::string dataName = toStringUsingCharset ( + (const char *) label, + (CharacterSet) charSet); + std::string shortName; + for (int i = 0; i < 16; i ++) + if (getBits_1 (d, bitOffset + 16 * 8 + i) != 0) + shortName. push_back (dataName. at (i)); + + + ensemble::service prim; + prim. programType = 0; + prim. name = dataName; + prim. shortName = shortName; + prim. SId = SId; + theEnsemble -> primaries. push_back (prim); + if (theParameters -> serviceName != nullptr) + theParameters -> serviceName (dataName, SId, -1, userData); +} + +void fibDecoder::connect_channel () { + fibLocker. lock(); + currentConfig -> reset (); + nextConfig -> reset (); + theEnsemble -> reset (); + fibLocker. unlock(); +} + +void fibDecoder::disconnect_channel () { + fibLocker. lock (); + currentConfig -> reset (); + nextConfig -> reset (); + theEnsemble -> reset (); + fibLocker. unlock(); +} + +void fibDecoder::reset () { +// connect_channel (); +} + +bool fibDecoder::syncReached() { + return theEnsemble -> isSynced; +} + +uint32_t fibDecoder::get_SId (int index) { + return currentConfig -> SC_C_table [index]. SId; +} + +std::string fibDecoder::get_serviceName (uint32_t SId) { + for (auto &prim: theEnsemble -> primaries) + if (prim. SId == SId) + return prim. name; + return ""; +} + +uint8_t fibDecoder::serviceType (int index) { + if ((index < 0) || ((uint16_t)index >= currentConfig -> SC_C_table. size ())) + return UNKNOWN_SERVICE; + return currentConfig -> SC_C_table [index]. TMid == 00 ? + AUDIO_SERVICE : + PACKET_SERVICE; +} + +void fibDecoder::audioData (int index, audiodata &ad) { +fibConfig::serviceComp_C &comp = currentConfig -> SC_C_table [index]; + for (auto &serv : theEnsemble -> primaries) { + if (serv. SId == comp. SId) { + ad. serviceName = serv. name; + ad. shortName = serv. shortName; + ad. SId = serv. SId; + ad. programType = serv. programType; +// ad. fmFrequencies = serv. fmFrequencies; + break; + } + } + int subChId = currentConfig -> subChannelOf (index); + ad. subchId = subChId; + int subChannel_index = + currentConfig -> findIndex_subChannel_table (subChId); + if (subChannel_index < 0) + return; + fibConfig::subChannel &channel = + currentConfig -> subChannel_table [subChannel_index]; + ad. startAddr = channel. startAddr; + ad. shortForm = channel. shortForm; + ad. protLevel = channel. protLevel; + ad. length = channel. Length; + ad. bitRate = channel. bitRate; + ad. ASCTy = currentConfig -> dabTypeOf (index); + ad. language = currentConfig -> languageOf (index); + ad. defined = true; +} + +void fibDecoder::packetData (int index, packetdata &pd) { +fibConfig::serviceComp_C &comp = currentConfig -> SC_C_table [index]; + for (auto &serv : theEnsemble -> primaries) { + if (serv. SId == comp. SId) { + pd. serviceName = serv. name; + pd. shortName = serv. shortName; + pd. SId = serv. SId; + break; + } + } + int subChId = currentConfig -> subChannelOf (index); + pd. subchId = subChId; + int subChannel_index = + currentConfig -> findIndex_subChannel_table (subChId); + if (subChannel_index < 0) + return; + fibConfig::subChannel &channel = + currentConfig -> subChannel_table [subChannel_index]; + pd. startAddr = channel. startAddr; + pd. shortForm = channel. shortForm; + pd. protLevel = channel. protLevel; + pd. length = channel. Length; + pd. bitRate = channel. bitRate; + pd. FEC_scheme = currentConfig -> FEC_schemeOf (index); + pd. appType = currentConfig -> appTypeOf (index); + pd. DGflag = currentConfig -> DG_flag (index); + pd. DSCTy = currentConfig -> DSCTy (index); + pd. packetAddress = currentConfig -> packetAddressOf (index); + pd. defined = true; +} + +int fibDecoder::get_nrComps (uint32_t SId) { + for (auto &SId_element : currentConfig -> SId_table) + if (SId_element. SId == SId) + return SId_element. comps. size (); + return 0; +} +// +// for primary services we return the index of the first +// component, the secondary services, the index of the +// component with the matching SCIds +// +int fibDecoder::getServiceComp (const std::string &service) { +// first we check to see if the service is a primary one + std::string ss = service; + for (int i = service. size (); i < 16; i ++) + ss. push_back (' '); + for (auto &serv : theEnsemble -> primaries) { + if (serv. name != ss) + continue; + for (auto & SId_element: currentConfig -> SId_table) { + if (SId_element. SId == serv. SId) + return SId_element. comps [0]; + } + } + + for (auto &serv : theEnsemble -> secondaries) { + if (serv. name != service) + continue; + return get_serviceComp_SCIds (serv. SId, serv. SCIds); + } + return -1; +} + +int fibDecoder::get_serviceComp (uint32_t SId, int compnr) { + for (auto &SId_element : currentConfig -> SId_table) { + if (SId_element. SId == SId) { + return SId_element. comps [compnr]; + } + } + return -1; +} + +int fibDecoder::get_serviceComp_SCIds (uint32_t SId, int SCIds) { + for (auto &SId_element : currentConfig -> SId_table) { + if (SId_element. SId != SId) + continue; + for (int i = 0; i < (int) SId_element. comps. size (); i ++) { + int index = SId_element. comps [i]; + if (currentConfig -> SCIdsOf (index) == SCIds) + return index; + } + } + return -1; +} + +bool fibDecoder::isPrimary (const std::string &s) { + for (auto &serv : theEnsemble -> primaries) { + if (s == serv. name) + return true; + } + return false; +} + +uint8_t fibDecoder::get_ecc () { + return theEnsemble -> eccByte; +} + +uint32_t fibDecoder::get_EId () { + return theEnsemble -> EId; +} + +std::vector fibDecoder::getFrequency (const std::string &s) { +std::vector res; + for (auto &serv : theEnsemble -> primaries) { + if (serv. name == s) + return serv. fmFrequencies; + } + return res; +} + +// required for ETI generation +int fibDecoder::nrChannels () { + return currentConfig -> subChannel_table. size (); +} +// + +int32_t fibDecoder::get_CIFcount () { + return CIFcount; +} + +void fibDecoder::get_CIFcount (int16_t &high, int16_t &low) { + high = CIFcount_hi; + low = CIFcount_lo; +} + +uint32_t fibDecoder::julianDate () { + return mjd; +} + +void fibDecoder::handle_announcement (uint16_t SId, uint16_t flags, + uint8_t subChId) { + (void)subChId; + for (auto &serv : currentConfig -> SId_table) + if (serv. SId == SId) { +// if (serv. announcing != flags) +// emit announcement (SId, flags); + serv. announcing = flags; + } +} + +uint16_t fibDecoder::get_announcing (uint16_t SId) { + for (auto &serv : currentConfig -> SId_table) + if (serv. SId == SId) + return serv. announcing; + return 0; +} + +int fibDecoder::freeSpace () { + return currentConfig -> freeSpace (); +} + +std::string fibDecoder::get_ensembleName () { + return theEnsemble -> ensembleName; +} + diff --git a/library/src/ofdm/fib-processor.cpp b/library/src/ofdm/fib-processor.cpp index aa3bdfa..d77a37e 100644 --- a/library/src/ofdm/fib-processor.cpp +++ b/library/src/ofdm/fib-processor.cpp @@ -163,35 +163,35 @@ uint8_t extension = getBits_5 (d, 8 + 3); //uint8_t CN = getBits_1 (d, 8 + 0); //fprintf(stderr,"DBG::FIB::FIG0: extension=%d\n", extension); switch (extension) { - case 0: + case 0: // ensemble information (6.4.1) FIG0Extension0 (d); break; - case 1: + case 1: // subchannel organization (6.2.1) FIG0Extension1 (d); break; - case 2: + case 2: // service organization (6.3.1) FIG0Extension2 (d); break; - case 3: + case 3: // service component in packet mode (6.3.2) FIG0Extension3 (d); break; - case 4: + case 4: // service component with CA (6.3.3) FIG0Extension4 (d); break; - case 5: + case 5: // service component language FIG0Extension5 (d); break; - case 6: + case 6: // service linking information (8.1.15) FIG0Extension6 (d); break; - case 7: + case 7: : FIG0Extension7 (d); break; diff --git a/library/src/ofdm/fic-handler.cpp b/library/src/ofdm/fic-handler.cpp index 258c6ab..2b24000 100644 --- a/library/src/ofdm/fic-handler.cpp +++ b/library/src/ofdm/fic-handler.cpp @@ -42,7 +42,7 @@ void *userData): viterbiSpiral (768), // viterbiHandler (768), - fibProcessor (p, + fibHandler (p, userData), params (p -> dabMode) { int16_t i, j, k; @@ -195,42 +195,40 @@ int16_t inputCount = 0; } show_ficCRC (true); fibProtector. lock (); - fibProcessor. process_FIB (p, ficno); + fibHandler. process_FIB (p, ficno); fibProtector. unlock (); } } void ficHandler::clearEnsemble (void) { fibProtector. lock (); - fibProcessor. clearEnsemble (); + fibHandler. clear_ensemble (); fibProtector. unlock (); } -uint8_t ficHandler::kindofService (const std::string &s) { +uint8_t ficHandler::serviceType (int index) { uint8_t result; fibProtector. lock (); - result = fibProcessor. kindofService (s); + result = fibHandler. serviceType (index); fibProtector. unlock (); return result; } -void ficHandler::dataforAudioService (const std::string &s, - audiodata *d, int c) { +void ficHandler::audioData (int index, audiodata &ad) { fibProtector. lock (); - fibProcessor. dataforAudioService (s, d, c); + fibHandler. audioData (index, ad); fibProtector. unlock (); } -void ficHandler::dataforDataService (const std::string &s, - packetdata *d, int c) { +void ficHandler::packetData (int index, packetdata &pd) { fibProtector. lock (); - fibProcessor. dataforDataService (s, d, c); + fibHandler. packetData (index, pd ); fibProtector. unlock (); } int32_t ficHandler::get_CIFcount () { // no lock, because using std::atomic<> in fib_processor class - return fibProcessor. get_CIFcount(); + return fibHandler. get_CIFcount(); } int16_t ficHandler::get_ficRatio () { @@ -238,15 +236,7 @@ int16_t ficHandler::get_ficRatio () { } bool ficHandler::syncReached () { - return fibProcessor. syncReached (); -} - -std::string ficHandler::nameFor (int32_t serviceId) { - return fibProcessor. nameFor (serviceId); -} - -int32_t ficHandler::SIdFor (const std::string &name) { - return fibProcessor. SIdFor (name); + return fibHandler. syncReached (); } static int pos = 0; @@ -263,6 +253,30 @@ void ficHandler::show_ficCRC (bool b) { } void ficHandler::reset () { - fibProcessor. reset (); + fibHandler. reset (); +} + +int ficHandler::getServiceComp (const std::string &s) { + return fibHandler. getServiceComp (s); +} + +int ficHandler::get_SId (int index) { + return fibHandler. get_SId (index); +} + +std::string ficHandler::get_serviceName (uint32_t SId) { + return fibHandler. get_serviceName (SId); +} + +uint8_t ficHandler::get_ecc () { + return fibHandler. get_ecc (); +} + +uint32_t ficHandler::get_EId () { + return fibHandler. get_EId (); +} + +std::string ficHandler::get_ensembleName () { + return fibHandler. get_ensembleName (); } diff --git a/library/src/ofdm/phasetable.cpp b/library/src/ofdm/phasetable.cpp index 7157447..ed8a572 100644 --- a/library/src/ofdm/phasetable.cpp +++ b/library/src/ofdm/phasetable.cpp @@ -120,8 +120,10 @@ struct phasetableElement modeIV_table [] = { {-1000, -1000, 0, 0} }; - phaseTable::phaseTable (int16_t modus) { - Mode = modus; + phaseTable::phaseTable (int16_t dabMode): + params (dabMode), + T_u (params. get_T_u ()) { + Mode = dabMode; currentTable = modeI_table; switch (Mode) { default: @@ -137,9 +139,21 @@ struct phasetableElement modeIV_table [] = { currentTable = modeIV_table; break; } + refTable. resize (T_u); + for (int i = 0; i < T_u; i ++) + refTable [i] = std::complex (0, 0); +// +// generate the refence values using the format we have after +// doing an FFT + for (int i = 1; i <= params. get_carriers() / 2; i ++) { + float Phi_k = get_Phi (i); + refTable [i] = std::complex (cos (Phi_k), sin (Phi_k)); + Phi_k = get_Phi (-i); + refTable [T_u - i] = std::complex (cos (Phi_k), sin (Phi_k)); + } } - phaseTable::~phaseTable (void) { + phaseTable::~phaseTable () { } static diff --git a/library/src/ofdm/tii-detector.cpp b/library/src/ofdm/tii-detector.cpp index 460bada..0949743 100644 --- a/library/src/ofdm/tii-detector.cpp +++ b/library/src/ofdm/tii-detector.cpp @@ -26,8 +26,11 @@ #include // +#define SECTION_SIZE 192 +#define NR_SECTIONS 4 +constexpr float F_DEG_PER_RAD = (float)(180.0 / M_PI); static -uint8_t table [] = { +uint8_t patternTable [] = { 0017, // 0 0 0 0 1 1 1 1 0 0027, // 0 0 0 1 0 1 1 1 1 0033, // 0 0 0 1 1 0 1 1 2 @@ -107,170 +110,327 @@ uint8_t table [] = { }; TII_Detector::TII_Detector (uint8_t dabMode): - params (dabMode), - my_fftHandler (dabMode) { -int16_t i; + params (dabMode), + theTable (dabMode), + T_u (params. get_T_u ()), + T_g (params. get_T_g ()), + carriers (params. get_carriers ()), + my_fftHandler (dabMode) { - this -> T_u = params. get_T_u(); - carriers = params. get_carriers(); - theBuffer. resize (T_u); - fft_buffer = my_fftHandler. getVector(); - window. resize (T_u); - for (i = 0; i < T_u; i ++) - window [i] = (0.42 - - 0.5 * cos (2 * M_PI * (float)i / T_u) + - 0.08 * cos (4 * M_PI * (float)i / T_u)); + + nullSymbolBuffer. resize (T_u); + window. resize (T_u); + for (int i = 0; i < T_u; i ++) + window [i] = 0.54 - 0.46 * cos (2 * M_PI * (float)i / T_u); - for (i = 71; i < 256; i ++) - invTable [i] = -1; - for (i = 0; i < 70; ++i) - invTable [table [i]] = i; + table_2. resize (carriers / 2); + int teller = 0; + for (int carrier = - carriers / 2; + carrier < carriers / 2; carrier += 2) { + int index = carrier < 0 ? carrier + T_u : carrier + 1; + table_2 [teller ++] = theTable. refTable [index] * + conj (theTable. refTable [index + 1]); + } + reset (); } TII_Detector::~TII_Detector() { } +void TII_Detector::resetBuffer () { + for (int i = 0; i < T_u; i ++) + nullSymbolBuffer [i] = Complex (0, 0); +} + void TII_Detector::reset() { - for (int i = 0; i < T_u; i ++) - theBuffer [i] = std::complex (0, 0); + resetBuffer(); + memset ((void *)decodedBuffer, 0, carriers / 2 * sizeof (Complex)); } // To eliminate (reduce?) noise in the input signal, we might // add a few spectra before computing (up to the user) -void TII_Detector::addBuffer (std::vector> v) { -int i; +void TII_Detector::addBuffer (const std::vector &v) { +Complex tmpBuffer [T_u]; - for (i = 0; i < T_u; i ++) - fft_buffer [i] = cmul (v [i], window [i]); - my_fftHandler. do_FFT(); - - for (i = 0; i < T_u; i ++) - theBuffer [i] += fft_buffer [i]; + for (int i = 0; i < T_u; i ++) + tmpBuffer [i] = v [T_g + i]; + my_fftHandler. fft (tmpBuffer); + for (int i = 0; i < T_u; i ++) + nullSymbolBuffer [i] += tmpBuffer [i]; } -// -// Note that the input is fft output, not yet reodered -void TII_Detector::collapse (std::complex *inVec, float *outVec) { -int i; - for (i = 0; i < carriers / 8; i ++) { - int carr = - carriers / 2 + 2 * i; - outVec [i] = abs (real (inVec [(T_u + carr) % T_u] * - conj (inVec [(T_u + carr + 1) % T_u]))); - carr = - carriers / 2 + 1 * carriers / 4 + 2 * i; - outVec [i] += abs (real (inVec [(T_u + carr) % T_u] * - conj (inVec [(T_u + carr + 1) % T_u]))); - carr = - carriers / 2 + 2 * carriers / 4 + 2 * i + 1; - outVec [i] += abs (real (inVec [(T_u + carr) % T_u] * - conj (inVec [(T_u + carr + 1) % T_u]))); - carr = - carriers / 2 + 3 * carriers / 4 + 2 * i + 1; - outVec [i] += abs (real (inVec [(T_u + carr) % T_u] * - conj (inVec [(T_u + carr + 1) % T_u]))); +void TII_Detector::collapse (const Complex *inVec, + Complex *etsiVec, Complex *nonetsiVec, + bool tiiFilter) { +Complex buffer [carriers / 2]; +bool carrierDelete = false; + memcpy (buffer, inVec, carriers / 2 * sizeof (Complex)); + + int nrSections = tiiFilter ? 2 : 4; +// a single carrier cannot be a TII carrier. + if (carrierDelete) { + for (int i = 0; i < SECTION_SIZE; i++) { + float x [4]; + float max = 0; + float sum = 0; + int index = 0; + for (int j = 0; j < nrSections; j++) { + x [j] = jan_abs (buffer [i + j * SECTION_SIZE]); + sum += x [j]; + if (x [j] > max) { + max = x[j]; + index = j; + } + } + + float min = (sum - max) / 3; + if (sum < max * 1.5 && max > 0.0) { + buffer [i + index * SECTION_SIZE] *= min / max; + } + } + } + + for (int i = 0; i < SECTION_SIZE; i++) { + etsiVec [i] = Complex (0, 0); + nonetsiVec [i] = Complex (0, 0); + for (int j = 0; j < nrSections; j++) { + Complex x = buffer [i + j * SECTION_SIZE]; + etsiVec [i] += x; + nonetsiVec [i] += x * conj (table_2 [i + j * SECTION_SIZE]); + } } } +// We determine first the offset of the "best fit", +// the offset indicates the subId +static uint8_t bits [] = {0x80, 0x40, 0x20, 0x10 , 0x08, 0x04, 0x02, 0x01}; + +// Sort the elements according to their strength static -uint8_t bits [] = {0x80, 0x40, 0x20, 0x10 , 0x08, 0x04, 0x02, 0x01}; - -#define NUM_GROUPS 8 -#define GROUPSIZE 24 -uint16_t TII_Detector::processNULL () { -int i, j; -float hulpTable [NUM_GROUPS * GROUPSIZE]; // collapsed values -float C_table [GROUPSIZE]; // contains the values -int D_table [GROUPSIZE]; // count of indices in C_table with data -float avgTable [NUM_GROUPS]; - -// we map the "carriers" carriers (complex values) onto -// a collapsed vector of "carriers / 8" length, -// considered to consist of 8 segments of 24 values -// Each "value" is the sum of 4 pairs of subsequent carriers, -// taken from the 4 quadrants -768 .. 385, 384 .. -1, 1 .. 384, 385 .. 768 - - collapse (theBuffer. data(), hulpTable); -// -// since the "energy levels" in the different GROUPSIZE'd values -// may differ, we compute an average for each of the -// NUM_GROUPS GROUPSIZE - value groups. - - memset (avgTable, 0, NUM_GROUPS * sizeof (float)); - for (i = 0; i < NUM_GROUPS; i ++) { - avgTable [i] = 0; - for (j = 0; j < GROUPSIZE; j ++) - avgTable [i] += hulpTable [i * GROUPSIZE + j]; - - avgTable [i] /= GROUPSIZE; - } -// -// Determining the offset is then easy, look at the corresponding -// elements in the NUM_GROUPS sections and mark the highest ones. -// The summation of the high values are stored in the C_table, -// the number of times the limit is reached in the group -// is recorded in the D_table -// -// So, basically we look into GROUPSIZE colums of NUMGROUPS -// values and look for the maximum -// Threshold 4 * avgTable is 6 dB, we consider that a minimum -// measurement shows that that is a reasonable value, -// alternatively, we could take the "minValue" as reference -// and "raise" the threshold. However, that might be -// too much for 8-bit incoming values - memset (D_table, 0, GROUPSIZE * sizeof (int)); - memset (C_table, 0, GROUPSIZE * sizeof (float)); -// -// We gebruiken C en D table alleen maar om de begin offset -// te kunnen vinden - for (i = 0; i < GROUPSIZE; i ++) { - for (j = 0; j < NUM_GROUPS; j ++) { - if (hulpTable [j * GROUPSIZE + i] > 4 * avgTable [j]) { - C_table [i] += hulpTable [j * GROUPSIZE + i]; - D_table [i] ++; - } - } - } - -// we extract from this result the highest values that -// meet the constraint of 4 values being sufficiently high - float maxTable = 0; - int maxIndex = -1; - - for (j = 0; j < GROUPSIZE; j ++) { - if ((D_table [j] >= 4) && (C_table [j] > maxTable)) { - maxTable = C_table [j]; - maxIndex = j; - break; - } - } -// - if (maxIndex < 0) +int fcmp (const void *a, const void *b) { + tiiData *element1 = (tiiData *)a; + tiiData *element2 = (tiiData *)b; + if (element1 -> strength > element2 -> strength) + return -1; + else + if (element1 -> strength < element2 -> strength) + return 1; + else return 0; - -// The - almost - final step is then to figure out which -// group contributed most, obviously only where maxIndex > 0 -// we start with collecting the values of the correct -// elements of the NUM_GROUPS groups - - float x [NUM_GROUPS]; - for (i = 0; i < NUM_GROUPS; i ++) - x [i] = hulpTable [maxIndex + GROUPSIZE * i]; -// -// we extract the four max values as bits - uint16_t pattern = 0; - for (i = 0; i < 4; i ++) { - float mmax = 0; - int ind = -1; - for (int k = 0; k < NUM_GROUPS; k ++) { - if (x [k] > mmax) { - mmax = x [k]; - ind = k; - } - } - - if (ind != -1) { - x [ind] = 0; - pattern |= bits [ind]; - } - } - return maxIndex + (invTable [pattern]) * 256; } +std::vector TII_Detector::processNULL (int16_t threshold_db) { +// collapsed ETSI float values +float etsi_floatTable [NUM_GROUPS * GROUPSIZE]; +// collapsed non-ETSI float values +float nonetsi_floatTable [NUM_GROUPS * GROUPSIZE]; +// collapsed ETSI complex values + +Complex etsiTable [NUM_GROUPS * GROUPSIZE]; +// collapsed non-ETSI complex values +Complex nonetsiTable [NUM_GROUPS * GROUPSIZE]; + +float max = 0; // abs value of the strongest carrier +float noise = 1e9; // noise level +std::vector theResult; // results +float avg_etsi [NUM_GROUPS]; +float avg_nonetsi [NUM_GROUPS]; + + tiiThreshold = 4; +bool tiiFilter = true; +float threshold = pow (10, (float)threshold_db / 10); // threshold above noise +int Teller = 0; + + for (int32_t idx = -carriers / 2; idx < carriers / 2; idx += 2) { + const int32_t fftIdx = idx < 0 ? idx + T_u : idx + 1; + decodedBuffer [Teller++] += + nullSymbolBuffer [fftIdx] * conj (nullSymbolBuffer [fftIdx + 1]); + } + + collapse (decodedBuffer, etsiTable, nonetsiTable, tiiFilter); + + +// fill the float tables, determine the abs value of the strongest carrier + for (int i = 0; i < NUM_GROUPS * GROUPSIZE; i++) { + float x = jan_abs (etsiTable [i]); + etsi_floatTable [i] = x; + if (x > max) + max = x; + x = jan_abs (nonetsiTable [i]); + nonetsi_floatTable [i] = x; + if (x > max) + max = x; + } + + for (int group = 0; group < NUM_GROUPS; group ++) { + avg_etsi [group] = 0; + avg_nonetsi [group] = 0; + for (int j = 0; j < GROUPSIZE; j ++) { + avg_etsi [group] += etsi_floatTable [group * GROUPSIZE + j]; + avg_nonetsi [group] += nonetsi_floatTable [group * GROUPSIZE + j]; + } + avg_etsi [group] /= GROUPSIZE; + avg_nonetsi [group] /= GROUPSIZE; + } +// determine the noise level by taking the level of the lowest group + for (int subId = 0; subId < GROUPSIZE; subId++) { + float avg = 0; + for (int i = 0; i < NUM_GROUPS; i++) + avg += etsi_floatTable [subId + i * GROUPSIZE]; + avg /= NUM_GROUPS; + if (avg < noise) + noise = avg; + } + + for (int subId = 0; subId < GROUPSIZE; subId++) { + tiiData element; + Complex sum = Complex (0,0); + Complex etsi_sum = Complex (0,0); + Complex nonetsi_sum = Complex (0,0); + int count = 0; + int etsi_count = 0; + int nonetsi_count = 0; + int pattern = 0; + int etsi_pattern = 0; + int nonetsi_pattern = 0; + int mainId = 0; + bool norm = false; + Complex *cmplx_ptr = nullptr;; + float *float_ptr = nullptr; +// The number of times the limit is reached in the group is counted + for (int i = 0; i < NUM_GROUPS; i++) { + float etsi_noiseLevel = tiiFilter ? avg_etsi [i] : noise; + float nonetsi_noiseLevel = tiiFilter ? avg_nonetsi [i] : noise; + if (etsi_floatTable [subId + i * GROUPSIZE] > + etsi_noiseLevel * threshold) { + etsi_count++; + etsi_pattern |= bits [i]; + etsi_sum += etsiTable [subId + GROUPSIZE * i]; + } + if (nonetsi_floatTable [subId + i * GROUPSIZE] > + nonetsi_noiseLevel * threshold) { + nonetsi_count++; + nonetsi_pattern |= bits [i]; + nonetsi_sum += nonetsiTable [subId + GROUPSIZE * i]; + } + } +// + if ((etsi_count >= 4) || (nonetsi_count >= 4)) { + if (jan_abs (nonetsi_sum) > jan_abs (etsi_sum)) { + norm = true; + sum = nonetsi_sum; + cmplx_ptr = nonetsiTable; + float_ptr = nonetsi_floatTable; + count = nonetsi_count; + pattern = nonetsi_pattern; + } + else { + sum = etsi_sum; + cmplx_ptr = etsiTable; + float_ptr = etsi_floatTable; + count = etsi_count; + pattern = etsi_pattern; + } + } + +// Find the Main Id that matches the pattern + if (count == 4) { + for (; mainId < (int)nrPatterns (); mainId++) + if (getPattern (mainId) == pattern) + break; + } + +// Find the best match. We extract the four max values as bits + else + if (count > 4) { + float mm = 0; + for (int k = 0; k < (int)nrPatterns (); k++) { + Complex val = Complex (0, 0); + for (int i = 0; i < NUM_GROUPS; i++) { + if (getPattern (k) & bits [i]) { + val += cmplx_ptr [subId + GROUPSIZE * i]; + } + } + + if (jan_abs (val) > mm) { + mm = jan_abs (val); + sum = val; + mainId = k; + } + } + } // end if (count > 4), List the result + + if (count >= 4) { + element. mainId = mainId; + element. subId = subId; + element. strength = jan_abs (sum) / max / (tiiFilter ? 2 : 4); + element. phase = arg (sum) * F_DEG_PER_RAD; + element. norm = norm; + element. collision = false; + element. pattern = getPattern (mainId); + theResult. push_back (element); + } + (void)float_ptr; +// +//// Collisions still to be done +// if ((count > 4) && (selected_subId != 0)) { +// sum = Complex (0,0); +// +//// Calculate the level of the second main ID +// for (int i = 0; i < NUM_GROUPS; i++) { +// if ((getPattern (mainId) & bits [i]) == 0) { +// int index = subId + GROUPSIZE * i; +// if (float_ptr [index] > noise * threshold) +// sum += cmplx_ptr [index]; +// } +// } +// +// if (subId == selected_subId) { // List all possible main IDs +// for (int k = 0; k < (int)nrPatterns (); k++) { +// int pattern2 = getPattern (k) & pattern; +// int count2 = 0; +// for (int i = 0; i < NUM_GROUPS; i++) +// if (pattern2 & bits [i]) +// count2++; +// if ((count2 == 4) && (k != mainId)) { +// element. mainId = k; +// element. subId = selected_subId; +// element. strength = jan_abs(sum) / max / (count - 4); +// element. phase = arg(sum) * F_DEG_PER_RAD; +// element. norm = norm; +// element. collision = true; +// element. pattern = getPattern (mainId); +// theResult. push_back (element); +// } +// } +// } +// else { // List only additional main ID 99 +//// element. mainId = 99; +//// element. strength = abs(sum)/max/(count-4); +//// element. phase = arg(sum) * F_DEG_PER_RAD; +//// element. norm = norm; +//// theResult.push_back(element); +// } +// } + } +// fprintf(stderr, "max =%.0f, noise = %.1fdB\n", max, 10 * log10(noise/max)); + if (max > 4000) +// if (max > 4000000) + for (int i = 0; i < carriers / 2; i++) + decodedBuffer [i] *= 0.9; + resetBuffer(); + qsort (theResult. data (), theResult. size(), + sizeof (tiiData), &fcmp); + return theResult; +} + + +uint16_t TII_Detector::getPattern (int n) { + return patternTable [n]; +} + +uint16_t TII_Detector::nrPatterns () { + return (uint16_t)sizeof (patternTable); +} + diff --git a/library/src/backend/charsets.cpp b/library/src/support/charsets.cpp similarity index 100% rename from library/src/backend/charsets.cpp rename to library/src/support/charsets.cpp diff --git a/library/src/support/fft-handler.cpp b/library/src/support/fft-handler.cpp index 80c182b..c06c2c3 100644 --- a/library/src/support/fft-handler.cpp +++ b/library/src/support/fft-handler.cpp @@ -41,11 +41,19 @@ fftwf_free (vector); } +void fft_handler::fft (Complex *v) { + for (int i = 0; i < fftSize; i ++) + vector [i] = v [i]; + fftwf_execute (plan); + for (int i = 0; i < fftSize; i ++) + v [i] = vector [i]; +} + complex *fft_handler::getVector () { return vector; } // -void fft_handler::do_FFT (void) { +void fft_handler::do_FFT () { fftwf_execute (plan); } diff --git a/library/src/time-converter.cpp b/library/src/time-converter.cpp new file mode 100644 index 0000000..f305ba8 --- /dev/null +++ b/library/src/time-converter.cpp @@ -0,0 +1,51 @@ +# +/* + * Copyright (C) 2013 .. 2024 + * Jan van Katwijk (J.vanKatwijk@gmail.com) + * Lazy Chair Computing + * + * This file is part of the Qt-DAB + * + * Qt-DAB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Qt-DAB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qt-DAB; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "time-converter.h" + +// Modified Julian Date (recompute according to wikipedia) +void convertTime (uint32_t mjd, uint16_t *out) { +int32_t J = mjd + 2400001; +int32_t j = J + 32044; +int32_t g = j / 146097; +int32_t dg = j % 146097; +int32_t c = ((dg / 36524) + 1) * 3 / 4; +int32_t dc = dg - c * 36524; +int32_t b = dc / 1461; +int32_t db = dc % 1461; +int32_t a = ((db / 365) + 1) * 3 / 4; +int32_t da = db - a * 365; +int32_t y = g * 400 + c * 100 + b * 4 + a; +int32_t m = ((da * 5 + 308) / 153) - 2; +int32_t d = da - ((m + 4) * 153 / 5) + 122; +int32_t Y = y - 4800 + ((m + 2) / 12); +int32_t M = ((m + 2) % 12) + 1; +int32_t D = d + 1; + + + out [0] = Y; + out [1] = M; + out [2] = D; +} + +