ms: make app configurable

This adds proper config options.
The ul/dl freq lines can be copied from the osmo-trx (network side) cfg.

Change-Id: Ibd432f7abbd00065a59104d2c006b676d5db7b47
diff --git a/Transceiver52M/ms/ms_rx_lower.cpp b/Transceiver52M/ms/ms_rx_lower.cpp
index d894e96..b169dd8 100644
--- a/Transceiver52M/ms/ms_rx_lower.cpp
+++ b/Transceiver52M/ms/ms_rx_lower.cpp
@@ -108,12 +108,12 @@
 	runmean = gain_check ? (runmean * (gain_check + 2) - 1 + sum) / (gain_check + 2) : sum;
 
 	if (gain_check == avgburst_num - 1) {
-		DBGLG2() << "\x1B[32m #RXG \033[0m" << rxgain << " " << runmean << " " << sum << std::endl;
+		DBGLG2() << "\x1B[32m #RXG \033[0m" << cfg.rxgain << " " << runmean << " " << sum << std::endl;
 		auto gainoffset = runmean < (rxFullScale / 4 ? 4 : 2);
 		gainoffset = runmean < (rxFullScale / 2 ? 2 : 1);
-		float newgain = runmean < rx_max_cutoff ? rxgain + gainoffset : rxgain - gainoffset;
+		float newgain = runmean < rx_max_cutoff ? cfg.rxgain + gainoffset : cfg.rxgain - gainoffset;
 		// FIXME: gian cutoff
-		if (newgain != rxgain && newgain <= 60) {
+		if (newgain != cfg.rxgain && newgain <= 60) {
 			auto gain_fun = [this, newgain] { setRxGain(newgain); };
 			worker_thread.add_task(gain_fun);
 		}
@@ -144,7 +144,7 @@
 	while (upper_is_ready && !rxqueue.spsc_push(&brst))
 		;
 
-	if (do_auto_gain)
+	if (!use_agc)
 		maybe_update_gain(brst);
 
 	return false;
@@ -158,24 +158,24 @@
 	const auto buf_len = is_first_sch_acq ? SCH_LEN_SPS : ONE_TS_BURST_LEN;
 	const auto which_in_buffer = is_first_sch_acq ? first_sch_buf : burst_copy_buffer;
 	memset((void *)&sch_acq_buffer[0], 0, sizeof(sch_acq_buffer));
-#if 1
-	const auto which_out_buffer = is_first_sch_acq ? sch_acq_buffer : &sch_acq_buffer[40 * 2];
-	const auto ss = reinterpret_cast<std::complex<float> *>(which_out_buffer);
-	std::complex<float> channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
-	int start;
-	convert_and_scale(which_out_buffer, which_in_buffer, buf_len * 2, 1.f / float(rxFullScale));
-	if (is_first_sch_acq) {
-		float max_corr = 0;
-		start = get_sch_buffer_chan_imp_resp(ss, &channel_imp_resp[0], buf_len, &max_corr);
-	} else {
-		start = get_sch_chan_imp_resp(ss, &channel_imp_resp[0]);
-		start = start < 39 ? start : 39;
-		start = start > -39 ? start : -39;
-	}
-	detect_burst_nb(&ss[start], &channel_imp_resp[0], 0, sch_demod_bits);
+	if (use_va) {
+		const auto which_out_buffer = is_first_sch_acq ? sch_acq_buffer : &sch_acq_buffer[40 * 2];
+		const auto ss = reinterpret_cast<std::complex<float> *>(which_out_buffer);
+		std::complex<float> channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
+		int start;
+		convert_and_scale(which_out_buffer, which_in_buffer, buf_len * 2, 1.f / float(rxFullScale));
+		if (is_first_sch_acq) {
+			float max_corr = 0;
+			start = get_sch_buffer_chan_imp_resp(ss, &channel_imp_resp[0], buf_len, &max_corr);
+		} else {
+			start = get_sch_chan_imp_resp(ss, &channel_imp_resp[0]);
+			start = start < 39 ? start : 39;
+			start = start > -39 ? start : -39;
+		}
+		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);
-#if 0
+		auto sch_decode_success = decode_sch(sch_demod_bits, is_first_sch_acq);
+#if 0 // useful to debug offset shifts
 	auto burst = new signalVector(buf_len, 50);
 	const auto corr_type = is_first_sch_acq ? sch_detect_type::SCH_DETECT_BUFFER : sch_detect_type::SCH_DETECT_FULL;
 	struct estim_burst_params ebp;
@@ -189,113 +189,114 @@
 	std::cerr << "ooffs: " << howmuchdelay << " " << std::endl;
 	std::cerr << "voffs: " << start << " " << sch_decode_success << std::endl;
 #endif
-	if (sch_decode_success) {
-		const auto ts_offset_symb = 4;
-		if (is_first_sch_acq) {
-			// update ts to first sample in sch buffer, to allow delay calc for current ts
-			first_sch_ts_start = first_sch_buf_rcv_ts + start - (ts_offset_symb * 4) - 1;
-		} else if (abs(start) > 1) {
-			// continuous sch tracking, only update if off too much
-			temp_ts_corr_offset += -start;
-			std::cerr << "offs: " << start << " " << temp_ts_corr_offset << std::endl;
+		if (sch_decode_success) {
+			const auto ts_offset_symb = 4;
+			if (is_first_sch_acq) {
+				// update ts to first sample in sch buffer, to allow delay calc for current ts
+				first_sch_ts_start = first_sch_buf_rcv_ts + start - (ts_offset_symb * 4) - 1;
+			} else if (abs(start) > 1) {
+				// continuous sch tracking, only update if off too much
+				temp_ts_corr_offset += -start;
+				std::cerr << "offs: " << start << " " << temp_ts_corr_offset << std::endl;
+			}
+
+			return true;
+		} else {
+			DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << start << " "
+				 << current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
 		}
-
-		return true;
 	} else {
-		DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << start << " " << current_gsm_time.FN()
-			 << ":" << current_gsm_time.TN() << std::endl;
-	}
-#else
-	const auto ts_offset_symb = 4;
-	auto burst = new signalVector(buf_len, 50);
-	const auto corr_type = is_first_sch_acq ? sch_detect_type::SCH_DETECT_BUFFER : sch_detect_type::SCH_DETECT_FULL;
-	struct estim_burst_params ebp;
+		const auto ts_offset_symb = 4;
+		auto burst = new signalVector(buf_len, 50);
+		const auto corr_type =
+			is_first_sch_acq ? sch_detect_type::SCH_DETECT_BUFFER : sch_detect_type::SCH_DETECT_FULL;
+		struct estim_burst_params ebp;
 
-	// scale like uhd, +-2k -> +-32k
-	convert_and_scale(burst->begin(), which_in_buffer, buf_len * 2, SAMPLE_SCALE_FACTOR);
+		// scale like uhd, +-2k -> +-32k
+		convert_and_scale(burst->begin(), which_in_buffer, buf_len * 2, SAMPLE_SCALE_FACTOR);
 
-	auto rv = detectSCHBurst(*burst, 4, 4, corr_type, &ebp);
+		auto rv = detectSCHBurst(*burst, 4, 4, corr_type, &ebp);
 
-	int howmuchdelay = ebp.toa * 4;
+		int howmuchdelay = ebp.toa * 4;
 
-	if (!rv) {
-		delete burst;
-		DBGLG() << "SCH : \x1B[31m detect fail \033[0m NOOOOOOOOOOOOOOOOOO toa:" << ebp.toa << " "
-			<< current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
-		return false;
-	}
-
-	SoftVector *bits;
-	if (is_first_sch_acq) {
-		// can't be legit with a buf size spanning _at least_ one SCH but delay that implies partial sch burst
-		if (howmuchdelay < 0 || (buf_len - howmuchdelay) < ONE_TS_BURST_LEN) {
+		if (!rv) {
 			delete burst;
+			DBGLG() << "SCH : \x1B[31m detect fail \033[0m NOOOOOOOOOOOOOOOOOO toa:" << ebp.toa << " "
+				<< current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
 			return false;
 		}
 
-		struct estim_burst_params ebp2;
-		// auto sch_chunk = new signalVector(ONE_TS_BURST_LEN, 50);
-		// auto sch_chunk_start = sch_chunk->begin();
-		// memcpy(sch_chunk_start, sch_buf_f.data() + howmuchdelay, sizeof(std::complex<float>) * ONE_TS_BURST_LEN);
-
-		auto delay = delayVector(burst, NULL, -howmuchdelay);
-
-		scaleVector(*delay, (complex)1.0 / ebp.amp);
-
-		auto rv2 = detectSCHBurst(*delay, 4, 4, sch_detect_type::SCH_DETECT_FULL, &ebp2);
-		DBGLG() << "FIRST SCH : " << (rv2 ? "yes " : "   ") << "Timing offset     " << ebp2.toa << " symbols"
-			<< std::endl;
-
-		bits = demodAnyBurst(*delay, SCH, 4, &ebp2);
-		delete delay;
-	} else {
-		bits = demodAnyBurst(*burst, SCH, 4, &ebp);
-	}
-
-	delete burst;
-
-	// clamp to +-1.5 because +-127 softbits scaled by 64 after -0.5 can be at most +-1.5
-	clamp_array(bits->begin(), 148, 1.5f);
-
-	float_to_sbit(&bits->begin()[0], (signed char *)&sch_demod_bits[0], 62, 148);
-	// float_to_sbit(&bits->begin()[106], &data[39], 62, 39);
-
-	if (decode_sch((char *)sch_demod_bits, is_first_sch_acq)) {
-		auto current_gsm_time_updated = timekeeper.gsmtime();
+		SoftVector *bits;
 		if (is_first_sch_acq) {
-			// update ts to first sample in sch buffer, to allow delay calc for current ts
-			first_sch_ts_start = first_sch_buf_rcv_ts + howmuchdelay - (ts_offset_symb * 4);
-		} else {
-			// continuous sch tracking, only update if off too much
-			auto diff = [](float x, float y) { return x > y ? x - y : y - x; };
-
-			auto d = diff(ebp.toa, ts_offset_symb);
-			if (abs(d) > 0.3) {
-				if (ebp.toa < ts_offset_symb)
-					ebp.toa = d;
-				else
-					ebp.toa = -d;
-				temp_ts_corr_offset += ebp.toa * 4;
-
-				DBGLG() << "offs: " << ebp.toa << " " << temp_ts_corr_offset << std::endl;
+			// can't be legit with a buf size spanning _at least_ one SCH but delay that implies partial sch burst
+			if (howmuchdelay < 0 || (buf_len - howmuchdelay) < ONE_TS_BURST_LEN) {
+				delete burst;
+				return false;
 			}
+
+			struct estim_burst_params ebp2;
+			// auto sch_chunk = new signalVector(ONE_TS_BURST_LEN, 50);
+			// auto sch_chunk_start = sch_chunk->begin();
+			// memcpy(sch_chunk_start, sch_buf_f.data() + howmuchdelay, sizeof(std::complex<float>) * ONE_TS_BURST_LEN);
+
+			auto delay = delayVector(burst, NULL, -howmuchdelay);
+
+			scaleVector(*delay, (complex)1.0 / ebp.amp);
+
+			auto rv2 = detectSCHBurst(*delay, 4, 4, sch_detect_type::SCH_DETECT_FULL, &ebp2);
+			DBGLG() << "FIRST SCH : " << (rv2 ? "yes " : "   ") << "Timing offset     " << ebp2.toa
+				<< " symbols" << std::endl;
+
+			bits = demodAnyBurst(*delay, SCH, 4, &ebp2);
+			delete delay;
+		} else {
+			bits = demodAnyBurst(*burst, SCH, 4, &ebp);
 		}
 
-		auto a = gsm_sch_check_fn(current_gsm_time_updated.FN() - 1);
-		auto b = gsm_sch_check_fn(current_gsm_time_updated.FN());
-		auto c = gsm_sch_check_fn(current_gsm_time_updated.FN() + 1);
-		DBGLG() << "L SCH : Timing offset     " << rv << " " << ebp.toa << " " << a << b << c << "fn "
-			<< current_gsm_time_updated.FN() << ":" << current_gsm_time_updated.TN() << std::endl;
+		delete burst;
+
+		// clamp to +-1.5 because +-127 softbits scaled by 64 after -0.5 can be at most +-1.5
+		clamp_array(bits->begin(), 148, 1.5f);
+
+		float_to_sbit(&bits->begin()[0], (signed char *)&sch_demod_bits[0], 62, 148);
+		// float_to_sbit(&bits->begin()[106], &data[39], 62, 39);
+
+		if (decode_sch((char *)sch_demod_bits, is_first_sch_acq)) {
+			auto current_gsm_time_updated = timekeeper.gsmtime();
+			if (is_first_sch_acq) {
+				// update ts to first sample in sch buffer, to allow delay calc for current ts
+				first_sch_ts_start = first_sch_buf_rcv_ts + howmuchdelay - (ts_offset_symb * 4);
+			} else {
+				// continuous sch tracking, only update if off too much
+				auto diff = [](float x, float y) { return x > y ? x - y : y - x; };
+
+				auto d = diff(ebp.toa, ts_offset_symb);
+				if (abs(d) > 0.3) {
+					if (ebp.toa < ts_offset_symb)
+						ebp.toa = d;
+					else
+						ebp.toa = -d;
+					temp_ts_corr_offset += ebp.toa * 4;
+
+					DBGLG() << "offs: " << ebp.toa << " " << temp_ts_corr_offset << std::endl;
+				}
+			}
+
+			auto a = gsm_sch_check_fn(current_gsm_time_updated.FN() - 1);
+			auto b = gsm_sch_check_fn(current_gsm_time_updated.FN());
+			auto c = gsm_sch_check_fn(current_gsm_time_updated.FN() + 1);
+			DBGLG() << "L SCH : Timing offset     " << rv << " " << ebp.toa << " " << a << b << c << "fn "
+				<< current_gsm_time_updated.FN() << ":" << current_gsm_time_updated.TN() << std::endl;
+
+			delete bits;
+			return true;
+		} else {
+			DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << ebp.toa << " "
+				 << current_gsm_time.FN() << ":" << current_gsm_time.TN() << std::endl;
+		}
 
 		delete bits;
-		return true;
-	} else {
-		DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << ebp.toa << " " << current_gsm_time.FN()
-			 << ":" << current_gsm_time.TN() << std::endl;
 	}
-
-	delete bits;
-#endif
 	return false;
 }
 
@@ -333,12 +334,12 @@
 			float sum = normed_abs_sum(first_sch_buf, SCH_LEN_SPS);
 
 			//FIXME: arbitrary value, gain cutoff
-			if (sum > target_val || rxgain >= 60) // enough ?
+			if (sum > target_val || cfg.rxgain >= 60) // enough ?
 				sch_thread_done = this->handle_sch(true);
 			else {
-				std::cerr << "\x1B[32m #RXG \033[0m gain " << rxgain << " -> " << rxgain + 4
+				std::cerr << "\x1B[32m #RXG \033[0m gain " << cfg.rxgain << " -> " << cfg.rxgain + 4
 					  << " sample avg:" << sum << " target: >=" << target_val << std::endl;
-				setRxGain(rxgain + 4);
+				setRxGain(cfg.rxgain + 4);
 			}
 
 			if (!sch_thread_done)