4df14bf223aebe0b0a97ee010755c64e8fa6e81b
[openblackhole/openblackhole-enigma2.git] / lib / dvb / sec.cpp
1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/sec.h>
3 #include <lib/dvb/rotor_calc.h>
4 #include <lib/dvb/dvbtime.h>
5
6 #include <set>
7
8 #include <lib/base/eerror.h>
9
10 //#define SEC_DEBUG
11
12 #ifdef SEC_DEBUG
13 #define eSecDebug(arg...) eDebug(arg)
14 #else
15 #define eSecDebug(arg...)
16 #endif
17
18 DEFINE_REF(eDVBSatelliteEquipmentControl);
19
20 eDVBSatelliteEquipmentControl *eDVBSatelliteEquipmentControl::instance;
21
22 int eDVBSatelliteEquipmentControl::m_params[MAX_PARAMS];
23 /*
24    defaults are set in python lib/python/Components/NimManager.py
25    in InitSecParams function via setParam call
26 */
27
28 void eDVBSatelliteEquipmentControl::setParam(int param, int value)
29 {
30         if (param >= 0 && param < MAX_PARAMS)
31                 m_params[param]=value;
32 }
33
34 eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBRegisteredFrontend> &avail_frontends, eSmartPtrList<eDVBRegisteredFrontend> &avail_simulate_frontends)
35         :m_lnbidx((sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters))-1), m_curSat(m_lnbs[0].m_satellites.end()), m_avail_frontends(avail_frontends), m_avail_simulate_frontends(avail_simulate_frontends), m_rotorMoving(0)
36 {
37         if (!instance)
38                 instance = this;
39         clear();
40 }
41
42 #define eSecDebugNoSimulate(x...) \
43         do { \
44                 if (!simulate) \
45                 { \
46                         eSecDebug(x); \
47                 } \
48         } while(0)
49
50 int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite &sat, iDVBFrontend *fe, int slot_id, int *highest_score_lnb)
51 {
52         bool simulate = ((eDVBFrontend*)fe)->is_simulate();
53         bool direct_connected = m_not_linked_slot_mask & slot_id;
54         int score=0, satcount=0;
55         long linked_prev_ptr=-1, linked_next_ptr=-1, linked_csw=-1, linked_ucsw=-1, linked_toneburst=-1,
56                 fe_satpos_depends_ptr=-1, fe_rotor_pos=-1;
57         bool linked_in_use = false;
58
59         eSecDebugNoSimulate("direct_connected %d", !!direct_connected);
60
61         fe->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
62         fe->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
63         fe->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, fe_satpos_depends_ptr);
64
65         // first we search the linkage base frontend and check if any tuner in prev direction is used
66         while (linked_prev_ptr != -1)
67         {
68                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
69                 if (linked_fe->m_inuse)
70                         linked_in_use = true;
71                 fe = linked_fe->m_frontend;
72                 linked_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
73         }
74
75         fe->getData(eDVBFrontend::ROTOR_POS, fe_rotor_pos);
76
77         // now check also the linked tuners  is in use
78         while (!linked_in_use && linked_next_ptr != -1)
79         {
80                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
81                 if (linked_fe->m_inuse)
82                         linked_in_use = true;
83                 linked_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
84         }
85
86         // when a linked in use tuner is found we get the tuner data...
87         if (linked_in_use)
88         {
89                 fe->getData(eDVBFrontend::CSW, linked_csw);
90                 fe->getData(eDVBFrontend::UCSW, linked_ucsw);
91                 fe->getData(eDVBFrontend::TONEBURST, linked_toneburst);
92         }
93
94         if (highest_score_lnb)
95                 *highest_score_lnb = -1;
96
97         eSecDebugNoSimulate("canTune %d", slot_id);
98
99         for (int idx=0; idx <= m_lnbidx; ++idx )
100         {
101                 bool rotor=false;
102                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
103                 bool is_unicable = lnb_param.SatCR_idx != -1;
104                 bool is_unicable_position_switch = lnb_param.SatCR_positions > 1;
105
106                 if ( lnb_param.m_slot_mask & slot_id ) // lnb for correct tuner?
107                 {
108                         int ret = 0;
109                         eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
110
111                         eSecDebugNoSimulate("lnb %d found", idx);
112
113                         satcount += lnb_param.m_satellites.size();
114
115                         std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
116                                 lnb_param.m_satellites.find(sat.orbital_position);
117                         if ( sit != lnb_param.m_satellites.end())
118                         {
119                                 bool diseqc=false;
120                                 long band=0,
121                                         satpos_depends_ptr=fe_satpos_depends_ptr,
122                                         csw = di_param.m_committed_cmd,
123                                         ucsw = di_param.m_uncommitted_cmd,
124                                         toneburst = di_param.m_toneburst_param,
125                                         rotor_pos = fe_rotor_pos;
126
127                                 eSecDebugNoSimulate("sat %d found", sat.orbital_position);
128
129                                 /* Dishpro bandstacking HACK */
130                                 if (lnb_param.m_lof_threshold == 1000)
131                                 {
132                                         if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical))
133                                         {
134                                                 band |= 1;
135                                         }
136                                         band |= 2; /* voltage always 18V for Dishpro */
137                                 }
138                                 else
139                                 {
140                                         if ( sat.frequency > lnb_param.m_lof_threshold )
141                                                 band |= 1;
142                                         if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical))
143                                                 band |= 2;
144                                 }
145
146                                 if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
147                                 {
148                                         diseqc=true;
149                                         if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
150                                                 csw = 0xF0 | (csw << 2);
151
152                                         if (di_param.m_committed_cmd <= eDVBSatelliteDiseqcParameters::SENDNO)
153                                                 csw |= band;
154
155                                         if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )  // ROTOR
156                                                 rotor = true;
157
158                                         ret = 10000;
159                                 }
160                                 else
161                                 {
162                                         csw = band;
163                                         ret = 15000;
164                                 }
165
166                                 if (sat.no_rotor_command_on_tune && !rotor) {
167                                         eSecDebugNoSimulate("no rotor but no_rotor_command_on_tune is set.. ignore lnb %d", idx);
168                                         continue;
169                                 }
170
171                                 eSecDebugNoSimulate("ret1 %d", ret);
172
173                                 if (linked_in_use && !is_unicable)
174                                 {
175                                         // compare tuner data
176                                         if ( (csw != linked_csw) ||
177                                                 ( diseqc && (ucsw != linked_ucsw || toneburst != linked_toneburst) ) ||
178                                                 ( rotor && rotor_pos != sat.orbital_position ) )
179                                         {
180                                                 ret = 0;
181                                         }
182                                         else
183                                                 ret += 15;
184                                         eSecDebugNoSimulate("ret2 %d", ret);
185                                 }
186                                 else if ((rotor && satpos_depends_ptr != -1) && !(is_unicable && is_unicable_position_switch))
187                                 {
188                                         eSecDebugNoSimulate("satpos depends");
189                                         eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) satpos_depends_ptr;
190                                         if (direct_connected) // current fe is direct connected.. (can turn the rotor)
191                                         {
192                                                 if (satpos_depends_to_fe->m_inuse) // if the dependent frontend is in use?
193                                                 {
194                                                         if (rotor_pos != sat.orbital_position) // new orbital position not equal to current orbital pos?
195                                                                 ret = 0;
196                                                         else
197                                                                 ret += 10;
198                                                 }
199                                                 eSecDebugNoSimulate("ret3 %d", ret);
200                                         }
201                                         else // current fe is dependent of another tuner ... (so this fe can't turn the rotor!)
202                                         {
203                                                 // get current orb pos of the tuner with rotor connection
204                                                 satpos_depends_to_fe->m_frontend->getData(eDVBFrontend::ROTOR_POS, rotor_pos);
205                                                 if (rotor_pos == -1 /* we dont know the rotor position yet */
206                                                         || rotor_pos != sat.orbital_position ) // not the same orbital position?
207                                                 {
208                                                         ret = 0;
209                                                 }
210                                         }
211                                         eSecDebugNoSimulate("ret4 %d", ret);
212                                 }
213
214                                 if (ret && rotor && rotor_pos != -1)
215                                         ret -= abs(rotor_pos-sat.orbital_position);
216
217                                 eSecDebugNoSimulate("ret5 %d", ret);
218
219                                 if (ret && !is_unicable)
220                                 {
221                                         int lof = sat.frequency > lnb_param.m_lof_threshold ?
222                                                 lnb_param.m_lof_hi : lnb_param.m_lof_lo;
223                                         int tuner_freq = abs(sat.frequency - lof);
224                                         if (tuner_freq < 900000 || tuner_freq > 2200000)
225                                                 ret = 0;
226                                 }
227
228                                 if (ret && lnb_param.m_prio != -1)
229                                         ret = lnb_param.m_prio;
230
231                                 eSecDebugNoSimulate("ret %d, score old %d", ret, score);
232                                 if (ret > score)
233                                 {
234                                         score = ret;
235                                         if (highest_score_lnb)
236                                                 *highest_score_lnb = idx;
237                                 }
238                                 eSecDebugNoSimulate("score new %d", score);
239                         }
240                 }
241         }
242         if (score && satcount)
243         {
244                 if (score > (satcount-1))
245                         score -= (satcount-1);
246                 else
247                         score = 1; // min score
248         }
249         if (score && direct_connected)
250                 score += 5; // increase score for tuners with direct sat connection
251         eSecDebugNoSimulate("final score %d", score);
252         return score;
253 }
254
255 bool need_turn_fast(int turn_speed)
256 {
257         if (turn_speed == eDVBSatelliteRotorParameters::FAST)
258                 return true;
259         else if (turn_speed != eDVBSatelliteRotorParameters::SLOW)
260         {
261                 int begin = turn_speed >> 16; // high word is start time
262                 int end = turn_speed&0xFFFF; // low word is end time
263                 time_t now_time = ::time(0);
264                 tm nowTime;
265                 localtime_r(&now_time, &nowTime);
266                 int now = (nowTime.tm_hour + 1) * 60 + nowTime.tm_min + 1;
267                 bool neg = end <= begin;
268                 if (neg) {
269                         int tmp = begin;
270                         begin = end;
271                         end = tmp;
272                 }
273                 if ((now >= begin && now < end) ^ neg)
274                         return true;
275         }
276         return false;
277 }
278
279 #define VOLTAGE(x) (lnb_param.m_increased_voltage ? iDVBFrontend::voltage##x##_5 : iDVBFrontend::voltage##x)
280
281 #define eDebugNoSimulate(x...) \
282         do { \
283                 if (!simulate) \
284                         eDebug(x); \
285         } while(0)
286
287 RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, const eDVBFrontendParametersSatellite &sat, int &frequency, int slot_id, unsigned int tunetimeout)
288 {
289         bool simulate = ((eDVBFrontend*)&frontend)->is_simulate();
290         int lnb_idx = -1;
291         if (canTune(sat, &frontend, slot_id, &lnb_idx))
292         {
293                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[lnb_idx];
294                 eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
295                 eDVBSatelliteRotorParameters &rotor_param = lnb_param.m_rotor_parameters;
296
297                 std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
298                         lnb_param.m_satellites.find(sat.orbital_position);
299                 if ( sit != lnb_param.m_satellites.end())
300                 {
301                         eSecCommandList sec_sequence;
302                         eDVBSatelliteSwitchParameters &sw_param = sit->second;
303                         bool doSetFrontend = true;
304                         bool doSetVoltageToneFrontend = true;
305                         bool forceChanged = false;
306                         bool needDiSEqCReset = false;
307                         long band=0,
308                                 voltage = iDVBFrontend::voltageOff,
309                                 tone = iDVBFrontend::toneOff,
310                                 csw = di_param.m_committed_cmd,
311                                 ucsw = di_param.m_uncommitted_cmd,
312                                 toneburst = di_param.m_toneburst_param,
313                                 lastcsw = -1,
314                                 lastucsw = -1,
315                                 lastToneburst = -1,
316                                 lastRotorCmd = -1,
317                                 curRotorPos = -1,
318                                 satposDependPtr = -1;
319                         iDVBFrontend *sec_fe=&frontend;
320                         eDVBRegisteredFrontend *linked_fe = 0;
321                         eDVBSatelliteDiseqcParameters::t_diseqc_mode diseqc_mode = di_param.m_diseqc_mode;
322                         eDVBSatelliteSwitchParameters::t_voltage_mode voltage_mode = sw_param.m_voltage_mode;
323                         bool diseqc13V = voltage_mode == eDVBSatelliteSwitchParameters::HV_13;
324                         bool is_unicable = lnb_param.SatCR_idx != -1;
325
326                         bool useGotoXX = false;
327                         int RotorCmd=-1;
328                         int send_mask = 0;
329
330                         lnb_param.guard_offset = 0; //HACK
331
332                         frontend.setData(eDVBFrontend::SATCR, lnb_param.SatCR_idx);
333
334                         if (diseqc13V)
335                                 voltage_mode = eDVBSatelliteSwitchParameters::HV;
336
337                         frontend.getData(eDVBFrontend::SATPOS_DEPENDS_PTR, satposDependPtr);
338
339                         if (!(m_not_linked_slot_mask & slot_id))  // frontend with direct connection?
340                         {
341                                 long linked_prev_ptr;
342                                 frontend.getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
343                                 while (linked_prev_ptr != -1)
344                                 {
345                                         linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
346                                         sec_fe = linked_fe->m_frontend;
347                                         sec_fe->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
348                                 }
349                                 if (satposDependPtr != -1)  // we dont need uncommitted switch and rotor cmds on second output of a rotor lnb
350                                         diseqc_mode = eDVBSatelliteDiseqcParameters::V1_0;
351                                 else {
352                                         // in eDVBFrontend::tuneLoop we call closeFrontend and ->inc_use() in this this condition (to put the kernel frontend thread into idle state)
353                                         // so we must resend all diseqc stuff (voltage is disabled when the frontend is closed)
354                                         int state;
355                                         sec_fe->getState(state);
356                                         if (!linked_fe->m_inuse && state != eDVBFrontend::stateIdle)
357                                                 forceChanged = true;
358                                 }
359                         }
360
361                         sec_fe->getData(eDVBFrontend::CSW, lastcsw);
362                         sec_fe->getData(eDVBFrontend::UCSW, lastucsw);
363                         sec_fe->getData(eDVBFrontend::TONEBURST, lastToneburst);
364                         sec_fe->getData(eDVBFrontend::ROTOR_CMD, lastRotorCmd);
365                         sec_fe->getData(eDVBFrontend::ROTOR_POS, curRotorPos);
366
367                         if (lastcsw == lastucsw && lastToneburst == lastucsw && lastucsw == -1)
368                                 needDiSEqCReset = true;
369
370                         /* Dishpro bandstacking HACK */
371                         if (lnb_param.m_lof_threshold == 1000)
372                         {
373                                 if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical))
374                                 {
375                                         band |= 1;
376                                 }
377                                 band |= 2; /* voltage always 18V for Dishpro */
378                         }
379                         else
380                         {
381                                 if ( sat.frequency > lnb_param.m_lof_threshold )
382                                         band |= 1;
383                                 if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical))
384                                         band |= 2;
385                         }
386
387                         int lof = (band&1)?lnb_param.m_lof_hi:lnb_param.m_lof_lo;
388
389                         if(!is_unicable)
390                         {
391                                 // calc Frequency
392                                 int local= abs(sat.frequency
393                                         - lof);
394                                 frequency = ((((local * 2) / 125) + 1) / 2) * 125;
395                                 frontend.setData(eDVBFrontend::FREQ_OFFSET, sat.frequency - frequency);
396
397                                 /* Dishpro bandstacking HACK */
398                                 if (lnb_param.m_lof_threshold == 1000)
399                                         voltage = VOLTAGE(18);
400                                 else if ( voltage_mode == eDVBSatelliteSwitchParameters::_14V
401                                         || ( sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical
402                                                 && voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
403                                         voltage = VOLTAGE(13);
404                                 else if ( voltage_mode == eDVBSatelliteSwitchParameters::_18V
405                                         || ( !(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical)
406                                                 && voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
407                                         voltage = VOLTAGE(18);
408                                 if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::ON)
409                                         || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && (band&1) ) )
410                                         tone = iDVBFrontend::toneOn;
411                                 else if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::OFF)
412                                         || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && !(band&1) ) )
413                                         tone = iDVBFrontend::toneOff;
414                         }
415                         else
416                         {
417                                 int tmp1 = abs(sat.frequency
418                                                 -lof)
419                                                 + lnb_param.SatCRvco
420                                                 - 1400000
421                                                 + lnb_param.guard_offset;
422                                 int tmp2 = ((((tmp1 * 2) / 4000) + 1) / 2) * 4000;
423                                 frequency = lnb_param.SatCRvco - (tmp1-tmp2) + lnb_param.guard_offset;
424                                 lnb_param.UnicableTuningWord = ((tmp2 / 4000)
425                                                 | ((band & 1) ? 0x400 : 0)                      //HighLow
426                                                 | ((band & 2) ? 0x800 : 0)                      //VertHor
427                                                 | ((lnb_param.LNBNum & 1) ? 0 : 0x1000)                 //Umschaltung LNB1 LNB2
428                                                 | (lnb_param.SatCR_idx << 13));         //Adresse des SatCR
429                                                 eDebug("[prepare] UnicableTuningWord %#04x",lnb_param.UnicableTuningWord);
430                                                 eDebug("[prepare] guard_offset %d",lnb_param.guard_offset);
431                                 frontend.setData(eDVBFrontend::FREQ_OFFSET, (lnb_param.UnicableTuningWord & 0x3FF) *4000 + 1400000 + lof - (2 * (lnb_param.SatCRvco - (tmp1-tmp2))) );
432                                 voltage = VOLTAGE(13);
433                         }
434
435                         if (diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
436                         {
437                                 if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
438                                         csw = 0xF0 | (csw << 2);
439
440                                 if (di_param.m_committed_cmd <= eDVBSatelliteDiseqcParameters::SENDNO)
441                                         csw |= band;
442
443                                 bool send_csw =
444                                         (di_param.m_committed_cmd != eDVBSatelliteDiseqcParameters::SENDNO);
445                                 bool changed_csw = send_csw && (forceChanged || csw != lastcsw);
446
447                                 bool send_ucsw =
448                                         (di_param.m_uncommitted_cmd && diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0);
449                                 bool changed_ucsw = send_ucsw && (forceChanged || ucsw != lastucsw);
450
451                                 bool send_burst =
452                                         (di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO);
453                                 bool changed_burst = send_burst && (forceChanged || toneburst != lastToneburst);
454
455                                 /* send_mask
456                                         1 must send csw
457                                         2 must send ucsw
458                                         4 send toneburst first
459                                         8 send toneburst at end */
460                                 if (changed_burst) // toneburst first and toneburst changed
461                                 {
462                                         if (di_param.m_command_order&1)
463                                         {
464                                                 send_mask |= 4;
465                                                 if ( send_csw )
466                                                         send_mask |= 1;
467                                                 if ( send_ucsw )
468                                                         send_mask |= 2;
469                                         }
470                                         else
471                                                 send_mask |= 8;
472                                 }
473                                 if (changed_ucsw)
474                                 {
475                                         send_mask |= 2;
476                                         if ((di_param.m_command_order&4) && send_csw)
477                                                 send_mask |= 1;
478                                         if (di_param.m_command_order==4 && send_burst)
479                                                 send_mask |= 8;
480                                 }
481                                 if (changed_csw)
482                                 {
483                                         if ( di_param.m_use_fast
484                                                 && di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO
485                                                 && (lastcsw & 0xF0)
486                                                 && ((csw / 4) == (lastcsw / 4)) )
487                                                 eDebugNoSimulate("dont send committed cmd (fast diseqc)");
488                                         else
489                                         {
490                                                 send_mask |= 1;
491                                                 if (!(di_param.m_command_order&4) && send_ucsw)
492                                                         send_mask |= 2;
493                                                 if (!(di_param.m_command_order&1) && send_burst)
494                                                         send_mask |= 8;
495                                         }
496                                 }
497
498 #if 0
499                                 eDebugNoNewLineStart("sendmask: ");
500                                 for (int i=3; i >= 0; --i)
501                                         if ( send_mask & (1<<i) )
502                                                 eDebugNoNewLine("1");
503                                         else
504                                                 eDebugNoNewLine("0");
505                                 eDebugNoNewLine("");
506 #endif
507                                 if ( diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2
508                                         && !sat.no_rotor_command_on_tune )
509                                 {
510                                         if (sw_param.m_rotorPosNum) // we have stored rotor pos?
511                                                 RotorCmd=sw_param.m_rotorPosNum;
512                                         else  // we must calc gotoxx cmd
513                                         {
514                                                 eDebugNoSimulate("Entry for %d,%d? not in Rotor Table found... i try gotoXX?", sat.orbital_position / 10, sat.orbital_position % 10 );
515                                                 useGotoXX = true;
516
517                                                 double  SatLon = abs(sat.orbital_position)/10.00,
518                                                                 SiteLat = rotor_param.m_gotoxx_parameters.m_latitude,
519                                                                 SiteLon = rotor_param.m_gotoxx_parameters.m_longitude;
520
521                                                 if ( rotor_param.m_gotoxx_parameters.m_la_direction == eDVBSatelliteRotorParameters::SOUTH )
522                                                         SiteLat = -SiteLat;
523
524                                                 if ( rotor_param.m_gotoxx_parameters.m_lo_direction == eDVBSatelliteRotorParameters::WEST )
525                                                         SiteLon = 360 - SiteLon;
526
527                                                 eDebugNoSimulate("siteLatitude = %lf, siteLongitude = %lf, %lf degrees", SiteLat, SiteLon, SatLon );
528                                                 double satHourAngle =
529                                                         calcSatHourangle( SatLon, SiteLat, SiteLon );
530                                                 eDebugNoSimulate("PolarmountHourAngle=%lf", satHourAngle );
531
532                                                 static int gotoXTable[10] =
533                                                         { 0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E };
534
535                                                 if (SiteLat >= 0) // Northern Hemisphere
536                                                 {
537                                                         int tmp=(int)round( fabs( 180 - satHourAngle ) * 10.0 );
538                                                         RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
539
540                                                         if (satHourAngle < 180) // the east
541                                                                 RotorCmd |= 0xE000;
542                                                         else                                    // west
543                                                                 RotorCmd |= 0xD000;
544                                                 }
545                                                 else // Southern Hemisphere
546                                                 {
547                                                         if (satHourAngle < 180) // the east
548                                                         {
549                                                                 int tmp=(int)round( fabs( satHourAngle ) * 10.0 );
550                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
551                                                                 RotorCmd |= 0xD000;
552                                                         }
553                                                         else // west
554                                                         {
555                                                                 int tmp=(int)round( fabs( 360 - satHourAngle ) * 10.0 );
556                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
557                                                                 RotorCmd |= 0xE000;
558                                                         }
559                                                 }
560                                                 eDebugNoSimulate("RotorCmd = %04x", RotorCmd);
561                                         }
562                                 }
563
564                                 if ( send_mask )
565                                 {
566                                         int diseqc_repeats = diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0 ? di_param.m_repeats : 0;
567                                         int vlt = iDVBFrontend::voltageOff;
568                                         eSecCommand::pair compare;
569                                         compare.steps = +3;
570                                         compare.tone = iDVBFrontend::toneOff;
571                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
572                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
573                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) );
574
575                                         if (diseqc13V)
576                                                 vlt = iDVBFrontend::voltage13;
577                                         else if ( RotorCmd != -1 && RotorCmd != lastRotorCmd )
578                                         {
579                                                 if (rotor_param.m_inputpower_parameters.m_use && !is_unicable)
580                                                         vlt = VOLTAGE(18);  // in input power mode set 18V for measure input power
581                                                 else
582                                                         vlt = VOLTAGE(13);  // in normal mode start turning with 13V
583                                         }
584                                         else
585                                                 vlt = voltage;
586
587                                         // check if voltage is already correct..
588                                         compare.voltage = vlt;
589                                         compare.steps = +7;
590                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
591
592                                         // check if voltage is disabled
593                                         compare.voltage = iDVBFrontend::voltageOff;
594                                         compare.steps = +4;
595                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
596
597                                         // voltage is changed... use DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS
598                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, vlt) );
599                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );
600                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +3) );
601
602                                         // voltage was disabled.. use DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS
603                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, vlt) );
604                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
605
606                                         sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS) );
607                                         if (needDiSEqCReset)
608                                         {
609                                                 eDVBDiseqcCommand diseqc;
610                                                 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
611                                                 diseqc.len = 3;
612                                                 diseqc.data[0] = 0xE0;
613                                                 diseqc.data[1] = 0;
614                                                 diseqc.data[2] = 0;
615                                                 // diseqc reset
616                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
617                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_DISEQC_RESET_CMD]) );
618                                                 diseqc.data[2] = 3;
619                                                 // diseqc peripherial powersupply on
620                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
621                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD]) );
622                                         }
623
624                                         for (int seq_repeat = 0; seq_repeat < (di_param.m_seq_repeat?2:1); ++seq_repeat)
625                                         {
626                                                 if ( send_mask & 4 )
627                                                 {
628                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
629                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_TONEBURST]) );
630                                                 }
631
632                                                 int loops=0;
633
634                                                 if ( send_mask & 1 )
635                                                         ++loops;
636                                                 if ( send_mask & 2 )
637                                                         ++loops;
638
639                                                 loops <<= diseqc_repeats;
640
641                                                 for ( int i = 0; i < loops;)  // fill commands...
642                                                 {
643                                                         eDVBDiseqcCommand diseqc;
644                                                         memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
645                                                         diseqc.len = 4;
646                                                         diseqc.data[0] = i ? 0xE1 : 0xE0;
647                                                         diseqc.data[1] = 0x10;
648                                                         if ( (send_mask & 2) && (di_param.m_command_order & 4) )
649                                                         {
650                                                                 diseqc.data[2] = 0x39;
651                                                                 diseqc.data[3] = ucsw;
652                                                         }
653                                                         else if ( send_mask & 1 )
654                                                         {
655                                                                 diseqc.data[2] = 0x38;
656                                                                 diseqc.data[3] = csw;
657                                                         }
658                                                         else  // no committed command confed.. so send uncommitted..
659                                                         {
660                                                                 diseqc.data[2] = 0x39;
661                                                                 diseqc.data[3] = ucsw;
662                                                         }
663                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
664
665                                                         i++;
666                                                         if ( i < loops )
667                                                         {
668                                                                 int cmd=0;
669                                                                 if (diseqc.data[2] == 0x38 && (send_mask & 2))
670                                                                         cmd=0x39;
671                                                                 else if (diseqc.data[2] == 0x39 && (send_mask & 1))
672                                                                         cmd=0x38;
673                                                                 int tmp = m_params[DELAY_BETWEEN_DISEQC_REPEATS];
674                                                                 if (cmd)
675                                                                 {
676                                                                         int delay = diseqc_repeats ? (tmp - 54) / 2 : tmp;  // standard says 100msek between two repeated commands
677                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay) );
678                                                                         diseqc.data[2]=cmd;
679                                                                         diseqc.data[3]=(cmd==0x38) ? csw : ucsw;
680                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
681                                                                         ++i;
682                                                                         if ( i < loops )
683                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay ) );
684                                                                         else
685                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
686                                                                 }
687                                                                 else  // delay 120msek when no command is in repeat gap
688                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, tmp) );
689                                                         }
690                                                         else
691                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
692                                                 }
693
694                                                 if ( send_mask & 8 )  // toneburst at end of sequence
695                                                 {
696                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
697                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_TONEBURST]) );
698                                                 }
699
700                                                 if (di_param.m_seq_repeat && seq_repeat == 0)
701                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_BEFORE_SEQUENCE_REPEAT]) );
702                                         }
703                                 }
704                         }
705                         else
706                         {
707                                 sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS) );
708                                 csw = band;
709                         }
710
711                         sec_fe->setData(eDVBFrontend::NEW_CSW, csw);
712                         sec_fe->setData(eDVBFrontend::NEW_UCSW, ucsw);
713                         sec_fe->setData(eDVBFrontend::NEW_TONEBURST, di_param.m_toneburst_param);
714
715                         if(is_unicable)
716                         {
717                                 // check if voltage is disabled
718                                 eSecCommand::pair compare;
719                                 compare.steps = +3;
720                                 compare.voltage = iDVBFrontend::voltageOff;
721                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
722                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
723                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS] ) );
724
725                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) );
726                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
727                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );  // wait 20 ms after voltage change
728
729                                 eDVBDiseqcCommand diseqc;
730                                 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
731                                 diseqc.len = 5;
732                                 diseqc.data[0] = 0xE0;
733                                 diseqc.data[1] = 0x10;
734                                 diseqc.data[2] = 0x5A;
735                                 diseqc.data[3] = lnb_param.UnicableTuningWord >> 8;
736                                 diseqc.data[4] = lnb_param.UnicableTuningWord;
737
738                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
739                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
740                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
741                                 if ( RotorCmd != -1 && RotorCmd != lastRotorCmd && !rotor_param.m_inputpower_parameters.m_use)
742                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) );  // wait 150msec after voltage change
743                         }
744
745                         eDebugNoSimulate("RotorCmd %02x, lastRotorCmd %02lx", RotorCmd, lastRotorCmd);
746                         if ( RotorCmd != -1 && RotorCmd != lastRotorCmd )
747                         {
748                                 int mrt = m_params[MOTOR_RUNNING_TIMEOUT]; // in seconds!
749                                 eSecCommand::pair compare;
750                                 if (!send_mask && !is_unicable)
751                                 {
752                                         compare.steps = +3;
753                                         compare.tone = iDVBFrontend::toneOff;
754                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
755                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
756                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) );
757
758                                         compare.voltage = iDVBFrontend::voltageOff;
759                                         compare.steps = +4;
760                                         // the next is a check if voltage is switched off.. then we first set a voltage :)
761                                         // else we set voltage after all diseqc stuff..
762                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
763
764                                         if (rotor_param.m_inputpower_parameters.m_use)
765                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) ); // set 18V for measure input power
766                                         else
767                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) ); // in normal mode start turning with 13V
768
769                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_MOTOR_CMD]) ); // wait 750ms when voltage was disabled
770                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +9) );  // no need to send stop rotor cmd and recheck voltage
771                                 }
772                                 else
773                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_BETWEEN_SWITCH_AND_MOTOR_CMD]) ); // wait 700ms when diseqc changed
774
775                                 eDVBDiseqcCommand diseqc;
776                                 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
777                                 diseqc.len = 3;
778                                 diseqc.data[0] = 0xE0;
779                                 diseqc.data[1] = 0x31;  // positioner
780                                 diseqc.data[2] = 0x60;  // stop
781                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_ROTORPOS_VALID_GOTO, +5) );
782                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
783                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
784                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
785                                 // wait 150msec after send rotor stop cmd
786                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_MOTOR_STOP_CMD]) );
787
788                                 diseqc.data[0] = 0xE0;
789                                 diseqc.data[1] = 0x31;          // positioner
790                                 if ( useGotoXX )
791                                 {
792                                         diseqc.len = 5;
793                                         diseqc.data[2] = 0x6E;  // drive to angular position
794                                         diseqc.data[3] = ((RotorCmd & 0xFF00) / 0x100);
795                                         diseqc.data[4] = RotorCmd & 0xFF;
796                                 }
797                                 else
798                                 {
799                                         diseqc.len = 4;
800                                         diseqc.data[2] = 0x6B;  // goto stored sat position
801                                         diseqc.data[3] = RotorCmd;
802                                         diseqc.data[4] = 0x00;
803                                 }
804
805                         // use measure rotor input power to detect motor state
806                                 if ( rotor_param.m_inputpower_parameters.m_use)
807                                 {
808                                         bool turn_fast = need_turn_fast(rotor_param.m_inputpower_parameters.m_turning_speed) && !is_unicable;
809                                         eSecCommand::rotor cmd;
810                                         eSecCommand::pair compare;
811                                         if (turn_fast)
812                                                 compare.voltage = VOLTAGE(18);
813                                         else
814                                                 compare.voltage = VOLTAGE(13);
815                                         compare.steps = +3;
816                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
817                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
818                         // measure idle power values
819                                         compare.steps = -2;
820                                         if (turn_fast) {
821                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER]) );  // wait 150msec after voltage change
822                                                 sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 1) );
823                                                 compare.val = 1;
824                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO, compare) );
825                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
826                                         }
827                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER]) );  // wait 150msec before measure
828                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 0) );
829                                         compare.val = 0;
830                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO, compare) );
831                         ////////////////////////////
832                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_DISEQC_RETRYS, m_params[MOTOR_COMMAND_RETRIES]) );  // 2 retries
833                                         sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
834                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
835                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 40) );  // 2 seconds rotor start timout
836                         // rotor start loop
837                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // 50msec delay
838                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
839                                         cmd.direction=1;  // check for running rotor
840                                         cmd.deltaA=rotor_param.m_inputpower_parameters.m_delta;
841                                         cmd.steps=+5;
842                                         cmd.okcount=0;
843                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );  // check if rotor has started
844                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +2 ) );  // timeout .. we assume now the rotor is already at the correct position
845                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // goto loop start
846                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO, turn_fast ? 10 : 9 ) );  // timeout .. we assume now the rotor is already at the correct position
847                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -8) );  // goto loop start
848                         ////////////////////
849                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_MOVING) );
850                                         if (turn_fast)
851                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) );
852                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, mrt*20) );  // mrt is in seconds... our SLEEP time is 50ms.. so * 20
853                         // rotor running loop
854                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
855                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
856                                         cmd.direction=0;  // check for stopped rotor
857                                         cmd.steps=+3;
858                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );
859                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +2 ) );  // timeout ? this should never happen
860                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // running loop start
861                         /////////////////////
862                                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
863                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_STOPPED) );
864                                 }
865                         // use normal motor turning mode
866                                 else
867                                 {
868                                         if (curRotorPos != -1)
869                                         {
870                                                 mrt = abs(curRotorPos - sat.orbital_position);
871                                                 if (mrt > 1800)
872                                                         mrt = 3600 - mrt;
873                                                 if (mrt % 10)
874                                                         mrt += 10; // round a little bit
875                                                 mrt *= 2000;  // (we assume a very slow rotor with just 0.5 degree per second here)
876                                                 mrt /= 10000;
877                                                 mrt += 3; // a little bit overhead
878                                         }
879                                         doSetVoltageToneFrontend=false;
880                                         doSetFrontend=false;
881                                         eSecCommand::rotor cmd;
882                                         eSecCommand::pair compare;
883                                         compare.voltage = VOLTAGE(13);
884                                         compare.steps = +3;
885                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
886                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
887                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) );  // wait 150msec after voltage change
888
889                                         sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
890                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_MOVING) );
891                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
892                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 1000) ); // sleep one second before change voltage or tone
893
894                                         compare.voltage = voltage;
895                                         compare.steps = +3;
896                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // correct final voltage?
897                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 2000) );  // wait 2 second before set high voltage
898                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
899
900                                         compare.tone = tone;
901                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
902                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
903                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) );
904                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 0) );
905
906                                         cmd.direction=1;  // check for running rotor
907                                         cmd.deltaA=0;
908                                         cmd.steps = +3;
909                                         cmd.okcount=0;
910                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, mrt*4) );  // mrt is in seconds... our SLEEP time is 250ms.. so * 4
911                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );  // 250msec delay
912                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TUNER_LOCKED_GOTO, cmd ) );
913                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +5 ) );
914                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -3) );  // goto loop start
915                                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
916                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_STOPPED) );
917                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +4) );
918                                         sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, tunetimeout) );
919                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
920                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -5) );
921                                         eDebug("set rotor timeout to %d seconds", mrt);
922                                 }
923                                 sec_fe->setData(eDVBFrontend::NEW_ROTOR_CMD, RotorCmd);
924                                 sec_fe->setData(eDVBFrontend::NEW_ROTOR_POS, sat.orbital_position);
925                         }
926
927                         if (doSetVoltageToneFrontend && !is_unicable)
928                         {
929                                 eSecCommand::pair compare;
930                                 compare.voltage = voltage;
931                                 compare.steps = +3;
932                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
933                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
934                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_VOLTAGE_CHANGE]) );
935                                 compare.tone = tone;
936                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
937                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
938                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) );
939                         }
940
941                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_SWITCHPARMS) );
942
943                         if (doSetFrontend)
944                         {
945                                 sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, tunetimeout) );
946                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
947                         }
948
949                         sec_sequence.push_front( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
950                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 500) );
951                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
952
953                         frontend.setSecSequence(sec_sequence);
954
955                         return 0;
956                 }
957         }
958         eDebugNoSimulate("found no useable satellite configuration for %s freq %d%s %s on orbital position (%d)",
959                 sat.system ? "DVB-S2" : "DVB-S",
960                 sat.frequency,
961                 sat.polarisation == eDVBFrontendParametersSatellite::Polarisation_Horizontal ? "H" :
962                         eDVBFrontendParametersSatellite::Polarisation_Vertical ? "V" :
963                         eDVBFrontendParametersSatellite::Polarisation_CircularLeft ? "CL" : "CR",
964                 sat.modulation == eDVBFrontendParametersSatellite::Modulation_Auto ? "AUTO" :
965                         eDVBFrontendParametersSatellite::Modulation_QPSK ? "QPSK" :
966                         eDVBFrontendParametersSatellite::Modulation_8PSK ? "8PSK" : "QAM16",
967                 sat.orbital_position );
968         return -1;
969 }
970
971 void eDVBSatelliteEquipmentControl::prepareTurnOffSatCR(iDVBFrontend &frontend, int satcr)
972 {
973         eSecCommandList sec_sequence;
974
975         // check if voltage is disabled
976         eSecCommand::pair compare;
977         compare.steps = +9;     //only close frontend
978         compare.voltage = iDVBFrontend::voltageOff;
979
980         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
981         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
982         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
983
984         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
985         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
986         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );
987
988         eDVBDiseqcCommand diseqc;
989         memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
990         diseqc.len = 5;
991         diseqc.data[0] = 0xE0;
992         diseqc.data[1] = 0x10;
993         diseqc.data[2] = 0x5A;
994         diseqc.data[3] = satcr << 5;
995         diseqc.data[4] = 0x00;
996
997         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
998         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
999         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
1000         sec_sequence.push_back( eSecCommand(eSecCommand::DELAYED_CLOSE_FRONTEND) );
1001
1002         frontend.setSecSequence(sec_sequence);
1003 }
1004
1005 RESULT eDVBSatelliteEquipmentControl::clear()
1006 {
1007         eSecDebug("eDVBSatelliteEquipmentControl::clear()");
1008         for (int i=0; i <= m_lnbidx; ++i)
1009         {
1010                 m_lnbs[i].m_satellites.clear();
1011                 m_lnbs[i].m_slot_mask = 0;
1012                 m_lnbs[i].m_prio = -1; // auto
1013         }
1014         m_lnbidx=-1;
1015
1016         m_not_linked_slot_mask=0;
1017
1018         //reset some tuner configuration
1019         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
1020         {
1021                 it->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, -1);
1022                 it->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, -1);
1023                 it->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, -1);
1024                 it->m_frontend->setData(eDVBFrontend::ROTOR_POS, -1);
1025                 it->m_frontend->setData(eDVBFrontend::ROTOR_CMD, -1);
1026                 it->m_frontend->setData(eDVBFrontend::SATCR, -1);
1027         }
1028
1029         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
1030         {
1031                 it->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, -1);
1032                 it->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, -1);
1033                 it->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, -1);
1034                 it->m_frontend->setData(eDVBFrontend::ROTOR_POS, -1);
1035                 it->m_frontend->setData(eDVBFrontend::ROTOR_CMD, -1);
1036                 it->m_frontend->setData(eDVBFrontend::SATCR, -1);
1037         }
1038
1039         return 0;
1040 }
1041
1042 /* LNB Specific Parameters */
1043 RESULT eDVBSatelliteEquipmentControl::addLNB()
1044 {
1045         if ( (m_lnbidx+1) < (int)(sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters)))
1046                 m_curSat=m_lnbs[++m_lnbidx].m_satellites.end();
1047         else
1048         {
1049                 eDebug("no more LNB free... cnt is %d", m_lnbidx);
1050                 return -ENOSPC;
1051         }
1052         eSecDebug("eDVBSatelliteEquipmentControl::addLNB(%d)", m_lnbidx);
1053         return 0;
1054 }
1055
1056 RESULT eDVBSatelliteEquipmentControl::setLNBSlotMask(int slotmask)
1057 {
1058         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSlotMask(%d)", slotmask);
1059         if ( currentLNBValid() )
1060                 m_lnbs[m_lnbidx].m_slot_mask = slotmask;
1061         else
1062                 return -ENOENT;
1063         return 0;
1064 }
1065
1066 RESULT eDVBSatelliteEquipmentControl::setLNBLOFL(int lofl)
1067 {
1068         eSecDebug("eDVBSatelliteEquipmentControl::setLNBLOFL(%d)", lofl);
1069         if ( currentLNBValid() )
1070                 m_lnbs[m_lnbidx].m_lof_lo = lofl;
1071         else
1072                 return -ENOENT;
1073         return 0;
1074 }
1075
1076 RESULT eDVBSatelliteEquipmentControl::setLNBLOFH(int lofh)
1077 {
1078         eSecDebug("eDVBSatelliteEquipmentControl::setLNBLOFH(%d)", lofh);
1079         if ( currentLNBValid() )
1080                 m_lnbs[m_lnbidx].m_lof_hi = lofh;
1081         else
1082                 return -ENOENT;
1083         return 0;
1084 }
1085
1086 RESULT eDVBSatelliteEquipmentControl::setLNBThreshold(int threshold)
1087 {
1088         eSecDebug("eDVBSatelliteEquipmentControl::setLNBThreshold(%d)", threshold);
1089         if ( currentLNBValid() )
1090                 m_lnbs[m_lnbidx].m_lof_threshold = threshold;
1091         else
1092                 return -ENOENT;
1093         return 0;
1094 }
1095
1096 RESULT eDVBSatelliteEquipmentControl::setLNBIncreasedVoltage(bool onoff)
1097 {
1098         eSecDebug("eDVBSatelliteEquipmentControl::setLNBIncreasedVoltage(%d)", onoff);
1099         if ( currentLNBValid() )
1100                 m_lnbs[m_lnbidx].m_increased_voltage = onoff;
1101         else
1102                 return -ENOENT;
1103         return 0;
1104 }
1105
1106 RESULT eDVBSatelliteEquipmentControl::setLNBPrio(int prio)
1107 {
1108         eSecDebug("eDVBSatelliteEquipmentControl::setLNBPrio(%d)", prio);
1109         if ( currentLNBValid() )
1110                 m_lnbs[m_lnbidx].m_prio = prio;
1111         else
1112                 return -ENOENT;
1113         return 0;
1114 }
1115
1116 RESULT eDVBSatelliteEquipmentControl::setLNBNum(int LNBNum)
1117 {
1118         eSecDebug("eDVBSatelliteEquipmentControl::setLNBNum(%d)", LNBNum);
1119         if(!((LNBNum >= 1) && (LNBNum <= MAX_LNBNUM)))
1120                 return -EPERM;
1121         if ( currentLNBValid() )
1122                 m_lnbs[m_lnbidx].LNBNum = LNBNum;
1123         else
1124                 return -ENOENT;
1125         return 0;
1126 }
1127
1128 /* DiSEqC Specific Parameters */
1129 RESULT eDVBSatelliteEquipmentControl::setDiSEqCMode(int diseqcmode)
1130 {
1131         eSecDebug("eDVBSatelliteEquipmentControl::setDiSEqcMode(%d)", diseqcmode);
1132         if ( currentLNBValid() )
1133                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_diseqc_mode = (eDVBSatelliteDiseqcParameters::t_diseqc_mode)diseqcmode;
1134         else
1135                 return -ENOENT;
1136         return 0;
1137 }
1138
1139 RESULT eDVBSatelliteEquipmentControl::setToneburst(int toneburst)
1140 {
1141         eSecDebug("eDVBSatelliteEquipmentControl::setToneburst(%d)", toneburst);
1142         if ( currentLNBValid() )
1143                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_toneburst_param = (eDVBSatelliteDiseqcParameters::t_toneburst_param)toneburst;
1144         else
1145                 return -ENOENT;
1146         return 0;
1147 }
1148
1149 RESULT eDVBSatelliteEquipmentControl::setRepeats(int repeats)
1150 {
1151         eSecDebug("eDVBSatelliteEquipmentControl::setRepeats(%d)", repeats);
1152         if ( currentLNBValid() )
1153                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_repeats=repeats;
1154         else
1155                 return -ENOENT;
1156         return 0;
1157 }
1158
1159 RESULT eDVBSatelliteEquipmentControl::setCommittedCommand(int command)
1160 {
1161         eSecDebug("eDVBSatelliteEquipmentControl::setCommittedCommand(%d)", command);
1162         if ( currentLNBValid() )
1163                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_committed_cmd=command;
1164         else
1165                 return -ENOENT;
1166         return 0;
1167 }
1168
1169 RESULT eDVBSatelliteEquipmentControl::setUncommittedCommand(int command)
1170 {
1171         eSecDebug("eDVBSatelliteEquipmentControl::setUncommittedCommand(%d)", command);
1172         if ( currentLNBValid() )
1173                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_uncommitted_cmd = command;
1174         else
1175                 return -ENOENT;
1176         return 0;
1177 }
1178
1179 RESULT eDVBSatelliteEquipmentControl::setCommandOrder(int order)
1180 {
1181         eSecDebug("eDVBSatelliteEquipmentControl::setCommandOrder(%d)", order);
1182         if ( currentLNBValid() )
1183                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_command_order=order;
1184         else
1185                 return -ENOENT;
1186         return 0;
1187 }
1188
1189 RESULT eDVBSatelliteEquipmentControl::setFastDiSEqC(bool onoff)
1190 {
1191         eSecDebug("eDVBSatelliteEquipmentControl::setFastDiSEqc(%d)", onoff);
1192         if ( currentLNBValid() )
1193                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_use_fast=onoff;
1194         else
1195                 return -ENOENT;
1196         return 0;
1197 }
1198
1199 RESULT eDVBSatelliteEquipmentControl::setSeqRepeat(bool onoff)
1200 {
1201         eSecDebug("eDVBSatelliteEquipmentControl::setSeqRepeat(%d)", onoff);
1202         if ( currentLNBValid() )
1203                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_seq_repeat = onoff;
1204         else
1205                 return -ENOENT;
1206         return 0;
1207 }
1208
1209 /* Rotor Specific Parameters */
1210 RESULT eDVBSatelliteEquipmentControl::setLongitude(float longitude)
1211 {
1212         eSecDebug("eDVBSatelliteEquipmentControl::setLongitude(%f)", longitude);
1213         if ( currentLNBValid() )
1214                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_longitude=longitude;
1215         else
1216                 return -ENOENT;
1217         return 0;
1218 }
1219
1220 RESULT eDVBSatelliteEquipmentControl::setLatitude(float latitude)
1221 {
1222         eSecDebug("eDVBSatelliteEquipmentControl::setLatitude(%f)", latitude);
1223         if ( currentLNBValid() )
1224                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_latitude=latitude;
1225         else
1226                 return -ENOENT;
1227         return 0;
1228 }
1229
1230 RESULT eDVBSatelliteEquipmentControl::setLoDirection(int direction)
1231 {
1232         eSecDebug("eDVBSatelliteEquipmentControl::setLoDirection(%d)", direction);
1233         if ( currentLNBValid() )
1234                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_lo_direction=direction;
1235         else
1236                 return -ENOENT;
1237         return 0;
1238 }
1239
1240 RESULT eDVBSatelliteEquipmentControl::setLaDirection(int direction)
1241 {
1242         eSecDebug("eDVBSatelliteEquipmentControl::setLaDirection(%d)", direction);
1243         if ( currentLNBValid() )
1244                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_la_direction=direction;
1245         else
1246                 return -ENOENT;
1247         return 0;
1248 }
1249
1250 RESULT eDVBSatelliteEquipmentControl::setUseInputpower(bool onoff)
1251 {
1252         eSecDebug("eDVBSatelliteEquipmentControl::setUseInputpower(%d)", onoff);
1253         if ( currentLNBValid() )
1254                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_use=onoff;
1255         else
1256                 return -ENOENT;
1257         return 0;
1258 }
1259
1260 RESULT eDVBSatelliteEquipmentControl::setInputpowerDelta(int delta)
1261 {
1262         eSecDebug("eDVBSatelliteEquipmentControl::setInputpowerDelta(%d)", delta);
1263         if ( currentLNBValid() )
1264                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_delta=delta;
1265         else
1266                 return -ENOENT;
1267         return 0;
1268 }
1269
1270 /* Unicable Specific Parameters */
1271 RESULT eDVBSatelliteEquipmentControl::setLNBSatCR(int SatCR_idx)
1272 {
1273         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCR(%d)", SatCR_idx);
1274         if(!((SatCR_idx >=-1) && (SatCR_idx < MAX_SATCR)))
1275                 return -EPERM;
1276         if ( currentLNBValid() )
1277                 m_lnbs[m_lnbidx].SatCR_idx = SatCR_idx;
1278         else
1279                 return -ENOENT;
1280         return 0;
1281 }
1282
1283 RESULT eDVBSatelliteEquipmentControl::setLNBSatCRvco(int SatCRvco)
1284 {
1285         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCRvco(%d)", SatCRvco);
1286         if(!((SatCRvco >= 950*1000) && (SatCRvco <= 2150*1000)))
1287                 return -EPERM;
1288         if(!((m_lnbs[m_lnbidx].SatCR_idx >= 0) && (m_lnbs[m_lnbidx].SatCR_idx < MAX_SATCR)))
1289                 return -ENOENT;
1290         if ( currentLNBValid() )
1291                 m_lnbs[m_lnbidx].SatCRvco = SatCRvco;
1292         else
1293                 return -ENOENT;
1294         return 0;
1295 }
1296
1297 RESULT eDVBSatelliteEquipmentControl::setLNBSatCRpositions(int SatCR_positions)
1298 {
1299         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCRpositions(%d)", SatCR_positions);
1300         if(SatCR_positions < 1 || SatCR_positions > 2)
1301                 return -EPERM;
1302         if ( currentLNBValid() )
1303                 m_lnbs[m_lnbidx].SatCR_positions = SatCR_positions;
1304         else
1305                 return -ENOENT;
1306         return 0;
1307 }
1308
1309 RESULT eDVBSatelliteEquipmentControl::getLNBSatCRpositions()
1310 {
1311         if ( currentLNBValid() )
1312                 return m_lnbs[m_lnbidx].SatCR_positions;
1313         return -ENOENT;
1314 }
1315
1316 RESULT eDVBSatelliteEquipmentControl::getLNBSatCR()
1317 {
1318         if ( currentLNBValid() )
1319                 return m_lnbs[m_lnbidx].SatCR_idx;
1320         return -ENOENT;
1321 }
1322
1323 RESULT eDVBSatelliteEquipmentControl::getLNBSatCRvco()
1324 {
1325         if ( currentLNBValid() )
1326                 return m_lnbs[m_lnbidx].SatCRvco;
1327         return -ENOENT;
1328 }
1329
1330 /* Satellite Specific Parameters */
1331 RESULT eDVBSatelliteEquipmentControl::addSatellite(int orbital_position)
1332 {
1333         eSecDebug("eDVBSatelliteEquipmentControl::addSatellite(%d)", orbital_position);
1334         if ( currentLNBValid() )
1335         {
1336                 std::map<int, eDVBSatelliteSwitchParameters>::iterator it =
1337                         m_lnbs[m_lnbidx].m_satellites.find(orbital_position);
1338                 if ( it == m_lnbs[m_lnbidx].m_satellites.end() )
1339                 {
1340                         std::pair<std::map<int, eDVBSatelliteSwitchParameters>::iterator, bool > ret =
1341                                 m_lnbs[m_lnbidx].m_satellites.insert(
1342                                         std::pair<int, eDVBSatelliteSwitchParameters>(orbital_position, eDVBSatelliteSwitchParameters())
1343                                 );
1344                         if ( ret.second )
1345                                 m_curSat = ret.first;
1346                         else
1347                                 return -ENOMEM;
1348                 }
1349                 else
1350                         return -EEXIST;
1351         }
1352         else
1353                 return -ENOENT;
1354         return 0;
1355 }
1356
1357 RESULT eDVBSatelliteEquipmentControl::setVoltageMode(int mode)
1358 {
1359         eSecDebug("eDVBSatelliteEquipmentControl::setVoltageMode(%d)", mode);
1360         if ( currentLNBValid() && m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1361                 m_curSat->second.m_voltage_mode = (eDVBSatelliteSwitchParameters::t_voltage_mode)mode;
1362         else
1363                 return -ENOENT;
1364         return 0;
1365
1366 }
1367
1368 RESULT eDVBSatelliteEquipmentControl::setToneMode(int mode)
1369 {
1370         eSecDebug("eDVBSatelliteEquipmentControl::setToneMode(%d)", mode);
1371         if ( currentLNBValid() )
1372         {
1373                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1374                         m_curSat->second.m_22khz_signal = (eDVBSatelliteSwitchParameters::t_22khz_signal)mode;
1375                 else
1376                         return -EPERM;
1377         }
1378         else
1379                 return -ENOENT;
1380         return 0;
1381 }
1382
1383 RESULT eDVBSatelliteEquipmentControl::setRotorPosNum(int rotor_pos_num)
1384 {
1385         eSecDebug("eDVBSatelliteEquipmentControl::setRotorPosNum(%d)", rotor_pos_num);
1386         if ( currentLNBValid() )
1387         {
1388                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1389                         m_curSat->second.m_rotorPosNum=rotor_pos_num;
1390                 else
1391                         return -EPERM;
1392         }
1393         else
1394                 return -ENOENT;
1395         return 0;
1396 }
1397
1398 RESULT eDVBSatelliteEquipmentControl::setRotorTurningSpeed(int speed)
1399 {
1400         eSecDebug("eDVBSatelliteEquipmentControl::setRotorTurningSpeed(%d)", speed);
1401         if ( currentLNBValid() )
1402                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_turning_speed = speed;
1403         else
1404                 return -ENOENT;
1405         return 0;
1406 }
1407
1408 struct sat_compare
1409 {
1410         int orb_pos, lofl, lofh;
1411         sat_compare(int o, int lofl, int lofh)
1412                 :orb_pos(o), lofl(lofl), lofh(lofh)
1413         {}
1414         sat_compare(const sat_compare &x)
1415                 :orb_pos(x.orb_pos), lofl(x.lofl), lofh(x.lofh)
1416         {}
1417         bool operator < (const sat_compare & cmp) const
1418         {
1419                 if (orb_pos == cmp.orb_pos)
1420                 {
1421                         if ( abs(lofl-cmp.lofl) < 200000 )
1422                         {
1423                                 if (abs(lofh-cmp.lofh) < 200000)
1424                                         return false;
1425                                 return lofh<cmp.lofh;
1426                         }
1427                         return lofl<cmp.lofl;
1428                 }
1429                 return orb_pos < cmp.orb_pos;
1430         }
1431 };
1432
1433 RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
1434 {
1435         eSecDebug("eDVBSatelliteEquipmentControl::setTunerLinked(%d, %d)", tu1, tu2);
1436         if (tu1 != tu2)
1437         {
1438                 eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1439                 eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
1440                 for (; it != m_avail_frontends.end(); ++it)
1441                 {
1442                         if (it->m_frontend->getSlotID() == tu1)
1443                                 p1 = *it;
1444                         else if (it->m_frontend->getSlotID() == tu2)
1445                                 p2 = *it;
1446                 }
1447                 if (p1 && p2)
1448                 {
1449                         p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
1450                         p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
1451                 }
1452
1453                 p1=p2=NULL;
1454                 it=m_avail_simulate_frontends.begin();
1455                 for (; it != m_avail_simulate_frontends.end(); ++it)
1456                 {
1457                         if (it->m_frontend->getSlotID() == tu1)
1458                                 p1 = *it;
1459                         else if (it->m_frontend->getSlotID() == tu2)
1460                                 p2 = *it;
1461                 }
1462                 if (p1 && p2)
1463                 {
1464                         p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
1465                         p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
1466                         return 0;
1467                 }
1468         }
1469         return -1;
1470 }
1471
1472 RESULT eDVBSatelliteEquipmentControl::setTunerDepends(int tu1, int tu2)
1473 {
1474         eSecDebug("eDVBSatelliteEquipmentControl::setTunerDepends(%d, %d)", tu1, tu2);
1475         if (tu1 == tu2)
1476                 return -1;
1477
1478         eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1479
1480         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
1481         {
1482                 if (it->m_frontend->getSlotID() == tu1)
1483                         p1 = *it;
1484                 else if (it->m_frontend->getSlotID() == tu2)
1485                         p2 = *it;
1486         }
1487         if (p1 && p2)
1488         {
1489                 p1->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p2);
1490                 p2->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p1);
1491         }
1492
1493         p1=p2=NULL;
1494         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
1495         {
1496                 if (it->m_frontend->getSlotID() == tu1)
1497                         p1 = *it;
1498                 else if (it->m_frontend->getSlotID() == tu2)
1499                         p2 = *it;
1500         }
1501         if (p1 && p2)
1502         {
1503                 p1->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p2);
1504                 p2->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p1);
1505                 return 0;
1506         }
1507
1508         return -1;
1509 }
1510
1511 void eDVBSatelliteEquipmentControl::setSlotNotLinked(int slot_no)
1512 {
1513         eSecDebug("eDVBSatelliteEquipmentControl::setSlotNotLinked(%d)", slot_no);
1514         m_not_linked_slot_mask |= (1 << slot_no);
1515 }
1516
1517 bool eDVBSatelliteEquipmentControl::isRotorMoving()
1518 {
1519         return m_rotorMoving;
1520 }
1521
1522 void eDVBSatelliteEquipmentControl::setRotorMoving(int slot_no, bool b)
1523 {
1524         if (b)
1525                 m_rotorMoving |= (1 << slot_no);
1526         else
1527                 m_rotorMoving &= ~(1 << slot_no);
1528 }