mirror of https://github.com/wb2osz/direwolf.git
2400 bps PSK compatibility with MFJ-2400.
This commit is contained in:
parent
ad12fa86d6
commit
b37fda96fb
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
- "-g" option to force G3RUH mode for lower speeds where a different modem type may be the default.
|
- "-g" option to force G3RUH mode for lower speeds where a different modem type may be the default.
|
||||||
|
|
||||||
|
- 2400 bps compatibility with MFJ-2400. See ***2400-4800-PSK-for-APRS-Packet-Radio.pdf*** for details
|
||||||
|
|
||||||
- "atest -h" will display the frame in hexadecimal for closer inspection.
|
- "atest -h" will display the frame in hexadecimal for closer inspection.
|
||||||
|
|
||||||
- Add support for Multi-GNSS NMEA sentences.
|
- Add support for Multi-GNSS NMEA sentences.
|
||||||
|
|
|
@ -735,7 +735,7 @@ install-rpi :
|
||||||
# Combine some unit tests into a single regression sanity check.
|
# Combine some unit tests into a single regression sanity check.
|
||||||
|
|
||||||
|
|
||||||
check : dtest ttest tttexttest pftest tlmtest lltest enctest kisstest pad2test xidtest dtmftest check-modem1200 check-modem300 check-modem9600 check-modem19200 check-modem2400 check-modem2400-g check-modem4800
|
check : dtest ttest tttexttest pftest tlmtest lltest enctest kisstest pad2test xidtest dtmftest check-modem1200 check-modem300 check-modem9600 check-modem19200 check-modem2400-a check-modem2400-b check-modem2400-g check-modem4800
|
||||||
|
|
||||||
# Can we encode and decode at popular data rates?
|
# Can we encode and decode at popular data rates?
|
||||||
|
|
||||||
|
@ -763,11 +763,17 @@ check-modem19200 : gen_packets atest
|
||||||
./atest -B19200 -F1 -L64 -G68 /tmp/test19.wav
|
./atest -B19200 -F1 -L64 -G68 /tmp/test19.wav
|
||||||
rm /tmp/test19.wav
|
rm /tmp/test19.wav
|
||||||
|
|
||||||
check-modem2400 : gen_packets atest
|
check-modem2400-a : gen_packets atest
|
||||||
./gen_packets -B2400 -n 100 -o /tmp/test24.wav
|
./gen_packets -B2400 -j -n 100 -o /tmp/test24-a.wav
|
||||||
./atest -B2400 -F0 -L70 -G78 /tmp/test24.wav
|
./atest -B2400 -j -F0 -L76 -G80 test24-a.wav
|
||||||
./atest -B2400 -F1 -L80 -G87 /tmp/test24.wav
|
./atest -B2400 -j -F1 -L84 -G88 test24-a.wav
|
||||||
rm /tmp/test24.wav
|
rm /tmp/test24-a.wav
|
||||||
|
|
||||||
|
check-modem2400-b : gen_packets atest
|
||||||
|
./gen_packets -B2400 -J -n 100 -o /tmp/test24-b.wav
|
||||||
|
./atest -B2400 -J -F0 -L79 -G83 test24-b.wav
|
||||||
|
./atest -B2400 -J -F1 -L87 -G91 test24-b.wav
|
||||||
|
rm /tmp/test24-b.wav
|
||||||
|
|
||||||
check-modem2400-g : gen_packets atest
|
check-modem2400-g : gen_packets atest
|
||||||
./gen_packets -B2400 -g -n 100 -o /tmp/test24-g.wav
|
./gen_packets -B2400 -g -n 100 -o /tmp/test24-g.wav
|
||||||
|
|
38
Makefile.win
38
Makefile.win
|
@ -277,7 +277,7 @@ strlcat.o : misc/strlcat.c
|
||||||
|
|
||||||
# Combine some unit tests into a single regression sanity check.
|
# Combine some unit tests into a single regression sanity check.
|
||||||
|
|
||||||
check : dtest ttest tttexttest pftest tlmtest lltest enctest kisstest pad2test xidtest dtmftest check-modem1200 check-modem300 check-modem9600 check-modem19200 check-modem2400 check-modem2400-g check-modem4800
|
check : dtest ttest tttexttest pftest tlmtest lltest enctest kisstest pad2test xidtest dtmftest check-modem1200 check-modem300 check-modem9600 check-modem19200 check-modem2400-a check-modem2400-b check-modem2400-g check-modem4800
|
||||||
|
|
||||||
# Can we encode and decode at popular data rates?
|
# Can we encode and decode at popular data rates?
|
||||||
# Verify that single bit fixup increases the count.
|
# Verify that single bit fixup increases the count.
|
||||||
|
@ -324,13 +324,21 @@ check-modem19200 : gen_packets atest
|
||||||
sleep 1
|
sleep 1
|
||||||
rm test19.wav
|
rm test19.wav
|
||||||
|
|
||||||
check-modem2400 : gen_packets atest
|
check-modem2400-a : gen_packets atest
|
||||||
gen_packets -B2400 -n 100 -o test24.wav
|
gen_packets -B2400 -j -n 100 -o test24-a.wav
|
||||||
sleep 1
|
sleep 1
|
||||||
atest -B2400 -F0 -L70 -G78 test24.wav
|
atest -B2400 -j -F0 -L76 -G80 test24-a.wav
|
||||||
atest -B2400 -F1 -L80 -G87 test24.wav
|
atest -B2400 -j -F1 -L84 -G88 test24-a.wav
|
||||||
sleep 1
|
sleep 1
|
||||||
rm test24.wav
|
rm test24-a.wav
|
||||||
|
|
||||||
|
check-modem2400-b : gen_packets atest
|
||||||
|
gen_packets -B2400 -J -n 100 -o test24-b.wav
|
||||||
|
sleep 1
|
||||||
|
atest -B2400 -J -F0 -L79 -G83 test24-b.wav
|
||||||
|
atest -B2400 -J -F1 -L87 -G91 test24-b.wav
|
||||||
|
sleep 1
|
||||||
|
rm test24-b.wav
|
||||||
|
|
||||||
check-modem2400-g : gen_packets atest
|
check-modem2400-g : gen_packets atest
|
||||||
gen_packets -B2400 -g -n 100 -o test24-g.wav
|
gen_packets -B2400 -g -n 100 -o test24-g.wav
|
||||||
|
@ -518,8 +526,8 @@ testagc96 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c de
|
||||||
misc.a regex.a
|
misc.a regex.a
|
||||||
rm -f atest96.exe
|
rm -f atest96.exe
|
||||||
$(CC) $(CFLAGS) -o atest96 $^
|
$(CC) $(CFLAGS) -o atest96 $^
|
||||||
./atest96 -B 9600 ../walkabout9600c.wav | grep "packets decoded in" >atest.out
|
./atest96 -B 9600 ../walkabout9600c.wav noisy96.wav zzz16.wav zzz16.wav zzz16.wav zzz8.wav zzz8.wav zzz8.wav | grep "packets decoded in" >atest.out
|
||||||
#./atest96 -B 9600 ../walkabout9600c.wav noisy96.wav zzz16.wav zzz16.wav zzz16.wav zzz8.wav zzz8.wav zzz8.wav | grep "packets decoded in" >atest.out
|
#./atest96 -B 9600 ../walkabout9600c.wav | grep "packets decoded in" >atest.out
|
||||||
#./atest96 -B 9600 zzz16.wav zzz8.wav | grep "packets decoded in" >atest.out
|
#./atest96 -B 9600 zzz16.wav zzz8.wav | grep "packets decoded in" >atest.out
|
||||||
#./atest96 -B 9600 noisy96.wav | grep "packets decoded in" >atest.out
|
#./atest96 -B 9600 noisy96.wav | grep "packets decoded in" >atest.out
|
||||||
#./atest96 -B 9600 19990303_0225_9600_8bis_22kHz.wav | grep "packets decoded in" >atest.out
|
#./atest96 -B 9600 19990303_0225_9600_8bis_22kHz.wav | grep "packets decoded in" >atest.out
|
||||||
|
@ -536,10 +544,22 @@ testagc24 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c de
|
||||||
misc.a regex.a
|
misc.a regex.a
|
||||||
rm -f atest24.exe
|
rm -f atest24.exe
|
||||||
sleep 1
|
sleep 1
|
||||||
$(CC) $(CFLAGS) -o atest24 $^
|
$(CC) $(CFLAGS) -o atest24mfj $^
|
||||||
./atest24 -B 2400 test2400.wav | grep "packets decoded in" >atest.out
|
./atest24 -B 2400 test2400.wav | grep "packets decoded in" >atest.out
|
||||||
echo " " > tune.h
|
echo " " > tune.h
|
||||||
|
|
||||||
|
testagc24mfj : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c demod_9600.c \
|
||||||
|
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
|
||||||
|
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
|
||||||
|
dwgpsnmea.o dwgps.o serial_port.o latlong.o \
|
||||||
|
symbols.o tt_text.o textcolor.o telemetry.o dtime_now.o \
|
||||||
|
misc.a regex.a
|
||||||
|
rm -f atest24mfj.exe
|
||||||
|
sleep 1
|
||||||
|
$(CC) $(CFLAGS) -o atest24mfj $^
|
||||||
|
./atest24mfj -F 1 -B 2400 ../ref-doc/MFJ-2400-PSK/2k4_short.wav
|
||||||
|
echo " " > tune.h
|
||||||
|
|
||||||
testagc48 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c demod_9600.c \
|
testagc48 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c demod_9600.c \
|
||||||
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
|
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
|
||||||
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
|
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
|
||||||
|
|
128
atest.c
128
atest.c
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2019 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -182,7 +182,10 @@ static int sample_number = -1; /* Sample number from the file. */
|
||||||
|
|
||||||
static int B_opt = DEFAULT_BAUD; // Bits per second. Need to change all baud references to bps.
|
static int B_opt = DEFAULT_BAUD; // Bits per second. Need to change all baud references to bps.
|
||||||
static int g_opt = 0; // G3RUH modem regardless of speed.
|
static int g_opt = 0; // G3RUH modem regardless of speed.
|
||||||
|
static int j_opt = 0; /* 2400 bps PSK compatible with direwolf <= 1.5 */
|
||||||
|
static int J_opt = 0; /* 2400 bps PSK compatible MFJ-2400 and maybe others. */
|
||||||
static int h_opt = 0; // Hexadecimal display of received packet.
|
static int h_opt = 0; // Hexadecimal display of received packet.
|
||||||
|
static char P_opt[16] = ""; // Demodulator profiles.
|
||||||
|
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
|
@ -219,49 +222,6 @@ int main (int argc, char *argv[])
|
||||||
my_audio_config.adev[0].samples_per_sec = DEFAULT_SAMPLES_PER_SEC;
|
my_audio_config.adev[0].samples_per_sec = DEFAULT_SAMPLES_PER_SEC;
|
||||||
my_audio_config.adev[0].bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
|
my_audio_config.adev[0].bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
|
||||||
|
|
||||||
// Results v0.9:
|
|
||||||
//
|
|
||||||
// fix_bits = 0 971 packets, 69 sec
|
|
||||||
// fix_bits = SINGLE 990 64
|
|
||||||
// fix_bits = DOUBLE 992 65
|
|
||||||
// fix_bits = TRIPLE 992 67
|
|
||||||
// fix_bits = TWO_SEP 1004 476
|
|
||||||
|
|
||||||
// Essentially no difference in time for those with order N time.
|
|
||||||
// Time increases greatly for the one with order N^2 time.
|
|
||||||
|
|
||||||
|
|
||||||
// Results: version 1.1, decoder C, my_audio_config.fix_bits = RETRY_MAX - 1
|
|
||||||
//
|
|
||||||
// 971 NONE
|
|
||||||
// +19 SINGLE
|
|
||||||
// +2 DOUBLE
|
|
||||||
// +12 TWO_SEP
|
|
||||||
// +3 REMOVE_MANY
|
|
||||||
// ----
|
|
||||||
// 1007 Total in 1008 sec. More than twice as long as earlier version.
|
|
||||||
|
|
||||||
// Results: version 1.1, decoders ABC, my_audio_config.fix_bits = RETRY_MAX - 1
|
|
||||||
//
|
|
||||||
// 976 NONE
|
|
||||||
// +21 SINGLE
|
|
||||||
// +1 DOUBLE
|
|
||||||
// +22 TWO_SEP
|
|
||||||
// +1 MANY
|
|
||||||
// +3 REMOVE_MANY
|
|
||||||
// ----
|
|
||||||
// 1024 Total in 2042 sec.
|
|
||||||
// About 34 minutes of CPU time for a roughly 40 minute CD.
|
|
||||||
// Many computers wouldn't be able to keep up.
|
|
||||||
|
|
||||||
// The SINGLE and TWO_SEP techniques are the most effective.
|
|
||||||
// Should we reorder the enum values so that TWO_SEP
|
|
||||||
// comes after SINGLE? That way "FIX_BITS 2" would
|
|
||||||
// use the two most productive techniques and not waste
|
|
||||||
// time on the others. People with plenty of CPU power
|
|
||||||
// to spare can still specify larger numbers for the other
|
|
||||||
// techniques with less return on investment.
|
|
||||||
|
|
||||||
|
|
||||||
for (channel=0; channel<MAX_CHANS; channel++) {
|
for (channel=0; channel<MAX_CHANS; channel++) {
|
||||||
|
|
||||||
|
@ -299,7 +259,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
/* ':' following option character means arg is required. */
|
/* ':' following option character means arg is required. */
|
||||||
|
|
||||||
c = getopt_long(argc, argv, "B:P:D:U:gF:L:G:012h",
|
c = getopt_long(argc, argv, "B:P:D:U:gjJF:L:G:012h",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -316,10 +276,20 @@ int main (int argc, char *argv[])
|
||||||
g_opt = 1;
|
g_opt = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'j': /* -j V.26 compatible with earlier direwolf. */
|
||||||
|
|
||||||
|
j_opt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J': /* -J V.26 compatible with MFJ-2400. */
|
||||||
|
|
||||||
|
J_opt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'P': /* -P for modem profile. */
|
case 'P': /* -P for modem profile. */
|
||||||
|
|
||||||
dw_printf ("Demodulator profile set to \"%s\"\n", optarg);
|
// Wait until after other options processed.
|
||||||
strlcpy (my_audio_config.achan[0].profiles, optarg, sizeof(my_audio_config.achan[0].profiles));
|
strlcpy (P_opt, optarg, sizeof(P_opt));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D': /* -D reduce sampling rate for lower CPU usage. */
|
case 'D': /* -D reduce sampling rate for lower CPU usage. */
|
||||||
|
@ -353,7 +323,7 @@ int main (int argc, char *argv[])
|
||||||
my_audio_config.achan[0].upsample = upsample;
|
my_audio_config.achan[0].upsample = upsample;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F': /* -D set "fix bits" level. */
|
case 'F': /* -F set "fix bits" level. */
|
||||||
|
|
||||||
my_audio_config.achan[0].fix_bits = atoi(optarg);
|
my_audio_config.achan[0].fix_bits = atoi(optarg);
|
||||||
|
|
||||||
|
@ -411,7 +381,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set modem type based on data rate.
|
* Set modem type based on data rate.
|
||||||
* (Could be overridden by -g later.)
|
* (Could be overridden by -g, -j, or -J later.)
|
||||||
*/
|
*/
|
||||||
/* 300 implies 1600/1800 AFSK. */
|
/* 300 implies 1600/1800 AFSK. */
|
||||||
/* 1200 implies 1200/2200 AFSK. */
|
/* 1200 implies 1200/2200 AFSK. */
|
||||||
|
@ -478,6 +448,40 @@ int main (int argc, char *argv[])
|
||||||
strlcpy (my_audio_config.achan[0].profiles, " ", sizeof(my_audio_config.achan[0].profiles)); // avoid getting default later.
|
strlcpy (my_audio_config.achan[0].profiles, " ", sizeof(my_audio_config.achan[0].profiles)); // avoid getting default later.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have two different incompatible flavors of V.26.
|
||||||
|
*/
|
||||||
|
if (j_opt) {
|
||||||
|
|
||||||
|
// V.26 compatible with earlier versions of direwolf.
|
||||||
|
// Example: -B 2400 -j or simply -j
|
||||||
|
|
||||||
|
my_audio_config.achan[0].v26_alternative = V26_A;
|
||||||
|
my_audio_config.achan[0].modem_type = MODEM_QPSK;
|
||||||
|
my_audio_config.achan[0].mark_freq = 0;
|
||||||
|
my_audio_config.achan[0].space_freq = 0;
|
||||||
|
my_audio_config.achan[0].baud = 2400;
|
||||||
|
strlcpy (my_audio_config.achan[0].profiles, "", sizeof(my_audio_config.achan[0].profiles));
|
||||||
|
}
|
||||||
|
if (J_opt) {
|
||||||
|
|
||||||
|
// V.26 compatible with MFJ and maybe others.
|
||||||
|
// Example: -B 2400 -J or simply -J
|
||||||
|
|
||||||
|
my_audio_config.achan[0].v26_alternative = V26_B;
|
||||||
|
my_audio_config.achan[0].modem_type = MODEM_QPSK;
|
||||||
|
my_audio_config.achan[0].mark_freq = 0;
|
||||||
|
my_audio_config.achan[0].space_freq = 0;
|
||||||
|
my_audio_config.achan[0].baud = 2400;
|
||||||
|
strlcpy (my_audio_config.achan[0].profiles, "", sizeof(my_audio_config.achan[0].profiles));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needs to be after -B, -j, -J.
|
||||||
|
if (strlen(P_opt) > 0) {
|
||||||
|
dw_printf ("Demodulator profile set to \"%s\"\n", P_opt);
|
||||||
|
strlcpy (my_audio_config.achan[0].profiles, P_opt, sizeof(my_audio_config.achan[0].profiles));
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (&my_audio_config.achan[1], &my_audio_config.achan[0], sizeof(my_audio_config.achan[0]));
|
memcpy (&my_audio_config.achan[1], &my_audio_config.achan[0], sizeof(my_audio_config.achan[0]));
|
||||||
|
|
||||||
|
|
||||||
|
@ -879,11 +883,15 @@ static void usage (void) {
|
||||||
dw_printf (" atest [ options ] wav-file-in\n");
|
dw_printf (" atest [ options ] wav-file-in\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" -B n Bits/second for data. Proper modem automatically selected for speed.\n");
|
dw_printf (" -B n Bits/second for data. Proper modem automatically selected for speed.\n");
|
||||||
dw_printf (" 300 baud uses 1600/1800 Hz AFSK.\n");
|
dw_printf (" 300 bps defaults to AFSK tones of 1600 & 1800.\n");
|
||||||
dw_printf (" 1200 (default) baud uses 1200/2200 Hz AFSK.\n");
|
dw_printf (" 1200 bps uses AFSK tones of 1200 & 2200.\n");
|
||||||
dw_printf (" 9600 baud uses K9NG/G2RUH standard.\n");
|
dw_printf (" 2400 bps uses QPSK based on V.26 standard.\n");
|
||||||
|
dw_printf (" 4800 bps uses 8PSK based on V.27 standard.\n");
|
||||||
|
dw_printf (" 9600 bps and up uses K9NG/G3RUH standard.\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" -g Force G3RUH modem rather rather than default for data rate.\n");
|
dw_printf (" -g Use G3RUH modem rather rather than default for data rate.\n");
|
||||||
|
dw_printf (" -j 2400 bps QPSK compatible with direwolf <= 1.5.\n");
|
||||||
|
dw_printf (" -J 2400 bps QPSK compatible with MFJ-2400.\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" -D n Divide audio sample rate by n.\n");
|
dw_printf (" -D n Divide audio sample rate by n.\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
|
@ -894,8 +902,12 @@ static void usage (void) {
|
||||||
dw_printf (" 1 = Try to fix only a single bit. \n");
|
dw_printf (" 1 = Try to fix only a single bit. \n");
|
||||||
dw_printf (" more = Try modifying more bits to get a good CRC.\n");
|
dw_printf (" more = Try modifying more bits to get a good CRC.\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" -P m Select the demodulator type such as A, B, C, D (default for 300 baud),\n");
|
dw_printf (" -L Error if less than this number decoded.\n");
|
||||||
dw_printf (" E (default for 1200 baud), F, A+, B+, C+, D+, E+, F+.\n");
|
dw_printf ("\n");
|
||||||
|
dw_printf (" -G Error if greater than this number decoded.\n");
|
||||||
|
dw_printf ("\n");
|
||||||
|
dw_printf (" -P m Select the demodulator type such as D (default for 300 bps),\n");
|
||||||
|
dw_printf (" E+ (default for 1200 bps), PQRS for 2400 bps, etc.\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" -0 Use channel 0 (left) of stereo audio (default).\n");
|
dw_printf (" -0 Use channel 0 (left) of stereo audio (default).\n");
|
||||||
dw_printf (" -1 use channel 1 (right) of stereo audio.\n");
|
dw_printf (" -1 use channel 1 (right) of stereo audio.\n");
|
||||||
|
@ -918,11 +930,11 @@ static void usage (void) {
|
||||||
dw_printf (" bits per second.\n");
|
dw_printf (" bits per second.\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" atest 02_Track_2.wav\n");
|
dw_printf (" atest 02_Track_2.wav\n");
|
||||||
dw_printf (" atest -P C+ 02_Track_2.wav\n");
|
dw_printf (" atest -P E- 02_Track_2.wav\n");
|
||||||
dw_printf (" atest -F 1 02_Track_2.wav\n");
|
dw_printf (" atest -F 1 02_Track_2.wav\n");
|
||||||
dw_printf (" atest -P C+ -F 1 02_Track_2.wav\n");
|
dw_printf (" atest -P E- -F 1 02_Track_2.wav\n");
|
||||||
dw_printf ("\n");
|
dw_printf ("\n");
|
||||||
dw_printf (" Try different combinations of options to find the best decoding\n");
|
dw_printf (" Try different combinations of options to compare decoding\n");
|
||||||
dw_printf (" performance.\n");
|
dw_printf (" performance.\n");
|
||||||
|
|
||||||
exit (1);
|
exit (1);
|
||||||
|
|
16
audio.h
16
audio.h
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "direwolf.h" /* for MAX_CHANS used throughout the application. */
|
#include "direwolf.h" /* for MAX_CHANS used throughout the application. */
|
||||||
#include "ax25_pad.h" /* for AX25_MAX_ADDR_LEN */
|
#include "ax25_pad.h" /* for AX25_MAX_ADDR_LEN */
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -141,6 +141,20 @@ struct audio_s {
|
||||||
/* Might try MFJ-2400 / CCITT v.26 / Bell 201 someday. */
|
/* Might try MFJ-2400 / CCITT v.26 / Bell 201 someday. */
|
||||||
/* No modem. Might want this for DTMF only channel. */
|
/* No modem. Might want this for DTMF only channel. */
|
||||||
|
|
||||||
|
enum v26_e { V26_UNSPECIFIED=0, V26_A, V26_B } v26_alternative;
|
||||||
|
|
||||||
|
// Original implementaion used alternative A for 2400 bbps PSK.
|
||||||
|
// Years later, we discover that MFJ-2400 used alternative B.
|
||||||
|
// It's likely the others did too.
|
||||||
|
// For release 1.6, default to original style but print warning.
|
||||||
|
// Later default to MFJ compatible and still print warning if
|
||||||
|
// if user did not pick one explicitly.
|
||||||
|
|
||||||
|
#if (MAJOR_VERSION > 1) || (MINOR_VERSION > 6)
|
||||||
|
#define V26_DEFAULT V26_B
|
||||||
|
#else
|
||||||
|
#define V26_DEFAULT V26_A
|
||||||
|
#endif
|
||||||
|
|
||||||
enum dtmf_decode_t { DTMF_DECODE_OFF, DTMF_DECODE_ON } dtmf_decode;
|
enum dtmf_decode_t { DTMF_DECODE_OFF, DTMF_DECODE_ON } dtmf_decode;
|
||||||
|
|
||||||
|
|
15
config.c
15
config.c
|
@ -761,6 +761,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
/* set to radio when corresponding */
|
/* set to radio when corresponding */
|
||||||
/* audio device is defined. */
|
/* audio device is defined. */
|
||||||
p_audio_config->achan[channel].modem_type = MODEM_AFSK;
|
p_audio_config->achan[channel].modem_type = MODEM_AFSK;
|
||||||
|
p_audio_config->achan[channel].v26_alternative = V26_UNSPECIFIED;
|
||||||
p_audio_config->achan[channel].mark_freq = DEFAULT_MARK_FREQ; /* -m option */
|
p_audio_config->achan[channel].mark_freq = DEFAULT_MARK_FREQ; /* -m option */
|
||||||
p_audio_config->achan[channel].space_freq = DEFAULT_SPACE_FREQ; /* -s option */
|
p_audio_config->achan[channel].space_freq = DEFAULT_SPACE_FREQ; /* -s option */
|
||||||
p_audio_config->achan[channel].baud = DEFAULT_BAUD; /* -b option */
|
p_audio_config->achan[channel].baud = DEFAULT_BAUD; /* -b option */
|
||||||
|
@ -1264,6 +1265,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
* *9 - Upsample ratio for G3RUH.
|
* *9 - Upsample ratio for G3RUH.
|
||||||
* [A-Z+-]+ - Letters, plus, minus for the demodulator "profile."
|
* [A-Z+-]+ - Letters, plus, minus for the demodulator "profile."
|
||||||
* g3ruh - This modem type regardless of default for speed.
|
* g3ruh - This modem type regardless of default for speed.
|
||||||
|
* v26a or v26b - V.26 alternative. a=original, b=MFJ compatible
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "MODEM") == 0) {
|
else if (strcasecmp(t, "MODEM") == 0) {
|
||||||
|
@ -1540,6 +1542,19 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
p_audio_config->achan[channel].space_freq = 0;
|
p_audio_config->achan[channel].space_freq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (strcasecmp(t, "V26A") == 0 || /* Compatible with direwolf versions <= 1.5. New in 1.6. */
|
||||||
|
strcasecmp(t, "V26B") == 0) { /* Compatible with MFJ-2400. New in 1.6. */
|
||||||
|
|
||||||
|
if (p_audio_config->achan[channel].modem_type != MODEM_QPSK ||
|
||||||
|
p_audio_config->achan[channel].baud != 2400) {
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Line %d: %s option can only be used with 2400 bps PSK.\n", line, t);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p_audio_config->achan[channel].v26_alternative = (strcasecmp(t, "V26A") == 0) ? V26_A : V26_B;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Line %d: Unrecognized option for MODEM: %s\n", line, t);
|
dw_printf ("Line %d: Unrecognized option for MODEM: %s\n", line, t);
|
||||||
|
|
36
demod.c
36
demod.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2019 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -94,7 +94,6 @@ static int sample_count[MAX_CHANS][MAX_SUBCHANS];
|
||||||
|
|
||||||
int demod_init (struct audio_s *pa)
|
int demod_init (struct audio_s *pa)
|
||||||
{
|
{
|
||||||
//int j;
|
|
||||||
int chan; /* Loop index over number of radio channels. */
|
int chan; /* Loop index over number of radio channels. */
|
||||||
char profile;
|
char profile;
|
||||||
|
|
||||||
|
@ -520,6 +519,31 @@ int demod_init (struct audio_s *pa)
|
||||||
|
|
||||||
case MODEM_QPSK: // New for 1.4
|
case MODEM_QPSK: // New for 1.4
|
||||||
|
|
||||||
|
// In versions 1.4 and 1.5, V.26 "Alternative A" was used.
|
||||||
|
// years later, I discover that the MFJ-2400 used "Alternative B."
|
||||||
|
// It looks like the other two manufacturers use the same but we
|
||||||
|
// can't be sure until we find one for compatbility testing.
|
||||||
|
|
||||||
|
// In version 1.6 we add a choice for the user.
|
||||||
|
// If neither one was explicitly specified, print a message and take
|
||||||
|
// a default. My current thinking is that we default to direwolf <= 1.5
|
||||||
|
// compatible for version 1.6 and MFJ compatible after that.
|
||||||
|
|
||||||
|
if (save_audio_config_p->achan[chan].v26_alternative == V26_UNSPECIFIED) {
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Two incompatible versions of 2400 bps QPSK are now available.\n");
|
||||||
|
dw_printf ("For compatbility with direwolf <= 1.5, use 'V26A' modem option in config file.\n");
|
||||||
|
dw_printf ("For compatbility MFJ-2400 use 'V26B' modem option in config file.\n");
|
||||||
|
dw_printf ("Command line options -j and -J can be used for channel 0.\n");
|
||||||
|
dw_printf ("For more information, read the Dire Wolf User Guide and\n");
|
||||||
|
dw_printf ("2400-4800-PSK-for-APRS-Packet-Radio.pdf.\n");
|
||||||
|
dw_printf ("The default in this release could be different in a later release.\n");
|
||||||
|
|
||||||
|
save_audio_config_p->achan[chan].v26_alternative = V26_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: See how much CPU this takes on ARM and decide if we should have different defaults.
|
// TODO: See how much CPU this takes on ARM and decide if we should have different defaults.
|
||||||
|
|
||||||
if (strlen(save_audio_config_p->achan[chan].profiles) == 0) {
|
if (strlen(save_audio_config_p->achan[chan].profiles) == 0) {
|
||||||
|
@ -539,6 +563,12 @@ int demod_init (struct audio_s *pa)
|
||||||
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec);
|
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec);
|
||||||
if (save_audio_config_p->achan[chan].decimate != 1)
|
if (save_audio_config_p->achan[chan].decimate != 1)
|
||||||
dw_printf (" / %d", save_audio_config_p->achan[chan].decimate);
|
dw_printf (" / %d", save_audio_config_p->achan[chan].decimate);
|
||||||
|
|
||||||
|
if (save_audio_config_p->achan[chan].v26_alternative == V26_B)
|
||||||
|
dw_printf (", compatible with MFJ-2400");
|
||||||
|
else
|
||||||
|
dw_printf (", compatible with earlier direwolf");
|
||||||
|
|
||||||
if (save_audio_config_p->achan[chan].dtmf_decode != DTMF_DECODE_OFF)
|
if (save_audio_config_p->achan[chan].dtmf_decode != DTMF_DECODE_OFF)
|
||||||
dw_printf (", DTMF decoder enabled");
|
dw_printf (", DTMF decoder enabled");
|
||||||
dw_printf (".\n");
|
dw_printf (".\n");
|
||||||
|
@ -556,6 +586,7 @@ int demod_init (struct audio_s *pa)
|
||||||
// save_audio_config_p->achan[chan].modem_type, profile);
|
// save_audio_config_p->achan[chan].modem_type, profile);
|
||||||
|
|
||||||
demod_psk_init (save_audio_config_p->achan[chan].modem_type,
|
demod_psk_init (save_audio_config_p->achan[chan].modem_type,
|
||||||
|
save_audio_config_p->achan[chan].v26_alternative,
|
||||||
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec / save_audio_config_p->achan[chan].decimate,
|
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec / save_audio_config_p->achan[chan].decimate,
|
||||||
save_audio_config_p->achan[chan].baud,
|
save_audio_config_p->achan[chan].baud,
|
||||||
profile,
|
profile,
|
||||||
|
@ -610,6 +641,7 @@ int demod_init (struct audio_s *pa)
|
||||||
// save_audio_config_p->achan[chan].modem_type, profile);
|
// save_audio_config_p->achan[chan].modem_type, profile);
|
||||||
|
|
||||||
demod_psk_init (save_audio_config_p->achan[chan].modem_type,
|
demod_psk_init (save_audio_config_p->achan[chan].modem_type,
|
||||||
|
save_audio_config_p->achan[chan].v26_alternative,
|
||||||
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec / save_audio_config_p->achan[chan].decimate,
|
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec / save_audio_config_p->achan[chan].decimate,
|
||||||
save_audio_config_p->achan[chan].baud,
|
save_audio_config_p->achan[chan].baud,
|
||||||
profile,
|
profile,
|
||||||
|
|
65
demod_psk.c
65
demod_psk.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2016 John Langner, WB2OSZ
|
// Copyright (C) 2016, 2019 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
//#define DEBUG4 1 /* capture PSK demodulator output to log files */
|
//#define DEBUG4 1 /* capture PSK demodulator output to log files */
|
||||||
|
|
||||||
|
//#define DEBUG5 1 /* Print bit stream */
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
|
@ -63,8 +64,7 @@
|
||||||
* http://www.brazoriacountyares.org/winlink-collection/TNC%20manuals/Kantronics/2400_modem_operators_guide@rgf.pdf
|
* http://www.brazoriacountyares.org/winlink-collection/TNC%20manuals/Kantronics/2400_modem_operators_guide@rgf.pdf
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* The MFJ and AEA both use the EXAR XR-2123 PSK modem chip.
|
* From what I'm able to gather, they all used the EXAR XR-2123 PSK modem chip.
|
||||||
* The Kantronics has a P423 ???
|
|
||||||
*
|
*
|
||||||
* Can't find the chip specs on the EXAR website so Google it.
|
* Can't find the chip specs on the EXAR website so Google it.
|
||||||
*
|
*
|
||||||
|
@ -79,8 +79,8 @@
|
||||||
* "bis" and "ter" are from Latin for second and third.
|
* "bis" and "ter" are from Latin for second and third.
|
||||||
* I used the "ter" version which has phase shifts of 0, 90, 180, and 270 degrees.
|
* I used the "ter" version which has phase shifts of 0, 90, 180, and 270 degrees.
|
||||||
*
|
*
|
||||||
* There are other references to an alternative B which uses other multiples of 45.
|
* There are ealier references to an alternative B which uses other phase shifts offset
|
||||||
* The XR-2123 data sheet mentions only multiples of 90. That's what I went with.
|
* by another 45 degrees.
|
||||||
*
|
*
|
||||||
* The XR-2123 does not perform the scrambling as specified in V.26 so I wonder if
|
* The XR-2123 does not perform the scrambling as specified in V.26 so I wonder if
|
||||||
* the vendors implemented it in software or just left it out.
|
* the vendors implemented it in software or just left it out.
|
||||||
|
@ -161,6 +161,8 @@ static inline float my_atan2f (float y, float x)
|
||||||
*
|
*
|
||||||
* Inputs: modem_type - MODEM_QPSK or MODEM_8PSK.
|
* Inputs: modem_type - MODEM_QPSK or MODEM_8PSK.
|
||||||
*
|
*
|
||||||
|
* v26_alt - V26_A (classic) or V25_B (MFJ compatible)
|
||||||
|
*
|
||||||
* samples_per_sec - Audio sample rate.
|
* samples_per_sec - Audio sample rate.
|
||||||
*
|
*
|
||||||
* bps - Bits per second.
|
* bps - Bits per second.
|
||||||
|
@ -189,7 +191,7 @@ static inline float my_atan2f (float y, float x)
|
||||||
*
|
*
|
||||||
*----------------------------------------------------------------*/
|
*----------------------------------------------------------------*/
|
||||||
|
|
||||||
void demod_psk_init (enum modem_t modem_type, int samples_per_sec, int bps, char profile, struct demodulator_state_s *D)
|
void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_per_sec, int bps, char profile, struct demodulator_state_s *D)
|
||||||
{
|
{
|
||||||
int correct_baud; // baud is not same as bits/sec here!
|
int correct_baud; // baud is not same as bits/sec here!
|
||||||
int carrier_freq;
|
int carrier_freq;
|
||||||
|
@ -199,6 +201,8 @@ void demod_psk_init (enum modem_t modem_type, int samples_per_sec, int bps, char
|
||||||
memset (D, 0, sizeof(struct demodulator_state_s));
|
memset (D, 0, sizeof(struct demodulator_state_s));
|
||||||
|
|
||||||
D->modem_type = modem_type;
|
D->modem_type = modem_type;
|
||||||
|
D->v26_alt = v26_alt;
|
||||||
|
|
||||||
D->num_slicers = 1; // Haven't thought about this yet. Is it even applicable?
|
D->num_slicers = 1; // Haven't thought about this yet. Is it even applicable?
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,6 +214,8 @@ void demod_psk_init (enum modem_t modem_type, int samples_per_sec, int bps, char
|
||||||
|
|
||||||
if (modem_type == MODEM_QPSK) {
|
if (modem_type == MODEM_QPSK) {
|
||||||
|
|
||||||
|
assert (D->v26_alt != V26_UNSPECIFIED);
|
||||||
|
|
||||||
correct_baud = bps / 2;
|
correct_baud = bps / 2;
|
||||||
// Originally I thought of scaling it to the data rate,
|
// Originally I thought of scaling it to the data rate,
|
||||||
// e.g. 2400 bps -> 1800 Hz, but decided to make it a
|
// e.g. 2400 bps -> 1800 Hz, but decided to make it a
|
||||||
|
@ -645,7 +651,16 @@ void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulato
|
||||||
id = ((int)((delta / (2.f * (float)M_PI) + 1.f) * 256.f)) & 0xff;
|
id = ((int)((delta / (2.f * (float)M_PI) + 1.f) * 256.f)) & 0xff;
|
||||||
|
|
||||||
if (D->modem_type == MODEM_QPSK) {
|
if (D->modem_type == MODEM_QPSK) {
|
||||||
demod_phase_shift = ((id + 32) >> 6) & 0x3;
|
#ifdef TUNE_PSKOFFSET
|
||||||
|
demod_phase_shift = ((id + TUNE_PSKOFFSET) >> 6) & 0x3;
|
||||||
|
#else
|
||||||
|
if (D->v26_alt == V26_B) {
|
||||||
|
demod_phase_shift = ((id + 2) >> 6) & 0x3; // MFJ compatible
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
demod_phase_shift = ((id + 32) >> 6) & 0x3; // Classic
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
demod_phase_shift = ((id + 16) >> 5) & 0x7;
|
demod_phase_shift = ((id + 16) >> 5) & 0x7;
|
||||||
|
@ -671,25 +686,20 @@ void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulato
|
||||||
|
|
||||||
if (D->modem_type == MODEM_QPSK) {
|
if (D->modem_type == MODEM_QPSK) {
|
||||||
|
|
||||||
#if 1 // Speed up special case.
|
float a = my_atan2f(I,Q);
|
||||||
if (I > 0) {
|
|
||||||
if (Q > 0)
|
|
||||||
demod_phase_shift = 0; /* 0 to 90 degrees, etc. */
|
|
||||||
else
|
|
||||||
demod_phase_shift = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (Q > 0)
|
|
||||||
demod_phase_shift = 3;
|
|
||||||
else
|
|
||||||
demod_phase_shift = 2;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
a = my_atan2f(I,Q);
|
|
||||||
int id = ((int)((a / (2.f * (float)M_PI) + 1.f) * 256.f)) & 0xff;
|
int id = ((int)((a / (2.f * (float)M_PI) + 1.f) * 256.f)) & 0xff;
|
||||||
// 128 compensates for 180 degree phase shift due
|
// 128 compensates for 180 degree phase shift due
|
||||||
// to 1 1/2 carrier cycles per symbol period.
|
// to 1 1/2 carrier cycles per symbol period.
|
||||||
demod_phase_shift = ((id + 128) >> 6) & 0x3;
|
|
||||||
|
#ifdef TUNE_PSKOFFSET
|
||||||
|
demod_phase_shift = ((id + TUNE_PSKOFFSET) >> 6) & 0x3;
|
||||||
|
#else
|
||||||
|
if (D->v26_alt == V26_B) {
|
||||||
|
demod_phase_shift = ((id + 98) >> 6) & 0x3; // MFJ compatible
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
demod_phase_shift = ((id + 128) >> 6) & 0x3; // Classic
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -752,7 +762,13 @@ void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulato
|
||||||
|
|
||||||
} /* end demod_psk_process_sample */
|
} /* end demod_psk_process_sample */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TUNE_GRAY
|
||||||
|
TUNE_GRAY
|
||||||
|
#else
|
||||||
static const int phase_to_gray_v26[4] = {0, 1, 3, 2};
|
static const int phase_to_gray_v26[4] = {0, 1, 3, 2};
|
||||||
|
#endif
|
||||||
|
|
||||||
static const int phase_to_gray_v27[8] = {1, 0, 2, 3, 7, 6, 4, 5};
|
static const int phase_to_gray_v27[8] = {1, 0, 2, 3, 7, 6, 4, 5};
|
||||||
|
|
||||||
|
|
||||||
|
@ -813,6 +829,9 @@ inline static void nudge_pll (int chan, int subchan, int slice, int demod_bits,
|
||||||
a * 360 / (2*M_PI), delta * 360 / (2*M_PI), demod_bits, (gray >> 1) & 1, gray & 1);
|
a * 360 / (2*M_PI), delta * 360 / (2*M_PI), demod_bits, (gray >> 1) & 1, gray & 1);
|
||||||
|
|
||||||
//dw_printf ("phaseshift=%d, bits= %d %d \n", demod_bits, (gray >> 1) & 1, gray & 1);
|
//dw_printf ("phaseshift=%d, bits= %d %d \n", demod_bits, (gray >> 1) & 1, gray & 1);
|
||||||
|
#endif
|
||||||
|
#if DEBUG5
|
||||||
|
dw_printf ("%d\n%d\n", (gray >> 1) & 1, gray & 1);
|
||||||
#endif
|
#endif
|
||||||
hdlc_rec_bit (chan, subchan, slice, (gray >> 1) & 1, 0, -1);
|
hdlc_rec_bit (chan, subchan, slice, (gray >> 1) & 1, 0, -1);
|
||||||
hdlc_rec_bit (chan, subchan, slice, gray & 1, 0, -1);
|
hdlc_rec_bit (chan, subchan, slice, gray & 1, 0, -1);
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
/* demod_psk.h */
|
/* demod_psk.h */
|
||||||
|
|
||||||
|
|
||||||
void demod_psk_init (enum modem_t modem_type, int samples_per_sec, int bps, char profile, struct demodulator_state_s *D);
|
void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_per_sec, int bps, char profile, struct demodulator_state_s *D);
|
||||||
|
|
||||||
void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulator_state_s *D);
|
void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulator_state_s *D);
|
||||||
|
|
44
direwolf.c
44
direwolf.c
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -201,6 +201,8 @@ int main (int argc, char *argv[])
|
||||||
int t_opt = 1; /* Text color option. */
|
int t_opt = 1; /* Text color option. */
|
||||||
int a_opt = 0; /* "-a n" interval, in seconds, for audio statistics report. 0 for none. */
|
int a_opt = 0; /* "-a n" interval, in seconds, for audio statistics report. 0 for none. */
|
||||||
int g_opt = 0; /* G3RUH mode, ignoring default for speed. */
|
int g_opt = 0; /* G3RUH mode, ignoring default for speed. */
|
||||||
|
int j_opt = 0; /* 2400 bps PSK compatible with direwolf <= 1.5 */
|
||||||
|
int J_opt = 0; /* 2400 bps PSK compatible MFJ-2400 and maybe others. */
|
||||||
|
|
||||||
int d_k_opt = 0; /* "-d k" option for serial port KISS. Can be repeated for more detail. */
|
int d_k_opt = 0; /* "-d k" option for serial port KISS. Can be repeated for more detail. */
|
||||||
int d_n_opt = 0; /* "-d n" option for Network KISS. Can be repeated for more detail. */
|
int d_n_opt = 0; /* "-d n" option for Network KISS. Can be repeated for more detail. */
|
||||||
|
@ -354,7 +356,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
/* ':' following option character means arg is required. */
|
/* ':' following option character means arg is required. */
|
||||||
|
|
||||||
c = getopt_long(argc, argv, "P:B:gD:U:c:pxr:b:n:d:q:t:ul:L:Sa:E:T:",
|
c = getopt_long(argc, argv, "P:B:gjJD:U:c:pxr:b:n:d:q:t:ul:L:Sa:E:T:",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -411,6 +413,16 @@ int main (int argc, char *argv[])
|
||||||
g_opt = 1;
|
g_opt = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'j': /* -j V.26 compatible with earlier direwolf. */
|
||||||
|
|
||||||
|
j_opt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J': /* -J V.26 compatible with MFJ-2400. */
|
||||||
|
|
||||||
|
J_opt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'P': /* -P for modem profile. */
|
case 'P': /* -P for modem profile. */
|
||||||
|
|
||||||
//debug: dw_printf ("Demodulator profile set to \"%s\"\n", optarg);
|
//debug: dw_printf ("Demodulator profile set to \"%s\"\n", optarg);
|
||||||
|
@ -691,11 +703,34 @@ int main (int argc, char *argv[])
|
||||||
audio_config.achan[0].space_freq = 0;
|
audio_config.achan[0].space_freq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (j_opt) {
|
||||||
|
|
||||||
|
// V.26 compatible with earlier versions of direwolf.
|
||||||
|
// Example: -B 2400 -j or simply -j
|
||||||
|
|
||||||
|
audio_config.achan[0].v26_alternative = V26_A;
|
||||||
|
audio_config.achan[0].modem_type = MODEM_QPSK;
|
||||||
|
audio_config.achan[0].mark_freq = 0;
|
||||||
|
audio_config.achan[0].space_freq = 0;
|
||||||
|
audio_config.achan[0].baud = 2400;
|
||||||
|
}
|
||||||
|
if (J_opt) {
|
||||||
|
|
||||||
|
// V.26 compatible with MFJ and maybe others.
|
||||||
|
// Example: -B 2400 -J or simply -J
|
||||||
|
|
||||||
|
audio_config.achan[0].v26_alternative = V26_B;
|
||||||
|
audio_config.achan[0].modem_type = MODEM_QPSK;
|
||||||
|
audio_config.achan[0].mark_freq = 0;
|
||||||
|
audio_config.achan[0].space_freq = 0;
|
||||||
|
audio_config.achan[0].baud = 2400;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
audio_config.statistics_interval = a_opt;
|
audio_config.statistics_interval = a_opt;
|
||||||
|
|
||||||
if (strlen(P_opt) > 0) {
|
if (strlen(P_opt) > 0) {
|
||||||
/* -P for modem profile. */
|
/* -P for modem profile. */
|
||||||
/* TODO: Not yet documented. Should probably since it is consistent with atest. */
|
|
||||||
strlcpy (audio_config.achan[0].profiles, P_opt, sizeof(audio_config.achan[0].profiles));
|
strlcpy (audio_config.achan[0].profiles, P_opt, sizeof(audio_config.achan[0].profiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1293,6 +1328,9 @@ static void usage (char **argv)
|
||||||
dw_printf (" 4800 bps uses 8PSK based on V.27 standard.\n");
|
dw_printf (" 4800 bps uses 8PSK based on V.27 standard.\n");
|
||||||
dw_printf (" 9600 bps and up uses K9NG/G3RUH standard.\n");
|
dw_printf (" 9600 bps and up uses K9NG/G3RUH standard.\n");
|
||||||
dw_printf (" -g Force G3RUH modem regardless of speed.\n");
|
dw_printf (" -g Force G3RUH modem regardless of speed.\n");
|
||||||
|
dw_printf (" -j 2400 bps QPSK compatible with direwolf <= 1.5.\n");
|
||||||
|
dw_printf (" -J 2400 bps QPSK compatible with MFJ-2400.\n");
|
||||||
|
dw_printf (" -P xxx Modem Profiles.\n");
|
||||||
dw_printf (" -D n Divide audio sample rate by n for channel 0.\n");
|
dw_printf (" -D n Divide audio sample rate by n for channel 0.\n");
|
||||||
dw_printf (" -d Debug options:\n");
|
dw_printf (" -d Debug options:\n");
|
||||||
dw_printf (" a a = AGWPE network protocol client.\n");
|
dw_printf (" a a = AGWPE network protocol client.\n");
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -28,6 +28,8 @@ struct demodulator_state_s
|
||||||
*/
|
*/
|
||||||
enum modem_t modem_type; // MODEM_AFSK, MODEM_8PSK, etc.
|
enum modem_t modem_type; // MODEM_AFSK, MODEM_8PSK, etc.
|
||||||
|
|
||||||
|
enum v26_e v26_alt; // Which alternative when V.26.
|
||||||
|
|
||||||
char profile; // 'A', 'B', etc. Upper case.
|
char profile; // 'A', 'B', etc. Upper case.
|
||||||
// Only needed to see if we are using 'F' to take fast path.
|
// Only needed to see if we are using 'F' to take fast path.
|
||||||
|
|
||||||
|
@ -145,6 +147,7 @@ struct demodulator_state_s
|
||||||
|
|
||||||
float pre_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
float pre_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel for the mark and space detection filters.
|
* Kernel for the mark and space detection filters.
|
||||||
*/
|
*/
|
||||||
|
@ -227,6 +230,7 @@ struct demodulator_state_s
|
||||||
float m_valley, s_valley;
|
float m_valley, s_valley;
|
||||||
float m_amp_prev, s_amp_prev;
|
float m_amp_prev, s_amp_prev;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the PLL and data bit timing.
|
* For the PLL and data bit timing.
|
||||||
* starting in version 1.2 we can have multiple slicers for one demodulator.
|
* starting in version 1.2 we can have multiple slicers for one demodulator.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2013, 2014, 2015, 2016, 2019 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -164,6 +164,9 @@ int main(int argc, char **argv)
|
||||||
int chan;
|
int chan;
|
||||||
int experiment = 0;
|
int experiment = 0;
|
||||||
|
|
||||||
|
int g_opt = 0;
|
||||||
|
int j_opt = 0;
|
||||||
|
int J_opt = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up default values for the modem.
|
* Set up default values for the modem.
|
||||||
|
@ -215,7 +218,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* ':' following option character means arg is required. */
|
/* ':' following option character means arg is required. */
|
||||||
|
|
||||||
c = getopt_long(argc, argv, "gm:s:a:b:B:r:n:o:z:82M:X",
|
c = getopt_long(argc, argv, "gjJm:s:a:b:B:r:n:o:z:82M:X",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -310,11 +313,17 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
case 'g': /* -g for g3ruh scrambling */
|
case 'g': /* -g for g3ruh scrambling */
|
||||||
|
|
||||||
// FIXME: order dependent. -g must come after -B.
|
g_opt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
modem.achan[0].modem_type = MODEM_SCRAMBLE;
|
case 'j': /* -j V.26 compatible with earlier direwolf. */
|
||||||
text_color_set(DW_COLOR_INFO);
|
|
||||||
dw_printf ("Using scrambled baseband signal rather than AFSK.\n");
|
j_opt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J': /* -J V.26 compatible with MFJ-2400. */
|
||||||
|
|
||||||
|
J_opt = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm': /* -m for Mark freq */
|
case 'm': /* -m for Mark freq */
|
||||||
|
@ -449,6 +458,41 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These must be processed after -B option.
|
||||||
|
|
||||||
|
if (g_opt) { /* -g for g3ruh scrambling */
|
||||||
|
|
||||||
|
modem.achan[0].modem_type = MODEM_SCRAMBLE;
|
||||||
|
text_color_set(DW_COLOR_INFO);
|
||||||
|
dw_printf ("Using G3RUH mode regardless of bit rate.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j_opt) { /* -j V.26 compatible with earlier direwolf. */
|
||||||
|
|
||||||
|
modem.achan[0].v26_alternative = V26_A;
|
||||||
|
modem.achan[0].modem_type = MODEM_QPSK;
|
||||||
|
modem.achan[0].mark_freq = 0;
|
||||||
|
modem.achan[0].space_freq = 0;
|
||||||
|
modem.achan[0].baud = 2400;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (J_opt) { /* -J V.26 compatible with MFJ-2400. */
|
||||||
|
|
||||||
|
modem.achan[0].v26_alternative = V26_B;
|
||||||
|
modem.achan[0].modem_type = MODEM_QPSK;
|
||||||
|
modem.achan[0].mark_freq = 0;
|
||||||
|
modem.achan[0].space_freq = 0;
|
||||||
|
modem.achan[0].baud = 2400;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modem.achan[0].modem_type == MODEM_QPSK &&
|
||||||
|
modem.achan[0].v26_alternative == V26_UNSPECIFIED) {
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("ERROR: Either -j or -J must be specified when using 2400 bps QPSK.\n");
|
||||||
|
usage (argv);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the output file.
|
* Open the output file.
|
||||||
|
@ -689,6 +733,8 @@ static void usage (char **argv)
|
||||||
dw_printf (" -b <number> Bits / second for data. Default is %d.\n", DEFAULT_BAUD);
|
dw_printf (" -b <number> Bits / second for data. Default is %d.\n", DEFAULT_BAUD);
|
||||||
dw_printf (" -B <number> Bits / second for data. Proper modem selected for 300, 1200, 2400, 4800, 9600.\n");
|
dw_printf (" -B <number> Bits / second for data. Proper modem selected for 300, 1200, 2400, 4800, 9600.\n");
|
||||||
dw_printf (" -g Scrambled baseband rather than AFSK.\n");
|
dw_printf (" -g Scrambled baseband rather than AFSK.\n");
|
||||||
|
dw_printf (" -j 2400 bps QPSK compatible with direwolf <= 1.5.\n");
|
||||||
|
dw_printf (" -J 2400 bps QPSK compatible with MFJ-2400.\n");
|
||||||
dw_printf (" -m <number> Mark frequency. Default is %d.\n", DEFAULT_MARK_FREQ);
|
dw_printf (" -m <number> Mark frequency. Default is %d.\n", DEFAULT_MARK_FREQ);
|
||||||
dw_printf (" -s <number> Space frequency. Default is %d.\n", DEFAULT_SPACE_FREQ);
|
dw_printf (" -s <number> Space frequency. Default is %d.\n", DEFAULT_SPACE_FREQ);
|
||||||
dw_printf (" -r <number> Audio sample Rate. Default is %d.\n", DEFAULT_SAMPLES_PER_SEC);
|
dw_printf (" -r <number> Audio sample Rate. Default is %d.\n", DEFAULT_SAMPLES_PER_SEC);
|
||||||
|
|
|
@ -280,6 +280,8 @@ int gen_tone_init (struct audio_s *audio_config_p, int amp, int gen_packets)
|
||||||
* This avoids overshoot, ringing, and adding more jitter.
|
* This avoids overshoot, ringing, and adding more jitter.
|
||||||
* Alternating bits come out has sine wave of baud/2 Hz.
|
* Alternating bits come out has sine wave of baud/2 Hz.
|
||||||
*
|
*
|
||||||
|
* Version 1.6: MFJ-2400 compatibility for V.26.
|
||||||
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
static const int gray2phase_v26[4] = {0, 1, 3, 2};
|
static const int gray2phase_v26[4] = {0, 1, 3, 2};
|
||||||
|
@ -304,6 +306,8 @@ void tone_gen_put_bit (int chan, int dat)
|
||||||
dat = 0;
|
dat = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: change to switch instead of if if if
|
||||||
|
|
||||||
if (save_audio_config_p->achan[chan].modem_type == MODEM_QPSK) {
|
if (save_audio_config_p->achan[chan].modem_type == MODEM_QPSK) {
|
||||||
|
|
||||||
int dibit;
|
int dibit;
|
||||||
|
@ -324,7 +328,9 @@ void tone_gen_put_bit (int chan, int dat)
|
||||||
|
|
||||||
symbol = gray2phase_v26[dibit];
|
symbol = gray2phase_v26[dibit];
|
||||||
tone_phase[chan] += symbol * PHASE_SHIFT_90;
|
tone_phase[chan] += symbol * PHASE_SHIFT_90;
|
||||||
|
if (save_audio_config_p->achan[chan].v26_alternative == V26_B) {
|
||||||
|
tone_phase[chan] += PHASE_SHIFT_45;
|
||||||
|
}
|
||||||
bit_count[chan]++;
|
bit_count[chan]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
55
man1/atest.1
55
man1/atest.1
|
@ -21,17 +21,46 @@ atest \- Decode AX.25 frames from an audio file.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-B " "n"
|
.BI "-B " "n"
|
||||||
Bits / second for data. Proper modem selected for 300, 1200, 9600.
|
Data rate in bits/sec. Standard values are 300, 1200, 2400, 4800, 9600.
|
||||||
300 baud uses 1600/1800 Hz AFSK.
|
.PD 0
|
||||||
1200 (default) baud uses 1200/2200 Hz AFSK.
|
.RS
|
||||||
9600 baud uses K9NG/G2RUH standard.
|
.RS
|
||||||
|
300 bps defaults to AFSK tones of 1600 & 1800.
|
||||||
|
.P
|
||||||
|
1200 bps uses AFSK tones of 1200 & 2200.
|
||||||
|
.P
|
||||||
|
2400 bps uses QPSK based on V.26 standard.
|
||||||
|
.P
|
||||||
|
4800 bps uses 8PSK based on V.27 standard.
|
||||||
|
.P
|
||||||
|
9600 bps and up uses K9NG/G3RUH standard.
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.PD
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-g "
|
||||||
|
Force G3RUH modem regardless of data rate.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-j "
|
||||||
|
2400 bps QPSK compatible with Dire Wolf <= 1.5.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-J "
|
||||||
|
2400 bps QPSK compatible with MFJ-2400.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-D " "n"
|
.BI "-D " "n"
|
||||||
Divide audio sample rate by n.
|
Divide audio sample rate by n.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-h "
|
||||||
|
Print frame contents as hexadecimal bytes.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-F " "n"
|
.BI "-F " "n"
|
||||||
Amount of effort to try fixing frames with an invalid CRC.
|
Amount of effort to try fixing frames with an invalid CRC.
|
||||||
|
@ -39,9 +68,17 @@ Amount of effort to try fixing frames with an invalid CRC.
|
||||||
1 = Try to fix only a single bit.
|
1 = Try to fix only a single bit.
|
||||||
more = Try modifying more bits to get a good CRC.
|
more = Try modifying more bits to get a good CRC.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-L "
|
||||||
|
Error if Less than this number decoded.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-G "
|
||||||
|
Error if Greater than this number decoded.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-P " "m"
|
.BI "-P " "m"
|
||||||
Select the demodulator type such as A, B, C, D (default for 300 baud), E (default for 1200 baud), F, A+, B+, C+, D+, E+, F+.
|
Select the demodulator type such as D (default for 300 bps), E+ (default for 1200 bps), PQRS for 2400 bps, etc.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,20 +109,20 @@ This generates and decodes 3 test files with 1200, 300, and 9600 bits per second
|
||||||
.PD 0
|
.PD 0
|
||||||
.B atest 02_Track_2.wav
|
.B atest 02_Track_2.wav
|
||||||
.P
|
.P
|
||||||
.B atest -P C+ 02_Track_2.wav
|
.B atest -P E- 02_Track_2.wav
|
||||||
.P
|
.P
|
||||||
.B atest -F 1 02_Track_2.wav
|
.B atest -F 1 02_Track_2.wav
|
||||||
.P
|
.P
|
||||||
.B atest -P C+ -F 1 02_Track_2.wav
|
.B atest -P E- -F 1 02_Track_2.wav
|
||||||
.PD
|
.PD
|
||||||
.P
|
.P
|
||||||
.RS
|
.RS
|
||||||
Try different combinations of options to find the best decoding performance.
|
Try different combinations of options to compare decoding performance.
|
||||||
.RE
|
.RE
|
||||||
.P
|
.P
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
More detailed information is in the pdf files in /usr/local/share/doc/direwolf, or possibly /usr/share/doc/direwolf, depending on installation location.
|
More detailed information is in the pdf files in /usr/local/share/doc/direwolf, or possibly /usr/share/doc/direwolf, depending on installation location.
|
||||||
|
|
||||||
Applications in this package: aclients, atest, decode_aprs, direwolf, gen_packets, kissutil, ll2utm, log2gpx, text2tt, tt2text, utm2ll
|
Applications in this package: aclients, atest, cm108, decode_aprs, direwolf, gen_packets, kissutil, ll2utm, log2gpx, text2tt, tt2text, utm2ll
|
||||||
|
|
||||||
|
|
|
@ -48,19 +48,35 @@ Audio sample size for first channel. 8 or 16. Default 16.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-B " "n"
|
.BI "-B " "n"
|
||||||
Data rate in bits/sec for first channel. Standard values are 300, 1200, 9600.
|
Data rate in bits/sec for first channel. Standard values are 300, 1200, 2400, 4800, 9600.
|
||||||
.PD 0
|
.PD 0
|
||||||
.RS
|
.RS
|
||||||
.RS
|
.RS
|
||||||
If < 600, tones are set to 1600 & 1800.
|
300 bps defaults to AFSK tones of 1600 & 1800.
|
||||||
.P
|
.P
|
||||||
If > 2400, K9NG/G3RUH scrambling is used.
|
1200 bps uses AFSK tones of 1200 & 2200.
|
||||||
.P
|
.P
|
||||||
Otherwise, AFSK tones are set to 1200 & 2200.
|
2400 bps uses QPSK based on V.26 standard.
|
||||||
|
.P
|
||||||
|
4800 bps uses 8PSK based on V.27 standard.
|
||||||
|
.P
|
||||||
|
9600 bps and up uses K9NG/G3RUH standard.
|
||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.PD
|
.PD
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-g "
|
||||||
|
Force G3RUH modem regardless of data rate.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-j "
|
||||||
|
2400 bps QPSK compatible with Dire Wolf <= 1.5.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-J "
|
||||||
|
2400 bps QPSK compatible with MFJ-2400.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-D " "n"
|
.BI "-D " "n"
|
||||||
Divide audio sample by n for first channel.
|
Divide audio sample by n for first channel.
|
||||||
|
@ -92,6 +108,10 @@ o = Output controls such as PTT and DCD.
|
||||||
i = IGate
|
i = IGate
|
||||||
.P
|
.P
|
||||||
h = Hamlib verbose level. Repeat for more.
|
h = Hamlib verbose level. Repeat for more.
|
||||||
|
.P
|
||||||
|
m = Monitor heard station list.
|
||||||
|
.P
|
||||||
|
f = Packet filtering.
|
||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.PD
|
.PD
|
||||||
|
@ -152,5 +172,5 @@ rtl_fm \-f 144.39M \-o 4 \- | direwolf \-n 1 \-r 24000 \-b 16 \-
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
More detailed information is in the pdf files in /usr/local/share/doc/direwolf, or possibly /usr/share/doc/direwolf, depending on installation location.
|
More detailed information is in the pdf files in /usr/local/share/doc/direwolf, or possibly /usr/share/doc/direwolf, depending on installation location.
|
||||||
|
|
||||||
Applications in this package: aclients, atest, decode_aprs, direwolf, gen_packets, kissutil, ll2utm, log2gpx, text2tt, tt2text, utm2ll
|
Applications in this package: aclients, atest, cm108, decode_aprs, direwolf, gen_packets, kissutil, ll2utm, log2gpx, text2tt, tt2text, utm2ll
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,35 @@ Bits / second for data. Default is 1200.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-B " "n"
|
.BI "-B " "n"
|
||||||
Bits / second for data. Proper modem selected for 300, 1200, 9600.
|
Data rate in bits/sec for first channel. Standard values are 300, 1200, 2400, 4800, 9600.
|
||||||
|
.PD 0
|
||||||
|
.RS
|
||||||
|
.RS
|
||||||
|
300 bps defaults to AFSK tones of 1600 & 1800.
|
||||||
|
.P
|
||||||
|
1200 bps uses AFSK tones of 1200 & 2200.
|
||||||
|
.P
|
||||||
|
2400 bps uses QPSK based on V.26 standard.
|
||||||
|
.P
|
||||||
|
4800 bps uses 8PSK based on V.27 standard.
|
||||||
|
.P
|
||||||
|
9600 bps and up uses K9NG/G3RUH standard.
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.PD
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-g "
|
.BI "-g "
|
||||||
Scrambled baseband rather than AFSK.
|
Force G3RUH modem regardless of data rate.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-j "
|
||||||
|
2400 bps QPSK compatible with Dire Wolf <= 1.5.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-J "
|
||||||
|
2400 bps QPSK compatible with MFJ-2400.
|
||||||
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-m " "n"
|
.BI "-m " "n"
|
||||||
|
@ -112,5 +136,5 @@ Read message from stdin and put quarter volume sound into the file x.wav. Decod
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
More detailed information is in the pdf files in /usr/local/share/doc/direwolf, or possibly /usr/share/doc/direwolf, depending on installation location.
|
More detailed information is in the pdf files in /usr/local/share/doc/direwolf, or possibly /usr/share/doc/direwolf, depending on installation location.
|
||||||
|
|
||||||
Applications in this package: aclients, atest, decode_aprs, direwolf, gen_packets, ll2utm, log2gpx, text2tt, tt2text, utm2ll
|
Applications in this package: aclients, atest, cm108, decode_aprs, direwolf, gen_packets, kissutil, ll2utm, log2gpx, text2tt, tt2text, utm2ll
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue