Statistics
| Branch: | Tag: | Revision:

dvbd / src / tune.c @ a24dbbce

History | View | Annotate | Download (8.81 KB)

1
/* dvbtune - tune.c
2

3
   Copyright (C) Dave Chapman 2001,2002
4
  
5
   This program is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU General Public License
7
   as published by the Free Software Foundation; either version 2
8
   of the License, or (at your option) any later version.
9

10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14

15
   You should have received a copy of the GNU General Public License
16
   along with this program; if not, write to the Free Software
17
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
   Or, point your browser to http://www.gnu.org/copyleft/gpl.html
19

20
*/
21
   
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <stdint.h>
25
#include <ctype.h>
26
#include <sys/ioctl.h>
27
#include <sys/poll.h>
28
#include <unistd.h>
29
#include <error.h>
30
#include <time.h>
31
#include <errno.h>
32

    
33
#include <linux/dvb/dmx.h>
34
#include <linux/dvb/frontend.h>
35

    
36
#include "tune.h"
37

    
38

    
39
void print_status(FILE* fd,fe_status_t festatus) {
40
  fprintf(fd,"FE_STATUS:");
41
  if (festatus & FE_HAS_SIGNAL) fprintf(fd," FE_HAS_SIGNAL");
42
  if (festatus & FE_TIMEDOUT) fprintf(fd," FE_TIMEDOUT");
43
  if (festatus & FE_HAS_LOCK) fprintf(fd," FE_HAS_LOCK");
44
  if (festatus & FE_HAS_CARRIER) fprintf(fd," FE_HAS_CARRIER");
45
  if (festatus & FE_HAS_VITERBI) fprintf(fd," FE_HAS_VITERBI");
46
  if (festatus & FE_HAS_SYNC) fprintf(fd," FE_HAS_SYNC");
47
  fprintf(fd,"\n");
48
}
49

    
50

    
51
struct diseqc_cmd {
52
   struct dvb_diseqc_master_cmd cmd;
53
   uint32_t wait;
54
};
55

    
56
static int diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd *cmd,
57
                     fe_sec_tone_mode_t t, unsigned char sat_no)
58
{
59
   if(ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) < 0)
60
           return -1;
61
   if(ioctl(fd, FE_SET_VOLTAGE, v) < 0)
62
           return -1;
63
   usleep(15 * 1000);
64
   if(sat_no >= 1 && sat_no <= 4)        //1.x compatible equipment
65
   {
66
    if(ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd) < 0)
67
           return -1;
68
    usleep(cmd->wait * 1000);
69
    usleep(15 * 1000);
70
   }
71
   else        //A or B simple diseqc
72
   {
73
    fprintf(stderr, "SETTING SIMPLE %c BURST\n", sat_no);
74
    if(ioctl(fd, FE_DISEQC_SEND_BURST, (sat_no == 'B' ? SEC_MINI_B : SEC_MINI_A)) < 0)
75
           return -1;
76
    usleep(15 * 1000);
77
   }
78
   if(ioctl(fd, FE_SET_TONE, t) < 0)
79
           return -1;
80

    
81
   return 0;
82
}
83

    
84
/* digital satellite equipment control,
85
 * specification is available from http://www.eutelsat.com/ 
86
 */
87

    
88
static int do_diseqc(int fd, unsigned char sat_no, int polv, int hi_lo)
89
{
90
    struct diseqc_cmd cmd =  { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
91

    
92
    if(sat_no != 0)
93
    {
94
        unsigned char d = sat_no;
95

    
96
        /* param: high nibble: reset bits, low nibble set bits,
97
        * bits are: option, position, polarizaion, band
98
        */
99
        sat_no--;
100
        cmd.cmd.msg[3] =
101
                0xf0 | (((sat_no * 4) & 0x0f) | (polv ? 0 : 2) | (hi_lo ? 1 : 0));
102

    
103
        return diseqc_send_msg(fd, 
104
                    polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18,
105
                    &cmd, 
106
                    hi_lo ? SEC_TONE_ON : SEC_TONE_OFF, 
107
                    d);
108
    }
109
    else         //only tone and voltage
110
    {
111
        fe_sec_voltage_t voltage;
112
        
113
        fprintf(stderr, "Setting only tone %s and voltage %dV\n", (hi_lo ? "ON" : "OFF"), (polv ? 13 : 18));
114
        
115
        if(ioctl(fd, FE_SET_VOLTAGE, (polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18)) < 0)
116
               return -1;
117
            
118
        if(ioctl(fd, FE_SET_TONE, (hi_lo ? SEC_TONE_ON : SEC_TONE_OFF)) < 0)
119
               return -1;
120
        
121
        usleep(15 * 1000);
122
        
123
        return 0;
124
    }
125
}
126

    
127
int check_status(int fd_frontend,int type, struct dvb_frontend_parameters* feparams,unsigned int base) {
128
  int32_t strength;
129
  fe_status_t festatus;
130
  struct pollfd pfd[1];
131
  int status, locks=0, ok=0;
132
  time_t tm1, tm2;
133

    
134
  if (ioctl(fd_frontend,FE_SET_FRONTEND,feparams) < 0) {
135
    perror("ERROR tuning channel\n");
136
    return -1;
137
  }
138

    
139
  pfd[0].fd = fd_frontend;
140
  pfd[0].events = POLLPRI;
141

    
142
  tm1 = tm2 = time((time_t*) NULL);
143
  fprintf(stderr,"Getting frontend status\n");
144
  while (!ok) {
145
    festatus = 0;
146
    if (poll(pfd,1,3000) > 0){
147
      if (pfd[0].revents & POLLPRI){
148
        if(ioctl(fd_frontend,FE_READ_STATUS,&festatus) >= 0)
149
          if(festatus & FE_HAS_LOCK)
150
            locks++;
151
      }
152
    }
153
    usleep(10000);
154
    tm2 = time((time_t*) NULL);
155
    if((festatus & FE_TIMEDOUT) || (locks >= 2) || (tm2 - tm1 >= 3))
156
            ok = 1;
157
  }
158

    
159
  if (festatus & FE_HAS_LOCK) {
160
      if(ioctl(fd_frontend,FE_GET_FRONTEND,feparams) >= 0) {
161
        switch(type) {
162
         case FE_OFDM:
163
           fprintf(stderr,"Event:  Frequency: %d\n",feparams->frequency);
164
           break;
165
         case FE_QPSK:
166
           fprintf(stderr,"Event:  Frequency: %d\n",(unsigned int)(feparams->frequency + base));
167
           fprintf(stderr,"        SymbolRate: %d\n",feparams->u.qpsk.symbol_rate);
168
           fprintf(stderr,"        FEC_inner:  %d\n",feparams->u.qpsk.fec_inner);
169
           fprintf(stderr,"\n");
170
           break;
171
         case FE_QAM:
172
           fprintf(stderr,"Event:  Frequency: %d\n",feparams->frequency);
173
           fprintf(stderr,"        SymbolRate: %d\n",feparams->u.qpsk.symbol_rate);
174
           fprintf(stderr,"        FEC_inner:  %d\n",feparams->u.qpsk.fec_inner);
175
           break;
176
#ifdef DVB_ATSC
177
        case FE_ATSC:
178
           fprintf(stderr, "Event:  Frequency: %d\n",feparams->frequency);
179
           fprintf(stderr, "        Modulation: %d\n",feparams->u.vsb.modulation);
180
           break;
181
#endif
182
         default:
183
           break;
184
        }
185
      }
186

    
187
      strength=0;
188
      if(ioctl(fd_frontend,FE_READ_BER,&strength) >= 0)
189
        fprintf(stderr,"Bit error rate: %d\n",strength);
190

    
191
      strength=0;
192
      if(ioctl(fd_frontend,FE_READ_SIGNAL_STRENGTH,&strength) >= 0)
193
        fprintf(stderr,"Signal strength: %d\n",strength);
194

    
195
      strength=0;
196
      if(ioctl(fd_frontend,FE_READ_SNR,&strength) >= 0)
197
        fprintf(stderr,"SNR: %d\n",strength);
198
      
199
      strength=0;
200
      if(ioctl(fd_frontend,FE_READ_UNCORRECTED_BLOCKS,&strength) >= 0)
201
        fprintf(stderr,"UNC: %d\n",strength);
202

    
203
      print_status(stderr,festatus);
204
    } else {
205
    fprintf(stderr,"Not able to lock to the signal on the given frequency\n");
206
    return -1;
207
  }
208
  return 0;
209
}
210

    
211
int tune_it(int fd_frontend, unsigned int freq, unsigned int srate, char pol, int tone, fe_spectral_inversion_t specInv, unsigned char diseqc,fe_modulation_t modulation,fe_code_rate_t HP_CodeRate,fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth, fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier) {
212
  int res, hi_lo, dfd;
213
  unsigned int base;
214
  struct dvb_frontend_parameters feparams;
215
  struct dvb_frontend_info fe_info;
216

    
217
  if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0)){
218
     perror("FE_GET_INFO: ");
219
     return -1;
220
  }
221
  
222
  fprintf(stderr,"Using DVB card \"%s\", freq=%d\n",fe_info.name, freq);
223

    
224
  if (freq < 1000000) freq*=1000UL;
225
  switch(fe_info.type) {
226
    case FE_OFDM:
227
      feparams.frequency=freq;
228
      feparams.inversion=specInv;
229
      feparams.u.ofdm.bandwidth=bandwidth;
230
      feparams.u.ofdm.code_rate_HP=HP_CodeRate;
231
      feparams.u.ofdm.code_rate_LP=LP_CodeRate;
232
      feparams.u.ofdm.constellation=modulation;
233
      feparams.u.ofdm.transmission_mode=TransmissionMode;
234
      feparams.u.ofdm.guard_interval=guardInterval;
235
      feparams.u.ofdm.hierarchy_information=hier;
236
      fprintf(stderr,"tuning DVB-T (%s) to %d Hz, Bandwidth: %d\n",DVB_T_LOCATION,freq, 
237
        bandwidth==BANDWIDTH_8_MHZ ? 8 : (bandwidth==BANDWIDTH_7_MHZ ? 7 : 6));
238
      break;
239
    case FE_QPSK:
240
            pol = toupper(pol);
241
        if (freq > 2200000) {
242
        if (freq < SLOF) {
243
          feparams.frequency=(freq-LOF1);
244
          hi_lo = 0;
245
          base = LOF1;
246
        } else {
247
          feparams.frequency=(freq-LOF2);
248
          hi_lo = 1;
249
          base = LOF2;
250
      } 
251
      } else {
252
          feparams.frequency=freq;
253
          base = 0;
254
      }
255

    
256
      fprintf(stderr,"tuning DVB-S to Freq: %u, Pol:%c Srate=%d, 22kHz tone=%s, LNB: %d\n",feparams.frequency,pol,srate,tone == SEC_TONE_ON ? "on" : "off", diseqc);
257
      feparams.inversion=specInv;
258
      feparams.u.qpsk.symbol_rate=srate;
259
      feparams.u.qpsk.fec_inner=FEC_AUTO;
260
      dfd = fd_frontend;
261

    
262
   if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0)
263
        fprintf(stderr, "DISEQC SETTING SUCCEDED\n");
264
   else  {
265
        fprintf(stderr, "DISEQC SETTING FAILED\n");
266
          return -1;
267
        }
268
      break;
269
    case FE_QAM:
270
      fprintf(stderr,"tuning DVB-C to %d, srate=%d\n",freq,srate);
271
      feparams.frequency=freq;
272
      feparams.inversion=INVERSION_OFF;
273
      feparams.u.qam.symbol_rate = srate;
274
      feparams.u.qam.fec_inner = FEC_AUTO;
275
      feparams.u.qam.modulation = modulation;
276
      break;
277
#ifdef DVB_ATSC
278
    case FE_ATSC:
279
      fprintf(stderr, "tuning ATSC to %d, modulation=%d\n",freq,modulation);
280
      feparams.frequency=freq;
281
      feparams.u.vsb.modulation = modulation;
282
      break;
283
#endif
284
    default:
285
      fprintf(stderr,"Unknown FE type. Aborting\n");
286
      exit(-1);
287
  }
288
  usleep(100000);
289

    
290
  return(check_status(fd_frontend,fe_info.type,&feparams,base));
291
}