Mailing List archive

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

[linux-dvb] Re: Channel switching



Klaus Schmidinger wrote:
> 
> I therefore commented out the checks whether the settings have actually changed,
> so that the tuning commands would always be sent to the DVB card. The result was
> that still sometimes channels don't sync at the first attempt, but (as far as I
> have seen in my tests) they always sync when VDR retries tuning to the same channel.
...
> --- dvb.c.001   Fri Sep  7 08:21:43 2001
> +++ dvb.c       Sat Sep  8 11:28:02 2001
> @@ -2771,16 +2772,20 @@
>  {
>          switch (dvb->dvbtype) {
>          case DVB_S:
> +/*
>                  if (dvb->front.srate!=dvb->new_srate ||
>                      dvb->front.fec!=dvb->new_fec) {

                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Since your ctest.c uses FEC_AUTO, and fe_lock() reads the real FEC
from the frontend into dvb->front.fec, this test will always
evaluate to TRUE, and the demodulator parameters will be always be set.

*Except* when the previous channel failed to sync. Then, dvb->front.fec
will keep the FEC_AUTO value, which explains why your retries had no effect.

The datasheet for the VES1893 and stv0299 say that they continuously
try to sync, so it shouldn't make much of a difference...

> +*/
>                          dvb->front.srate=dvb->new_srate;
>                          dvb->front.fec=dvb->new_fec;
>                          demod_command(dvb, DVB_SET_FRONTEND, &dvb->front);
>                          //if (dvb->demod_type==DVB_DEMOD_STV0299)
>                                  demod_command(dvb, DVB_RESET, 0);
> +/*
>                  }
>                  if (dvb->front.freq==dvb->new_freq && fe_lock(dvb))
>                          return mon_complete(dvb);
> +*/
> 
>                  dvb->front.freq=dvb->new_freq;
>                  tuner_command(dvb, TUNER_SET_TVFREQ, &dvb->front.freq);


My understanding of the DVB hardware suggests to set the tuner
before setting the demodulator, but again, the VES1893 and stv0299
should be able to sync anyway.

I added some debug prints to the driver's tuning code to find out what
it actually does. It showed that there were a lot of
zig-zag scans. I tentatively tried to improve the tuning code by
- doing the tuner_command first
- always doing a DVB_RESET after a tuner_command or a demod_command

With this modificatons, fe_lock() almost always returns TRUE on
the first try with ctest and with my own test progams, and I don't
get any failed syncs anymore.

I append a patch against the current CVS which includes my debug
prints.

Note: I only tested DVB-S, not DVB-C.


Index: dvb.c
===================================================================
RCS file: /cvs/linuxtv/DVB/driver/dvb.c,v
retrieving revision 1.91
diff -u -r1.91 dvb.c
--- dvb.c	2001/09/06 19:28:29	1.91
+++ dvb.c	2001/09/10 17:42:28
@@ -2678,6 +2678,13 @@
         {
                 struct qpskEvent ev;
                 
+                printk(KERN_DEBUG "mon_complete: freq=%d, sr=%d, "
+                       "realfreq=%d, step=%-2d, fdiff=%d, fec=%d\n",
+                       dvb->front.freq, dvb->front.srate,
+                       dvb->front.curfreq,
+                       dvb->mon_fstate,
+                       (dvb->front.curfreq - dvb->front.freq),
+                       dvb->front.fec);
                 ev.type=FE_COMPLETION_EV;
                 ev.u.completionEvent.iFrequency=dvb->front.freq/1000;
                 ev.u.completionEvent.SymbolRate=dvb->front.srate;
@@ -2719,6 +2726,8 @@
                 dvb->mon_tuning=0;
                 ev.type=FE_FAILURE_EV;
                 add_qpsk_event(&dvb->qpsk, &ev);
+                printk(KERN_DEBUG "mon_fail: freq=%d, sr=%d\n",
+                       dvb->front.freq, dvb->front.srate);
                 break;
         }
         case DVB_C:
@@ -2739,9 +2748,10 @@
 mon_zigzag(struct dvb_struct *dvb)
 {
         int i=dvb->mon_fstate;
-        u32 sfreq=dvb->front.curfreq=dvb->front.freq;
+        u32 sfreq=dvb->front.freq;
         u32 soff=dvb->front.srate/16;
         
+        printk("mon_zigzag: i=%d freq=%d\n", i, sfreq);
         if (fe_lock(dvb)) 
                 return mon_complete(dvb);
         if (i==20) 
@@ -2769,31 +2779,43 @@
 static int 
 mon_tune(struct dvb_struct *dvb)
 {
+        int kickit = 0, locked = 0;
+
+        printk("mon_tune\n");
         switch (dvb->dvbtype) {
         case DVB_S:
-                if (dvb->front.srate!=dvb->new_srate || 
-                    dvb->front.fec!=dvb->new_fec) {
-                        dvb->front.srate=dvb->new_srate;
-                        dvb->front.fec=dvb->new_fec;
-                        demod_command(dvb, DVB_SET_FRONTEND, &dvb->front); 
-                        //if (dvb->demod_type==DVB_DEMOD_STV0299) 
-                                demod_command(dvb, DVB_RESET, 0); 
-                } 
-                if (dvb->front.freq==dvb->new_freq && fe_lock(dvb))
-                        return mon_complete(dvb);
-
-                dvb->front.freq=dvb->new_freq;
-                tuner_command(dvb, TUNER_SET_TVFREQ, &dvb->front.freq); 
-                if (dvb->demod_type==DVB_DEMOD_STV0299) 
-                        demod_command(dvb, DVB_RESET, 0); 
+                locked = fe_lock(dvb);
+                if (! locked || dvb->front.freq != dvb->new_freq) {
+                        printk("mon_tune: TUNER_SET_TVFREQ\n");
+                        dvb->front.freq = dvb->new_freq;
+                        tuner_command(dvb, TUNER_SET_TVFREQ, &dvb->front.freq);
+                        kickit = 1;
+                }
+                /* if locked == 1, dvb->front.fec is guaranteed to be != FEC_AUTO,
+                 * so using FEC_AUTO will always reset the demod
+                 */
+                if (!locked
+                    || dvb->front.srate != dvb->new_srate
+                    || dvb->front.fec != dvb->new_fec) {
+                        dvb->front.srate = dvb->new_srate;
+                        dvb->front.fec = dvb->new_fec;
+                        printk("mon_tune: DVB_SET_FRONTEND\n");
+                        demod_command(dvb, DVB_SET_FRONTEND, &dvb->front);
+                        kickit = 1;
+                }
+                if (kickit)
+                        demod_command(dvb, DVB_RESET, 0);
                 dprintk("freq=%d\n", dvb->new_freq);
                 mdelay(10);
-                if (fe_lock(dvb)) 
+                dvb->mon_fstate = 1;
+                dvb->front.curfreq = dvb->front.freq;
+                if (fe_lock(dvb)) {
+                        printk("mon_tune: locked on 1st try\n");
                         return mon_complete(dvb);
+                }
+                printk("need zigzag, freq=%d\n", dvb->new_freq);
                 dvb->mon_tuning=2;
-                dvb->mon_fstate=1;
                 dvb->mon_delay=HZ/10;
-                dvb->front.curfreq=dvb->front.freq;
                 return 0;
         case DVB_C:
         case DVB_T:
===================================================================


I also patched ctest to
- log each channel switch via syslog, so i can match it with
  the driver log
- set FEC explicitly, not via FEC_AUTO


===================================================================
--- ctest.c	Mon Sep 10 15:58:49 2001
+++ ctest-km.c	Mon Sep 10 17:32:40 2001
@@ -11,7 +11,6 @@
 #include <sys/ioctl.h>
 #include <sys/poll.h>
 #include <unistd.h>
-#include <syslog.h>
 
 #define LOG_ERROR   fprintf(stderr, "\nERROR (%s,%d): %m\n", __FILE__, __LINE__);
 #define CHECK(s) { if ((s) < 0) LOG_ERROR; } // used for 'ioctl()' calls
@@ -20,7 +19,6 @@
   char *name;
   int freq;
   char pol;
-  int fec;
   int diseqc;
   int srate;
   int vpid;
@@ -31,14 +29,14 @@
 tChannel SatChannels[] = {
 #define XXX
 #ifdef XXX
-  { "RTL", 12188, 'h', 3, 0, 27500, 163, 104, 105 },
-  { "Sat.1", 12480, 'v', 3, 0, 27500, 1791, 1792, 34 },
-  { "Pro-7", 12480, 'v', 3, 0, 27500, 255, 256, 32 },
-  { "ORF1", 12692, 'h', 4, 0, 22000, 160, 161, 165 },
-  { "DW TV", 12363, 'v', 3, 0, 27500, 305, 306, 0 },
-  { "BLOOMBERG TV", 11817, 'v', 3, 0, 27500, 163, 92, 0 },
-  { "Premiere World Promo", 11798, 'h', 3, 0, 27500, 255, 256, 0 },
-  { "13th Street", 11797, 'h', 3, 0, 27500, 2303, 2304, 0 },
+  { "RTL", 12188, 'h', 0, 27500, 163, 104, 105 },
+  { "Sat.1", 12480, 'v', 0, 27500, 1791, 1792, 34 },
+  { "Pro-7", 12480, 'v', 0, 27500, 255, 256, 32 },
+  { "ORF1", 12692, 'h', 0, 22000, 160, 161, 165 },
+  { "DW TV", 12363, 'v', 0, 27500, 305, 306, 0 },
+  { "BLOOMBERG TV", 11817, 'v', 0, 27500, 163, 92, 0 },
+  { "Premiere World Promo", 11798, 'h', 0, 27500, 255, 256, 0 },
+  { "13th Street", 11797, 'h', 0, 27500, 2303, 2304, 0 },
 /*
   { "ORF1", 12692, 'h', 0, 22000, 160, 161, 165 },
   { "DW TV", 12363, 'v', 0, 27500, 305, 306, 0 },
@@ -388,7 +386,7 @@
   fprintf(stderr, "P");//XXX
 }
 
-bool SetChannel(int FrequencyMHz, char Polarization, int Fec, int Diseqc, int Srate, int Vpid, int Apid, int Tpid)
+bool SetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Tpid)
 {
   bool ChannelSynced = false;
 
@@ -430,7 +428,7 @@
      qpskParameters qpsk;
      qpsk.iFrequency = freq * 1000UL;
      qpsk.SymbolRate = Srate * 1000UL;
-     qpsk.FEC_inner = Fec;
+     qpsk.FEC_inner = FEC_AUTO;
 
      int volt = (Polarization == 'v' || Polarization == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
 
@@ -539,15 +537,13 @@
 
 int main(void)
 {
-  openlog("ctest", 0, LOG_KERN);
   OpenFiles();
   for (;;) {
       tChannel *ch = (fd_qpskfe >= 0) ? SatChannels : CableChannels;
       while (ch->name) {
             fprintf(stderr, "tuning to %s\t", ch->name);
-            syslog(LOG_KERN | LOG_DEBUG, "tuning to %s", ch->name);
             for (int i = 0; i < 3; i++) {
-                if (SetChannel(ch->freq, ch->pol, ch->fec, ch->diseqc, ch->srate, ch->vpid, ch->apid, ch->tpid))
+                if (SetChannel(ch->freq, ch->pol, ch->diseqc, ch->srate, ch->vpid, ch->apid, ch->tpid))
                    break;
                 sleep(1);
                 }
===================================================================



Regards,
Johannes


-- 
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe linux-dvb" as subject.


Home | Main Index | Thread Index