[PATCH] GOTOX patch for vdr-1.7.16

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

after some time I've improved the gotox patch for vdr - it is now
correctly resolving condition for sending diseqc command in
cDvbTuner::SetFrontend(void) even if diseqc command doesn't change also
with cascaded diseqc switches. So the diseqc is now sent immediately
after channel switch and not after frontend tuning is timeouted.

It was tested with diseqc.conf entries like this (cascaded: motor <->
uncommitted switch <-> committed switch):

S1.0W   11700 V  9750  t V G [E0 10 39 F1] v W30 [E0 10 38 FC] W30 v t
S1.0W   99999 V 10600  t V G [E0 10 39 F1] v W30 [E0 10 38 FD] W30 v T
S1.0W   11700 H  9750  t V G [E0 10 39 F1] V W30 [E0 10 38 FE] W30 V t
S1.0W   99999 H 10600  t V G [E0 10 39 F1] V W30 [E0 10 38 FF] W30 V T

S9.0E   11700 V  9750  t V G [E0 10 39 F1] v W30 [E0 10 38 FC] W30 v t
S9.0E   99999 V 10600  t V G [E0 10 39 F1] v W30 [E0 10 38 FD] W30 v T
S9.0E   11700 H  9750  t V G [E0 10 39 F1] V W30 [E0 10 38 FE] W30 V t
S9.0E   99999 H 10600  t V G [E0 10 39 F1] V W30 [E0 10 38 FF] W30 V T


BR,

Ales
diff -rup a/config.c b/config.c
--- a/config.c	2010-06-06 12:06:43.000000000 +0200
+++ b/config.c	2011-01-28 14:44:30.888676207 +0100
@@ -326,6 +326,12 @@ cSetup::cSetup(void)
   LnbFrequLo =  9750;
   LnbFrequHi = 10600;
   DiSEqC = 0;
+  UseGotox = 0;
+  GotoxSpeed = 100;
+  GotoxRepeat = 0;
+  GotoxSN = 0; GotoxLat = 613; GotoxEW = 1; GotoxLong = 236; // Somewhere at Tampere, Finland :^)
+  GotoxMaxSwing = 60; 
+  GotoxPrevSource = 0;
   SetSystemTime = 0;
   TimeSource = 0;
   TimeTransponder = 0;
@@ -517,6 +523,15 @@ bool cSetup::Parse(const char *Name, con
   else if (!strcasecmp(Name, "LnbFrequLo"))          LnbFrequLo         = atoi(Value);
   else if (!strcasecmp(Name, "LnbFrequHi"))          LnbFrequHi         = atoi(Value);
   else if (!strcasecmp(Name, "DiSEqC"))              DiSEqC             = atoi(Value);
+  else if (!strcasecmp(Name, "UseGotox"))            UseGotox           = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxSpeed"))          GotoxSpeed         = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxRepeat"))         GotoxRepeat        = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxSN"))             GotoxSN            = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxLat"))            GotoxLat           = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxEW"))             GotoxEW            = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxLong"))           GotoxLong          = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxMaxSwing"))       GotoxMaxSwing      = atoi(Value);
+  else if (!strcasecmp(Name, "GotoxPrevSource"))     GotoxPrevSource    = atoi(Value);
   else if (!strcasecmp(Name, "SetSystemTime"))       SetSystemTime      = atoi(Value);
   else if (!strcasecmp(Name, "TimeSource"))          TimeSource         = cSource::FromString(Value);
   else if (!strcasecmp(Name, "TimeTransponder"))     TimeTransponder    = atoi(Value);
@@ -613,6 +628,15 @@ bool cSetup::Save(void)
   Store("LnbFrequLo",         LnbFrequLo);
   Store("LnbFrequHi",         LnbFrequHi);
   Store("DiSEqC",             DiSEqC);
+  Store("UseGotox",           UseGotox);
+  Store("GotoxSpeed",         GotoxSpeed);
+  Store("GotoxRepeat",        GotoxRepeat);
+  Store("GotoxSN",            GotoxSN);
+  Store("GotoxLat",           GotoxLat);
+  Store("GotoxEW",            GotoxEW);
+  Store("GotoxLong",          GotoxLong);
+  Store("GotoxMaxSwing",	  GotoxMaxSwing);
+  Store("GotoxPrevSource",    GotoxPrevSource);
   Store("SetSystemTime",      SetSystemTime);
   Store("TimeSource",         cSource::ToString(TimeSource));
   Store("TimeTransponder",    TimeTransponder);
diff -rup a/config.h b/config.h
--- a/config.h	2010-09-12 13:31:21.000000000 +0200
+++ b/config.h	2011-01-28 14:45:10.882778898 +0100
@@ -229,6 +229,15 @@ public:
   int LnbFrequLo;
   int LnbFrequHi;
   int DiSEqC;
+  int GotoxRepeat;
+  int GotoxSN;
+  int GotoxEW;
+  int GotoxSpeed;
+  int GotoxLat;
+  int GotoxLong;
+  int GotoxMaxSwing;
+  int UseGotox;
+  int GotoxPrevSource;
   int SetSystemTime;
   int TimeSource;
   int TimeTransponder;
diff -rup a/diseqc.c b/diseqc.c
--- a/diseqc.c	2010-02-06 16:43:31.000000000 +0100
+++ b/diseqc.c	2011-01-28 14:46:03.418659831 +0100
@@ -134,6 +134,7 @@ cDiseqc::eDiseqcActions cDiseqc::Execute
           case 'V': return daVoltage18;
           case 'A': return daMiniA;
           case 'B': return daMiniB;
+	      case 'G': return daGotoX;
           case 'W': *CurrentAction = Wait(*CurrentAction); break;
           case '[': *CurrentAction = Codes(*CurrentAction); return *CurrentAction ? daCodes : daNone;
           default: return daNone;
diff -rup a/diseqc.h b/diseqc.h
--- a/diseqc.h	2010-02-06 16:14:42.000000000 +0100
+++ b/diseqc.h	2011-01-28 14:46:10.495659376 +0100
@@ -22,6 +22,7 @@ public:
     daVoltage18,
     daMiniA,
     daMiniB,
+    daGotoX,
     daCodes,
     };
   enum { MaxDiseqcCodes = 6 };
diff -rup a/dvbdevice.c b/dvbdevice.c
--- a/dvbdevice.c	2010-05-01 11:47:13.000000000 +0200
+++ b/dvbdevice.c	2011-01-28 14:47:30.655659479 +0100
@@ -15,9 +15,11 @@
 #include <linux/dvb/frontend.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <math.h>
 #include "channels.h"
 #include "diseqc.h"
 #include "dvbci.h"
+#include "skins.h"
 #include "menuitems.h"
 #include "sourceparams.h"
 
@@ -265,6 +267,7 @@ private:
   fe_delivery_system frontendType;
   cChannel channel;
   const char *diseqcCommands;
+  int lastSource;
   eTunerStatus tunerStatus;
   cMutex mutex;
   cCondVar locked;
@@ -292,6 +295,7 @@ cDvbTuner::cDvbTuner(int Device, int Fd_
   lockTimeout = 0;
   lastTimeoutReport = 0;
   diseqcCommands = NULL;
+  lastSource = 0;
   tunerStatus = tsIdle;
   if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2)
      CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
@@ -365,6 +369,99 @@ static unsigned int FrequencyToHz(unsign
   return f;
 }
 
+void HandleGotox(int fd_frontend, int new_source)
+{
+  
+  int gotoXTable[10] = { 0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E };
+  int satlong;
+  int satprev;
+  float waitseconds = 0;
+  float waitmaximum = 60;
+
+  if (Setup.UseGotox == 0)
+    return;
+
+  // Check if zapped into new source position?
+  if (new_source != Setup.GotoxPrevSource) {
+    if ((new_source & 0xFF000000) != 0x53000000) 
+      return; // Fail, not S type source
+    satlong = (new_source & 0x00000FFFF);
+    satprev = (Setup.GotoxPrevSource & 0x0000FFFF);
+    if (new_source & 0x00008000) {
+      satlong ^= 0x0000FFFF; satlong++; satlong *= (-1);
+    }
+    if (Setup.GotoxPrevSource & 0x00008000) {
+      satprev ^= 0x0000FFFF; satprev++; satprev *= (-1);
+    }
+    if (Setup.GotoxSpeed > 0) {
+      waitseconds = fabs(satlong-satprev)/(float)(Setup.GotoxSpeed);
+      waitmaximum = 10*(float)(Setup.GotoxMaxSwing)/(float)(Setup.GotoxSpeed);
+      if (waitseconds < 0.0) waitseconds = 0.0; // Should not happen but ...
+      if (waitseconds > waitmaximum) waitseconds = 2 + waitmaximum; // Limit wait time to +2s over dish max. move
+    }
+    int Long=Setup.GotoxEW ? -Setup.GotoxLong : Setup.GotoxLong;
+    int Lat=Setup.GotoxSN ? -Setup.GotoxLat : Setup.GotoxLat;
+    double azimuth=M_PI+atan(tan((satlong-Long)*M_PI/1800)/sin(Lat*M_PI/1800));
+    double x=acos(cos((satlong-Long)*M_PI/1800)*cos(Lat*M_PI/1800));
+    double elevation=atan((cos(x)-0.1513)/sin(x));
+    double SatHourangle=180+atan((-cos(elevation)*sin(azimuth))/(sin(elevation)*cos(Lat*M_PI/1800)
+			   -cos(elevation)*sin(Lat*M_PI/1800)*cos(azimuth)))*180/M_PI;
+    int tmp=(int)(fabs(180-SatHourangle)*10);
+    tmp=(tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
+    int p2=(tmp%0x0100);
+    int p1=(tmp/0x0100);
+    if (SatHourangle < 180)
+      p1 |= 0xe0;
+    else
+      p1 |= 0xd0;
+
+    dsyslog("DiSEqC GotoX %d (%d) -> %d (%d), wait time %4.1fs",
+	    satprev, Setup.GotoxPrevSource, satlong, new_source, waitseconds);
+
+#if 1
+    // Set high LNB voltage and tone off, then wait > 15ms
+    CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18));
+    CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
+    usleep(20000);
+    
+    // Send 1st GotoX command, then wait > 15ms
+    uchar gotox_bytes[5] = { 0xe0, 0x31, 0x6e, p1, p2};
+    struct dvb_diseqc_master_cmd gotox_cmd;
+    memcpy(gotox_cmd.msg, gotox_bytes, 5);
+    gotox_cmd.msg_len = 5;
+    CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &gotox_cmd));
+    usleep(20000);
+
+    // Send repeated GotoX command, then wait > 15ms
+    if (Setup.GotoxRepeat) {
+      gotox_bytes[0] = 0xe1;
+      memcpy(gotox_cmd.msg, gotox_bytes, 5);
+      CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &gotox_cmd));
+      usleep(20000);
+    }
+    
+ 	 {
+ 	   char mess_move[60];
+        snprintf(mess_move,sizeof(mess_move),"Moving dish to %d.%d%s - %ds", \
+       	(new_source & 0x0800)?-satlong/10:satlong/10, \
+       	(new_source & 0x0800)?-satlong%10:satlong%10, \
+       	(new_source & 0x0800)?"E":"W", (int)waitseconds);
+      // Wait for dish movement and display message approx. for that time
+      Skins.QueueMessage(mtWarning, mess_move, int(1 + waitseconds - Setup.ChannelInfoTime), 0);
+      while (waitseconds > 0.0) {
+        usleep(100000); // 100ms
+        waitseconds = waitseconds - 100e-3;
+      }
+    }
+
+#endif
+
+    Setup.GotoxPrevSource = new_source;
+    dsyslog("DiSEqC GotoX done.");
+  }
+}
+
+
 bool cDvbTuner::SetFrontend(void)
 {
 #define MAXFRONTENDCMDS 16
@@ -394,7 +491,9 @@ bool cDvbTuner::SetFrontend(void)
      if (Setup.DiSEqC) {
         cDiseqc *diseqc = Diseqcs.Get(device, channel.Source(), channel.Frequency(), dtp.Polarization());
         if (diseqc) {
-           if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
+           if (diseqc->Commands() && (!diseqcCommands || \
+           		 (strcmp(diseqcCommands, diseqc->Commands())) || \
+           		  (strrchr(diseqc->Commands(),'G') && (channel.Source() != lastSource )))) {
               cDiseqc::eDiseqcActions da;
               for (char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
                   switch (da) {
@@ -405,6 +504,7 @@ bool cDvbTuner::SetFrontend(void)
                     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: {
                          int n = 0;
                          uchar *codes = diseqc->Codes(n);
@@ -420,6 +520,7 @@ bool cDvbTuner::SetFrontend(void)
                     }
                   }
               diseqcCommands = diseqc->Commands();
+              lastSource = channel.Source();
               }
            frequency -= diseqc->Lof();
            }
@@ -429,6 +530,10 @@ bool cDvbTuner::SetFrontend(void)
            }
         }
      else {
+         // Send GotoX DiSEqC command if activated in vdr setup. Then wait with high LNB voltage
+         // estimated time for dish movement
+        HandleGotox(fd_frontend, channel.Source()); 
+
         int tone = SEC_TONE_OFF;
         if (frequency < (unsigned int)Setup.LnbSLOF) {
            frequency -= Setup.LnbFrequLo;
@@ -541,6 +646,7 @@ void cDvbTuner::Action(void)
                if (Timer.TimedOut()) {
                   tunerStatus = tsSet;
                   diseqcCommands = NULL;
+                  lastSource = 0;
                   if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these
                      isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder());
                      lastTimeoutReport = time(NULL);
@@ -551,6 +657,7 @@ void cDvbTuner::Action(void)
                if (Status & FE_REINIT) {
                   tunerStatus = tsSet;
                   diseqcCommands = NULL;
+                  lastSource = 0;
                   isyslog("frontend %d/%d was reinitialized", adapter, frontend);
                   lastTimeoutReport = 0;
                   continue;
diff -rup a/menu.c b/menu.c
--- a/menu.c	2010-06-06 11:56:16.000000000 +0200
+++ b/menu.c	2011-01-28 14:50:08.625533824 +0100
@@ -2890,8 +2890,15 @@ void cMenuSetupLNB::Setup(void)
      Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"),               &data.LnbSLOF));
      Add(new cMenuEditIntItem( tr("Setup.LNB$Low LNB frequency (MHz)"),  &data.LnbFrequLo));
      Add(new cMenuEditIntItem( tr("Setup.LNB$High LNB frequency (MHz)"), &data.LnbFrequHi));
-     }
-
+  }
+  Add(new cMenuEditBoolItem(tr("Setup.LNB$Use GotoX dish positioning"), &data.UseGotox));
+  if (data.UseGotox) {
+     Add(new cMenuEditBoolItem(tr("Setup.LNB$Repeat GotoX commands"), &data.GotoxRepeat));
+     Add(new cMenuEditIntpItem(tr("Setup.LNB$Latitude"), &data.GotoxLat,0,900,&data.GotoxSN,tr("North"),tr("South")));
+     Add(new cMenuEditIntpItem(tr("Setup.LNB$Longitude"), &data.GotoxLong,0,1800,&data.GotoxEW,tr("West"),tr("East")));
+     Add(new cMenuEditIntItem(tr("Setup.LNB$GotoxMaxSwing"), &data.GotoxMaxSwing,0,180));
+     Add(new cMenuEditIntdItem(tr("Setup.LNB$Rotor speed (deg/s)"), &data.GotoxSpeed, 1, 100));
+  }
   SetCurrent(Get(current));
   Display();
 }
@@ -2899,10 +2906,15 @@ void cMenuSetupLNB::Setup(void)
 eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
 {
   int oldDiSEqC = data.DiSEqC;
+  int oldUseGotox = data.UseGotox;
   eOSState state = cMenuSetupBase::ProcessKey(Key);
 
   if (Key != kNone && data.DiSEqC != oldDiSEqC)
      Setup();
+
+  if (Key != kNone && data.UseGotox != oldUseGotox)
+     Setup();
+
   return state;
 }
 
diff -rup a/menuitems.c b/menuitems.c
--- a/menuitems.c	2010-06-06 12:37:08.000000000 +0200
+++ b/menuitems.c	2011-01-28 14:50:21.357534700 +0100
@@ -1113,3 +1113,121 @@ void cMenuSetupPage::SetupStore(const ch
   if (plugin)
      plugin->SetupStore(Name, Value);
 }
+
+// cMenuEditIntpItem & cMenuEditIntdItem for GotoX function
+
+void cMenuEditIntpItem::Set(void)
+{
+  char buf[16];
+  snprintf(buf, sizeof(buf), "%d.%d %s", *value/10, *value % 10, *value2 ? trueString : falseString);
+  SetValue(buf);
+}
+
+void cMenuEditIntdItem::Set(void)
+{
+  char buf[16];
+  snprintf(buf, sizeof(buf), "%d.%d", *value/10, *value % 10);
+  SetValue(buf);
+}
+
+
+cMenuEditIntpItem::cMenuEditIntpItem(const char *Name, int *Value, int Min, int Max,int *Value2, const char *FalseString,const char *TrueString):cMenuEditIntItem(Name, Value, Min, Max)
+{
+  value = Value;
+  value2= Value2;
+  trueString = TrueString;
+  falseString = FalseString;
+  min = Min;
+  max = Max;
+  Set();
+}
+
+cMenuEditIntdItem::cMenuEditIntdItem(const char *Name, int *Value, int Min, int Max):cMenuEditIntItem(Name, Value, Min, Max)
+{
+  value = Value;
+  min = Min;
+  max = Max;
+  Set();
+}
+
+eOSState cMenuEditIntpItem::ProcessKey(eKeys Key)
+{
+  eOSState state = cMenuEditItem::ProcessKey(Key);
+  if (state == osUnknown)
+  {
+    int newValue = *value;
+    int newValue2= *value2;
+    Key = NORMALKEY(Key);
+    switch (Key) {
+      case kNone  : break;
+      case k0...k9:
+                    if (fresh)
+                    {
+                      *value = 0;
+                      fresh = false;
+                    }
+                    newValue = *value * 10 + (Key - k0);
+                    break;
+      case kLeft  :
+                    newValue2 = 0;
+                    fresh = true;
+                    break;
+      case kRight :
+                    newValue2 = 1;
+                    fresh = true;
+                    break;
+      default     :
+                    if (*value < min) { *value = min; Set(); }
+                    if (*value > max) { *value = max; Set(); }
+                    return state;
+                 }
+    if ((!fresh || min <= newValue) && newValue <= max)
+    {
+      *value = newValue;
+      *value2 = newValue2;
+      Set();
+    }
+ state = osContinue;
+  }
+  return state;
+}
+
+eOSState cMenuEditIntdItem::ProcessKey(eKeys Key)
+{
+  eOSState state = cMenuEditItem::ProcessKey(Key);
+  if (state == osUnknown)
+  {
+    int newValue = *value;
+    Key = NORMALKEY(Key);
+    switch (Key) {
+      case kNone  : break;
+      case k0...k9:
+                    if (fresh)
+                    {
+                      *value = 0;
+                      fresh = false;
+                    }
+                    newValue = *value * 10 + (Key - k0);
+                    break;
+      case kLeft  :
+	            newValue = *value - 1;
+                    fresh = true;
+                    break;
+      case kRight :
+                    newValue = *value + 1;
+                    fresh = true;
+                    break;
+      default     :
+                    if (*value < min) { *value = min; Set(); }
+                    if (*value > max) { *value = max; Set(); }
+                    return state;
+                 }
+    if ((!fresh || min <= newValue) && newValue <= max)
+    {
+      *value = newValue;
+      Set();
+    }
+    state = osContinue;
+  }
+  return state;
+}
diff -rup a/menuitems.h b/menuitems.h
--- a/menuitems.h	2010-06-06 12:32:38.000000000 +0200
+++ b/menuitems.h	2011-01-28 14:50:36.217533731 +0100
@@ -201,4 +201,22 @@ public:
   void SetPlugin(cPlugin *Plugin);
   };
 
+class cMenuEditIntpItem : public cMenuEditIntItem {
+protected:
+  virtual void Set(void);
+  const char *falseString, *trueString;
+  int *value2;
+public:
+  cMenuEditIntpItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX, int *Value2=0, const char *FalseString = "", const char *TrueSting = NULL);
+  virtual eOSState ProcessKey(eKeys Key);
+};
+
+class cMenuEditIntdItem : public cMenuEditIntItem {
+protected:
+  virtual void Set(void);
+public:
+  cMenuEditIntdItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
+  virtual eOSState ProcessKey(eKeys Key);
+};
+
 #endif //__MENUITEMS_H
_______________________________________________
vdr mailing list
vdr@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux