Commit 6db88c78 authored by Titouan Soulard's avatar Titouan Soulard

trx-bridge: better timestamp handling

- Save input and output timestamps separately
- Avoid timestamp mismatch from trx_play
- Loop on reading samples from input device
parent 412d4662
......@@ -20,11 +20,8 @@ int trx_play_start(TRXState *s, const TRXDriverParams2 *p) {
return 0;
}
// Dummy function used for the sole purpose of setting the timestamp
void trx_play_write(TRXState *s, trx_timestamp_t timestamp, const void **samples, int count, int tx_port_index, TRXWriteMetadata *md) {
struct TRXPlayContext *trx_play_ctx = s->opaque;
trx_play_ctx->last_timestamp = timestamp;
// Nothing to do
}
int trx_play_read(TRXState *s, trx_timestamp_t *ptimestamp, void **psamples, int count, int rx_port_index, TRXReadMetadata *md) {
......@@ -38,6 +35,9 @@ int trx_play_read(TRXState *s, trx_timestamp_t *ptimestamp, void **psamples, int
channels = (TRXComplex **) psamples;
// Restrict count to buffer length
if(count > trx_play_ctx->sample_count) count = trx_play_ctx->sample_count;
// Handle reading after end of buffer
if(trx_play_ctx->current_sample + count >= trx_play_ctx->sample_count) {
extra_samples = trx_play_ctx->current_sample + count - trx_play_ctx->sample_count;
......@@ -115,6 +115,7 @@ int trx_driver_init(TRXState *s) {
trx_play_ctx->samples = (TRXComplex *) samples_file_content;
trx_play_ctx->sample_count = sample_count;
trx_play_ctx->current_sample = 0;
trx_play_ctx->last_timestamp = 0;
printf("trx_play: looping %u frames from %s\n", sample_count, samples_file_path);
......
......@@ -137,14 +137,17 @@ int main(int argc, char *argv[]) {
TRXReadMetadata read_md;
TRXWriteMetadata write_md;
trx_timestamp_t input_ts;
trx_timestamp_t output_ts = 0;
trx_timestamp_t input_rx_ts = 0;
trx_timestamp_t input_tx_ts = 0;
trx_timestamp_t output_rx_ts = 0;
trx_timestamp_t output_tx_ts = 0;
size_t bridge_config_path_size;
size_t driver_config_dir_size;
int opt;
int input_read_count;
int input_read_count_extra;
int output_read_count;
int result;
char *error;
......@@ -163,6 +166,7 @@ int main(int argc, char *argv[]) {
// IQ samples are complex numbers
// A flat plane of Complex is created for all channels
TRXComplex *input_samples = malloc(2 * TRX_BUFFER_SIZE * sizeof(TRXComplex));
TRXComplex *input_channels_base[2] = { input_samples, &input_samples[TRX_BUFFER_SIZE] };
TRXComplex *input_channels[2] = { input_samples, &input_samples[TRX_BUFFER_SIZE] };
TRXComplex *output_samples = malloc(2 * TRX_BUFFER_SIZE * sizeof(TRXComplex));
......@@ -295,28 +299,49 @@ int main(int argc, char *argv[]) {
printf("trx-bridge: started successfully\n");
while(1) {
// First step is to read samples from output to get the timestamp
output_read_count = output_trx_state.trx_read_func2(&output_trx_state, &output_ts, (void **) output_channels, TRX_BUFFER_SIZE, 0, &read_md);
// Read from output first to know how many samples should be read
output_rx_ts = 0;
output_read_count = output_trx_state.trx_read_func2(&output_trx_state, &output_rx_ts, (void **) output_channels, TRX_BUFFER_SIZE, 0, &read_md);
// As much samples should be read from input than from output.
// However, sometimes, the input driver won't return enough samples,
// so we need to loop for samples.
input_read_count = 0;
while(input_read_count < output_read_count) {
input_channels[0] = input_channels_base[0] + input_read_count;
input_channels[1] = input_channels_base[1] + input_read_count;
input_read_count_extra = input_trx_state.trx_read_func2(&input_trx_state, &input_rx_ts, (void **) input_channels, output_read_count - input_read_count, 0, &read_md);
// If no samples can be read, escape from infinite loop
// This return to operations, but will discard some frames
if(input_read_count_extra == 0) break;
input_read_count += input_read_count_extra;
}
// Expected behavior: input timestamp is set once based on output timestamp
// and incremented every time.
// Expected behavior: TX (i.e. write) timestamp is set once based on RX (i.e. read)
// timestamp and incremented after every write.
// The buffer size in TRX SDR is four times the samples rate, so this
// value is used here as an offset between the two timestamps.
if(input_ts == 0) input_ts = output_ts + 4 * 23040;
// Real behavior: sometimes, the output timestamp deviates, so they should be
// matched again.
if(output_ts != input_ts - 4 * 23040) {
printf("TS don't match %ld != %ld\n", output_ts, input_ts - 4 * 23040);
input_ts = output_ts + 4 * 23040;
// value is used here as tn offset between the two timestamps.
if(output_tx_ts == 0) output_tx_ts = output_rx_ts + 4 * 23040;
if(input_tx_ts == 0) input_tx_ts = input_rx_ts + 4 * 23040;
// Real behavior: sometimes, the TX timestamp deviates, so it should be matched again.
if(output_tx_ts != output_rx_ts + 4 * 23040) {
printf("Output timestamp don't match %lu != %lu\n", output_tx_ts, output_rx_ts + 4 * 23040);
output_tx_ts = output_rx_ts + 4 * 23040;
}
if(input_tx_ts != input_rx_ts + 4 * 23040) {
printf("Input timestamp don't match %lu != %lu\n", input_tx_ts, input_rx_ts + 4 * 23040);
input_tx_ts = input_rx_ts + 4 * 23040;
}
// Writing to input also propagates timestamp
input_trx_state.trx_write_func2(&input_trx_state, input_ts, (const void **) output_channels, output_read_count, 0, &write_md);
output_trx_state.trx_write_func2(&output_trx_state, output_tx_ts, (const void **) input_channels_base, input_read_count, 0, &write_md);
output_tx_ts += input_read_count;
// Finally, read and write back from input to output
input_read_count = input_trx_state.trx_read_func2(&input_trx_state, &input_ts, (void **) input_channels, output_read_count, 0, &read_md);
output_trx_state.trx_write_func2(&output_trx_state, input_ts, (const void **) input_channels, input_read_count, 0, &write_md);
input_trx_state.trx_write_func2(&input_trx_state, input_tx_ts, (const void **) output_channels, output_read_count, 0, &write_md);
input_tx_ts += output_read_count;
}
dlclose(input_lib_handle);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment