minimodem: rtty and cmdline band_width

* 'rtty' cmdline parm enables 45.45 baud 5-bit Baudot
 * band_width cmdline parm
This commit is contained in:
Kamal Mostafa 2011-06-10 18:09:47 -07:00
parent 8a6847195e
commit 35f03b742e
5 changed files with 155 additions and 44 deletions

View File

@ -26,7 +26,9 @@ SIMPLEAUDIO_SRC = \
FSK_SRC = fsk.h fsk.c FSK_SRC = fsk.h fsk.c
BAUDOT_SRC = baudot.h baudot.c
minimodem_LDADD = $(DEPS_LIBS) minimodem_LDADD = $(DEPS_LIBS)
minimodem_SOURCES = minimodem.c $(FSK_SRC) $(SIMPLEAUDIO_SRC) minimodem_SOURCES = minimodem.c $(BAUDOT_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC)

View File

@ -54,11 +54,12 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES = CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS) PROGRAMS = $(bin_PROGRAMS)
am__objects_1 = fsk.$(OBJEXT) am__objects_1 = baudot.$(OBJEXT)
am__objects_2 = simpleaudio.$(OBJEXT) simpleaudio-pulse.$(OBJEXT) \ am__objects_2 = fsk.$(OBJEXT)
am__objects_3 = simpleaudio.$(OBJEXT) simpleaudio-pulse.$(OBJEXT) \
simpleaudio-sndfile.$(OBJEXT) simpleaudio-sndfile.$(OBJEXT)
am_minimodem_OBJECTS = minimodem.$(OBJEXT) $(am__objects_1) \ am_minimodem_OBJECTS = minimodem.$(OBJEXT) $(am__objects_1) \
$(am__objects_2) $(am__objects_2) $(am__objects_3)
minimodem_OBJECTS = $(am_minimodem_OBJECTS) minimodem_OBJECTS = $(am_minimodem_OBJECTS)
am__DEPENDENCIES_1 = am__DEPENDENCIES_1 =
minimodem_DEPENDENCIES = $(am__DEPENDENCIES_1) minimodem_DEPENDENCIES = $(am__DEPENDENCIES_1)
@ -174,8 +175,9 @@ SIMPLEAUDIO_SRC = \
simpleaudio-sndfile.c simpleaudio-sndfile.c
FSK_SRC = fsk.h fsk.c FSK_SRC = fsk.h fsk.c
BAUDOT_SRC = baudot.h baudot.c
minimodem_LDADD = $(DEPS_LIBS) minimodem_LDADD = $(DEPS_LIBS)
minimodem_SOURCES = minimodem.c $(FSK_SRC) $(SIMPLEAUDIO_SRC) minimodem_SOURCES = minimodem.c $(BAUDOT_SRC) $(FSK_SRC) $(SIMPLEAUDIO_SRC)
all: all-am all: all-am
.SUFFIXES: .SUFFIXES:
@ -257,6 +259,7 @@ mostlyclean-compile:
distclean-compile: distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/baudot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsk.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimodem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minimodem.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio-pulse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simpleaudio-pulse.Po@am__quote@

View File

@ -1,17 +1,29 @@
/*
* baudot.c
*
* Copyright (C) 2011 Kamal Mostafa <kamal@whence.com>
*
* NO LICENSE HAS BEEN SPECIFIED OR GRANTED FOR THIS WORK.
*
*/
#include <assert.h>
static char static char
baudot[32][3] = { baudot_table[32][3] = {
// letter, U.S. figs, CCITT No.2 figs (Europe) // letter, U.S. figs, CCITT No.2 figs (Europe)
{ '*', '*', '*' }, // NUL { '*', '*', '*' }, // NUL
{ 'E', '3', '3' }, { 'E', '3', '3' },
{ '\n', '\n', '\n' }, { 0xA, 0xA, 0xA }, // LF
{ 'A', '-', '-' }, { 'A', '-', '-' },
{ ' ', ' ', ' ' }, // SPACE { ' ', ' ', ' ' }, // SPACE
{ 'S', '*', '\'' }, // BELL or apostrophe { 'S', '*', '\'' }, // BELL or apostrophe
{ 'I', '8', '8' }, { 'I', '8', '8' },
{ 'U', '7', '7' }, { 'U', '7', '7' },
{ '\n', '\n', '\n' }, { 0xD, 0xD, 0xD }, // CR
{ 'D', '$', '*' }, // '$' or ENQ { 'D', '$', '*' }, // '$' or ENQ
{ 'R', '4', '4' }, { 'R', '4', '4' },
{ 'J', '\'', '*' }, // apostrophe or BELL { 'J', '\'', '*' }, // apostrophe or BELL
@ -43,3 +55,38 @@ baudot[32][3] = {
#define BAUDOT_FIGS 0x1B #define BAUDOT_FIGS 0x1B
#define BAUDOT_SPACE 0x04 #define BAUDOT_SPACE 0x04
static int baudot_charset = 0; // FIXME
void
baudot_reset()
{
baudot_charset = 0;
}
/*
* returns nonzero if *char_outp was stuffed with an output character
*/
int
baudot( unsigned char databits, char *char_outp )
{
/* Baudot (RTTY) */
assert( (databits & ~0x1F) == 0 );
int stuff_char = 1;
if ( databits == BAUDOT_FIGS ) {
baudot_charset = 1;
stuff_char = 0;
} else if ( databits == BAUDOT_LTRS ) {
baudot_charset = 0;
stuff_char = 0;
} else if ( databits == BAUDOT_SPACE ) {
baudot_charset = 0;
}
if ( stuff_char )
*char_outp = baudot_table[databits][baudot_charset];
return stuff_char;
}

19
src/baudot.h Normal file
View File

@ -0,0 +1,19 @@
/*
* baudot.h
*
* Copyright (C) 2011 Kamal Mostafa <kamal@whence.com>
*
* NO LICENSE HAS BEEN SPECIFIED OR GRANTED FOR THIS WORK.
*
*/
void
baudot_reset();
/*
* returns nonzero if *char_outp was stuffed with an output character
*/
int
baudot( unsigned char databits, char *char_outp );

View File

@ -17,37 +17,78 @@
#include "simpleaudio.h" #include "simpleaudio.h"
#include "fsk.h" #include "fsk.h"
#include "baudot.h"
int int
main( int argc, char*argv[] ) main( int argc, char*argv[] )
{ {
if ( argc < 2 ) { if ( argc < 2 ) {
fprintf(stderr, "usage: minimodem {baud|mode} [filename] " fprintf(stderr, "usage: minimodem {baud|mode} [filename] "
"[ band_width ] "
"[ mark_hz space_hz ]\n"); "[ mark_hz space_hz ]\n");
return 1; return 1;
} }
int argi = 1; int argi = 1;
float decode_rate; float decode_rate;
int decode_n_data_bits;
decode_rate = atof(argv[argi]); if ( strncasecmp(argv[argi],"rtty",5)==0 ) {
decode_rate = 45.45;
decode_n_data_bits = 5;
} else {
decode_rate = atof(argv[argi]);
decode_n_data_bits = 8;
}
argi++; argi++;
unsigned int band_width;
unsigned int bfsk_mark_f;
unsigned int bfsk_space_f;
unsigned int autodetect_shift;
if ( decode_rate >= 400 ) {
/*
* Bell 202: baud=1200 mark=1200 space=2200
*/
bfsk_mark_f = 1200;
bfsk_space_f = 2200;
band_width = 200;
autodetect_shift = 0; // not used
} else if ( decode_rate >= 100 ) {
/*
* Bell 103: baud=300 mark=1270 space=1070
* ITU-T V.21: baud=300 mark=1280 space=1080
*/
bfsk_mark_f = 1270;
bfsk_space_f = 1070;
band_width = 50; // close enough
autodetect_shift = 200;
} else {
/*
* RTTY: baud=45.45 mark/space=variable shift=-170
*/
bfsk_mark_f = 0;
bfsk_space_f = 0;
band_width = 10;
// band_width = 68; // FIXME FIXME FIXME -- causes assert crash
autodetect_shift = 170;
}
/*
* Open the input audio stream
*/
simpleaudio *sa = NULL; simpleaudio *sa = NULL;
if ( argi < argc ) { if ( argi < argc && strncmp(argv[argi],"-",2)!=0 ) {
char *p; sa = simpleaudio_open_source_sndfile(argv[argi++]);
for ( p=argv[argi]; *p; p++ ) if ( !sa )
if ( !(isdigit(*p) || *p == '.') ) return 1;
break;
if ( *p ) {
sa = simpleaudio_open_source_sndfile(argv[argi++]);
if ( !sa )
return 1;
}
} }
if ( ! sa ) { if ( ! sa ) {
sa = simpleaudio_open_source_pulseaudio(argv[0], "FSK demodulator"); sa = simpleaudio_open_source_pulseaudio(argv[0], "input audio");
} }
if ( !sa ) if ( !sa )
return 1; return 1;
@ -57,28 +98,13 @@ main( int argc, char*argv[] )
assert( nchannels == 1 ); assert( nchannels == 1 );
unsigned int band_width;
band_width = decode_rate;
/* /*
* Bell 103: baud=300 mark=1270 space=1070 * Alloc for band_width and tone frequency overrides
* ITU-T V.21: baud=300 mark=1280 space=1080 * FIXME -- tone override doesn't work with autodetect carrier
*/ */
unsigned int bfsk_mark_f = 1270;
unsigned int bfsk_space_f = 1070;
#define CARRIER_AUTODETECT_THRESHOLD 0.10
#ifdef CARRIER_AUTODETECT_THRESHOLD
unsigned int autodetect_shift = 200;
#endif
band_width = 50; /* close enough */
/* if ( argi < argc ) {
* Bell 202: baud=1200 mark=1200 space=2200 band_width = atoi(argv[argi++]); // FIXME make band_width float?
*/
if ( decode_rate >= 400 ) {
bfsk_mark_f = 1200;
bfsk_space_f = 2200;
band_width = 200;
} }
if ( argi < argc ) { if ( argi < argc ) {
@ -97,9 +123,9 @@ main( int argc, char*argv[] )
* Prepare the fsk plan * Prepare the fsk plan
*/ */
fsk_plan *fskp = fsk_plan_new(sample_rate, fsk_plan *fskp;
bfsk_mark_f, bfsk_space_f, fskp = fsk_plan_new(sample_rate, bfsk_mark_f, bfsk_space_f,
band_width, 8); band_width, decode_n_data_bits);
if ( !fskp ) { if ( !fskp ) {
fprintf(stderr, "fsk_plan_new() failed\n"); fprintf(stderr, "fsk_plan_new() failed\n");
return 1; return 1;
@ -173,6 +199,7 @@ main( int argc, char*argv[] )
if ( samples_nvalid == 0 ) if ( samples_nvalid == 0 )
break; break;
#define CARRIER_AUTODETECT_THRESHOLD 0.03
#ifdef CARRIER_AUTODETECT_THRESHOLD #ifdef CARRIER_AUTODETECT_THRESHOLD
/* Auto-detect carrier frequency */ /* Auto-detect carrier frequency */
static int carrier_band = -1; static int carrier_band = -1;
@ -278,6 +305,7 @@ main( int argc, char*argv[] )
(unsigned int)(decode_rate + 0.5), (unsigned int)(decode_rate + 0.5),
fskp->b_mark * fskp->band_width); fskp->b_mark * fskp->band_width);
carrier = 1; carrier = 1;
baudot_reset(); // FIXME -- lame here
} }
confidence_total += confidence; confidence_total += confidence;
@ -302,7 +330,19 @@ main( int argc, char*argv[] )
nsamples_per_bit, fskp->n_data_bits, nsamples_per_bit, fskp->n_data_bits,
frame_start_sample, advance); frame_start_sample, advance);
char the_byte = isprint(bits)||isspace(bits) ? bits : '.'; char the_byte;
if ( fskp->n_data_bits == 5 ) {
/* Baudot (RTTY) */
assert( (bits & ~0x1F) == 0 );
int got_char;
got_char = baudot(bits, &the_byte);
if ( ! got_char )
continue;
} else {
/* ASCII */
the_byte = isprint(bits)||isspace(bits) ? bits : '.';
}
printf( "%c", the_byte ); printf( "%c", the_byte );
fflush(stdout); fflush(stdout);