From 1f8eb7c658a6f1359157734c1a2b57fb6d3f22fe Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 25 Jul 2023 18:43:24 +0200 Subject: [PATCH] ms: add demod test tool and data It just uses the viterbi equalizer and the sigproclib to generate and demodulate bursts and prints the bits, only useful for development. Change-Id: I852e34d9667d1f12f235f8b3da1fcc0d738b2db9 --- .checkpatch.conf | 1 + .gitignore | 1 + configure.ac | 1 + utils/Makefile.am | 2 + utils/va-test/Makefile.am | 17 + utils/va-test/burst-gen.cpp | 531 ++++++++++++++++++++++++++++++ utils/va-test/demodbits_tsc7.s8 | Bin 0 -> 148 bytes utils/va-test/nb_chunk_tsc7.cfile | Bin 0 -> 12000 bytes 8 files changed, 553 insertions(+) create mode 100644 utils/va-test/Makefile.am create mode 100644 utils/va-test/burst-gen.cpp create mode 100644 utils/va-test/demodbits_tsc7.s8 create mode 100644 utils/va-test/nb_chunk_tsc7.cfile diff --git a/.checkpatch.conf b/.checkpatch.conf index 1e4b479c..16998010 100644 --- a/.checkpatch.conf +++ b/.checkpatch.conf @@ -1,4 +1,5 @@ --exclude osmocom-bb/.* --exclude .*h --exclude Transceiver52M/grgsm_vitac/.* +--exclude utils/va-test/.* --ignore FUNCTION_WITHOUT_ARGS \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0b33e0fe..581b08f3 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,7 @@ contrib/osmo-trx.spec !contrib/osmo-trx.spec.in utils/osmo-prbs-tool +utils/va-test/osmo-burst-gen /.qtc_clangd/* /.cache/* /.vscode/* diff --git a/configure.ac b/configure.ac index 69055fd4..8aecb274 100644 --- a/configure.ac +++ b/configure.ac @@ -374,6 +374,7 @@ AC_CONFIG_FILES([\ tests/CommonLibs/Makefile \ tests/Transceiver52M/Makefile \ utils/Makefile \ + utils/va-test/Makefile \ doc/Makefile \ doc/examples/Makefile \ contrib/Makefile \ diff --git a/utils/Makefile.am b/utils/Makefile.am index bac9a7f3..1818093c 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,6 +1,8 @@ AM_CPPFLAGS = $(LIBOSMOCODING_CFLAGS) AM_CFLAGS = -Wall +DIST_SUBDIRS = va-test + EXTRA_DIST = clockdump.sh matlab noinst_PROGRAMS = osmo-prbs-tool diff --git a/utils/va-test/Makefile.am b/utils/va-test/Makefile.am new file mode 100644 index 00000000..d5a72e5e --- /dev/null +++ b/utils/va-test/Makefile.am @@ -0,0 +1,17 @@ +include $(top_srcdir)/Makefile.common + +noinst_PROGRAMS = osmo-burst-gen + +osmo_burst_gen_SOURCES = burst-gen.cpp \ + ${top_srcdir}/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp \ + ${top_srcdir}/Transceiver52M/grgsm_vitac/viterbi_detector.cc +osmo_burst_gen_LDADD = \ + ${top_srcdir}/Transceiver52M/libtransceiver_common.la \ + $(ARCH_LA) \ + $(GSM_LA) \ + $(COMMON_LA) +osmo_burst_gen_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES) \ + -I${top_srcdir}/Transceiver52M/arch/common \ + -I${top_srcdir}/Transceiver52M/device/common \ + -I${top_srcdir}/Transceiver52M + diff --git a/utils/va-test/burst-gen.cpp b/utils/va-test/burst-gen.cpp new file mode 100644 index 00000000..bdd0c4bd --- /dev/null +++ b/utils/va-test/burst-gen.cpp @@ -0,0 +1,531 @@ +/* + * (C) 2023 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Eric Wild + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +// this allows messing with the demod to check the detecton offset impact, +// not intended for actual automated tests. + +#include "sigProcLib.h" + +extern "C" { +#include "convert.h" +#include +} + +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define DO_RACH + +const int SAMPLE_SCALE_FACTOR = 1; + +template +void convert_and_scale(void *dst, void *src, unsigned int src_len, ST scale) +{ + for (unsigned int i = 0; i < src_len; i++) + reinterpret_cast(dst)[i] = static_cast((reinterpret_cast(src)[i]) * scale); +} +template +void convert_and_scale_default(void *dst, void *src, unsigned int src_len) +{ + return convert_and_scale(dst, src, src_len, SAMPLE_SCALE_FACTOR); +} + +static const unsigned int txFullScale = (float)(1 << 14) - 1; +// static const unsigned int rxFullScale = (float)(1 << 14) - 1; + +static const BitVector + gRACHBurstx("0011101001001011011111111001100110101010001111000110111101111110000111001001010110011000"); + +static const BitVector gTrainingSequencex[] = { + BitVector("00100101110000100010010111"), BitVector("00101101110111100010110111"), + BitVector("01000011101110100100001110"), BitVector("01000111101101000100011110"), + BitVector("00011010111001000001101011"), BitVector("01001110101100000100111010"), + BitVector("10100111110110001010011111"), BitVector("11101111000100101110111100"), +}; + +struct mrv { + std::vector bits; + signalVector *rvbuf; + std::unique_ptr>> convolved; + // mrv(): bits(), demod_bits() {} + CorrType ct; +}; + +static mrv genRandNormalBurstx(int tsc, int sps, int tn) +{ + mrv retstruct; + int i = 0; + BitVector bits(148); + + /* Tail bits */ + for (; i < 3; i++) + bits[i] = 0; + + /* Random bits */ + for (int j = 0; i < 60; i++, j++) + bits[i] = rand() % 2; + + /* Stealing bit */ + bits[i++] = 0; + + /* Training sequence */ + for (int n = 0; i < 87; i++, n++) + bits[i] = gTrainingSequencex[tsc][n]; + + /* Stealing bit */ + bits[i++] = 0; + + /* Random bits */ + for (; i < 145; i++) + bits[i] = rand() % 2; + + /* Tail bits */ + for (; i < 148; i++) + bits[i] = 0; + + int guard = 8 + !(tn % 4); + auto r = modulateBurst(bits, guard, sps); + + retstruct.rvbuf = r; + for (size_t i = 0; i < bits.size(); i++) + retstruct.bits.push_back(bits.bit(i) ? 1 : 0); + return retstruct; +} + +static mrv genRandAccessBurstx(int delay, int sps, int tn) +{ + mrv retstruct; + int i = 0; + BitVector bits(88 + delay); + + /* delay */ + for (; i < delay; i++) + bits[i] = 0; + + /* head and synch bits */ + for (int n = 0; i < 49 + delay; i++, n++) + bits[i] = gRACHBurstx[n]; + + /* Random bits */ + for (int j = 0; i < 85 + delay; i++, j++) + bits[i] = rand() % 2; + + for (; i < 88 + delay; i++) + bits[i] = 0; + + int guard = 68 - delay + !(tn % 4); + auto r = modulateBurst(bits, guard, sps); + + retstruct.rvbuf = r; + for (size_t i = 0; i < bits.size(); i++) + retstruct.bits.push_back(bits.bit(i) ? 1 : 0); + return retstruct; +} + +extern gr_complex d_acc_training_seq[N_ACCESS_BITS]; ///begin(); + auto n = burst->bytes(); + char *data = reinterpret_cast(start); + + const int len_in_real = burst->size() * 2; + auto cvrtbuf_tx_a = new int16_t[len_in_real]; + convert_float_short(cvrtbuf_tx_a, (float *)burst->begin(), float(txFullScale), len_in_real); + + std::ofstream fout; + fout.open(fname + ".cfile", std::ios::binary | std::ios::out); + fout.write(data, n); + fout.close(); + + fout.open(fname + ".cs16", std::ios::binary | std::ios::out); + fout.write((char *)cvrtbuf_tx_a, len_in_real * sizeof(uint16_t)); + fout.close(); + delete[] cvrtbuf_tx_a; +} + +// borrowed from a real world burst.. +static std::vector> chan_im_resp = { + { 4.1588e-05 + -0.000361925 }, { 0.000112728 + -0.000289796 }, { 0.000162952 + -0.000169028 }, + { 0.000174185 + -2.54575e-05 }, { 0.000142947 + 0.000105992 }, { 8.65919e-05 + 0.000187041 }, + { 4.15799e-05 + 0.000184346 }, { 5.30207e-05 + 7.84921e-05 }, { 0.000158877 + -0.000128058 }, + { 0.000373956 + -0.000407954 }, { 0.000680606 + -0.000712065 }, { 0.00102929 + -0.000979604 }, + { 0.00135049 + -0.00115333 }, { 0.00157434 + -0.0011948 }, { 0.00165098 + -0.00109534 }, + { 0.00156519 + -0.000878794 }, { 0.0013399 + -0.000594285 }, { 0.00102788 + -0.00030189 }, + { 0.000694684 + -5.58912e-05 }, { 0.000399328 + 0.000109463 } +}; + +// as above, downsampled to 1sps + just magnitude +static std::vector chan_im_resp_trunc = { 1., 0.20513351, 0.10020305, 0.11490235 }; + +template +auto conv(const std::vector &a, const std::vector &b) -> std::unique_ptr> +{ + int data_len = a.size(); + int conv_len = b.size(); + int conv_size = conv_len + data_len - 1; + auto retv = std::make_unique>(conv_size); + + for (int i = 0; i < data_len; ++i) { + for (int j = 0; j < conv_len; ++j) { + (*retv)[i + j] += a[i] * b[j]; + } + } + return retv; +} + +template +static auto conv(const A *a, int len, std::vector &b) +{ + std::vector aa(len); + std::copy_n(a, len, aa.begin()); + std::reverse(b.begin(), b.end()); + return conv(aa, b); +} +template +static auto conv(const A *a, int len, std::vector &b) +{ + std::vector aa(len); + std::copy_n(a, len, aa.begin()); + std::reverse(b.begin(), b.end()); + return conv(aa, b); +} + +// signalvector is owning despite claiming not to, but we can pretend, too.. +static void dummy_free(void *wData){}; +static void *dummy_alloc(size_t newSize) +{ + return 0; +}; + +template +size_t read_from_file(std::string path, std::vector &outvec) +{ + std::ifstream infile; + infile.open(path, std::ios::in | std::ios::binary); + if (infile.fail()) { + std::cout << " not found: " << path << std::endl; + exit(0); + } + infile.seekg(0, std::ios_base::end); + size_t fsize = infile.tellg(); + auto fsize_in_T = fsize / sizeof(T); + infile.seekg(0, std::ios_base::beg); + + outvec.resize(fsize_in_T); + infile.read(reinterpret_cast(&outvec[0]), fsize); + infile.close(); + std::cout << "Read " << fsize << " from " << path << std::endl; + return fsize; +} +void demod_real_burst(int num = 0) +{ + auto path = "./nb_chunk_tsc7.cfile"; + auto bitfile = "./demodbits_tsc7.s8"; + + std::vector> burstdata; + std::vector bitdata; + read_from_file(path, burstdata); + read_from_file(bitfile, bitdata); + + // print "known good" burst bits + std::cerr << "known bits:" << std::endl; + std::cerr << std::setw(5) << 0 << " - "; + for (auto i : bitdata) + std::cout << (i > 0 ? "1" : "0"); + std::cerr << std::endl; + std::cerr << "demod tests sigproclib:" << std::endl; + + auto ct = CorrType::TSC; + auto delay = 0; + auto tsc = 7; + int offset = 0; + auto cplx = reinterpret_cast(&burstdata[offset]); + auto stdcplx = reinterpret_cast *>(&burstdata[offset]); + signalVector sv(&cplx[0], 0, burstdata.size() - offset, dummy_alloc, dummy_free); + + struct estim_burst_params ebp; + auto rc = detectAnyBurst(sv, tsc, BURST_THRESH, 4, ct, 40, &ebp); + + auto rxBurst = std::unique_ptr(demodAnyBurst(sv, (CorrType)rc, 4, &ebp)); + // print osmotrx sigproclib demod result + std::cerr << std::setw(5) << int(ebp.toa) << " o "; + for (ssize_t i = 0 + delay; i < 148 + delay; i++) + std::cout << (rxBurst->bit(i) ? "1" : "0"); + std::cerr << std::endl; + + std::cerr << "demod test va:" << std::endl; + std::complex chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + char demodded_softbits[444]; + + // demod at known offset + { + auto inp = &stdcplx[29]; // known offset + auto normal_burst_startX = get_norm_chan_imp_resp(inp, &chan_imp_resp[0], &ncmax, tsc); + detect_burst_nb(inp, &chan_imp_resp[0], normal_burst_startX, demodded_softbits); + + std::cerr << std::setw(5) << normal_burst_startX << " v "; + for (size_t i = 0; i < 148; i++) + std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + std::cerr << std::endl; + } + { + std::cerr << "-- va start offset loop --" << std::endl; + std::cerr << "offset/det offset/#errors/known^demod bits" << std::endl; + for (int i = 0; i < 34; i++) { + auto inp = &stdcplx[i]; + auto conved_beg = inp; + + auto me = get_norm_chan_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, tsc); + detect_burst_nb(conved_beg, &chan_imp_resp[0], me, demodded_softbits); + auto bitdiffarr = std::make_unique(148); + for (size_t i = 0; i < 148; i++) + bitdiffarr.get()[i] = (demodded_softbits[i] < 0 ? 1 : 0) ^ (bitdata[i] > 0 ? 1 : 0); + auto ber = std::accumulate(bitdiffarr.get(), bitdiffarr.get() + 148, 0); + + std::cerr << std::setw(3) << i << ": " << std::setw(3) << me << " v " << std::setw(3) << ber + << " "; + for (size_t i = 0; i < 148; i++) + std::cerr << (bitdiffarr[i] ? "1" : "0"); + std::cerr << std::endl; + // std::cerr << std::setw(4) << i << " (" << std::setw(4) << 29 - i << "):" << std::setw(4) << org + // << " " << std::setw(4) << me << " y " << std::endl; + } + } +} + +auto gen_burst(CorrType t, int delay, int tsc) +{ + mrv rs; + if (t == CorrType::RACH) { + rs = genRandAccessBurstx(delay, 4, tsc); + + } else if (t == CorrType::TSC) { + rs = genRandNormalBurstx(tsc, 4, 0); + } else { + std::cerr << "wtf?" << std::endl; + exit(0); + } + rs.ct = t; + + signalVector *burst = rs.rvbuf; + // sv_write_helper(burst, std::to_string(num)); + // scaleVector(*burst, {1, 0}); + const int len_in_real = burst->size() * 2; + auto cvrtbuf_tx_a = std::make_unique(len_in_real); + auto cvrtbuf_rx_a = std::make_unique(len_in_real); + auto rx_cfloat = reinterpret_cast *>(&cvrtbuf_rx_a[0]); + + convert_float_short(cvrtbuf_tx_a.get(), (float *)burst->begin(), float(txFullScale), len_in_real); + convert_short_float(cvrtbuf_rx_a.get(), cvrtbuf_tx_a.get(), len_in_real); + for (int i = 0; i < len_in_real; i++) // scale properly! + cvrtbuf_rx_a[i] *= 1. / txFullScale; + auto conved = conv(rx_cfloat, burst->size(), chan_im_resp); + + std::cerr << "-- generated " << (t == CorrType::RACH ? "RACH" : "TSC") << " burst --" << std::endl; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (rs.bits[i] ? "1" : "0"); + std::cerr << std::endl; + delete burst; + rs.convolved = std::move(conved); + return rs; +} + +void demod_generated_burst(CorrType t) +{ + int tsc = 0; + int delay = 0; + auto rs = gen_burst(t, delay, tsc); + auto conved_beg = &(*rs.convolved)[0]; + + if (rs.ct == CorrType::RACH) { + std::complex chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + char demodded_softbits[444]; + int normal_burst_start = 0; + normal_burst_start = get_access_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, 0); + normal_burst_start = std::max(normal_burst_start, 0); + for (int j = 0; j < 4; j++) { + for (int start_val = 0; start_val < 16; start_val++) { + auto bitdiffarr = std::make_unique(rs.bits.size()); + detect_burst_ab(conved_beg, &chan_imp_resp[0], normal_burst_start + j, + demodded_softbits, start_val); + + for (size_t i = 0; i < rs.bits.size(); i++) + bitdiffarr.get()[i] = (demodded_softbits[i] < 0 ? 1 : 0) ^ rs.bits[i]; + auto ber = std::accumulate(bitdiffarr.get(), bitdiffarr.get() + rs.bits.size(), 0); + + std::cerr << "ber " << std::setw(4) << ber << " bo:" << std::setw(4) << j + << " vas:" << std::setw(4) << start_val << " "; + // for (size_t i = 0; i < rs.num_bits; i++) + // std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + // std::cerr << std::endl; + // std::cerr << "d " << std::setw(4) << ber << " "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (bitdiffarr.get()[i] ? "1" : "0"); + std::cerr << std::endl; + + // std::cerr << "v " << std::setw(4) << j << std::setw(4) << start_val << " "; + // for (size_t i = 0; i < rs.num_bits; i++) + // std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + // std::cerr << std::endl; + // std::cerr << "d " << std::setw(4) << ber << " "; + // for (size_t i = 0; i < rs.num_bits; i++) + // std::cerr << (ptr.get()[i] ? "1" : "0"); + // std::cerr << std::endl; + } + } + + } else { + std::complex chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + char demodded_softbits[444]; + + auto normal_burst_start = get_norm_chan_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, tsc); + detect_burst_nb(conved_beg, &chan_imp_resp[0], normal_burst_start + 0, demodded_softbits); + std::cerr << "toa " << std::setprecision(2) << normal_burst_start << std::endl; + + std::cerr << "vita "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (demodded_softbits[i] < 0 ? "1" : "0"); + std::cerr << std::endl; + std::cerr << "diff "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << ((demodded_softbits[i] < 0 ? 1 : 0) ^ rs.bits[i] ? "1" : "0"); + std::cerr << std::endl; + } + + struct estim_burst_params ebp; + char demodded_softbits[444]; + complex *rx_sigproc_cfloat = reinterpret_cast(conved_beg); + signalVector sv(rx_sigproc_cfloat, 0, rs.convolved->size(), dummy_alloc, dummy_free); + + auto rc = detectAnyBurst(sv, tsc, BURST_THRESH, 4, rs.ct, 40, &ebp); + auto rxBurst = std::unique_ptr(demodAnyBurst(sv, (CorrType)rc, 4, &ebp)); + + std::cerr << "toa " << std::setprecision(2) << ebp.toa << std::endl; + + for (ssize_t i = 0; i < delay; i++) // maybe pad rach op? + demodded_softbits[i] = 0; + for (size_t i = 0 + delay; i < rs.bits.size() + delay; i++) + demodded_softbits[i] = (rxBurst->bit(i) ? 1 : 0); + + std::cerr << "sigp "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (demodded_softbits[i] ? "1" : "0"); + std::cerr << std::endl; + + std::cerr << "diff "; + for (size_t i = 0; i < rs.bits.size(); i++) + std::cerr << (demodded_softbits[i] ^ rs.bits[i] ? "1" : "0"); + std::cerr << std::endl; +} + +void demod_test_offsets() +{ + const int tsc = 0; + const int delaybuffer_realoffset = 100; + + { + auto rs = gen_burst(CorrType::RACH, 0, tsc); + typeof(*rs.convolved) delay_buffer(rs.convolved->size() * 2); // plenty of space.. + + for (int delay = -10; delay < 60; delay++) { + std::fill(delay_buffer.begin(), delay_buffer.end(), 0); + std::copy(rs.convolved->begin(), rs.convolved->end(), + delay_buffer.begin() + delaybuffer_realoffset + delay); + + auto conved_beg = &delay_buffer[delaybuffer_realoffset]; + + std::complex chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + auto va_burst_start = get_access_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, 60); + + complex *rx_sigproc_cfloat = reinterpret_cast(conved_beg); + struct estim_burst_params ebp; + signalVector sv(rx_sigproc_cfloat, 0, rs.convolved->size(), dummy_alloc, dummy_free); + detectAnyBurst(sv, tsc, BURST_THRESH, 4, rs.ct, 60, &ebp); + std::cerr << "delay:" << std::setw(3) << std::setprecision(2) << delay; + std::cerr << " va: " << std::setw(3) << std::setprecision(2) << va_burst_start; + std::cerr << " sg: " << std::setw(3) << std::setprecision(2) << ebp.toa; + std::cerr << " d: " << std::setw(3) << std::setprecision(2) << (ebp.toa * 4) - va_burst_start; + std::cerr << " ! " << float(va_burst_start + 13) / 4 << std::endl; + } + } + { + auto rs = gen_burst(CorrType::TSC, 0, tsc); + typeof(*rs.convolved) delay_buffer(rs.convolved->size() * 2); // plenty of space.. + + for (int delay = -10; delay < 10; delay++) { + std::fill(delay_buffer.begin(), delay_buffer.end(), 0); + std::copy(rs.convolved->begin(), rs.convolved->end(), + delay_buffer.begin() + delaybuffer_realoffset + delay); + + auto conved_beg = &delay_buffer[delaybuffer_realoffset]; + + std::complex chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR]; + float ncmax; + auto va_burst_start = get_norm_chan_imp_resp(conved_beg, &chan_imp_resp[0], &ncmax, tsc); + + complex *rx_sigproc_cfloat = reinterpret_cast(conved_beg); + struct estim_burst_params ebp; + signalVector sv(rx_sigproc_cfloat, 0, rs.convolved->size(), dummy_alloc, dummy_free); + detectAnyBurst(sv, tsc, BURST_THRESH, 4, rs.ct, 60, &ebp); + std::cerr << "delay:" << std::setw(3) << std::setprecision(2) << delay; + std::cerr << " va: " << std::setw(3) << std::setprecision(2) << va_burst_start; + std::cerr << " sg: " << std::setw(3) << std::setprecision(2) << ebp.toa; + std::cerr << " d: " << std::setw(3) << std::setprecision(2) << (ebp.toa * 4) - va_burst_start; + std::cerr << " ! " << float(va_burst_start + 19) / 4 << std::endl; + } + } +} + +int main() +{ + convolve_init(); + convert_init(); + sigProcLibSetup(); + initvita(); + + for (int i = 0; i < 1; i++) { + demod_real_burst(i); + demod_generated_burst(CorrType::RACH); + demod_generated_burst(CorrType::TSC); + demod_test_offsets(); + } +} diff --git a/utils/va-test/demodbits_tsc7.s8 b/utils/va-test/demodbits_tsc7.s8 new file mode 100644 index 0000000000000000000000000000000000000000..c91cd6c5c4201d7b16305c78d1b16fe88f60da89 GIT binary patch literal 148 zcmYjK0TKW(2;u*qUMRO}T{HqF2y&kK4g*x;l-fEBB?-H{;rFjPb7vlHUF+%7IcH}) D7!LqX literal 0 HcmV?d00001 diff --git a/utils/va-test/nb_chunk_tsc7.cfile b/utils/va-test/nb_chunk_tsc7.cfile new file mode 100644 index 0000000000000000000000000000000000000000..67e577e99bd03cb302cd2300c9b2127595667e87 GIT binary patch literal 12000 zcmWNXhd)+t7{=|9y=V58gz%pGQK3X>Ck+}}DxvzdQz>a0$tWaAk`XHMp8KH)p(2Vz zX-HO*C|U7)|A6y3pYwd4bKlo>eXkm+7~C?x1!gbk#hV*{FyCe6X{QT^5op$=i|H8- z_og~kn|6kC&Om`i)lrUHj5Mv9k;0L0m!nD*9Q$*dG-<;`95*4|n65MY!=1jujNUDL z%oUueNwr*b3*CPF#*~am&PMrYJnDU&^P>DFdlkPG&RhD7aV^`x7Cm1Go)79-@9@>I z(3203rl`Xh-#Zo)4l+-VSh1@r_Hqxz7&Fa_^x56xy^L_k@516sn(#3A1am1v7E0HN zK$k%=Q#8W}92r^0{lXMbJ|k}b`jjtoF?v4d&{-RHo9I#I=amWeZO14>&ZuJlMguUd zt!1mLmEq=D7f!NKGLxHU1Y734;|e`a0j1Y`c)s-u91H>s%n>GDku&i>X&F+kHOS8W zCPO~A*s+&>OOWz&Qud89B4qu4^4u8-6VR8F!lqs6gR+2`n5f$Vd(=L;+*~g5#jNnVB9M=C;H)>i3qwCB99Q9zaeEkaaifh5Kh`ns<*B`i~c#QM7c@%@1 z^EhAa`KY~AH7ghR8}|kzpucQ2ZaFPVPrvoUh4!|TS$4*5_p$kOfx$T#6`DzhYxzhX z@>Bh-X5{bE1GxJ!hqMR2=G_0!f~2Nzfx+$agpA&Ry=gsA`05H=KT`%i&i3%YnhQ1t zBb-&%C2(c!Z?<()CHO@hN2l2=@XO_+#^W%^IQ|8rZYe?JdSUvvwv3asS()}m39}9(RE1q=tANGMM*}22FXh{ zAYDCaFh@;?w6xwTl$bFF9Eo_`IS>Uqj!dGyLljdws6^@6Qr0e9k^VhzgPT{2(sOAh zcoY8MdbvAn#+vUqIbz9#UhKzKU2FKe_%BWyxB|;Q^a`VB};CoY3pW zPSprFGPfOJ%|B*m>jTv2_F!ZC7UH_TL%6-pj*X(NnAN|98JeO_54Q(1qR;HsW^E(AOpk8Cg1=Kf!S~B;CaJK0N;!7 zo?nav3cg^Pk86{zH!18B4Kw0B#~-yen35Ck)A6j6F44G}hv8jH#6~p??ca%$Hp##2 zG>b796E9|Lgug&|ZwAPHF9#bl8FHIH6Fks?{IR$SfwMfx25t)Rz%xA4!(J)5evC5Fdp9s72(2!Puc+{gT+bd#XW44^B8P4zJ%g? zs^M+c2i#Z@3bA`d=^c$8MzKYn&Ty;YT3=VB-DjtuYq=~9GG2s1RpNB&yj6Hmh>xbG z8)0{6JLV?FvPSDl@U@@~WB)7~6)&5E-54Xo{d${uNJ z0{LJ)oLp52vzLaVg3E0v5-q_@`|WVQegK)Q9){Hsr?F#0_WnbX^q^l7+np~$^J4$9 zief`J?A67pcz(ox)*ILq#TqQ@pUG&~l;ZGBT`+o($L|?oB_2b0JN11vQc-H`5PE?}U zr_E5Ae;w~X4=KFi1bE@*Mhvf7#fC*!VxlxK$qM|mBJma@yjzymKNe&*JyxVk=a#a6 zj>*!&=5U-fBaE?iGbhsH&tUxqO>)e@fUGrdg!JRCJv_2Tr z)u*-E`{7LN40=#Nh1uLv7Dv+ArQZQG-YFC>2;mH5r}7dPQl_{-g<{T?}9h0NHe z4$N*`3%fRcM&0SD@H-$EJ8G-JL|F;H7Jh(h{=%?VqZtk~H-n2pFyLSF#W81#K`Foe}@TpQb*H?y5WX{08 zs~>Sk_8rE|y9qDLjI+bWIe1wm34_EI;dk~e9`l#y@;`fzQLDW`&FLQIbhX2O+~7pJ34C$B3vF&{ zOxM~kkb2OG4Y(yjYLnvGfe>Y4ICCMp{D?03BsY!YDP%&Vl@pkayl;w<>te#>^@)4> zOXgjX0tu;q!cjFJ0?xaytYuXpj2TAZ-9v$}XhkmuEENY+RZXf;mCNWYx2D#8ZBZLTu+@72C44?Z+uqAK@>GJn|Ch(UA5|v`syCR`!kQ#=AHb{}Ibv71 z5te8PkPN#8@G8FxtZU>UVZ(bktW(CEzVrzuSL8A0SN6m3LJ0_3!cV%VABFfRA@Z>3 z88nOy!;=3*$-$p5Ay-I;EDbpe2_Fnd#`cGdiL3(eolUHo=m&_DyoT1Zk3c^BLenpM zn8^D}$U(1}isILcLtHKcpDRxn*xMlkEs zYPgwq4KrWf2I=b^?4Gd}I8`vhVa-HH_O=Qpa+4ZqoF2+t7}q5?hlAMUCF7P0*T{K^M|2=Cz|IC3cE<{O2}0WSEM#vo_KoPBjY1x>3tz5Abr35!KXl zN9#EP^l-vrPRWiEOxv*y9;^vLk-<{X|4#vBRNKHM^bPmk>3UeA@PQfFa|5>7hro6( zC)oC*9um1FjCYeH*&^w~L|L1VwffhXyfk}K@_9#Q!@@Ej2Dn-vVw=xrYhIEOQ zJ@#+Yr~J*$cxXVBF1(;h&!&+%*8IMnql zL6>7<FN@ zLUd#BFo@kci+?K3iRQLL%%jK7CZf}Av^+1ikyg+{RZ~& z$*BZFOYxpf6}Y1={pYU?5-Ia(px#dQ+s(!FHgYh=Z5C}*@WQ#Zx^zW`9sUXtqs7hN zSr6?Y?EQI}UAAKwCpV?B74D)m=eQnZCMLh-g{5kS?ESc=>1@i9KEQ=s}$av40+mbEK?@?_*KA|6)71Uz$ee zLp}H*$kCD-1ucaD#f|r zm7x3hthbb{J3556Yd5n2)0ODT&T!V^kO5uufDcP|o6xXXYf)ZBm)@On3nP=IsjXcz z3Lb02n*)M$np-q#*~wC0w_3LJw>X{h;0-f>41Gxk-MxL4N$ zH&&6%|7A&J&Q3yTf)_bC?=C34-$cf$i64iY*Hf2)}M!awmtCpNFp@Zork5j z(!g<#Ka=*A=bhAr@aV)f@M*k+U$z|rr*9N@-ctv|$$C83FUdTQtHC)Bi&??gY)o?X zM8?DmZ@ON^CuKTpjZZcPJu-&hYtvD;xBwoRT)<@a5wM?bj`5zt#D9e(>$2=COt1RO zyl9L7wcXL6I+4bJd>4d;-ed=NsFAP}61a8lOmf2iFuUZ>Z1T!b0z~H8629!0pf{jI zgm)Q}qO+BdBfgTn7*&MX&g;px*l+CdC-cb9&ij}fAWuxTi&014EGQzzH0II}6KG{i zM;BCZHBx8N+j_Uyw<@MIvD}kwpHQL(JrkT-t#J&ElY@O@&#>o12n?=_!tyx?C#N}M zbW;~tN&jZ$(?rMt{%lsKLyr8s|A;+%S%J(>6UGHW;zTvv73J(Yp}*}MYW~ZB&ysiX zcy24j{ZP|_F$p4IBa z==x%ixUNEoU>qa!xfkxtN@lMVhX6-$J${-$#OZa2$53HQoVaxrpSs?{bLfs=Woyx) z^Dj3s^D{0DGlF)THmpic0~xI*Y}crR*AI%Z>UkA}C|t%E**I`nqky7j%FrLE#vFWT z_ed*vKZJ33Xa8RlM99v-riW8Vc)l|pEs`hKF3iJY0)iyKeL3>SltI<8!x(UG2OJ1a z#1n%>%!F1k{{1v+&)Lw30qGC8vHl;hpz zn%&tTX4JsVt+@^>oa60HtTw=mH^N+r{su;Eas{jMtI2-g!fSRN;yYWs7ADM4GgxhC!gVu-FcyeYlOjirVd{PUF?K@fH(Wf9;rv;J8 z`7nR}J$UYx26nkW;n%)I;PVwH&a-d8?>SOr`oWg>@k=X&;{4hy1??r zFOV^7g-x;V!K3*DOg)nVR%bgwja2~CvSC={wT?YCRfwEg{vUomAxy%qJi+<{L%`4T zM8^Zl!C0#uSM}|Nr7x;b{uRT#?}*0~D;d00OHdK7pzt?_H8&{2@s3XB;pY-GejN?1 z&6&8ovJZZTgyTGKEh1eQgs$IhiMU}H`tP(Os%yAdT%$?Gorf^(a5H=nSEc4@tdtgDct!ISr~`e-j660XF$qmS`cW;y1s$wBd+{=<)#ea z?rY6>a8QnBw~k};q$b^xDMQ)&GIX)48kMtqg{1;2bip%Ad~rmazIIAye0G1w=jO4% z9JA{iim1BHdAC{J%zys&% z(C}G0JLa5|P27{gVfN4z=UU6Cg*_);5 zhTE<%u*4TVmS+WQR^ zt$f%L+a8>KCK+pkV(5|y4^hjsZ_r2Z$uLKoorilm4(9@>dl=eX2LQPtdbPWocMQNql6Oc=JhC5e$ zf+>c}amm_2km}RmK9%_gs=LjgB9))uy?79?7a`jtN`X&Ail`lX0SlifkhRAsRJbXV z!D$JwVVWFqIK3VI>k}k4bBsW`{wpZ`76E;er;xxW3-1$hz-0yp8ai^|_S)@mJ?06> zZaNGxmb_fdYbpFY{{_TXvCP@j7MOlCla=jx0vFarAxAh7LX&!NfAJxZvXZ9{FK-5k z3rf^2?Gz;5r=clnt}CF@i@5F4t=j3 zM|JCS+~)4}Xyq#mHb3U0YTGGDerSW1iTRMU*Bt*wH-q4}S?KiqJ6PZmo<{x(A+34H zr^|)GC4*R8>;WIQs8h!eKkYp;t!VCzC3x{Ihc-19q3`bLRQS?2l>e?w>r5L_Lv;vS zRz~8Lg;n_TSt9G0kcW;bGH`B7F8VyW3CtAUEK#Wg-(tiYA76oC;4REpnhsXm7USb- zi(t9VLoVaGi}6dC14qxqvrdPfg5a{*7!)f&HrIxsX{Q7+zmtc*Rt^C=$3Vdbry`p<)1=PlV1V5FO;Lw0$Zl!)F<2_djRf4yu$|nT9`3bh`t{D z1Xf){177z1&5NLn8y^uX8)4T^{S2K~>sfKRGPqsIhn)-;?nT(4oP9Z5$PU2flutnU z&Y<4F2n70U#~WgNWWk9sHuBR~NSe@K3TjedvDH2*HVxa9ft3=S#S$@bH+0THWrGKSL$hSE=-U-7v;iR{t=jHcmobgx}dYY2R5y0 z1Y7f7m>TjJ=9^W6sqHP;@%Ru3WCz3V`RSaP5&!}DeYp0-re9D8-=wCw8)~&%iLjJM)D=^064oWB;L>i_XdDe zL}`&7_0mLrGeh3}jsxXAuB7Z1!`-^dozxw@hHGZIl07kebW5ZIX+5Gy$Cgebr@V!z zO{oeQn45)j2l>dNgu85BTq8Umvw_27dGOh=3^;q^VQ=IFNZpHqCAWo0+KX$Dxb7z; z?aYM0t_t7}d;-^sZ^0UuS77NG1G_l&Fuo}X1a23@5$6J!u{IKR8rQ&wesTEf(FAAh z{n+fh8mM*-N4b)G(D*fi`*|~5@sKg47sKGavID(SbPa+^ZRlK`C-9?OlKQLvhJ!1w zq1g^OVi@eeiBVN258kE1ktzw26)I0|8&rdB6_CLM6Oc`IB``41aN1gin0Bv%hVyEqcQg)Ezw45KBM)H8 zLql@(NCvc=&?8?KZh_M)RfwWNA1BIIm>iH;hXm{|BXaJjV_@} z9*4m51bce>O&FL>s#E!`*>F9g3GIHgfaXy*eC8!gI>HT^8c`(@(|Q(CZYq#irVE5x z{y=*%&ui?BhQ;xw1W%-MJp2sFqH__LHz7vOKa-?uUu8kWF$XHOEr$8n;7)yht;N(@ zdphIIFFZIROcyDe(Vj=4XlOc*KA!#2{@httT6tm{Y#Cr^;k5!tZPKUy8!92WUXq?1 z$b~t|1Ne7o5O~e0M+Y?l7<7JsmOt*;Hx67z^N$^DExR6bIXkiYu_@lt$icf(I@r7Y z3r@1Da0-tJr#RlhJskoxHRcai?)boCR62CM${CdNwWU%~i@D;qmUL|TIT(zeLgP|} z$i)rUQU8h!IW8)~?me@BFo!+C#l@8*@fCr3(o7-}^A?nTXcDn6WgwA0g_ucShwqMp zB=R5czgsU%wp#qh5d0C*zEhy?&Cjvi*n9=hpr1DZF zE3sf0G?!jQhDiW<)z6szCxNl~%SQ*tH1VX}IC^%X$6z$ofgb&u1F5@A>HZzh;cL4T{k5tZDz|;au^;Ks zKld&kJg^K7m4spwkI@`ibrdVR6mg$<81Blvi39uZV!^4esQax9%hrleKJC}|Gf0}I zEU!WRSyD82vJf>oMCi;JiFmVM0?cSiw^F>SEld@66kx|re){`Q1`3Pyp<2gP zJj?T`d$*lHoo$&o!9O3}Cc@EHSP93=L(sKuoUO9Fg75m}P|}Hu%Wkd2>+l0x1rqVX zDLJYjUW*0chV+Q(FT7G?K`qV>;mSFtG;(VTl7H&-bXFS1zvFR?Fi+g!IDqBf`H|Lr zMuR)eY~q5?=oF)g7HfW>u;>xou!xVIIhKhvgJRVF`xEp}lcIN4XJe_h6g}Ry4n<#z zQug2&_q@pjKFPL#7gM@X{aP-MrM<=n^gEJOx#%6?5EE1!j$ zr>2l7%A!pDZ}?FE61xw4flWrAu&=ZgFrx$gcYOoHnN1kB^CxU~O~=E(f5G-vGxQYd zfDAW%X3LE#$b5PVuE`~Ufod~Y3UlD3vjADyIl<`;9tEL%S)4Qe6e^G1#lt?kVP~Wu zEt%24L?1V!8#ntg)#-Dna?L1HmTYmn0=MpP{Gv50m-i$yt}lYS4& zRWk5~_7CuVatK={#mO1(>A0$ADxsPh$j3DyF-op@{seFSoR7roLrP?J(PR9o&QI*J zKj6^kkMK&X1+6uCU51GJXk_;ie!DHj?lrGqj&?YAjei;Fc-X?^vTHDw@&F#4l81*^ ze?k1%G1i_VN~{7d;p}Sy#7g-y2J`mG^E@GH{`L~ge91@i(^#gq>&ZY?%&ymZr&TPpKk&+I#V&XbrK_0zF_;634Ep`N}Yc3(ahTt^wL9N zx=(Tt&!|aIua&n^^_?V*DgDIyF{1QB(=&{ugIfV{7G)ZGVzC5W*^DjL@{gukp zV&F6OI}20Q1D|knQXj5eR*YYkbfT4I6#9t`<1WeFs6I`C*1DZSh4acZw3EfBcJlN` zk2t-f-it?PFm(3BX|6akE z79X`f-Udx^GIZvuDrmLlF(&83uwqU*24>yj7`5-k+IhZs)95pM-S;CVOx)*^)zVbO zO^UJbk)vxqWiclmhw#aCO?dV_3uW?xp;y=m_be`g%cPj~KJpU|wxqHD{o^OEN_6qx z(@tnFyNZb_u`ufJ4J9|vWcD4BrWxS}@Gw__YMD-;rOF6e9yO!mDzSJ9ZRw)UD(R}K^8!v1#I8mj%lA8AX=vy#ST}2 zme^ff*_Q^Ne}|yw9bZ^vG7E#G{xEhy?QDQ|6UTbD8SAO2$ENQ};T$nfWaH~Y89pD% ze&6zl@yL3`T4xk6XAl2k7eBqkB(7A%s3)q7cDW7yJ}SWZy37qd42`+&&dw;`?#o?# zQ5B_7j=SPoBD;l~To~hdh?5fK!WFW4!&sGxvr#Q(5Kd39PmSk+we}qrGiN|DTxQqo z?O~i2g>nO;+BpCI++m`klUTjYD`EDrxmeC49o>94(68Yw4CgiD>5eW)iV>rx-mUO( zyEfGqD~9=Qh1 zH^V(K<1q8Q6#LOim?&+|U>5ZWlcvo8I}ZyJ{hepvhom?e%}apv_wr;@|5eyHqD`un z?0}=`CdB(*9>d3Dm8*I?*m>tfiLgR8PMLZaL>7qAQ>wnq&ZCC(?Tr2SWr{u> z!7==vY)&UP?ZblIgl?IPWhyIX(9IJR4oWD|#d1nydr1!p3Rx26c8X)c(}@3zEUau( zCUOrEE!GZ0bj^F5qw)rB-X2AVj+bC!!B3Ajv_s>9c3d(lOp1iB}wIyL$<{se*HU$SpI}-YlTQzVk2xfQ6g>+Z^M;# zU2-9D9o)RC&(qkvu9}Y$8OXlM)W-J0lLuEAEr^E1@Gs2vs2paokTv92^su(EN1=La z6mH~YyYqI`V9+iWP6T)2*V;NryZ0UkEoD&3<Y z!-oVV^3g_?>;*o;ImhGP%hKVs^a>Jq?;`W9VJ=}y5972k1){q}l140xg^l`dG}1?v zJs!E4-gnBu^t_c+uvnU!Z<|V&xEa&Pf;hC{873eXs#QYi4v$K4vrB;XM`G|tUAtn_!TUB{gKQ(3c@?{QNCdgW4N^s8=QWy`Kv_f;okwgy(38D zG;ZSMV|BRSwFqs}cVWb%I(#cUllyV-JyupNgMU$P@z;aL@K&M_U#9kgIq$ic_dW3H z+zNKjKVI)q%LGh~eLzX61X@Df8Lcx@csckh_J*t;+1I@kFMl*3qk%_o;cOKmcEBH} zf9EGpqg*i3qZLGbb+J*f8aA&|$7ge&gG(xdY}Gr^Yde5>KJ73ea~-XIzlVS89^%4^ zeDJQ};>xQVpvm+eE)8;E1o;y1rrxZY=h6+{A;11sJ#N2JW=z!V$v| ztotlOGnYHzPF+Jf+e;QREiCB0DdHISpAjv;I1Md$ebPClJ8-6v01Y3yjLM3=s92MX z=SO+nPKoQN`&oc~IeZZV92IFrdH{a^tWC$`eDKFs4cep{jNg>`Y0dWAs9kp(ne=)L z5Pi(9cl^y`;$onsJB)eUB&f=&!(QnZP#zJ4W`8Te?${7_p!hoY@VUZGW+pHhPhfVP zB4fXzAKr)Nus1q-;dI4JeAk9x+;R|ua#q2-OR;#uM}|p1k%#>Wzu6J{dd!gxL|xNi zJoO_H<8RB-hv9j6zeA74o_mZr29|V{b`92AThsk%AJOHrDIHqVkF1pvJybl7f3WaoyIe#&yzlxo`qz4Tilrz?IKB0Tq1qeL<5l5S!4WZCy4Qa%*c?@)WvBMS>Kq|jFH7=Uo}1!%G%kf77Pts;08nmQSM(uO7!u>rAQn?=~#Ul%rW3C2B;U z<2|0Ajw&|AbaS4UFucR;_&ScCzg>fQ#~;C`%N- qK%m4ewgetSWSJ0dmdu9SO-?AT@dy^I-_4tA@4^4mK@>VFLjDH|sq|C; literal 0 HcmV?d00001