Split FSK modem code into separate modulator and demodulator
This commit is contained in:
parent
360729d270
commit
6dcc8baad4
|
@ -87,7 +87,8 @@ typedef struct bnetz {
|
||||||
|
|
||||||
/* dsp states */
|
/* dsp states */
|
||||||
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, "Telegramm" */
|
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, "Telegramm" */
|
||||||
fsk_t fsk; /* fsk modem instance */
|
fsk_mod_t fsk_mod; /* fsk modem instance */
|
||||||
|
fsk_demod_t fsk_demod;
|
||||||
uint16_t rx_telegramm; /* rx shift register for receiveing telegramm */
|
uint16_t rx_telegramm; /* rx shift register for receiveing telegramm */
|
||||||
double rx_telegramm_quality[16];/* quality of each bit in telegramm */
|
double rx_telegramm_quality[16];/* quality of each bit in telegramm */
|
||||||
double rx_telegramm_level[16]; /* level of each bit in telegramm */
|
double rx_telegramm_level[16]; /* level of each bit in telegramm */
|
||||||
|
|
|
@ -61,7 +61,7 @@ int tx_telegramm_pos = 0;
|
||||||
int latspl;
|
int latspl;
|
||||||
|
|
||||||
/* instances */
|
/* instances */
|
||||||
fsk_t fsk;
|
fsk_mod_t fsk_mod;
|
||||||
#ifdef HAVE_ALSA
|
#ifdef HAVE_ALSA
|
||||||
void *audio = NULL;
|
void *audio = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -226,7 +226,7 @@ again:
|
||||||
break;
|
break;
|
||||||
case TX_MODE_FSK:
|
case TX_MODE_FSK:
|
||||||
/* send FSK until it stops, then fill with silence */
|
/* send FSK until it stops, then fill with silence */
|
||||||
count = fsk_send(&fsk, samples, length, 0);
|
count = fsk_mod_send(&fsk_mod, samples, length, 0);
|
||||||
samples += count;
|
samples += count;
|
||||||
length -= count;
|
length -= count;
|
||||||
if (length)
|
if (length)
|
||||||
|
@ -286,7 +286,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
bnetz_init_telegramm();
|
bnetz_init_telegramm();
|
||||||
memset(&fsk, 0, sizeof(fsk));
|
memset(&fsk_mod, 0, sizeof(fsk_mod));
|
||||||
|
|
||||||
/* latency of send buffer in samples */
|
/* latency of send buffer in samples */
|
||||||
latspl = samplerate * latency / 1000;
|
latspl = samplerate * latency / 1000;
|
||||||
|
@ -340,7 +340,7 @@ int main(int argc, char *argv[])
|
||||||
sprintf(funkwahl, "wwww%c%s%se%c%s%se", start_digit, station_id, dialing + 1, start_digit, station_id, dialing + 1);
|
sprintf(funkwahl, "wwww%c%s%se%c%s%se", start_digit, station_id, dialing + 1, start_digit, station_id, dialing + 1);
|
||||||
|
|
||||||
/* init fsk */
|
/* init fsk */
|
||||||
if (fsk_init(&fsk, NULL, fsk_send_bit, NULL, samplerate, BIT_RATE, F0, F1, 1.0, 0, 0) < 0) {
|
if (fsk_mod_init(&fsk_mod, NULL, fsk_send_bit, samplerate, BIT_RATE, F0, F1, 1.0, 0) < 0) {
|
||||||
PDEBUG(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
PDEBUG(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -389,7 +389,7 @@ exit:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* exit fsk */
|
/* exit fsk */
|
||||||
fsk_cleanup(&fsk);
|
fsk_mod_cleanup(&fsk_mod);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,11 @@ int dsp_init_sender(bnetz_t *bnetz, double squelch_db)
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation @ 2000 Hz)\n", TX_PEAK_FSK, 4.0);
|
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f (%.3f KHz deviation @ 2000 Hz)\n", TX_PEAK_FSK, 4.0);
|
||||||
|
|
||||||
/* init fsk */
|
/* init fsk */
|
||||||
if (fsk_init(&bnetz->fsk, bnetz, fsk_send_bit, fsk_receive_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 0, BIT_ADJUST) < 0) {
|
if (fsk_mod_init(&bnetz->fsk_mod, bnetz, fsk_send_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 0) < 0) {
|
||||||
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (fsk_demod_init(&bnetz->fsk_demod, bnetz, fsk_receive_bit, bnetz->sender.samplerate, BIT_RATE, F0, F1, BIT_ADJUST) < 0) {
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +125,8 @@ void dsp_cleanup_sender(bnetz_t *bnetz)
|
||||||
{
|
{
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for 'Sender'.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for 'Sender'.\n");
|
||||||
|
|
||||||
fsk_cleanup(&bnetz->fsk);
|
fsk_mod_cleanup(&bnetz->fsk_mod);
|
||||||
|
fsk_demod_cleanup(&bnetz->fsk_demod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If good tone is received, we just set this tone, if not already and reset counters.
|
/* If good tone is received, we just set this tone, if not already and reset counters.
|
||||||
|
@ -270,7 +275,7 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_l
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* fsk/tone signal */
|
/* fsk/tone signal */
|
||||||
fsk_receive(&bnetz->fsk, samples, length);
|
fsk_demod_receive(&bnetz->fsk_demod, samples, length);
|
||||||
|
|
||||||
/* process signal mute/loss, without signalling tone / FSK frames */
|
/* process signal mute/loss, without signalling tone / FSK frames */
|
||||||
switch (squelch(&bnetz->squelch, rf_level_db, (double)length / (double)bnetz->sender.samplerate)) {
|
switch (squelch(&bnetz->squelch, rf_level_db, (double)length / (double)bnetz->sender.samplerate)) {
|
||||||
|
@ -375,7 +380,7 @@ again:
|
||||||
case DSP_MODE_TELEGRAMM:
|
case DSP_MODE_TELEGRAMM:
|
||||||
/* Encode tone/frame into audio stream. If frames have
|
/* Encode tone/frame into audio stream. If frames have
|
||||||
* stopped, process again for rest of stream. */
|
* stopped, process again for rest of stream. */
|
||||||
count = fsk_send(&bnetz->fsk, samples, length, 0);
|
count = fsk_mod_send(&bnetz->fsk_mod, samples, length, 0);
|
||||||
samples += count;
|
samples += count;
|
||||||
length -= count;
|
length -= count;
|
||||||
if (length)
|
if (length)
|
||||||
|
@ -412,7 +417,7 @@ void bnetz_set_dsp_mode(bnetz_t *bnetz, enum dsp_mode mode)
|
||||||
/* reset telegramm */
|
/* reset telegramm */
|
||||||
if (mode == DSP_MODE_TELEGRAMM && bnetz->dsp_mode != mode) {
|
if (mode == DSP_MODE_TELEGRAMM && bnetz->dsp_mode != mode) {
|
||||||
bnetz->tx_telegramm = 0;
|
bnetz->tx_telegramm = 0;
|
||||||
fsk_tx_reset(&bnetz->fsk);
|
fsk_mod_tx_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));
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", bnetz_dsp_mode_name(bnetz->dsp_mode), bnetz_dsp_mode_name(mode));
|
||||||
|
|
232
src/libfsk/fsk.c
232
src/libfsk/fsk.c
|
@ -33,21 +33,18 @@
|
||||||
* fsk = instance of fsk modem
|
* fsk = instance of fsk modem
|
||||||
* inst = instance of user
|
* inst = instance of user
|
||||||
* send_bit() = function to be called whenever a new bit has to be sent
|
* 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
|
* samplerate = samplerate
|
||||||
* bitrate = bits per second
|
* bitrate = bits per second
|
||||||
* f0, f1 = two frequencies for bit 0 and bit 1
|
* f0, f1 = two frequencies for bit 0 and bit 1
|
||||||
* level = level to modulate the frequencies
|
* level = level to modulate the frequencies
|
||||||
* coherent = use coherent modulation (FFSK)
|
* 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 i;
|
||||||
int rc;
|
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));
|
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->sin_tab[i] = sin((double)i / 65536.0 * 2.0 * PI) * level;
|
||||||
|
|
||||||
fsk->inst = inst;
|
fsk->inst = inst;
|
||||||
fsk->rx_bit = -1;
|
|
||||||
fsk->rx_bitadjust = bitadjust;
|
|
||||||
fsk->receive_bit = receive_bit;
|
|
||||||
fsk->tx_bit = -1;
|
fsk->tx_bit = -1;
|
||||||
fsk->level = level;
|
fsk->level = level;
|
||||||
fsk->send_bit = send_bit;
|
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;
|
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;
|
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);
|
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;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
fsk_cleanup(fsk);
|
fsk_mod_cleanup(fsk);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup transceiver instance. */
|
/* 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) {
|
if (fsk->sin_tab) {
|
||||||
free(fsk->sin_tab);
|
free(fsk->sin_tab);
|
||||||
fsk->sin_tab = NULL;
|
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);
|
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
|
* Therefore we change the sample counter only slightly, so bit slips may not
|
||||||
* happen so quickly.
|
* 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;
|
sample_t I[length], Q[length], frequency[length], f;
|
||||||
int i;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
#include "../libfm/fm.h"
|
#include "../libfm/fm.h"
|
||||||
|
|
||||||
typedef struct ffsk {
|
typedef struct fsk_mod {
|
||||||
void *inst;
|
void *inst;
|
||||||
int (*send_bit)(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 bits_per_sample; /* fraction of a bit per sample */
|
||||||
double *sin_tab; /* sine table with correct peak level */
|
double *sin_tab; /* sine table with correct peak level */
|
||||||
double phaseshift65536[2]; /* how much the phase of fsk synbol changes per sample */
|
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 tx_phase65536; /* current transmit phase */
|
||||||
double level; /* level (amplitude) of signal */
|
double level; /* level (amplitude) of signal */
|
||||||
int coherent; /* set, if coherent TX mode */
|
int coherent; /* set, if coherent TX mode */
|
||||||
|
@ -16,15 +14,27 @@ typedef struct ffsk {
|
||||||
double f1_deviation;
|
double f1_deviation;
|
||||||
int low_bit, high_bit; /* a low or high deviation means which bit? */
|
int low_bit, high_bit; /* a low or high deviation means which bit? */
|
||||||
int tx_bit; /* current transmitting bit (-1 if not set) */
|
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 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_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 */
|
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);
|
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_cleanup(fsk_t *fsk);
|
void fsk_mod_cleanup(fsk_mod_t *fsk);
|
||||||
void fsk_receive(fsk_t *fsk, sample_t *sample, int length);
|
int fsk_mod_send(fsk_mod_t *fsk, sample_t *sample, int length, int add);
|
||||||
int fsk_send(fsk_t *fsk, sample_t *sample, int length, int add);
|
void fsk_mod_tx_reset(fsk_mod_t *fsk);
|
||||||
void fsk_tx_reset(fsk_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);
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,11 @@ int dsp_init_sender(nmt_t *nmt, double deviation_factor)
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.3f (%.3f KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER * deviation_factor, 0.3 * deviation_factor);
|
PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.3f (%.3f KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER * deviation_factor, 0.3 * deviation_factor);
|
||||||
|
|
||||||
/* init fsk */
|
/* init fsk */
|
||||||
if (fsk_init(&nmt->fsk, nmt, fsk_send_bit, fsk_receive_bit, nmt->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 1, BIT_ADJUST) < 0) {
|
if (fsk_mod_init(&nmt->fsk_mod, nmt, fsk_send_bit, nmt->sender.samplerate, BIT_RATE, F0, F1, TX_PEAK_FSK, 1) < 0) {
|
||||||
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (fsk_demod_init(&nmt->fsk_demod, nmt, fsk_receive_bit, nmt->sender.samplerate, BIT_RATE, F0, F1, BIT_ADJUST) < 0) {
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +167,8 @@ void dsp_cleanup_sender(nmt_t *nmt)
|
||||||
{
|
{
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for Transceiver.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for Transceiver.\n");
|
||||||
|
|
||||||
fsk_cleanup(&nmt->fsk);
|
fsk_mod_cleanup(&nmt->fsk_mod);
|
||||||
|
fsk_demod_cleanup(&nmt->fsk_demod);
|
||||||
|
|
||||||
if (nmt->super_filter_spl) {
|
if (nmt->super_filter_spl) {
|
||||||
free(nmt->super_filter_spl);
|
free(nmt->super_filter_spl);
|
||||||
|
@ -336,7 +341,7 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double __at
|
||||||
nmt->super_filter_pos = pos;
|
nmt->super_filter_pos = pos;
|
||||||
|
|
||||||
/* fsk signal */
|
/* fsk signal */
|
||||||
fsk_receive(&nmt->fsk, samples, length);
|
fsk_demod_receive(&nmt->fsk_demod, samples, length);
|
||||||
|
|
||||||
/* muting audio while receiving frame */
|
/* muting audio while receiving frame */
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
|
@ -449,7 +454,7 @@ again:
|
||||||
jitter_load(&nmt->sender.dejitter, samples, length);
|
jitter_load(&nmt->sender.dejitter, samples, length);
|
||||||
/* send after dejitter, so audio is flushed */
|
/* send after dejitter, so audio is flushed */
|
||||||
if (nmt->dms.tx_frame_valid) {
|
if (nmt->dms.tx_frame_valid) {
|
||||||
fsk_send(&nmt->fsk, samples, length, 0);
|
fsk_mod_send(&nmt->fsk_mod, samples, length, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (nmt->supervisory)
|
if (nmt->supervisory)
|
||||||
|
@ -464,7 +469,7 @@ again:
|
||||||
case DSP_MODE_FRAME:
|
case DSP_MODE_FRAME:
|
||||||
/* Encode frame into audio stream. If frames have
|
/* Encode frame into audio stream. If frames have
|
||||||
* stopped, process again for rest of stream. */
|
* stopped, process again for rest of stream. */
|
||||||
count = fsk_send(&nmt->fsk, samples, length, 0);
|
count = fsk_mod_send(&nmt->fsk_mod, samples, length, 0);
|
||||||
/* special case: add supervisory signal to frame at loop test */
|
/* special case: add supervisory signal to frame at loop test */
|
||||||
if (nmt->sender.loopback && nmt->supervisory)
|
if (nmt->sender.loopback && nmt->supervisory)
|
||||||
super_encode(nmt, samples, count);
|
super_encode(nmt, samples, count);
|
||||||
|
@ -501,7 +506,7 @@ void nmt_set_dsp_mode(nmt_t *nmt, enum dsp_mode mode)
|
||||||
{
|
{
|
||||||
/* reset frame */
|
/* reset frame */
|
||||||
if (mode == DSP_MODE_FRAME && nmt->dsp_mode != mode) {
|
if (mode == DSP_MODE_FRAME && nmt->dsp_mode != mode) {
|
||||||
fsk_tx_reset(&nmt->fsk);
|
fsk_mod_tx_reset(&nmt->fsk_mod);
|
||||||
nmt->tx_frame_length = 0;
|
nmt->tx_frame_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,8 @@ typedef struct nmt {
|
||||||
|
|
||||||
/* dsp states */
|
/* dsp states */
|
||||||
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
||||||
fsk_t fsk; /* fsk processing */
|
fsk_mod_t fsk_mod; /* fsk processing */
|
||||||
|
fsk_demod_t fsk_demod;
|
||||||
int super_samples; /* number of samples in buffer for supervisory detection */
|
int super_samples; /* number of samples in buffer for supervisory detection */
|
||||||
goertzel_t super_goertzel[5]; /* filter for supervisory decoding */
|
goertzel_t super_goertzel[5]; /* filter for supervisory decoding */
|
||||||
sample_t *super_filter_spl; /* array with sample buffer for supervisory detection */
|
sample_t *super_filter_spl; /* array with sample buffer for supervisory detection */
|
||||||
|
|
|
@ -85,7 +85,11 @@ int dsp_init_sender(r2000_t *r2000)
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f\n", TX_PEAK_FSK);
|
PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.3f\n", TX_PEAK_FSK);
|
||||||
|
|
||||||
/* init fsk */
|
/* init fsk */
|
||||||
if (fsk_init(&r2000->fsk, r2000, fsk_send_bit, fsk_receive_bit, r2000->sender.samplerate, FSK_BIT_RATE, FSK_F0, FSK_F1, TX_PEAK_FSK, 1, FSK_BIT_ADJUST) < 0) {
|
if (fsk_mod_init(&r2000->fsk_mod, r2000, fsk_send_bit, r2000->sender.samplerate, FSK_BIT_RATE, FSK_F0, FSK_F1, TX_PEAK_FSK, 1) < 0) {
|
||||||
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (fsk_demod_init(&r2000->fsk_demod, r2000, fsk_receive_bit, r2000->sender.samplerate, FSK_BIT_RATE, FSK_F0, FSK_F1, FSK_BIT_ADJUST) < 0) {
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +99,11 @@ int dsp_init_sender(r2000_t *r2000)
|
||||||
r2000->rx_max = 144;
|
r2000->rx_max = 144;
|
||||||
|
|
||||||
/* init supervisorty fsk */
|
/* init supervisorty fsk */
|
||||||
if (fsk_init(&r2000->super_fsk, r2000, super_send_bit, super_receive_bit, r2000->sender.samplerate, SUPER_BIT_RATE, SUPER_F0, SUPER_F1, TX_PEAK_SUPER, 0, SUPER_BIT_ADJUST) < 0) {
|
if (fsk_mod_init(&r2000->super_fsk_mod, r2000, super_send_bit, r2000->sender.samplerate, SUPER_BIT_RATE, SUPER_F0, SUPER_F1, TX_PEAK_SUPER, 0) < 0) {
|
||||||
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (fsk_demod_init(&r2000->super_fsk_demod, r2000, super_receive_bit, r2000->sender.samplerate, SUPER_BIT_RATE, SUPER_F0, SUPER_F1, SUPER_BIT_ADJUST) < 0) {
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
PDEBUG_CHAN(DDSP, DEBUG_ERROR, "FSK init failed!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -122,8 +130,10 @@ void dsp_cleanup_sender(r2000_t *r2000)
|
||||||
{
|
{
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for Transceiver.\n");
|
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for Transceiver.\n");
|
||||||
|
|
||||||
fsk_cleanup(&r2000->fsk);
|
fsk_mod_cleanup(&r2000->fsk_mod);
|
||||||
fsk_cleanup(&r2000->super_fsk);
|
fsk_demod_cleanup(&r2000->fsk_demod);
|
||||||
|
fsk_mod_cleanup(&r2000->super_fsk_mod);
|
||||||
|
fsk_demod_cleanup(&r2000->super_fsk_demod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for SYNC bits, then collect data bits */
|
/* Check for SYNC bits, then collect data bits */
|
||||||
|
@ -254,14 +264,14 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double __at
|
||||||
if (r2000->dsp_mode == DSP_MODE_AUDIO_TX
|
if (r2000->dsp_mode == DSP_MODE_AUDIO_TX
|
||||||
|| r2000->dsp_mode == DSP_MODE_AUDIO_TX_RX
|
|| r2000->dsp_mode == DSP_MODE_AUDIO_TX_RX
|
||||||
|| r2000->sender.loopback)
|
|| r2000->sender.loopback)
|
||||||
fsk_receive(&r2000->super_fsk, samples, length);
|
fsk_demod_receive(&r2000->super_fsk_demod, samples, length);
|
||||||
|
|
||||||
/* do de-emphasis */
|
/* do de-emphasis */
|
||||||
if (r2000->de_emphasis)
|
if (r2000->de_emphasis)
|
||||||
de_emphasis(&r2000->estate, samples, length);
|
de_emphasis(&r2000->estate, samples, length);
|
||||||
|
|
||||||
/* fsk signal */
|
/* fsk signal */
|
||||||
fsk_receive(&r2000->fsk, samples, length);
|
fsk_demod_receive(&r2000->fsk_demod, samples, length);
|
||||||
|
|
||||||
/* we must have audio mode for both ways and a call */
|
/* we must have audio mode for both ways and a call */
|
||||||
if (r2000->dsp_mode == DSP_MODE_AUDIO_TX_RX
|
if (r2000->dsp_mode == DSP_MODE_AUDIO_TX_RX
|
||||||
|
@ -342,19 +352,19 @@ again:
|
||||||
if (r2000->pre_emphasis)
|
if (r2000->pre_emphasis)
|
||||||
pre_emphasis(&r2000->estate, samples, length);
|
pre_emphasis(&r2000->estate, samples, length);
|
||||||
/* add supervisory to sample buffer */
|
/* add supervisory to sample buffer */
|
||||||
fsk_send(&r2000->super_fsk, samples, length, 1);
|
fsk_mod_send(&r2000->super_fsk_mod, samples, length, 1);
|
||||||
break;
|
break;
|
||||||
case DSP_MODE_FRAME:
|
case DSP_MODE_FRAME:
|
||||||
/* Encode frame into audio stream. If frames have
|
/* Encode frame into audio stream. If frames have
|
||||||
* stopped, process again for rest of stream. */
|
* stopped, process again for rest of stream. */
|
||||||
count = fsk_send(&r2000->fsk, samples, length, 0);
|
count = fsk_mod_send(&r2000->fsk_mod, samples, length, 0);
|
||||||
/* do pre-emphasis */
|
/* do pre-emphasis */
|
||||||
if (r2000->pre_emphasis)
|
if (r2000->pre_emphasis)
|
||||||
pre_emphasis(&r2000->estate, samples, count);
|
pre_emphasis(&r2000->estate, samples, count);
|
||||||
/* special case: add supervisory signal to frame at loop test */
|
/* special case: add supervisory signal to frame at loop test */
|
||||||
if (r2000->sender.loopback) {
|
if (r2000->sender.loopback) {
|
||||||
/* add supervisory to sample buffer */
|
/* add supervisory to sample buffer */
|
||||||
fsk_send(&r2000->super_fsk, samples, count, 1);
|
fsk_mod_send(&r2000->super_fsk_mod, samples, count, 1);
|
||||||
}
|
}
|
||||||
memset(power, 1, count);
|
memset(power, 1, count);
|
||||||
samples += count;
|
samples += count;
|
||||||
|
@ -390,12 +400,12 @@ void r2000_set_dsp_mode(r2000_t *r2000, enum dsp_mode mode, int super)
|
||||||
/* reset telegramm */
|
/* reset telegramm */
|
||||||
if (mode == DSP_MODE_FRAME && r2000->dsp_mode != mode) {
|
if (mode == DSP_MODE_FRAME && r2000->dsp_mode != mode) {
|
||||||
r2000->tx_frame_length = 0;
|
r2000->tx_frame_length = 0;
|
||||||
fsk_tx_reset(&r2000->fsk);
|
fsk_mod_tx_reset(&r2000->fsk_mod);
|
||||||
}
|
}
|
||||||
if ((mode == DSP_MODE_AUDIO_TX || mode == DSP_MODE_AUDIO_TX_RX)
|
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->dsp_mode != DSP_MODE_AUDIO_TX && r2000->dsp_mode != DSP_MODE_AUDIO_TX_RX)) {
|
||||||
r2000->super_tx_word_length = 0;
|
r2000->super_tx_word_length = 0;
|
||||||
fsk_tx_reset(&r2000->super_fsk);
|
fsk_mod_tx_reset(&r2000->super_fsk_mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (super >= 0) {
|
if (super >= 0) {
|
||||||
|
|
|
@ -85,7 +85,8 @@ typedef struct r2000 {
|
||||||
|
|
||||||
/* dsp states */
|
/* dsp states */
|
||||||
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
||||||
fsk_t fsk; /* fsk processing */
|
fsk_mod_t fsk_mod; /* fsk processing */
|
||||||
|
fsk_demod_t fsk_demod;
|
||||||
char tx_frame[208]; /* carries bits of one frame to transmit */
|
char tx_frame[208]; /* carries bits of one frame to transmit */
|
||||||
int tx_frame_length;
|
int tx_frame_length;
|
||||||
int tx_frame_pos;
|
int tx_frame_pos;
|
||||||
|
@ -102,7 +103,8 @@ typedef struct r2000 {
|
||||||
uint64_t rx_bits_count_last; /* sample counter of last frame */
|
uint64_t rx_bits_count_last; /* sample counter of last frame */
|
||||||
|
|
||||||
/* supervisory dsp states */
|
/* supervisory dsp states */
|
||||||
fsk_t super_fsk; /* fsk processing */
|
fsk_mod_t super_fsk_mod; /* fsk processing */
|
||||||
|
fsk_demod_t super_fsk_demod;
|
||||||
uint32_t super_tx_word; /* supervisory info to transmit */
|
uint32_t super_tx_word; /* supervisory info to transmit */
|
||||||
int super_tx_word_length;
|
int super_tx_word_length;
|
||||||
int super_tx_word_pos;
|
int super_tx_word_pos;
|
||||||
|
|
Loading…
Reference in New Issue