rtl-ais/main.c

241 wiersze
6.8 KiB
C

/*
* Copyright (C) 2012 by Kyle Keen <keenerd@gmail.com>
*
* 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;
}