RFC: one or many positioners?

Message ID 20130422113831.GA15421@ankka.com
State New
Headers

Commit Message

Antti Hartikainen April 22, 2013, 11:38 a.m. UTC
  On Mon, Apr 22, 2013 at 11:46:34AM +0300, Teemu Suikki wrote:
> 2013/4/21 Klaus Schmidinger <Klaus.Schmidinger@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.
{
   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));
         }
  

Comments

Klaus Schmidinger April 22, 2013, 12:33 p.m. UTC | #1
On 22.04.2013 13:38, Antti Hartikainen wrote:
> ...
> I think I would be interested to have possibility for multiple positioners later, if VDR would only support it.

There doesn't seem to be such a big demand for multiple positioners,
so I guess I'll take the easy way and assume there is only one.

> 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

I'll see what I can do to make it work with several devices connected to
the same movable dish.

Klaus
  
VDRU VDRU April 22, 2013, 2:55 p.m. UTC | #2
On Mon, Apr 22, 2013 at 5:33 AM, Klaus Schmidinger
<Klaus.Schmidinger@tvdr.de> wrote:
>> I think I would be interested to have possibility for multiple positioners
>> later, if VDR would only support it.
>
> There doesn't seem to be such a big demand for multiple positioners,
> so I guess I'll take the easy way and assume there is only one.

For the sake of future-proofing, maybe the motor stuff can be added in
such a way that it wouldn't take a total rewrite to support
multi-motor setups in the event it's decided later on such support
would be advantageous. Since motor support is finally arriving, we
don't want to undershoot (although single motor setups certainly seem
like the easy majority).

Another consideration is what setups will look like once VDR advances
into server/client design. Will those setups be more likely to have
multiple motors? I dunno, but it's worth asking imo.
  

Patch

--- 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 @@