aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-11-16 21:04:23 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2017-11-25 19:24:03 +0100
commit083ea4edaab0ea5b0c9c2aedd1483be4ec97bc5b (patch)
tree159a1584b1ef66b170d73405a4afac11a0bffc8e /src/common
parentf4754dcb37fa08775ca7e4af4f1bb4ea294fabcc (diff)
Restructure: Move fsk from common code to 'libfsk'
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/fsk.c288
-rw-r--r--src/common/fsk.h30
3 files changed, 0 insertions, 319 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 9e9908a..adabe55 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -7,7 +7,6 @@ libcommon_a_SOURCES = \
debug.c \
sound_alsa.c \
compandor.c \
- fsk.c \
display_wave.c \
display_measurements.c
diff --git a/src/common/fsk.c b/src/common/fsk.c
deleted file mode 100644
index fecd3bf..0000000
--- a/src/common/fsk.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* FSK audio processing (coherent FSK modem)
- *
- * (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <math.h>
-#include "../common/sample.h"
-#include "../common/debug.h"
-#include "fsk.h"
-
-#define PI M_PI
-
-/*
- * 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)
-{
- double bandwidth;
- int i;
- int rc;
-
- PDEBUG(DDSP, DEBUG_DEBUG, "Setup FSK for Transceiver. (F0 = %.1f, F1 = %.1f, peak = %.1f)\n", f0, f1, level);
-
- memset(fsk, 0, sizeof(*fsk));
-
- /* gen sine table with deviation */
- fsk->sin_tab = calloc(65536+16384, sizeof(*fsk->sin_tab));
- if (!fsk->sin_tab) {
- fprintf(stderr, "No mem!\n");
- rc = -ENOMEM;
- goto error;
- }
- for (i = 0; i < 65536; i++)
- 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;
- 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);
-
- fsk->phaseshift65536[0] = f0 / (double)samplerate * 65536.0;
- PDEBUG(DDSP, DEBUG_DEBUG, "phaseshift65536[0] = %.4f\n", fsk->phaseshift65536[0]);
- fsk->phaseshift65536[1] = f1 / (double)samplerate * 65536.0;
- PDEBUG(DDSP, DEBUG_DEBUG, "phaseshift65536[1] = %.4f\n", fsk->phaseshift65536[1]);
-
- /* use coherent modulation, i.e. each bit has an integer number of
- * half waves and starts/ends at zero crossing
- */
- if (coherent) {
- double waves;
-
- fsk->coherent = 1;
- waves = (f0 / bitrate);
- if (fabs(round(waves * 2) - (waves * 2)) > 0.001) {
- fprintf(stderr, "Failed to set coherent mode, half waves of F0 does not fit exactly into one bit, please fix!\n");
- abort();
- }
- fsk->cycles_per_bit65536[0] = waves * 65536.0;
- waves = (f1 / bitrate);
- if (fabs(round(waves * 2) - (waves * 2)) > 0.001) {
- fprintf(stderr, "Failed to set coherent mode, half waves of F1 does not fit exactly into one bit, please fix!\n");
- abort();
- }
- fsk->cycles_per_bit65536[1] = waves * 65536.0;
- }
-
- return 0;
-
-error:
- fsk_cleanup(fsk);
- return rc;
-}
-
-/* Cleanup transceiver instance. */
-void fsk_cleanup(fsk_t *fsk)
-{
- PDEBUG(DDSP, DEBUG_DEBUG, "Cleanup FSK for Transceiver.\n");
-
- if (fsk->sin_tab) {
- free(fsk->sin_tab);
- fsk->sin_tab = NULL;
- }
-
- fm_demod_exit(&fsk->demod);
-}
-
-//#define DEBUG_MODULATOR
-//#define DEBUG_FILTER
-
-/* Demodulates bits
- *
- * If bit is received, callback function send_bit() is called.
- *
- * We sample each bit 0.5 bits after polarity change.
- *
- * If we have a bit change, adjust sample counter towards one half bit duration.
- * We may have noise, so the bit change may be wrong or not at the correct place.
- * This can cause bit slips.
- * 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)
-{
- sample_t I[length], Q[length], frequency[length], f;
- int i;
- int bit;
- double level, quality;
-
- /* demod samples to offset arround center frequency */
- fm_demodulate_real(&fsk->demod, frequency, length, sample, I, Q);
-
- for (i = 0; i < length; i++) {
- f = frequency[i];
- if (f < 0)
- bit = fsk->low_bit;
- else
- bit = fsk->high_bit;
-#ifdef DEBUG_FILTER
- printf("|%s| %.3f\n", debug_amplitude(f / fabs(fsk->f0_deviation)), f / fabs(fsk->f0_deviation));
-#endif
-
-
- if (fsk->rx_bit != bit) {
-#ifdef DEBUG_FILTER
- puts("bit change");
-#endif
- fsk->rx_bit = bit;
- if (fsk->rx_bitpos < 0.5) {
- fsk->rx_bitpos += fsk->rx_bitadjust;
- if (fsk->rx_bitpos > 0.5)
- fsk->rx_bitpos = 0.5;
- } else
- if (fsk->rx_bitpos > 0.5) {
- fsk->rx_bitpos -= fsk->rx_bitadjust;
- if (fsk->rx_bitpos < 0.5)
- fsk->rx_bitpos = 0.5;
- }
- }
- /* if bit counter reaches 1, we substract 1 and sample the bit */
- if (fsk->rx_bitpos >= 1.0) {
- /* peak level is the length of I/Q vector
- * since we filter out the unwanted modulation product, the vector is only half of length */
- level = sqrt(I[i] * I[i] + Q[i] * Q[i]) * 2.0;
- /* quality is defined on how accurat the target frequency it hit
- * if it is hit close to the center or close to double deviation from center, quality is close to 0 */
- if (bit == 0)
- quality = 1.0 - fabs((f - fsk->f0_deviation) / fsk->f0_deviation);
- else
- quality = 1.0 - fabs((f - fsk->f1_deviation) / fsk->f1_deviation);
- if (quality < 0)
- quality = 0;
-#ifdef DEBUG_FILTER
- printf("sample (level=%.3f, quality=%.3f)\n", level / fsk->level, quality);
-#endif
- /* adjust the values, because this is best we can get from fm demodulator */
- fsk->receive_bit(fsk->inst, bit, quality / 0.95, level);
- fsk->rx_bitpos -= 1.0;
- }
- fsk->rx_bitpos += fsk->bits_per_sample;
- }
-}
-
-/* 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/common/fsk.h b/src/common/fsk.h
deleted file mode 100644
index a7cc428..0000000
--- a/src/common/fsk.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "../libfm/fm.h"
-
-typedef struct ffsk {
- 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 tx_phase65536; /* current transmit phase */
- double level; /* level (amplitude) of signal */
- int coherent; /* set, if coherent TX mode */
- 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 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 */
- 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;
-
-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);
-