work on linked tuners ( can not test it :( )
[enigma2.git] / lib / dvb / sec.cpp
1 #include <config.h>
2 #include <lib/dvb/dvb.h>
3 #include <lib/dvb/sec.h>
4 #include <lib/dvb/rotor_calc.h>
5
6 #if HAVE_DVB_API_VERSION < 3
7 #define INVERSION Inversion
8 #define FREQUENCY Frequency
9 #define FEC_INNER FEC_inner
10 #define SYMBOLRATE SymbolRate
11 #else
12 #define INVERSION inversion
13 #define FREQUENCY frequency
14 #define FEC_INNER fec_inner
15 #define SYMBOLRATE symbol_rate
16 #endif
17 #include <lib/base/eerror.h>
18
19 DEFINE_REF(eDVBSatelliteEquipmentControl);
20
21 eDVBSatelliteEquipmentControl *eDVBSatelliteEquipmentControl::instance;
22
23 eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBRegisteredFrontend> &avail_frontends)
24         :m_lnbidx(-1), m_curSat(m_lnbs[0].m_satellites.end()), m_avail_frontends(avail_frontends)
25 {
26         if (!instance)
27                 instance = this;
28
29         clear();
30
31 // ASTRA
32         addLNB();
33         setLNBTunerMask(3);
34         setLNBLOFL(9750000);
35         setLNBThreshold(11750000);
36         setLNBLOFH(10607000);
37         setDiSEqCMode(eDVBSatelliteDiseqcParameters::V1_0);
38         setToneburst(eDVBSatelliteDiseqcParameters::NO);
39         setRepeats(0);
40         setCommittedCommand(eDVBSatelliteDiseqcParameters::BB);
41         setCommandOrder(0); // committed, toneburst
42         setFastDiSEqC(true);
43         setSeqRepeat(false);
44         addSatellite(192);
45         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
46         setToneMode(eDVBSatelliteSwitchParameters::HILO);
47
48 // HOTBIRD
49         addLNB();
50         setLNBTunerMask(3);
51         setLNBLOFL(9750000);
52         setLNBLOFH(10600000);
53         setLNBThreshold(11750000);
54         setDiSEqCMode(eDVBSatelliteDiseqcParameters::V1_0);
55         setToneburst(eDVBSatelliteDiseqcParameters::NO);
56         setRepeats(0);
57         setCommittedCommand(eDVBSatelliteDiseqcParameters::AB);
58         setCommandOrder(0); // committed, toneburst
59         setFastDiSEqC(true);
60         setSeqRepeat(false);
61         addSatellite(130);
62         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
63         setToneMode(eDVBSatelliteSwitchParameters::HILO);
64 }
65
66 int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite &sat, iDVBFrontend *fe, int frontend_id )
67 {
68         int ret=0;
69
70         for (int idx=0; idx <= m_lnbidx; ++idx )
71         {
72                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
73                 if ( lnb_param.tuner_mask & frontend_id ) // lnb for correct tuner?
74                 {
75                         eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
76
77                         std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
78                                 lnb_param.m_satellites.find(sat.orbital_position);
79                         if ( sit != lnb_param.m_satellites.end())
80                         {
81                                 int band=0,
82                                         linked_to=0, // linked tuner
83                                         csw = di_param.m_committed_cmd,
84                                         ucsw = di_param.m_uncommitted_cmd,
85                                         toneburst = di_param.m_toneburst_param,
86                                         curRotorPos;
87
88                                 fe->getData(6, curRotorPos);
89                                 fe->getData(7, linked_to);
90
91                                 if ( sat.frequency > lnb_param.m_lof_threshold )
92                                         band |= 1;
93                                 if (sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Horizontal)
94                                         band |= 2;
95
96                                 if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
97                                 {
98                                         if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
99                                         {
100                                                 csw = 0xF0 | (csw << 2);
101                                                 csw |= band;
102                                         }
103
104                                         if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )  // ROTOR
105                                         {
106                                                 if ( curRotorPos == sat.orbital_position )
107                                                         ret=20;
108                                                 else
109                                                         ret=10;
110                                         }
111                                 }
112                                 
113                                 if (!ret)
114                                         ret=40;
115
116                                 if (linked_to != -1)  // check for linked tuners..
117                                 {
118                                         bool found=false;
119                                         eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
120                                         for (; it != m_avail_frontends.end(); ++it)
121                                                 if ( !linked_to )
122                                                 {
123                                                         found=true;
124                                                         break;
125                                                 }
126                                                 else
127                                                         --linked_to;
128
129                                         if (found && it->m_inuse)
130                                         {
131                                                 int lastcsw = -1,
132                                                         lastucsw = -1,
133                                                         lastToneburst = -1,
134                                                         curRotorPos = -1;
135                                                 it->m_frontend->getData(0, lastcsw);
136                                                 it->m_frontend->getData(1, lastucsw);
137                                                 it->m_frontend->getData(2, lastToneburst);
138                                                 it->m_frontend->getData(6, curRotorPos);
139
140                                                 if (csw != lastcsw || ucsw != lastucsw ||
141                                                         toneburst != lastToneburst || curRotorPos != sat.orbital_position )
142                                                 {
143                                                         eDebug("can not tune this transponder with linked tuner in use!!");
144                                                         ret=0;
145                                                 }
146                                                 else
147                                                         eDebug("OK .. can tune this transponder with linked tuner in use :)");
148                                         }
149                                 }
150                         }
151                 }
152         }
153         return ret;
154 }
155
156 RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPARAMETERS &parm, eDVBFrontendParametersSatellite &sat, int frontend_id)
157 {
158         bool linked=false;
159
160         for (int idx=0; idx <= m_lnbidx; ++idx )
161         {
162                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
163                 if (!(lnb_param.tuner_mask & frontend_id)) // lnb for correct tuner?
164                         continue;
165                 eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
166                 eDVBSatelliteRotorParameters &rotor_param = lnb_param.m_rotor_parameters;
167
168                 std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
169                         lnb_param.m_satellites.find(sat.orbital_position);
170                 if ( sit != lnb_param.m_satellites.end())
171                 {
172                         eDVBSatelliteSwitchParameters &sw_param = sit->second;
173
174                         int band=0,
175                                 linked_to=-1, // linked tuner
176                                 voltage = iDVBFrontend::voltageOff,
177                                 tone = iDVBFrontend::toneOff,
178                                 csw = di_param.m_committed_cmd,
179                                 ucsw = di_param.m_uncommitted_cmd,
180                                 toneburst = di_param.m_toneburst_param,
181                                 lastcsw = -1,
182                                 lastucsw = -1,
183                                 lastToneburst = -1,
184                                 lastRotorCmd = -1,
185                                 curRotorPos = -1;
186
187                         frontend.getData(0, lastcsw);
188                         frontend.getData(1, lastucsw);
189                         frontend.getData(2, lastToneburst);
190                         frontend.getData(5, lastRotorCmd);
191                         frontend.getData(6, curRotorPos);
192                         frontend.getData(7, linked_to);
193
194                         if (linked_to != -1)
195                         {
196                                 bool found=false;
197                                 eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
198                                 for (; it != m_avail_frontends.end(); ++it)
199                                         if ( !linked_to )
200                                         {
201                                                 found=true;
202                                                 break;
203                                         }
204                                         else
205                                                 --linked_to;
206                                 if (found && it->m_inuse)
207                                 {
208                                         eDebug("[SEC] frontend is linked with another one and the other is in use.. so we dont do SEC!!");
209                                         linked=true;
210                                         continue;
211                                 }
212                         }
213
214                         if ( sat.frequency > lnb_param.m_lof_threshold )
215                                 band |= 1;
216
217                         if (band&1)
218                                 parm.FREQUENCY = sat.frequency - lnb_param.m_lof_hi;
219                         else
220                                 parm.FREQUENCY = sat.frequency - lnb_param.m_lof_lo;
221
222                         if (sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Horizontal)
223                                 band |= 2;
224
225                         parm.INVERSION = (!sat.inversion) ? INVERSION_ON : INVERSION_OFF;
226
227                         switch (sat.fec)
228                         {
229                                 default:
230                                 case eDVBFrontendParametersSatellite::FEC::fNone:
231                                         eDebug("no fec set.. assume auto");
232                                 case eDVBFrontendParametersSatellite::FEC::fAuto:
233                                         parm.u.qpsk.FEC_INNER = FEC_AUTO;
234                                         break;
235                                 case eDVBFrontendParametersSatellite::FEC::f1_2:
236                                         parm.u.qpsk.FEC_INNER = FEC_1_2;
237                                         break;
238                                 case eDVBFrontendParametersSatellite::FEC::f2_3:
239                                         parm.u.qpsk.FEC_INNER = FEC_2_3;
240                                         break;
241                                 case eDVBFrontendParametersSatellite::FEC::f3_4:
242                                         parm.u.qpsk.FEC_INNER = FEC_3_4;
243                                         break;
244                                 case eDVBFrontendParametersSatellite::FEC::f5_6:
245                                         parm.u.qpsk.FEC_INNER = FEC_5_6;
246                                         break;
247                                 case eDVBFrontendParametersSatellite::FEC::f7_8: 
248                                         parm.u.qpsk.FEC_INNER = FEC_7_8;
249                                         break;
250                         }
251
252                         parm.u.qpsk.SYMBOLRATE = sat.symbol_rate;
253
254                         if ( sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::_14V
255                                 || ( sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Vertical
256                                         && sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
257                                 voltage = iDVBFrontend::voltage13;
258                         else if ( sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::_18V
259                                 || ( sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Horizontal
260                                         && sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
261                                 voltage = iDVBFrontend::voltage18;
262
263                         if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::ON)
264                                 || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && (band&1) ) )
265                                 tone = iDVBFrontend::toneOn;
266                         else if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::OFF)
267                                 || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && !(band&1) ) )
268                                 tone = iDVBFrontend::toneOff;
269
270                         eSecCommandList sec_sequence;
271
272                         if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
273                         {
274                                 if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
275                                 {
276                                         csw = 0xF0 | (csw << 2);
277                                         csw |= band;
278                                 }
279
280                                 bool send_csw =
281                                         (di_param.m_committed_cmd != eDVBSatelliteDiseqcParameters::SENDNO);
282                                 bool changed_csw = send_csw && csw != lastcsw;
283
284                                 bool send_ucsw =
285                                         (di_param.m_uncommitted_cmd && di_param.m_diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0);
286                                 bool changed_ucsw = send_ucsw && ucsw != lastucsw;
287
288                                 bool send_burst =
289                                         (di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO);
290                                 bool changed_burst = send_burst && toneburst != lastToneburst;
291
292                                 bool send_diseqc = changed_ucsw;
293                                 if (!send_diseqc)
294                                         send_diseqc = changed_burst && (send_ucsw || send_csw);
295                                 if (!send_diseqc)
296                                 {
297                                         send_diseqc = changed_csw;
298                                         if ( send_diseqc && di_param.m_use_fast && (csw & 0xF0) && (lastcsw & 0xF0) && ((csw / 4) == (lastcsw / 4)) )
299                                                 send_diseqc = false;
300                                 }
301
302                                 if ( send_diseqc || changed_burst )
303                                 {
304                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
305                                         eSecCommand::pair compare;
306                                         compare.voltage = voltage;
307                                         compare.steps = +3;
308                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
309                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
310                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
311                                 }
312
313                                 for (int seq_repeat = 0; seq_repeat < (di_param.m_seq_repeat?2:1); ++seq_repeat)
314                                 {
315                                         if ( di_param.m_command_order & 1 && // toneburst at begin of sequence
316                                                 changed_burst && di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO )
317                                         {
318                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
319                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
320                                                 frontend.setData(2, di_param.m_toneburst_param);
321                                         }
322
323                                         if ( send_diseqc )
324                                         {
325                                                 int loops=0;
326
327                                                 if ( send_csw )
328                                                         ++loops;
329                                                 if ( send_ucsw )
330                                                         ++loops;
331
332                                                 for ( int i=0; i < di_param.m_repeats; ++i )
333                                                         loops *= 2;
334
335                                                 for ( int i = 0; i < loops;)  // fill commands...
336                                                 {
337                                                         eDVBDiseqcCommand diseqc;
338                                                         diseqc.len = 4;
339                                                         diseqc.data[0] = i ? 0xE1 : 0xE0;
340                                                         diseqc.data[1] = 0x10;
341
342                                                         if ( !send_csw || (send_ucsw && (di_param.m_command_order & 4) ) )
343                                                         {
344                                                                 diseqc.data[2] = 0x39;
345                                                                 diseqc.data[3] = ucsw;
346                                                         }
347                                                         else
348                                                         {
349                                                                 diseqc.data[2] = 0x38;
350                                                                 diseqc.data[3] = csw;
351                                                         }
352                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
353
354                                                         i++;
355                                                         if ( i < loops )
356                                                         {
357                                                                 int cmd=0;
358                                                                 if (diseqc.data[2] == 0x38 && send_ucsw)
359                                                                         cmd=0x39;
360                                                                 else if (diseqc.data[2] == 0x39 && send_csw)
361                                                                         cmd=0x38;
362                                                                 if (cmd)
363                                                                 {
364                                                                         static int delay = (120 - 54) / 2;  // standard says 100msek between two repeated commands
365                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay) );
366                                                                         diseqc.data[2]=cmd;
367                                                                         diseqc.data[3]=(cmd==0x38) ? csw : ucsw;
368                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
369                                                                         ++i;
370                                                                         if ( i < loops )
371                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay ) );
372                                                                         else
373                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
374                                                                 }
375                                                                 else  // delay 120msek when no command is in repeat gap
376                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 120) );
377                                                         }
378                                                         else
379                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
380
381                                                         frontend.setData(0, csw);
382                                                         frontend.setData(1, ucsw);
383                                                 }
384                                         }
385
386                                         if ( !(di_param.m_command_order & 1) && // toneburst at end of sequence
387                                                 (changed_burst || send_diseqc) && di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO )
388                                         {
389                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
390                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
391                                                 frontend.setData(2, di_param.m_toneburst_param);
392                                         }
393                                 }
394
395                                 if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )
396                                 {
397                                         int RotorCmd=0;
398                                         bool useGotoXX = false;
399
400                                         if (sw_param.m_rotorPosNum) // we have stored rotor pos?
401                                                 RotorCmd=sw_param.m_rotorPosNum;
402                                         else  // we must calc gotoxx cmd
403                                         {
404                                                 eDebug("Entry for %d,%d° not in Rotor Table found... i try gotoXX°", sat.orbital_position / 10, sat.orbital_position % 10 );
405                                                 useGotoXX = true;
406
407                                                 int satDir = sat.orbital_position < 0 ?
408                                                         eDVBSatelliteRotorParameters::WEST :
409                                                         eDVBSatelliteRotorParameters::EAST;
410
411                                                 double  SatLon = abs(sat.orbital_position)/10.00,
412                                                                 SiteLat = rotor_param.m_gotoxx_parameters.m_latitude,
413                                                                 SiteLon = rotor_param.m_gotoxx_parameters.m_longitude;
414
415                                                 if ( rotor_param.m_gotoxx_parameters.m_la_direction == eDVBSatelliteRotorParameters::SOUTH )
416                                                         SiteLat = -SiteLat;
417
418                                                 if ( rotor_param.m_gotoxx_parameters.m_lo_direction == eDVBSatelliteRotorParameters::WEST )
419                                                         SiteLon = 360 - SiteLon;
420
421                                                 if (satDir == eDVBSatelliteRotorParameters::WEST )
422                                                         SatLon = 360 - SatLon;
423
424                                                 eDebug("siteLatitude = %lf, siteLongitude = %lf, %lf degrees", SiteLat, SiteLon, SatLon );
425                                                 double satHourAngle =
426                                                         calcSatHourangle( SatLon, SiteLat, SiteLon );
427                                                 eDebug("PolarmountHourAngle=%lf", satHourAngle );
428
429                                                 static int gotoXTable[10] =
430                                                         { 0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E };
431
432                                                 if (SiteLat >= 0) // Northern Hemisphere
433                                                 {
434                                                         int tmp=(int)round( fabs( 180 - satHourAngle ) * 10.0 );
435                                                         RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
436
437                                                         if (satHourAngle < 180) // the east
438                                                                 RotorCmd |= 0xE000;
439                                                         else                                    // west
440                                                                 RotorCmd |= 0xD000;
441                                                 }
442                                                 else // Southern Hemisphere
443                                                 {
444                                                         if (satHourAngle < 180) // the east
445                                                         {
446                                                                 int tmp=(int)round( fabs( satHourAngle ) * 10.0 );
447                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
448                                                                 RotorCmd |= 0xD000;
449                                                         }
450                                                         else                                    // west
451                                                         {          
452                                                                 int tmp=(int)round( fabs( 360 - satHourAngle ) * 10.0 );
453                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
454                                                                 RotorCmd |= 0xE000;
455                                                         }
456                                                 }
457                                                 eDebug("RotorCmd = %04x", RotorCmd);
458                                         }
459                                         if ( RotorCmd != lastRotorCmd )
460                                         {
461                                                 if ( changed_burst || send_diseqc )
462                                                 {
463                                                         // override first voltage change
464                                                         *(++(++sec_sequence.begin()))=eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13);
465                                                         // wait 1 second after first switch diseqc command
466                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 1000) );
467                                                 }
468                                                 else  // no other diseqc commands before
469                                                 {
470                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
471                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 15) );  // wait 15msec after tone change
472                                                         eSecCommand::pair compare;
473                                                         compare.voltage = voltage;
474                                                         compare.steps = +3;
475                                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
476                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
477                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec after voltage change
478                                                 }
479
480                                                 eDVBDiseqcCommand diseqc;
481                                                 diseqc.data[0] = 0xE0;
482                                                 diseqc.data[1] = 0x31;          // positioner
483                                                 if ( useGotoXX )
484                                                 {
485                                                         diseqc.len = 5;
486                                                         diseqc.data[2] = 0x6E;  // drive to angular position
487                                                         diseqc.data[3] = ((RotorCmd & 0xFF00) / 0x100);
488                                                         diseqc.data[4] = RotorCmd & 0xFF;
489                                                 }
490                                                 else
491                                                 {
492                                                         diseqc.len = 4;
493                                                         diseqc.data[2] = 0x6B;  // goto stored sat position
494                                                         diseqc.data[3] = RotorCmd;
495                                                 }
496
497                                                 if ( rotor_param.m_inputpower_parameters.m_use )
498                                                 { // use measure rotor input power to detect rotor state
499                                                         eSecCommand::rotor cmd;
500 // measure idle power values
501                                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_IDLE_INPUTPOWER_AVAIL_GOTO, +8) ); // already measured?
502                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec after voltage change
503                                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 0) );
504                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18) );
505                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 100) );  // wait 100msec before measure
506                                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 1) );
507                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) ); // back to lower voltage
508                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
509 ////////////////////////////
510                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
511                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec after voltage change
512                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
513                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 40) );  // 2 seconds rotor start timout
514 // rotor start loop
515                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // 50msec delay
516                                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
517                                                         cmd.direction=1;  // check for running rotor
518                                                         cmd.deltaA=rotor_param.m_inputpower_parameters.m_delta;
519                                                         cmd.steps=+3;
520                                                         cmd.okcount=0;
521                                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );  // check if rotor has started
522                                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +10 ) );  // timeout .. we assume now the rotor is already at the correct position
523                                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // goto loop start
524 ////////////////////
525                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 2400) );  // 2 minutes running timeout
526                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18) );
527                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
528 // rotor running loop
529                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
530                                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
531                                                         cmd.direction=0;  // check for stopped rotor
532                                                         cmd.steps=+3;
533                                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );
534                                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +3 ) );  // timeout ? this should never happen
535                                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // running loop start
536 /////////////////////
537                                                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
538                                                         frontend.setData(3, RotorCmd);
539                                                         frontend.setData(4, sat.orbital_position);
540                                                 }
541                                                 else
542                                                         eFatal("rotor turning without inputpowermeasure not implemented yet");
543                                         }
544                                 }
545                         }
546                         else
547                                 frontend.setData(0, band); // store band as csw .. needed for linked tuner handling
548
549                         eSecCommand::pair compare;
550                         compare.voltage = voltage;
551                         compare.steps = +3;
552                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
553                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
554                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 10) );
555
556                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
557                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 15) );
558
559                         frontend.setSecSequence(sec_sequence);
560
561                         return 0;
562                 }
563         }
564
565         if (linked)
566                 return 0;
567
568         eDebug("found no satellite configuration for orbital position (%d)", sat.orbital_position );
569         return -1;
570 }
571
572 RESULT eDVBSatelliteEquipmentControl::clear()
573 {
574         for (int i=0; i < m_lnbidx; ++i)
575         {
576                 m_lnbs[i].m_satellites.clear();
577                 m_lnbs[i].tuner_mask = 0;
578         }
579         m_lnbidx=-1;
580
581 // clear linked tuner configuration
582         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
583                 it->m_frontend->setData(7, -1);
584
585         return 0;
586 }
587
588 /* LNB Specific Parameters */
589 RESULT eDVBSatelliteEquipmentControl::addLNB()
590 {
591         if ( m_lnbidx < (int)(sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters)))
592                 m_curSat=m_lnbs[++m_lnbidx].m_satellites.end();
593         else
594         {
595                 eDebug("no more LNB free... cnt is %d", m_lnbidx);
596                 return -ENOSPC;
597         }
598         return 0;
599 }
600
601 RESULT eDVBSatelliteEquipmentControl::setLNBTunerMask(int tunermask)
602 {
603         if ( currentLNBValid() )
604                 m_lnbs[m_lnbidx].tuner_mask = tunermask;
605         else
606                 return -ENOENT;
607         return 0;
608 }
609
610 RESULT eDVBSatelliteEquipmentControl::setLNBLOFL(int lofl)
611 {
612         if ( currentLNBValid() )
613                 m_lnbs[m_lnbidx].m_lof_lo = lofl;
614         else
615                 return -ENOENT;
616         return 0;
617 }
618
619 RESULT eDVBSatelliteEquipmentControl::setLNBLOFH(int lofh)
620 {
621         if ( currentLNBValid() )
622                 m_lnbs[m_lnbidx].m_lof_hi = lofh;
623         else
624                 return -ENOENT;
625         return 0;
626 }
627
628 RESULT eDVBSatelliteEquipmentControl::setLNBThreshold(int threshold)
629 {
630         if ( currentLNBValid() )
631                 m_lnbs[m_lnbidx].m_lof_threshold = threshold;
632         else
633                 return -ENOENT;
634         return 0;
635 }
636
637 RESULT eDVBSatelliteEquipmentControl::setLNBIncreasedVoltage(bool onoff)
638 {
639         if ( currentLNBValid() )
640                 m_lnbs[m_lnbidx].m_increased_voltage = onoff;
641         else
642                 return -ENOENT;
643         return 0;
644 }
645
646 /* DiSEqC Specific Parameters */
647 RESULT eDVBSatelliteEquipmentControl::setDiSEqCMode(int diseqcmode)
648 {
649         if ( currentLNBValid() )
650                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_diseqc_mode = (eDVBSatelliteDiseqcParameters::t_diseqc_mode)diseqcmode;
651         else
652                 return -ENOENT;
653         return 0;
654 }
655
656 RESULT eDVBSatelliteEquipmentControl::setToneburst(int toneburst)
657 {
658         if ( currentLNBValid() )
659                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_toneburst_param = (eDVBSatelliteDiseqcParameters::t_toneburst_param)toneburst;
660         else
661                 return -ENOENT;
662         return 0;
663 }
664
665 RESULT eDVBSatelliteEquipmentControl::setRepeats(int repeats)
666 {
667         if ( currentLNBValid() )
668                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_repeats=repeats;
669         else
670                 return -ENOENT;
671         return 0;
672 }
673
674 RESULT eDVBSatelliteEquipmentControl::setCommittedCommand(int command)
675 {
676         if ( currentLNBValid() )
677                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_committed_cmd=command;
678         else
679                 return -ENOENT;
680         return 0;
681 }
682
683 RESULT eDVBSatelliteEquipmentControl::setUncommittedCommand(int command)
684 {
685         if ( currentLNBValid() )
686                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_uncommitted_cmd = command;
687         else
688                 return -ENOENT;
689         return 0;
690 }
691
692 RESULT eDVBSatelliteEquipmentControl::setCommandOrder(int order)
693 {
694         if ( currentLNBValid() )
695                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_command_order=order;
696         else
697                 return -ENOENT;
698         return 0;
699 }
700
701 RESULT eDVBSatelliteEquipmentControl::setFastDiSEqC(bool onoff)
702 {
703         if ( currentLNBValid() )
704                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_use_fast=onoff;
705         else
706                 return -ENOENT;
707         return 0;
708 }
709
710 RESULT eDVBSatelliteEquipmentControl::setSeqRepeat(bool onoff)
711 {
712         if ( currentLNBValid() )
713                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_seq_repeat = onoff;
714         else
715                 return -ENOENT;
716         return 0;
717 }
718
719 /* Rotor Specific Parameters */
720 RESULT eDVBSatelliteEquipmentControl::setLongitude(float longitude)
721 {
722         if ( currentLNBValid() )
723                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_longitude=longitude;
724         else
725                 return -ENOENT;
726         return 0;
727 }
728
729 RESULT eDVBSatelliteEquipmentControl::setLatitude(float latitude)
730 {
731         if ( currentLNBValid() )
732                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_latitude=latitude;
733         else
734                 return -ENOENT;
735         return 0;
736 }
737
738 RESULT eDVBSatelliteEquipmentControl::setLoDirection(int direction)
739 {
740         if ( currentLNBValid() )
741                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_lo_direction=direction;
742         else
743                 return -ENOENT;
744         return 0;
745 }
746
747 RESULT eDVBSatelliteEquipmentControl::setLaDirection(int direction)
748 {
749         if ( currentLNBValid() )
750                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_la_direction=direction;
751         else
752                 return -ENOENT;
753         return 0;
754 }
755
756 RESULT eDVBSatelliteEquipmentControl::setUseInputpower(bool onoff)
757 {
758         if ( currentLNBValid() )
759                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_use=onoff;
760         else
761                 return -ENOENT;
762         return 0;
763 }
764
765 RESULT eDVBSatelliteEquipmentControl::setInputpowerDelta(int delta)
766 {
767         if ( currentLNBValid() )
768                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_delta=delta;
769         else
770                 return -ENOENT;
771         return 0;
772 }
773
774 /* Satellite Specific Parameters */
775 RESULT eDVBSatelliteEquipmentControl::addSatellite(int orbital_position)
776 {
777         if ( currentLNBValid() )
778         {
779                 std::map<int, eDVBSatelliteSwitchParameters>::iterator it =
780                         m_lnbs[m_lnbidx].m_satellites.find(orbital_position);
781                 if ( it == m_lnbs[m_lnbidx].m_satellites.end() )
782                 {
783                         std::pair<std::map<int, eDVBSatelliteSwitchParameters>::iterator, bool > ret =
784                                 m_lnbs[m_lnbidx].m_satellites.insert(
785                                         std::pair<int, eDVBSatelliteSwitchParameters>(orbital_position, eDVBSatelliteSwitchParameters())
786                                 );
787                         if ( ret.second )
788                                 m_curSat = ret.first;
789                         else
790                                 return -ENOMEM;
791                 }
792                 else
793                         return -EEXIST;
794         }
795         else
796                 return -ENOENT;
797         return 0;
798 }
799
800 RESULT eDVBSatelliteEquipmentControl::setVoltageMode(int mode)
801 {
802         if ( currentLNBValid() && m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
803                 m_curSat->second.m_voltage_mode = (eDVBSatelliteSwitchParameters::t_voltage_mode)mode;
804         else
805                 return -ENOENT;
806         return 0;
807
808 }
809
810 RESULT eDVBSatelliteEquipmentControl::setToneMode(int mode)
811 {
812         if ( currentLNBValid() )
813         {
814                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
815                         m_curSat->second.m_22khz_signal = (eDVBSatelliteSwitchParameters::t_22khz_signal)mode;
816                 else
817                         return -EPERM;
818         }
819         else
820                 return -ENOENT;
821         return 0;
822 }
823
824 RESULT eDVBSatelliteEquipmentControl::setRotorPosNum(int rotor_pos_num)
825 {
826         if ( currentLNBValid() )
827         {
828                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
829                         m_curSat->second.m_rotorPosNum=rotor_pos_num;
830                 else
831                         return -EPERM;
832         }
833         else
834                 return -ENOENT;
835         return 0;
836 }
837
838 RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
839 {
840         if (tu1 == tu2)
841                 return -1;
842
843         eDVBFrontend *p1=NULL, *p2=NULL;
844         int tmp1=tu1, tmp2=tu2;
845
846         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
847         {
848                 if ( !tmp1 )
849                         p1 = it->m_frontend;
850                 else
851                         --tmp1;
852                 if (!tmp2)
853                         p2 = it->m_frontend;
854                 else
855                         --tmp2;
856         }
857         if (p1 && p2)
858         {
859                 p1->setData(7, tu2);
860                 p1->setTone(iDVBFrontend::toneOff);
861                 p1->setVoltage(iDVBFrontend::voltageOff);
862
863                 p2->setData(7, tu1);
864                 return 0;
865         }
866         return -1;
867 }