From b02886aa9275dba22f1adcb3bcd0010fa04512fa Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 7 Oct 2012 16:01:19 +0200 Subject: [PATCH] add basic support for DVB-T This needs more fine tuning wrt scan setup etc, but should work for now. --- data/Makefile.am | 2 +- data/locale/deutsch.locale | 2 + data/locale/english.locale | 2 + data/mk_terrestrial_xml.pl | 92 +++++++++++++++++++++++++ data/terrestrial.xml | 86 +++++++++++++++++++++++ src/gui/scan.cpp | 12 ++++ src/gui/scan_setup.cpp | 39 ++++++++--- src/neutrino.cpp | 13 +++- src/system/locals.h | 2 + src/system/locals_intern.h | 2 + src/zapit/include/zapit/getservices.h | 2 +- src/zapit/include/zapit/scan.h | 1 - src/zapit/include/zapit/settings.h | 1 + src/zapit/src/frontend.cpp | 98 +++++++++++++++++++++++++-- src/zapit/src/getservices.cpp | 64 +++++++++++++---- src/zapit/src/scan.cpp | 12 ++-- src/zapit/src/transponder.cpp | 49 ++++++++++++-- 17 files changed, 433 insertions(+), 46 deletions(-) create mode 100755 data/mk_terrestrial_xml.pl create mode 100644 data/terrestrial.xml diff --git a/data/Makefile.am b/data/Makefile.am index 7519719cd..3ba17d519 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -5,4 +5,4 @@ SUBDIRS += lcd endif configdir = $(CONFIGDIR) -config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml +config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml terrestrial.xml diff --git a/data/locale/deutsch.locale b/data/locale/deutsch.locale index 5128ccb86..ecf5dde3f 100644 --- a/data/locale/deutsch.locale +++ b/data/locale/deutsch.locale @@ -1187,6 +1187,7 @@ scants.abort_body Scanvorgang wirklich abbrechen? scants.abort_header breche Scan ab... scants.actcable Kabelnetz: scants.actsatellite Satellit: +scants.actterrestrial Terrestrisch: scants.bouquet Bouquets scants.bouquet_create neu erstellen scants.bouquet_erase löschen @@ -1274,6 +1275,7 @@ stringinput.caps Groß-/Kleinbuchstaben stringinput.clear Alles löschen subtitles.head Untertitel subtitles.stop Untertitel aus +terrestrialsetup.provider DVB-T Region timer.eventrecord.msg Die Sendung wurde zur Aufnahme vorgemerkt. timer.eventrecord.title Aufnahme vormerken timer.eventtimed.msg Die Sendung wurde vorgemerkt. diff --git a/data/locale/english.locale b/data/locale/english.locale index d4fef7366..226e52712 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -1188,6 +1188,7 @@ scants.abort_body Should the search really be aborted? scants.abort_header Abortion of channel scan scants.actcable Cable: scants.actsatellite Satellite: +scants.actterrestrial Terrestrial: scants.bouquet Bouquet scants.bouquet_create create new scants.bouquet_erase erase all @@ -1275,6 +1276,7 @@ stringinput.caps caps / no caps stringinput.clear clear all subtitles.head Subtitles subtitles.stop Stop subtitles +terrestrialsetup.provider Terrestrial Provider timer.eventrecord.msg ... TO be DONE, or not to be done timer.eventrecord.title Schedule Record timer.eventtimed.msg The event is scheduled.\nThe box will power on and \nswitch to this channel at the given time. diff --git a/data/mk_terrestrial_xml.pl b/data/mk_terrestrial_xml.pl new file mode 100755 index 000000000..e008f25ec --- /dev/null +++ b/data/mk_terrestrial_xml.pl @@ -0,0 +1,92 @@ +#!/usr/bin/perl -w +# +# create a terrestrial.xml for neutrino from the data installed by the +# dvb utils +# the behaviour is similar to the "scan" program form the dvb utils. +# +# Released under the GPL V2 or later +# (C) 2009-2012 Stefan Seyfried + +use strict; +my $srcdir = "/usr/share/dvb/dvb-t"; + +# can be given as "de-*" +my $scanfile = shift; +$scanfile = "auto-Default" unless (defined $scanfile); + +my @sourcefiles = glob($srcdir . "/" . $scanfile); +my ($sourcefile, $basename, $line, $k); +my ($freq, $bw, $cr_hp, $cr_lp, $mod, $tmode, $gint, $hier); + +# from /usr/include/linux/dvb/frontend.h +# inversion is not used in the scan files +my %INV = ("INVERSION_OFF" => 0, "INVERSION_ON" => 1, "INVERSION_AUTO" => 2); +my %CODE_RATE = ("NONE" => 0, "1/2" => 1, "2/3" => 2, "3/4" => 3, "4/5" => 4, + "5/6" => 5, "6/7" => 6, "7/8" => 7, "8/9" => 8, "AUTO" => 9); +my %MODULATION = ("QPSK" => 0, "QAM16" => 1, "QAM32" => 2, "QAM64" => 3, + "QAM128" => 4, "QAM256" => 5, "AUTO" => 6); +my %T_MODE = ("2k" => 0, "8k" => 1, "AUTO" => 2); +my %BWIDTH = ("8MHz" => 0, "7MHz" => 1, "6MHz" => 2, "AUTO" => 3); +my %GINTERVAL = ("1/32" => 0, "1/16" => 1, "1/8" => 2, "1/4" => 3, "AUTO" => 4); +my %HIERARCHY = ("NONE" => 0, "1" => 1, "2" => 2, "4" => 3, "AUTO" => 4); + + +# print the header +print("\n"); +print("\n\n"); +print("\n"); +# +# explain the parameters +print("\n\n"); +# header ends... + +print("\n"); +foreach $sourcefile (@sourcefiles) +{ + open(FILE, "< $sourcefile") or die "can't open $sourcefile: $!\n"; + $basename = $sourcefile; + $basename =~ s#^.*/##; + print("\t\n"); + while ($line = ) + { # T 184500000 7MHz 3/4 NONE QAM16 8k 1/4 NONE + next unless ($line =~ m/^T\s+(\d+)\s+(\dMHz)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/); + $freq = $1; $bw = $2; $cr_hp = $3; $cr_lp = $4; $mod = $5; $tmode = $6; $gint = $7; $hier = $8; + unless (defined($CODE_RATE{$cr_hp})) { warn "$basename: illegal cr_hp: $cr_hp, using AUTO\n"; $cr_hp="AUTO" }; + unless (defined($CODE_RATE{$cr_lp})) { warn "$basename: illegal cr_lp: $cr_lp, using AUTO\n"; $cr_lp="AUTO" }; + unless (defined($MODULATION{$mod})) { die "$basename: illegal mod: $mod\n" }; # no errors in those (yet). + unless (defined($T_MODE{$tmode})) { die "$basename: illegal tmode: $tmode\n" }; + unless (defined($GINTERVAL{$gint})) { die "$basename: illegal gint: $gint\n" }; + unless (defined($HIERARCHY{$hier})) { die "$basename: illegal hier: $hier\n" }; + unless (defined($BWIDTH{$bw})) { die "$basename: illegal bw: $bw\n" }; + if ($cr_hp eq "NONE") { $cr_hp="AUTO" }; # same as scan.c + if ($cr_lp eq "NONE") { $cr_lp="AUTO" }; # same as scan.c + printf("\t\t\n", + $freq / 1000, $BWIDTH{$bw}, $MODULATION{$mod}, + $T_MODE{$tmode}, $CODE_RATE{$cr_hp}, $CODE_RATE{$cr_lp}, + $GINTERVAL{$gint}, $HIERARCHY{$hier}); + } + print("\t\n"); +} +print("\n"); diff --git a/data/terrestrial.xml b/data/terrestrial.xml new file mode 100644 index 000000000..6c03dd07e --- /dev/null +++ b/data/terrestrial.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/gui/scan.cpp b/src/gui/scan.cpp index 2a36740f8..371239b25 100644 --- a/src/gui/scan.cpp +++ b/src/gui/scan.cpp @@ -202,6 +202,18 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) TP.feparams.dvb_feparams.u.qpsk.symbol_rate = atoi(scansettings.TP_rate); TP.feparams.dvb_feparams.u.qpsk.fec_inner = (fe_code_rate_t) scansettings.TP_fec; TP.polarization = scansettings.TP_pol; + } else if (g_info.delivery_system == DVB_T) { + /* DVB-T. TODO: proper menu and parameter setup, not all "AUTO" */ + if (TP.feparams.dvb_feparams.frequency < 300000) + TP.feparams.dvb_feparams.u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + else + TP.feparams.dvb_feparams.u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + TP.feparams.dvb_feparams.u.ofdm.code_rate_HP = FEC_AUTO; + TP.feparams.dvb_feparams.u.ofdm.code_rate_LP = FEC_AUTO; + TP.feparams.dvb_feparams.u.ofdm.constellation = QAM_AUTO; + TP.feparams.dvb_feparams.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + TP.feparams.dvb_feparams.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + TP.feparams.dvb_feparams.u.ofdm.hierarchy_information = HIERARCHY_AUTO; } else { TP.feparams.dvb_feparams.u.qam.symbol_rate = atoi(scansettings.TP_rate); TP.feparams.dvb_feparams.u.qam.fec_inner = (fe_code_rate_t)scansettings.TP_fec; diff --git a/src/gui/scan_setup.cpp b/src/gui/scan_setup.cpp index 56198127c..b14e73628 100644 --- a/src/gui/scan_setup.cpp +++ b/src/gui/scan_setup.cpp @@ -218,7 +218,19 @@ CScanSetup::CScanSetup(bool wizard_mode) is_wizard = wizard_mode; //define caption of some forwarders and widgets depends of current receiver type - satprov_locale = (r_system == DVB_S) ? LOCALE_SATSETUP_SATELLITE : LOCALE_CABLESETUP_PROVIDER; + switch (r_system) + { + case DVB_S: + satprov_locale = LOCALE_SATSETUP_SATELLITE; + break; + case DVB_T: + satprov_locale = LOCALE_TERRESTRIALSETUP_PROVIDER; + break; + case DVB_C: + default: + satprov_locale = LOCALE_CABLESETUP_PROVIDER; + break; + } satSelect = NULL; frontendSetup = NULL; @@ -368,7 +380,7 @@ int CScanSetup::showScanMenu() /* add configured satellites to satSelect */ fillSatSelect(); } - else if (r_system == DVB_C) //cable + else if (r_system == DVB_C || r_system == DVB_T) //cable { //-------------------------------------------------------------- settings->addItem(GenericMenuSeparatorLine); @@ -848,15 +860,20 @@ int CScanSetup::addScanOptionsItems(CMenuWidget *options_menu, const int &shortc printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); int shortCut = shortcut; + CMenuOptionChooser *fec = NULL; + CMenuOptionChooser *mod_pol= NULL; + CStringInput *rate = NULL; + CMenuForwarder *Rate = NULL; + CStringInput *freq = new CStringInput(LOCALE_EXTRA_TP_FREQ, (char *) scansettings.TP_freq, freq_length, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789"); CMenuForwarder *Freq = new CMenuDForwarder(LOCALE_EXTRA_TP_FREQ, true, scansettings.TP_freq, freq, "", CRCInput::convertDigitToKey(shortCut++)); - CStringInput *rate = new CStringInput(LOCALE_EXTRA_TP_RATE, (char *) scansettings.TP_rate, 8, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789"); - CMenuForwarder *Rate = new CMenuDForwarder(LOCALE_EXTRA_TP_RATE, true, scansettings.TP_rate, rate, "", CRCInput::convertDigitToKey(shortCut++)); + if (r_system != DVB_T) { + rate = new CStringInput(LOCALE_EXTRA_TP_RATE, (char *) scansettings.TP_rate, 8, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789"); + Rate = new CMenuDForwarder(LOCALE_EXTRA_TP_RATE, true, scansettings.TP_rate, rate, "", CRCInput::convertDigitToKey(shortCut++)); + } - CMenuOptionChooser *fec = NULL; - - CMenuOptionChooser *mod_pol= NULL; + /* TODO: DVB-T scan options */ if (r_system == DVB_S) { fec = new CMenuOptionChooser(LOCALE_EXTRA_TP_FEC, (int *)&scansettings.TP_fec, SATSETUP_SCANTP_FEC, fec_count, true, NULL, CRCInput::convertDigitToKey(shortCut++), "", true); mod_pol = new CMenuOptionChooser(LOCALE_EXTRA_TP_POL, (int *)&scansettings.TP_pol, SATSETUP_SCANTP_POL, SATSETUP_SCANTP_POL_COUNT, true, NULL, CRCInput::convertDigitToKey(shortCut++)); @@ -865,10 +882,12 @@ int CScanSetup::addScanOptionsItems(CMenuWidget *options_menu, const int &shortc } options_menu->addItem(Freq); - options_menu->addItem(Rate); - if (r_system == DVB_S) + if (Rate) + options_menu->addItem(Rate); + if (fec) options_menu->addItem(fec); - options_menu->addItem(mod_pol); + if (mod_pol) + options_menu->addItem(mod_pol); return shortCut; } diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 37f2daa01..b8dc9b6bd 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -1869,7 +1869,18 @@ fprintf(stderr, "[neutrino start] %d -> %5ld ms\n", __LINE__, time_monotonic_ms cpuFreq = new cCpuFreqManager(); cpuFreq->SetCpuFreq(g_settings.cpufreq * 1000 * 1000); - g_info.delivery_system = CFEManager::getInstance()->getLiveFE()->getInfo()->type == FE_QPSK ? DVB_S : DVB_C; + switch (CFEManager::getInstance()->getLiveFE()->getInfo()->type) { + case FE_QPSK: + g_info.delivery_system = DVB_S; + break; + case FE_OFDM: + g_info.delivery_system = DVB_T; + break; + case FE_QAM: + default: + g_info.delivery_system = DVB_C; + break; + } #if HAVE_COOL_HARDWARE /* only SAT-hd1 before rev 8 has fan */ g_info.has_fan = (cs_get_revision() < 8 && g_info.delivery_system == DVB_S); diff --git a/src/system/locals.h b/src/system/locals.h index e013eccf4..b29c95e3a 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -1215,6 +1215,7 @@ typedef enum LOCALE_SCANTS_ABORT_HEADER, LOCALE_SCANTS_ACTCABLE, LOCALE_SCANTS_ACTSATELLITE, + LOCALE_SCANTS_ACTTERRESTRIAL, LOCALE_SCANTS_BOUQUET, LOCALE_SCANTS_BOUQUET_CREATE, LOCALE_SCANTS_BOUQUET_ERASE, @@ -1302,6 +1303,7 @@ typedef enum LOCALE_STRINGINPUT_CLEAR, LOCALE_SUBTITLES_HEAD, LOCALE_SUBTITLES_STOP, + LOCALE_TERRESTRIALSETUP_PROVIDER, LOCALE_TIMER_EVENTRECORD_MSG, LOCALE_TIMER_EVENTRECORD_TITLE, LOCALE_TIMER_EVENTTIMED_MSG, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index fffc15c75..a0d883ef9 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -1215,6 +1215,7 @@ const char * locale_real_names[] = "scants.abort_header", "scants.actcable", "scants.actsatellite", + "scants.actterrestrial", "scants.bouquet", "scants.bouquet_create", "scants.bouquet_erase", @@ -1302,6 +1303,7 @@ const char * locale_real_names[] = "stringinput.clear", "subtitles.head", "subtitles.stop", + "terrestrialsetup.provider", "timer.eventrecord.msg", "timer.eventrecord.title", "timer.eventtimed.msg", diff --git a/src/zapit/include/zapit/getservices.h b/src/zapit/include/zapit/getservices.h index 7783bcfbb..10d6deef0 100644 --- a/src/zapit/include/zapit/getservices.h +++ b/src/zapit/include/zapit/getservices.h @@ -88,7 +88,7 @@ class CServiceManager sat_transponder_map_t satelliteTransponders; bool ParseScanXml(); - void ParseTransponders(xmlNodePtr node, t_satellite_position satellitePosition, bool cable); + void ParseTransponders(xmlNodePtr node, t_satellite_position satellitePosition, fe_type fe); void ParseChannels(xmlNodePtr node, const t_transport_stream_id transport_stream_id, const t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq, uint8_t polarization); void FindTransponder(xmlNodePtr search); void ParseSatTransponders(fe_type_t frontendType, xmlNodePtr search, t_satellite_position satellitePosition); diff --git a/src/zapit/include/zapit/scan.h b/src/zapit/include/zapit/scan.h index 36a6f5b54..b298a9469 100644 --- a/src/zapit/include/zapit/scan.h +++ b/src/zapit/include/zapit/scan.h @@ -60,7 +60,6 @@ class CServiceScan : public OpenThreads::Thread private: bool started; bool running; - bool cable; bool abort_scan; scan_type_t scan_mode; int flags; diff --git a/src/zapit/include/zapit/settings.h b/src/zapit/include/zapit/settings.h index b72dc214f..4f5192ad7 100644 --- a/src/zapit/include/zapit/settings.h +++ b/src/zapit/include/zapit/settings.h @@ -47,6 +47,7 @@ #define CABLES_XML CONFIGDIR "/cables.xml" #define SATELLITES_XML CONFIGDIR "/satellites.xml" +#define TERRESTRIAL_XML CONFIGDIR "/terrestrial.xml" #if HAVE_TRIPLEDRAGON == 0 #define AUDIO_DEVICE "/dev/dvb/adapter0/audio0" diff --git a/src/zapit/src/frontend.cpp b/src/zapit/src/frontend.cpp index 8cac24368..318418b4e 100644 --- a/src/zapit/src/frontend.cpp +++ b/src/zapit/src/frontend.cpp @@ -52,17 +52,27 @@ extern int zapit_debug; #define FREQUENCY 1 #define MODULATION 2 #define INVERSION 3 +// common to S/S2/C #define SYMBOL_RATE 4 #define DELIVERY_SYSTEM 5 #define INNER_FEC 6 // DVB-S/S2 specific #define PILOTS 7 #define ROLLOFF 8 +// DVB-T specific +#define BANDWIDTH 4 +#define CODE_RATE_HP 6 +#define CODE_RATE_LP 7 +#define TRANSMISSION_MODE 8 +#define GUARD_INTERVAL 9 +#define HIERARCHY 10 + #define FE_COMMON_PROPS 2 #define FE_DVBS_PROPS 6 #define FE_DVBS2_PROPS 8 #define FE_DVBC_PROPS 6 +#define FE_DVBT_PROPS 10 /* stolen from dvb.c from vlc */ static const struct dtv_property dvbs_cmdargs[] = { @@ -100,6 +110,21 @@ static const struct dtv_property dvbc_cmdargs[] = { { DTV_TUNE, {}, { 0 }, 0}, }; +static const struct dtv_property dvbt_cmdargs[] = { + { DTV_CLEAR, {0,0,0}, { 0 } ,0}, + { DTV_FREQUENCY, {}, { 0 } ,0}, + { DTV_MODULATION, {}, { QAM_AUTO } ,0}, + { DTV_INVERSION, {}, { INVERSION_AUTO } ,0}, + { DTV_BANDWIDTH_HZ, {}, { 8000000 } ,0}, + { DTV_DELIVERY_SYSTEM, {}, { SYS_DVBT } ,0}, + { DTV_CODE_RATE_HP, {}, { FEC_AUTO } ,0}, + { DTV_CODE_RATE_LP, {}, { FEC_AUTO } ,0}, + { DTV_TRANSMISSION_MODE,{}, { TRANSMISSION_MODE_AUTO}, 0}, + { DTV_GUARD_INTERVAL, {}, { GUARD_INTERVAL_AUTO}, 0}, + { DTV_HIERARCHY, {}, { HIERARCHY_AUTO }, 0}, + { DTV_TUNE, {}, { 0 }, 0}, +}; + #define diff(x,y) (max(x,y) - min(x,y)) @@ -528,7 +553,8 @@ void CFrontend::getDelSys(int f, int m, char *&fec, char *&sys, char *&mod) void CFrontend::getDelSys(uint8_t type, int f, int m, char *&fec, char *&sys, char *&mod) { - if (type == FE_QPSK) { + switch (type) { + case FE_QPSK: if (f < FEC_S2_QPSK_1_2) { sys = (char *)"DVB"; mod = (char *)"QPSK"; @@ -539,7 +565,9 @@ void CFrontend::getDelSys(uint8_t type, int f, int m, char *&fec, char *&sys, ch sys = (char *)"DVB-S2"; mod = (char *)"8PSK"; } - } else if (type == FE_QAM) { + break; + case FE_QAM: + case FE_OFDM: sys = (char *)"DVB"; switch (m) { case QAM_16: @@ -557,11 +585,23 @@ void CFrontend::getDelSys(uint8_t type, int f, int m, char *&fec, char *&sys, ch case QAM_256: mod = (char *)"QAM_256"; break; + case QPSK: + if (type == FE_OFDM) { + mod = (char *)"QPSK"; + break; + } + /* fallthrouh for FE_QAM... */ case QAM_AUTO: default: mod = (char *)"QAM_AUTO"; break; } + break; + default: + printf("[frontend] unknown type %d!\n", type); + sys = (char *)"UNKNOWN"; + mod = (char *)"UNKNOWN"; + break; } switch (f) { @@ -641,6 +681,11 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p modulation = feparams->dvb_feparams.u.qam.modulation; delsys = SYS_DVBC_ANNEX_AC; break; + case FE_OFDM: + fec_inner = FEC_AUTO; /* dummy, for next switch statement */ + modulation = feparams->dvb_feparams.u.ofdm.constellation; + delsys = SYS_DVBT; + break; default: printf("frontend: unknown frontend type, exiting\n"); return 0; @@ -739,6 +784,36 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p cmdseq.props[INNER_FEC].u.data = fec_inner; nrOfProps = FE_DVBC_PROPS; break; + case FE_OFDM: + memcpy(cmdseq.props, dvbt_cmdargs, sizeof(dvbt_cmdargs)); + nrOfProps = FE_DVBT_PROPS; + cmdseq.props[FREQUENCY].u.data = feparams->dvb_feparams.frequency; + cmdseq.props[MODULATION].u.data = modulation; + cmdseq.props[INVERSION].u.data = feparams->dvb_feparams.inversion; + cmdseq.props[CODE_RATE_HP].u.data = feparams->dvb_feparams.u.ofdm.code_rate_HP; + cmdseq.props[CODE_RATE_LP].u.data = feparams->dvb_feparams.u.ofdm.code_rate_LP; + cmdseq.props[TRANSMISSION_MODE].u.data = feparams->dvb_feparams.u.ofdm.transmission_mode; + cmdseq.props[GUARD_INTERVAL].u.data = feparams->dvb_feparams.u.ofdm.guard_interval; + cmdseq.props[HIERARCHY].u.data = feparams->dvb_feparams.u.ofdm.hierarchy_information; + switch (feparams->dvb_feparams.u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + cmdseq.props[BANDWIDTH].u.data = 6000000; + break; + case BANDWIDTH_7_MHZ: + cmdseq.props[BANDWIDTH].u.data = 7000000; + break; + case BANDWIDTH_8_MHZ: + cmdseq.props[BANDWIDTH].u.data = 8000000; + break; + default: + printf("[fe%d] unknown bandwidth for OFDM %d\n", + fenumber, feparams->dvb_feparams.u.ofdm.bandwidth); + /* fallthrough */ + case BANDWIDTH_AUTO: + cmdseq.props[BANDWIDTH].u.data = 0; + break; + } + break; default: printf("frontend: unknown frontend type, exiting\n"); return false; @@ -758,7 +833,7 @@ bool CFrontend::buildProperties(const FrontendParameters *feparams, struct dtv_p int CFrontend::setFrontend(const FrontendParameters *feparams, bool /*nowait*/) { - struct dtv_property cmdargs[FE_COMMON_PROPS + FE_DVBS2_PROPS]; // WARNING: increase when needed more space + struct dtv_property cmdargs[FE_COMMON_PROPS + FE_DVBT_PROPS]; // WARNING: increase when needed more space struct dtv_properties cmdseq; cmdseq.num = FE_COMMON_PROPS; @@ -1143,10 +1218,10 @@ int CFrontend::setParameters(TP_params *TP, bool /*nowait*/) feparams = &currTP.feparams; freq = (int) feparams->dvb_feparams.frequency; char * f, *s, *m; + bool high_band; - if (info.type == FE_QPSK) { - bool high_band; - + switch (info.type) { + case FE_QPSK: if (freq < lnbSwitch) { high_band = false; freq_offset = lnbOffsetLow; @@ -1158,7 +1233,8 @@ int CFrontend::setParameters(TP_params *TP, bool /*nowait*/) feparams->dvb_feparams.frequency = abs(freq - freq_offset); setSec(TP->diseqc, TP->polarization, high_band); getDelSys(feparams->dvb_feparams.u.qpsk.fec_inner, dvbs_get_modulation(feparams->dvb_feparams.u.qpsk.fec_inner), f, s, m); - } else if (info.type == FE_QAM) { + break; + case FE_QAM: if (freq < 1000*1000) feparams->dvb_feparams.frequency = freq * 1000; getDelSys(feparams->dvb_feparams.u.qam.fec_inner,feparams->dvb_feparams.u.qam.modulation, f, s, m); @@ -1173,6 +1249,14 @@ int CFrontend::setParameters(TP_params *TP, bool /*nowait*/) break; } #endif + case FE_OFDM: + if (freq < 1000*1000) + feparams->dvb_feparams.frequency = freq * 1000; + getDelSys(feparams->dvb_feparams.u.ofdm.code_rate_HP,feparams->dvb_feparams.u.ofdm.constellation, f, s, m); + break; + default: + printf("[fe%d] unknown type %d\n", fenumber, info.type); + break; } //printf("[fe%d] tuner to frequency %d (offset %d timeout %d)\n", fenumber, feparams->dvb_feparams.frequency, freq_offset, TIMEOUT_MAX_MS); diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index b773d6469..e9c6cfe12 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -70,11 +70,12 @@ bool CServiceManager::ParseScanXml(void) case FE_QPSK: scanInputParser = parseXmlFile(SATELLITES_XML); break; - case FE_QAM: scanInputParser = parseXmlFile(CABLES_XML); break; - + case FE_OFDM: + scanInputParser = parseXmlFile(TERRESTRIAL_XML); + break; default: WARN("Unknown type %d", frontendType); return false; @@ -291,7 +292,7 @@ std::string CServiceManager::GetServiceName(t_channel_id channel_id) return ""; } -void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position satellitePosition, bool cable) +void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position satellitePosition, fe_type fe) { uint8_t polarization = 0; @@ -304,14 +305,18 @@ void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position sa feparams.dvb_feparams.frequency = xmlGetNumericAttribute(node, "frq", 0); feparams.dvb_feparams.inversion = (fe_spectral_inversion) xmlGetNumericAttribute(node, "inv", 0); - if(cable) { + switch (fe) { + case FE_QAM: feparams.dvb_feparams.u.qam.symbol_rate = xmlGetNumericAttribute(node, "sr", 0); feparams.dvb_feparams.u.qam.fec_inner = (fe_code_rate_t) xmlGetNumericAttribute(node, "fec", 0); feparams.dvb_feparams.u.qam.modulation = (fe_modulation_t) xmlGetNumericAttribute(node, "mod", 0); if (feparams.dvb_feparams.frequency > 1000*1000) feparams.dvb_feparams.frequency = feparams.dvb_feparams.frequency/1000; //transponderlist was read from tuxbox - } else { + break; + case FE_OFDM: + break; + default: feparams.dvb_feparams.u.qpsk.fec_inner = (fe_code_rate_t) xmlGetNumericAttribute(node, "fec", 0); feparams.dvb_feparams.u.qpsk.symbol_rate = xmlGetNumericAttribute(node, "sr", 0); @@ -325,7 +330,8 @@ void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position sa else feparams.dvb_feparams.frequency = (int) 1000 * (int) round ((double) feparams.dvb_feparams.frequency / (double) 1000); } - freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, cable); + + freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, fe != FE_QPSK); transponder_id_t tid = CREATE_TRANSPONDER_ID64(freq, satellitePosition,original_network_id,transport_stream_id); transponder t(frontendType, tid, feparams, polarization); @@ -438,18 +444,19 @@ void CServiceManager::ParseChannels(xmlNodePtr node, const t_transport_stream_id void CServiceManager::FindTransponder(xmlNodePtr search) { while (search) { - bool cable = false; + bool sat = false; - if (!(strcmp(xmlGetName(search), "cable"))) - cable = true; - else if ((strcmp(xmlGetName(search), "sat"))) { + if (!(strcmp(xmlGetName(search), "sat"))) + sat = true; + else if (strcmp(xmlGetName(search), "cable") && strcmp(xmlGetName(search), "terrestrial")) { search = search->xmlNextNode; continue; } t_satellite_position satellitePosition = xmlGetSignedNumericAttribute(search, "position", 10); DBG("going to parse dvb-%c provider %s\n", xmlGetName(search)[0], xmlGetAttribute(search, "name")); - ParseTransponders(search->xmlChildrenNode, satellitePosition, cable); + /* ParseTransponders is only interested in sat / not sat, sp the real type does not matter */ + ParseTransponders(search->xmlChildrenNode, satellitePosition, sat ? FE_QPSK : FE_QAM); newfound++; search = search->xmlNextNode; } @@ -490,7 +497,28 @@ void CServiceManager::ParseSatTransponders(fe_type_t fType, xmlNodePtr search, t feparams.dvb_feparams.u.qpsk.fec_inner = (fe_code_rate_t) xml_fec; feparams.dvb_feparams.frequency = (int) 1000 * (int) round ((double) feparams.dvb_feparams.frequency / (double) 1000); } - freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, fType == FE_QAM); + else if (fType == FE_OFDM) { + feparams.dvb_feparams.u.ofdm.bandwidth = (fe_bandwidth_t) + xmlGetNumericAttribute(tps, "bandwidth", 0); + feparams.dvb_feparams.u.ofdm.constellation = (fe_modulation_t) + xmlGetNumericAttribute(tps, "constellation", 0); + feparams.dvb_feparams.u.ofdm.transmission_mode = (fe_transmit_mode_t) + xmlGetNumericAttribute(tps, "transmission_mode", 0); + feparams.dvb_feparams.u.ofdm.code_rate_HP = (fe_code_rate_t) + xmlGetNumericAttribute(tps, "code_rate_HP", 0); + feparams.dvb_feparams.u.ofdm.code_rate_LP = (fe_code_rate_t) + xmlGetNumericAttribute(tps, "code_rate_LP", 0); + feparams.dvb_feparams.u.ofdm.guard_interval = (fe_guard_interval_t) + xmlGetNumericAttribute(tps, "guard_interval", 0); + feparams.dvb_feparams.u.ofdm.hierarchy_information = (fe_hierarchy_t) + xmlGetNumericAttribute(tps, "hierarchy", 0); + if (feparams.dvb_feparams.frequency > 1000*1000) + feparams.dvb_feparams.frequency /= 1000; // old transponder list + } + else /* we'll probably crash sooner or later, so write to STDERR... */ + fprintf(stderr, "[getservices] %s: unknown frontend type %d!\n", __func__, fType); + + freq_id_t freq = CREATE_FREQ_ID(feparams.dvb_feparams.frequency, fType != FE_QPSK); polarization &= 7; transponder_id_t tid = CREATE_TRANSPONDER_ID64(freq, satellitePosition, fake_nid, fake_tid); @@ -636,7 +664,8 @@ bool CServiceManager::LoadServices(bool only_current) position = xmlGetSignedNumericAttribute(search, "position", 10); char * name = xmlGetAttribute(search, "name"); InitSatPosition(position, name); - } else if(!(strcmp(xmlGetName(search), "cable"))) { + } else if (!strcmp(xmlGetName(search), "cable") || + !strcmp(xmlGetName(search), "terrestrial")) { char * name = xmlGetAttribute(search, "name"); InitSatPosition(position, name); } @@ -726,7 +755,9 @@ void CServiceManager::WriteSatHeader(FILE * fd, sat_config_t &config) case FE_QAM: /* cable */ fprintf(fd, "\t\n", config.name.c_str(), config.position); break; - case FE_OFDM: + case FE_OFDM: /* terrestrial */ + fprintf(fd, "\t\n", config.name.c_str(), config.position); + break; default: break; } @@ -792,6 +823,9 @@ void CServiceManager::SaveServices(bool tocopy, bool if_changed) case FE_QAM: fprintf(fd, "\t\n"); break; + case FE_OFDM: + fprintf(fd, "\t\n"); + break; default: break; } @@ -913,6 +947,8 @@ bool CServiceManager::SaveCurrentServices(transponder_id_t tpid) sprintf(satstr, "\t<%s name=\"%s\"\n", "cable", spos_it->second.name.c_str()); break; case FE_OFDM: + sprintf(satstr, "\t<%s name=\"%s\"\n", "terrestrial", spos_it->second.name.c_str()); + break; default: break; } diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index b7143a7e4..f82d2dcf9 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -282,7 +282,7 @@ _repeat: } } - freq_id_t freq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, cable); + freq_id_t freq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, frontendType != FE_QPSK); CNit nit(satellitePosition, freq, cable_nid); if(flags & SCAN_NIT) @@ -489,7 +489,6 @@ bool CServiceScan::SetFrontend(t_satellite_position satellitePosition) frontend = fe; CFEManager::getInstance()->setLiveFE(frontend); frontendType = frontend->getInfo()->type; - cable = (frontend->getInfo()->type == FE_QAM);//FIXME return true; } @@ -601,9 +600,10 @@ bool CServiceScan::ScanTransponder() printf("[scan] NIT %s, fta only: %s, satellites %s\n", flags & SCAN_NIT ? "yes" : "no", flags & SCAN_FTA ? "yes" : "no", scanProviders.size() == 1 ? "single" : "multi"); - freq_id_t freq = CREATE_FREQ_ID(TP->feparams.dvb_feparams.frequency, cable); + freq_id_t freq = CREATE_FREQ_ID(TP->feparams.dvb_feparams.frequency, frontendType != FE_QPSK); fake_tid++; fake_nid++; + transponder_id_t tid = CREATE_TRANSPONDER_ID64(freq, satellitePosition, fake_nid, fake_tid); transponder t(frontendType, tid, TP->feparams, TP->polarization); t.dump("[scan]"); @@ -643,7 +643,7 @@ bool CServiceScan::ReplaceTransponderParams(freq_id_t freq, t_satellite_position bool ret = false; for (transponder_list_t::iterator tI = transponders.begin(); tI != transponders.end(); ++tI) { if (tI->second.satellitePosition == satellitePosition) { - freq_id_t newfreq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, cable); + freq_id_t newfreq = CREATE_FREQ_ID(tI->second.feparams.dvb_feparams.frequency, frontendType != FE_QPSK); if (freq == newfreq) { memcpy(&tI->second.feparams, feparams, sizeof(struct dvb_frontend_parameters)); tI->second.polarization = polarization; @@ -659,7 +659,7 @@ bool CServiceScan::ReplaceTransponderParams(freq_id_t freq, t_satellite_position void CServiceScan::SendTransponderInfo(transponder &t) { uint32_t actual_freq = t.feparams.dvb_feparams.frequency; - if (!cable) + if (frontendType == FE_QAM) actual_freq /= 1000; CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_FREQUENCY, &actual_freq,sizeof(actual_freq)); @@ -667,7 +667,7 @@ void CServiceScan::SendTransponderInfo(transponder &t) CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_PROVIDER, (void *) " ", 2); CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_SERVICENAME, (void *) " ", 2); - if (!cable) { + if (frontendType == FE_QPSK) { uint32_t actual_polarisation = ((t.feparams.dvb_feparams.u.qpsk.symbol_rate/1000) << 16) | (t.feparams.dvb_feparams.u.qpsk.fec_inner << 8) | (uint)t.polarization; CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_FREQUENCYP, &actual_polarisation,sizeof(actual_polarisation)); } diff --git a/src/zapit/src/transponder.cpp b/src/zapit/src/transponder.cpp index 0db0d34bb..147b327b8 100644 --- a/src/zapit/src/transponder.cpp +++ b/src/zapit/src/transponder.cpp @@ -52,13 +52,20 @@ transponder::transponder() bool transponder::operator==(const transponder& t) const { - return ( + if (type != FE_OFDM) + return ( (satellitePosition == t.satellitePosition) && //(transport_stream_id == t.transport_stream_id) && //(original_network_id == t.original_network_id) && ((polarization & 1) == (t.polarization & 1)) && (abs((int) feparams.dvb_feparams.frequency - (int)t.feparams.dvb_feparams.frequency) <= 3000) ); + return ((satellitePosition == t.satellitePosition) && + //(transport_stream_id == t.transport_stream_id) && + //(original_network_id == t.original_network_id) && + ((polarization & 1) == (t.polarization & 1)) && + (abs((int) feparams.dvb_feparams.frequency - (int)t.feparams.dvb_feparams.frequency) <= 100) + ); } bool transponder::compare(const transponder& t) const @@ -76,13 +83,23 @@ bool transponder::compare(const transponder& t) const (dvb_feparams1->u.qam.modulation == dvb_feparams2->u.qam.modulation || dvb_feparams1->u.qam.modulation == QAM_AUTO || dvb_feparams2->u.qam.modulation == QAM_AUTO) ); - } else { + } else if (type == FE_QPSK) { ret = ( (t == (*this)) && (dvb_feparams1->u.qpsk.symbol_rate == dvb_feparams2->u.qpsk.symbol_rate) && (dvb_feparams1->u.qpsk.fec_inner == dvb_feparams2->u.qpsk.fec_inner || dvb_feparams1->u.qpsk.fec_inner == FEC_AUTO || dvb_feparams2->u.qpsk.fec_inner == FEC_AUTO) ); + } else if (type == FE_OFDM) { + ret = ( (t == (*this)) && + (dvb_feparams1->u.ofdm.bandwidth == dvb_feparams2->u.ofdm.bandwidth) && + (dvb_feparams1->u.ofdm.code_rate_HP == dvb_feparams2->u.ofdm.code_rate_HP || + dvb_feparams1->u.ofdm.code_rate_HP == FEC_AUTO || dvb_feparams2->u.ofdm.code_rate_HP == FEC_AUTO) && + (dvb_feparams1->u.ofdm.code_rate_LP == dvb_feparams2->u.ofdm.code_rate_LP || + dvb_feparams1->u.ofdm.code_rate_LP == FEC_AUTO || dvb_feparams2->u.ofdm.code_rate_LP == FEC_AUTO) && + (dvb_feparams1->u.ofdm.constellation == dvb_feparams2->u.ofdm.constellation || + dvb_feparams1->u.ofdm.constellation == QAM_AUTO || dvb_feparams2->u.ofdm.constellation == QAM_AUTO) + ); } return ret; } @@ -98,12 +115,20 @@ void transponder::dumpServiceXml(FILE * fd) dvb_feparams->u.qam.symbol_rate, dvb_feparams->u.qam.fec_inner, dvb_feparams->u.qam.modulation); - } else { + } else if (type == FE_QPSK) { fprintf(fd, "\t\t\n", transport_stream_id, original_network_id, dvb_feparams->frequency, dvb_feparams->inversion, dvb_feparams->u.qpsk.symbol_rate, dvb_feparams->u.qpsk.fec_inner, polarization); + } else if (type == FE_OFDM) { + fprintf(fd, "\t\t\n", + transport_stream_id, original_network_id, + dvb_feparams->frequency, dvb_feparams->inversion, + dvb_feparams->u.ofdm.bandwidth, dvb_feparams->u.ofdm.code_rate_HP, + dvb_feparams->u.ofdm.code_rate_LP, dvb_feparams->u.ofdm.constellation, + dvb_feparams->u.ofdm.transmission_mode, dvb_feparams->u.ofdm.guard_interval, + dvb_feparams->u.ofdm.hierarchy_information); } } @@ -115,10 +140,14 @@ void transponder::dump(std::string label) printf("%s tp-id %016llx freq %d rate %d fec %d mod %d\n", label.c_str(), transponder_id, dvb_feparams->frequency, dvb_feparams->u.qam.symbol_rate, dvb_feparams->u.qam.fec_inner, dvb_feparams->u.qam.modulation); - else + else if (type == FE_QPSK) printf("%s tp-id %016llx freq %d rate %d fec %d pol %d\n", label.c_str(), transponder_id, dvb_feparams->frequency, dvb_feparams->u.qpsk.symbol_rate, dvb_feparams->u.qpsk.fec_inner, polarization); + else if (type == FE_OFDM) + printf("%s tp-id %016llx freq %d bw %d coderate %d\n", label.c_str(), + transponder_id, dvb_feparams->frequency, dvb_feparams->u.ofdm.bandwidth, + dvb_feparams->u.ofdm.code_rate_HP); } void transponder::ddump(std::string label) @@ -142,8 +171,10 @@ char transponder::pol(unsigned char p) std::string transponder::description() { char buf[128] = {0}; - char * f, *s, *m; + char *f, *s, *m, *f2; struct dvb_frontend_parameters *dvb_feparams = &feparams.dvb_feparams; + const char *bw[4] = { "8MHz", "7MHz", "6MHz", "auto" }; + int b; switch(type) { case FE_QPSK: @@ -155,7 +186,15 @@ std::string transponder::description() snprintf(buf, sizeof(buf), "%d %d %s %s %s ", dvb_feparams->frequency/1000, dvb_feparams->u.qam.symbol_rate/1000, f, s, m); break; case FE_OFDM: + CFrontend::getDelSys(type, dvb_feparams->u.ofdm.code_rate_HP, dvb_feparams->u.ofdm.constellation, f, s, m); + CFrontend::getDelSys(type, dvb_feparams->u.ofdm.code_rate_LP, dvb_feparams->u.ofdm.constellation, f2, s, m); + b = dvb_feparams->u.ofdm.bandwidth; + if (b > 3) + b = 3; + snprintf(buf, sizeof(buf), "%d %s %s %s %s ", dvb_feparams->frequency, bw[b], f, f2, m); + break; case FE_ATSC: + snprintf(buf, sizeof(buf), "ATSC not yet supported "); break; } return std::string(buf);