mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
synced 2025-11-03 05:33:16 +00:00
wip
Change-Id: Ie8fdf358df07f3944cb223584581514d6c229de7
This commit is contained in:
@@ -871,7 +871,7 @@ int Transceiver::ctrl_sock_handle_rx(int chan)
|
||||
LOGCHAN(chan, DTRXCTRL, INFO) << "command is '" << command << "'";
|
||||
|
||||
if (match_cmd(command, "POWEROFF", NULL)) {
|
||||
stop();
|
||||
// stop();
|
||||
sprintf(response,"RSP POWEROFF 0");
|
||||
} else if (match_cmd(command, "POWERON", NULL)) {
|
||||
if (!start()) {
|
||||
|
||||
@@ -114,7 +114,9 @@ class trxmsif {
|
||||
dl.ts.store(write_ts);
|
||||
dl.len_written.store(howmany);
|
||||
}
|
||||
shm::mtx_log::print_guard() << std::endl << "####w+ " << write_ts << " " << howmany << std::endl << std::endl;
|
||||
shm::mtx_log::print_guard() << std::endl
|
||||
<< "####w+ " << write_ts << " " << howmany << std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void signal_read_start()
|
||||
@@ -155,13 +157,13 @@ class trxmsif {
|
||||
|
||||
// data left from prev read
|
||||
if (left_to_read >= howmany) {
|
||||
memcpy(outbuf, buf, samp2byte(howmany));
|
||||
memcpy(outbuf, &buf[dl_readoffset], samp2byte(howmany));
|
||||
dl_readoffset += howmany;
|
||||
|
||||
shm::mtx_log::print_guard() << "\tr++ " << *read_ts << " " << howmany << std::endl;
|
||||
return;
|
||||
} else {
|
||||
memcpy(outbuf, buf, samp2byte(left_to_read));
|
||||
memcpy(outbuf, &buf[dl_readoffset], samp2byte(left_to_read));
|
||||
dl_readoffset = 0;
|
||||
auto still_left_to_read = howmany - left_to_read;
|
||||
{
|
||||
@@ -170,11 +172,12 @@ class trxmsif {
|
||||
dl.r.wait_and_reset(1);
|
||||
assert(*read_ts != dl.ts.load());
|
||||
len_avail = dl.len_written.load();
|
||||
dl_readoffset += still_left_to_read;
|
||||
assert(len_avail >= still_left_to_read);
|
||||
memcpy(outbuf + left_to_read, buf, samp2byte(still_left_to_read));
|
||||
shm::mtx_log::print_guard() << "\tr+++2 " << *read_ts << " " << howmany << " "
|
||||
<< still_left_to_read << " new @" << dl.ts.load() << std::endl;
|
||||
memcpy(&outbuf[left_to_read], buf, samp2byte(still_left_to_read));
|
||||
dl_readoffset += still_left_to_read;
|
||||
shm::mtx_log::print_guard()
|
||||
<< "\tr+++2 " << *read_ts << " " << howmany << " " << still_left_to_read
|
||||
<< " new @" << dl.ts.load() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#endif
|
||||
#include <complex>
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
@@ -43,8 +42,8 @@ gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a S
|
||||
gr_complex d_norm_training_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS]; ///<encoded training sequences of a normal and dummy burst
|
||||
const int d_chan_imp_length = CHAN_IMP_RESP_LENGTH;
|
||||
|
||||
void initvita() {
|
||||
|
||||
void initvita()
|
||||
{
|
||||
/**
|
||||
* Prepare SCH sequence bits
|
||||
*
|
||||
@@ -52,8 +51,7 @@ void initvita() {
|
||||
* Burst and two guard periods
|
||||
* (one guard period is an arbitrary overlap)
|
||||
*/
|
||||
gmsk_mapper(SYNC_BITS, N_SYNC_BITS,
|
||||
d_sch_training_seq, gr_complex(0.0, -1.0));
|
||||
gmsk_mapper(SYNC_BITS, N_SYNC_BITS, d_sch_training_seq, gr_complex(0.0, -1.0));
|
||||
for (auto &i : d_sch_training_seq)
|
||||
i = conj(i);
|
||||
|
||||
@@ -63,21 +61,15 @@ void initvita() {
|
||||
* If first bit of the sequence is 0
|
||||
* => first symbol is 1, else -1
|
||||
*/
|
||||
gr_complex startpoint = train_seq[i][0] == 0 ?
|
||||
gr_complex(1.0, 0.0) : gr_complex(-1.0, 0.0);
|
||||
gmsk_mapper(train_seq[i], N_TRAIN_BITS,
|
||||
d_norm_training_seq[i], startpoint);
|
||||
gr_complex startpoint = train_seq[i][0] == 0 ? gr_complex(1.0, 0.0) : gr_complex(-1.0, 0.0);
|
||||
gmsk_mapper(train_seq[i], N_TRAIN_BITS, d_norm_training_seq[i], startpoint);
|
||||
for (auto &i : d_norm_training_seq[i])
|
||||
i = conj(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MULTI_VER_TARGET_ATTR
|
||||
void
|
||||
detect_burst(const gr_complex* input,
|
||||
gr_complex* chan_imp_resp, int burst_start,
|
||||
unsigned char* output_binary)
|
||||
void detect_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, unsigned char *output_binary)
|
||||
{
|
||||
std::vector<gr_complex> rhh_temp(CHAN_IMP_RESP_LENGTH * d_OSR);
|
||||
unsigned int stop_states[2] = { 4, 12 };
|
||||
@@ -90,31 +82,27 @@ detect_burst(const gr_complex* input,
|
||||
for (int ii = 0; ii < d_chan_imp_length; ii++)
|
||||
rhh[ii] = conj(rhh_temp[ii * d_OSR]);
|
||||
|
||||
mafi(&input[burst_start], BURST_SIZE, chan_imp_resp,
|
||||
d_chan_imp_length * d_OSR, filtered_burst);
|
||||
mafi(&input[burst_start], BURST_SIZE, chan_imp_resp, d_chan_imp_length * d_OSR, filtered_burst);
|
||||
|
||||
viterbi_detector(filtered_burst, BURST_SIZE, rhh,
|
||||
start_state, stop_states, 2, output);
|
||||
viterbi_detector(filtered_burst, BURST_SIZE, rhh, start_state, stop_states, 2, output);
|
||||
|
||||
for (int i = 0; i < BURST_SIZE; i++)
|
||||
output_binary[i] = output[i] > 0;
|
||||
}
|
||||
|
||||
int process_vita_burst(gr_complex* input, int tsc, unsigned char* output_binary) {
|
||||
int process_vita_burst(gr_complex *input, int tsc, unsigned char *output_binary)
|
||||
{
|
||||
gr_complex channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
|
||||
int normal_burst_start, dummy_burst_start;
|
||||
float dummy_corr_max, normal_corr_max;
|
||||
|
||||
dummy_burst_start = get_norm_chan_imp_resp(input,
|
||||
&channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
|
||||
normal_burst_start = get_norm_chan_imp_resp(input,
|
||||
&channel_imp_resp[0], &normal_corr_max, tsc);
|
||||
dummy_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
|
||||
normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, tsc);
|
||||
|
||||
if (normal_corr_max > dummy_corr_max) {
|
||||
/* Perform MLSE detection */
|
||||
detect_burst(input, &channel_imp_resp[0],
|
||||
normal_burst_start, output_binary);
|
||||
|
||||
detect_burst(input, &channel_imp_resp[0], normal_burst_start, output_binary);
|
||||
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
@@ -124,22 +112,20 @@ int process_vita_burst(gr_complex* input, int tsc, unsigned char* output_binary)
|
||||
}
|
||||
}
|
||||
|
||||
int process_vita_sc_burst(gr_complex* input, int tsc, unsigned char* output_binary, int* offset) {
|
||||
int process_vita_sc_burst(gr_complex *input, int tsc, unsigned char *output_binary, int *offset)
|
||||
{
|
||||
gr_complex channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
|
||||
|
||||
/* Get channel impulse response */
|
||||
int d_c0_burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]);
|
||||
// *offset = d_c0_burst_start;
|
||||
/* Perform MLSE detection */
|
||||
detect_burst(input, &channel_imp_resp[0],
|
||||
d_c0_burst_start, output_binary);
|
||||
detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gmsk_mapper(const unsigned char* input,
|
||||
int nitems, gr_complex* gmsk_output, gr_complex start_point)
|
||||
void gmsk_mapper(const unsigned char *input, int nitems, gr_complex *gmsk_output, gr_complex start_point)
|
||||
{
|
||||
gr_complex j = gr_complex(0.0, 1.0);
|
||||
gmsk_output[0] = start_point;
|
||||
@@ -156,16 +142,13 @@ gmsk_mapper(const unsigned char* input,
|
||||
encoded_symbol = current_symbol * previous_symbol;
|
||||
|
||||
/* And do GMSK mapping */
|
||||
gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0)
|
||||
* gmsk_output[i - 1];
|
||||
gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0) * gmsk_output[i - 1];
|
||||
|
||||
previous_symbol = current_symbol;
|
||||
}
|
||||
}
|
||||
|
||||
gr_complex
|
||||
correlate_sequence(const gr_complex* sequence,
|
||||
int length, const gr_complex* input)
|
||||
gr_complex correlate_sequence(const gr_complex *sequence, int length, const gr_complex *input)
|
||||
{
|
||||
gr_complex result(0.0, 0.0);
|
||||
|
||||
@@ -176,9 +159,7 @@ correlate_sequence(const gr_complex* sequence,
|
||||
}
|
||||
|
||||
/* Computes autocorrelation for positive arguments */
|
||||
inline void
|
||||
autocorrelation(const gr_complex* input,
|
||||
gr_complex* out, int nitems)
|
||||
inline void autocorrelation(const gr_complex *input, gr_complex *out, int nitems)
|
||||
{
|
||||
for (int k = nitems - 1; k >= 0; k--) {
|
||||
out[k] = gr_complex(0, 0);
|
||||
@@ -187,9 +168,7 @@ autocorrelation(const gr_complex* input,
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
mafi(const gr_complex* input, int nitems,
|
||||
gr_complex* filter, int filter_length, gr_complex* output)
|
||||
inline void mafi(const gr_complex *input, int nitems, gr_complex *filter, int filter_length, gr_complex *output)
|
||||
{
|
||||
for (int n = 0; n < nitems; n++) {
|
||||
int a = n * d_OSR;
|
||||
@@ -221,10 +200,12 @@ int get_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, int se
|
||||
|
||||
/* Compute window energies */
|
||||
auto window_energy_start_offset = strongest_corr_nr - 6 * d_OSR;
|
||||
window_energy_start_offset = window_energy_start_offset < 0 ? 0 : window_energy_start_offset; //can end up out of range..
|
||||
window_energy_start_offset =
|
||||
window_energy_start_offset < 0 ? 0 : window_energy_start_offset; //can end up out of range..
|
||||
auto window_energy_end_offset = strongest_corr_nr + 6 * d_OSR + d_chan_imp_length * d_OSR;
|
||||
auto iter = power_buffer.begin() + window_energy_start_offset;
|
||||
auto iter_end = power_buffer.begin() + window_energy_end_offset;
|
||||
iter_end = iter_end < power_buffer.end() ? iter_end : power_buffer.end(); //can end up out of range..
|
||||
while (iter != iter_end) {
|
||||
std::vector<float>::iterator iter_ii = iter;
|
||||
bool loop_end = false;
|
||||
@@ -321,12 +302,12 @@ int get_sch_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp)
|
||||
|
||||
int get_sch_buffer_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, unsigned int len, float *corr_max)
|
||||
{
|
||||
const auto tseqlen = N_SYNC_BITS - (2 * TRAIN_BEGINNING);
|
||||
const int search_center = SYNC_POS + TRAIN_BEGINNING;
|
||||
const int search_start_pos = 0;
|
||||
// FIXME: proper end offset
|
||||
const int search_stop_pos = len - (N_SYNC_BITS*8);
|
||||
auto tseq = &d_sch_training_seq[TRAIN_BEGINNING];
|
||||
const int search_stop_pos = len - (N_SYNC_BITS * 8);
|
||||
const auto tseq = &d_sch_training_seq[TRAIN_BEGINNING];
|
||||
const auto tseqlen = N_SYNC_BITS - (2 * TRAIN_BEGINNING);
|
||||
|
||||
return get_chan_imp_resp(input, chan_imp_resp, search_center, search_start_pos, search_stop_pos, tseq, tseqlen,
|
||||
corr_max);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <complex>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
@@ -145,6 +146,7 @@ template <typename T> struct ipc_hw {
|
||||
{
|
||||
void *ret;
|
||||
static int to_skip = 0;
|
||||
static uint64_t last_ts;
|
||||
|
||||
blade_sample_type pbuf[508 * 2];
|
||||
|
||||
@@ -185,7 +187,9 @@ template <typename T> struct ipc_hw {
|
||||
if (to_skip < 120) // prevents weird overflows on startup
|
||||
to_skip++;
|
||||
else {
|
||||
assert(last_ts != rcd.get_first_ts());
|
||||
burst_handler(&rcd);
|
||||
last_ts = rcd.get_first_ts();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -173,6 +173,7 @@ __attribute__((xray_always_instrument)) __attribute__((noinline)) void rcv_burst
|
||||
unsigned int fnbm = 0;
|
||||
signalVector burst(ONE_TS_BURST_LEN, 100, 100);
|
||||
|
||||
#if 0
|
||||
cpu_set_t cpuset;
|
||||
|
||||
CPU_ZERO(&cpuset);
|
||||
@@ -192,7 +193,7 @@ __attribute__((xray_always_instrument)) __attribute__((noinline)) void rcv_burst
|
||||
std::cerr << "scheduler: errreur! " << std::strerror(errno);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
while (1) {
|
||||
one_burst e;
|
||||
while (!q->spsc_pop(&e)) {
|
||||
|
||||
@@ -44,13 +44,13 @@ extern "C" {
|
||||
#define DBGLG(...) std::cerr
|
||||
#endif
|
||||
|
||||
#if !defined(SYNCTHINGONLY) || !defined(NODAMNLOG)
|
||||
#if !defined(SYNCTHINGONLY) //|| !defined(NODAMNLOG)
|
||||
#define DBGLG2(...) ms_trx::dummy_log()
|
||||
#else
|
||||
#define DBGLG2(...) std::cerr
|
||||
#endif
|
||||
|
||||
#define PRINT_Q_OVERFLOW
|
||||
// #define PRINT_Q_OVERFLOW
|
||||
__attribute__((xray_always_instrument)) __attribute__((noinline)) bool ms_trx::decode_sch(float *bits,
|
||||
bool update_global_clock)
|
||||
{
|
||||
@@ -145,6 +145,8 @@ bool ms_trx::handle_sch_or_nb(bool get_first_sch)
|
||||
#ifdef PRINT_Q_OVERFLOW
|
||||
if (!pushok)
|
||||
std::cout << "F" << std::endl;
|
||||
else
|
||||
std::cout << "+" << std::endl;;
|
||||
#endif
|
||||
if (do_auto_gain)
|
||||
maybe_update_gain(brst);
|
||||
@@ -180,7 +182,10 @@ bool ms_trx::handle_sch(bool is_first_sch_acq)
|
||||
|
||||
auto start = is_first_sch_acq ? get_sch_buffer_chan_imp_resp(ss, &channel_imp_resp[0], buf_len, &max_corr) :
|
||||
get_sch_chan_imp_resp(ss, channel_imp_resp);
|
||||
detect_burst(&ss[start], &channel_imp_resp[0], 0, outbin);
|
||||
if(start <0)
|
||||
std::cerr << "wtf start" << start << (is_first_sch_acq ? "FIRST" : "") << std::endl;
|
||||
auto clamped_start = start < 0 ? 0 : start;
|
||||
detect_burst(&ss[0], &channel_imp_resp[0], clamped_start, outbin);
|
||||
|
||||
SoftVector bitss(148);
|
||||
for (int i = 0; i < 148; i++) {
|
||||
|
||||
@@ -220,6 +220,9 @@ int main(int argc, char *argv[])
|
||||
if (tx_flag)
|
||||
std::thread(tx_test, trx, &trx->ts_hitter_q, &trx->mTSC).detach();
|
||||
trx->start();
|
||||
|
||||
usleep(1000*100);
|
||||
trx->signal_start();
|
||||
do {
|
||||
sleep(1);
|
||||
} while (1);
|
||||
@@ -253,6 +256,7 @@ bh_fn_t ms_trx::rx_bh()
|
||||
return [this](dev_buf_t *rcd) -> int {
|
||||
if (this->search_for_sch(rcd) == SCH_STATE::FOUND)
|
||||
this->grab_bursts(rcd);
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user