aboutsummaryrefslogtreecommitdiffstats
path: root/src/libfsk
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2019-09-01 15:38:16 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2019-11-29 15:58:32 +0100
commit6dcc8baad448d000ef355abc6d9abf7a3490a800 (patch)
treed46e472ec720c369071e49398783630d16f47bb2 /src/libfsk
parent360729d27034a3fe684b4a2ddea516d027dab935 (diff)
Split FSK modem code into separate modulator and demodulator
Diffstat (limited to 'src/libfsk')
-rw-r--r--src/libfsk/fsk.c232
-rw-r--r--src/libfsk/fsk.h32
2 files changed, 158 insertions, 106 deletions
diff --git a/src/libfsk/fsk.c b/src/libfsk/fsk.c
index 6b5fe03..7f1ed6e 100644
--- a/src/libfsk/fsk.c
+++ b/src/libfsk/fsk.c
@@ -33,21 +33,18 @@
* fsk = instance of fsk modem
* inst = instance of user
* send_bit() = function to be called whenever a new bit has to be sent
- * receive_bit() = function to be called whenever a new bit was received
* samplerate = samplerate
* bitrate = bits per second
* f0, f1 = two frequencies for bit 0 and bit 1
* level = level to modulate the frequencies
* coherent = use coherent modulation (FFSK)
- * bitadjust = how much to adjust the sample clock when a bitchange was detected. (0 = nothing, don't use this, 0.5 full adjustment)
*/
-int fsk_init(fsk_t *fsk, void *inst, int (*send_bit)(void *inst), void (*receive_bit)(void *inst, int bit, double quality, double level), int samplerate, double bitrate, double f0, double f1, double level, int coherent, double bitadjust)
+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)
{
- double bandwidth;
int i;
int rc;
- PDEBUG(DDSP, DEBUG_DEBUG, "Setup FSK for Transceiver. (F0 = %.1f, F1 = %.1f, peak = %.1f)\n", f0, f1, level);
+ PDEBUG(DDSP, DEBUG_DEBUG, "Setup FSK for Transmitter. (F0 = %.1f, F1 = %.1f, peak = %.1f)\n", f0, f1, level);
memset(fsk, 0, sizeof(*fsk));
@@ -62,9 +59,6 @@ int fsk_init(fsk_t *fsk, void *inst, int (*send_bit)(void *inst), void (*receive
fsk->sin_tab[i] = sin((double)i / 65536.0 * 2.0 * PI) * level;
fsk->inst = inst;
- fsk->rx_bit = -1;
- fsk->rx_bitadjust = bitadjust;
- fsk->receive_bit = receive_bit;
fsk->tx_bit = -1;
fsk->level = level;
fsk->send_bit = send_bit;
@@ -78,14 +72,6 @@ int fsk_init(fsk_t *fsk, void *inst, int (*send_bit)(void *inst), void (*receive
fsk->high_bit = 0;
}
- /* calculate bandwidth */
- bandwidth = fabs(f0 - f1) * 2.0;
-
- /* init fm demodulator */
- rc = fm_demod_init(&fsk->demod, (double)samplerate, (f0 + f1) / 2.0, bandwidth);
- if (rc < 0)
- goto error;
-
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);
@@ -118,19 +104,150 @@ int fsk_init(fsk_t *fsk, void *inst, int (*send_bit)(void *inst), void (*receive
return 0;
error:
- fsk_cleanup(fsk);
+ fsk_mod_cleanup(fsk);
return rc;
}
/* Cleanup transceiver instance. */
-void fsk_cleanup(fsk_t *fsk)
+void fsk_mod_cleanup(fsk_mod_t *fsk)
{
- PDEBUG(DDSP, DEBUG_DEBUG, "Cleanup FSK for Transceiver.\n");
+ PDEBUG(DDSP, DEBUG_DEBUG, "Cleanup FSK for Transmitter.\n");
if (fsk->sin_tab) {
free(fsk->sin_tab);
fsk->sin_tab = NULL;
}
+}
+
+/* modulate bits
+ *
+ * If first/next bit is required, callback function send_bit() is called.
+ * If there is no (more) data to be transmitted, the callback functions shall
+ * return -1. In this case, this function stops and returns the number of
+ * samples that have been rendered so far, if any.
+ *
+ * For coherent mode (FSK), we round the phase on every bit change to the
+ * next zero crossing. This prevents phase shifts due to rounding errors.
+ */
+int fsk_mod_send(fsk_mod_t *fsk, sample_t *sample, int length, int add)
+{
+ int count = 0;
+ double phase, phaseshift;
+
+ phase = fsk->tx_phase65536;
+
+ /* get next bit */
+ if (fsk->tx_bit < 0) {
+next_bit:
+ fsk->tx_bit = fsk->send_bit(fsk->inst);
+#ifdef DEBUG_MODULATOR
+ printf("bit change to %d\n", fsk->tx_bit);
+#endif
+ if (fsk->tx_bit < 0)
+ goto done;
+ /* correct phase when changing bit */
+ if (fsk->coherent) {
+ /* round phase to nearest zero crossing */
+ if (phase > 16384.0 && phase < 49152.0)
+ 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);
+#endif
+ }
+ }
+
+ /* 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];
+#ifdef DEBUG_MODULATOR
+ printf("|%s|\n", debug_amplitude(fsk->sin_tab[(uint16_t)phase] / fsk->level));
+#endif
+ phase += phaseshift;
+ if (phase >= 65536.0)
+ phase -= 65536.0;
+ fsk->tx_bitpos += fsk->bits_per_sample;
+ }
+ if (fsk->tx_bitpos >= 1.0) {
+ fsk->tx_bitpos -= 1.0;
+ goto next_bit;
+ }
+
+done:
+ fsk->tx_phase65536 = phase;
+
+ return count;
+}
+
+/* reset transmitter state, so we get a clean start */
+void fsk_mod_tx_reset(fsk_mod_t *fsk)
+{
+ fsk->tx_phase65536 = 0;
+ fsk->tx_bitpos = 0;
+ fsk->tx_bit = -1;
+}
+
+/*
+ * fsk = instance of fsk modem
+ * inst = instance of user
+ * receive_bit() = function to be called whenever a new bit was received
+ * samplerate = samplerate
+ * bitrate = bits per second
+ * f0, f1 = two frequencies for bit 0 and bit 1
+ * bitadjust = how much to adjust the sample clock when a bitchange was detected. (0 = nothing, don't use this, 0.5 full adjustment)
+ */
+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)
+{
+ double bandwidth;
+ int rc;
+
+ PDEBUG(DDSP, DEBUG_DEBUG, "Setup FSK for Receiver. (F0 = %.1f, F1 = %.1f)\n", f0, f1);
+
+ memset(fsk, 0, sizeof(*fsk));
+
+ fsk->inst = inst;
+ fsk->rx_bit = -1;
+ fsk->rx_bitadjust = bitadjust;
+ fsk->receive_bit = receive_bit;
+ fsk->f0_deviation = (f0 - f1) / 2.0;
+ fsk->f1_deviation = (f1 - f0) / 2.0;
+ if (f0 < f1) {
+ fsk->low_bit = 0;
+ fsk->high_bit = 1;
+ } else {
+ fsk->low_bit = 1;
+ fsk->high_bit = 0;
+ }
+
+ /* calculate bandwidth */
+ bandwidth = fabs(f0 - f1) * 2.0;
+
+ /* init fm demodulator */
+ rc = fm_demod_init(&fsk->demod, (double)samplerate, (f0 + f1) / 2.0, bandwidth);
+ if (rc < 0)
+ goto error;
+
+ 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);
+
+ return 0;
+
+error:
+ fsk_demod_cleanup(fsk);
+ return rc;
+}
+
+/* Cleanup transceiver instance. */
+void fsk_demod_cleanup(fsk_demod_t *fsk)
+{
+ PDEBUG(DDSP, DEBUG_DEBUG, "Cleanup FSK for Receiver.\n");
fm_demod_exit(&fsk->demod);
}
@@ -150,7 +267,7 @@ void fsk_cleanup(fsk_t *fsk)
* Therefore we change the sample counter only slightly, so bit slips may not
* happen so quickly.
*/
-void fsk_receive(fsk_t *fsk, sample_t *sample, int length)
+void fsk_demod_receive(fsk_demod_t *fsk, sample_t *sample, int length)
{
sample_t I[length], Q[length], frequency[length], f;
int i;
@@ -211,78 +328,3 @@ void fsk_receive(fsk_t *fsk, sample_t *sample, int length)
}
}
-/* modulate bits
- *
- * If first/next bit is required, callback function send_bit() is called.
- * If there is no (more) data to be transmitted, the callback functions shall
- * return -1. In this case, this function stops and returns the number of
- * samples that have been rendered so far, if any.
- *
- * For coherent mode (FSK), we round the phase on every bit change to the
- * next zero crossing. This prevents phase shifts due to rounding errors.
- */
-int fsk_send(fsk_t *fsk, sample_t *sample, int length, int add)
-{
- int count = 0;
- double phase, phaseshift;
-
- phase = fsk->tx_phase65536;
-
- /* get next bit */
- if (fsk->tx_bit < 0) {
-next_bit:
- fsk->tx_bit = fsk->send_bit(fsk->inst);
-#ifdef DEBUG_MODULATOR
- printf("bit change to %d\n", fsk->tx_bit);
-#endif
- if (fsk->tx_bit < 0)
- goto done;
- /* correct phase when changing bit */
- if (fsk->coherent) {
- /* round phase to nearest zero crossing */
- if (phase > 16384.0 && phase < 49152.0)
- 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);
-#endif
- }
- }
-
- /* 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];
-#ifdef DEBUG_MODULATOR
- printf("|%s|\n", debug_amplitude(fsk->sin_tab[(uint16_t)phase] / fsk->level));
-#endif
- phase += phaseshift;
- if (phase >= 65536.0)
- phase -= 65536.0;
- fsk->tx_bitpos += fsk->bits_per_sample;
- }
- if (fsk->tx_bitpos >= 1.0) {
- fsk->tx_bitpos -= 1.0;
- goto next_bit;
- }
-
-done:
- fsk->tx_phase65536 = phase;
-
- return count;
-}
-
-/* reset transmitter state, so we get a clean start */
-void fsk_tx_reset(fsk_t *fsk)
-{
- fsk->tx_phase65536 = 0;
- fsk->tx_bitpos = 0;
- fsk->tx_bit = -1;
-}
-
diff --git a/src/libfsk/fsk.h b/src/libfsk/fsk.h
index a7cc428..395e915 100644
--- a/src/libfsk/fsk.h
+++ b/src/libfsk/fsk.h
@@ -1,14 +1,12 @@
#include "../libfm/fm.h"
-typedef struct ffsk {
+typedef struct fsk_mod {
void *inst;
int (*send_bit)(void *inst);
- void (*receive_bit)(void *inst, int bit, double quality, double level);
- fm_demod_t demod;
double bits_per_sample; /* fraction of a bit per sample */
double *sin_tab; /* sine table with correct peak level */
double phaseshift65536[2]; /* how much the phase of fsk synbol changes per sample */
- double cycles_per_bit65536[2]; /* cacles of one bit */
+ double cycles_per_bit65536[2]; /* cycles of one bit */
double tx_phase65536; /* current transmit phase */
double level; /* level (amplitude) of signal */
int coherent; /* set, if coherent TX mode */
@@ -16,15 +14,27 @@ typedef struct ffsk {
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) */
- int rx_bit; /* current receiving bit (-1 if not yet measured) */
double tx_bitpos; /* current transmit position in bit */
+} fsk_mod_t;
+
+typedef struct fsk_demod {
+ void *inst;
+ void (*receive_bit)(void *inst, int bit, double quality, double level);
+ fm_demod_t demod;
+ double bits_per_sample; /* fraction of a bit per sample */
+ double f0_deviation; /* deviation of frequencies, relative to center */
+ double f1_deviation;
+ int low_bit, high_bit; /* a low or high deviation means which bit? */
+ int rx_bit; /* current receiving bit (-1 if not yet measured) */
double rx_bitpos; /* current receive position in bit (sampleclock) */
double rx_bitadjust; /* how much does a bit change cause the sample clock to be adjusted in phase */
-} fsk_t;
+} fsk_demod_t;
-int fsk_init(fsk_t *fsk, void *inst, int (*send_bit)(void *inst), void (*receive_bit)(void *inst, int bit, double quality, double level), int samplerate, double bitrate, double f0, double f1, double level, int coherent, double bitadjust);
-void fsk_cleanup(fsk_t *fsk);
-void fsk_receive(fsk_t *fsk, sample_t *sample, int length);
-int fsk_send(fsk_t *fsk, sample_t *sample, int length, int add);
-void fsk_tx_reset(fsk_t *fsk);
+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);
+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);
+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);