forked from dgiardini/rtl-ais
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
240 lines (228 loc) · 6.81 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
* Copyright (C) 2012 by Kyle Keen <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
typedef void* rtlsdr_dev_t;
#include "convenience.h"
#include "rtl_ais.h"
void usage(void)
{
fprintf(stderr,
"rtl_ais, a simple AIS tuner\n"
"\t and generic dual-frequency FM demodulator\n\n"
"(probably not a good idea to use with e4000 tuners)\n"
"Use: rtl_ais [options] [outputfile]\n"
"\t[-l left_frequency (default: 161.975M)]\n"
"\t[-r right_frequency (default: 162.025M)]\n"
"\t left freq < right freq\n"
"\t frequencies must be within 1.2MHz\n"
"\t[-s sample_rate (default: 24k)]\n"
"\t maximum value, might be down to 12k\n"
"\t[-o output_rate (default: 48k)]\n"
"\t must be equal or greater than twice -s value\n"
"\t[-E toggle edge tuning (default: off)]\n"
"\t[-D toggle DC filter (default: on)]\n"
//"\t[-O toggle oversampling (default: off)\n"
"\t[-d device_index (default: 0)]\n"
"\t[-g tuner_gain (default: automatic)]\n"
"\t[-p ppm_error (default: 0)]\n"
"\t[-R enable RTL chip AGC (default: off)]\n"
"\t[-A turn off built-in AIS decoder (default: on)]\n"
"\t use this option to output samples to file or stdout.\n"
"\tBuilt-in AIS decoder options:\n"
"\t[-h host (default: 127.0.0.1)]\n"
"\t[-P port (default: 10110)]\n"
"\t[-T use TCP communication, rtl-ais is tcp server ( -h is ignored)\n"
"\t[-t time to keep ais messages in sec, using tcp listener (default: 15)\n"
"\t[-n log NMEA sentences to console (stderr) (default off)]\n"
"\t[-I add sample index to NMEA messages (default off)]\n"
"\t[-L log sound levels to console (stderr) (default off)]\n\n"
"\t[-S seconds_for_decoder_stats (default 0=off)]\n\n"
"\tWhen the built-in AIS decoder is disabled the samples are sent to\n"
"\tto [outputfile] (a '-' dumps samples to stdout)\n"
"\t omitting the filename also uses stdout\n\n"
"\tOutput is stereo 2x16 bit signed ints\n\n"
"\tExamples:\n"
"\tReceive AIS traffic,sent UDP NMEA sentences to 127.0.0.1 port 10110\n"
"\t and log the senteces to console:\n\n"
"\trtl_ais -n\n\n"
"\tTune two fm stations and play one on each channel:\n\n"
"\trtl_ais -l233.15M -r233.20M -A | play -r48k -traw -es -b16 -c2 -V1 - "
"\n");
exit(1);
}
static volatile int do_exit = 0;
static void sighandler(int signum)
{
signum = signum;
fprintf(stderr, "Signal caught, exiting!\n");
do_exit = 1;
}
int main(int argc, char **argv)
{
#ifndef WIN32
struct sigaction sigact;
sigact.sa_handler = sighandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
sigaction(SIGPIPE, &sigact, NULL);
#else
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
#endif
int opt;
struct rtl_ais_config config;
rtl_ais_default_config(&config);
config.host = strdup("127.0.0.1");
config.port = strdup("10110");
while ((opt = getopt(argc, argv, "l:r:s:o:EODd:g:p:RATIt:P:h:nLS:?")) != -1)
{
switch (opt) {
case 'l':
config.left_freq = (int)atofs(optarg);
break;
case 'r':
config.right_freq = (int)atofs(optarg);
break;
case 's':
config.sample_rate = (int)atofs(optarg);
break;
case 'o':
config.output_rate = (int)atofs(optarg);
break;
case 'E':
config.edge = !config.edge;
break;
case 'D':
config.dc_filter = !config.dc_filter;
break;
case 'O':
config.oversample = !config.oversample;
break;
case 'd':
config.dev_index = verbose_device_search(optarg);
config.dev_given = 1;
break;
case 'g':
config.gain = (int)(atof(optarg) * 10);
break;
case 'p':
config.ppm_error = atoi(optarg);
config.custom_ppm = 1;
break;
case 'R':
config.rtl_agc=1;
break;
case 'A':
config.use_internal_aisdecoder=0;
break;
case 'I':
config.add_sample_num = 1;
break;
case 'P':
config.port=strdup(optarg);
break;
case 'T':
config.use_tcp_listener=1;
break;
case 't':
config.tcp_keep_ais_time = atoi(optarg);
break;
case 'h':
config.host=strdup(optarg);
break;
case 'L':
config.show_levels=1;
break;
case 'S':
config.seconds_for_decoder_stats=atoi(optarg);
break;
case 'n':
config.debug_nmea = 1;
break;
case '?':
default:
usage();
return 2;
}
}
if (argc <= optind) {
config.filename = "-";
} else {
config.filename = argv[optind];
}
if (config.edge) {
fprintf(stderr, "Edge tuning enabled.\n");
} else {
fprintf(stderr, "Edge tuning disabled.\n");
}
if (config.dc_filter) {
fprintf(stderr, "DC filter enabled.\n");
} else {
fprintf(stderr, "DC filter disabled.\n");
}
if (config.rtl_agc) {
fprintf(stderr, "RTL AGC enabled.\n");
} else {
fprintf(stderr, "RTL AGC disabled.\n");
}
if (config.use_internal_aisdecoder) {
fprintf(stderr, "Internal AIS decoder enabled.\n");
} else {
fprintf(stderr, "Internal AIS decoder disabled.\n");
}
struct rtl_ais_context *ctx = rtl_ais_start(&config);
if(!ctx) {
fprintf(stderr, "\nrtl_ais_start failed, exiting...\n");
exit(1);
}
/*
aidecoder.c appends the messages to a queue that can be used for a
routine if rtl_ais is compiled as lib. Here we only loop and dequeue
the messages, and the puts() sentence that print the message is
commented out. If the -n parameter is used the messages are printed from
nmea_sentence_received() in aidecoder.c
*/
while(!do_exit && rtl_ais_isactive(ctx)) {
#if _POSIX_C_SOURCE >= 199309L // nanosleep available()
struct timespec five = { 0, 50 * 1000 * 1000};
#endif
const char *str;
if(config.use_internal_aisdecoder)
{
// dequeue
while((str = rtl_ais_next_message(ctx)))
{
//puts(str); or code something that fits your needs
}
}
#if _POSIX_C_SOURCE >= 199309L // nanosleep available()
nanosleep(&five, NULL);
#else
usleep(50000);
#endif
}
rtl_ais_cleanup(ctx);
return 0;
}