aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2016-11-30 18:09:38 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2016-11-30 18:09:38 +0100
commite34d74aa232a4b7b656a2c36eda952d597bdadfd (patch)
tree46e40cf2ad6e30069c9038b883818a1be172f1a2 /src
parent0b43b63d1f68dbab16d319e79866cdf6b71f5511 (diff)
C-Netz: Simplifying TX signal clock sync between two channels
Diffstat (limited to 'src')
-rw-r--r--src/cnetz/cnetz.c13
-rw-r--r--src/cnetz/cnetz.h4
-rw-r--r--src/cnetz/dsp.c50
3 files changed, 30 insertions, 37 deletions
diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c
index e0f5281..7519241 100644
--- a/src/cnetz/cnetz.c
+++ b/src/cnetz/cnetz.c
@@ -84,6 +84,19 @@
* work with that.
*/
+/*
+ * Notes on sync:
+ *
+ * The encoder generates a precise clocked signal using correction value given
+ * by command line. For multichannel, the second sound card's channel (slave) is
+ * synced to the first one (master), if calculation of signal phase might drift
+ * due to routing errors.
+ *
+ * The decoder is synced to the phone, whenever it receives a valid frame.
+ *
+ * See dsp.c and fsk_fm_demod.c for code about syncing.
+ */
+
#define CHAN cnetz->sender.kanal
#include <stdio.h>
diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h
index 3bda112..343e0f8 100644
--- a/src/cnetz/cnetz.h
+++ b/src/cnetz/cnetz.h
@@ -96,12 +96,14 @@ typedef struct cnetz {
int fsk_tx_buffer_pos; /* current position sending buffer */
double fsk_tx_bitstep; /* fraction of a bit each sample */
double fsk_tx_phase; /* current bit position */
+ uint64_t fsk_tx_scount; /* sample counter (used to sync multiple channels) */
int scrambler; /* 0 = normal speech, 1 = scrambled speech */
int16_t *dsp_speech_buffer; /* samples in one chunk */
int dsp_speech_length; /* number of samples */
int dsp_speech_pos; /* current position in buffer */
- int frame_last_count; /* master's count position of last frame sync */
+ /* sync multiple channels on one sound card */
+ uint64_t frame_last_scount; /* master's sample count of last frame sync */
double frame_last_phase; /* master's bit phase of last frame sync */
/* audio offset removal */
diff --git a/src/cnetz/dsp.c b/src/cnetz/dsp.c
index ee5f81b..3e2dbdb 100644
--- a/src/cnetz/dsp.c
+++ b/src/cnetz/dsp.c
@@ -599,41 +599,27 @@ again:
/* start new telegramm, so we generate one */
if (pos == 0) {
- /* measure actual signal speed */
+ /* a new hyper frame starts */
if (cnetz->sched_ts == 0 && cnetz->sched_r_m == 0) {
+ /* measure actual signal speed */
calc_clock_speed(cnetz, cnetz->sender.samplerate * 24 / 10, 1, 1);
- /* sync TX */
+ /* sync TX (might not be required, if there is no error in math calculation) */
if (cnetz->sender.slave) {
/* we are master, so we store sample count and phase */
- cnetz->frame_last_count = count;
+ cnetz->frame_last_scount = cnetz->fsk_tx_scount;
cnetz->frame_last_phase = cnetz->fsk_tx_phase;
}
if (cnetz->sender.master) {
- /* we are slave, so we sync to sample count and phase */
+ /* we are slave, so we sync to phase */
cnetz_t *master = (cnetz_t *)cnetz->sender.master;
- /* if we are still in sync with the sample count, we adjust the phase */
- if (master->frame_last_count == count) {
- PDEBUG(DDSP, DEBUG_DEBUG, "Sync slave to master: phase(master) = %.15f, phase(slave) = %.15f\n", master->frame_last_phase, cnetz->frame_last_phase);
- cnetz->frame_last_phase = master->frame_last_phase;
- }
- /* only sync, if we do not hit the border of the sample chunk.
- * this way we have slave and master sync at the same sample chunk. */
- if (master->frame_last_count > 0 && master->frame_last_count < length - 1 && count > 0 && count < length - 1) {
- /* if the sample count is one sample ahead, we go back one sample */
- if (count == master->frame_last_count + 1) {
- PDEBUG(DDSP, DEBUG_INFO, "Sync slave to master by going back one sample: phase(master) = %.15f, phase(slave) = %.15f\n", master->frame_last_phase, cnetz->frame_last_phase);
- count--;
- samples--;
- cnetz->frame_last_phase = master->frame_last_phase;
- }
- /* if the sample count is one sample behind, we go forward one sample */
- if (count == master->frame_last_count - 1) {
- PDEBUG(DDSP, DEBUG_INFO, "Sync slave to master by going forth one sample: phase(master) = %.15f, phase(slave) = %.15f\n", master->frame_last_phase, cnetz->frame_last_phase);
- count++;
- *samples = samples[-1];
- samples++;
- cnetz->frame_last_phase = master->frame_last_phase;
- }
+ /* it may happen that the sample count does not match with the master,
+ * because one has a phase wrap before and the other after a sample.
+ * then we do it next hyper frame cycle */
+ if (master->frame_last_scount == cnetz->fsk_tx_scount) {
+ PDEBUG(DDSP, DEBUG_DEBUG, "Sync phase of slave to master: master=%.15f, slave=%.15f, diff=%.15f\n", master->frame_last_phase, cnetz->fsk_tx_phase, master->frame_last_phase - cnetz->fsk_tx_phase);
+ cnetz->fsk_tx_phase = master->frame_last_phase;
+ } else {
+ PDEBUG(DDSP, DEBUG_DEBUG, "Not sync phase of slave to master: Sample counts during frame change are different, ignoring this time!\n");
}
}
}
@@ -746,6 +732,7 @@ again:
}
cnetz->dsp_speech_length = speech_length;
cnetz->dsp_speech_pos = speech_pos;
+ cnetz->fsk_tx_scount += copy;
pos += copy;
count += copy;
if (pos == cnetz->fsk_tx_buffer_length) {
@@ -780,15 +767,6 @@ void sender_send(sender_t *sender, int16_t *samples, int length)
exit(0);
}
-#if 0
- #warning check phase between slave and master process
- /* check for sync to master */
- if (sender->master) {
- if (((cnetz_t *)(sender->master))->fsk_tx_phase != cnetz->fsk_tx_phase) {
- printf("phase between master and slave differs: %.10f vs %.10f!\n", ((cnetz_t *)(sender->master))->fsk_tx_phase, cnetz->fsk_tx_phase);
- }
- }
-#endif
}
/* unshrink audio segment from the duration of 60 bits to 12.5 ms */