[vdr] RFC: one or many positioners?

Antti Hartikainen ami+vdr at ah.fi
Mon Apr 22 13:38:31 CEST 2013


On Mon, Apr 22, 2013 at 11:46:34AM +0300, Teemu Suikki wrote:
> 2013/4/21 Klaus Schmidinger <Klaus.Schmidinger at tvdr.de>:
> > I'm currently implementing support for steerable dishes, loosely based
> > on https://linuxtv.org/patch/12911. In doing so, I'm defining a virtual
> > base class cPositioner, which defines all the functions necessary to
> > control the positioner. An implementation of cDiseqcPositioner will
> > allow control of "DiSEqC 1.2" and "USALS" motors. A plugin can derive
> > from cPositioner and implement its very own way of controlling a
> > positioner (like through a serial or USB port or whatever).
> >
> > The question I have now is: will it be enough to have *one* single
> > positioner
> > in any given setup, or are there actually users who have more than one
> > positioner?
> > Supporting only a single positioner (as is done in the aforementioned patch)
> > of course simplifies things quite a bit. So I wouldn't want to add this
> > level of complexity unless there is a real need for it.

Thank you Klaus for working on the positioner support. :)

> Hmm, I guess most only have single positioner. But this might change
> if VDR actually supported more than one. :)
> 
> However, it would be nice to be able to use twin or quad LNB in
> positioner, even if using diseqc switches.. I have no idea how to
> configure this. :)
> 
> An example, my system has four tuners. Each one has 4-to-1 diseqc
> switch. They are configured like this:
> 
> ...
> 
> My positioner actually has twin LNB. I'd like to connect the other
> output to tuner2 input 2, but there is no way this would work even
> with heavy patching of VDR..

I think I would be interested to have possibility for multiple positioners later, if VDR would only support it.

Currently I have only one dish, which is motorised. There I have a Quad LNB. VDR has three DVB-S2 tuners (+ unrelated DVB-T(2) tuners).

Tuner 1: Connected directly to LNB
Tuner 2: Connected directly to LNB
Tuner 3: Connected to LNB via motor

Tuner 3 is used for motor control only, no actual signal is being received there, even it would be and is possible, but this tuner is horrible with weak 
transponders, yet it's the only tuner I have that can supply 18V to motor+LNB.

I have made VEEERY ugly patching to VDR (as I'm not really a software developer and don't know how things should be done, and I have done some unnecessary things 
"just in case"), but I think sharing it will give some people some ideas. But atleast it is working perfectly in my environemnt. :) I don't know what kind of 
unwanted things it may cause elsewhere.

So basicly what I did, I took fd_frontend of tuner 3 (identified by subsystemId), and use it as dfd_frontend. Then I made some changes to device bonding, to 
restrict devices to same satellite source, instead of same band/polarisation. All devices are set in VDR configuration to "connected to cable 1".

And there I have it, somehow working motorised multi-tuner setup. :)

Patch assumes that VDR is patched with GOTOXX patch.
-------------- next part --------------
--- vdr-2.0.0/dvbdevice.c	2013-03-31 13:13:32.081458741 +0300
+++ vdr-1.7.40/dvbdevice.c	2013-03-31 13:26:33.260190854 +0300
@@ -23,6 +23,9 @@
 #include "menuitems.h"
 #include "sourceparams.h"
 
+int dfd_frontend=0;
+int adap=0;
+
 #if (DVB_API_VERSION << 8 | DVB_API_VERSION_MINOR) < 0x0508
 #define DTV_STREAM_ID DTV_DVBT2_PLP_ID
 #define FE_CAN_MULTISTREAM 0x4000000
@@ -344,8 +347,19 @@
   device = Device;
   fd_frontend = Fd_Frontend;
   adapter = Adapter;
+  printf("adapter: %i\n",adapter);
+
+//  if(adapter==4&&dfd_frontend<=0) { dfd_frontend=fd_frontend; printf("dfd_frontend set to %i\n",dfd_frontend); }
   frontend = Frontend;
   subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
+//  printf("device: %d\n",device);
+//  printf("subsystemId: %08X\n",subsystemId);
+//  if(0x13C2300A==subsystemId) {
+  if(0xD4649022==subsystemId) {
+//    adap++;
+//    if(adap==2)
+     dfd_frontend=fd_frontend; printf("dfd_frontend set to %i\n",dfd_frontend);
+  }
   tuneTimeout = 0;
   lockTimeout = 0;
   lastTimeoutReport = 0;
@@ -414,7 +428,10 @@
   cDvbTransponderParameters dtp(Channel->Parameters());
   if (Setup.DiSEqC) {
      if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL))
-        return diseqc->Commands();
+          printf("returning %i\n",Channel->Source());
+        return cString::sprintf("%i",Channel->Source());
+//        return 0;
      }
   else {
      bool ToneOff = Channel->Frequency() < Setup.LnbSLOF;
@@ -765,6 +777,8 @@
 {
   if (!lnbPowerTurnedOn) {
      CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
+     if(dfd_frontend!=fd_frontend)
+       CHECK(ioctl(dfd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); // must explicitly turn on LNB power
      lnbPowerTurnedOn = true;
      }
   static cMutex Mutex;
@@ -773,6 +787,7 @@
   struct dvb_diseqc_master_cmd cmd;
   const char *CurrentAction = NULL;
   for (;;) {
+      printf("dfd_frontend: %i\nfd_frontend: %i\n",dfd_frontend,fd_frontend);
       cmd.msg_len = sizeof(cmd.msg);
       cDiseqc::eDiseqcActions da = Diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len, scr, Frequency);
       if (da == cDiseqc::daNone)
@@ -784,8 +799,8 @@
         case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
         case cDiseqc::daMiniA:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
         case cDiseqc::daMiniB:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
-        case cDiseqc::daGotoX:     HandleGotox(fd_frontend, channel.Source()); break;
-        case cDiseqc::daCodes:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
+        case cDiseqc::daGotoX:     HandleGotox(dfd_frontend, channel.Source()); break;
+        case cDiseqc::daCodes:     CHECK(ioctl(dfd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); CHECK(ioctl(dfd_frontend, FE_SET_TONE, SEC_TONE_OFF)); CHECK(ioctl(dfd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
         default: esyslog("ERROR: unknown diseqc command %d", da);
         }
       }
@@ -814,6 +829,10 @@
 {
   CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13));
   CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
+  if(dfd_frontend!=fd_frontend) {
+    CHECK(ioctl(dfd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13));
+    CHECK(ioctl(dfd_frontend, FE_SET_TONE, SEC_TONE_OFF));
+  }
 }
 
 static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTransponderParameters *Dtp)
@@ -869,13 +888,11 @@
            frequency -= diseqc->Lof();
            if (diseqc != lastDiseqc || diseqc->IsScr() || \
                  ((TestDiseqcForGotoXX(diseqc) && (channel.Source() != lastSource )))) {
-              if (IsBondedMaster()) {
+               if (IsBondedMaster() || !IsBondedMaster()) {
                  ExecuteDiseqc(diseqc, &frequency);
                  if (frequency == 0)
                     return false;
                  }
-              else
-                 ResetToneAndVoltage();
               lastDiseqc = diseqc;
               lastSource = channel.Source();
               }
@@ -900,10 +917,10 @@
            tone = SEC_TONE_ON;
            }
         int volt = (dtp.Polarization() == 'V' || dtp.Polarization() == 'R') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
-        if (!IsBondedMaster()) {
-           tone = SEC_TONE_OFF;
-           volt = SEC_VOLTAGE_13;
-           }
+//        if (!IsBondedMaster()) {
+//           tone = SEC_TONE_OFF;
+//           volt = SEC_VOLTAGE_13;
+//           }
         CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
         CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
         }


More information about the vdr mailing list