From patchwork Sat Mar 6 10:23:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Jurik X-Patchwork-Id: 12790 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.69) (envelope-from ) id 1NnrAm-0003ML-TZ for vdr@linuxtv.org; Sat, 06 Mar 2010 11:23:55 +0100 X-tubIT-Incoming-IP: 194.228.2.86 Received: from smtp-out1.iol.cz ([194.228.2.86]) by mail.tu-berlin.de (exim-4.69/mailfrontend-b) with esmtp for id 1NnrAl-0003AQ-QY; Sat, 06 Mar 2010 11:23:52 +0100 Received: from antivir3.iol.cz (antivir3.iplanet.iol.cz [192.168.30.206]) by smtp-out1.iol.cz (Postfix) with ESMTP id C43CC38E647; Sat, 6 Mar 2010 11:23:50 +0100 (CET) Received: from localhost (antivir3.iol.cz [127.0.0.1]) by antivir3.iol.cz (Postfix) with ESMTP id B51C4FAC032; Sat, 6 Mar 2010 11:23:50 +0100 (CET) X-Virus-Scanned: amavisd-new at iol.cz Received: from antivir3.iol.cz ([127.0.0.1]) by localhost (antivir3.iol.cz [127.0.0.1]) (amavisd-new, port 10124) with LMTP id 9ARpx6kanuLs; Sat, 6 Mar 2010 11:23:50 +0100 (CET) Received: from port3.iol.cz (unknown [192.168.30.93]) by antivir3.iol.cz (Postfix) with ESMTP id 92A6EFAC031; Sat, 6 Mar 2010 11:23:50 +0100 (CET) X-SBRS: None X-SBRS-none: None X-RECVLIST: MTA-OUT-QUICK X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ArUgANO7kUtYZ3gv/2dsb2JhbACDC4EClz5zpQ6PeYQOagQ Received: from unknown (HELO ales-lin.localnet) ([88.103.120.47]) by port3.iol.cz with ESMTP; 06 Mar 2010 11:23:50 +0100 From: Ales Jurik To: vdr@linuxtv.org Date: Sat, 6 Mar 2010 11:23:50 +0100 User-Agent: KMail/1.12.4 (Linux/2.6.30-1-amd64; KDE/4.3.4; x86_64; ; ) MIME-Version: 1.0 Message-Id: <201003061123.50137.ajurik@quick.cz> X-tubIT-Score: 0.0 () X-PMX-Version: 5.5.4.371499, Antispam-Engine: 2.7.1.369594, Antispam-Data: 2010.3.6.100923 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' MIME_TEXT_ONLY_MP_MIXED 0.05, BODY_SIZE_10000_PLUS 0, TO_NO_NAME 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __CTYPE_MULTIPART_MIXED 0, __HAS_MSGID 0, __MIME_TEXT_ONLY 0, __MIME_VERSION 0, __SANE_MSGID 0, __TO_MALFORMED_2 0, __USER_AGENT 0' X-LSpam-Score: -3.0 (---) X-LSpam-Report: No, score=-3.0 required=5.0 tests=AWL=0.571, BAYES_00=-2.599, RCVD_IN_DNSWL_LOW=-1 autolearn=ham Subject: [vdr] [PATCH] GOTOX patch for vdr-1.7.13 X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.11 Precedence: list Reply-To: ajurik@quick.cz, VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 06 Mar 2010 10:23:55 -0000 Status: O X-Status: X-Keywords: X-UID: 22514 Hi, here you can find new version of gotox patch for vdr-1.7.13. I've added new menuentry - GotoxMaxSwing - max possible angle of rotor move. This set automatically maximum wait time for rotor move (tohether with rotor speed) instead of 60s as it was in previous versions. BR, Ales diff -rupN a//config.c b//config.c --- a//config.c 2010-01-31 13:36:36.000000000 +0100 +++ b//config.c 2010-03-06 11:16:11.000000000 +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; @@ -514,6 +520,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); @@ -607,6 +622,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 -rupN a//config.h b//config.h --- a//config.h 2010-02-05 16:38:32.000000000 +0100 +++ b//config.h 2010-03-06 11:16:11.000000000 +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 -rupN a//diseqc.c b//diseqc.c --- a//diseqc.c 2010-02-06 16:43:31.000000000 +0100 +++ b//diseqc.c 2010-03-06 11:16:11.000000000 +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 -rupN a//diseqc.h b//diseqc.h --- a//diseqc.h 2010-02-06 16:14:42.000000000 +0100 +++ b//diseqc.h 2010-03-06 11:11:23.296532650 +0100 @@ -22,6 +22,7 @@ public: daVoltage18, daMiniA, daMiniB, + daGotoX, daCodes, }; enum { MaxDiseqcCodes = 6 }; diff -rupN a//dvbdevice.c b//dvbdevice.c --- a//dvbdevice.c 2010-02-21 18:10:35.000000000 +0100 +++ b//dvbdevice.c 2010-03-06 11:16:11.000000000 +0100 @@ -15,9 +15,11 @@ #include #include #include +#include #include "channels.h" #include "diseqc.h" #include "dvbci.h" +#include "skins.h" #include "menuitems.h" #include "sourceparams.h" @@ -353,6 +355,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 @@ -393,6 +488,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); @@ -417,6 +513,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; diff -rupN a//menu.c b//menu.c --- a//menu.c 2010-02-21 15:09:19.000000000 +0100 +++ b//menu.c 2010-03-06 11:16:11.000000000 +0100 @@ -2880,8 +2880,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(); } @@ -2889,10 +2896,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 -rupN a//menuitems.c b//menuitems.c --- a//menuitems.c 2010-02-16 15:44:35.000000000 +0100 +++ b//menuitems.c 2010-03-06 11:11:23.305021194 +0100 @@ -1106,3 +1106,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 -rupN a//menuitems.h b//menuitems.h --- a//menuitems.h 2010-02-21 14:58:21.000000000 +0100 +++ b//menuitems.h 2010-03-06 11:11:23.305021194 +0100 @@ -200,4 +200,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