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