|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|