aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bnetz/dsp.c2
-rw-r--r--src/datenklo/am791x.c2
-rw-r--r--src/libfsk/fsk.c167
-rw-r--r--src/libfsk/fsk.h10
-rw-r--r--src/nmt/dsp.c2
-rw-r--r--src/r2000/dsp.c4
6 files changed, 137 insertions, 50 deletions
diff --git a/src/bnetz/dsp.c b/src/bnetz/dsp.c
index 809cb53..5305183 100644
--- a/src/bnetz/dsp.c
+++ b/src/bnetz/dsp.c
@@ -420,7 +420,7 @@ void bnetz_set_dsp_mode(bnetz_t *bnetz, enum dsp_mode mode)
/* reset telegramm */
if (mode == DSP_MODE_TELEGRAMM && bnetz->dsp_mode != mode) {
bnetz->tx_telegramm = 0;
- fsk_mod_tx_reset(&bnetz->fsk_mod);
+ fsk_mod_reset(&bnetz->fsk_mod);
}
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", bnetz_dsp_mode_name(bnetz->dsp_mode), bnetz_dsp_mode_name(mode));
diff --git a/src/datenklo/am791x.c b/src/datenklo/am791x.c
index 146a779..b3164af 100644
--- a/src/datenklo/am791x.c
+++ b/src/datenklo/am791x.c
@@ -314,7 +314,7 @@ int send_sto(am791x_t *am791x, sample_t *sample, int length)
/* modulate STO */
phaseshift = am791x->sto_phaseshift65536;
- while (count < length && fsk->tx_bitpos < 1.0) {
+ while (count < length) {
sample[count++] = fsk->sin_tab[(uint16_t)phase];
phase += phaseshift;
if (phase >= 65536.0)
diff --git a/src/libfsk/fsk.c b/src/libfsk/fsk.c
index 6604de0..dcc437d 100644
--- a/src/libfsk/fsk.c
+++ b/src/libfsk/fsk.c
@@ -29,6 +29,12 @@
#define PI M_PI
+/* uncomment to see the modulated curve */
+//#define DEBUG_MODULATOR
+
+/* uncomment to see the shape of the filter */
+//#define DEBUG_MODULATOR_SHAPE
+
/*
* fsk = instance of fsk modem
* inst = instance of user
@@ -41,6 +47,7 @@
*/
int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int samplerate, double bitrate, double f0, double f1, double level, int ffsk, int filter)
{
+ double temp;
int i;
int rc;
@@ -49,7 +56,7 @@ int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int sa
memset(fsk, 0, sizeof(*fsk));
/* gen sine table with deviation */
- fsk->sin_tab = calloc(65536+16384, sizeof(*fsk->sin_tab));
+ fsk->sin_tab = calloc(65536, sizeof(*fsk->sin_tab));
if (!fsk->sin_tab) {
fprintf(stderr, "No mem!\n");
rc = -ENOMEM;
@@ -59,7 +66,6 @@ int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int sa
fsk->sin_tab[i] = sin((double)i / 65536.0 * 2.0 * PI) * level;
fsk->inst = inst;
- fsk->tx_bit = -1;
fsk->level = level;
fsk->send_bit = send_bit;
fsk->f0_deviation = (f0 - f1) / 2.0;
@@ -72,12 +78,12 @@ int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int sa
fsk->high_bit = 0;
}
- fsk->bits_per_sample = (double)bitrate / (double)samplerate;
- PDEBUG(DDSP, DEBUG_DEBUG, "Bitduration of %.4f bits per sample @ %d.\n", fsk->bits_per_sample, samplerate);
+ fsk->bits65536_per_sample = (double)bitrate / (double)samplerate * 65536.0;
+ PDEBUG(DDSP, DEBUG_DEBUG, "Bitduration of %.4f bits per sample @ %d.\n", fsk->bits65536_per_sample / 65536.0, samplerate);
fsk->phaseshift65536[0] = f0 / (double)samplerate * 65536.0;
- PDEBUG(DDSP, DEBUG_DEBUG, "F0 = %.0f Hz (phaseshift65536[0] = %.4f)\n", f0, fsk->phaseshift65536[0]);
fsk->phaseshift65536[1] = f1 / (double)samplerate * 65536.0;
+ PDEBUG(DDSP, DEBUG_DEBUG, "F0 = %.0f Hz (phaseshift65536[0] = %.4f)\n", f0, fsk->phaseshift65536[0]);
PDEBUG(DDSP, DEBUG_DEBUG, "F1 = %.0f Hz (phaseshift65536[1] = %.4f)\n", f1, fsk->phaseshift65536[1]);
/* use ffsk modulation, i.e. each bit has an integer number of
@@ -86,6 +92,12 @@ int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int sa
if (ffsk) {
double waves;
+ if (filter) {
+ PDEBUG(DDSP, DEBUG_ERROR, "Cannot use FFSK with filter.\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
PDEBUG(DDSP, DEBUG_DEBUG, "enable FFSK modulation mode\n");
fsk->ffsk = 1;
waves = (f0 / bitrate);
@@ -100,22 +112,39 @@ int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int sa
abort();
}
fsk->cycles_per_bit65536[1] = waves * 65536.0;
+ } else {
+ fsk->cycles_per_bit65536[0] = f0 / bitrate * 65536.0;
+ fsk->cycles_per_bit65536[1] = f1 / bitrate * 65536.0;
}
+ PDEBUG(DDSP, DEBUG_DEBUG, "F0 = %.0f Hz (cycles_per_bit65536[0] = %.4f)\n", f0, fsk->cycles_per_bit65536[0]);
+ PDEBUG(DDSP, DEBUG_DEBUG, "F1 = %.0f Hz (cycles_per_bit65536[1] = %.4f)\n", f1, fsk->cycles_per_bit65536[1]);
- /* if filter is enabled, add a band pass filter to smooth the spectrum of the tones
- * the bandwidth is twice the difference between f0 and f1
- */
+ /* if filter is enabled, use a cosine shaped curve to change the phase each sample */
if (filter) {
- double low = (f0 + f1) / 2.0 - fabs(f0 - f1);
- double high = (f0 + f1) / 2.0 + fabs(f0 - f1);
+ fsk->phase_tab_0_1 = calloc(65536 + 65536, sizeof(*fsk->sin_tab));
+ if (!fsk->phase_tab_0_1) {
+ fprintf(stderr, "No mem!\n");
+ rc = -ENOMEM;
+ goto error;
+ }
+ fsk->phase_tab_1_0 = fsk->phase_tab_0_1 + 65536;
+ for (i = 0; i < 65536; i++) {
+ temp = cos((double)i / 65536.0 * PI) / 2 + 0.5; /* half cosine going from 1 to 0 */
+ fsk->phase_tab_0_1[i] = temp * fsk->phaseshift65536[0] + (1.0 - temp) * fsk->phaseshift65536[1];
+ fsk->phase_tab_1_0[i] = temp * fsk->phaseshift65536[1] + (1.0 - temp) * fsk->phaseshift65536[0];
+#ifdef DEBUG_MODULATOR_SHAPE
+ fsk->phase_tab_0_1[i] = 1.0 - temp;
+ fsk->phase_tab_1_0[i] = temp;
+#endif
+ }
- PDEBUG(DDSP, DEBUG_DEBUG, "enable filter to smooth FSK transmission. (frequency rage %.0f .. %.0f)\n", low, high);
+ PDEBUG(DDSP, DEBUG_DEBUG, "Enable filter to smooth FSK transmission.\n");
fsk->filter = 1;
- /* use fourth order (2 iter) filter, since it is as fast as second order (1 iter) filter */
- iir_highpass_init(&fsk->lp[0], low, samplerate, 2);
- iir_lowpass_init(&fsk->lp[1], high, samplerate, 2);
}
+ /* must reset, because bit states must be initialized */
+ fsk_mod_reset(fsk);
+
return 0;
error:
@@ -132,6 +161,11 @@ void fsk_mod_cleanup(fsk_mod_t *fsk)
free(fsk->sin_tab);
fsk->sin_tab = NULL;
}
+ if (fsk->phase_tab_0_1) {
+ free(fsk->phase_tab_0_1);
+ fsk->phase_tab_0_1 = NULL;
+ fsk->phase_tab_1_0 = NULL;
+ }
}
/* modulate bits
@@ -154,12 +188,16 @@ int fsk_mod_send(fsk_mod_t *fsk, sample_t *sample, int length, int add)
/* get next bit */
if (fsk->tx_bit < 0) {
next_bit:
+ fsk->tx_last_bit = fsk->tx_bit;
fsk->tx_bit = fsk->send_bit(fsk->inst);
#ifdef DEBUG_MODULATOR
- printf("bit change to %d\n", fsk->tx_bit);
+ printf("bit change from %d to %d\n", fsk->tx_last_bit, fsk->tx_bit);
#endif
- if (fsk->tx_bit < 0)
+ if (fsk->tx_bit < 0) {
+ fsk_mod_reset(fsk);
goto done;
+ }
+ fsk->tx_bit &= 1;
/* correct phase when changing bit */
if (fsk->ffsk) {
/* round phase to nearest zero crossing */
@@ -167,40 +205,86 @@ next_bit:
phase = 32768.0;
else
phase = 0;
- /* set phase according to current position in bit */
- phase += fsk->tx_bitpos * fsk->cycles_per_bit65536[fsk->tx_bit & 1];
#ifdef DEBUG_MODULATOR
- printf("phase %.3f bitpos=%.6f\n", phase, fsk->tx_bitpos);
+ printf("phase %.3f bitpos=%.6f\n", phase / 65536.0, fsk->tx_bitpos65536 / 65536.0);
#endif
}
+ if (!fsk->filter) {
+ /* change phase forward to the current bit position */
+ phase += fsk->tx_bitpos65536 / 65536.0 * fsk->cycles_per_bit65536[fsk->tx_bit];
+ if (phase >= 65536.0)
+ phase -= 65536.0;
+ }
}
/* modulate bit */
- phaseshift = fsk->phaseshift65536[fsk->tx_bit & 1];
- while (count < length && fsk->tx_bitpos < 1.0) {
- if (add)
- sample[count++] += fsk->sin_tab[(uint16_t)phase];
- else
- sample[count++] = fsk->sin_tab[(uint16_t)phase];
+ if (!fsk->filter || fsk->tx_last_bit < 0 || fsk->tx_last_bit == fsk->tx_bit) {
+ /* without filtering or when there is no bit change */
+ phaseshift = fsk->phaseshift65536[fsk->tx_bit];
+ while (count < length && fsk->tx_bitpos65536 < 65536.0) {
+ if (add)
+ sample[count++] += fsk->sin_tab[(uint16_t)phase];
+ else
+ sample[count++] = fsk->sin_tab[(uint16_t)phase];
+#ifdef DEBUG_MODULATOR
+ printf("|%s| %d\n", debug_amplitude(fsk->sin_tab[(uint16_t)phase] / fsk->level), fsk->tx_bit);
+#endif
+#ifdef DEBUG_MODULATOR_SHAPE
+ printf("|%s| %d\n", debug_amplitude(fsk->tx_bit), fsk->tx_bit);
+#endif
+ phase += phaseshift;
+ if (phase >= 65536.0)
+ phase -= 65536.0;
+ fsk->tx_bitpos65536 += fsk->bits65536_per_sample;
+ }
+ } else if (fsk->tx_bit > fsk->tx_last_bit) {
+ /* with cosine shape filter, going from phase of 0 to phase of 1 */
+ while (count < length && fsk->tx_bitpos65536 < 65536.0) {
+ if (add)
+ sample[count++] += fsk->sin_tab[(uint16_t)phase];
+ else
+ sample[count++] = fsk->sin_tab[(uint16_t)phase];
+#ifdef DEBUG_MODULATOR
+ printf("|%s| 0->1\n", debug_amplitude(fsk->sin_tab[(uint16_t)phase] / fsk->level));
+#endif
+#ifdef DEBUG_MODULATOR_SHAPE
+ printf("|%s|0->1\n", debug_amplitude(fsk->phase_tab_0_1[(uint16_t)fsk->tx_bitpos65536]));
+#endif
+ phase += fsk->phase_tab_0_1[(uint16_t)fsk->tx_bitpos65536];
+ if (phase >= 65536.0)
+ phase -= 65536.0;
+ fsk->tx_bitpos65536 += fsk->bits65536_per_sample;
+ }
+ } else {
+ /* with cosine shape filter, going from phase of 1 to phase of 0 */
+ while (count < length && fsk->tx_bitpos65536 < 65536.0) {
+ if (add)
+ sample[count++] += fsk->sin_tab[(uint16_t)phase];
+ else
+ sample[count++] = fsk->sin_tab[(uint16_t)phase];
#ifdef DEBUG_MODULATOR
- printf("|%s|\n", debug_amplitude(fsk->sin_tab[(uint16_t)phase] / fsk->level));
+ printf("|%s|1->0\n", debug_amplitude(fsk->sin_tab[(uint16_t)phase] / fsk->level));
+#endif
+#ifdef DEBUG_MODULATOR_SHAPE
+ printf("|%s|1->0\n", debug_amplitude(fsk->phase_tab_1_0[(uint16_t)fsk->tx_bitpos65536]));
#endif
- phase += phaseshift;
- if (phase >= 65536.0)
- phase -= 65536.0;
- fsk->tx_bitpos += fsk->bits_per_sample;
+ phase += fsk->phase_tab_1_0[(uint16_t)fsk->tx_bitpos65536];
+ if (phase >= 65536.0)
+ phase -= 65536.0;
+ fsk->tx_bitpos65536 += fsk->bits65536_per_sample;
+ }
}
- if (fsk->tx_bitpos >= 1.0) {
- fsk->tx_bitpos -= 1.0;
+ if (fsk->tx_bitpos65536 >= 65536.0) {
+ fsk->tx_bitpos65536 -= 65536.0;
+ if (!fsk->filter) {
+ /* change phase back to the point when bit has changed */
+ phase -= fsk->tx_bitpos65536 / 65536.0 * fsk->cycles_per_bit65536[fsk->tx_bit];
+ if (phase < 0.0)
+ phase += 65536.0;
+ }
goto next_bit;
}
- /* post filter */
- if (fsk->filter) {
- iir_process(&fsk->lp[0], sample, length);
- iir_process(&fsk->lp[1], sample, length);
- }
-
done:
fsk->tx_phase65536 = phase;
@@ -208,11 +292,12 @@ done:
}
/* reset transmitter state, so we get a clean start */
-void fsk_mod_tx_reset(fsk_mod_t *fsk)
+void fsk_mod_reset(fsk_mod_t *fsk)
{
- fsk->tx_phase65536 = 0;
- fsk->tx_bitpos = 0;
+ fsk->tx_phase65536 = 0.0;
+ fsk->tx_bitpos65536 = 0.0;
fsk->tx_bit = -1;
+ fsk->tx_last_bit = -1;
}
/*
diff --git a/src/libfsk/fsk.h b/src/libfsk/fsk.h
index cb62170..da67f46 100644
--- a/src/libfsk/fsk.h
+++ b/src/libfsk/fsk.h
@@ -6,8 +6,10 @@
typedef struct fsk_mod {
void *inst;
int (*send_bit)(void *inst);
- double bits_per_sample; /* fraction of a bit per sample */
+ double bits65536_per_sample; /* fraction of a bit per sample */
double *sin_tab; /* sine table with correct peak level */
+ double *phase_tab_0_1; /* cosine shaped phase table (bit 0 to 1) */
+ double *phase_tab_1_0; /* cosine shaped phase table (bit 1 to 0) */
double phaseshift65536[2]; /* how much the phase of fsk synbol changes per sample */
double cycles_per_bit65536[2]; /* cycles of one bit */
double tx_phase65536; /* current transmit phase */
@@ -17,9 +19,9 @@ typedef struct fsk_mod {
double f1_deviation;
int low_bit, high_bit; /* a low or high deviation means which bit? */
int tx_bit; /* current transmitting bit (-1 if not set) */
- double tx_bitpos; /* current transmit position in bit */
+ int tx_last_bit; /* last transmitting bit (-1 if not set) */
+ double tx_bitpos65536; /* current transmit position in bit */
int filter; /* set, if filters are used */
- iir_filter_t lp[2]; /* filter to smooth transmission spectrum */
} fsk_mod_t;
typedef struct fsk_demod {
@@ -39,7 +41,7 @@ typedef struct fsk_demod {
int fsk_mod_init(fsk_mod_t *fsk, void *inst, int (*send_bit)(void *inst), int samplerate, double bitrate, double f0, double f1, double level, int coherent, int filter);
void fsk_mod_cleanup(fsk_mod_t *fsk);
int fsk_mod_send(fsk_mod_t *fsk, sample_t *sample, int length, int add);
-void fsk_mod_tx_reset(fsk_mod_t *fsk);
+void fsk_mod_reset(fsk_mod_t *fsk);
int fsk_demod_init(fsk_demod_t *fsk, void *inst, void (*receive_bit)(void *inst, int bit, double quality, double level), int samplerate, double bitrate, double f0, double f1, double bitadjust);
void fsk_demod_cleanup(fsk_demod_t *fsk);
void fsk_demod_receive(fsk_demod_t *fsk, sample_t *sample, int length);
diff --git a/src/nmt/dsp.c b/src/nmt/dsp.c
index 2d6e972..e63ae45 100644
--- a/src/nmt/dsp.c
+++ b/src/nmt/dsp.c
@@ -515,7 +515,7 @@ void nmt_set_dsp_mode(nmt_t *nmt, enum dsp_mode mode)
{
/* reset frame */
if (mode == DSP_MODE_FRAME && nmt->dsp_mode != mode) {
- fsk_mod_tx_reset(&nmt->fsk_mod);
+ fsk_mod_reset(&nmt->fsk_mod);
nmt->tx_frame_length = 0;
}
diff --git a/src/r2000/dsp.c b/src/r2000/dsp.c
index 79ae05b..bb3b97c 100644
--- a/src/r2000/dsp.c
+++ b/src/r2000/dsp.c
@@ -402,12 +402,12 @@ void r2000_set_dsp_mode(r2000_t *r2000, enum dsp_mode mode, int super)
/* reset telegramm */
if (mode == DSP_MODE_FRAME && r2000->dsp_mode != mode) {
r2000->tx_frame_length = 0;
- fsk_mod_tx_reset(&r2000->fsk_mod);
+ fsk_mod_reset(&r2000->fsk_mod);
}
if ((mode == DSP_MODE_AUDIO_TX || mode == DSP_MODE_AUDIO_TX_RX)
&& (r2000->dsp_mode != DSP_MODE_AUDIO_TX && r2000->dsp_mode != DSP_MODE_AUDIO_TX_RX)) {
r2000->super_tx_word_length = 0;
- fsk_mod_tx_reset(&r2000->super_fsk_mod);
+ fsk_mod_reset(&r2000->super_fsk_mod);
}
if (super >= 0) {