Skip to content

Commit

Permalink
New AFSK demodulators.
Browse files Browse the repository at this point in the history
'A' uses mark and space filters but simpler and cleaner
than earlier attempts.
New 'B' uses a different technique where the demodulated
signal is proportional to the frequency.
  • Loading branch information
wb2osz committed Nov 28, 2020
1 parent fdf660a commit 9922f17
Show file tree
Hide file tree
Showing 12 changed files with 754 additions and 584 deletions.
18 changes: 10 additions & 8 deletions src/atest.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ int main (int argc, char *argv[])
my_audio_config.achan[channel].space_freq = DEFAULT_SPACE_FREQ;
my_audio_config.achan[channel].baud = DEFAULT_BAUD;

strlcpy (my_audio_config.achan[channel].profiles, "E", sizeof(my_audio_config.achan[channel].profiles));
strlcpy (my_audio_config.achan[channel].profiles, "A", sizeof(my_audio_config.achan[channel].profiles));

my_audio_config.achan[channel].num_freq = 1;
my_audio_config.achan[channel].offset = 0;
Expand Down Expand Up @@ -430,19 +430,21 @@ int main (int argc, char *argv[])
/* We have similar logic in direwolf.c, config.c, gen_packets.c, and atest.c, */
/* that need to be kept in sync. Maybe it could be a common function someday. */

if (my_audio_config.achan[0].baud == 100) {
if (my_audio_config.achan[0].baud == 100) { // What was this for?
my_audio_config.achan[0].modem_type = MODEM_AFSK;
my_audio_config.achan[0].mark_freq = 1615;
my_audio_config.achan[0].space_freq = 1785;
strlcpy (my_audio_config.achan[0].profiles, "D", sizeof(my_audio_config.achan[0].profiles));
//strlcpy (my_audio_config.achan[0].profiles, "A", sizeof(my_audio_config.achan[0].profiles));
}
else if (my_audio_config.achan[0].baud < 600) {
else if (my_audio_config.achan[0].baud < 600) { // e.g. HF SSB packet
my_audio_config.achan[0].modem_type = MODEM_AFSK;
my_audio_config.achan[0].mark_freq = 1600;
my_audio_config.achan[0].space_freq = 1800;
strlcpy (my_audio_config.achan[0].profiles, "D", sizeof(my_audio_config.achan[0].profiles));
// Previously we had a "D" which was fine tuned for 300 bps.
// In v1.7, it's not clear if we should use "B" or just stick with "A".
//strlcpy (my_audio_config.achan[0].profiles, "B", sizeof(my_audio_config.achan[0].profiles));
}
else if (my_audio_config.achan[0].baud < 1800) {
else if (my_audio_config.achan[0].baud < 1800) { // common 1200
my_audio_config.achan[0].modem_type = MODEM_AFSK;
my_audio_config.achan[0].mark_freq = DEFAULT_MARK_FREQ;
my_audio_config.achan[0].space_freq = DEFAULT_SPACE_FREQ;
Expand All @@ -460,7 +462,7 @@ int main (int argc, char *argv[])
my_audio_config.achan[0].space_freq = 0;
strlcpy (my_audio_config.achan[0].profiles, "", sizeof(my_audio_config.achan[0].profiles));
}
else if (my_audio_config.achan[0].baud == 12345) {
else if (my_audio_config.achan[0].baud == 12345) { // Hack for different use of 9600
my_audio_config.achan[0].modem_type = MODEM_AIS;
my_audio_config.achan[0].baud = 9600;
my_audio_config.achan[0].mark_freq = 0;
Expand All @@ -473,7 +475,7 @@ int main (int argc, char *argv[])
// Will make more precise in afsk demod init.
my_audio_config.achan[0].mark_freq = 2083; // Actually 2083.3 - logic 1.
my_audio_config.achan[0].space_freq = 1563; // Actually 1562.5 - logic 0.
strlcpy (my_audio_config.achan[0].profiles, "D", sizeof(my_audio_config.achan[0].profiles));
strlcpy (my_audio_config.achan[0].profiles, "A", sizeof(my_audio_config.achan[0].profiles));
}
else {
my_audio_config.achan[0].modem_type = MODEM_SCRAMBLE;
Expand Down
2 changes: 1 addition & 1 deletion src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
// Will make more precise in afsk demod init.
p_audio_config->achan[channel].mark_freq = 2083; // Actually 2083.3 - logic 1.
p_audio_config->achan[channel].space_freq = 1563; // Actually 1562.5 - logic 0.
// ? strlcpy (p_audio_config->achan[channel].profiles, "D", sizeof(p_audio_config->achan[channel].profiles));
// ? strlcpy (p_audio_config->achan[channel].profiles, "A", sizeof(p_audio_config->achan[channel].profiles));
}
else {
p_audio_config->achan[channel].modem_type = MODEM_SCRAMBLE;
Expand Down
67 changes: 39 additions & 28 deletions src/demod.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,46 +198,57 @@ int demod_init (struct audio_s *pa)
assert (num_letters == (int)(strlen(just_letters)));

/*
* Pick a good default demodulator if none specified.
* Pick a good default demodulator if none specified.
* Previously, we had "D" optimized for 300 bps.
* Gone in 1.7 so it is always "A+".
*/
if (num_letters == 0) {
strlcpy (just_letters, "A", sizeof(just_letters));
num_letters = strlen(just_letters);

if (save_audio_config_p->achan[chan].baud < 600) {

/* This has been optimized for 300 baud. */

strlcpy (just_letters, "D", sizeof(just_letters));
if (have_plus != -1) have_plus = 1; // Add as default for version 1.2
// If not explicitly turned off.
}

}
else {
/*
* Special case for ARM.
* The higher end ARM chips have loads of power but many people
* are using a single core Pi Zero or similar.
* (I'm still using a model 1 for my digipeater/IGate!)
* Decreasing CPU requirement has a negligible impact on decoding performance.
*
* atest -PA- 01_Track_1.wav --> 1002 packets decoded.
* atest -PA- -D3 01_Track_1.wav --> 997 packets decoded.
*
* Someone concerned about 1/2 of one percent difference can add "-D 1"
*/
#if __arm__
/* We probably don't have a lot of CPU power available. */
/* Previously we would use F if possible otherwise fall back to A. */

/* In version 1.2, new default is E+ /3. */
strlcpy (just_letters, "E", sizeof(just_letters)); // version 1.2 now E.
if (have_plus != -1) have_plus = 1; // Add as default for version 1.2
// If not explicitly turned off.
if (save_audio_config_p->achan[chan].decimate == 0) {
if (save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec > 40000) {
save_audio_config_p->achan[chan].decimate = 3;
}
}
#else
strlcpy (just_letters, "E", sizeof(just_letters)); // version 1.2 changed C to E.
if (have_plus != -1) have_plus = 1; // Add as default for version 1.2
// If not explicitly turned off.
#endif
if (save_audio_config_p->achan[chan].decimate == 0) {
if (save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec > 40000) {
save_audio_config_p->achan[chan].decimate = 3;
}
num_letters = 1;
}
#endif

/*
* Number of filter taps is proportional to number of audio samples in a "symbol" duration.
* These can get extremely large for low speeds, e.g. 300 baud.
* In this case, increase the decimation ration. Crude approximation. Could be improved.
*/
if (save_audio_config_p->achan[chan].decimate == 0 &&
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec > 40000 &&
save_audio_config_p->achan[chan].baud < 600) {

// Avoid enormous number of filter taps.

save_audio_config_p->achan[chan].decimate = 3;
}

assert (num_letters == (int)(strlen(just_letters)));

/*
* Put it back together again.
*/
assert (num_letters == (int)(strlen(just_letters)));

/* At this point, have_plus can have 3 values: */
/* 1 = turned on, either explicitly or by applied default */
Expand Down Expand Up @@ -286,7 +297,7 @@ int demod_init (struct audio_s *pa)

if (save_audio_config_p->achan[chan].decimate == 0) {
save_audio_config_p->achan[chan].decimate = 1;
if (strchr (just_letters, 'D') != NULL && save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec > 40000) {
if (strchr (just_letters, 'B') != NULL && save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec > 40000) {
save_audio_config_p->achan[chan].decimate = 3;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/demod_9600.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ void demod_9600_init (enum modem_t modem_type, int samples_per_sec, int baud, st

//dw_printf ("demod_9600_init: call gen_lowpass(fc=%.2f, , size=%d, )\n", fc, D->lp_filter_size);

(void)gen_lowpass (fc, D->lp_filter, D->lp_filter_size, D->lp_window, 0);
gen_lowpass (fc, D->lp_filter, D->lp_filter_size, D->lp_window);

/* Version 1.2: Experiment with different slicing levels. */

Expand Down
Loading

0 comments on commit 9922f17

Please sign in to comment.