mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
				synced 2025-11-04 06:03:17 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9269aaa9cb | ||
| 
						 | 
					f97c53bc9c | 
@@ -1,5 +1,4 @@
 | 
				
			|||||||
--exclude osmocom-bb/.*
 | 
					--exclude osmocom-bb/.*
 | 
				
			||||||
--exclude .*h
 | 
					--exclude .*h
 | 
				
			||||||
--exclude Transceiver52M/grgsm_vitac/.*
 | 
					--exclude Transceiver52M/grgsm_vitac/.*
 | 
				
			||||||
--exclude utils/va-test/.*
 | 
					 | 
				
			||||||
--ignore FUNCTION_WITHOUT_ARGS
 | 
					--ignore FUNCTION_WITHOUT_ARGS
 | 
				
			||||||
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
open_collective: osmocom
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -38,7 +38,6 @@ Transceiver52M/device/ipc/ipc-driver-test
 | 
				
			|||||||
.deps
 | 
					.deps
 | 
				
			||||||
.libs
 | 
					.libs
 | 
				
			||||||
.dirstamp
 | 
					.dirstamp
 | 
				
			||||||
.version
 | 
					 | 
				
			||||||
*~
 | 
					*~
 | 
				
			||||||
Makefile
 | 
					Makefile
 | 
				
			||||||
config.log
 | 
					config.log
 | 
				
			||||||
@@ -84,7 +83,6 @@ contrib/osmo-trx.spec
 | 
				
			|||||||
!contrib/osmo-trx.spec.in
 | 
					!contrib/osmo-trx.spec.in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
utils/osmo-prbs-tool
 | 
					utils/osmo-prbs-tool
 | 
				
			||||||
utils/va-test/osmo-burst-gen
 | 
					 | 
				
			||||||
/.qtc_clangd/*
 | 
					/.qtc_clangd/*
 | 
				
			||||||
/.cache/*
 | 
					/.cache/*
 | 
				
			||||||
/.vscode/*
 | 
					/.vscode/*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ std::vector<std::string> comma_delimited_to_vector(const char* opt)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
	    std::string substr;
 | 
						    std::string substr;
 | 
				
			||||||
	    getline(ss, substr, ',');
 | 
						    getline(ss, substr, ',');
 | 
				
			||||||
	    result.push_back(std::move(substr));
 | 
						    result.push_back(substr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -781,6 +781,17 @@ DEFUN(show_trx, show_trx_cmd,
 | 
				
			|||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int trx_vty_is_config_node(struct vty *vty, int node)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (node) {
 | 
				
			||||||
 | 
						case TRX_NODE:
 | 
				
			||||||
 | 
						case CHAN_NODE:
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int trx_vty_go_parent(struct vty *vty)
 | 
					static int trx_vty_go_parent(struct vty *vty)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (vty->node) {
 | 
						switch (vty->node) {
 | 
				
			||||||
@@ -818,6 +829,7 @@ struct vty_app_info g_vty_info = {
 | 
				
			|||||||
	.version	= PACKAGE_VERSION,
 | 
						.version	= PACKAGE_VERSION,
 | 
				
			||||||
	.copyright	= trx_copyright,
 | 
						.copyright	= trx_copyright,
 | 
				
			||||||
	.go_parent_cb	= trx_vty_go_parent,
 | 
						.go_parent_cb	= trx_vty_go_parent,
 | 
				
			||||||
 | 
						.is_config_node	= trx_vty_is_config_node,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct trx_ctx *vty_trx_ctx_alloc(void *talloc_ctx)
 | 
					struct trx_ctx *vty_trx_ctx_alloc(void *talloc_ctx)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,15 +55,12 @@ const BitVector GSM::gEdgeTrainingSequence[] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const BitVector GSM::gDummyBurst("0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000");
 | 
					const BitVector GSM::gDummyBurst("0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000");
 | 
				
			||||||
const BitVector GSM::gDummyBurstTSC("01110001011100010111000101");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)", synch. sequence bits */
 | 
					/* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)", synch. sequence bits */
 | 
				
			||||||
const BitVector GSM::gRACHSynchSequenceTS0("01001011011111111001100110101010001111000");  /* GSM, GMSK (default) */
 | 
					const BitVector GSM::gRACHSynchSequenceTS0("01001011011111111001100110101010001111000");  /* GSM, GMSK (default) */
 | 
				
			||||||
const BitVector GSM::gRACHSynchSequenceTS1("01010100111110001000011000101111001001101");  /* EGPRS, 8-PSK */
 | 
					const BitVector GSM::gRACHSynchSequenceTS1("01010100111110001000011000101111001001101");  /* EGPRS, 8-PSK */
 | 
				
			||||||
const BitVector GSM::gRACHSynchSequenceTS2("11101111001001110101011000001101101110111");  /* EGPRS, GMSK */
 | 
					const BitVector GSM::gRACHSynchSequenceTS2("11101111001001110101011000001101101110111");  /* EGPRS, GMSK */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const BitVector GSM::gSCHSynchSequence("1011100101100010000001000000111100101101010001010111011000011011");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//                               |-head-||---------midamble----------------------||--------------data----------------||t|
 | 
					//                               |-head-||---------midamble----------------------||--------------data----------------||t|
 | 
				
			||||||
const BitVector GSM::gRACHBurst("0011101001001011011111111001100110101010001111000110111101111110000111001001010110011000");
 | 
					const BitVector GSM::gRACHBurst("0011101001001011011111111001100110101010001111000110111101111110000111001001010110011000");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,16 +52,11 @@ extern const BitVector gEdgeTrainingSequence[];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/** C0T0 filler burst, GSM 05.02, 5.2.6 */
 | 
					/** C0T0 filler burst, GSM 05.02, 5.2.6 */
 | 
				
			||||||
extern const BitVector gDummyBurst;
 | 
					extern const BitVector gDummyBurst;
 | 
				
			||||||
extern const BitVector gDummyBurstTSC;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Random access burst synch. sequence */
 | 
					/** Random access burst synch. sequence */
 | 
				
			||||||
extern const BitVector gRACHSynchSequenceTS0;
 | 
					extern const BitVector gRACHSynchSequenceTS0;
 | 
				
			||||||
extern const BitVector gRACHSynchSequenceTS1;
 | 
					extern const BitVector gRACHSynchSequenceTS1;
 | 
				
			||||||
extern const BitVector gRACHSynchSequenceTS2;
 | 
					extern const BitVector gRACHSynchSequenceTS2;
 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Synchronization burst sync sequence */
 | 
					 | 
				
			||||||
extern const BitVector gSCHSynchSequence;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Random access burst synch. sequence, GSM 05.02 5.2.7 */
 | 
					/** Random access burst synch. sequence, GSM 05.02 5.2.7 */
 | 
				
			||||||
extern const BitVector gRACHBurst;
 | 
					extern const BitVector gRACHBurst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,19 +43,12 @@ SUBDIRS += \
 | 
				
			|||||||
	doc \
 | 
						doc \
 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BUILT_SOURCES = $(top_srcdir)/.version
 | 
					 | 
				
			||||||
$(top_srcdir)/.version:
 | 
					 | 
				
			||||||
	echo $(VERSION) > $@-t && mv $@-t $@
 | 
					 | 
				
			||||||
dist-hook:
 | 
					 | 
				
			||||||
	echo $(VERSION) > $(distdir)/.tarball-version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXTRA_DIST = \
 | 
					EXTRA_DIST = \
 | 
				
			||||||
	.version \
 | 
					 | 
				
			||||||
	LEGAL \
 | 
						LEGAL \
 | 
				
			||||||
	COPYING \
 | 
						COPYING \
 | 
				
			||||||
	README.md \
 | 
						README.md \
 | 
				
			||||||
 | 
						contrib/osmo-trx.spec.in \
 | 
				
			||||||
	debian \
 | 
						debian \
 | 
				
			||||||
	git-version-gen \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
 | 
					AM_DISTCHECK_CONFIGURE_FLAGS = \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
									
									
									
									
								
							@@ -4,17 +4,17 @@ About OsmoTRX
 | 
				
			|||||||
OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
physical layer of a BTS comprising the following 3GPP specifications:
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* TS 05.01 *Physical layer on the radio path*
 | 
					* TS 05.01 "Physical layer on the radio path"
 | 
				
			||||||
* TS 05.02 *Multiplexing and Multiple Access on the Radio Path*
 | 
					* TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
				
			||||||
* TS 05.04 *Modulation*
 | 
					* TS 05.04 "Modulation"
 | 
				
			||||||
* TS 05.10 *Radio subsystem synchronization*
 | 
					* TS 05.10 "Radio subsystem synchronization"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OsmoTRX is originally based on the transceiver code from the
 | 
					OsmoTRX is originally based on the transceiver code from the
 | 
				
			||||||
[OpenBTS](https://osmocom.org/projects/osmobts/wiki/OpenBTS) project, but setup
 | 
					[OpenBTS](https://osmocom.org/projects/osmobts/wiki/OpenBTS) project, but setup
 | 
				
			||||||
to operate independently with the purpose of using with non-OpenBTS software and
 | 
					to operate independently with the purpose of using with non-OpenBTS software and
 | 
				
			||||||
projects, specifically within the Osmocom stack.  Used together with
 | 
					projects, specifically within the Osmocom stack.  Used together with
 | 
				
			||||||
[OsmoBTS](https://osmocom.org/projects/osmobts/wiki) you can get a pretty
 | 
					[OsmoBTS](https://osmocom.org/projects/osmobts/wiki) you can get a pretty
 | 
				
			||||||
standard GSM/GPRS/EGPRS BTS with Abis interface as per the relevant 3GPP specifications.
 | 
					standard GSM BTS with Abis interface as per the relevant 3GPP specifications.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Homepage
 | 
					Homepage
 | 
				
			||||||
--------
 | 
					--------
 | 
				
			||||||
@@ -27,7 +27,7 @@ GIT Repository
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
You can clone from the official osmo-trx.git repository using
 | 
					You can clone from the official osmo-trx.git repository using
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
					        git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-trx`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-trx>
 | 
					There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-trx>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,13 +39,6 @@ also available online for each of the sub-libraries at User Manual for OsmoTRX
 | 
				
			|||||||
can be generated during the build process, and is also available online at
 | 
					can be generated during the build process, and is also available online at
 | 
				
			||||||
<https://ftp.osmocom.org/docs/latest/osmotrx-usermanual.pdf>.
 | 
					<https://ftp.osmocom.org/docs/latest/osmotrx-usermanual.pdf>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Forum
 | 
					 | 
				
			||||||
-----
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
We welcome any osmo-trx related discussions in the
 | 
					 | 
				
			||||||
[Cellular Network Infrastructure -> 2 RAN (GERAN)](https://discourse.osmocom.org/c/cni/geran)
 | 
					 | 
				
			||||||
section of the osmocom discourse (web based Forum).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Mailing List
 | 
					Mailing List
 | 
				
			||||||
------------
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,20 +50,13 @@ Please observe the [Osmocom Mailing List
 | 
				
			|||||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
 | 
					Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
 | 
				
			||||||
when posting.
 | 
					when posting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Issue Tracker
 | 
					 | 
				
			||||||
-------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
We use the [issue tracker of the osmo-trx project on osmocom.org](https://osmocom.org/projects/osmotrx/issues) for
 | 
					 | 
				
			||||||
tracking the state of bug reports and feature requests.  Feel free to submit any issues you may find, or help
 | 
					 | 
				
			||||||
us out by resolving existing issues.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Contributing
 | 
					Contributing
 | 
				
			||||||
------------
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Our coding standards are described at
 | 
					Our coding standards are described at
 | 
				
			||||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
 | 
					<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We use a Gerrit based patch submission/review process for managing contributions.
 | 
					We us a gerrit based patch submission/review process for managing contributions.
 | 
				
			||||||
Please see <https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit>
 | 
					Please see <https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit>
 | 
				
			||||||
for more details
 | 
					for more details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
 | 
					 | 
				
			||||||
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
 | 
					 | 
				
			||||||
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
 | 
					 | 
				
			||||||
# LIBVERSION=c:r:a
 | 
					 | 
				
			||||||
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
 | 
					 | 
				
			||||||
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
 | 
					 | 
				
			||||||
# If any interfaces have been added since the last public release: c:r:a + 1.
 | 
					 | 
				
			||||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
 | 
					 | 
				
			||||||
#library	what			description / commit summary line
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,7 +88,6 @@ TRXCON_LDADD = \
 | 
				
			|||||||
MS_LOWER_SRC = \
 | 
					MS_LOWER_SRC = \
 | 
				
			||||||
	ms/sch.c \
 | 
						ms/sch.c \
 | 
				
			||||||
	ms/ms.cpp \
 | 
						ms/ms.cpp \
 | 
				
			||||||
	ms/threadsched.cpp \
 | 
					 | 
				
			||||||
	ms/ms_rx_lower.cpp \
 | 
						ms/ms_rx_lower.cpp \
 | 
				
			||||||
	grgsm_vitac/grgsm_vitac.cpp \
 | 
						grgsm_vitac/grgsm_vitac.cpp \
 | 
				
			||||||
	grgsm_vitac/viterbi_detector.cc
 | 
						grgsm_vitac/viterbi_detector.cc
 | 
				
			||||||
@@ -102,7 +101,6 @@ MS_UPPER_SRC = \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
noinst_HEADERS += \
 | 
					noinst_HEADERS += \
 | 
				
			||||||
   	ms/ms.h \
 | 
					   	ms/ms.h \
 | 
				
			||||||
	ms/threadsched.h \
 | 
					 | 
				
			||||||
	ms/bladerf_specific.h \
 | 
						ms/bladerf_specific.h \
 | 
				
			||||||
	ms/uhd_specific.h \
 | 
						ms/uhd_specific.h \
 | 
				
			||||||
	ms/ms_upper.h \
 | 
						ms/ms_upper.h \
 | 
				
			||||||
@@ -127,16 +125,16 @@ osmo_trx_uhd_LDADD = \
 | 
				
			|||||||
	$(UHD_LIBS)
 | 
						$(UHD_LIBS)
 | 
				
			||||||
osmo_trx_uhd_CPPFLAGS  = $(AM_CPPFLAGS) $(UHD_CFLAGS)
 | 
					osmo_trx_uhd_CPPFLAGS  = $(AM_CPPFLAGS) $(UHD_CFLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if ENABLE_MS_TRX
 | 
					if ENABLE_MS_TRX
 | 
				
			||||||
#bin_PROGRAMS += osmo-trx-ms-uhd
 | 
					bin_PROGRAMS += osmo-trx-ms-uhd
 | 
				
			||||||
#osmo_trx_ms_uhd_SOURCES = $(MS_LOWER_SRC) $(MS_UPPER_SRC)
 | 
					osmo_trx_ms_uhd_SOURCES = $(MS_LOWER_SRC) $(MS_UPPER_SRC)
 | 
				
			||||||
#osmo_trx_ms_uhd_LDADD = \
 | 
					osmo_trx_ms_uhd_LDADD = \
 | 
				
			||||||
#	$(builddir)/device/uhd/libdevice.la \
 | 
						$(builddir)/device/uhd/libdevice.la \
 | 
				
			||||||
#	$(COMMON_LDADD) \
 | 
						$(COMMON_LDADD) \
 | 
				
			||||||
#	$(UHD_LIBS) \
 | 
						$(UHD_LIBS) \
 | 
				
			||||||
#	$(TRXCON_LDADD)
 | 
						$(TRXCON_LDADD)
 | 
				
			||||||
#osmo_trx_ms_uhd_CPPFLAGS  = $(AM_CPPFLAGS) $(UHD_CFLAGS) -DBUILDUHD
 | 
					osmo_trx_ms_uhd_CPPFLAGS  = $(AM_CPPFLAGS) $(UHD_CFLAGS) -DBUILDUHD
 | 
				
			||||||
#endif
 | 
					endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if DEVICE_USRP1
 | 
					if DEVICE_USRP1
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ extern "C" {
 | 
				
			|||||||
#define M_PI			3.14159265358979323846264338327f
 | 
					#define M_PI			3.14159265358979323846264338327f
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_OUTPUT_LEN		4096*4
 | 
					#define MAX_OUTPUT_LEN		4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace std;
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -959,18 +959,19 @@ int Transceiver::ctrl_sock_handle_rx(int chan)
 | 
				
			|||||||
      sprintf(response, "RSP NOHANDOVER 0 %u %u", ts, ss);
 | 
					      sprintf(response, "RSP NOHANDOVER 0 %u %u", ts, ss);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if (match_cmd(command, "SETMAXDLY", ¶ms)) {
 | 
					  } else if (match_cmd(command, "SETMAXDLY", ¶ms)) {
 | 
				
			||||||
    //set expected maximum time-of-arrival for Access Bursts
 | 
					    //set expected maximum time-of-arrival
 | 
				
			||||||
    int maxDelay;
 | 
					    int maxDelay;
 | 
				
			||||||
    sscanf(params, "%d", &maxDelay);
 | 
					    sscanf(params, "%d", &maxDelay);
 | 
				
			||||||
    mMaxExpectedDelayAB = maxDelay; // 1 GSM symbol is approx. 1 km
 | 
					    mMaxExpectedDelayAB = maxDelay; // 1 GSM symbol is approx. 1 km
 | 
				
			||||||
    sprintf(response,"RSP SETMAXDLY 0 %d",maxDelay);
 | 
					    sprintf(response,"RSP SETMAXDLY 0 %d",maxDelay);
 | 
				
			||||||
  } else if (match_cmd(command, "SETMAXDLYNB", ¶ms)) {
 | 
					  } else if (match_cmd(command, "SETMAXDLYNB", ¶ms)) {
 | 
				
			||||||
    //set expected maximum time-of-arrival for Normal Bursts
 | 
					    //set expected maximum time-of-arrival
 | 
				
			||||||
    int maxDelay;
 | 
					    int maxDelay;
 | 
				
			||||||
    sscanf(params, "%d", &maxDelay);
 | 
					    sscanf(params, "%d", &maxDelay);
 | 
				
			||||||
    mMaxExpectedDelayNB = maxDelay; // 1 GSM symbol is approx. 1 km
 | 
					    mMaxExpectedDelayNB = maxDelay; // 1 GSM symbol is approx. 1 km
 | 
				
			||||||
    sprintf(response,"RSP SETMAXDLYNB 0 %d",maxDelay);
 | 
					    sprintf(response,"RSP SETMAXDLYNB 0 %d",maxDelay);
 | 
				
			||||||
  } else if (match_cmd(command, "SETRXGAIN", ¶ms)) {
 | 
					  } else if (match_cmd(command, "SETRXGAIN", ¶ms)) {
 | 
				
			||||||
 | 
					    //set expected maximum time-of-arrival
 | 
				
			||||||
    int newGain;
 | 
					    int newGain;
 | 
				
			||||||
    sscanf(params, "%d", &newGain);
 | 
					    sscanf(params, "%d", &newGain);
 | 
				
			||||||
    newGain = mRadioInterface->setRxGain(newGain, chan);
 | 
					    newGain = mRadioInterface->setRxGain(newGain, chan);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -150,7 +150,7 @@ static void lms_log_callback(int lvl, const char *msg)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	/* map lime specific log levels */
 | 
						/* map lime specific log levels */
 | 
				
			||||||
	static const int lvl_map[5] = {
 | 
						static const int lvl_map[5] = {
 | 
				
			||||||
		[LMS_LOG_CRITICAL] = LOGL_FATAL,
 | 
							[0] = LOGL_FATAL,
 | 
				
			||||||
		[LMS_LOG_ERROR] = LOGL_ERROR,
 | 
							[LMS_LOG_ERROR] = LOGL_ERROR,
 | 
				
			||||||
		[LMS_LOG_WARNING] = LOGL_NOTICE,
 | 
							[LMS_LOG_WARNING] = LOGL_NOTICE,
 | 
				
			||||||
		[LMS_LOG_INFO] = LOGL_INFO,
 | 
							[LMS_LOG_INFO] = LOGL_INFO,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,19 +75,18 @@ USRPDevice::USRPDevice(InterfaceType iface, const struct trx_cfg *cfg) : RadioDe
 | 
				
			|||||||
   * split sample rate Tx/Rx - 4/1 sps we need to need to
 | 
					   * split sample rate Tx/Rx - 4/1 sps we need to need to
 | 
				
			||||||
   * compensate for advance rather than delay.
 | 
					   * compensate for advance rather than delay.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  pingOffset = 272;
 | 
					  if (tx_sps == 1)
 | 
				
			||||||
 | 
					    pingOffset = 272;
 | 
				
			||||||
  /* Split SPS (4/1) unsupported on USRP1
 | 
					  else if (tx_sps == 4)
 | 
				
			||||||
   * if(tx_sps == 4 && rx_sps == 1)
 | 
					    pingOffset = 269 - 7500;
 | 
				
			||||||
   *   pingOffset = 269 - 7500;
 | 
					  else
 | 
				
			||||||
   */
 | 
					    pingOffset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SWLOOPBACK
 | 
					#ifdef SWLOOPBACK
 | 
				
			||||||
  samplePeriod = 1.0e6/actualSampleRate;
 | 
					  samplePeriod = 1.0e6/actualSampleRate;
 | 
				
			||||||
  loopbackBufferSize = 0;
 | 
					  loopbackBufferSize = 0;
 | 
				
			||||||
  gettimeofday(&lastReadTime,NULL);
 | 
					  gettimeofday(&lastReadTime,NULL);
 | 
				
			||||||
  firstRead = false;
 | 
					  firstRead = false;
 | 
				
			||||||
  pingOffset = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,7 +101,7 @@ int USRPDevice::open()
 | 
				
			|||||||
  m_uRx.reset();
 | 
					  m_uRx.reset();
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    m_uRx = usrp_standard_rx_sptr(usrp_standard_rx::make(
 | 
					    m_uRx = usrp_standard_rx_sptr(usrp_standard_rx::make(
 | 
				
			||||||
                                        0, decimRate, 1, -1,
 | 
					                                        0, decimRate * tx_sps, 1, -1,
 | 
				
			||||||
                                        usrp_standard_rx::FPGA_MODE_NORMAL,
 | 
					                                        usrp_standard_rx::FPGA_MODE_NORMAL,
 | 
				
			||||||
                                        1024, 16 * 8, rbf));
 | 
					                                        1024, 16 * 8, rbf));
 | 
				
			||||||
    m_uRx->set_fpga_master_clock_freq(masterClockRate);
 | 
					    m_uRx->set_fpga_master_clock_freq(masterClockRate);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,7 +95,7 @@ NO_UBSAN static void detect_burst_generic(const gr_complex *input, gr_complex *c
 | 
				
			|||||||
	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 (unsigned int i = 0; i < burst_size; i++)
 | 
						for (unsigned int i = 0; i < burst_size; i++)
 | 
				
			||||||
		output_binary[i] = output[i] > 0 ? -127 : 127; // pre flip bits!
 | 
							output_binary[i] = (char)(output[i] * -127); // pre flip bits!
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NO_UBSAN void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary,
 | 
					NO_UBSAN void detect_burst_nb(const gr_complex *input, gr_complex *chan_imp_resp, int burst_start, char *output_binary,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -254,7 +254,6 @@ struct blade_hw {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_DEBUG);
 | 
							bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_DEBUG);
 | 
				
			||||||
		bladerf_set_usb_reset_on_open(true);
 | 
							bladerf_set_usb_reset_on_open(true);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		blade_check(bladerf_open, &dev, "");
 | 
							blade_check(bladerf_open, &dev, "");
 | 
				
			||||||
		if (!dev) {
 | 
							if (!dev) {
 | 
				
			||||||
			std::cerr << "open failed, device missing?" << std::endl;
 | 
								std::cerr << "open failed, device missing?" << std::endl;
 | 
				
			||||||
@@ -269,8 +268,7 @@ struct blade_hw {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool is_locked;
 | 
							bool is_locked;
 | 
				
			||||||
		blade_check(bladerf_set_pll_enable, dev, true);
 | 
							blade_check(bladerf_set_pll_enable, dev, true);
 | 
				
			||||||
		uint64_t refclock = 10000000UL;
 | 
							blade_check(bladerf_set_pll_refclk, dev, 10000000UL);
 | 
				
			||||||
		blade_check(bladerf_set_pll_refclk, dev, refclock);
 | 
					 | 
				
			||||||
		for (int i = 0; i < 20; i++) {
 | 
							for (int i = 0; i < 20; i++) {
 | 
				
			||||||
			usleep(50 * 1000);
 | 
								usleep(50 * 1000);
 | 
				
			||||||
			bladerf_get_pll_lock_state(dev, &is_locked);
 | 
								bladerf_get_pll_lock_state(dev, &is_locked);
 | 
				
			||||||
@@ -429,12 +427,10 @@ struct blade_hw {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	auto get_rx_burst_handler_fn(bh_fn_t burst_handler)
 | 
						auto get_rx_burst_handler_fn(bh_fn_t burst_handler)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		using thist = decltype(this);
 | 
							auto fn = [this] {
 | 
				
			||||||
		auto fn = [](void *args) -> void * {
 | 
					 | 
				
			||||||
			thist t = reinterpret_cast<thist>(args);
 | 
					 | 
				
			||||||
			int status = 0;
 | 
								int status = 0;
 | 
				
			||||||
			if (!stop_lower_threads_flag)
 | 
								if (!stop_lower_threads_flag)
 | 
				
			||||||
				status = bladerf_stream(t->rx_stream, BLADERF_RX_X1);
 | 
									status = bladerf_stream(rx_stream, BLADERF_RX_X1);
 | 
				
			||||||
			if (status < 0)
 | 
								if (status < 0)
 | 
				
			||||||
				std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
 | 
									std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -444,12 +440,10 @@ struct blade_hw {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	auto get_tx_burst_handler_fn(bh_fn_t burst_handler)
 | 
						auto get_tx_burst_handler_fn(bh_fn_t burst_handler)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		using thist = decltype(this);
 | 
							auto fn = [this] {
 | 
				
			||||||
		auto fn = [](void *args) -> void * {
 | 
					 | 
				
			||||||
			thist t = reinterpret_cast<thist>(args);
 | 
					 | 
				
			||||||
			int status = 0;
 | 
								int status = 0;
 | 
				
			||||||
			if (!stop_lower_threads_flag)
 | 
								if (!stop_lower_threads_flag)
 | 
				
			||||||
				status = bladerf_stream(t->tx_stream, BLADERF_TX_X1);
 | 
									status = bladerf_stream(tx_stream, BLADERF_TX_X1);
 | 
				
			||||||
			if (status < 0)
 | 
								if (status < 0)
 | 
				
			||||||
				std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
 | 
									std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,8 +35,6 @@ extern "C" {
 | 
				
			|||||||
#include "sch.h"
 | 
					#include "sch.h"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "threadsched.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
dummylog ms_trx::dummy_log;
 | 
					dummylog ms_trx::dummy_log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DBGXX
 | 
					#ifdef DBGXX
 | 
				
			||||||
@@ -85,11 +83,13 @@ void ms_trx::start_lower_ms()
 | 
				
			|||||||
	if (stop_lower_threads_flag)
 | 
						if (stop_lower_threads_flag)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	auto fn = get_rx_burst_handler_fn(rx_bh());
 | 
						auto fn = get_rx_burst_handler_fn(rx_bh());
 | 
				
			||||||
	lower_rx_task = spawn_worker_thread(sched_params::thread_names::RXRUN, fn, this);
 | 
						lower_rx_task = std::thread(fn);
 | 
				
			||||||
 | 
						set_name_aff_sched(lower_rx_task.native_handle(), sched_params::thread_names::RXRUN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usleep(1000);
 | 
						usleep(1000);
 | 
				
			||||||
	auto fn2 = get_tx_burst_handler_fn(tx_bh());
 | 
						auto fn2 = get_tx_burst_handler_fn(tx_bh());
 | 
				
			||||||
	lower_tx_task = spawn_worker_thread(sched_params::thread_names::TXRUN, fn2, this);
 | 
						lower_tx_task = std::thread(fn2);
 | 
				
			||||||
 | 
						set_name_aff_sched(lower_tx_task.native_handle(), sched_params::thread_names::TXRUN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	actually_enable_streams();
 | 
						actually_enable_streams();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -105,9 +105,9 @@ void ms_trx::stop_threads()
 | 
				
			|||||||
	stop_lower_threads_flag = true;
 | 
						stop_lower_threads_flag = true;
 | 
				
			||||||
	close_device();
 | 
						close_device();
 | 
				
			||||||
	std::cerr << "dev closed..." << std::endl;
 | 
						std::cerr << "dev closed..." << std::endl;
 | 
				
			||||||
	pthread_join(lower_rx_task, nullptr);
 | 
						lower_rx_task.join();
 | 
				
			||||||
	std::cerr << "L rx dead..." << std::endl;
 | 
						std::cerr << "L rx dead..." << std::endl;
 | 
				
			||||||
	pthread_join(lower_tx_task, nullptr);
 | 
						lower_tx_task.join();
 | 
				
			||||||
	std::cerr << "L tx dead..." << std::endl;
 | 
						std::cerr << "L tx dead..." << std::endl;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -130,7 +130,7 @@ void ms_trx::submit_burst(blade_sample_type *buffer, int len, GSM::Time target)
 | 
				
			|||||||
		tosend.decTN(-diff_tn);
 | 
							tosend.decTN(-diff_tn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// in theory fn equal and tn+3 equal is also a problem...
 | 
						// in theory fn equal and tn+3 equal is also a problem...
 | 
				
			||||||
	if (diff_fn < 0 || (diff_fn == 0 && (target_tn-now_time.TN() < 3))) {
 | 
						if (diff_fn < 0 || (diff_fn == 0 && (now_time.TN() - target_tn < 1))) {
 | 
				
			||||||
		std::cerr << "## TX too late?! fn DIFF:" << diff_fn << " tn LOCAL: " << now_time.TN()
 | 
							std::cerr << "## TX too late?! fn DIFF:" << diff_fn << " tn LOCAL: " << now_time.TN()
 | 
				
			||||||
			  << " tn OTHER: " << target_tn << std::endl;
 | 
								  << " tn OTHER: " << target_tn << std::endl;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@
 | 
				
			|||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
// #include <thread>
 | 
					#include <thread>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(BUILDBLADE)
 | 
					#if defined(BUILDBLADE)
 | 
				
			||||||
#include "bladerf_specific.h"
 | 
					#include "bladerf_specific.h"
 | 
				
			||||||
@@ -42,9 +42,9 @@
 | 
				
			|||||||
#include "GSMCommon.h"
 | 
					#include "GSMCommon.h"
 | 
				
			||||||
#include "itrq.h"
 | 
					#include "itrq.h"
 | 
				
			||||||
#include "threadpool.h"
 | 
					#include "threadpool.h"
 | 
				
			||||||
#include "threadsched.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const unsigned int ONE_TS_BURST_LEN = (3 + 58 + 26 + 58 + 3 + 8.25) * 4 /*sps*/;
 | 
					const unsigned int ONE_TS_BURST_LEN = (3 + 58 + 26 + 58 + 3 + 8.25) * 4 /*sps*/;
 | 
				
			||||||
 | 
					const unsigned int NUM_RXQ_FRAMES = 1; // rx thread <-> upper rx queue
 | 
				
			||||||
const unsigned int SCH_LEN_SPS = (ONE_TS_BURST_LEN * 8 /*ts*/ * 12 /*frames*/);
 | 
					const unsigned int SCH_LEN_SPS = (ONE_TS_BURST_LEN * 8 /*ts*/ * 12 /*frames*/);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
@@ -133,7 +133,7 @@ struct one_burst {
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using rx_queue_t = spsc_cond_timeout<4, one_burst, true, false>;
 | 
					using rx_queue_t = spsc_cond_timeout<8 * NUM_RXQ_FRAMES, one_burst, true, false>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class SCH_STATE { SEARCHING, FOUND };
 | 
					enum class SCH_STATE { SEARCHING, FOUND };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -217,23 +217,43 @@ class time_keeper {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using ts_hitter_q_t = spsc_cond<64, GSM::Time, true, false>;
 | 
					static struct sched_params {
 | 
				
			||||||
 | 
						enum thread_names { U_CTL = 0, U_RX, U_TX, SCH_SEARCH, MAIN, LEAKCHECK, RXRUN, TXRUN, _THRD_NAME_COUNT };
 | 
				
			||||||
// used to globally initialize the sched/hw information
 | 
						enum target { ODROID = 0, PI4 };
 | 
				
			||||||
struct sched_hw_info {
 | 
						const char *name;
 | 
				
			||||||
	int hw_cpus;
 | 
						int core;
 | 
				
			||||||
	sched_params::target hw_target;
 | 
						int schedtype;
 | 
				
			||||||
 | 
						int prio;
 | 
				
			||||||
	sched_hw_info()
 | 
					} schdp[][sched_params::_THRD_NAME_COUNT]{
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		hw_cpus = std::thread::hardware_concurrency();
 | 
							{ "upper_ctrl", 2, SCHED_RR, sched_get_priority_max(SCHED_RR) },
 | 
				
			||||||
		hw_target = hw_cpus > 4 ? sched_params::target::ODROID : sched_params::target::PI4;
 | 
							{ "upper_rx", 2, SCHED_RR, sched_get_priority_max(SCHED_RR) - 5 },
 | 
				
			||||||
		set_sched_target(hw_target);
 | 
							{ "upper_tx", 2, SCHED_RR, sched_get_priority_max(SCHED_RR) - 1 },
 | 
				
			||||||
		std::cerr << "scheduling for: " << (hw_cpus > 4 ? "odroid" : "pi4") << std::endl;
 | 
					
 | 
				
			||||||
	}
 | 
							{ "sch_search", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
				
			||||||
 | 
							{ "main", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
				
			||||||
 | 
							{ "leakcheck", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 10 },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{ "rxrun", 4, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 2 },
 | 
				
			||||||
 | 
							{ "txrun", 5, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1 },
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							{ "upper_ctrl", 1, SCHED_RR, sched_get_priority_max(SCHED_RR) },
 | 
				
			||||||
 | 
							{ "upper_rx", 1, SCHED_RR, sched_get_priority_max(SCHED_RR) - 5 },
 | 
				
			||||||
 | 
							{ "upper_tx", 1, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1 },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{ "sch_search", 1, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
				
			||||||
 | 
							{ "main", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
				
			||||||
 | 
							{ "leakcheck", 1, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 10 },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							{ "rxrun", 2, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 2 },
 | 
				
			||||||
 | 
							{ "txrun", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1 },
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ms_trx : public BASET, public sched_hw_info {
 | 
					using ts_hitter_q_t = spsc_cond<64, GSM::Time, true, false>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ms_trx : public BASET {
 | 
				
			||||||
	using base = BASET;
 | 
						using base = BASET;
 | 
				
			||||||
	static dummylog dummy_log;
 | 
						static dummylog dummy_log;
 | 
				
			||||||
	unsigned int mTSC;
 | 
						unsigned int mTSC;
 | 
				
			||||||
@@ -241,8 +261,8 @@ struct ms_trx : public BASET, public sched_hw_info {
 | 
				
			|||||||
	int timing_advance;
 | 
						int timing_advance;
 | 
				
			||||||
	bool do_auto_gain;
 | 
						bool do_auto_gain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pthread_t lower_rx_task;
 | 
						std::thread lower_rx_task;
 | 
				
			||||||
	pthread_t lower_tx_task;
 | 
						std::thread lower_tx_task;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// provides bursts to upper rx thread
 | 
						// provides bursts to upper rx thread
 | 
				
			||||||
	rx_queue_t rxqueue;
 | 
						rx_queue_t rxqueue;
 | 
				
			||||||
@@ -258,7 +278,9 @@ struct ms_trx : public BASET, public sched_hw_info {
 | 
				
			|||||||
	int64_t first_sch_ts_start = -1;
 | 
						int64_t first_sch_ts_start = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	time_keeper timekeeper;
 | 
						time_keeper timekeeper;
 | 
				
			||||||
	single_thread_pool worker_thread; // uses base class sched target hw info
 | 
						int hw_cpus;
 | 
				
			||||||
 | 
						sched_params::target hw_target;
 | 
				
			||||||
 | 
						single_thread_pool worker_thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void start_lower_ms();
 | 
						void start_lower_ms();
 | 
				
			||||||
	std::atomic<bool> upper_is_ready;
 | 
						std::atomic<bool> upper_is_ready;
 | 
				
			||||||
@@ -280,8 +302,12 @@ struct ms_trx : public BASET, public sched_hw_info {
 | 
				
			|||||||
		: mTSC(0), mBSIC(0), timing_advance(0), do_auto_gain(false), rxqueue(),
 | 
							: mTSC(0), mBSIC(0), timing_advance(0), do_auto_gain(false), rxqueue(),
 | 
				
			||||||
		  first_sch_buf(new blade_sample_type[SCH_LEN_SPS]),
 | 
							  first_sch_buf(new blade_sample_type[SCH_LEN_SPS]),
 | 
				
			||||||
		  burst_copy_buffer(new blade_sample_type[ONE_TS_BURST_LEN]), first_sch_buf_rcv_ts(0),
 | 
							  burst_copy_buffer(new blade_sample_type[ONE_TS_BURST_LEN]), first_sch_buf_rcv_ts(0),
 | 
				
			||||||
		  rcv_done{ false }, sch_thread_done{ false }, upper_is_ready(false)
 | 
							  rcv_done{ false }, sch_thread_done{ false }, hw_cpus(std::thread::hardware_concurrency()),
 | 
				
			||||||
 | 
							  hw_target(hw_cpus > 4 ? sched_params::target::ODROID : sched_params::target::PI4),
 | 
				
			||||||
 | 
							  upper_is_ready(false)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							std::cerr << "scheduling for: " << (hw_cpus > 4 ? "odroid" : "pi4") << std::endl;
 | 
				
			||||||
 | 
							set_name_aff_sched(worker_thread.get_handle(), sched_params::thread_names::SCH_SEARCH);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	virtual ~ms_trx()
 | 
						virtual ~ms_trx()
 | 
				
			||||||
@@ -298,4 +324,73 @@ struct ms_trx : public BASET, public sched_hw_info {
 | 
				
			|||||||
		assert(val > -127 && val < 128);
 | 
							assert(val > -127 && val < 128);
 | 
				
			||||||
		timing_advance = val * 4;
 | 
							timing_advance = val * 4;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void set_name_aff_sched(sched_params::thread_names name)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							set_name_aff_sched(pthread_self(), name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void set_name_aff_sched(std::thread::native_handle_type h, sched_params::thread_names name)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto tgt = schdp[hw_target][name];
 | 
				
			||||||
 | 
							// std::cerr << "scheduling for: " << tgt.name << ":" << tgt.core << std::endl;
 | 
				
			||||||
 | 
							set_name_aff_sched(h, tgt.name, tgt.core, tgt.schedtype, tgt.prio);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using pt_sig = void *(*)(void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pthread_t spawn_worker_thread(sched_params::thread_names name, pt_sig fun, void *arg)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto tgt = schdp[hw_target][name];
 | 
				
			||||||
 | 
							// std::cerr << "scheduling for: " << tgt.name << ":" << tgt.core << " prio:" << tgt.prio << std::endl;
 | 
				
			||||||
 | 
							return do_spawn_thr(tgt.name, tgt.core, tgt.schedtype, tgt.prio, fun, arg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
						void set_name_aff_sched(std::thread::native_handle_type h, const char *name, int cpunum, int schedtype,
 | 
				
			||||||
 | 
									int prio)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							pthread_setname_np(h, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cpu_set_t cpuset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CPU_ZERO(&cpuset);
 | 
				
			||||||
 | 
							CPU_SET(cpunum, &cpuset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (pthread_setaffinity_np(h, sizeof(cpuset), &cpuset) < 0) {
 | 
				
			||||||
 | 
								std::cerr << name << " affinity: errreur! " << std::strerror(errno);
 | 
				
			||||||
 | 
								return exit(0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sched_param sch_params;
 | 
				
			||||||
 | 
							sch_params.sched_priority = prio;
 | 
				
			||||||
 | 
							if (pthread_setschedparam(h, schedtype, &sch_params) < 0) {
 | 
				
			||||||
 | 
								std::cerr << name << " sched: errreur! " << std::strerror(errno);
 | 
				
			||||||
 | 
								return exit(0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pthread_t do_spawn_thr(const char *name, int cpunum, int schedtype, int prio, pt_sig fun, void *arg)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							pthread_t thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pthread_attr_t attr;
 | 
				
			||||||
 | 
							pthread_attr_init(&attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sched_param sch_params;
 | 
				
			||||||
 | 
							sch_params.sched_priority = prio;
 | 
				
			||||||
 | 
							cpu_set_t cpuset;
 | 
				
			||||||
 | 
							CPU_ZERO(&cpuset);
 | 
				
			||||||
 | 
							CPU_SET(cpunum, &cpuset);
 | 
				
			||||||
 | 
							auto a = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
 | 
				
			||||||
 | 
							a |= pthread_attr_setschedpolicy(&attr, schedtype);
 | 
				
			||||||
 | 
							a |= pthread_attr_setschedparam(&attr, &sch_params);
 | 
				
			||||||
 | 
							a |= pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
 | 
				
			||||||
 | 
							if(a)
 | 
				
			||||||
 | 
								std::cerr << "thread arg rc:" << a << std::endl;
 | 
				
			||||||
 | 
							pthread_create(&thread, &attr, fun, arg);
 | 
				
			||||||
 | 
							pthread_setname_np(thread, name);
 | 
				
			||||||
 | 
							pthread_attr_destroy(&attr);
 | 
				
			||||||
 | 
							return thread;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,8 +19,6 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "sigProcLib.h"
 | 
					 | 
				
			||||||
#include "signalVector.h"
 | 
					 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
#include <complex>
 | 
					#include <complex>
 | 
				
			||||||
@@ -157,12 +155,12 @@ bool ms_trx::handle_sch(bool is_first_sch_acq)
 | 
				
			|||||||
	auto current_gsm_time = timekeeper.gsmtime();
 | 
						auto current_gsm_time = timekeeper.gsmtime();
 | 
				
			||||||
	const auto buf_len = is_first_sch_acq ? SCH_LEN_SPS : ONE_TS_BURST_LEN;
 | 
						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;
 | 
						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 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);
 | 
						const auto ss = reinterpret_cast<std::complex<float> *>(which_out_buffer);
 | 
				
			||||||
	std::complex<float> channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
						std::complex<float> channel_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int start;
 | 
						int start;
 | 
				
			||||||
 | 
						memset((void *)&sch_acq_buffer[0], 0, sizeof(sch_acq_buffer));
 | 
				
			||||||
	convert_and_scale(which_out_buffer, which_in_buffer, buf_len * 2, 1.f / float(rxFullScale));
 | 
						convert_and_scale(which_out_buffer, which_in_buffer, buf_len * 2, 1.f / float(rxFullScale));
 | 
				
			||||||
	if (is_first_sch_acq) {
 | 
						if (is_first_sch_acq) {
 | 
				
			||||||
		float max_corr = 0;
 | 
							float max_corr = 0;
 | 
				
			||||||
@@ -175,22 +173,9 @@ bool ms_trx::handle_sch(bool is_first_sch_acq)
 | 
				
			|||||||
	detect_burst_nb(&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);
 | 
						auto sch_decode_success = decode_sch(sch_demod_bits, is_first_sch_acq);
 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto rv = detectSCHBurst(*burst, 4, 4, corr_type, &ebp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int howmuchdelay = ebp.toa * 4;
 | 
					 | 
				
			||||||
	std::cerr << "ooffs: " << howmuchdelay << " " << std::endl;
 | 
					 | 
				
			||||||
	std::cerr << "voffs: " << start << " " << sch_decode_success << std::endl;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	if (sch_decode_success) {
 | 
						if (sch_decode_success) {
 | 
				
			||||||
		const auto ts_offset_symb = 4;
 | 
							const auto ts_offset_symb = 0;
 | 
				
			||||||
		if (is_first_sch_acq) {
 | 
							if (is_first_sch_acq) {
 | 
				
			||||||
			// update ts to first sample in sch buffer, to allow delay calc for current ts
 | 
								// 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;
 | 
								first_sch_ts_start = first_sch_buf_rcv_ts + start - (ts_offset_symb * 4) - 1;
 | 
				
			||||||
@@ -205,97 +190,6 @@ bool ms_trx::handle_sch(bool is_first_sch_acq)
 | 
				
			|||||||
		DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << start << " " << current_gsm_time.FN()
 | 
							DBGLG2() << "L SCH : \x1B[31m decode fail \033[0m @ toa:" << start << " " << current_gsm_time.FN()
 | 
				
			||||||
			 << ":" << current_gsm_time.TN() << std::endl;
 | 
								 << ":" << 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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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) {
 | 
					 | 
				
			||||||
			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);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,6 @@ void __lsan_do_recoverable_leak_check();
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ms_trxcon_if.h"
 | 
					#include "ms_trxcon_if.h"
 | 
				
			||||||
#include "ms_upper.h"
 | 
					#include "ms_upper.h"
 | 
				
			||||||
#include "threadsched.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern bool trxc_l1ctl_init(void *tallctx);
 | 
					extern bool trxc_l1ctl_init(void *tallctx);
 | 
				
			||||||
struct trxcon_inst *g_trxcon;
 | 
					struct trxcon_inst *g_trxcon;
 | 
				
			||||||
@@ -199,7 +198,6 @@ bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset)
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 1
 | 
					 | 
				
			||||||
	convert_and_scale(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
 | 
						convert_and_scale(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
						pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
				
			||||||
@@ -233,42 +231,6 @@ bool upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset)
 | 
				
			|||||||
		// 	detect_burst(ss, &chan_imp_resp2[0], dummy_burst_start, outbin);
 | 
							// 	detect_burst(ss, &chan_imp_resp2[0], dummy_burst_start, outbin);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// lower layer sch detection offset, easy to verify by just printing the detected value using both the va+sigproc code.
 | 
					 | 
				
			||||||
	convert_and_scale(ss + 16, e.burst, ONE_TS_BURST_LEN * 2, 15);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pow = energyDetect(sv, 20 * 4 /*sps*/);
 | 
					 | 
				
			||||||
	if (pow < -1) {
 | 
					 | 
				
			||||||
		LOG(ALERT) << "Received empty burst";
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	avg = sqrt(pow);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Detect normal or RACH bursts */
 | 
					 | 
				
			||||||
	CorrType type = CorrType::TSC;
 | 
					 | 
				
			||||||
	struct estim_burst_params ebp;
 | 
					 | 
				
			||||||
	auto rc = detectAnyBurst(sv, mTSC, 3, 4, type, 48, &ebp);
 | 
					 | 
				
			||||||
	if (rc > 0) {
 | 
					 | 
				
			||||||
		type = (CorrType)rc;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rc < 0) {
 | 
					 | 
				
			||||||
		std::cerr << "UR : \x1B[31m rx fail \033[0m @ toa:" << ebp.toa << " " << e.gsmts.FN() << ":"
 | 
					 | 
				
			||||||
			  << e.gsmts.TN() << std::endl;
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	SoftVector *bits = demodAnyBurst(sv, type, 4, &ebp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SoftVector::const_iterator burstItr = bits->begin();
 | 
					 | 
				
			||||||
	// invert and fix to +-127 sbits
 | 
					 | 
				
			||||||
	for (int ii = 0; ii < 148; ii++) {
 | 
					 | 
				
			||||||
		demodded_softbits[ii] = *burstItr++ > 0.0f ? -127 : 127;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	delete bits;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	RSSI = (int)floor(20.0 * log10(rxFullScale / avg));
 | 
						RSSI = (int)floor(20.0 * log10(rxFullScale / avg));
 | 
				
			||||||
	// FIXME: properly handle offset, sch/nb alignment diff? handled by lower anyway...
 | 
						// FIXME: properly handle offset, sch/nb alignment diff? handled by lower anyway...
 | 
				
			||||||
	timingOffset = (int)round(0);
 | 
						timingOffset = (int)round(0);
 | 
				
			||||||
@@ -296,7 +258,6 @@ void upper_trx::driveReceiveFIFO()
 | 
				
			|||||||
		trxcon_phyif_handle_burst_ind(g_trxcon, &bi);
 | 
							trxcon_phyif_handle_burst_ind(g_trxcon, &bi);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	burstTime.incTN(2);
 | 
					 | 
				
			||||||
	struct trxcon_phyif_rts_ind rts {
 | 
						struct trxcon_phyif_rts_ind rts {
 | 
				
			||||||
		static_cast<uint32_t>(burstTime.FN()), static_cast<uint8_t>(burstTime.TN())
 | 
							static_cast<uint32_t>(burstTime.FN()), static_cast<uint8_t>(burstTime.TN())
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
@@ -495,7 +456,7 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
		std::cerr << "Error initializing hardware, quitting.." << std::endl;
 | 
							std::cerr << "Error initializing hardware, quitting.." << std::endl;
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	set_name_aff_sched(sched_params::thread_names::MAIN);
 | 
						trx->set_name_aff_sched(sched_params::thread_names::MAIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!trxc_l1ctl_init(tall_trxcon_ctx)) {
 | 
						if (!trxc_l1ctl_init(tall_trxcon_ctx)) {
 | 
				
			||||||
		std::cerr << "Error initializing l1ctl, quitting.." << std::endl;
 | 
							std::cerr << "Error initializing l1ctl, quitting.." << std::endl;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,12 +20,13 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <thread>
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <future>
 | 
					#include <future>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <queue>
 | 
					#include <queue>
 | 
				
			||||||
#include "threadsched.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct single_thread_pool {
 | 
					struct single_thread_pool {
 | 
				
			||||||
	std::mutex m;
 | 
						std::mutex m;
 | 
				
			||||||
@@ -33,7 +34,7 @@ struct single_thread_pool {
 | 
				
			|||||||
	std::atomic<bool> stop_flag;
 | 
						std::atomic<bool> stop_flag;
 | 
				
			||||||
	std::atomic<bool> is_ready;
 | 
						std::atomic<bool> is_ready;
 | 
				
			||||||
	std::deque<std::function<void()>> wq;
 | 
						std::deque<std::function<void()>> wq;
 | 
				
			||||||
	pthread_t worker_thread;
 | 
						std::thread worker_thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template <class F>
 | 
						template <class F>
 | 
				
			||||||
	void add_task(F &&f)
 | 
						void add_task(F &&f)
 | 
				
			||||||
@@ -44,23 +45,19 @@ struct single_thread_pool {
 | 
				
			|||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	single_thread_pool() : stop_flag(false), is_ready(false)
 | 
						single_thread_pool() : stop_flag(false), is_ready(false), worker_thread(std::thread([this] { thread_loop(); }))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		worker_thread = spawn_worker_thread(
 | 
					 | 
				
			||||||
			sched_params::thread_names::SCH_SEARCH,
 | 
					 | 
				
			||||||
			[](void *args) -> void * {
 | 
					 | 
				
			||||||
				using thist = decltype(this);
 | 
					 | 
				
			||||||
				thist t = reinterpret_cast<thist>(args);
 | 
					 | 
				
			||||||
				t->thread_loop();
 | 
					 | 
				
			||||||
				return 0;
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			this);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	~single_thread_pool()
 | 
						~single_thread_pool()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		stop();
 | 
							stop();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::thread::native_handle_type get_handle()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return worker_thread.native_handle();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
	void stop()
 | 
						void stop()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -70,7 +67,7 @@ struct single_thread_pool {
 | 
				
			|||||||
			stop_flag = true;
 | 
								stop_flag = true;
 | 
				
			||||||
			cv.notify_one();
 | 
								cv.notify_one();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pthread_join(worker_thread, nullptr);
 | 
							worker_thread.join();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void thread_loop()
 | 
						void thread_loop()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,104 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Author: Eric Wild <ewild@sysmocom.de>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 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 <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <cerrno>
 | 
					 | 
				
			||||||
#include <cstdlib>
 | 
					 | 
				
			||||||
#include <cstring>
 | 
					 | 
				
			||||||
#include <iostream>
 | 
					 | 
				
			||||||
#include <thread>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern "C" {
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "threadsched.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
sched_params::target scheduling_target;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_sched_target(sched_params::target t)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	scheduling_target = t;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_name_aff_sched(std::thread::native_handle_type h, const char *name, int cpunum, int schedtype, int prio)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	pthread_setname_np(h, name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cpu_set_t cpuset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	CPU_ZERO(&cpuset);
 | 
					 | 
				
			||||||
	CPU_SET(cpunum, &cpuset);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pthread_setaffinity_np(h, sizeof(cpuset), &cpuset) < 0) {
 | 
					 | 
				
			||||||
		std::cerr << name << " affinity: errreur! " << std::strerror(errno);
 | 
					 | 
				
			||||||
		return exit(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sched_param sch_params;
 | 
					 | 
				
			||||||
	sch_params.sched_priority = prio;
 | 
					 | 
				
			||||||
	if (pthread_setschedparam(h, schedtype, &sch_params) < 0) {
 | 
					 | 
				
			||||||
		std::cerr << name << " sched: errreur! " << std::strerror(errno);
 | 
					 | 
				
			||||||
		return exit(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static pthread_t do_spawn_thr(const char *name, int cpunum, int schedtype, int prio, worker_func_sig fun, void *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	pthread_t thread;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pthread_attr_t attr;
 | 
					 | 
				
			||||||
	pthread_attr_init(&attr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sched_param sch_params;
 | 
					 | 
				
			||||||
	sch_params.sched_priority = prio;
 | 
					 | 
				
			||||||
	cpu_set_t cpuset;
 | 
					 | 
				
			||||||
	CPU_ZERO(&cpuset);
 | 
					 | 
				
			||||||
	CPU_SET(cpunum, &cpuset);
 | 
					 | 
				
			||||||
	auto a = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
 | 
					 | 
				
			||||||
	a |= pthread_attr_setschedpolicy(&attr, schedtype);
 | 
					 | 
				
			||||||
	a |= pthread_attr_setschedparam(&attr, &sch_params);
 | 
					 | 
				
			||||||
	a |= pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
 | 
					 | 
				
			||||||
	if (a)
 | 
					 | 
				
			||||||
		std::cerr << "thread arg rc:" << a << std::endl;
 | 
					 | 
				
			||||||
	pthread_create(&thread, &attr, fun, arg);
 | 
					 | 
				
			||||||
	pthread_setname_np(thread, name);
 | 
					 | 
				
			||||||
	pthread_attr_destroy(&attr);
 | 
					 | 
				
			||||||
	return thread;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_name_aff_sched(std::thread::native_handle_type h, sched_params::thread_names name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto tgt = schdp[scheduling_target][name];
 | 
					 | 
				
			||||||
	// std::cerr << "scheduling for: " << tgt.name << ":" << tgt.core << std::endl;
 | 
					 | 
				
			||||||
	set_name_aff_sched(h, tgt.name, tgt.core, tgt.schedtype, tgt.prio);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_name_aff_sched(sched_params::thread_names name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	set_name_aff_sched(pthread_self(), name);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pthread_t spawn_worker_thread(sched_params::thread_names name, worker_func_sig fun, void *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto tgt = schdp[scheduling_target][name];
 | 
					 | 
				
			||||||
	// std::cerr << "scheduling for: " << tgt.name << ":" << tgt.core << " prio:" << tgt.prio << std::endl;
 | 
					 | 
				
			||||||
	return do_spawn_thr(tgt.name, tgt.core, tgt.schedtype, tgt.prio, fun, arg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,68 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Author: Eric Wild <ewild@sysmocom.de>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 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 <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern "C" {
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
#include <sched.h>
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct sched_params {
 | 
					 | 
				
			||||||
	enum thread_names { U_CTL = 0, U_RX, U_TX, SCH_SEARCH, MAIN, LEAKCHECK, RXRUN, TXRUN, _THRD_NAME_COUNT };
 | 
					 | 
				
			||||||
	enum target { ODROID = 0, PI4 };
 | 
					 | 
				
			||||||
	const char *name;
 | 
					 | 
				
			||||||
	int core;
 | 
					 | 
				
			||||||
	int schedtype;
 | 
					 | 
				
			||||||
	int prio;
 | 
					 | 
				
			||||||
} schdp[][sched_params::_THRD_NAME_COUNT]{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		{ "upper_ctrl", 2, SCHED_RR, sched_get_priority_max(SCHED_RR) },
 | 
					 | 
				
			||||||
		{ "upper_rx", 2, SCHED_RR, sched_get_priority_max(SCHED_RR) - 5 },
 | 
					 | 
				
			||||||
		{ "upper_tx", 2, SCHED_RR, sched_get_priority_max(SCHED_RR) - 1 },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{ "sch_search", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
					 | 
				
			||||||
		{ "main", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
					 | 
				
			||||||
		{ "leakcheck", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 10 },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{ "rxrun", 4, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 2 },
 | 
					 | 
				
			||||||
		{ "txrun", 5, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1 },
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		{ "upper_ctrl", 1, SCHED_RR, sched_get_priority_max(SCHED_RR) },
 | 
					 | 
				
			||||||
		{ "upper_rx", 1, SCHED_RR, sched_get_priority_max(SCHED_RR) - 5 },
 | 
					 | 
				
			||||||
		{ "upper_tx", 1, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1 },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{ "sch_search", 1, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
					 | 
				
			||||||
		{ "main", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 5 },
 | 
					 | 
				
			||||||
		{ "leakcheck", 1, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 10 },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{ "rxrun", 2, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 2 },
 | 
					 | 
				
			||||||
		{ "txrun", 3, SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1 },
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_sched_target(sched_params::target t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using worker_func_sig = void *(*)(void *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_name_aff_sched(sched_params::thread_names name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pthread_t spawn_worker_thread(sched_params::thread_names name, worker_func_sig fun, void *arg);
 | 
					 | 
				
			||||||
@@ -231,29 +231,24 @@ struct uhd_hw {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	auto get_rx_burst_handler_fn(bh_fn_t burst_handler)
 | 
						auto get_rx_burst_handler_fn(bh_fn_t burst_handler)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// C cb -> ghetto closure capture, which is fine, the args never change.
 | 
							auto fn = [this, burst_handler] {
 | 
				
			||||||
		static auto rx_burst_cap_this = this;
 | 
					 | 
				
			||||||
		static auto rx_burst_cap_bh = burst_handler;
 | 
					 | 
				
			||||||
		auto fn = [](void *args) -> void * {
 | 
					 | 
				
			||||||
			pthread_setname_np(pthread_self(), "rxrun");
 | 
								pthread_setname_np(pthread_self(), "rxrun");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
 | 
								uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
 | 
				
			||||||
			stream_cmd.stream_now = true;
 | 
								stream_cmd.stream_now = true;
 | 
				
			||||||
			stream_cmd.time_spec = uhd::time_spec_t();
 | 
								stream_cmd.time_spec = uhd::time_spec_t();
 | 
				
			||||||
			rx_burst_cap_this->rx_stream->issue_stream_cmd(stream_cmd);
 | 
								rx_stream->issue_stream_cmd(stream_cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			while (!rx_burst_cap_this->stop_lower_threads_flag) {
 | 
								while (!stop_lower_threads_flag) {
 | 
				
			||||||
				rx_burst_cap_this->rx_cb(rx_burst_cap_bh);
 | 
									rx_cb(burst_handler);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		return fn;
 | 
							return fn;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto get_tx_burst_handler_fn(bh_fn_t burst_handler)
 | 
						auto get_tx_burst_handler_fn(bh_fn_t burst_handler)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto fn = [](void *args) -> void * {
 | 
							auto fn = [] {
 | 
				
			||||||
			// dummy
 | 
								// dummy
 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		return fn;
 | 
							return fn;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -645,7 +645,6 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	osmo_init_logging2(tall_trx_ctx, &log_info);
 | 
						osmo_init_logging2(tall_trx_ctx, &log_info);
 | 
				
			||||||
	log_enable_multithread();
 | 
						log_enable_multithread();
 | 
				
			||||||
	log_cache_enable();
 | 
					 | 
				
			||||||
	osmo_stats_init(tall_trx_ctx);
 | 
						osmo_stats_init(tall_trx_ctx);
 | 
				
			||||||
	vty_init(&g_vty_info);
 | 
						vty_init(&g_vty_info);
 | 
				
			||||||
	logging_vty_add_cmds();
 | 
						logging_vty_add_cmds();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,8 +129,6 @@ struct PulseSequence {
 | 
				
			|||||||
static CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 | 
					static CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 | 
				
			||||||
static CorrelationSequence *gEdgeMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 | 
					static CorrelationSequence *gEdgeMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 | 
				
			||||||
static CorrelationSequence *gRACHSequences[] = {NULL,NULL,NULL};
 | 
					static CorrelationSequence *gRACHSequences[] = {NULL,NULL,NULL};
 | 
				
			||||||
static CorrelationSequence *gSCHSequence = NULL;
 | 
					 | 
				
			||||||
static CorrelationSequence *gDummySequence = NULL;
 | 
					 | 
				
			||||||
static PulseSequence *GSMPulse1 = NULL;
 | 
					static PulseSequence *GSMPulse1 = NULL;
 | 
				
			||||||
static PulseSequence *GSMPulse4 = NULL;
 | 
					static PulseSequence *GSMPulse4 = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -153,12 +151,6 @@ void sigProcLibDestroy()
 | 
				
			|||||||
    gRACHSequences[i] = NULL;
 | 
					    gRACHSequences[i] = NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delete gSCHSequence;
 | 
					 | 
				
			||||||
  gSCHSequence = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete gDummySequence;
 | 
					 | 
				
			||||||
  gDummySequence = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete GMSKRotation1;
 | 
					  delete GMSKRotation1;
 | 
				
			||||||
  delete GMSKReverseRotation1;
 | 
					  delete GMSKReverseRotation1;
 | 
				
			||||||
  delete GMSKRotation4;
 | 
					  delete GMSKRotation4;
 | 
				
			||||||
@@ -323,7 +315,6 @@ static signalVector *convolve(const signalVector *x, const signalVector *h,
 | 
				
			|||||||
    append = true;
 | 
					    append = true;
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case CUSTOM:
 | 
					  case CUSTOM:
 | 
				
			||||||
  // FIXME: x->getstart?
 | 
					 | 
				
			||||||
    if (start < h->size() - 1) {
 | 
					    if (start < h->size() - 1) {
 | 
				
			||||||
      head = h->size() - start;
 | 
					      head = h->size() - start;
 | 
				
			||||||
      append = true;
 | 
					      append = true;
 | 
				
			||||||
@@ -1298,77 +1289,6 @@ release:
 | 
				
			|||||||
  return status;
 | 
					  return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool generateDummyMidamble(int sps)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool status = true;
 | 
					 | 
				
			||||||
  float toa;
 | 
					 | 
				
			||||||
  complex *data = NULL;
 | 
					 | 
				
			||||||
  signalVector *autocorr = NULL, *midamble = NULL;
 | 
					 | 
				
			||||||
  signalVector *midMidamble = NULL, *_midMidamble = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete gDummySequence;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Use middle 16 bits of each TSC. Correlation sequence is not pulse shaped */
 | 
					 | 
				
			||||||
  midMidamble = modulateBurst(gDummyBurstTSC.segment(5,16), 0, sps, true);
 | 
					 | 
				
			||||||
  if (!midMidamble)
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Simulated receive sequence is pulse shaped */
 | 
					 | 
				
			||||||
  midamble = modulateBurst(gDummyBurstTSC, 0, sps, false);
 | 
					 | 
				
			||||||
  if (!midamble) {
 | 
					 | 
				
			||||||
    status = false;
 | 
					 | 
				
			||||||
    goto release;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // NOTE: Because ideal TSC 16-bit midamble is 66 symbols into burst,
 | 
					 | 
				
			||||||
  //       the ideal TSC has an + 180 degree phase shift,
 | 
					 | 
				
			||||||
  //       due to the pi/2 frequency shift, that
 | 
					 | 
				
			||||||
  //       needs to be accounted for.
 | 
					 | 
				
			||||||
  //       26-midamble is 61 symbols into burst, has +90 degree phase shift.
 | 
					 | 
				
			||||||
  scaleVector(*midMidamble, complex(-1.0, 0.0));
 | 
					 | 
				
			||||||
  scaleVector(*midamble, complex(0.0, 1.0));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  conjugateVector(*midMidamble);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* For SSE alignment, reallocate the midamble sequence on 16-byte boundary */
 | 
					 | 
				
			||||||
  data = (complex *) convolve_h_alloc(midMidamble->size());
 | 
					 | 
				
			||||||
  _midMidamble = new signalVector(data, 0, midMidamble->size(), convolve_h_alloc, free);
 | 
					 | 
				
			||||||
  _midMidamble->setAligned(true);
 | 
					 | 
				
			||||||
  midMidamble->copyTo(*_midMidamble);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  autocorr = convolve(midamble, _midMidamble, NULL, NO_DELAY);
 | 
					 | 
				
			||||||
  if (!autocorr) {
 | 
					 | 
				
			||||||
    status = false;
 | 
					 | 
				
			||||||
    goto release;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  gDummySequence = new CorrelationSequence;
 | 
					 | 
				
			||||||
  gDummySequence->sequence = _midMidamble;
 | 
					 | 
				
			||||||
  gDummySequence->gain = peakDetect(*autocorr, &toa, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* For 1 sps only
 | 
					 | 
				
			||||||
   *     (Half of correlation length - 1) + midpoint of pulse shape + remainder
 | 
					 | 
				
			||||||
   *     13.5 = (16 / 2 - 1) + 1.5 + (26 - 10) / 2
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  if (sps == 1)
 | 
					 | 
				
			||||||
    gDummySequence->toa = toa - 13.5;
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    gDummySequence->toa = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
release:
 | 
					 | 
				
			||||||
  delete autocorr;
 | 
					 | 
				
			||||||
  delete midamble;
 | 
					 | 
				
			||||||
  delete midMidamble;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!status) {
 | 
					 | 
				
			||||||
    delete _midMidamble;
 | 
					 | 
				
			||||||
    free(data);
 | 
					 | 
				
			||||||
    gDummySequence = NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static CorrelationSequence *generateEdgeMidamble(int tsc)
 | 
					static CorrelationSequence *generateEdgeMidamble(int tsc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  complex *data = NULL;
 | 
					  complex *data = NULL;
 | 
				
			||||||
@@ -1464,69 +1384,6 @@ release:
 | 
				
			|||||||
  return status;
 | 
					  return status;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool generateSCHSequence(int sps)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool status = true;
 | 
					 | 
				
			||||||
  float toa;
 | 
					 | 
				
			||||||
  complex *data = NULL;
 | 
					 | 
				
			||||||
  signalVector *autocorr = NULL;
 | 
					 | 
				
			||||||
  signalVector *seq0 = NULL, *seq1 = NULL, *_seq1 = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete gSCHSequence;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  seq0 = modulateBurst(gSCHSynchSequence, 0, sps, false);
 | 
					 | 
				
			||||||
  if (!seq0)
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  seq1 = modulateBurst(gSCHSynchSequence, 0, sps, true);
 | 
					 | 
				
			||||||
  if (!seq1) {
 | 
					 | 
				
			||||||
    status = false;
 | 
					 | 
				
			||||||
    goto release;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  conjugateVector(*seq1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* For SSE alignment, reallocate the midamble sequence on 16-byte boundary */
 | 
					 | 
				
			||||||
  data = (complex *) convolve_h_alloc(seq1->size());
 | 
					 | 
				
			||||||
  _seq1 = new signalVector(data, 0, seq1->size(), convolve_h_alloc, free);
 | 
					 | 
				
			||||||
  _seq1->setAligned(true);
 | 
					 | 
				
			||||||
  seq1->copyTo(*_seq1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  autocorr = convolve(seq0, _seq1, autocorr, NO_DELAY);
 | 
					 | 
				
			||||||
  if (!autocorr) {
 | 
					 | 
				
			||||||
    status = false;
 | 
					 | 
				
			||||||
    goto release;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  gSCHSequence = new CorrelationSequence;
 | 
					 | 
				
			||||||
  gSCHSequence->sequence = _seq1;
 | 
					 | 
				
			||||||
  gSCHSequence->buffer = data;
 | 
					 | 
				
			||||||
  gSCHSequence->gain = peakDetect(*autocorr, &toa, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* For 1 sps only
 | 
					 | 
				
			||||||
   *     (Half of correlation length - 1) + midpoint of pulse shaping filer
 | 
					 | 
				
			||||||
   *     20.5 = (64 / 2 - 1) + 1.5
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  if (sps == 1)
 | 
					 | 
				
			||||||
    gSCHSequence->toa = toa - 32.5;
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    gSCHSequence->toa = 0.0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
release:
 | 
					 | 
				
			||||||
  delete autocorr;
 | 
					 | 
				
			||||||
  delete seq0;
 | 
					 | 
				
			||||||
  delete seq1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!status) {
 | 
					 | 
				
			||||||
    delete _seq1;
 | 
					 | 
				
			||||||
    free(data);
 | 
					 | 
				
			||||||
    gSCHSequence = NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return status;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Peak-to-average computation +/- range from peak in symbols
 | 
					 * Peak-to-average computation +/- range from peak in symbols
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -1584,15 +1441,14 @@ float energyDetect(const signalVector &rxBurst, unsigned windowLength)
 | 
				
			|||||||
  return energy/windowLength;
 | 
					  return energy/windowLength;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static signalVector *downsampleBurst(const signalVector &burst, int in_len = DOWNSAMPLE_IN_LEN,
 | 
					static signalVector *downsampleBurst(const signalVector &burst)
 | 
				
			||||||
				     int out_len = DOWNSAMPLE_OUT_LEN)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  signalVector in(in_len, dnsampler->len());
 | 
					  signalVector in(DOWNSAMPLE_IN_LEN, dnsampler->len());
 | 
				
			||||||
  // gSCHSequence->sequence->size(), ensure next conv has no realloc
 | 
					  signalVector *out = new signalVector(DOWNSAMPLE_OUT_LEN);
 | 
				
			||||||
  signalVector *out = new signalVector(out_len, 64);
 | 
					  burst.copyToSegment(in, 0, DOWNSAMPLE_IN_LEN);
 | 
				
			||||||
  burst.copyToSegment(in, 0, in_len);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (dnsampler->rotate((float *)in.begin(), in_len, (float *)out->begin(), out_len) < 0) {
 | 
					  if (dnsampler->rotate((float *) in.begin(), DOWNSAMPLE_IN_LEN,
 | 
				
			||||||
 | 
					                        (float *) out->begin(), DOWNSAMPLE_OUT_LEN) < 0) {
 | 
				
			||||||
    delete out;
 | 
					    delete out;
 | 
				
			||||||
    out = NULL;
 | 
					    out = NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -1613,12 +1469,6 @@ static float computeCI(const signalVector *burst, const CorrelationSequence *syn
 | 
				
			|||||||
  /* Integer position where the sequence starts */
 | 
					  /* Integer position where the sequence starts */
 | 
				
			||||||
  const int ps = start + 1 - N + (int)roundf(toa);
 | 
					  const int ps = start + 1 - N + (int)roundf(toa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(ps < 0) // might be -22 for toa 40 with N=64, if off by a lot during sch ms sync
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (ps + N > (int)burst->size())
 | 
					 | 
				
			||||||
	  return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Estimate Signal power */
 | 
					  /* Estimate Signal power */
 | 
				
			||||||
  S = 0.0f;
 | 
					  S = 0.0f;
 | 
				
			||||||
  for (int i=0, j=ps; i<(int)N; i++,j++)
 | 
					  for (int i=0, j=ps; i<(int)N; i++,j++)
 | 
				
			||||||
@@ -1802,80 +1652,6 @@ static int detectRACHBurst(const signalVector &burst, float threshold, int sps,
 | 
				
			|||||||
  return rc;
 | 
					  return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int detectSCHBurst(signalVector &burst,
 | 
					 | 
				
			||||||
		    float thresh,
 | 
					 | 
				
			||||||
		    int sps,
 | 
					 | 
				
			||||||
        sch_detect_type state, struct estim_burst_params *ebp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  int rc, start, target, head, tail, len;
 | 
					 | 
				
			||||||
  complex _amp;
 | 
					 | 
				
			||||||
  CorrelationSequence *sync;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ((sps != 1) && (sps != 4))
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  target = 3 + 39 + 64;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  switch (state) {
 | 
					 | 
				
			||||||
  case sch_detect_type::SCH_DETECT_NARROW:
 | 
					 | 
				
			||||||
    head = 4;
 | 
					 | 
				
			||||||
    tail = 4;
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
  case sch_detect_type::SCH_DETECT_BUFFER:
 | 
					 | 
				
			||||||
	  target = 1;
 | 
					 | 
				
			||||||
	  head = 0;
 | 
					 | 
				
			||||||
	  tail = (12 * 8 * 625) / 4; // 12 frames, downsampled /4 to 1 sps
 | 
					 | 
				
			||||||
	  break;
 | 
					 | 
				
			||||||
  case sch_detect_type::SCH_DETECT_FULL:
 | 
					 | 
				
			||||||
  default:
 | 
					 | 
				
			||||||
    head = target - 1;
 | 
					 | 
				
			||||||
    tail = 39 + 3 + 9;
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  start = (target - head) * 1 - 1;
 | 
					 | 
				
			||||||
  len = (head + tail) * 1;
 | 
					 | 
				
			||||||
  sync = gSCHSequence;
 | 
					 | 
				
			||||||
  signalVector corr(len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  signalVector *dec = downsampleBurst(burst, len * 4, len);
 | 
					 | 
				
			||||||
  rc = detectBurst(*dec, corr, sync, thresh, 1, start, len, ebp);
 | 
					 | 
				
			||||||
  delete dec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (rc < 0) {
 | 
					 | 
				
			||||||
    return -1;
 | 
					 | 
				
			||||||
  } else if (!rc) {
 | 
					 | 
				
			||||||
      ebp->amp = 0.0f;
 | 
					 | 
				
			||||||
      ebp->toa = 0.0f;
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (state == sch_detect_type::SCH_DETECT_BUFFER)
 | 
					 | 
				
			||||||
	  ebp->toa = ebp->toa - (3 + 39 + 64);
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
	  /* Subtract forward search bits from delay */
 | 
					 | 
				
			||||||
	  ebp->toa = ebp->toa - head;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return rc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int detectDummyBurst(const signalVector &burst, float threshold,
 | 
					 | 
				
			||||||
                               int sps, unsigned max_toa, struct estim_burst_params *ebp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  int rc, target, head, tail;
 | 
					 | 
				
			||||||
  CorrelationSequence *sync;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  target = 3 + 58 + 16 + 5;
 | 
					 | 
				
			||||||
  head = 10;
 | 
					 | 
				
			||||||
  tail = 6 + max_toa;
 | 
					 | 
				
			||||||
  sync = gDummySequence;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ebp->tsc = 0;
 | 
					 | 
				
			||||||
  rc = detectGeneralBurst(burst, threshold, sps, target, head, tail, sync, ebp);
 | 
					 | 
				
			||||||
  return rc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Normal burst detection
 | 
					 * Normal burst detection
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -1894,7 +1670,7 @@ static int analyzeTrafficBurst(const signalVector &burst, unsigned tsc, float th
 | 
				
			|||||||
    return -SIGERR_UNSUPPORTED;
 | 
					    return -SIGERR_UNSUPPORTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  target = 3 + 58 + 16 + 5;
 | 
					  target = 3 + 58 + 16 + 5;
 | 
				
			||||||
  head = 10;
 | 
					  head = 6;
 | 
				
			||||||
  tail = 6 + max_toa;
 | 
					  tail = 6 + max_toa;
 | 
				
			||||||
  sync = gMidambles[tsc];
 | 
					  sync = gMidambles[tsc];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1943,9 +1719,6 @@ int detectAnyBurst(const signalVector &burst, unsigned tsc, float threshold,
 | 
				
			|||||||
  case RACH:
 | 
					  case RACH:
 | 
				
			||||||
    rc = detectRACHBurst(burst, threshold, sps, max_toa, type == EXT_RACH, ebp);
 | 
					    rc = detectRACHBurst(burst, threshold, sps, max_toa, type == EXT_RACH, ebp);
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case IDLE:
 | 
					 | 
				
			||||||
    rc = detectDummyBurst(burst, threshold, sps, max_toa, ebp);
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
  default:
 | 
					  default:
 | 
				
			||||||
    LOG(ERR) << "Invalid correlation type";
 | 
					    LOG(ERR) << "Invalid correlation type";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -2148,9 +1921,6 @@ bool sigProcLibSetup()
 | 
				
			|||||||
  generateRACHSequence(&gRACHSequences[1], gRACHSynchSequenceTS1, 1);
 | 
					  generateRACHSequence(&gRACHSequences[1], gRACHSynchSequenceTS1, 1);
 | 
				
			||||||
  generateRACHSequence(&gRACHSequences[2], gRACHSynchSequenceTS2, 1);
 | 
					  generateRACHSequence(&gRACHSequences[2], gRACHSynchSequenceTS2, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  generateSCHSequence(1);
 | 
					 | 
				
			||||||
  generateDummyMidamble(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (int tsc = 0; tsc < 8; tsc++) {
 | 
					  for (int tsc = 0; tsc < 8; tsc++) {
 | 
				
			||||||
    generateMidamble(1, tsc);
 | 
					    generateMidamble(1, tsc);
 | 
				
			||||||
    gEdgeMidambles[tsc] = generateEdgeMidamble(tsc);
 | 
					    gEdgeMidambles[tsc] = generateEdgeMidamble(tsc);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,6 @@ enum CorrType{
 | 
				
			|||||||
  TSC,         ///< timeslot should contain a normal burst
 | 
					  TSC,         ///< timeslot should contain a normal burst
 | 
				
			||||||
  EXT_RACH,    ///< timeslot should contain an extended access burst
 | 
					  EXT_RACH,    ///< timeslot should contain an extended access burst
 | 
				
			||||||
  RACH,        ///< timeslot should contain an access burst
 | 
					  RACH,        ///< timeslot should contain an access burst
 | 
				
			||||||
  SCH,
 | 
					 | 
				
			||||||
  EDGE,        ///< timeslot should contain an EDGE burst
 | 
					  EDGE,        ///< timeslot should contain an EDGE burst
 | 
				
			||||||
  IDLE         ///< timeslot is an idle (or dummy) burst
 | 
					  IDLE         ///< timeslot is an idle (or dummy) burst
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -94,8 +93,6 @@ signalVector *generateDummyBurst(int sps, int tn);
 | 
				
			|||||||
void scaleVector(signalVector &x,
 | 
					void scaleVector(signalVector &x,
 | 
				
			||||||
                 complex scale);
 | 
					                 complex scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signalVector *delayVector(const signalVector *in, signalVector *out, float delay);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
        Rough energy estimator.
 | 
					        Rough energy estimator.
 | 
				
			||||||
        @param rxBurst A GSM burst.
 | 
					        @param rxBurst A GSM burst.
 | 
				
			||||||
@@ -136,17 +133,6 @@ int detectAnyBurst(const signalVector &burst,
 | 
				
			|||||||
                   unsigned max_toa,
 | 
					                   unsigned max_toa,
 | 
				
			||||||
                   struct estim_burst_params *ebp);
 | 
					                   struct estim_burst_params *ebp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class sch_detect_type {
 | 
					 | 
				
			||||||
	SCH_DETECT_FULL,
 | 
					 | 
				
			||||||
	SCH_DETECT_NARROW,
 | 
					 | 
				
			||||||
	SCH_DETECT_BUFFER,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int detectSCHBurst(signalVector &rxBurst,
 | 
					 | 
				
			||||||
                    float detectThreshold,
 | 
					 | 
				
			||||||
                    int sps,
 | 
					 | 
				
			||||||
                    sch_detect_type state, struct estim_burst_params *ebp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Demodulate burst basde on type and output soft bits */
 | 
					/** Demodulate burst basde on type and output soft bits */
 | 
				
			||||||
SoftVector *demodAnyBurst(const signalVector &burst, CorrType type,
 | 
					SoftVector *demodAnyBurst(const signalVector &burst, CorrType type,
 | 
				
			||||||
                          int sps, struct estim_burst_params *ebp);
 | 
					                          int sps, struct estim_burst_params *ebp);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								configure.ac
									
									
									
									
									
								
							@@ -82,10 +82,10 @@ AC_TYPE_SIZE_T
 | 
				
			|||||||
AC_HEADER_TIME
 | 
					AC_HEADER_TIME
 | 
				
			||||||
AC_C_BIGENDIAN
 | 
					AC_C_BIGENDIAN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.10.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 1.10.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding >= 1.9.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AC_ARG_ENABLE(sanitize,
 | 
					AC_ARG_ENABLE(sanitize,
 | 
				
			||||||
	[AS_HELP_STRING(
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
@@ -240,6 +240,7 @@ AS_IF([test "x$with_sse" != "xno"], [
 | 
				
			|||||||
    AM_CONDITIONAL(HAVE_SSE4_1, false)
 | 
					    AM_CONDITIONAL(HAVE_SSE4_1, false)
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl Check if the compiler supports specified GCC's built-in function
 | 
				
			||||||
AC_DEFUN([CHECK_BUILTIN_SUPPORT], [
 | 
					AC_DEFUN([CHECK_BUILTIN_SUPPORT], [
 | 
				
			||||||
  AC_CACHE_CHECK(
 | 
					  AC_CACHE_CHECK(
 | 
				
			||||||
    [whether ${CC} has $1 built-in],
 | 
					    [whether ${CC} has $1 built-in],
 | 
				
			||||||
@@ -373,11 +374,11 @@ AC_CONFIG_FILES([\
 | 
				
			|||||||
    tests/CommonLibs/Makefile \
 | 
					    tests/CommonLibs/Makefile \
 | 
				
			||||||
    tests/Transceiver52M/Makefile \
 | 
					    tests/Transceiver52M/Makefile \
 | 
				
			||||||
    utils/Makefile \
 | 
					    utils/Makefile \
 | 
				
			||||||
    utils/va-test/Makefile \
 | 
					 | 
				
			||||||
    doc/Makefile \
 | 
					    doc/Makefile \
 | 
				
			||||||
    doc/examples/Makefile \
 | 
					    doc/examples/Makefile \
 | 
				
			||||||
    contrib/Makefile \
 | 
					    contrib/Makefile \
 | 
				
			||||||
    contrib/systemd/Makefile \
 | 
					    contrib/systemd/Makefile \
 | 
				
			||||||
    doc/manuals/Makefile \
 | 
					    doc/manuals/Makefile \
 | 
				
			||||||
 | 
					    contrib/osmo-trx.spec \
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
AC_OUTPUT
 | 
					AC_OUTPUT
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,19 +9,60 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
set -ex
 | 
					set -ex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
case "$INSTR" in
 | 
					substr() { [ -z "${2##*$1*}" ]; }
 | 
				
			||||||
	"--with-neon"*)
 | 
					
 | 
				
			||||||
		case "$(arch)" in
 | 
					#apt-get install qemu qemu-user-static qemu-system-arm debootstrap fakeroot proot
 | 
				
			||||||
			arm*)
 | 
					mychroot_nocwd() {
 | 
				
			||||||
				;;
 | 
					        # LC_ALL + LANGUAGE set to avoid lots of print errors due to locale not being set inside container
 | 
				
			||||||
			*)
 | 
					        # PATH is needed to be able to reach binaries like ldconfig without logging in to root, which adds the paths to PATH.
 | 
				
			||||||
				set +x
 | 
					        # PROOT_NO_SECCOMP is required due to proot bug #106
 | 
				
			||||||
				echo "ERROR: trying to build with INSTR=$INSTR but not running on a 32-bit arm machine! (arch=$(arch))"
 | 
					        LC_ALL=C LANGUAGE=C PATH="$PATH:/usr/sbin:/sbin" PROOT_NO_SECCOMP=1 proot -r "$ROOTFS" -w / -b /proc --root-id -q qemu-arm-static "$@"
 | 
				
			||||||
				exit 1
 | 
					}
 | 
				
			||||||
				;;
 | 
					
 | 
				
			||||||
		esac
 | 
					mychroot() {
 | 
				
			||||||
		;;
 | 
					        mychroot_nocwd -w / "$@"
 | 
				
			||||||
esac
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "${INSIDE_CHROOT}" ]; then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Only use ARM chroot if host is not ARM and the target is ARM:
 | 
				
			||||||
 | 
					        if ! $(substr "arm" "$(uname -m)") && [ "x${INSTR}" = "x--with-neon" -o "x${INSTR}" = "x--with-neon-vfpv4" ]; then
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                OSMOTRX_DIR="$PWD" # we assume we are called as contrib/jenkins.sh
 | 
				
			||||||
 | 
					                ROOTFS_PREFIX="${ROOTFS_PREFIX:-$HOME}"
 | 
				
			||||||
 | 
					                ROOTFS="${ROOTFS_PREFIX}/qemu-img"
 | 
				
			||||||
 | 
					                mkdir -p "${ROOTFS_PREFIX}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # Prepare chroot:
 | 
				
			||||||
 | 
					                if [ ! -d "$ROOTFS" ]; then
 | 
				
			||||||
 | 
					                        mkdir -p "$ROOTFS"
 | 
				
			||||||
 | 
					                        if [ "x${USE_DEBOOTSTRAP}" = "x1" ]; then
 | 
				
			||||||
 | 
					                                fakeroot qemu-debootstrap --foreign --include="linux-image-armmp-lpae" --arch=armhf stretch "$ROOTFS" http://ftp.de.debian.org/debian/
 | 
				
			||||||
 | 
					                                # Hack to avoid debootstrap trying to mount /proc, as it will fail with "no permissions" and anyway proot takes care of it:
 | 
				
			||||||
 | 
					                                sed -i "s/setup_proc//g" "$ROOTFS/debootstrap/suite-script"
 | 
				
			||||||
 | 
					                                mychroot /debootstrap/debootstrap --second-stage --verbose http://ftp.de.debian.org/debian/
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                                YESTERDAY=$(python -c 'import datetime ; print((datetime.datetime.now() - datetime.timedelta(days=1)).strftime("%Y%m%d"))')
 | 
				
			||||||
 | 
					                                wget -nc -q "https://uk.images.linuxcontainers.org/images/debian/stretch/armhf/default/${YESTERDAY}_22:42/rootfs.tar.xz"
 | 
				
			||||||
 | 
					                                tar -xf rootfs.tar.xz -C "$ROOTFS/" || true
 | 
				
			||||||
 | 
					                                echo "nameserver 8.8.8.8" > "$ROOTFS/etc/resolv.conf"
 | 
				
			||||||
 | 
					                        fi
 | 
				
			||||||
 | 
					                        mychroot -b /dev apt-get update
 | 
				
			||||||
 | 
					                        mychroot apt-get -y install build-essential dh-autoreconf pkg-config libuhd-dev libusb-1.0-0-dev libusb-dev git libtalloc-dev libgnutls28-dev stow
 | 
				
			||||||
 | 
					                fi
 | 
				
			||||||
 | 
					                # Run jenkins.sh inside the chroot:
 | 
				
			||||||
 | 
					                INSIDE_CHROOT=1 mychroot_nocwd \
 | 
				
			||||||
 | 
					                 -w /osmo-trx \
 | 
				
			||||||
 | 
					                 -b "$OSMOTRX_DIR:/osmo-trx" \
 | 
				
			||||||
 | 
					                 -b "$(which osmo-clean-workspace.sh):/usr/bin/osmo-clean-workspace.sh" \
 | 
				
			||||||
 | 
					                 -b "$(which osmo-build-dep.sh):/usr/bin/osmo-build-dep.sh" \
 | 
				
			||||||
 | 
					                 -b "$(which osmo-deps.sh):/usr/bin/osmo-deps.sh" \
 | 
				
			||||||
 | 
					                  ./contrib/jenkins.sh
 | 
				
			||||||
 | 
					                exit 0
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -ex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
					if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
				
			||||||
	echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
						echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
				
			||||||
@@ -44,17 +85,7 @@ export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
 | 
				
			|||||||
export LD_LIBRARY_PATH="$inst/lib"
 | 
					export LD_LIBRARY_PATH="$inst/lib"
 | 
				
			||||||
export PATH="$inst/bin:$PATH"
 | 
					export PATH="$inst/bin:$PATH"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG="
 | 
					CONFIG="--enable-sanitize --enable-werror --with-uhd --with-usrp1 --with-lms --with-ipc --with-mstrx $INSTR"
 | 
				
			||||||
	--enable-sanitize
 | 
					 | 
				
			||||||
	--enable-werror
 | 
					 | 
				
			||||||
	--with-bladerf
 | 
					 | 
				
			||||||
	--with-ipc
 | 
					 | 
				
			||||||
	--with-lms
 | 
					 | 
				
			||||||
	--with-mstrx
 | 
					 | 
				
			||||||
	--with-uhd
 | 
					 | 
				
			||||||
	--with-usrp1
 | 
					 | 
				
			||||||
	$INSTR
 | 
					 | 
				
			||||||
"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Additional configure options and depends
 | 
					# Additional configure options and depends
 | 
				
			||||||
if [ "$WITH_MANUALS" = "1" ]; then
 | 
					if [ "$WITH_MANUALS" = "1" ]; then
 | 
				
			||||||
@@ -78,7 +109,7 @@ $MAKE check \
 | 
				
			|||||||
  || cat-testlogs.sh
 | 
					  || cat-testlogs.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if arch | grep -v -q arm; then
 | 
					if arch | grep -v -q arm; then
 | 
				
			||||||
	DISTCHECK_CONFIGURE_FLAGS="$(echo $CONFIG | tr -d '\n')" $MAKE $PARALLEL_MAKE distcheck \
 | 
						DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE $PARALLEL_MAKE distcheck \
 | 
				
			||||||
	  || cat-testlogs.sh
 | 
						  || cat-testlogs.sh
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										254
									
								
								contrib/osmo-trx.spec.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								contrib/osmo-trx.spec.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# spec file for package osmo-trx
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2017, Martin Hauke <mardnh@gmx.de>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# All modifications and additions to the file contributed by third parties
 | 
				
			||||||
 | 
					# remain the property of their copyright owners, unless otherwise agreed
 | 
				
			||||||
 | 
					# upon. The license for this file, and modifications and additions to the
 | 
				
			||||||
 | 
					# file, is the same license as for the pristine package itself (unless the
 | 
				
			||||||
 | 
					# license for the pristine package is not an Open Source License, in which
 | 
				
			||||||
 | 
					# case the license is the MIT License). An "Open Source License" is a
 | 
				
			||||||
 | 
					# license that conforms to the Open Source Definition (Version 1.9)
 | 
				
			||||||
 | 
					# published by the Open Source Initiative.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name:           osmo-trx
 | 
				
			||||||
 | 
					Version:        @VERSION@
 | 
				
			||||||
 | 
					Release:        0
 | 
				
			||||||
 | 
					Summary:        SDR transceiver that implements Layer 1 of a GSM BTS
 | 
				
			||||||
 | 
					License:        AGPL-3.0-or-later
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					URL:            https://osmocom.org/projects/osmotrx
 | 
				
			||||||
 | 
					Source:         %{name}-%{version}.tar.xz
 | 
				
			||||||
 | 
					BuildRequires:  autoconf
 | 
				
			||||||
 | 
					BuildRequires:  automake
 | 
				
			||||||
 | 
					BuildRequires:  fdupes
 | 
				
			||||||
 | 
					BuildRequires:  gcc-c++
 | 
				
			||||||
 | 
					BuildRequires:  libtool
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig >= 0.20
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					BuildRequires:  systemd-rpm-macros
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					%if ! 0%{?centos_ver}
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(LimeSuite)
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(usrp) >= 3.3
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(fftw3f)
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmocoding) >= 1.9.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmocore) >= 1.9.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmoctrl) >= 1.9.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmovty) >= 1.9.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libusb-1.0)
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(uhd)
 | 
				
			||||||
 | 
					%{?systemd_requires}
 | 
				
			||||||
 | 
					%if 0%{?suse_version} > 1325
 | 
				
			||||||
 | 
					BuildRequires:  libboost_program_options-devel
 | 
				
			||||||
 | 
					BuildRequires:  libboost_system-devel
 | 
				
			||||||
 | 
					BuildRequires:  libboost_test-devel
 | 
				
			||||||
 | 
					BuildRequires:  libboost_thread-devel
 | 
				
			||||||
 | 
					%else
 | 
				
			||||||
 | 
					BuildRequires:  boost-devel
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description
 | 
				
			||||||
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TS 05.01 "Physical layer on the radio path"
 | 
				
			||||||
 | 
					TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
				
			||||||
 | 
					TS 05.04 "Modulation"
 | 
				
			||||||
 | 
					TS 05.10 "Radio subsystem synchronization"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this context, BTS is "Base transceiver station". It's the stations that
 | 
				
			||||||
 | 
					connect mobile phones to the mobile network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3GPP is the "3rd Generation Partnership Project" which is the collaboration
 | 
				
			||||||
 | 
					between different telecommunication associations for developing new
 | 
				
			||||||
 | 
					generations of mobile phone networks. (post-2G/GSM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package uhd
 | 
				
			||||||
 | 
					Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (UHD)
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					Requires:       uhd-firmware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description uhd
 | 
				
			||||||
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TS 05.01 "Physical layer on the radio path"
 | 
				
			||||||
 | 
					TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
				
			||||||
 | 
					TS 05.04 "Modulation"
 | 
				
			||||||
 | 
					TS 05.10 "Radio subsystem synchronization"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this context, BTS is "Base transceiver station". It's the stations that
 | 
				
			||||||
 | 
					connect mobile phones to the mobile network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3GPP is the "3rd Generation Partnership Project" which is the collaboration
 | 
				
			||||||
 | 
					between different telecommunication associations for developing new
 | 
				
			||||||
 | 
					generations of mobile phone networks. (post-2G/GSM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if ! 0%{?centos_ver}
 | 
				
			||||||
 | 
					%package usrp1
 | 
				
			||||||
 | 
					Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (USRP1)
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description usrp1
 | 
				
			||||||
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TS 05.01 "Physical layer on the radio path"
 | 
				
			||||||
 | 
					TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
				
			||||||
 | 
					TS 05.04 "Modulation"
 | 
				
			||||||
 | 
					TS 05.10 "Radio subsystem synchronization"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this context, BTS is "Base transceiver station". It's the stations that
 | 
				
			||||||
 | 
					connect mobile phones to the mobile network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3GPP is the "3rd Generation Partnership Project" which is the collaboration
 | 
				
			||||||
 | 
					between different telecommunication associations for developing new
 | 
				
			||||||
 | 
					generations of mobile phone networks. (post-2G/GSM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package lms
 | 
				
			||||||
 | 
					Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (LimeSuite)
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description lms
 | 
				
			||||||
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TS 05.01 "Physical layer on the radio path"
 | 
				
			||||||
 | 
					TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
				
			||||||
 | 
					TS 05.04 "Modulation"
 | 
				
			||||||
 | 
					TS 05.10 "Radio subsystem synchronization"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this context, BTS is "Base transceiver station". It's the stations that
 | 
				
			||||||
 | 
					connect mobile phones to the mobile network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3GPP is the "3rd Generation Partnership Project" which is the collaboration
 | 
				
			||||||
 | 
					between different telecommunication associations for developing new
 | 
				
			||||||
 | 
					generations of mobile phone networks. (post-2G/GSM)
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package ipc
 | 
				
			||||||
 | 
					Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (IPC)
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description ipc
 | 
				
			||||||
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TS 05.01 "Physical layer on the radio path"
 | 
				
			||||||
 | 
					TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
				
			||||||
 | 
					TS 05.04 "Modulation"
 | 
				
			||||||
 | 
					TS 05.10 "Radio subsystem synchronization"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this context, BTS is "Base transceiver station". It's the stations that
 | 
				
			||||||
 | 
					connect mobile phones to the mobile network.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3GPP is the "3rd Generation Partnership Project" which is the collaboration
 | 
				
			||||||
 | 
					between different telecommunication associations for developing new
 | 
				
			||||||
 | 
					generations of mobile phone networks. (post-2G/GSM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package ipc-test
 | 
				
			||||||
 | 
					Summary:        SDR transceiver that implements Layer 1 of a GSM BTS (IPC) driver test utility
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description ipc-test
 | 
				
			||||||
 | 
					OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
				
			||||||
 | 
					physical layer of a BTS comprising the following 3GPP specifications:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This package include the test tools for osmo-trx-ipc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%prep
 | 
				
			||||||
 | 
					%setup -q
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%build
 | 
				
			||||||
 | 
					echo "%{version}" >.tarball-version
 | 
				
			||||||
 | 
					autoreconf -fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if 0%{?centos_ver}
 | 
				
			||||||
 | 
					%configure \
 | 
				
			||||||
 | 
					  --docdir=%{_docdir}/%{name} \
 | 
				
			||||||
 | 
					  --with-systemdsystemunitdir=%{_unitdir} \
 | 
				
			||||||
 | 
					  --without-lms \
 | 
				
			||||||
 | 
					  --with-uhd \
 | 
				
			||||||
 | 
					  --without-usrp1 \
 | 
				
			||||||
 | 
					  --with-ipc
 | 
				
			||||||
 | 
					%else
 | 
				
			||||||
 | 
					%configure \
 | 
				
			||||||
 | 
					  --docdir=%{_docdir}/%{name} \
 | 
				
			||||||
 | 
					  --with-systemdsystemunitdir=%{_unitdir} \
 | 
				
			||||||
 | 
					  --with-lms \
 | 
				
			||||||
 | 
					  --with-uhd \
 | 
				
			||||||
 | 
					  --with-usrp1 \
 | 
				
			||||||
 | 
					  --with-ipc
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					make %{?_smp_mflags} V=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%check
 | 
				
			||||||
 | 
					make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%install
 | 
				
			||||||
 | 
					%make_install
 | 
				
			||||||
 | 
					%fdupes -s %{buildroot}/%{_datadir}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					%pre    lms %service_add_pre    osmo-trx-lms.service
 | 
				
			||||||
 | 
					%post   lms %service_add_post   osmo-trx-lms.service
 | 
				
			||||||
 | 
					%preun  lms %service_del_preun  osmo-trx-lms.service
 | 
				
			||||||
 | 
					%postun lms %service_del_postun osmo-trx-lms.service
 | 
				
			||||||
 | 
					%pre    uhd %service_add_pre    osmo-trx-uhd.service
 | 
				
			||||||
 | 
					%post   uhd %service_add_post   osmo-trx-uhd.service
 | 
				
			||||||
 | 
					%preun  uhd %service_del_preun  osmo-trx-uhd.service
 | 
				
			||||||
 | 
					%postun uhd %service_del_postun osmo-trx-uhd.service
 | 
				
			||||||
 | 
					%pre    usrp1 %service_add_pre    osmo-trx-usrp1.service
 | 
				
			||||||
 | 
					%post   usrp1 %service_add_post   osmo-trx-usrp1.service
 | 
				
			||||||
 | 
					%preun  usrp1 %service_del_preun  osmo-trx-usrp1.service
 | 
				
			||||||
 | 
					%postun usrp1 %service_del_postun osmo-trx-usrp1.service
 | 
				
			||||||
 | 
					%pre    ipc %service_add_pre    osmo-trx-ipc.service
 | 
				
			||||||
 | 
					%post   ipc %service_add_post   osmo-trx-ipc.service
 | 
				
			||||||
 | 
					%preun  ipc %service_del_preun  osmo-trx-ipc.service
 | 
				
			||||||
 | 
					%postun ipc %service_del_postun osmo-trx-ipc.service
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files
 | 
				
			||||||
 | 
					%license COPYING
 | 
				
			||||||
 | 
					%doc README.md
 | 
				
			||||||
 | 
					%doc %{_docdir}/%{name}/examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if ! 0%{?centos_ver}
 | 
				
			||||||
 | 
					%files lms
 | 
				
			||||||
 | 
					%{_bindir}/osmo-trx-lms
 | 
				
			||||||
 | 
					%dir %{_sysconfdir}/osmocom
 | 
				
			||||||
 | 
					%config(noreplace) %{_sysconfdir}/osmocom/osmo-trx-lms.cfg
 | 
				
			||||||
 | 
					%{_unitdir}/osmo-trx-lms.service
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files uhd
 | 
				
			||||||
 | 
					%{_bindir}/osmo-trx-uhd
 | 
				
			||||||
 | 
					%dir %{_sysconfdir}/osmocom
 | 
				
			||||||
 | 
					%config(noreplace) %{_sysconfdir}/osmocom/osmo-trx-uhd.cfg
 | 
				
			||||||
 | 
					%{_unitdir}/osmo-trx-uhd.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if ! 0%{?centos_ver}
 | 
				
			||||||
 | 
					%files usrp1
 | 
				
			||||||
 | 
					%{_bindir}/osmo-trx-usrp1
 | 
				
			||||||
 | 
					%dir %{_datadir}/usrp
 | 
				
			||||||
 | 
					%dir %{_datadir}/usrp/rev2
 | 
				
			||||||
 | 
					%dir %{_datadir}/usrp/rev4
 | 
				
			||||||
 | 
					%{_datadir}/usrp/rev2/std_inband.rbf
 | 
				
			||||||
 | 
					%{_datadir}/usrp/rev4/std_inband.rbf
 | 
				
			||||||
 | 
					%{_unitdir}/osmo-trx-usrp1.service
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files ipc
 | 
				
			||||||
 | 
					%{_bindir}/osmo-trx-ipc
 | 
				
			||||||
 | 
					%dir %{_sysconfdir}/osmocom
 | 
				
			||||||
 | 
					%config(noreplace) %{_sysconfdir}/osmocom/osmo-trx-ipc.cfg
 | 
				
			||||||
 | 
					%{_unitdir}/osmo-trx-ipc.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files ipc-test
 | 
				
			||||||
 | 
					%{_bindir}/ipc-driver-test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%changelog
 | 
				
			||||||
@@ -8,11 +8,8 @@ Type=simple
 | 
				
			|||||||
Restart=always
 | 
					Restart=always
 | 
				
			||||||
StateDirectory=osmocom
 | 
					StateDirectory=osmocom
 | 
				
			||||||
WorkingDirectory=%S/osmocom
 | 
					WorkingDirectory=%S/osmocom
 | 
				
			||||||
User=osmocom
 | 
					 | 
				
			||||||
Group=osmocom
 | 
					 | 
				
			||||||
ExecStart=/usr/bin/osmo-trx-ipc -C /etc/osmocom/osmo-trx-ipc.cfg
 | 
					ExecStart=/usr/bin/osmo-trx-ipc -C /etc/osmocom/osmo-trx-ipc.cfg
 | 
				
			||||||
RestartSec=2
 | 
					RestartSec=2
 | 
				
			||||||
AmbientCapabilities=CAP_SYS_NICE
 | 
					 | 
				
			||||||
# CPU scheduling policy:
 | 
					# CPU scheduling policy:
 | 
				
			||||||
CPUSchedulingPolicy=rr
 | 
					CPUSchedulingPolicy=rr
 | 
				
			||||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
					# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,8 @@ Type=simple
 | 
				
			|||||||
Restart=always
 | 
					Restart=always
 | 
				
			||||||
StateDirectory=osmocom
 | 
					StateDirectory=osmocom
 | 
				
			||||||
WorkingDirectory=%S/osmocom
 | 
					WorkingDirectory=%S/osmocom
 | 
				
			||||||
User=osmocom
 | 
					 | 
				
			||||||
Group=osmocom
 | 
					 | 
				
			||||||
ExecStart=/usr/bin/osmo-trx-lms -C /etc/osmocom/osmo-trx-lms.cfg
 | 
					ExecStart=/usr/bin/osmo-trx-lms -C /etc/osmocom/osmo-trx-lms.cfg
 | 
				
			||||||
RestartSec=2
 | 
					RestartSec=2
 | 
				
			||||||
AmbientCapabilities=CAP_SYS_NICE
 | 
					 | 
				
			||||||
# CPU scheduling policy:
 | 
					# CPU scheduling policy:
 | 
				
			||||||
CPUSchedulingPolicy=rr
 | 
					CPUSchedulingPolicy=rr
 | 
				
			||||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
					# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,12 +8,8 @@ Type=simple
 | 
				
			|||||||
Restart=always
 | 
					Restart=always
 | 
				
			||||||
StateDirectory=osmocom
 | 
					StateDirectory=osmocom
 | 
				
			||||||
WorkingDirectory=%S/osmocom
 | 
					WorkingDirectory=%S/osmocom
 | 
				
			||||||
Environment=HOME=%S/osmocom
 | 
					 | 
				
			||||||
User=osmocom
 | 
					 | 
				
			||||||
Group=osmocom
 | 
					 | 
				
			||||||
ExecStart=/usr/bin/osmo-trx-uhd -C /etc/osmocom/osmo-trx-uhd.cfg
 | 
					ExecStart=/usr/bin/osmo-trx-uhd -C /etc/osmocom/osmo-trx-uhd.cfg
 | 
				
			||||||
RestartSec=2
 | 
					RestartSec=2
 | 
				
			||||||
AmbientCapabilities=CAP_SYS_NICE
 | 
					 | 
				
			||||||
# CPU scheduling policy:
 | 
					# CPU scheduling policy:
 | 
				
			||||||
CPUSchedulingPolicy=rr
 | 
					CPUSchedulingPolicy=rr
 | 
				
			||||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
					# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,8 @@ Type=simple
 | 
				
			|||||||
Restart=always
 | 
					Restart=always
 | 
				
			||||||
StateDirectory=osmocom
 | 
					StateDirectory=osmocom
 | 
				
			||||||
WorkingDirectory=%S/osmocom
 | 
					WorkingDirectory=%S/osmocom
 | 
				
			||||||
User=osmocom
 | 
					 | 
				
			||||||
Group=osmocom
 | 
					 | 
				
			||||||
ExecStart=/usr/bin/osmo-trx-usrp1 -C /etc/osmocom/osmo-trx-usrp1.cfg
 | 
					ExecStart=/usr/bin/osmo-trx-usrp1 -C /etc/osmocom/osmo-trx-usrp1.cfg
 | 
				
			||||||
RestartSec=2
 | 
					RestartSec=2
 | 
				
			||||||
AmbientCapabilities=CAP_SYS_NICE
 | 
					 | 
				
			||||||
# CPU scheduling policy:
 | 
					# CPU scheduling policy:
 | 
				
			||||||
CPUSchedulingPolicy=rr
 | 
					CPUSchedulingPolicy=rr
 | 
				
			||||||
# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
					# For real-time scheduling policies an integer between 1 (lowest priority) and 99 (highest priority):
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,64 +1,9 @@
 | 
				
			|||||||
osmo-trx (1.7.1) unstable; urgency=medium
 | 
					osmo-trx (1.6.1) unstable; urgency=medium
 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Oliver Smith ]
 | 
					 | 
				
			||||||
  * contrib/jenkins: remove broken chroot + qemu code
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Neels Hofmeyr ]
 | 
					 | 
				
			||||||
  * comma_delimited_to_vector() optimization CID#465430
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 -- Oliver Smith <osmith@sysmocom.de>  Wed, 12 Feb 2025 12:43:24 +0100
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
osmo-trx (1.7.0) unstable; urgency=medium
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Eric ]
 | 
					 | 
				
			||||||
  * ms: adjust ts advance
 | 
					 | 
				
			||||||
  * ms: reduce rx burst queue size
 | 
					 | 
				
			||||||
  * ms: init blade with fpga control
 | 
					 | 
				
			||||||
  * devices: fix wrong gain to power mapping
 | 
					 | 
				
			||||||
  * ms: get rid of std::thread
 | 
					 | 
				
			||||||
  * ms: add demod test tool and data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Vadim Yanitskiy ]
 | 
					 | 
				
			||||||
  * osmo-trx-ms: bump osmocom-bb submodule commit
 | 
					 | 
				
			||||||
  * Transceiver::ctrl_sock_handle_rx(): fix copy-pasted comments
 | 
					 | 
				
			||||||
  * build: include version files into the release tarball
 | 
					 | 
				
			||||||
  * doc/examples: fix missing config files in release tarballs
 | 
					 | 
				
			||||||
  * README.md: cosmetic: fix a typo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Harald Welte ]
 | 
					 | 
				
			||||||
  * osmo-trx-uhd: Make sure HOME environment variable is set
 | 
					 | 
				
			||||||
  * README.md: Improve markdown formatting
 | 
					 | 
				
			||||||
  * README.md: Add Forum and Issue Tracker links
 | 
					 | 
				
			||||||
  * Add funding link to github mirror
 | 
					 | 
				
			||||||
  * README.md: Remove stray apostrophe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Andreas Eversberg ]
 | 
					 | 
				
			||||||
  * Use uniform log format for default config files
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [ Eric Wild ]
 | 
					  [ Eric Wild ]
 | 
				
			||||||
  * ms: do not set the blade tuning mode
 | 
					  * devices: fix wrong gain to power mapping
 | 
				
			||||||
  * ms: hard preswapped VA gsm bits
 | 
					 | 
				
			||||||
  * ms: add sigproclib demod
 | 
					 | 
				
			||||||
  * ms: fix up template deduction failure
 | 
					 | 
				
			||||||
  * ms: update osmocom-bb submodule
 | 
					 | 
				
			||||||
  * ms: disabe uhd ms build
 | 
					 | 
				
			||||||
  * transceiver: use log level cache
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [ Oliver Smith ]
 | 
					 -- Eric Wild <ewild@sysmocom.de>  Thu, 09 Nov 2023 14:16:21 +0200
 | 
				
			||||||
  * gitignore: add .version
 | 
					 | 
				
			||||||
  * debian/rules: make configure args diff friendly
 | 
					 | 
				
			||||||
  * debian: add osmo-trx-ms-blade
 | 
					 | 
				
			||||||
  * contrib/jenkins: make configure args diff friendly
 | 
					 | 
				
			||||||
  * contrib/jenkins: add --with-bladerf
 | 
					 | 
				
			||||||
  * contrib: remove rpm spec file
 | 
					 | 
				
			||||||
  * contrib/systemd: run as osmocom user
 | 
					 | 
				
			||||||
  * contrib/systemd/osmo-trx-uhd: fix HOME=
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  [ Pau Espin Pedrol ]
 | 
					 | 
				
			||||||
  * code-architecture.adoc: Fix missing alignment in digraph
 | 
					 | 
				
			||||||
  * doc: Introduce documentation for osmo-trx-ipc and its IPC interface
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 -- Oliver Smith <osmith@sysmocom.de>  Wed, 24 Jul 2024 15:57:14 +0200
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
osmo-trx (1.6.0) unstable; urgency=medium
 | 
					osmo-trx (1.6.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -14,9 +14,8 @@ Build-Depends: debhelper (>= 10),
 | 
				
			|||||||
               libtalloc-dev,
 | 
					               libtalloc-dev,
 | 
				
			||||||
               libusrp-dev,
 | 
					               libusrp-dev,
 | 
				
			||||||
               liblimesuite-dev,
 | 
					               liblimesuite-dev,
 | 
				
			||||||
               libbladerf-dev,
 | 
					               libosmocore-dev (>= 1.9.0),
 | 
				
			||||||
               libosmocore-dev (>= 1.10.0),
 | 
					               osmo-gsm-manuals-dev (>= 1.5.0)
 | 
				
			||||||
               osmo-gsm-manuals-dev (>= 1.6.0)
 | 
					 | 
				
			||||||
Standards-Version: 3.9.6
 | 
					Standards-Version: 3.9.6
 | 
				
			||||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
					Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
				
			||||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
					Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-trx
 | 
				
			||||||
@@ -111,25 +110,6 @@ Description: SDR transceiver that implements Layer 1 of a GSM BTS (generic IPC)
 | 
				
			|||||||
 between different telecommunication associations for developing new
 | 
					 between different telecommunication associations for developing new
 | 
				
			||||||
 generations of mobile phone networks. (post-2G/GSM)
 | 
					 generations of mobile phone networks. (post-2G/GSM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Package: osmo-trx-ms-blade
 | 
					 | 
				
			||||||
Architecture: any
 | 
					 | 
				
			||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
 | 
					 | 
				
			||||||
Description: MS side transceiver (bladeRF)
 | 
					 | 
				
			||||||
 OsmoTRX is a software-defined radio transceiver that implements the Layer 1
 | 
					 | 
				
			||||||
 physical layer of a BTS comprising the following 3GPP specifications:
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 TS 05.01 "Physical layer on the radio path"
 | 
					 | 
				
			||||||
 TS 05.02 "Multiplexing and Multiple Access on the Radio Path"
 | 
					 | 
				
			||||||
 TS 05.04 "Modulation"
 | 
					 | 
				
			||||||
 TS 05.10 "Radio subsystem synchronization"
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 In this context, BTS is "Base transceiver station". It's the stations that
 | 
					 | 
				
			||||||
 connect mobile phones to the mobile network.
 | 
					 | 
				
			||||||
 .
 | 
					 | 
				
			||||||
 3GPP is the "3rd Generation Partnership Project" which is the collaboration
 | 
					 | 
				
			||||||
 between different telecommunication associations for developing new
 | 
					 | 
				
			||||||
 generations of mobile phone networks. (post-2G/GSM)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Package: osmo-trx-doc
 | 
					Package: osmo-trx-doc
 | 
				
			||||||
Architecture: all
 | 
					Architecture: all
 | 
				
			||||||
Section: doc
 | 
					Section: doc
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								debian/osmo-trx-ipc.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-ipc.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
				
			|||||||
#!/bin/sh -e
 | 
					 | 
				
			||||||
case "$1" in
 | 
					 | 
				
			||||||
	configure)
 | 
					 | 
				
			||||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
					 | 
				
			||||||
		if ! getent group osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			groupadd --system osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		if ! getent passwd osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			useradd \
 | 
					 | 
				
			||||||
				--system \
 | 
					 | 
				
			||||||
				--gid osmocom \
 | 
					 | 
				
			||||||
				--home-dir /var/lib/osmocom \
 | 
					 | 
				
			||||||
				--shell /sbin/nologin \
 | 
					 | 
				
			||||||
				--comment "Open Source Mobile Communications" \
 | 
					 | 
				
			||||||
				osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
					 | 
				
			||||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
					 | 
				
			||||||
			if [ -e /etc/osmocom/osmo-trx-ipc.cfg ]; then
 | 
					 | 
				
			||||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-ipc.cfg
 | 
					 | 
				
			||||||
				chmod -v 0660 /etc/osmocom/osmo-trx-ipc.cfg
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if [ -d /etc/osmocom ]; then
 | 
					 | 
				
			||||||
				chown -v root:osmocom /etc/osmocom
 | 
					 | 
				
			||||||
				chmod -v 2775 /etc/osmocom
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			mkdir -p /var/lib/osmocom
 | 
					 | 
				
			||||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		;;
 | 
					 | 
				
			||||||
esac
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
					 | 
				
			||||||
# generated by other debhelper scripts.
 | 
					 | 
				
			||||||
#DEBHELPER#
 | 
					 | 
				
			||||||
							
								
								
									
										38
									
								
								debian/osmo-trx-lms.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-lms.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
				
			|||||||
#!/bin/sh -e
 | 
					 | 
				
			||||||
case "$1" in
 | 
					 | 
				
			||||||
	configure)
 | 
					 | 
				
			||||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
					 | 
				
			||||||
		if ! getent group osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			groupadd --system osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		if ! getent passwd osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			useradd \
 | 
					 | 
				
			||||||
				--system \
 | 
					 | 
				
			||||||
				--gid osmocom \
 | 
					 | 
				
			||||||
				--home-dir /var/lib/osmocom \
 | 
					 | 
				
			||||||
				--shell /sbin/nologin \
 | 
					 | 
				
			||||||
				--comment "Open Source Mobile Communications" \
 | 
					 | 
				
			||||||
				osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
					 | 
				
			||||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
					 | 
				
			||||||
			if [ -e /etc/osmocom/osmo-trx-lms.cfg ]; then
 | 
					 | 
				
			||||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-lms.cfg
 | 
					 | 
				
			||||||
				chmod -v 0660 /etc/osmocom/osmo-trx-lms.cfg
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if [ -d /etc/osmocom ]; then
 | 
					 | 
				
			||||||
				chown -v root:osmocom /etc/osmocom
 | 
					 | 
				
			||||||
				chmod -v 2775 /etc/osmocom
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			mkdir -p /var/lib/osmocom
 | 
					 | 
				
			||||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		;;
 | 
					 | 
				
			||||||
esac
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
					 | 
				
			||||||
# generated by other debhelper scripts.
 | 
					 | 
				
			||||||
#DEBHELPER#
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/osmo-trx-ms-blade.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-trx-ms-blade.install
									
									
									
									
										vendored
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
/usr/bin/osmo-trx-ms-blade
 | 
					 | 
				
			||||||
							
								
								
									
										38
									
								
								debian/osmo-trx-uhd.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-uhd.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
				
			|||||||
#!/bin/sh -e
 | 
					 | 
				
			||||||
case "$1" in
 | 
					 | 
				
			||||||
	configure)
 | 
					 | 
				
			||||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
					 | 
				
			||||||
		if ! getent group osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			groupadd --system osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		if ! getent passwd osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			useradd \
 | 
					 | 
				
			||||||
				--system \
 | 
					 | 
				
			||||||
				--gid osmocom \
 | 
					 | 
				
			||||||
				--home-dir /var/lib/osmocom \
 | 
					 | 
				
			||||||
				--shell /sbin/nologin \
 | 
					 | 
				
			||||||
				--comment "Open Source Mobile Communications" \
 | 
					 | 
				
			||||||
				osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
					 | 
				
			||||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
					 | 
				
			||||||
			if [ -e /etc/osmocom/osmo-trx-uhd.cfg ]; then
 | 
					 | 
				
			||||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-uhd.cfg
 | 
					 | 
				
			||||||
				chmod -v 0660 /etc/osmocom/osmo-trx-uhd.cfg
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if [ -d /etc/osmocom ]; then
 | 
					 | 
				
			||||||
				chown -v root:osmocom /etc/osmocom
 | 
					 | 
				
			||||||
				chmod -v 2775 /etc/osmocom
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			mkdir -p /var/lib/osmocom
 | 
					 | 
				
			||||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		;;
 | 
					 | 
				
			||||||
esac
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
					 | 
				
			||||||
# generated by other debhelper scripts.
 | 
					 | 
				
			||||||
#DEBHELPER#
 | 
					 | 
				
			||||||
							
								
								
									
										38
									
								
								debian/osmo-trx-usrp1.postinst
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								debian/osmo-trx-usrp1.postinst
									
									
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
				
			|||||||
#!/bin/sh -e
 | 
					 | 
				
			||||||
case "$1" in
 | 
					 | 
				
			||||||
	configure)
 | 
					 | 
				
			||||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
					 | 
				
			||||||
		if ! getent group osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			groupadd --system osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		if ! getent passwd osmocom >/dev/null; then
 | 
					 | 
				
			||||||
			useradd \
 | 
					 | 
				
			||||||
				--system \
 | 
					 | 
				
			||||||
				--gid osmocom \
 | 
					 | 
				
			||||||
				--home-dir /var/lib/osmocom \
 | 
					 | 
				
			||||||
				--shell /sbin/nologin \
 | 
					 | 
				
			||||||
				--comment "Open Source Mobile Communications" \
 | 
					 | 
				
			||||||
				osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
					 | 
				
			||||||
		if dpkg --compare-versions "$2" le "1.13.0"; then
 | 
					 | 
				
			||||||
			if [ -e /etc/osmocom/osmo-trx-usrp1.cfg ]; then
 | 
					 | 
				
			||||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-trx-usrp1.cfg
 | 
					 | 
				
			||||||
				chmod -v 0660 /etc/osmocom/osmo-trx-usrp1.cfg
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if [ -d /etc/osmocom ]; then
 | 
					 | 
				
			||||||
				chown -v root:osmocom /etc/osmocom
 | 
					 | 
				
			||||||
				chmod -v 2775 /etc/osmocom
 | 
					 | 
				
			||||||
			fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			mkdir -p /var/lib/osmocom
 | 
					 | 
				
			||||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
					 | 
				
			||||||
		fi
 | 
					 | 
				
			||||||
		;;
 | 
					 | 
				
			||||||
esac
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
					 | 
				
			||||||
# generated by other debhelper scripts.
 | 
					 | 
				
			||||||
#DEBHELPER#
 | 
					 | 
				
			||||||
							
								
								
									
										11
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							@@ -9,16 +9,7 @@ override_dh_shlibdeps:
 | 
				
			|||||||
	dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
 | 
						dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
override_dh_auto_configure:
 | 
					override_dh_auto_configure:
 | 
				
			||||||
	dh_auto_configure -- \
 | 
						dh_auto_configure -- --with-uhd --with-usrp1 --with-lms --with-ipc --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
 | 
				
			||||||
		--enable-manuals \
 | 
					 | 
				
			||||||
		--with-systemdsystemunitdir=/lib/systemd/system \
 | 
					 | 
				
			||||||
		--with-bladerf \
 | 
					 | 
				
			||||||
		--with-ipc \
 | 
					 | 
				
			||||||
		--with-lms \
 | 
					 | 
				
			||||||
		--with-mstrx \
 | 
					 | 
				
			||||||
		--with-uhd \
 | 
					 | 
				
			||||||
		--with-usrp1 \
 | 
					 | 
				
			||||||
		$(NULL)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
override_dh_strip:
 | 
					override_dh_strip:
 | 
				
			||||||
	dh_strip --dbg-package=osmo-trx-dbg
 | 
						dh_strip --dbg-package=osmo-trx-dbg
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,3 @@
 | 
				
			|||||||
# all config examples must be listed here unconditionally, so that
 | 
					 | 
				
			||||||
# all of them end up in the release tarball (see OS#6349)
 | 
					 | 
				
			||||||
EXTRA_DIST = \
 | 
					 | 
				
			||||||
	osmo-trx-uhd/osmo-trx-limesdr.cfg \
 | 
					 | 
				
			||||||
	osmo-trx-uhd/osmo-trx-usrp_b200.cfg \
 | 
					 | 
				
			||||||
	osmo-trx-uhd/osmo-trx-uhd.cfg \
 | 
					 | 
				
			||||||
	osmo-trx-uhd/osmo-trx-umtrx.cfg \
 | 
					 | 
				
			||||||
	osmo-trx-lms/osmo-trx-limesdr.cfg \
 | 
					 | 
				
			||||||
	osmo-trx-lms/osmo-trx-lms.cfg \
 | 
					 | 
				
			||||||
	osmo-trx-ipc/osmo-trx-ipc.cfg \
 | 
					 | 
				
			||||||
	$(NULL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
OSMOCONF_FILES =
 | 
					OSMOCONF_FILES =
 | 
				
			||||||
osmoconfdir = $(sysconfdir)/osmocom
 | 
					osmoconfdir = $(sysconfdir)/osmocom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,6 +19,7 @@ OSMOCONF_FILES += osmo-trx-ipc/osmo-trx-ipc.cfg
 | 
				
			|||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
osmoconf_DATA = $(OSMOCONF_FILES)
 | 
					osmoconf_DATA = $(OSMOCONF_FILES)
 | 
				
			||||||
 | 
					EXTRA_DIST = $(OSMOCONF_FILES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CFG_FILES = find $(srcdir) -type f -name '*.cfg*' | sed -e 's,^$(srcdir),,'
 | 
					CFG_FILES = find $(srcdir) -type f -name '*.cfg*' | sed -e 's,^$(srcdir),,'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
log stderr
 | 
					log stderr
 | 
				
			||||||
 logging filter all 1
 | 
					 logging filter all 1
 | 
				
			||||||
 logging color 1
 | 
					 logging color 1
 | 
				
			||||||
 logging print category-hex 0
 | 
					 | 
				
			||||||
 logging print category 1
 | 
					 logging print category 1
 | 
				
			||||||
 logging timestamp 0
 | 
					 logging timestamp 1
 | 
				
			||||||
 logging print file basename last
 | 
					 logging print file basename
 | 
				
			||||||
 logging print level 1
 | 
					 | 
				
			||||||
 logging level set-all notice
 | 
					 logging level set-all notice
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
line vty
 | 
					line vty
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
log stderr
 | 
					log stderr
 | 
				
			||||||
 logging filter all 1
 | 
					 logging filter all 1
 | 
				
			||||||
 logging color 1
 | 
					 logging color 1
 | 
				
			||||||
 logging print category-hex 0
 | 
					 | 
				
			||||||
 logging print category 1
 | 
					 logging print category 1
 | 
				
			||||||
 logging timestamp 0
 | 
					 logging timestamp 1
 | 
				
			||||||
 logging print file basename last
 | 
					 logging print file basename
 | 
				
			||||||
 logging print level 1
 | 
					 | 
				
			||||||
 logging level set-all notice
 | 
					 logging level set-all notice
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
line vty
 | 
					line vty
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
log stderr
 | 
					log stderr
 | 
				
			||||||
 logging filter all 1
 | 
					 logging filter all 1
 | 
				
			||||||
 logging color 1
 | 
					 logging color 1
 | 
				
			||||||
 logging print category-hex 0
 | 
					 | 
				
			||||||
 logging print category 1
 | 
					 logging print category 1
 | 
				
			||||||
 logging timestamp 0
 | 
					 logging timestamp 1
 | 
				
			||||||
 logging print file basename last
 | 
					 logging print file basename
 | 
				
			||||||
 logging print level 1
 | 
					 | 
				
			||||||
 logging level set-all notice
 | 
					 logging level set-all notice
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
line vty
 | 
					line vty
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
log stderr
 | 
					log stderr
 | 
				
			||||||
 logging filter all 1
 | 
					 logging filter all 1
 | 
				
			||||||
 logging color 1
 | 
					 logging color 1
 | 
				
			||||||
 logging print category-hex 0
 | 
					 | 
				
			||||||
 logging print category 1
 | 
					 logging print category 1
 | 
				
			||||||
 logging timestamp 0
 | 
					 logging timestamp 1
 | 
				
			||||||
 logging print file basename last
 | 
					 logging print file basename
 | 
				
			||||||
 logging print level 1
 | 
					 | 
				
			||||||
 logging level set-all notice
 | 
					 logging level set-all notice
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
line vty
 | 
					line vty
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
log stderr
 | 
					log stderr
 | 
				
			||||||
 logging filter all 1
 | 
					 logging filter all 1
 | 
				
			||||||
 logging color 1
 | 
					 logging color 1
 | 
				
			||||||
 logging print category-hex 0
 | 
					 | 
				
			||||||
 logging print category 1
 | 
					 logging print category 1
 | 
				
			||||||
 logging timestamp 0
 | 
					 logging timestamp 1
 | 
				
			||||||
 logging print file basename last
 | 
					 logging print file basename
 | 
				
			||||||
 logging print level 1
 | 
					 | 
				
			||||||
 logging level set-all notice
 | 
					 logging level set-all notice
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
line vty
 | 
					line vty
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@ digraph hierarchy {
 | 
				
			|||||||
node[shape=record,style=filled,fillcolor=gray95]
 | 
					node[shape=record,style=filled,fillcolor=gray95]
 | 
				
			||||||
edge[dir=back, arrowtail=empty]
 | 
					edge[dir=back, arrowtail=empty]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2[label = "{Transceiver|+ constructor()\l+ destructor()\l+ init()\l+ numChans()\l+ receiveFIFO()\l+ setSignalHandler()\l}"]
 | 
					2[label = "{Transceiver|+ constructor()\l+ destructor()\l+ init()\l+ numChans()\l+ receiveFIFO()\l+ setSignalHandler()}"]
 | 
				
			||||||
3[label = "{RadioInterface|...}"]
 | 
					3[label = "{RadioInterface|...}"]
 | 
				
			||||||
4[label = "{RadioInterfaceResamp|...}"]
 | 
					4[label = "{RadioInterfaceResamp|...}"]
 | 
				
			||||||
5[label = "{RadioInterfaceMulti|...}"]
 | 
					5[label = "{RadioInterfaceMulti|...}"]
 | 
				
			||||||
@@ -17,7 +17,6 @@ edge[dir=back, arrowtail=empty]
 | 
				
			|||||||
7[label = "{UHDDevice|...}"]
 | 
					7[label = "{UHDDevice|...}"]
 | 
				
			||||||
8[label = "{LMSDevice|...}"]
 | 
					8[label = "{LMSDevice|...}"]
 | 
				
			||||||
9[label = "{USRPDevice|...}"]
 | 
					9[label = "{USRPDevice|...}"]
 | 
				
			||||||
10[label = "{IPCDevice|...}"]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
2->3[arrowtail=odiamond]
 | 
					2->3[arrowtail=odiamond]
 | 
				
			||||||
3->4[constraint=false]
 | 
					3->4[constraint=false]
 | 
				
			||||||
@@ -26,7 +25,6 @@ edge[dir=back, arrowtail=empty]
 | 
				
			|||||||
6->7
 | 
					6->7
 | 
				
			||||||
6->8
 | 
					6->8
 | 
				
			||||||
6->9
 | 
					6->9
 | 
				
			||||||
6->10
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,301 +0,0 @@
 | 
				
			|||||||
[[ipc_if]]
 | 
					 | 
				
			||||||
== osmo-trx-ipc IPC Interface
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This interface is the one used by _osmo_trx_ipc_ backend to communicate to a
 | 
					 | 
				
			||||||
third party process in charge of driving the lowest layer device-specific bits
 | 
					 | 
				
			||||||
(from now on the Driver).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
It consists of a set of Unix Domain (UD) sockets for the control plane, plus a
 | 
					 | 
				
			||||||
shared memory region for the data plane.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Related code can be found in the
 | 
					 | 
				
			||||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc[Transceiver52M/device/ipc/]
 | 
					 | 
				
			||||||
directory in _osmo-trx.git_.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If you are a potential driver implementator, the
 | 
					 | 
				
			||||||
various primitives and data structures are publicly available in header file
 | 
					 | 
				
			||||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h].
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
=== Control plane
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Control plane protocol is transmitted over Unix Domain (UD) sockets using
 | 
					 | 
				
			||||||
message based primitives. Each primitive has a type identified by an integer,
 | 
					 | 
				
			||||||
and each type of primitive has a number of extra attributes attached to it. The
 | 
					 | 
				
			||||||
IPC interface consists of 2 types of UD sockets:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* _Master_ UD socket: One per osmo-trx-ipc process.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* _Channel_ UD socket: One for each channel managed by osmo-trx-ipc process.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The _Driver_ is in all cases expected to take the server role when creating UD
 | 
					 | 
				
			||||||
sockets, while _osmo-trx-ipc_ takes the client role and connects to sockets
 | 
					 | 
				
			||||||
provided by the driver.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
=== Master UD socket
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
During startup, _osmo-trx-ipc_ will try connecting to the _Driver_ Master UD
 | 
					 | 
				
			||||||
socket located in the path provided by its own (VTY) configuration. As a result,
 | 
					 | 
				
			||||||
it means the _Driver_ process must be running and listening on the Master UD
 | 
					 | 
				
			||||||
socket before _osmo-trx-ipc_ is started, otherwise _osmo-trx-ipc_ will fail and
 | 
					 | 
				
			||||||
exit.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Once connected, _osmo-trx-ipc_ will submit a `GREETING_REQ` message primitive
 | 
					 | 
				
			||||||
announcing the maximum supported protocol version (first version ever is `1`,
 | 
					 | 
				
			||||||
increasing over time).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The _Driver_ shall then answer in `GREETING_CNF` message primitive with its own
 | 
					 | 
				
			||||||
maximum supported version (`<=` version received), providing 0 if none is
 | 
					 | 
				
			||||||
supported.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If _osmo-trx-ipc_ receives back the requested version, then both sides agreed
 | 
					 | 
				
			||||||
on the protocol version to use.
 | 
					 | 
				
			||||||
If _osmo-trx-ipc_ receives back a lower version, it shall decide to continue
 | 
					 | 
				
			||||||
with version negotiation using a lower version, until a supported version or 0
 | 
					 | 
				
			||||||
is received. If finally 0 is received, _osmo-trx-ipc_ will disconnect and exit
 | 
					 | 
				
			||||||
with failure.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Once the version is negotiated (`v1` as of current date), _osmo-trx-ipc_ will
 | 
					 | 
				
			||||||
ask for device information and available characeristics to the _Driver_ using
 | 
					 | 
				
			||||||
the `INFO_REQ` message primitive.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The _Driver_ shall then answer with a `INFO_CNF` message
 | 
					 | 
				
			||||||
containing information, such as:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* String containing device description
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Available reference clocks,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* {rx,tx} I/Q scaling factors
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Maximum number of channels supported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* for each channel:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
** List of available {rx,tx} paths/antennas.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
** {min,max}{rx,tx} gains
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
** Nominal transmit power
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
All the information received from the _Driver_ during `INFO_CNF` will be used by
 | 
					 | 
				
			||||||
_osmo-trx-ipc_ to decide whether it can fullfil the requested configuration from
 | 
					 | 
				
			||||||
the user, and proceed to open the device, or exit with a failure (for instance
 | 
					 | 
				
			||||||
number of channels, referece clock or tx/rx antenna selected by the user cannot
 | 
					 | 
				
			||||||
be fullfilled).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_osmo-trx-ipc_ will then proceed to open the device and do an initial
 | 
					 | 
				
			||||||
configuration using an `OPEN_REQ` message, where it will provide the _Driver_
 | 
					 | 
				
			||||||
with the desired selected configuration (such as number of channels, rx/tx
 | 
					 | 
				
			||||||
paths, clock reference, bandwidth filters, etc.).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The _Driver_ shall then configure the device and send back a `OPEN_CNF` with:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* `return_code` integer attribute set to `0` on success or `!0` on error.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Name of the Posix Shared Memory region where data plane is going to be
 | 
					 | 
				
			||||||
transmitted.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* One path for each channel, containing the just-created UD socket to manage
 | 
					 | 
				
			||||||
that channel (for instance by taking Master UD socket path and appending
 | 
					 | 
				
			||||||
`_$chan_idx`).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Path Delay: this is the loopback path delay in samples (= used as a timestamp
 | 
					 | 
				
			||||||
offset internally by _osmo-trx-ipc_), this value contains the analog delay as
 | 
					 | 
				
			||||||
well as the delay introduced by the digital filters in the fpga in the sdr
 | 
					 | 
				
			||||||
devices, and is therefore device type and bandwidth/sample rate dependant. This
 | 
					 | 
				
			||||||
can not be omitted, wrong values will lead to a _osmo-trx-ipc_ that just doesn't
 | 
					 | 
				
			||||||
detect any bursts.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Finally, _osmo-trx-ipc_ will connect to each channel's UD socket (see next
 | 
					 | 
				
			||||||
section).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Upon _osmo-trx-ipc_ closing the UD master socket connection, the _Driver_ shall
 | 
					 | 
				
			||||||
go into _closed_ state: stop all processing and instruct the device to power
 | 
					 | 
				
			||||||
off.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TIP: See
 | 
					 | 
				
			||||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h]
 | 
					 | 
				
			||||||
for the detailed definition of all the related message primitives and data
 | 
					 | 
				
			||||||
types for this socket.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
=== Channel UD Socket
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This socket can be used by _osmo-trx-ipc_ to start/stop data plane processing or
 | 
					 | 
				
			||||||
change channel's parameters such as Rx/Tx Frequency, Rx/Tx gains, etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A channel can be either in _started_ or _stopped_ state. When a channel is
 | 
					 | 
				
			||||||
created (during `OPEN_REQ` in the Master UD Socket), it's by default in
 | 
					 | 
				
			||||||
_stopped_ state. `START_REQ` and `STOP_REQ` messages control this state, and
 | 
					 | 
				
			||||||
eventual failures can be reported through `START_CNF` and `STOP_CNF` by the
 | 
					 | 
				
			||||||
_Driver_.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The message `START_REQ` instructs the _Driver_ to start processing data in the
 | 
					 | 
				
			||||||
data plane. Similary, `STOP_REQ` instructs the _Driver_ to stop processing data
 | 
					 | 
				
			||||||
in the data plane.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Some parameters are usually changed only when the channel is in stopped mode,
 | 
					 | 
				
			||||||
for instance Rx/Tx Frequency.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TIP: See
 | 
					 | 
				
			||||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h]
 | 
					 | 
				
			||||||
for the detailed definition of all the related message primitives and data
 | 
					 | 
				
			||||||
types for this socket.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
=== Data Plane
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Data plane protocol is implemented by means of a ring buffer structure on top of
 | 
					 | 
				
			||||||
Posix Shared Memory (see `man 7 shm_overview`) between _osmo-trx-ipc_ process
 | 
					 | 
				
			||||||
and the _Driver_.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The Posix Shared Memory region is created and its memory structure prepared by
 | 
					 | 
				
			||||||
the _Driver_ and its name shared with _osmo-trx-ipc_ during _OPEN_CNF_ message
 | 
					 | 
				
			||||||
in the Master UD Socket from the Control Plane. Resource allocation for the
 | 
					 | 
				
			||||||
shared memory area and cleanup is up to the ipc server, as is mutex
 | 
					 | 
				
			||||||
initialization for the buffers.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
==== Posix Shared Memory structure
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[fig-shm-structure]]
 | 
					 | 
				
			||||||
.General overview of Posix Shared Memory structure
 | 
					 | 
				
			||||||
[graphviz]
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
digraph hierarchy {
 | 
					 | 
				
			||||||
node[shape=record,style=filled,fillcolor=gray95]
 | 
					 | 
				
			||||||
edge[dir=back, arrowtail=empty]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SHM[label = "{Posix Shared Memory region|+ num_chans\l+ Channels[]\l}"]
 | 
					 | 
				
			||||||
CHAN0[label = "{Channel 0|...}"]
 | 
					 | 
				
			||||||
CHAN1[label = "{Channel 1|...}"]
 | 
					 | 
				
			||||||
CHANN[label = "{Channel ...|}"]
 | 
					 | 
				
			||||||
STREAM0_UL[label = "{UL Stream|+ semaphore\l+ read_next\l+ write_next\l+ buffer_size /* In samples */\l+ num_buffers\l+ sample_buffers[]\l}"]
 | 
					 | 
				
			||||||
STREAM0_DL[label = "{DL Stream|+ semaphore\l+ read_next\l+ write_next\l+ buffer_size /* In samples */\l+ num_buffers\l+ sample_buffers[]\l}"]
 | 
					 | 
				
			||||||
STREAM1_UL[label = "{UL Stream|...}"]
 | 
					 | 
				
			||||||
STREAM1_DL[label = "{DL Stream|...}"]
 | 
					 | 
				
			||||||
STREAMN_UL[label = "{UL Stream|...}"]
 | 
					 | 
				
			||||||
STREAMN_DL[label = "{DL Stream|...}"]
 | 
					 | 
				
			||||||
BUF_0DL0[label = "{DL Sample Buffer 0|+ timestamp\l+ buffer_size /* In samples */\l+ samples[] = [16bit I + 16bit Q,...]\l}"]
 | 
					 | 
				
			||||||
BUF_0DLN[label = "{DL Sample Buffer ....|...}"]
 | 
					 | 
				
			||||||
BUF_0UL0[label = "{UL Sample Buffer 0|+ timestamp\l+ buffer_size /* In samples */\l+ samples[] = [16bit I + 16bit Q,...]\l}"]
 | 
					 | 
				
			||||||
BUF_0ULN[label = "{UL Sample Buffer ...|...}"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SHM->CHAN0
 | 
					 | 
				
			||||||
SHM->CHAN1
 | 
					 | 
				
			||||||
SHM->CHANN
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CHAN0->STREAM0_DL
 | 
					 | 
				
			||||||
CHAN0->STREAM0_UL
 | 
					 | 
				
			||||||
STREAM0_DL->BUF_0DL0
 | 
					 | 
				
			||||||
STREAM0_DL->BUF_0DLN
 | 
					 | 
				
			||||||
STREAM0_UL->BUF_0UL0
 | 
					 | 
				
			||||||
STREAM0_UL->BUF_0ULN
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CHAN1->STREAM1_UL
 | 
					 | 
				
			||||||
CHAN1->STREAM1_DL
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CHANN->STREAMN_UL
 | 
					 | 
				
			||||||
CHANN->STREAMN_DL
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The Posix Shared Memory region contains an array of _Channels_.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Each _Channel_ contains 2 Streams:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Downlink _Stream_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Uplink _Stream_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Each _Stream_ handles a ring buffer, which is implemented as:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* An array of pointers to _Sample Buffer_ structures.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Variables containing the number of buffers in the array, as well as the
 | 
					 | 
				
			||||||
maximum size in samples for each Sample Buffer.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Variables containing `next_read` and `next_write` _Sample Buffer_ (its index
 | 
					 | 
				
			||||||
in the array of pointers).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Unnamed Posix semaphores to do the required locking while using the ring
 | 
					 | 
				
			||||||
buffer.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Each _Sample Buffer_ contains:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* A `timestamp` variable, containing the position in the stream of the first
 | 
					 | 
				
			||||||
sample in the buffer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* A `data_len` variable, containing the amount of samples available to process
 | 
					 | 
				
			||||||
in the buffer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* An array of samples of size specified by the stream struct it is part of.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
==== Posix Shared Memory format
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The Posix Shared memory region shall be formatted applying the following
 | 
					 | 
				
			||||||
considerations:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* All pointers in the memory region are encoded as offsets from the start
 | 
					 | 
				
			||||||
address of the region itself, to allow different processes with different
 | 
					 | 
				
			||||||
address spaces to decode them.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* All structs must be force-aligned to 8 bytes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Number of buffers must be power of 2 (2,4,8,16,...) - 4 appears to be plenty
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* IQ samples format: One (complex) sample consists of 16bit i + 16bit q, so the
 | 
					 | 
				
			||||||
buffer size is number of IQ pairs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* A reasonable per-buffer size (in samples) is 2500, since this happens to be
 | 
					 | 
				
			||||||
the ususal TX (downlink) buffer size used by _osmo-trx-ipc_ with the b210 (rx
 | 
					 | 
				
			||||||
over-the-wire packet size for the b210 is 2040 samples, so the larger value of
 | 
					 | 
				
			||||||
both is convenient).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TIP: See
 | 
					 | 
				
			||||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/shm.h[Transceiver52M/device/ipc/shm.h]
 | 
					 | 
				
			||||||
for the detailed definition of all the objects being part of the Posix Shared
 | 
					 | 
				
			||||||
memory region structure
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
==== Posix Shared Memory procedures
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The queue in the shared memory area is not supposed to be used for actual
 | 
					 | 
				
			||||||
buffering of data, only for exchange, so the general expectation is that it is
 | 
					 | 
				
			||||||
mostly empty. The only exception to that might be minor processing delays, and
 | 
					 | 
				
			||||||
during startup.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Care must be taken to ensure that only timed waits for the mutex protecting it
 | 
					 | 
				
			||||||
and the condition variables are used, in order to ensure that no deadlock occurs
 | 
					 | 
				
			||||||
should the other side die/quit.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Thread cancellation should be disabled during reads/writes from/to the queue. In
 | 
					 | 
				
			||||||
general a timeout can be considered a non recoverable error during regular
 | 
					 | 
				
			||||||
processing after startup, at least with the current timeout value of one second.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Should over- or underflows occur a corresponding message should be sent towards
 | 
					 | 
				
			||||||
_osmo-trx-ipc_.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Upon **read** of `N` samples, the reader does something like:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Acquire the semaphore in the channel's stream object.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Read `stream->next_read`, if `next_read==next_write`, become blocked in
 | 
					 | 
				
			||||||
another sempahore (unlocking the previous one) until writer signals us, then
 | 
					 | 
				
			||||||
`buff = stream->buffers[next_read]`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Read `buff->data_len` samples, reset the buffer data (`data_len=0`),
 | 
					 | 
				
			||||||
increment `next_read` and if read samples is `<N`, continue with next buffer
 | 
					 | 
				
			||||||
until `next_read==next_write`, then block again or if timeout elapsed, then  we
 | 
					 | 
				
			||||||
reach conditon buffer underflow and `return len < N`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Release the semaphore
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Upon **write** of `N` samples, the writer does something like:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Acquire the semapore in the channel's stream object.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Write samples to `buff = stream->buffers[next_write]`. If `data_len!=0`,
 | 
					 | 
				
			||||||
signal `buffer_overflow` (increase field in stream object) and probably
 | 
					 | 
				
			||||||
increase next_read`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. Increase `next_write`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
. If `next_write` was `== next_read`, signal the reader through the other
 | 
					 | 
				
			||||||
semaphore that it can continue reading.
 | 
					 | 
				
			||||||
@@ -71,103 +71,3 @@ with a memory buffer. In this mode, data written to the USRP is actually stored
 | 
				
			|||||||
in a buffer, and read commands to the USRP simply pull data from this buffer.
 | 
					in a buffer, and read commands to the USRP simply pull data from this buffer.
 | 
				
			||||||
This was very useful in early testing, and still may be useful in testing basic
 | 
					This was very useful in early testing, and still may be useful in testing basic
 | 
				
			||||||
Transceiver and radioInterface functionality.
 | 
					Transceiver and radioInterface functionality.
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[backend_ipc]]
 | 
					 | 
				
			||||||
=== `osmo-trx-ipc` Inter Process Communication backend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This OsmoTRX model provides its own Inter Process Communication (IPC) interface
 | 
					 | 
				
			||||||
to drive the radio device driver (from now on the Driver), allowing for third
 | 
					 | 
				
			||||||
party processes to implement the lowest layer device-specific bits without being
 | 
					 | 
				
			||||||
affected by copyleft licenses of OsmoTRX.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For more information on such interface, see section <<ipc_if>>.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[fig-backend-ipc]]
 | 
					 | 
				
			||||||
.Architecture with _osmo-trx-ipc_ and its IPC _Driver_
 | 
					 | 
				
			||||||
[graphviz]
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
digraph G {
 | 
					 | 
				
			||||||
        rankdir=LR;
 | 
					 | 
				
			||||||
        MS0 [label="MS"];
 | 
					 | 
				
			||||||
        MS1 [label="MS"];
 | 
					 | 
				
			||||||
        OsmoTRX [label="osmo-trx-ipc", color=red];
 | 
					 | 
				
			||||||
        BTS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        subgraph cluster_ipc_driver {
 | 
					 | 
				
			||||||
                label = "IPC Driver";
 | 
					 | 
				
			||||||
                color=red;
 | 
					 | 
				
			||||||
                RE [label = "Radio Equipment"];
 | 
					 | 
				
			||||||
                REC [label="Radio Equipment Controller"];
 | 
					 | 
				
			||||||
                RE->REC;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        REC->OsmoTRX [label="IPC Interface", color=red];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        MS0->RE [label="Um"];
 | 
					 | 
				
			||||||
        MS1->RE [label="Um"];
 | 
					 | 
				
			||||||
        OsmoTRX->BTS [label="bursts over UDP"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A sample config file for this OsmoTRX model can be found in _osmo-trx.git_ https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/doc/examples/osmo-trx-ipc/osmo-trx-ipc.cfg[doc/examples/osmo-trx-ipc/osmo-trx-ipc.cfg]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In the config file, the following VTY command can be used to set up the IPC UD Master Socket _osmo-trx-ipc_ will connect to at startup:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.Example: _osmo-trx-ipc_ will connect to UD Master Socket /tmp/ipc_sock0 upon startup
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
dev-args ipc_msock=/tmp/ipc_sock0
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
==== ipc-device-test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
When built with `--with-ipc --with-uhd` configure options, _osmo-trx.git_ will
 | 
					 | 
				
			||||||
build the test program called _ipc-driver-test_. This program implements the
 | 
					 | 
				
			||||||
_Driver_ side of the osmo-trx-ipc interface (see <<ipc_if>> for more
 | 
					 | 
				
			||||||
information) on one side, and also interacts internally with UHD (eg B210 as
 | 
					 | 
				
			||||||
when using osmo-trx-uhd).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
You can use this small program as a reference to:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Test and experiment with _osmo-trx-ipc_.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Write your own IPC _Driver_ connecting to osmo-trx-ipc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[fig-backend-ipc-device-test]]
 | 
					 | 
				
			||||||
.Architecture with _osmo-trx-ipc_ and ipc-device-test as IPC _Driver_
 | 
					 | 
				
			||||||
[graphviz]
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
digraph G {
 | 
					 | 
				
			||||||
        rankdir=LR;
 | 
					 | 
				
			||||||
        MS0 [label="MS"];
 | 
					 | 
				
			||||||
        MS1 [label="MS"];
 | 
					 | 
				
			||||||
        SDR;
 | 
					 | 
				
			||||||
        ipc_device_test[label = "ipc-device-test", color=red];
 | 
					 | 
				
			||||||
        OsmoTRX [label="osmo-trx-ipc", color=red];
 | 
					 | 
				
			||||||
        BTS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        MS0->SDR [label="Um"];
 | 
					 | 
				
			||||||
        MS1->SDR [label="Um"];
 | 
					 | 
				
			||||||
        SDR->ipc_device_test [label="UHD"];
 | 
					 | 
				
			||||||
        ipc_device_test->OsmoTRX [label="IPC Interface", color=red];
 | 
					 | 
				
			||||||
        OsmoTRX->BTS [label="bursts over UDP"];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
----
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The code for this app is found here:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/ipc-driver-test.h[Transceiver52M/device/ipc/ipc-driver-test.h]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* https://gitea.osmocom.org/cellular-infrastructure/osmo-trx/src/branch/master/Transceiver52M/device/ipc/ipc-driver-test.c[Transceiver52M/device/ipc/ipc-driver-test.c]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Those files use the server-side (_Driver_ side) code to operate the Posix Shared
 | 
					 | 
				
			||||||
Memory region implemented in files `shm.c`, `shm.h`, `ipc_shm.c` and `ipc_shm.h`
 | 
					 | 
				
			||||||
in the same directory.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Most of the code in that same directory is deliverately released under a BSD
 | 
					 | 
				
			||||||
license (unlike most of _osmo-trx.git_), allowing third parties to reuse/recycle
 | 
					 | 
				
			||||||
the code on their implemented _Driver_ program no matter it being proprietary or
 | 
					 | 
				
			||||||
under an open license. However, care must be taken with external dependencies,
 | 
					 | 
				
			||||||
as for instance shm.c uses the talloc memory allocator, which is GPL licensed
 | 
					 | 
				
			||||||
and hence cannot be used in a proprietary driver.
 | 
					 | 
				
			||||||
@@ -35,8 +35,6 @@ include::./common/chapters/vty_cpu_sched.adoc[]
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
include::./common/chapters/trx_if.adoc[]
 | 
					include::./common/chapters/trx_if.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include::{srcdir}/chapters/ipc_if.adoc[]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include::./common/chapters/port_numbers.adoc[]
 | 
					include::./common/chapters/port_numbers.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include::./common/chapters/bibliography.adoc[]
 | 
					include::./common/chapters/bibliography.adoc[]
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule osmocom-bb updated: f12b17dffb...05ddc05233
									
								
							@@ -1,8 +1,6 @@
 | 
				
			|||||||
AM_CPPFLAGS = $(LIBOSMOCODING_CFLAGS)
 | 
					AM_CPPFLAGS = $(LIBOSMOCODING_CFLAGS)
 | 
				
			||||||
AM_CFLAGS = -Wall
 | 
					AM_CFLAGS = -Wall
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DIST_SUBDIRS = va-test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXTRA_DIST = clockdump.sh matlab
 | 
					EXTRA_DIST = clockdump.sh matlab
 | 
				
			||||||
 | 
					
 | 
				
			||||||
noinst_PROGRAMS = osmo-prbs-tool
 | 
					noinst_PROGRAMS = osmo-prbs-tool
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,531 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
					 | 
				
			||||||
 * All Rights Reserved
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Author: Eric Wild <ewild@sysmocom.de>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 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 <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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 <convolve.h>
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define _CRT_SECURE_NO_WARNINGS
 | 
					 | 
				
			||||||
#include <algorithm>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <iomanip>
 | 
					 | 
				
			||||||
#include <numeric>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
#include <iostream>
 | 
					 | 
				
			||||||
#include <fstream>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef HAVE_CONFIG_H
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <grgsm_vitac/grgsm_vitac.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DO_RACH
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const int SAMPLE_SCALE_FACTOR = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template <typename DST_T, typename SRC_T, typename ST>
 | 
					 | 
				
			||||||
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_T *>(dst)[i] = static_cast<DST_T>((reinterpret_cast<SRC_T *>(src)[i]) * scale);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
template <typename DST_T, typename SRC_T>
 | 
					 | 
				
			||||||
void convert_and_scale_default(void *dst, void *src, unsigned int src_len)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return convert_and_scale<DST_T, SRC_T>(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<char> bits;
 | 
					 | 
				
			||||||
	signalVector *rvbuf;
 | 
					 | 
				
			||||||
	std::unique_ptr<std::vector<std::complex<float>>> 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]; ///<encoded training sequence of a SCH burst
 | 
					 | 
				
			||||||
extern gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a SCH burst
 | 
					 | 
				
			||||||
extern gr_complex d_norm_training_seq[TRAIN_SEQ_NUM]
 | 
					 | 
				
			||||||
				     [N_TRAIN_BITS]; ///<encoded training sequences of a normal and dummy burst
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void sv_write_helper(signalVector *burst, std::string fname)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	auto start = burst->begin();
 | 
					 | 
				
			||||||
	auto n = burst->bytes();
 | 
					 | 
				
			||||||
	char *data = reinterpret_cast<char *>(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<std::complex<float>> 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<float> chan_im_resp_trunc = { 1., 0.20513351, 0.10020305, 0.11490235 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template <typename A, typename B>
 | 
					 | 
				
			||||||
auto conv(const std::vector<A> &a, const std::vector<B> &b) -> std::unique_ptr<std::vector<A>>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int data_len = a.size();
 | 
					 | 
				
			||||||
	int conv_len = b.size();
 | 
					 | 
				
			||||||
	int conv_size = conv_len + data_len - 1;
 | 
					 | 
				
			||||||
	auto retv = std::make_unique<std::vector<A>>(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 <typename A>
 | 
					 | 
				
			||||||
static auto conv(const A *a, int len, std::vector<float> &b)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	std::vector<A> aa(len);
 | 
					 | 
				
			||||||
	std::copy_n(a, len, aa.begin());
 | 
					 | 
				
			||||||
	std::reverse(b.begin(), b.end());
 | 
					 | 
				
			||||||
	return conv(aa, b);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
template <typename A>
 | 
					 | 
				
			||||||
static auto conv(const A *a, int len, std::vector<A> &b)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	std::vector<A> 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 <typename T>
 | 
					 | 
				
			||||||
size_t read_from_file(std::string path, std::vector<T> &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<char *>(&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<std::complex<float>> burstdata;
 | 
					 | 
				
			||||||
	std::vector<char> 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<complex *>(&burstdata[offset]);
 | 
					 | 
				
			||||||
	auto stdcplx = reinterpret_cast<std::complex<float> *>(&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<SoftVector>(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<float> 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<char[]>(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<short[]>(len_in_real);
 | 
					 | 
				
			||||||
	auto cvrtbuf_rx_a = std::make_unique<float[]>(len_in_real);
 | 
					 | 
				
			||||||
	auto rx_cfloat = reinterpret_cast<std::complex<float> *>(&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<float> 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<char[]>(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<float> 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<complex *>(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<SoftVector>(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<float> 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<complex *>(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<float> 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<complex *>(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();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user