Add radio tuning test app
[rdstmc.git] / tuning / tuning.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <sys/ioctl.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <time.h>
9
10 #include <linux/videodev2.h>
11
12 #include <sqlite3.h>
13
14 #include "rds.h"
15 #include "tmc.h"
16
17 sqlite3 *lcl_db;
18 int OutputFlags;
19
20 unsigned char pi_received = 0;
21 unsigned char sid_received = 0;
22
23 void test_rds_PI_cb(unsigned short PI, unsigned char ccode, unsigned char ptype, unsigned char pref, void *udata)
24 {
25         printf("New PI=%d ccode=%X ptype=%X '%s' '%s' pref=%d\n", PI, ccode, ptype, ptype_stext[ptype], ptype_ltext[ptype], pref);
26         pi_received = 1;
27 }
28
29 void test_rds_sname_cb(char *sname, void *udata)
30 {
31         printf("RDS sname='%s'\n", sname);
32         sid_received = 1;
33 }
34
35
36 void station_scan(int fd)
37 {
38 int ret;
39 struct v4l2_frequency v4lfreq;
40 struct v4l2_tuner v4ltuner;
41 unsigned short rdsgroup[4];
42
43         v4ltuner.index = 0;
44         ret = ioctl(fd, VIDIOC_G_TUNER, &v4ltuner);
45         if (ret < 0)
46                 return;
47         printf("tuner=%d\n", v4ltuner.index);
48         if (v4ltuner.type == V4L2_TUNER_RADIO)
49                 printf("  is a radio tuner\n");
50         printf("name='%s'\n", v4ltuner.name);
51
52         v4lfreq.tuner = v4ltuner.index;
53         memset(&v4lfreq.reserved, 0, 32);
54         ret = ioctl(fd, VIDIOC_G_FREQUENCY, &v4lfreq);
55         if (ret < 0)
56                 return;
57
58         v4lfreq.frequency = v4ltuner.rangelow;
59         while (v4lfreq.frequency <= v4ltuner.rangehigh) {
60                         ret = ioctl(fd, VIDIOC_S_FREQUENCY, &v4lfreq);
61                         if (ret < 0)
62                                 break;
63                         ret = ioctl(fd, VIDIOC_G_FREQUENCY, &v4lfreq);
64                         if (ret < 0)
65                                 break;
66                                 ret = ioctl(fd, VIDIOC_G_TUNER, &v4ltuner);
67                         if (ret < 0)
68                                 break;
69                         printf("%lf %d %d %s %s\n", (double)v4lfreq.frequency * 62.5 / 1000000,
70                                 v4lfreq.frequency,
71                                 v4ltuner.signal,
72                                 v4ltuner.rxsubchans & V4L2_TUNER_SUB_STEREO ? "stereo" : "mono",
73                                 v4ltuner.rxsubchans & V4L2_TUNER_SUB_RDS ? "RDS" : "noRDS");
74
75                         if (v4ltuner.signal > 30000) {
76                                 /* seems to be a strong signal, so try RDS */
77                                 pi_received = 0;
78                                 sid_received = 0;
79                                 rds_radio_retuned();
80                                 while (pi_received == 0 || sid_received == 0) {
81                                         if (rds_receive_group(fd, rdsgroup)) {
82                                                 /* group complete, start decode */
83                                                 rds_decode_group(rdsgroup);
84                     }
85                 }
86                         }
87
88                         v4lfreq.frequency += 1600; /* 1600 for .1MHz steps, 800 for 0.05MHz */
89         }
90 }
91
92
93 int main(int argc, char **argv)
94 {
95 int fd, ret;
96 struct v4l2_capability v4lcap;
97 struct v4l2_frequency v4lfreq;
98 struct v4l2_tuner v4ltuner;
99
100         fd = open ("/dev/radio0", O_RDONLY);
101         if (fd < 0) {
102                 printf("error opening fd\n");
103                 perror("open");
104                 return 1;
105         }
106
107         ret = ioctl(fd, VIDIOC_QUERYCAP, &v4lcap);
108         if (ret < 0)
109                 return 1;
110
111         printf("driver = '%s'\n", v4lcap.driver);
112         printf("card = '%s'\n", v4lcap.card);
113         printf("bus_info = '%s'\n", v4lcap.bus_info);
114         printf("cap && RADIO = %s\n", (v4lcap.capabilities & V4L2_CAP_RADIO) ? "yes" : "no");
115         printf("cap && TUNER = %s\n", (v4lcap.capabilities & V4L2_CAP_TUNER) ? "yes" : "no");
116         printf("cap && RDS = %s\n", (v4lcap.capabilities & V4L2_CAP_RDS_CAPTURE) ? "yes" : "no");
117
118         v4ltuner.index = 0;
119         ret = ioctl(fd, VIDIOC_G_TUNER, &v4ltuner);
120         if (ret < 0)
121                 return 1;
122         printf("tuner=%d\n", v4ltuner.index);
123         if (v4ltuner.type == V4L2_TUNER_RADIO)
124                 printf("  is a radio tuner\n");
125         printf("name='%s'\n", v4ltuner.name);
126
127         v4lfreq.tuner = v4ltuner.index;
128         memset(&v4lfreq.reserved, 0, 32);
129         ret = ioctl(fd, VIDIOC_G_FREQUENCY, &v4lfreq);
130
131         if (ret >= 0) {
132                 if (v4ltuner.capability & V4L2_TUNER_CAP_LOW) {
133                         printf("range %3.2lf MHz - %3.2lf MHz\n", (double)v4ltuner.rangelow * 62.5 / 1000000, (double)v4ltuner.rangehigh * 62.5 / 1000000);
134                         printf("freq = %3.2lf MHz\n", (double)v4lfreq.frequency * 62.5 / 1000000);
135                 } else
136                         printf("freq = %lf kHz\n", (double)v4lfreq.frequency * 62.5);
137         }
138         printf("signal: %d %s\n", v4ltuner.signal, v4ltuner.rxsubchans & V4L2_TUNER_SUB_STEREO ? "stereo" : "mono");
139         printf("RDS signal present: %s\n", v4ltuner.rxsubchans & V4L2_TUNER_SUB_RDS ? "yes" : "no");
140
141         if (argc > 1 && strcmp(argv[1], "-s")==0) {
142                 rds_init();
143         tmc_init();
144         rds_set_sname_cb(test_rds_sname_cb, NULL);
145         rds_set_PI_cb(test_rds_PI_cb, NULL);
146                 station_scan(fd);
147         }
148
149         close(fd);
150
151 return 0;
152 }