diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2017-11-16 21:04:23 +0100 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2017-11-25 19:24:03 +0100 |
commit | 083ea4edaab0ea5b0c9c2aedd1483be4ec97bc5b (patch) | |
tree | 159a1584b1ef66b170d73405a4afac11a0bffc8e /src/common | |
parent | f4754dcb37fa08775ca7e4af4f1bb4ea294fabcc (diff) |
Restructure: Move fsk from common code to 'libfsk'
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/Makefile.am | 1 | ||||
-rw-r--r-- | src/common/fsk.c | 288 | ||||
-rw-r--r-- | src/common/fsk.h | 30 |
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); - |