diff --git a/Transceiver52M/grgsm_vitac/constants.h b/Transceiver52M/grgsm_vitac/constants.h index 07f22907..27bf6f4d 100644 --- a/Transceiver52M/grgsm_vitac/constants.h +++ b/Transceiver52M/grgsm_vitac/constants.h @@ -38,6 +38,7 @@ #define STEALING_BIT 1 #define N_TRAIN_BITS 26 #define N_SYNC_BITS 64 +#define N_ACCESS_BITS 41 #define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS ) #define FCCH_BITS USEFUL_BITS #define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS) @@ -73,6 +74,12 @@ static const unsigned char SYNC_BITS[] = { 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 }; +static const unsigned char ACCESS_BITS [] = { + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0 +}; + const unsigned FCCH_FRAMES[] = { 0, 10, 20, 30, 40 }; const unsigned SCH_FRAMES[] = { 1, 11, 21, 31, 41 }; diff --git a/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp b/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp index 836c5552..5779d9d8 100644 --- a/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp +++ b/Transceiver52M/grgsm_vitac/grgsm_vitac.cpp @@ -39,13 +39,13 @@ #include "viterbi_detector.h" #include "grgsm_vitac.h" -//signalVector mChanResp; +gr_complex d_acc_training_seq[N_ACCESS_BITS]; /// 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 NO_UBSAN -void detect_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary) +template +NO_UBSAN static void detect_burst_generic(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, + char *output_binary, int ss) { std::vector rhh_temp(CHAN_IMP_RESP_LENGTH * d_OSR); unsigned int stop_states[2] = { 4, 12 }; - gr_complex filtered_burst[BURST_SIZE]; + gr_complex filtered_burst[burst_size]; gr_complex rhh[CHAN_IMP_RESP_LENGTH]; - float output[BURST_SIZE]; - int start_state = 3; - - // if(burst_start < 0 ||burst_start > 10) - // fprintf(stderr, "bo %d\n", burst_start); - - // burst_start = burst_start >= 0 ? burst_start : 0; + float output[burst_size]; + int start_state = ss; autocorrelation(chan_imp_resp, &rhh_temp[0], d_chan_imp_length * d_OSR); 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] * -127; // pre flip bits! + for (unsigned int i = 0; i < burst_size; i++) + output_binary[i] = (char)(output[i] * -127); // pre flip bits! } -void -gmsk_mapper(const unsigned char* input, - int nitems, gr_complex* gmsk_output, gr_complex start_point) +NO_UBSAN void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, + int ss) +{ + return detect_burst_generic(input, chan_imp_resp, burst_start, output_binary, ss); +} +NO_UBSAN void detect_burst_ab(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, + int ss) +{ + return detect_burst_generic<8 + 41 + 36 + 3>(input, chan_imp_resp, burst_start, output_binary, ss); +} + +NO_UBSAN void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary) +{ + return detect_burst_nb(input, chan_imp_resp, burst_start, output_binary, 3); +} +NO_UBSAN void detect_burst_ab(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary) +{ + return detect_burst_ab(input, chan_imp_resp, burst_start, output_binary, 3); +} + +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; @@ -122,16 +135,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); @@ -142,9 +152,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); @@ -153,9 +161,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; @@ -170,66 +176,45 @@ mafi(const gr_complex* input, int nitems, } } -int get_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, int search_center, int search_start_pos, - int search_stop_pos, gr_complex *tseq, int tseqlen, float *corr_max) +int get_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, int search_start_pos, int search_stop_pos, + gr_complex *tseq, int tseqlen, float *corr_max) { - std::vector correlation_buffer; + const int num_search_windows = search_stop_pos - search_start_pos; + const int power_search_window_len = d_chan_imp_length * d_OSR; std::vector window_energy_buffer; std::vector power_buffer; + std::vector correlation_buffer; - for (int ii = search_start_pos; ii < search_stop_pos; ii++) { - gr_complex correlation = correlate_sequence(tseq, tseqlen, &input[ii]); + power_buffer.reserve(num_search_windows); + correlation_buffer.reserve(num_search_windows); + window_energy_buffer.reserve(num_search_windows); + + for (int ii = 0; ii < num_search_windows; ii++) { + gr_complex correlation = correlate_sequence(tseq, tseqlen, &input[search_start_pos + ii]); correlation_buffer.push_back(correlation); power_buffer.push_back(std::pow(abs(correlation), 2)); } - int strongest_corr_nr = max_element(power_buffer.begin(), power_buffer.end()) - power_buffer.begin(); - /* 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.. - 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; - while (iter != iter_end) { - std::vector::iterator iter_ii = iter; - bool loop_end = false; - float energy = 0; + float windowSum = 0; - int len = d_chan_imp_length * d_OSR; - for (int ii = 0; ii < len; ii++, iter_ii++) { - if (iter_ii == power_buffer.end()) { - loop_end = true; - break; - } + // first window + for (int i = 0; i < power_search_window_len; i++) { + windowSum += power_buffer[i]; + } + window_energy_buffer.push_back(windowSum); - energy += (*iter_ii); - } - - if (loop_end) - break; - - window_energy_buffer.push_back(energy); - iter++; + // slide windows + for (int i = power_search_window_len; i < num_search_windows; i++) { + windowSum += power_buffer[i] - power_buffer[i - power_search_window_len]; + window_energy_buffer.push_back(windowSum); } - /* Calculate the strongest window number */ - int strongest_window_nr = window_energy_start_offset + - max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - + int strongest_window_nr = std::max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin(); - // auto window_search_start = window_energy_buffer.begin() + strongest_corr_nr - 5* d_OSR; - // auto window_search_end = window_energy_buffer.begin() + strongest_corr_nr + 10* d_OSR; - // window_search_end = window_search_end >= window_energy_buffer.end() ? window_energy_buffer.end() : window_search_end; - - // /* Calculate the strongest window number */ - // int strongest_window_nr = max_element(window_search_start, window_search_end /* - d_chan_imp_length * d_OSR*/) - window_energy_buffer.begin(); - - // if (strongest_window_nr < 0) - // strongest_window_nr = 0; - float max_correlation = 0; - for (int ii = 0; ii < d_chan_imp_length * d_OSR; ii++) { + for (int ii = 0; ii < power_search_window_len; ii++) { gr_complex correlation = correlation_buffer[strongest_window_nr + ii]; if (abs(correlation) > max_correlation) max_correlation = abs(correlation); @@ -242,7 +227,27 @@ int get_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, int se * Compute first sample position, which corresponds * to the first sample of the impulse response */ - return search_start_pos + strongest_window_nr - search_center * d_OSR; + return search_start_pos + strongest_window_nr; +} + +/* +8 ext tail bits +41 sync seq +36 encrypted bits +3 tail bits +68.25 extended tail bits (!) + +center at 8+5 (actually known tb -> known isi, start at 8?) FIXME +*/ +int get_access_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, float *corr_max, int max_delay) +{ + const int search_center = 8 + 5; + const int search_start_pos = (search_center - 5) * d_OSR + 1; + const int search_stop_pos = (search_center + 5 + d_chan_imp_length + max_delay) * d_OSR; + const auto tseq = &d_acc_training_seq[TRAIN_BEGINNING]; + const auto tseqlen = N_ACCESS_BITS - (2 * TRAIN_BEGINNING); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, corr_max) - + search_center * d_OSR; } /* @@ -260,8 +265,8 @@ int get_norm_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, f const int search_stop_pos = (search_center + 5 + d_chan_imp_length) * d_OSR; const auto tseq = &d_norm_training_seq[bcc][TRAIN_BEGINNING]; const auto tseqlen = N_TRAIN_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); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, corr_max) - + search_center * d_OSR; } /* @@ -281,8 +286,9 @@ int get_sch_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp) // strongest_window_nr + chan_imp_resp_center + SYNC_POS *d_OSR - 48 * d_OSR - 2 * d_OSR + 2 ; float corr_max; - return get_chan_imp_resp(input, chan_imp_resp, search_center, search_start_pos, search_stop_pos, tseq, tseqlen, - &corr_max); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, &corr_max) - + search_center * d_OSR; + ; } int get_sch_buffer_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, unsigned int len, float *corr_max) @@ -291,9 +297,9 @@ int get_sch_buffer_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_r 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); + const int search_stop_pos = len - (N_SYNC_BITS * 8); auto tseq = &d_sch_training_seq[TRAIN_BEGINNING]; - return get_chan_imp_resp(input, chan_imp_resp, search_center, search_start_pos, search_stop_pos, tseq, tseqlen, - corr_max); + return get_chan_imp_resp(input, chan_imp_resp, search_start_pos, search_stop_pos, tseq, tseqlen, corr_max) - + search_center * d_OSR; } \ No newline at end of file diff --git a/Transceiver52M/grgsm_vitac/grgsm_vitac.h b/Transceiver52M/grgsm_vitac/grgsm_vitac.h index 2c89d8c1..d00c3ad9 100644 --- a/Transceiver52M/grgsm_vitac/grgsm_vitac.h +++ b/Transceiver52M/grgsm_vitac/grgsm_vitac.h @@ -58,8 +58,11 @@ void initvita(); 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); -MULTI_VER_TARGET_ATTR_CLANGONLY -void detect_burst(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary); +void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, int ss); +void detect_burst_ab(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary, int ss); +void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary); +void detect_burst_ab(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary); + void gmsk_mapper(const unsigned char *input, int nitems, gr_complex *gmsk_output, gr_complex start_point); gr_complex correlate_sequence(const gr_complex *sequence, int length, const gr_complex *input); inline void autocorrelation(const gr_complex *input, gr_complex *out, int nitems); @@ -67,6 +70,7 @@ inline void mafi(const gr_complex *input, int nitems, gr_complex *filter, int fi int get_sch_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp); int get_norm_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, float *corr_max, int bcc); int get_sch_buffer_chan_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, unsigned int len, float *corr_max); +int get_access_imp_resp(const gr_complex *input, gr_complex *chan_imp_resp, float *corr_max, int max_delay); enum class btype { NB, SCH }; struct fdata { diff --git a/Transceiver52M/ms/ms_rx_lower.cpp b/Transceiver52M/ms/ms_rx_lower.cpp index 5a07df58..c2adda32 100644 --- a/Transceiver52M/ms/ms_rx_lower.cpp +++ b/Transceiver52M/ms/ms_rx_lower.cpp @@ -170,7 +170,7 @@ bool ms_trx::handle_sch(bool is_first_sch_acq) start = start < 39 ? start : 39; start = start > -39 ? start : -39; } - detect_burst(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits); + detect_burst_nb(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits); auto sch_decode_success = decode_sch(sch_demod_bits, is_first_sch_acq); diff --git a/Transceiver52M/ms/ms_upper.cpp b/Transceiver52M/ms/ms_upper.cpp index 0a2c3338..3c34efe8 100644 --- a/Transceiver52M/ms/ms_upper.cpp +++ b/Transceiver52M/ms/ms_upper.cpp @@ -196,7 +196,7 @@ bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset) // fprintf(stderr, "%s %d\n", (is_nb ? "N":"D"), burst_time.FN()); // if (is_nb) #endif - detect_burst(ss, &chan_imp_resp[0], normal_burst_start, demodded_softbits); + detect_burst_nb(ss, &chan_imp_resp[0], normal_burst_start, demodded_softbits); #ifdef DBGXX // else // detect_burst(ss, &chan_imp_resp2[0], dummy_burst_start, outbin);