2016-02-16 17:56:55 +00:00
|
|
|
/* FSK decoder of carrier FSK signals received by simple FM receiver
|
|
|
|
*
|
|
|
|
* (C) 2016 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* How does it work:
|
|
|
|
* -----------------
|
|
|
|
*
|
|
|
|
* C-Netz modulates the carrier frequency. If it is 2.4 kHz above, it is high
|
|
|
|
* level, if it is 2.4 kHz below, it is low level. Look at FTZ 171 TR 60
|
|
|
|
* Chapter 5 (data exchange) for closer information.
|
|
|
|
*
|
2017-05-17 10:21:19 +00:00
|
|
|
* Detecting level change (from SDR):
|
|
|
|
*
|
|
|
|
* Whenever we cross zero, we detect a level change. Also we know the level
|
|
|
|
* of the bit then. If we don't get another level change within 1.5 of bit
|
|
|
|
* duration, we will sample the next bit with the current level. From then
|
|
|
|
* we will sample the next bit 1.0 bit duration later, if there is still no
|
|
|
|
* level change. If we get another level change, we take that bit and wait
|
|
|
|
* 1.5 bit duration for next change...
|
|
|
|
*
|
|
|
|
* Detect level change (from analog radio):
|
2016-02-16 17:56:55 +00:00
|
|
|
*
|
|
|
|
* We don't just look for high/low level, because we don't know what the actual
|
|
|
|
* 0-level of the phone's transmitter is. (level of carrier frequency) Also we
|
|
|
|
* use receiver and sound card that cause any level to return to 0 after some
|
2017-05-17 10:21:19 +00:00
|
|
|
* time, Even if the transmitter still transmits a level above or below the
|
2016-02-16 17:56:55 +00:00
|
|
|
* carrier frequnecy. Insted we look at the change of the received signal. An
|
|
|
|
* upward change indicates 1. An downward change indicates 0. (This may also be
|
2017-05-17 10:21:19 +00:00
|
|
|
* reversed, if we find out, that we received a sync sequence in reversed
|
2016-02-16 17:56:55 +00:00
|
|
|
* polarity.) If there is no significant change in level, we keep the value of
|
|
|
|
* last change, regardless of what level we actually receive.
|
|
|
|
*
|
|
|
|
* To determine a change from noise, we use a theshold. This is set to half of
|
|
|
|
* the level of last received change. This means that the next change may be
|
2016-07-24 08:26:01 +00:00
|
|
|
* down to a half lower. There is a special case during distributed signaling.
|
2016-02-16 17:56:55 +00:00
|
|
|
* The first level change of each data chunk raises or falls from 0-level
|
|
|
|
* (unmodulated carrier), so the threshold for this bit is only a quarter of the
|
|
|
|
* last received change.
|
|
|
|
*
|
|
|
|
* While searching for a sync sequence, the threshold for the next change is set
|
|
|
|
* after each change. After synchronization, the the threshold is locked to half
|
|
|
|
* of the average change level of the sync sequence.
|
|
|
|
*
|
|
|
|
* Search window
|
|
|
|
*
|
|
|
|
* We use a window of one bit length (9 samples at 48 kHz sample rate) and look
|
|
|
|
* for a change that is higher than the threshold and has its highest slope in
|
|
|
|
* the middle of the window. To determine the level, the min and max value
|
|
|
|
* inside the window is searched. The differece is the change level. To
|
|
|
|
* determine the highest slope, the highest difference between subsequent
|
|
|
|
* samples is used. For every sample we move the window one bit to the right
|
|
|
|
* (next sample), check if change level matches the threshold and highest slope
|
|
|
|
* is in the middle and so forth. Only if the highes slope is exactly in the
|
|
|
|
* middle, we declare a change. This means that we detect a slope about half of
|
|
|
|
* a bit duration later.
|
|
|
|
*
|
|
|
|
* When we are not synced:
|
|
|
|
*
|
|
|
|
* For every change we record a bit. A positive change is 1 and a negative 0. If
|
|
|
|
* it turns out that the receiver or sound card is reversed, we reverse bits.
|
|
|
|
* After every change we wait up to 1.5 bit duration for next change. If there
|
|
|
|
* is a change, we record our next bit. If there is no change, we record the
|
|
|
|
* state of the last bit. After we had no change, we wait 1 bit duration, since
|
|
|
|
* we already 0.5 behind the start of the recently recorded bit.
|
|
|
|
*
|
|
|
|
* When we are synced:
|
|
|
|
*
|
|
|
|
* After we recorded the time of all level changes during the sync sequence, we
|
2019-07-15 19:14:52 +00:00
|
|
|
* calculate an average and use it as a time base for sampling the subsequent 150
|
2016-02-16 17:56:55 +00:00
|
|
|
* bit of a message. From now on, a bit change does not cause any resync. We
|
|
|
|
* just remember what change we received. Later we use it for sampling the 150
|
|
|
|
* bits.
|
|
|
|
*
|
|
|
|
* We wait a duration of 1.5 bits after the sync sequence and the start of the
|
|
|
|
* bit that follows the sync sequence. We record what we received as last
|
|
|
|
* change. For all following 149 bits we wait 1 bit duration and record what we
|
|
|
|
* received as last change.
|
|
|
|
*
|
|
|
|
* Sync clock
|
|
|
|
*
|
|
|
|
* Because we transmit and receive chunks of sample from buffers of different
|
|
|
|
* drivers, we cannot determine the exact latency between received and
|
|
|
|
* transmitted samples. Also some sound cards may have different RX and TX
|
|
|
|
* speed. One (pure software) solution is to sync ourself to the mobile phone,
|
2017-05-17 10:21:19 +00:00
|
|
|
* since the mobile phone is perfectly synced to us.
|
2016-02-16 17:56:55 +00:00
|
|
|
*
|
2017-05-17 10:21:19 +00:00
|
|
|
* After receiving and decoding of a frame, we use the time of received sync
|
2019-07-15 19:14:52 +00:00
|
|
|
* sequence to synchronize the receiver to the mobile phone. If we receive a
|
2016-02-16 17:56:55 +00:00
|
|
|
* message on the OgK (control channel), we know that this is a response to a
|
|
|
|
* message of a specific time slot we recently sent. Then we can fully sync the
|
|
|
|
* receiver's clock. For any other frame, we cannot determine the absolute
|
|
|
|
* clock. We just correct the receiver's clock, as the clock differs only
|
|
|
|
* slightly from the time the message was received.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-03-16 17:02:56 +00:00
|
|
|
/* Words on debugging:
|
|
|
|
*
|
|
|
|
* A debug file can be written. It will show the current sample that is right
|
|
|
|
* in the middle of the search window. Additional information is shown right
|
|
|
|
* of the sample graph.
|
|
|
|
*/
|
|
|
|
|
2017-05-17 10:21:19 +00:00
|
|
|
/* use to debug decoder
|
|
|
|
* if debug is set to 0, debugging will start from SPK_V signalling,
|
|
|
|
* if debug is set to 1, debugging will start at program start
|
|
|
|
*/
|
2017-03-16 17:02:56 +00:00
|
|
|
//#define DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
//static int debug = 0;
|
2017-03-16 17:02:56 +00:00
|
|
|
|
2016-02-16 17:56:55 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
2017-01-06 13:13:14 +00:00
|
|
|
#include <stdlib.h>
|
2016-02-16 17:56:55 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
2017-11-18 07:06:06 +00:00
|
|
|
#include "../libsample/sample.h"
|
2017-11-18 07:58:57 +00:00
|
|
|
#include "../libdebug/debug.h"
|
2016-02-16 17:56:55 +00:00
|
|
|
#include "cnetz.h"
|
|
|
|
#include "dsp.h"
|
|
|
|
#include "telegramm.h"
|
|
|
|
|
2017-05-19 17:11:59 +00:00
|
|
|
int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitrate, enum demod_type demod)
|
2016-02-16 17:56:55 +00:00
|
|
|
{
|
2016-10-07 07:14:22 +00:00
|
|
|
int len, half;
|
|
|
|
|
2016-02-16 17:56:55 +00:00
|
|
|
memset(fsk, 0, sizeof(*fsk));
|
|
|
|
if (samplerate < 48000) {
|
|
|
|
PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 48000 Hz!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fsk->cnetz = cnetz;
|
2017-05-19 17:11:59 +00:00
|
|
|
fsk->demod_type = demod;
|
2017-05-17 10:21:19 +00:00
|
|
|
|
2017-05-19 17:11:59 +00:00
|
|
|
switch (demod) {
|
|
|
|
case FSK_DEMOD_SLOPE:
|
2017-05-17 10:21:19 +00:00
|
|
|
PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking at slope (good for sound cards)\n");
|
2017-05-19 17:11:59 +00:00
|
|
|
break;
|
|
|
|
case FSK_DEMOD_LEVEL:
|
2017-05-17 10:21:19 +00:00
|
|
|
PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking zero crosssing (good for SDR)\n");
|
2017-05-19 17:11:59 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
PDEBUG(DDSP, DEBUG_ERROR, "Wrong demod type, please fix!\n");
|
|
|
|
abort();
|
|
|
|
}
|
2016-02-16 17:56:55 +00:00
|
|
|
|
|
|
|
len = (int)((double)samplerate / bitrate + 0.5);
|
|
|
|
half = (int)((double)samplerate / bitrate / 2.0 + 0.5);
|
2017-01-06 13:13:14 +00:00
|
|
|
fsk->bit_buffer_spl = calloc(sizeof(fsk->bit_buffer_spl[0]), len);
|
|
|
|
if (!fsk->bit_buffer_spl) {
|
|
|
|
PDEBUG(DDSP, DEBUG_ERROR, "No mem!\n");
|
|
|
|
goto error;
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fsk->bit_buffer_len = len;
|
|
|
|
fsk->bit_buffer_half = half;
|
|
|
|
fsk->bits_per_sample = bitrate / (double)samplerate;
|
|
|
|
|
2017-01-06 13:13:14 +00:00
|
|
|
fsk->speech_size = samplerate * 60 / bitrate + 10; /* 60 bits duration, add 10 to be safe */
|
|
|
|
fsk->speech_buffer = calloc(sizeof(fsk->speech_buffer[0]), fsk->speech_size);
|
|
|
|
if (!fsk->speech_buffer) {
|
|
|
|
PDEBUG(DDSP, DEBUG_ERROR, "No mem!\n");
|
|
|
|
goto error;
|
|
|
|
}
|
2016-02-16 17:56:55 +00:00
|
|
|
|
2017-01-29 06:25:12 +00:00
|
|
|
fsk->level_threshold = 0.1;
|
2016-02-16 17:56:55 +00:00
|
|
|
|
2017-03-16 17:02:56 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
char debug_filename[256];
|
2017-05-17 10:21:19 +00:00
|
|
|
sprintf(debug_filename, "/tmp/debug_decoder_channel_%d.txt", cnetz->sender.kanal);
|
2017-03-16 17:02:56 +00:00
|
|
|
fsk->debug_fp = fopen(debug_filename, "w");
|
|
|
|
if (!fsk->debug_fp) {
|
|
|
|
fprintf(stderr, "Failed to open decoder debug file '%s'!\n", debug_filename);
|
|
|
|
exit(0);
|
|
|
|
} else
|
|
|
|
printf("**** Writing decoder debug file '%s' ****\n", debug_filename);
|
|
|
|
#endif
|
|
|
|
|
2018-01-21 08:30:00 +00:00
|
|
|
fsk->dmp_frame_level = display_measurements_add(&cnetz->sender.dispmeas, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
|
|
|
fsk->dmp_frame_stddev = display_measurements_add(&cnetz->sender.dispmeas, "Frame Stddev", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
2017-09-25 16:46:50 +00:00
|
|
|
|
2016-02-16 17:56:55 +00:00
|
|
|
return 0;
|
2017-01-06 13:13:14 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
fsk_fm_exit(fsk);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fsk_fm_exit(fsk_fm_demod_t *fsk)
|
|
|
|
{
|
|
|
|
if (fsk->bit_buffer_spl) {
|
|
|
|
free(fsk->bit_buffer_spl);
|
|
|
|
fsk->bit_buffer_spl = NULL;
|
|
|
|
}
|
|
|
|
if (fsk->speech_buffer) {
|
|
|
|
free(fsk->speech_buffer);
|
|
|
|
fsk->speech_buffer = NULL;
|
|
|
|
}
|
2017-03-16 17:02:56 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (fsk->debug_fp) {
|
|
|
|
fclose(fsk->debug_fp);
|
|
|
|
fsk->debug_fp = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 10:28:51 +00:00
|
|
|
/* get levels, sync time and jitter/stddev from sync sequence or frame data */
|
|
|
|
static inline void get_levels(fsk_fm_demod_t *fsk, double *_min, double *_max, double *_avg, int *_probes, int num, double *_time, double *_jitter, double *_stddev)
|
2016-02-16 17:56:55 +00:00
|
|
|
{
|
2017-01-29 06:25:12 +00:00
|
|
|
int count = 0;
|
|
|
|
double min = 0, max = 0, avg = 0, level;
|
2017-10-02 10:28:51 +00:00
|
|
|
double time = 0, t, sync_average, sync_time, jitter = 0.0, stddev = 0.0;
|
2016-02-16 17:56:55 +00:00
|
|
|
int bit_offset;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* get levels an the average receive time */
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
level = fsk->change_levels[(fsk->change_pos - 1 - i) & 0xff];
|
2017-05-17 10:21:19 +00:00
|
|
|
if (level <= 0.0)
|
2016-02-16 17:56:55 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* in spk mode, we skip the voice part (62 bits) */
|
|
|
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
|
|
|
bit_offset = i + ((i + 2) >> 2) * 62;
|
|
|
|
else
|
|
|
|
bit_offset = i;
|
2016-10-07 07:14:22 +00:00
|
|
|
t = fmod(fsk->change_when[(fsk->change_pos - 1 - i) & 0xff] - fsk->bit_time + (double)bit_offset + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
2016-02-16 17:56:55 +00:00
|
|
|
if (t > BITS_PER_SUPERFRAME / 2)
|
|
|
|
t -= BITS_PER_SUPERFRAME;
|
|
|
|
//if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
2017-01-29 06:25:12 +00:00
|
|
|
// printf("%d: level=%.0f%% @%.2f difference=%.2f\n", bit_offset, level * 100, fsk->change_when[(fsk->change_pos - 1 - i) & 0xff], t);
|
2016-02-16 17:56:55 +00:00
|
|
|
time += t;
|
|
|
|
|
2017-01-29 06:25:12 +00:00
|
|
|
if (i == 0 || level < min)
|
2016-02-16 17:56:55 +00:00
|
|
|
min = level;
|
2017-01-29 06:25:12 +00:00
|
|
|
if (i == 0 || level > max)
|
2016-02-16 17:56:55 +00:00
|
|
|
max = level;
|
|
|
|
avg += level;
|
|
|
|
count++;
|
|
|
|
}
|
2017-10-02 10:28:51 +00:00
|
|
|
avg /= (double)count;
|
|
|
|
time /= (double)count;
|
2016-02-16 17:56:55 +00:00
|
|
|
|
2017-01-29 06:25:12 +00:00
|
|
|
/* should never happen */
|
2016-02-16 17:56:55 +00:00
|
|
|
if (!count) {
|
2017-01-29 06:25:12 +00:00
|
|
|
*_min = *_max = *_avg = 0.0;
|
2016-02-16 17:56:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* when did we received the sync?
|
|
|
|
* sync_average is the average about how early (negative) or
|
|
|
|
* late (positive) we received the sync relative to current bit_time.
|
|
|
|
* sync_time is the absolute time within the super frame.
|
|
|
|
*/
|
2017-10-02 10:28:51 +00:00
|
|
|
sync_average = time;
|
2016-10-07 07:14:22 +00:00
|
|
|
sync_time = fmod(sync_average + fsk->bit_time + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
2016-02-16 17:56:55 +00:00
|
|
|
|
|
|
|
*_probes = count;
|
|
|
|
*_min = min;
|
|
|
|
*_max = max;
|
2017-10-02 10:28:51 +00:00
|
|
|
*_avg = avg;
|
2016-02-16 17:56:55 +00:00
|
|
|
|
|
|
|
if (_time) {
|
|
|
|
// if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
|
|
|
// printf("sync at distributed mode\n");
|
|
|
|
// printf("sync at bit_time=%.2f (sync_average = %.2f)\n", sync_time, sync_average);
|
|
|
|
/* if our average sync is later (greater) than the current
|
|
|
|
* bit_time, we must wait longer (next_bit above 1.5)
|
|
|
|
* for the time to sample the bit.
|
|
|
|
* if sync is earlier, bit_time is already too late, so
|
|
|
|
* we must wait less than 1.5 bits */
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->next_bit = 1.5 + sync_average;
|
2016-02-16 17:56:55 +00:00
|
|
|
*_time = sync_time;
|
|
|
|
}
|
|
|
|
if (_jitter) {
|
|
|
|
/* get jitter of received changes */
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
level = fsk->change_levels[(fsk->change_pos - 1 - i) & 0xff];
|
2017-05-17 10:21:19 +00:00
|
|
|
if (level <= 0.0)
|
2016-02-16 17:56:55 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* in spk mode, we skip the voice part (62 bits) */
|
|
|
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V)
|
|
|
|
bit_offset = i + ((i + 2) >> 2) * 62;
|
|
|
|
else
|
|
|
|
bit_offset = i;
|
|
|
|
t = fmod(fsk->change_when[(fsk->change_pos - 1 - i) & 0xff] - sync_time + (double)bit_offset + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
|
|
|
if (t > BITS_PER_SUPERFRAME / 2)
|
|
|
|
t = BITS_PER_SUPERFRAME - t; /* turn negative into positive */
|
|
|
|
jitter += t;
|
|
|
|
}
|
|
|
|
*_jitter = jitter / (double)count;
|
|
|
|
}
|
2017-10-02 10:28:51 +00:00
|
|
|
if (_stddev) {
|
|
|
|
/* get standard deviation of level */
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
level = fsk->change_levels[(fsk->change_pos - 1 - i) & 0xff];
|
|
|
|
if (level <= 0.0)
|
|
|
|
continue;
|
|
|
|
stddev += (level - avg) * (level - avg);
|
|
|
|
}
|
|
|
|
*_stddev = sqrt(stddev / (double)count);
|
|
|
|
}
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 06:25:12 +00:00
|
|
|
static inline void got_bit(fsk_fm_demod_t *fsk, int bit, double change_level)
|
2016-02-16 17:56:55 +00:00
|
|
|
{
|
2017-01-29 06:25:12 +00:00
|
|
|
int probes;
|
|
|
|
double min, max, avg;
|
2016-02-16 17:56:55 +00:00
|
|
|
|
|
|
|
/* count bits, but do not exceed 4 bits per SPK block */
|
|
|
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
|
|
|
/* for first bit, we have only half of the modulation deviation, so we multiply level by two */
|
2016-10-07 07:14:22 +00:00
|
|
|
if (fsk->bit_count == 0)
|
2017-01-29 06:25:12 +00:00
|
|
|
change_level *= 2.0;
|
2017-05-17 10:21:19 +00:00
|
|
|
if (fsk->bit_count >= 4)
|
2016-02-16 17:56:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->bit_count++;
|
2016-02-16 17:56:55 +00:00
|
|
|
|
|
|
|
fsk->change_levels[fsk->change_pos] = change_level;
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->change_when[fsk->change_pos++] = fsk->bit_time;
|
2016-02-16 17:56:55 +00:00
|
|
|
|
|
|
|
|
2016-10-07 07:14:22 +00:00
|
|
|
switch (fsk->sync) {
|
2016-02-16 17:56:55 +00:00
|
|
|
case FSK_SYNC_NONE:
|
|
|
|
fsk->rx_sync = (fsk->rx_sync << 1) | bit;
|
|
|
|
/* use half level of last change for threshold change detection.
|
|
|
|
* if there is no change detected for 5 bits, set theshold to
|
|
|
|
* 1 percent, so the 7 pause bits before a frame will make sure
|
|
|
|
* that the change is below noise level, so the first sync
|
|
|
|
* bit is detected. then the change is set and adjusted
|
|
|
|
* for all other bits in the sync sequence.
|
|
|
|
* after sync, the theshold is set to half of the average of
|
|
|
|
* all changes in the sync sequence */
|
2017-01-29 06:25:12 +00:00
|
|
|
if (change_level > 0.0) {
|
|
|
|
fsk->level_threshold = change_level / 2.0;
|
2016-02-16 17:56:55 +00:00
|
|
|
} else if ((fsk->rx_sync & 0x1f) == 0x00 || (fsk->rx_sync & 0x1f) == 0x1f) {
|
|
|
|
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V)
|
2017-01-29 06:25:12 +00:00
|
|
|
fsk->level_threshold = 0.01;
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
if (detect_sync(fsk->rx_sync)) {
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->sync = FSK_SYNC_POSITIVE;
|
2016-02-16 17:56:55 +00:00
|
|
|
got_sync:
|
2017-03-16 17:02:56 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, " SYNC!");
|
2017-03-16 17:02:56 +00:00
|
|
|
#endif
|
2017-10-02 10:28:51 +00:00
|
|
|
get_levels(fsk, &min, &max, &avg, &probes, 30, &fsk->sync_time, NULL, &fsk->sync_stddev);
|
2017-05-17 10:21:19 +00:00
|
|
|
fsk->sync_level = avg;
|
2016-10-07 07:14:22 +00:00
|
|
|
if (fsk->sync == FSK_SYNC_NEGATIVE)
|
|
|
|
fsk->sync_level = -fsk->sync_level;
|
2017-10-02 10:28:51 +00:00
|
|
|
// printf("sync (change min=%.0f%% max=%.0f%% avg=%.0f%% sync_time=%.2f stddev=%.0f%% probes=%d)\n", min * 100, max * 100, avg * 100, fsk->sync_time, fsk->sync_stddev / avg, probes);
|
2017-05-17 10:21:19 +00:00
|
|
|
fsk->level_threshold = (double)avg;
|
2016-02-16 17:56:55 +00:00
|
|
|
fsk->rx_sync = 0;
|
|
|
|
fsk->rx_buffer_count = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (detect_sync(fsk->rx_sync ^ 0xfffffffff)) {
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->sync = FSK_SYNC_NEGATIVE;
|
2016-02-16 17:56:55 +00:00
|
|
|
goto got_sync;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FSK_SYNC_NEGATIVE:
|
|
|
|
bit = 1 - bit;
|
2018-01-27 14:52:33 +00:00
|
|
|
/* FALLTHRU */
|
2016-02-16 17:56:55 +00:00
|
|
|
case FSK_SYNC_POSITIVE:
|
|
|
|
fsk->rx_buffer[fsk->rx_buffer_count] = bit + '0';
|
|
|
|
if (++fsk->rx_buffer_count == 150) {
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->sync = FSK_SYNC_NONE;
|
2017-03-16 17:02:56 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, " FRAME DONE!");
|
2017-03-16 17:02:56 +00:00
|
|
|
#endif
|
2016-02-16 17:56:55 +00:00
|
|
|
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
|
|
|
/* received 40 bits after start of block */
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->sync_time = fmod(fsk->sync_time - (7+33) + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
2016-02-16 17:56:55 +00:00
|
|
|
} else {
|
|
|
|
/* received 662 bits after start of block (10 SPK blocks + 1 bit (== 2 level changes)) */
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->sync_time = fmod(fsk->sync_time - (66*10+2) + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
2017-09-25 16:46:50 +00:00
|
|
|
/* update measurements */
|
|
|
|
display_measurements_update(fsk->dmp_frame_level, fabs(fsk->sync_level) / fsk->cnetz->fsk_deviation * 100.0, 0.0);
|
|
|
|
display_measurements_update(fsk->dmp_frame_stddev, fsk->sync_stddev / fabs(fsk->sync_level) * 100.0, 0.0);
|
2017-10-02 10:28:51 +00:00
|
|
|
/* receive frame */
|
|
|
|
cnetz_decode_telegramm(fsk->cnetz, fsk->rx_buffer, fsk->sync_level, fsk->sync_time, fsk->sync_stddev);
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-17 10:21:19 +00:00
|
|
|
/* find bit change by checking slope within a window */
|
|
|
|
static inline void find_change_slope(fsk_fm_demod_t *fsk)
|
2016-02-16 17:56:55 +00:00
|
|
|
{
|
2017-01-27 15:57:34 +00:00
|
|
|
sample_t level_min = 0, level_max = 0, change_max = -1;
|
|
|
|
int change_at = -1, change_positive = -1;
|
|
|
|
sample_t s, last_s = 0;
|
|
|
|
sample_t threshold;
|
2016-02-16 17:56:55 +00:00
|
|
|
int i;
|
|
|
|
|
2017-05-17 10:21:19 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
/* show deviation of middle sample in windows (in a range of bandwidth) */
|
|
|
|
if (debug) {
|
|
|
|
fprintf(fsk->debug_fp, "%s",
|
|
|
|
debug_amplitude(
|
|
|
|
fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif
|
2016-02-16 17:56:55 +00:00
|
|
|
|
2017-01-29 06:25:12 +00:00
|
|
|
/* get level range (level_min and level_max) and also
|
|
|
|
* get maximum slope (change_max) and where it was
|
|
|
|
* (change_at) and what direction it went (change_positive)
|
|
|
|
*/
|
2016-10-07 07:14:22 +00:00
|
|
|
for (i = 0; i < fsk->bit_buffer_len; i++) {
|
2016-02-16 17:56:55 +00:00
|
|
|
last_s = s;
|
2016-10-07 07:14:22 +00:00
|
|
|
s = fsk->bit_buffer_spl[fsk->bit_buffer_pos++];
|
|
|
|
if (fsk->bit_buffer_pos == fsk->bit_buffer_len)
|
|
|
|
fsk->bit_buffer_pos = 0;
|
2016-02-16 17:56:55 +00:00
|
|
|
if (i > 0) {
|
|
|
|
if (s - last_s > change_max) {
|
|
|
|
change_max = s - last_s;
|
|
|
|
change_at = i;
|
|
|
|
change_positive = 1;
|
|
|
|
} else if (last_s - s > change_max) {
|
|
|
|
change_max = last_s - s;
|
|
|
|
change_at = i;
|
|
|
|
change_positive = 0;
|
|
|
|
}
|
|
|
|
}
|
2017-01-27 15:57:34 +00:00
|
|
|
if (i == 0 || s > level_max)
|
2016-02-16 17:56:55 +00:00
|
|
|
level_max = s;
|
2017-01-27 15:57:34 +00:00
|
|
|
if (i == 0 || s < level_min)
|
2016-02-16 17:56:55 +00:00
|
|
|
level_min = s;
|
|
|
|
}
|
|
|
|
/* for first bit, we have only half of the modulation deviation, so we divide the threshold by two */
|
2016-10-07 07:14:22 +00:00
|
|
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0)
|
2017-01-27 15:57:34 +00:00
|
|
|
threshold = fsk->level_threshold / 2.0;
|
2016-02-16 17:56:55 +00:00
|
|
|
else
|
2016-10-07 07:14:22 +00:00
|
|
|
threshold = fsk->level_threshold;
|
2016-02-16 17:56:55 +00:00
|
|
|
/* if we are not in sync, for every detected change we set
|
|
|
|
* next_bit to 1.5, so we wait 1.5 bits for next change
|
|
|
|
* if it is not received within this time, there is no change,
|
|
|
|
* so the bit does not change.
|
|
|
|
* if we are in sync, we remember last change. after 1.5
|
|
|
|
* bits after sync average, we measure the first bit
|
|
|
|
* and then all subsequent bits after 1.0 bits */
|
2016-10-07 07:14:22 +00:00
|
|
|
if (level_max - level_min > threshold && change_at == fsk->bit_buffer_half) {
|
2016-02-16 17:56:55 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
if (debug) {
|
|
|
|
fprintf(fsk->debug_fp, " CHANGE %d->%d (level=%.3f, threshold=%.3f)",
|
2017-03-16 17:02:56 +00:00
|
|
|
fsk->last_change_positive,
|
|
|
|
change_positive,
|
|
|
|
level_max - level_min,
|
|
|
|
threshold);
|
2017-05-17 10:21:19 +00:00
|
|
|
}
|
2016-02-16 17:56:55 +00:00
|
|
|
#endif
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->last_change_positive = change_positive;
|
|
|
|
if (!fsk->sync) {
|
|
|
|
fsk->next_bit = 1.5;
|
2017-10-02 10:28:51 +00:00
|
|
|
got_bit(fsk, change_positive, (level_max - level_min) / 2.0);
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-07 07:14:22 +00:00
|
|
|
if (fsk->next_bit <= 0.0) {
|
2016-02-16 17:56:55 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, " SAMPLING %d", fsk->last_change_positive);
|
2016-02-16 17:56:55 +00:00
|
|
|
#endif
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->next_bit += 1.0;
|
2017-05-17 10:21:19 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug && fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count >= 4)
|
|
|
|
fprintf(fsk->debug_fp, " (ignoring)");
|
|
|
|
#endif
|
|
|
|
got_bit(fsk, fsk->last_change_positive, 0.0);
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->next_bit -= fsk->bits_per_sample;
|
2017-05-17 10:21:19 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, "\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find bit change by looking at zero crossing */
|
|
|
|
static inline void find_change_level(fsk_fm_demod_t *fsk)
|
|
|
|
{
|
|
|
|
int change_positive = -1;
|
|
|
|
sample_t s;
|
|
|
|
|
|
|
|
/* get bit in the middle of the buffer */
|
|
|
|
s = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len];
|
|
|
|
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
/* show deviation */
|
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, "%s", debug_amplitude(s));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* just sample first bit in distributed mode */
|
|
|
|
if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0) {
|
|
|
|
if (fmod(fsk->bit_time, BITS_PER_SPK_BLOCK) < 1.5)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, " (First bit of data chunk)");
|
|
|
|
#endif
|
|
|
|
/* use current level for first bit to sample */
|
|
|
|
fsk->last_change_positive = (s > 0);
|
|
|
|
fsk->next_bit = 0.0;
|
|
|
|
} else {
|
|
|
|
/* see if we have a level change */
|
|
|
|
if (!fsk->last_change_positive && s > 0)
|
|
|
|
change_positive = 1;
|
|
|
|
if (fsk->last_change_positive && s < 0)
|
|
|
|
change_positive = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we are not in sync, for every detected change we set
|
|
|
|
* next_bit to 1.5, so we wait 1.5 bits for next change
|
|
|
|
* if it is not received within this time, there is no change,
|
|
|
|
* so the bit does not change.
|
|
|
|
* if we are in sync, we remember last change. after 1.5
|
|
|
|
* bits after sync average, we measure the first bit
|
|
|
|
* and then all subsequent bits after 1.0 bits */
|
|
|
|
if (change_positive >= 0) {
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, " CHANGE %d->%d", fsk->last_change_positive, change_positive);
|
|
|
|
#endif
|
|
|
|
fsk->last_change_positive = change_positive;
|
|
|
|
if (!fsk->sync) {
|
|
|
|
fsk->next_bit = 1.5;
|
2017-10-02 10:28:51 +00:00
|
|
|
/* if bit change is inside window, we can get level from borders of window */
|
|
|
|
s = fsk->bit_buffer_spl[fsk->bit_buffer_pos];
|
|
|
|
s -= fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_len - 1) % fsk->bit_buffer_len];
|
|
|
|
got_bit(fsk, change_positive, fabs(s / 2.0));
|
2017-05-17 10:21:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fsk->next_bit <= 0.0) {
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, " SAMPLING %d", fsk->last_change_positive);
|
|
|
|
#endif
|
|
|
|
fsk->next_bit += 1.0;
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug && fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count >= 4)
|
|
|
|
fprintf(fsk->debug_fp, " (ignoring)");
|
|
|
|
#endif
|
|
|
|
got_bit(fsk, fsk->last_change_positive, 0.0);
|
|
|
|
}
|
|
|
|
fsk->next_bit -= fsk->bits_per_sample;
|
|
|
|
|
|
|
|
done:
|
|
|
|
#ifdef DEBUG_DECODER
|
|
|
|
if (debug)
|
|
|
|
fprintf(fsk->debug_fp, "\n");
|
|
|
|
#endif
|
|
|
|
return;
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* receive FM signal from receiver */
|
2017-01-27 15:57:34 +00:00
|
|
|
void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length)
|
2016-02-16 17:56:55 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double t;
|
|
|
|
|
2016-07-24 08:26:01 +00:00
|
|
|
/* process signaling block, sample by sample */
|
2016-02-16 17:56:55 +00:00
|
|
|
for (i = 0; i < length; i++) {
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->bit_buffer_spl[fsk->bit_buffer_pos++] = samples[i];
|
|
|
|
if (fsk->bit_buffer_pos == fsk->bit_buffer_len)
|
|
|
|
fsk->bit_buffer_pos = 0;
|
2017-03-16 17:02:56 +00:00
|
|
|
|
2016-02-16 17:56:55 +00:00
|
|
|
/* for each sample process buffer */
|
|
|
|
if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) {
|
2017-05-17 10:21:19 +00:00
|
|
|
if (fsk->demod_type == FSK_DEMOD_SLOPE)
|
|
|
|
find_change_slope(fsk);
|
|
|
|
else
|
|
|
|
find_change_level(fsk);
|
|
|
|
} else {
|
2016-02-16 17:56:55 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
/* start debugging */
|
|
|
|
debug = 1;
|
2017-03-16 17:02:56 +00:00
|
|
|
#endif
|
2016-07-24 08:26:01 +00:00
|
|
|
/* in distributed signaling, measure over 5 bits, but ignore 5th bit.
|
2016-02-16 17:56:55 +00:00
|
|
|
* also reset next_bit, as soon as we reach the window */
|
|
|
|
/* note that we start from 0.5, because we detect change 0.5 bits later,
|
|
|
|
* because the detector of the change is in the middle of the 1 bit
|
|
|
|
* search window */
|
2016-10-07 07:14:22 +00:00
|
|
|
t = fmod(fsk->bit_time, BITS_PER_SPK_BLOCK);
|
2016-02-16 17:56:55 +00:00
|
|
|
if (t < 0.5) {
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->next_bit = 1.0 - fsk->bits_per_sample;
|
2016-02-16 17:56:55 +00:00
|
|
|
#ifdef DEBUG_DECODER
|
2017-05-17 10:21:19 +00:00
|
|
|
if (debug && fsk->bit_count)
|
2017-03-16 17:02:56 +00:00
|
|
|
fprintf(fsk->debug_fp, "---- SPK(V) BLOCK START ----\n");
|
2016-02-16 17:56:55 +00:00
|
|
|
#endif
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->bit_count = 0;
|
2016-02-16 17:56:55 +00:00
|
|
|
} else
|
|
|
|
if (t >= 0.5 && t < 5.5) {
|
2017-05-17 10:21:19 +00:00
|
|
|
if (fsk->demod_type == FSK_DEMOD_SLOPE)
|
|
|
|
find_change_slope(fsk);
|
|
|
|
else
|
|
|
|
find_change_level(fsk);
|
2016-02-16 17:56:55 +00:00
|
|
|
} else
|
|
|
|
if (t >= 5.5 && t < 65.5) {
|
|
|
|
/* get audio for the duration of 60 bits */
|
2016-05-13 06:56:26 +00:00
|
|
|
/* prevent overflow, if speech_size != 0 and SPK_V
|
|
|
|
* has been restarted. */
|
2017-08-27 07:35:46 +00:00
|
|
|
if (fsk->speech_count < fsk->speech_size)
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->speech_buffer[fsk->speech_count++] = samples[i];
|
2016-02-16 17:56:55 +00:00
|
|
|
} else
|
|
|
|
if (t >= 65.5) {
|
2016-10-07 07:14:22 +00:00
|
|
|
if (fsk->speech_count) {
|
|
|
|
unshrink_speech(fsk->cnetz, fsk->speech_buffer, fsk->speech_count);
|
|
|
|
fsk->speech_count = 0;
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-13 06:56:26 +00:00
|
|
|
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->bit_time += fsk->bits_per_sample;
|
|
|
|
if (fsk->bit_time >= BITS_PER_SUPERFRAME) {
|
|
|
|
fsk->bit_time -= BITS_PER_SUPERFRAME;
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
/* another clock is used to measure actual super frame time */
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->bit_time_uncorrected += fsk->bits_per_sample;
|
|
|
|
if (fsk->bit_time_uncorrected >= BITS_PER_SUPERFRAME) {
|
|
|
|
fsk->bit_time_uncorrected -= BITS_PER_SUPERFRAME;
|
2017-02-01 16:57:09 +00:00
|
|
|
calc_clock_speed(fsk->cnetz, (double)fsk->cnetz->sender.samplerate * 2.4, 0, 1);
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-07 06:55:18 +00:00
|
|
|
void fsk_correct_sync(fsk_fm_demod_t *fsk, double offset)
|
2016-02-16 17:56:55 +00:00
|
|
|
{
|
2016-10-07 07:14:22 +00:00
|
|
|
fsk->bit_time = fmod(fsk->bit_time - offset + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
2016-02-16 17:56:55 +00:00
|
|
|
}
|
|
|
|
|
2016-12-01 16:59:08 +00:00
|
|
|
/* copy sync from one instance to another (used to sync RX of SpK to OgK */
|
|
|
|
void fsk_copy_sync(fsk_fm_demod_t *fsk_to, fsk_fm_demod_t *fsk_from)
|
|
|
|
{
|
|
|
|
fsk_to->bit_time = fsk_from->bit_time;
|
|
|
|
}
|
|
|
|
|
2016-10-07 06:00:34 +00:00
|
|
|
void fsk_demod_reset(fsk_fm_demod_t *fsk)
|
|
|
|
{
|
|
|
|
fsk->sync = FSK_SYNC_NONE;
|
|
|
|
}
|
|
|
|
|