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:
parent
8a6847195e
commit
35f03b742e
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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@
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 );
|
112
src/minimodem.c
112
src/minimodem.c
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue