Compare commits

...

678 Commits

Author SHA1 Message Date
Eric
a0e1ed3215 ms-trx support
This is basically a trxcon that includes a transceiver, and can just
be used with existing and future apps supporting the trxcon interface,
i.e. mobile or ccch_scan.

Supports bladerf and uhd, binaries are automatically built if those libs
are detected + the osmocom-bb submodule exists.
Currently using hardcoded sched/prios aimed at a setup with working,
reliable usb and reserved cores, for example a raspi 4 (ONLY 4, not 3,
not 2, not any other version)

Additionally builds test tools used for development: osmo-trx-syncthing*

Change-Id: I36c65a8c725c4da76dc70006cd96b0a2b6878e84
2022-12-01 12:00:04 +01:00
Eric
a5439daaf7 vita demod by piotr krysik, modified
Had a few rounds of extensive cleanup. Uses gcc multiversioning for x86
targets.

Change-Id: I5466c522cf4de984a4810ec46df43a10b52ed78f
2022-12-01 12:00:04 +01:00
Eric
42cc715fac ill-fated ipcv2 for mstrx
The problem here is that the ipc if requires reducing the clock ind
inteval to a few fn/ts on the trx side to work at all, but scheduling
still does not work out, unless you start driving the IF using the tx
side, at which point the approach is useless, because it does not really
do more than a burst loopback that is easier to do with the higher
layers/interfaces.

The code is still useful should there be a reason to continue working on
this.

Change-Id: I8f582c7c06fed8d1dcc5ea52472a97dc313fdde5
2022-12-01 12:00:04 +01:00
Eric
008418327b bladerf xa4 support
This is not really finished, there are multiple reasons to not use this:
1) main clock is not a gsm multiple, so it will continously drift
2) small buffer sizes lead to tx gaps that are hard to detect and break
everything.

Change-Id: I455c34bb9520d5f09eeb1ac76fceb4bdea94d1ac
2022-12-01 12:00:04 +01:00
Eric
040497e0a4 osmocom-bb for ms-trx side trxcon integration
Change-Id: I784a3d66b68f6458056d92db2ec596755b704e61
2022-12-01 12:00:04 +01:00
Eric
8984d7f2ca rename noisevector class -> avgvector
The vectors feature is averaging, and not adding noise.

Change-Id: I05def8ab9ea7a2cece8db09c36c303e13ef40927
2022-11-30 16:40:42 +01:00
Eric
aa7a40ee84 ignore vscode dirs
Change-Id: Iad9fd20924b7cfc6dbbfb708aa9c692a3cab574c
2022-11-28 19:19:38 +01:00
Max
f2f35fc592 Add realtime scheduling and set priority in service file
This sets highest realtime priority among all Osmocom services.

Related: OS#5687
Change-Id: Id74acf201d4388493f0eeb38909641c662551164
2022-11-11 17:33:25 +03:00
Vadim Yanitskiy
00ddcfaf50 Transceiver::expectedCorrType(): RACH is always 8-bit on PTCCH/U
It does not make sense for the MS to use 11-bit Access Bursts on
PTCCH/U because the payload does not matter, only the ToA does.

Change-Id: I5fb9f1c6810cdcd26a885b183e414d01d422eb28
2022-10-26 04:13:43 +07:00
Max
2f20c564bf Set working directory in systemd service file
By default systemd will execute service with root directory
(or home directory for user instance) which might result in
attempts to create files in unexpected place. Let's set it
to 'osmocom' subdir of state directory
(/var/lib for system instance) instead.

Related: OS#4821
Change-Id: I041bb9e0b4250826d2d15d0ea2cdb93d7a0cd04b
2022-09-09 18:54:42 +07:00
Vadim Yanitskiy
19faae85c6 threshold_timer_update_intv(): call osmo_timer_del() unconditionally
osmo_timer_del() does check if a timer is active internally.

Change-Id: Icaf6f31a3235a3fb6993fa2bb35190150e35c2c2
2022-08-06 05:03:00 +07:00
Oliver Smith
1c6a3459cd contrib/jenkins: don't run "make distcheck" on arm
Avoid building osmo-trx a second time on arm during "make distcheck". If
the build of osmo-trx already passed on arm, running "make distcheck"
should give the exact same result as on x86_64.

This should shorten the build time significantly for osmo-trx jobs
running on raspberry pis, currently they take half an hour.

Change-Id: Ib4fbf7d54d479bbdda3c1415493bfc57b37d3971
2022-07-11 13:57:49 +02:00
Oliver Smith
32311d8635 gitignore: add uhddev_ipc.cpp
This file gets generated during the build.

Change-Id: I70bfb456e309daa4436767b2e55bce0c038a4975
2022-07-08 14:35:49 +02:00
Oliver Smith
71c46e91df configure.ac: add -lboost_thread for uhd < 4.2.0
Fix for the following error we see since building master-osmo-trx on
debian 10 instead of 9:
  /usr/bin/ld: ipc_driver_test-uhdwrap.o: undefined reference to symbol '_ZTIN5boost6detail16thread_data_baseE'
  /usr/bin/ld: //usr/lib/x86_64-linux-gnu/libboost_thread.so.1.67.0: error adding symbols: DSO missing from command line

After spending a lot of time on researching this, my understanding is
now that uhd.pc should have had "-lboost_thread" in versions up to the
latest release 4.2.0 because before that it would include boost thread
headers in its logging code:
04a83b6e76

ld is able to figure out which library provides the missing symbol, and
apparently depending on the binutils version and linker flags, it may
just ignore this and not show an error. This is why apparently it worked
with debian 9 and still does work in OBS (different flags), and why it
was not fixed upstream in uhd.pc. By now fixing it is not needed in the
latest version anymore, and there are already versions of uhd.pc in
various linux distributions without -lboost_thread, so I think it's
appropriate to add the workaround here in configure.ac.

Fixes: OS#5608
Related: https://stackoverflow.com/q/19901934
Change-Id: I0367f1c2981bf56252e7514d5993cbbec960b21b
2022-07-08 14:35:36 +02:00
Pau Espin Pedrol
a39fa875a3 Bump version: 1.4.0.3-9a3e → 1.4.1
Change-Id: I9a930264b7c40b3e205c9818634597cc21364a50
2022-06-29 09:32:57 +02:00
Harald Welte
9a3e3fceb8 update git URLs (git -> https; gitea)
Change-Id: I1ac62853250a6717f502959bd96fdc3e9ead7a91
2022-06-18 13:52:06 +02:00
Vadim Yanitskiy
1a19caf002 tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
When using 'check_PROGRAMS', autoconf/automake generates smarter
Makefiles, so that the test programs are not being compiled during
the normal 'make all', but only during 'make check'.

Change-Id: I816689e2aeac9decbc44ba210956a929cc7a3169
2022-04-13 19:55:36 +03:00
Oliver Smith
424c74d006 treewide: remove FSF address
Remove the paragraph about writing to the Free Software Foundation's
mailing address. The FSF has changed addresses in the past, and may do
so again. In 2021 this is not useful, let's rather have a bit less
boilerplate at the start of source files.

Change-Id: I8ba71ab9ccde4ba25151ecbeb2a323f706b57d43
2021-12-14 12:23:00 +01:00
Pau Espin Pedrol
a7143d3cd0 Bump version: 1.3.1.28-019d-dirty → 1.4.0
Change-Id: Ie675909593b0c383b59b7b4a4edd46cd93283622
2021-11-16 16:27:26 +01:00
Vadim Yanitskiy
019d698126 LMSDevice: LMS_GetDeviceList() may return a negative number
Change-Id: I855bd8ea6d9cb0f285f4dbbf3bcd09bff4e71044
Fixes: CID#240718
2021-10-25 13:12:51 +03:00
Vadim Yanitskiy
a686277c72 IPCDevice: check value returned from select()
Change-Id: I1c823317659547bb2391c57ac4d7931de1a383e3
Fxies: CID#240744
2021-10-25 13:10:18 +03:00
Vadim Yanitskiy
683f140739 IPCDevice: use thread safe strerror_r() instead of strerror()
Change-Id: Ia51ffa51ec7729572faca0282ae41c1e4968049f
2021-10-25 12:56:44 +03:00
Vadim Yanitskiy
5e40d92400 trx_rate_ctr: use thread safe strerror() in device_sig_cb()
Change-Id: Ibd52af22bbe99652f402ada87410de167a124b73
2021-10-25 12:56:44 +03:00
Pau Espin Pedrol
bb2cb9d54b lms,uhd: Allow changing band between poweroff & poweron
Before this patch, reconnecting to osmo-trx and attempting to configure it for
another band is not going to work without restarting the process.
The new variable is added in order to still allow POWEROFF followed by a
POWERON without need to reconfigure the device. In that case, previous
configuration is kept.

Change-Id: I43e5e1e4dcb36be605c6bd25dd6a5f3649e244e7
2021-09-21 17:24:18 +02:00
Pau Espin Pedrol
b9423b25b6 lms,uhd: Skip re-assigning same band
There's no need to spend time looking up again the same band
description.

Change-Id: I6f5631c9e64b9c261d52a856d757d08d2f336947
2021-09-21 17:24:18 +02:00
Pau Espin Pedrol
069f5cd857 lms,uhd: Validate band of RxFreq too
So far the validation is only done on TxFreq for all TRX. Let's also do
it for RxFreq.

Change-Id: I30eef2727ee96b1344aa1416edd66e2302b88964
2021-09-21 17:24:11 +02:00
Pau Espin Pedrol
c90b207803 lms: Drop duplicated check
Same check is already done by set_band().

Change-Id: I48d14f35e83fa17d1a8f4154479f0a5cee0f816d
2021-09-21 13:48:20 +02:00
Pau Espin Pedrol
985694175d computeCI: Document hardcoded multiplier
Logarithm change of base rule is used. Document it so it's clear where
it comes from.

Change-Id: Ia588e8dafda4e1abe0721f12491661949339a1ba
2021-09-03 13:52:02 +02:00
Oliver Smith
ac8a4e7297 d/patches/build-for-debian8.patch: remove
Remove this workaround, as we are not building for debian 8 anymore.

Related: OS#5223
Depends: osmo-ci Ibe7ba124557969df62798ba49c4489e9606c2341
Change-Id: I5519075a7f95fa61b0b5f1825e4e9324b9eede76
2021-09-03 08:26:59 +00:00
Pau Espin Pedrol
e16d0e1330 cosmetic: Fix typo in comment
Change-Id: I33f4253cecab8d92eec75af49e1671874b8cc111
2021-09-01 20:43:03 +02:00
Pau Espin Pedrol
e6fdf8fcad detectGeneralBurst(): Increase log level about clipping to INFO
There's another related logging line also at INFO level in the caller
path in  Transceiver.cpp, but it only prints if detectBurst() failed.
Let's print this one as INFO too, which proved to be a good logging
level. This way user also notices gain is too high despite osmo-trx is
still able to decode bursts.

Change-Id: Ieca4f19ae1099a430e9b838f8b6780b1c61a87a9
2021-09-01 20:36:33 +02:00
Pau Espin Pedrol
cdd77a447d computeCI(): Constify read-only variable
Change-Id: Ia157b970db92eef252c3657b35607307b7ebf988
2021-09-01 20:10:04 +02:00
Pau Espin Pedrol
7f696801ae computeCI(): Rename verbose repeated getter to constant
Change-Id: I9b426d01a282f572c0b915c5666642dce4c60475
2021-09-01 20:08:55 +02:00
Pau Espin Pedrol
d16eb314ed computeCI(): Constify param and pass it as reference
Change-Id: Icba5fce57c858bd16196ae3012c100c7e4134335
2021-09-01 19:51:28 +02:00
Pau Espin Pedrol
27bd2f6dd1 detectBurst(): constify parameter
Change-Id: I3d8738b492a175f2ef0c570579e335e7b7695694
2021-09-01 19:46:43 +02:00
Pau Espin Pedrol
8803f923f9 detectBurst(): Clear downsampling code path
downsampleBurst() and the Resampler below it clearly only support or are
confgiured for 1<->4 setup currently.

Change-Id: Iebaff7a34bd24e56627f148182859918accbfa82
2021-09-01 19:43:11 +02:00
Eric
ecea734b97 lms: init band
Gain setting without a band was apparently led to a very low output
level, thanks to defog for pointing this out.

Change-Id: I8b59d38dd7b0781776c9e61226185879541fdc53
Related: OS#3342
2021-07-11 21:12:04 +02:00
Eric
0c34c64a16 vty: printing fn offset should be signed
...because it is usually negative

Change-Id: I8297dbb0fec25720e73d59fd8e38834029154405
2021-06-16 15:20:51 +02:00
Pau Espin Pedrol
0a038223d0 Use new stat item/ctr getter APIs
Change-Id: I1fdfdae2810c3c82ff62fe725ffa364df4ebeff5
2021-06-04 17:21:42 +02:00
Eric
5e6b10cd9e uhd: ensure configured clock source is actually used
We wouldn't want to get caught running with unlocked external clock
sources, right?!

Change-Id: Ie38d85617f46eb5ab7d9527ddf6aaab4d3edf6bf
2021-05-29 15:55:28 +00:00
Vadim Yanitskiy
b6f238c0f2 ctrl_sock_handle_rx(): fix missing space in LOGCHAN() statement
Change-Id: I3c69d64dfe79dcc815e1d412569ed4e9ed428c52
2021-05-27 21:40:13 +00:00
Eric
c27fe60a25 add hidden fn adjustment command
This is only useful if the rf path delays the signal by at least one
frame, and therefore a fairly experimental command that might be removed
or reworked in the future and should not be relied upon.

Change-Id: I29964acffad5bad4f5bcad7f631e435a72979c46
2021-05-05 17:34:28 +02:00
Vadim Yanitskiy
a1ea63f777 gitignore: remove non-existing 'doc/manuals/osmomsc-usermanual.xml'
Change-Id: If0fef3f12f15780ed3a3e33db25cd29082ff142a
2021-04-16 19:04:48 +02:00
Pau Espin Pedrol
c7930b0b22 ipc: Makefile.am: Clean LDADD variable
Change-Id: I26c942496ab12883a4a1e0d549cb462642570636
2021-03-01 16:35:42 +01:00
Pau Espin Pedrol
17ce7740e5 Threads: Avoid printing pthread_self()
The type used to represent a thread ID is implementation
specific, and may be an opaqe structure, making it unsuitable to be
printed by standard means. Let's use osmo_gettid() instead.

Change-Id: Iaa4d0eaf52b901fff06cc67f8dd8b61ac6084911
Related: OS#5032
2021-03-01 16:35:42 +01:00
Pau Espin Pedrol
d06259f348 Drop logging pthread ID
new libosmocore osmo-trx already depends on does support printing thread
ID as prefix to all messages (confgiurable through VTY), so there's no
use in printing it in osmo-trx unconditionally.

Moreover, The type used to represent a thread ID is implementation
specific, and may be an opaqe structure, making it unsuitable to be
printed by standard means, so in any case we should be better printing
system's TID instead.

Related: OS#5032
Change-Id: Ie98a21246230c946afc47f4f5b9c6618eefde494
2021-03-01 16:35:42 +01:00
Pau Espin Pedrol
6c646c35b9 Threads.cpp: Fix missing extern C around libosmocore include
Change-Id: I76975ed71382ff2afa8cfaff2950e23ff750201e
2021-03-01 16:35:35 +01:00
Harald Welte
90d841748e Bump version: 1.3.0.1-e2404 → 1.3.1
Change-Id: I559b8d8608b3e492ae1ba0d5a54e226ab424b23b
2021-02-28 11:32:12 +01:00
Harald Welte
e2404f4e41 mark uhddev_ipc.cpp as BUILT_SOURCES
fixes "make dist-bzip2" on a clean checkout

Closes: OS#5052
Change-Id: Ieb4cefb16c8f43e708a96353c13342fe40ffdb54
2021-02-28 11:02:25 +01:00
Pau Espin Pedrol
309ad4d901 Bump version: 1.2.0.132-3b8f-dirty → 1.3.0
Change-Id: I92b99ebab1d54e9cbdc8469d76105c55bcb03f36
2021-02-23 14:27:15 +01:00
Vadim Yanitskiy
3b8f7c4d97 Add a (hidden) VTY parameter for Rx/Tx freq. shifting
Change-Id: I360e8ba91471757210c7f096c04928a6fbb91c61
Related: SYS#4454
2021-02-21 12:01:16 +01:00
Pau Espin Pedrol
48cad832ea tests: Replace deprecated API log_set_print_filename
Change-Id: I3cc0a92da39ab2594b3a7cefb314e2f2ecb628e2
2021-02-19 14:09:01 +01:00
Pau Espin Pedrol
56237bce95 tests: Explicitly drop category from log
Let's disable category here since we don't care about its formatting here.

In any case, every test relying on logging output validation should
always explicitly state the config to avoid issues in the future if
default values change.

Change-Id: Iaa77f8a7d3f752173507afd988bd76a8aa632082
Related: OS#5034
2021-02-19 14:08:44 +01:00
Pau Espin Pedrol
5738940535 Replace my_gettid with libosmocore osmo_gettid API
The API was moved to libosmocore, let's use it instead of defining our
own here with all the complexity in build system involved.

Depends: libosmocore.git Change-Id Id7534beeb22fcd50813dab76dd68818e2ff87ec2
Related: OS#5027
Change-Id: I19e32fbc47bd88a668e0c912e89b001b0f8831dd
2021-02-17 18:27:41 +01:00
Pau Espin Pedrol
cec9eda227 Threads.cpp: Use already existing gettid wrapper function
A wrapper function with better support already exists in debug.c and
announced in debug.h. Let's use that one instead.

Related: OS#5027
Change-Id: I2ccf94f95a531d5873da2a4681cf89cbc5b31422
2021-02-17 17:28:06 +01:00
Sylvain Munaut
ad202d72e1 sigProcLib: fix C/I computation for 8-PSK modulated bursts
Change-Id: I860af60bc0fbd36dfb38316fad65ddd3a5827a8f
Related: Ib4ceec553f2e5f77bf3f6777724968456a180f5e
Related: OS#4006, OS#4373
2021-02-04 20:44:51 +01:00
Oliver Smith
0f4d5791df configure.ac: set -std=gnu11
Change-Id: Ie95876d1d2ebf31ff588999d85584f6981522fa8
2021-01-28 10:48:35 +00:00
Vadim Yanitskiy
2a637a5c9c Transceiver: use proper factor for amplitude scaling
In Transceiver::addRadioVector() we scale the I/Q samples by scaling
the output voltage of the DAC.   A relative factor/divisor/ration in
the voltage domain cannot be used 1:1 in the power domain.

There exist two similar formulas:

  a) X_dB = 10 * log10(X_lin / X_ref)
  b) Y_db = 20 * log10(Y_lin / Y_ref)

both of them are correct, and according to [1]:

  a) If you convert a quantity X that relates to power or energy,
     => the factor is 10.
  b) If you convert a quantity Y that relates to amplitude,
     => the factor is 20.

Therefore we should be using 20 instead of 10.  This change makes
osmo-trx apply per-lchan attenuation values correctly.  Otherwise
it would double the values indicated in TRXD messages.

[1] https://dspillustrations.com/pages/posts/misc/decibel-conversion-factor-10-or-factor-20.html

Change-Id: I98bc00bd25df4913d45e55eb008d715aca76fc7c
Related: SYS#4918
2021-01-27 01:01:50 +01:00
Vadim Yanitskiy
819cad1776 Transceiver: fix integer division in addRadioVector()
By default, C/C++ compiler does assume integer division.  The
lack of explicit cast to 'double' causes the transceiver to
ignore non-decimal attenuation values (x % 10 > 0):

  txFullScale * 10 ^ ( -3 / 10)
	== txFullScale * 10 ^ 0
	== txFullScale * 1.0

  txFullScale * 10 ^ ( -8 / 10)
	== txFullScale * 10 ^ 0
	== txFullScale * 1.0

  txFullScale * 10 ^ (-10 / 10)
	== txFullScale * 10 ^ -1
	== txFullScale * 0.1

  txFullScale * 10 ^ (-18 / 10)
	== txFullScale * 10 ^ -1
	== txFullScale * 0.1

Change-Id: I85b1063f57f630d90c6da32827bec4a05afc6514
Related: SYS#4918
2021-01-21 00:24:16 +01:00
Pau Espin Pedrol
54a98b5b52 ChannelizerBase: Fix memory leak
The memory leak was reported by ASan:

Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x7f23b488e459 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x558e83e39e3c in ChannelizerBase::initFilters() /osmo-trx/Transceiver52M/ChannelizerBase.cpp:84
    #2 0x558e83e3a8a0 in ChannelizerBase::init() /osmo-trx/Transceiver52M/ChannelizerBase.cpp:188
    #3 0x558e83e2d263 in RadioInterfaceMulti::init(int) /osmo-trx/Transceiver52M/radioInterfaceMulti.cpp:197
    #4 0x558e83de76d2 in makeRadioInterface(trx_ctx*, RadioDevice*, int) /osmo-trx/Transceiver52M/osmo-trx.cpp:115
    #5 0x558e83dea663 in trx_start /osmo-trx/Transceiver52M/osmo-trx.cpp:600
    #6 0x558e83dead6f in main /osmo-trx/Transceiver52M/osmo-trx.cpp:695
    #7 0x7f23b2576151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)

Change-Id: Ibc4c7edeb9bba517db08fce152d863e6cc0c7bbb
2021-01-18 11:39:24 +00:00
Pau Espin Pedrol
fca503d0b4 radioInterfaceMulti: Fix memory leak upon close()
The leak was reported by ASan.

Direct leak of 48 byte(s) in 1 object(s) allocated from:
    #0 0x7fd9c9c29f41 in operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cpp:99
    #1 0x55bd63ae2364 in RadioInterfaceMulti::init(int) /git/osmo-trx/Transceiver52M/radioInterfaceMulti.cpp:209
    #2 0x55bd63a9c6d2 in makeRadioInterface(trx_ctx*, RadioDevice*, int) /git/osmo-trx/Transceiver52M/osmo-trx.cpp:115
    #3 0x55bd63a9f663 in trx_start /git/osmo-trx/Transceiver52M/osmo-trx.cpp:600
    #4 0x55bd63a9fd6f in main /git/osmo-trx/Transceiver52M/osmo-trx.cpp:695
    #5 0x7fd9c7910151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)

Change-Id: Ia4f9d4e47caa86ada98054763573e652d281992c
2021-01-17 17:18:49 +00:00
Oliver Smith
e8edd1fcae contrib/jenkins: don't build osmo-gsm-manuals
Related: OS#4912
Change-Id: Ibacb11da37acfd324cee37068099627136717781
2021-01-13 13:16:48 +01:00
Alexander Couzens
7e27deb8cb osmo-trx.spec: move ipc-driver-test into package ipc-test
Allow to drop the uhd runtime dependency of osmo-trx-ipc.
uhd is only required for the driver-test utility.

Related: SYS#5266
Change-Id: Iff91e09684167247c9c7de0141451a5b9344aa0d
2021-01-08 09:32:03 +01:00
Harald Welte
a9512d963a manual: Fix typo OsmTRX -> OsmoTRX
Change-Id: I4b3a76e41d4abbb08046a241ae9b7c079ce990ae
2021-01-07 14:07:14 +01:00
Harald Welte
c6220741b1 README update
* use https for hyperlinks
* explicitly mention the primary use case with OsmoBTS
* fix spelling in title

Change-Id: I4f20ad8666dcc6bbc23d78b40b7c73ddd7e6eacc
2021-01-06 13:27:56 +01:00
Pau Espin Pedrol
4a4e607a19 ipc-driver-test: Allow setting dir prefix for UD socket
Change-Id: I35282b38a1d560fb3440fe0aa9a27808d9d116cc
2020-12-10 15:26:32 +00:00
Vadim Yanitskiy
1587307a99 vty: fix swapped documentation for 'filler type' command
vty_cmd_string_from_valstr() expands the given 'struct value_string'
sequentionally, so the order of entries in both filler_{types,docs}
shall match (regardless of the value assigned).

Change-Id: Ieb3bbc4fb30f303c47555ca77d03a9e965bc72b5
2020-12-08 15:38:00 +01:00
Pau Espin Pedrol
7e83f18bba ipc: Fix wrong reference to BTS in log line
Change-Id: Idd272959e335c46ca88e348dd792e15ddb317d61
2020-12-07 19:28:44 +01:00
Pau Espin Pedrol
57db77f185 main: generate coredump and exit upon SIGABRT received
Previous code relied on abort() switching sigaction to SIG_FDL +
retriggering SIGABRT in case the signal handler returns, which would
then generate the coredump + terminate the process.
However, if a SIGABRT is received from somewhere else (kill -SIGABRT),
then the process would print the talloc report and continue running,
which is not desired.

Change-Id: I3a3ff56cb2d740a33731ecfdf76aa32606872883
Fixes: OS#4865
2020-11-25 17:50:21 +01:00
Harald Welte
94def47fdf Use osmo_fd_*_{disable,enable}
Change-Id: Ic8c8c418e123fbdff625556a900b19650deefe0b
Depends: libosmocore.git Idb89ba7bc7c129a6304a76900d17f47daf54d17d
2020-11-11 20:15:59 +00:00
Vadim Yanitskiy
3fb4d31ecb doc/manuals: generate XML VTY reference at build-time
Unfortunately, we cannot re-use the existing Makefile rules from:

  $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc

because they do not allow to generate the list of $(DOCBOOKS) from
a template, and require the project to store everything in separate
folders with specific names.  Also, those rules expect that the
target PDFs contain only a single word in their names (for example,
'osmoapp-vty-reference', not 'osmo-app-vty-reference'), while in a
project with multiple similarly named targets this would reduce
readability (imagine 'osmotrxuhd-vty-reference').

Change-Id: I798ea3b7417b8ca3e9c7d50911158c5413526237
Depends: I6aac73d998c5937894233631e654a160d5623198
Related: SYS#4937, SYS#4910
2020-11-04 19:33:05 +00:00
Vadim Yanitskiy
744e44eaa1 main: use logging API to print SIMD info instead of printf()
Otherwise these logging lines end up in the automatically generated
XML VTY reference (stdout), so this breaks further XML processing.

Change-Id: I8e0fd728d406e2452c9c0ddad5bce5f6b17fab42
Related: SYS#4937, SYS#4910
2020-11-04 19:33:05 +00:00
Vadim Yanitskiy
faacb1987e vty: fix documentation for 'ext-rach (disable|enable)'
Do not use 'extended' because it's not the same 11-bit Access Burst,
as it was assumed before.  Add missing docs for 'enable'/'disable'.

Change-Id: I80b5a584e554eb7cc2416017b10fee032202b372
2020-11-04 19:29:45 +00:00
Vadim Yanitskiy
c0e7ce922a vty: auto-generate cmd and doc strings for cfg_filler_type_cmd
Change-Id: I7fb228c63f3246f443ece67106abba0432b1659e
2020-11-02 09:28:19 +00:00
Vadim Yanitskiy
ab6e7f35ab vty: remove groundless statement about filler type 'dummy'
Dummy bursts have nothing to do with A5/x encryption, and I see
no reason why (and how?!?) would using that filler type break
encryption in osmo-bts-trx.  I asked the author of this code
back in August 2020 [1], and so far didn't get any response.

[1] https://lists.osmocom.org/pipermail/openbsc/2020-August/013208.html

Change-Id: Iae513d7acbb8ef682e1744ac8726cbd6ece8bd87
2020-11-02 09:27:59 +00:00
Vadim Yanitskiy
5d6504c45a vty: fix documentation for 'multi-arfcn (disable|enable)'
Change-Id: Id653ee058b208ddc105947319adad8da667be11f
2020-11-02 09:27:14 +00:00
Vadim Yanitskiy
c620ced36d vty: cosmetic: use VTY_IPV4_CMD in 'bind-ip' / 'remote-ip'
Change-Id: I8e44f771cbd03629c066bc24c3186997761f93f1
2020-11-02 09:27:08 +00:00
Vadim Yanitskiy
ef79fd9b95 vty: fix documentation for 'rx-sps (1|4)' and 'tx-sps (1|4)'
Change-Id: I70d9b16fd2b1c2cbaafc978724369cd2c9679cbd
2020-11-02 09:27:02 +00:00
Vadim Yanitskiy
e0bdb6b47b vty: fix documentation for 'egprs (disable|enable)'
Change-Id: I7a28bede8fd7d68b3afe9deec381fc93e46d65a9
2020-10-30 04:17:39 +07:00
Vadim Yanitskiy
948b4e4096 vty: fix documentation for 'swap-channels (disable|enable)'
Change-Id: Idca1a2beab07ef4df9ae5c55658cab80f7cc7565
2020-10-30 04:17:39 +07:00
Vadim Yanitskiy
c7a750d428 Transceiver: explicitly init m{Rx,Tx}LowerLoopThread
Coverity warns us that a non-static class members:

  - mRxLowerLoopThread, and
  - mTxLowerLoopThread,

are not initialized in this constructor nor in any functions that
it calls.  I don't think it's critical, because we do initialize
them in Transceiver::start(), but let's make them nullptr.

Change-Id: If9e06aa7965f17383ab6599c15945e8ce2703bbf
Fixes: CID#214952
2020-10-25 15:24:21 +07:00
Vadim Yanitskiy
0ff9c9fca3 Transceiver: use size_t and ARRAY_SIZE() in constructor
Change-Id: I164d66aad04d77957300b07e83b085f43a3ee8c1
2020-10-24 23:41:57 +00:00
Vadim Yanitskiy
24cb0c9948 device: drop unreasonable LIBOSMO{CTRL,VTY}_{CFLAGS,LIBS}
Neither VTY nor CTRL API is used in device specific code, excluding
the 'uhd' where osmo_cpu_sched_vty_apply_localthread() is called.

Change-Id: I568b443da4b96c005734d749faa22b9c7440f951
2020-10-24 23:41:57 +00:00
Vadim Yanitskiy
6be2d15541 main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
Change-Id: Ie54c45fdcc8660f37f8db2367b53404b189b3ffc
Depends: Ie2022a7f9e167e5ceacf15350c037dd43768ff40
Related: SYS#4910
2020-10-24 21:16:17 +00:00
Vadim Yanitskiy
bc5263cee1 device/common/Makefile.am: remove $(LMS_CFLAGS) from AM_CXXFLAGS
This is device-independent code, so it should not be here.

Change-Id: I1ffc3431a9a1a46c74c354b3f8a256684bfcbe73
2020-10-24 19:44:21 +00:00
Vadim Yanitskiy
6b4acc12f7 device/lms: get rid of 'using namespace std'
Change-Id: I4329801c502db73efa946f15c103b2c081cee5a7
2020-10-24 19:25:32 +07:00
Vadim Yanitskiy
d1ca287d83 device/lms: fix missing semicolon in LMSDevice::assign_band_desc()
Change-Id: I6aedb72306461ebb944fc13a795b0bf3121ea275
2020-10-24 19:25:32 +07:00
Vadim Yanitskiy
a0d862ba1d device/lms: fix: 'trx_vty.h' header requires C linkage
Otherwise, the linker fails to produce osmo-trx-lms binary:

  LMSDevice.cpp:493: undefined reference to
    `get_value_string(value_string const*, unsigned int)'

  LMSDevice.cpp:237: undefined reference to
    `osmo_panic(char const*, ...)'

Change-Id: I2fef166c13136af7b7aaa744d39427d76ad11769
Fixes: OS#4828
2020-10-24 19:25:32 +07:00
Harald Welte
c5989fe180 Use osmo_fd_setup() wherever applicable
Change-Id: Ie093dea96ec8990368695c0c5824e0fe44fb8540
2020-10-19 12:27:36 +02:00
Harald Welte
08970c562f ipc: Use OSMO_FD_* instead of deprecated BSC_FD_*
Change-Id: I98b3f9525954d6882f7488d650038a8e28f7b769
2020-10-18 22:41:40 +02:00
Pau Espin Pedrol
e91544d740 Calculate RSSI offset based on RxGain configuration
Prior to this patch, osmo-trx relied totally on proper VTY configuration
being set in "rssi-offset" together with the RxGain set through TRXC in
order to provide correct Uplink RSSI measurements to bts-trx.

With this patch, RSSI is now by default calculated (in LMS and UHD
backends) based on the currently set RxGain, by providing empirically
discovered values. Still, for backward compatibility, the old
"rssi-offset" command will overwrite completely the per-default
calculated rssi offset.
A new optional parameter "relative" is added at the end of the
"rssi-offset" VTY command to flag the value as relative to the newly
per-default calculated value. This way specific setups (like adding a
LNA / RF fronted) can still be expressed while still keeping the
automatic per-default offset.

Related: OS#4468
Change-Id: I8ef78fd20c22c60d61bfb18d80a4a36df4fd6c20
2020-10-14 12:53:04 +02:00
Pau Espin Pedrol
93fee1f163 Transceiver: Pass config struct instead of large list of params
Change-Id: Ifb43cb11f3e7a69b0a88f632f0a0c90ada7f939e
2020-10-14 12:52:04 +02:00
Pau Espin Pedrol
e69a56cec5 contrib/jenkins: Enable parallel make in make distcheck
Change-Id: I32925b35126bcd4ef7b5e1315dde28869c2b4b86
Related: OS#4421
2020-10-12 19:48:47 +02:00
Philipp Maier
76795401fb osmo-trx: add commandline option --vty-ref-xml
The commandline option --vty-ref-xml is needed to enable automatic
generation of the VTY reference manual.

Change-Id: I34dd36183e013ab005f39b235c4ab561590befb7
Related: SYS#4937, OS#1601
2020-10-09 20:48:00 +02:00
Philipp Maier
30863e8720 vty: add attributes to VTY commands indicating when they apply
Change-Id: I6dfdedc081eb8c3d53913f6fa38591920c8b3b43
Related: SYS#4937, OS#1601
2020-10-08 19:36:35 +02:00
Pau Espin Pedrol
0fbdfefebc arch: x86: Fix convolve optimizations breaking signal
This patch fixes MS failing to even see the network, and only RACHs of 1
zeroed byte being seen in GSMTAP.

The issue seems to only appear on some specific machines; others have
been running fine for weeks without this memset being an issue.

Fixes: 7a52e42ee0
Change-Id: I98ad885a5d71e7775973a4d881c0f1cd665ea711
2020-09-18 20:19:56 +02:00
Vadim Yanitskiy
b7c6f1e83f radioDevice: fix set_antennas(): consider MULTI_ARFCN mode
In the multi-ARFCN mode, if the Tx/Rx antenna names are explicitly
set in 'chan N' sections of the configuration file:

  trx
   ...
   multi-arfcn disable
   chan 0
    tx-path TX/RX
    rx-path RX2
   chan 1
    tx-path TX/RX
    rx-path RX2
   chan 2
    tx-path TX/RX
    rx-path RX2

osmo-trx would crash, because radioDevice::set_antennas() would
attempt to configure antenna names for all N physical channels,
while USRP devices usually have 2 or even 1 available.

The easiest approach is to remove both 'tx-path'/'rx-path' from
all 'chan N' sections excluding 'chan 0', so it would work fine.
This makes sense, because in the multi-ARFCN mode we actually
use only one physical channel.

However, let's still make sure that explicit configuration of the
Tx/Rx antenna names would not crash osmo-trx and skip N > 0 in
radioDevice::set_antennas().

Change-Id: I09f316f181cbbc2214e8913b73f7c1fcea4e8c05
Related: OS#4636
2020-09-12 14:47:21 +07:00
Vadim Yanitskiy
4d43684194 vty: add multi-ARFCN specific warning for chan N > 0
Change-Id: I12d7c466a9a428a384233c4377627e262f165401
Related: OS#4636
2020-09-12 14:39:20 +07:00
Vadim Yanitskiy
54bde5a8ba proto_trxd: cosmetic: 'if' is not a function, add space
Change-Id: I99cf10662232b1f6845d4019dd3b9be45a82d85b
2020-09-11 21:03:08 +07:00
Harald Welte
fd88564acb [cosmetic] radioIntefaceMulti: Fix whitespace / indent
Change-Id: I3addb844a79a8f4e8af03323fc50e57b8a3590a8
2020-09-11 12:43:05 +02:00
Harald Welte
82c72218fd [cosmetic] radioInterfaceMulti: More comments
Change-Id: If608627a77c39b5faabc72c7dd72d00fae8697a9
2020-09-11 12:43:02 +02:00
Eric
1f37e4dd74 transceiver: initialize reorder flag so we don't miscount
Change-Id: Ia7740b45611dbf09a406b3fd9f0a810d46c96bde
2020-09-04 20:36:34 +02:00
Pau Espin Pedrol
7d8676a144 Add support for TRXC MUTE command
Related: SYS#4920
Change-Id: I39983d026ad54c479aa224968e9491d01f30dc35
2020-09-01 13:27:39 +02:00
Harald Welte
8808fa86f0 Fix build on Debian8
We cannot use C99 or higher features in C code!

Last lines of build log:
[  265s]    for (unsigned int i = 0; i < decoded_region->num_chans; i++)
[  265s]    ^
[  265s] ipc-driver-test.c:473:3: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile
your code
[  265s] Makefile:580: recipe for target 'ipc_driver_test-ipc-driver-test.o' failed
[  265s] make[5]: *** [ipc_driver_test-ipc-driver-test.o] Error 1

Change-Id: I80c9cbd77f1cdf323ad2b492de7e9a177840c383
2020-08-27 10:08:53 +02:00
Pau Espin Pedrol
2a0fb962c7 ipc: fix var declaration in for loop
"""
error: 'for' loop initial declarations are only allowed in C99 or C11 mode
"""

Change-Id: I97cb9a0a3ecf64e3e5fcfca75431f8fe2a07bd10
2020-08-26 09:30:41 +00:00
Pau Espin Pedrol
03334967c9 jenkins.sh: Verify distro-specific patches apply
Change-Id: I75792c5defff63b7deaeb533b6818deaac3e0fd3
2020-08-25 15:41:30 +02:00
Pau Espin Pedrol
e30e0ad9be debian: Update debian8 osmo-trx specific patch
Recent commit adding osmo-trx-ipc didn't update the patch, which fails
to apply now due to files having changed its contents.

Change-Id: I6fa50e82320330f83c9753352418755e8b414edf
2020-08-25 15:41:30 +02:00
Eric
7a52e42ee0 transceiver: optimize code if optimizations are enabled
There is no point in checking basic stuff ten thousand times per second
since the sizes never change, so it's enough to enable the
checks/assertions for unoptimized (debug) builds.

This significantly decreases branch mispredictions.

Change-Id: Iebd9e91b3c7f37f2dc646d3017c45139977e4d15
2020-08-25 01:00:19 +02:00
Eric
4080eb76f8 devices: reset internal smart sample buffers upon stop
They are too smart, they keep the timestamps.

Change-Id: Idb4b8f03eb5ffdfd6d3fdbc137b20e3ddc4cfa65
2020-08-25 01:00:19 +02:00
Eric Wild
1e17c4fb0a osmo-trx-ipc
This adds a IPC backend that uses shared memory interface
to communicate with (proprietary) devices.

Requires config file option
dev-args ipc_msock=/path/to/socket
to specify the master socket the ipc backend should connect to.

If UHD is avaialble the ipc-driver-test tool can be used to test the
backend with a uhd device, this was so far only tested with a b2xx.

Change-Id: Ice63d3499026293ade8aad675ff7a883bcdd5756
2020-08-25 01:00:03 +02:00
Eric
f9a2f44272 add kernel style .clang-format with 120 chars per line limit
Change-Id: I1dc6610d7adfa1a52f3d41ad04544806c2be2c39
2020-08-14 03:47:43 +02:00
Vadim Yanitskiy
3bf2c5de8d debian/control: change maintainer to the Osmocom team / mailing list
Change-Id: Ida1a3583749a004e2a6c92cfed0b6806a5b83c78
2020-08-13 16:09:03 +07:00
Pau Espin Pedrol
553a25033e Use new libosmovty cpu sched config features
Using the new libosmovty features allow for:
* Setting different cpu-affinity masks for each thread in the process,
  both at startup through .cfg file as well as changing it at runtime.
* Unified VTY interface to change the scheduling policy of the process
  inherited by all osmocom processes enabling the feature.

Depends: libosmocore.git Change-Id If76a4bd2cc7b3c7adf5d84790a944d78be70e10a
Depends: osmo-gsm-masnuals.git Change-Id Icd75769ef630c3fa985fc5e2154d5521689cdd3c

Related: SYS#4986
Change-Id: I3798603779b88ea37da03033cf7737a6e4751d6e
2020-07-31 13:54:35 +02:00
Pau Espin Pedrol
1d165a043e Transceiver: Add several rate_ctr for rx error conditions
Since there's now a rate counter, we can drop log level for those events
which can be bursty and hence print lots of output in short periods of
time, which may affect performance. This way setting them to INFO it's
enough to avoid getting them in stderr unless explicitly configured by
the user (for instance to debug stuff), while still allowing a good
enough level to be enabled for other targets such as gsmtap.

Related: OS#4679
Change-Id: I000f7112e35ac68d3d922444f78468b1ea74cbba
2020-07-27 11:52:46 +02:00
Pau Espin Pedrol
199a306d27 Transceiver: Check log level before generating burst str representation
Avoid entering the logRxBurst() function and running a long loop even if
not used.

Change-Id: I67408bc8643d5d97355f277c4a2007064a83ae90
2020-07-27 10:58:54 +02:00
Pau Espin Pedrol
c249ce2a58 Transceiver: Lower some log levels which have an associated counter
They are left as INFO instead of DEBUG since they show possible
timing/performance issues in the setup.

Change-Id: I8aab10054ac89c29b871259fdbe59636723ddfb6
2020-07-17 18:33:13 +02:00
Pau Espin Pedrol
761da1a08a Introduce CTR log category
This way i most usual rate_ctr related internal logging is disabled by default
(notice), and it can b eeasily enabled by switching the category to info
or debug.

Change-Id: Id6c36432da7e7ce673c585bcae6772a695028ec5
2020-07-17 18:29:26 +02:00
Pau Espin Pedrol
9032c87d80 trx_rate_ctr: Lower some log levels
Change-Id: I1b5a63e6cc09ac02305c31ea7e94aff53ac0e5c2
2020-07-17 18:22:18 +02:00
Pau Espin Pedrol
df675784a7 Transceiver: Restrict conditions where FN gaps are detected
In pushRadioVector, like we did for driveTxPriorityQueue already, gaps
are possible in any channel for TRX!=0, since TRX0 is the only one
expected to be always transmitting.

Since we always need to transmit there, it makes no sense to check for
channel being not NONE.

Change-Id: I3b4b85b9100f69dfa113c54a4357120bd11ec86f
2020-07-17 14:12:37 +02:00
Pau Espin Pedrol
99330740dd Transceiver: Use already obtained value from Rx msg structure
Change-Id: I3854f284e6d6a561b3816b467985f59e690a282b
2020-07-15 14:06:03 +02:00
Pau Espin Pedrol
b70686c13d Transceiver: Provide initial value for TransceiverState::mFiller in constructor
Fixes: Coverity CID#211258
Change-Id: Ic00cc5939ca46407cb5bf8b6fcbcf3dc677041a2
2020-07-15 13:57:06 +02:00
Pau Espin Pedrol
1d0c6fe752 Add rate counter for missing Txbursts when scheduled towards the radioInterface
Related: OS#4487
Change-Id: Ibb2c492b3c67cbab11fbb936ae3a090fb5756aa8
2020-07-10 17:32:03 +02:00
Pau Espin Pedrol
8b0c5368f5 Transceiver: Fix race condition obtaining Dl burst from Upper layer
The queue was being accessed sequentially obtaining and releasing the
mutual exclusion zone twice. First in getStaleBurst() dropping all
FN<currTime, then in getCurrentBurst() trying to obtain FN=currTime.

However, since in between the mutex is released, it could happen that
for instance upper layer would introduce currTime-1 in the queue, which
would make then getCurrentBurst() detect that one instead of potential
currTime in the queue and return NULL.

By holding the mutex during the call to both functions we make sure the
state is kept during the whole transaction.

Related: OS#4487 (comment #7)
Change-Id: If1fd8d7fc5f21ee2894192ef1ac2a3cdda6bbb98
2020-07-10 17:32:03 +02:00
Pau Espin Pedrol
c0d6fd27ff Introduce rate counters to detect issues in received Dl bursts from TRXD
This ones together with rate counters already available in lower layers
allows to understand better the source of the problem with stalled tx
bursts.

Change-Id: Ia34f7e7d780ad1e12f24638a07f05fe91f2afea5
2020-07-10 17:32:03 +02:00
Pau Espin Pedrol
032c1d8da9 trx_rate_ctr: Fix locking wrong mutex
It was notcied due to sometimes causing deadlock at shutdown time.

Fixes: 92ba59dacf
Change-Id: I49bea4b0ae469794b5c80ee8fa4f275914a5194c
2020-07-10 17:31:10 +02:00
Pau Espin Pedrol
c62a05140c doc/manuals: Update thread documentation after dropping CTRL sock threads
Per-ARFCN CTRL threads managing CTRL socket loops were dropped a while
ago, but it was forgotten to udpate the documentation.

Change-Id: I34d117325e60b04b075c205d21bb0b827a5e8c52
2020-07-01 12:24:56 +02:00
Pau Espin Pedrol
a71c5d073f TransceiverState: Initialize ctrs field in constructor
Coverity dixit:
"Non-static class member field "ctrs.tx_stale_bursts" is not initialized
in this constructor nor in any functions that it calls."

Fixes: CID#211258
Change-Id: I4643a0500e9cad09938c05fab2f358167f72ffa9
2020-07-01 11:50:03 +02:00
Pau Espin Pedrol
92ba59dacf Introduce rate counter tx_stale_bursts
This allows checking if there's timing issues on the downlink side
between osmo-bts-trx and osmo-trx. This counter is useful to find
information about osmo-bts-trx 'fn-advance' setting, since this counter
basically counts if burstrs from it arrived too late to osmo-trx.

Change-Id: Id6df00da81f6d6884f4dddc5a2c4b354dca3af97
2020-06-29 17:08:37 +02:00
Pau Espin Pedrol
6a3a2b8647 Rename device specific rate counter multi-thread helpers
RadioInterface ones will be added in next commit, so let's differentiate
the structs required for each one.

Change-Id: Ib0e142a1dd4bedefdb4c5f15c34132da872c0975
2020-06-29 16:51:08 +02:00
Pau Espin Pedrol
fb96767ac5 trx_rate_ctr: Fix immediate rescheduling on per-sec thresholds
For instance, use in VTY:
"ctr-error-threshold tx_underruns 5 per-second"

If the condition becomes true (eg 5 underruns happened in one sec), the
statement inside OSMO_MAX would become -1, but it was being handled as
an unsigned when doing the OSMO_MAX internal comparison. As a result,
OSMO_MAX((unsigned)-1, 1) was returning -1 (unsigned) stored in
threshold_timer_sched_secs which then became and int -1, which was
handled by osmo_timer_schedule as a 0, hence having an immediate
trigerring all the time.

While at it, make threshold_timer_sched_secs unsigned since it doesn't
make sense to have it as signed anyway.

Change-Id: I6ea3d64dff189a5bc924e72d846e02d50536a8ea
2020-06-29 16:51:08 +02:00
Pau Espin Pedrol
394053e599 cosmetic: trx_rate_ctr: Fix whitespace
Change-Id: I4dc8220a6813d6ff30f1b241cc46b801adec4057
2020-06-29 16:51:08 +02:00
Vadim Yanitskiy
68d8db4d8c UHDDevice: catch LookupError/IndexError in set{Rx,Tx}Antenna()
Currently configuring 3 channels in multi-ARFCN mode makes the
process crash during the Rx/Tx antenna configuration due to
uncaught UHD specific LookupError/IndexError exceptions:

  terminate called after throwing an instance of 'uhd::index_error'
    what():  LookupError: IndexError: multi_usrp:
      TX channel 2 out of range for configured TX frontends

Let's catch them and terminate gracefully.

Change-Id: If66305f2787c6292375e4bfbd60c1d3d764cffd4
Related: OS#4636
2020-06-29 12:43:06 +00:00
Pau Espin Pedrol
58d80a014e {UHD,LMS}Dervice: Log expected resulting TxPower when setting device specific TxGain
Change-Id: I3c54c61cd6dd7e40bb2831fd4962ff72130b390d
2020-06-25 13:07:22 +02:00
Pau Espin Pedrol
5bd3d4263b Drop old TxGain APIs from parent radioDevice abstract class
All radioDevice subclasses except USRPDevice have already been reworked
to use the new SetPowerAttenuation() methods, hence we can drop the
compatibility layer that was added to transition from the old API to the
new one, and move those functions to USRPDevice.

This way we simplify the parent abstract class with methods not needed
by most devices and not used anymore by external users of those classes.

Change-Id: Ice005cd0a07c49b6e212c06f1228ef93c24db727
2020-06-25 13:07:22 +02:00
Pau Espin Pedrol
f68f19b110 LMSDevice: Compute TxGain on LimeSuite API based on expected Tx output power
Right now, according to a few measurements taken on LimeMicro devices, we
expect the Tx Gain at UHD level to relate 1:1 with the slope in Tx output
power given a specific band.

If more fine-grained results are wanted or some device doesn't follow a
1:1 slope relationship, functions TxGain2TxPower and TxPower2TxGain need
to be adapted/improved.

This patch is basically doing the same thing as was done previously for
UHDDevice in 992c9bd1ce.

Related: OS#4583
Change-Id: If154fe4d4cd118aa30ea43c22ee7119117b77da6
2020-06-25 11:05:36 +00:00
Harald Welte
8ac169f7ed osmo-trx.spec.in: Use %config(noreplace) to retain current config file
Change-Id: Ia6a279e4e19eee8368219e3bc1b011802b1fcadc
2020-06-24 05:25:34 +00:00
Pau Espin Pedrol
405f17a98c Transceiver: Allow sending negative nominal tx power in RSP NOMTXPOWER
Some SDR devices under some bands may provide only under 0 dBm Tx Power.

Change-Id: I8cecb7a37eb80db341a624eb7b826180eac4a1d4
2020-06-22 10:11:58 +00:00
Pau Espin Pedrol
b536ab9bdf proto_trxd: Fix UndefinedBehaviorSanitizer from ubsan
From UBSan:
proto_trxd.c:65:18: runtime error: 128 is outside the range of representable values of type 'char'.

Fixes: OS#4507
Change-Id: I71f815fe794a00934ee0e876848af56f30a21bfe
2020-06-19 18:31:05 +02:00
Harald Welte
174fb03b8e RPM spec file: Require uhd-firmware for osmo-trx-uhd
The automatic dependency will only depend on the UHD library
package.  The user will then fail to start osmo-trx-uhd due to
missing firmware.  So let's include an explicit 'Requires' to the
uhd-firmware package to solve this.

Change-Id: I0ebfe669c21d3957a48d57bd7248244e3e924236
2020-06-17 15:28:18 +02:00
Pau Espin Pedrol
b899c19f1f UHDDevice: Compute TxGain on UHD API based on expected Tx output power
Right now, according to a few measurements taken on B210, we expect the
Tx Gain at UHD level to relate 1:1 with the slope in Tx output power
given a specific band.

If more fine-grained results are wanted or some device doesn't follow a
1:1 slope relationship, functions TxGain2TxPower and TxPower2TxGain need
to be adapted/improved.

Change-Id: I6f432465dce5c6ec1f1bc4653f6149efb18c3f43
2020-06-15 10:41:16 +02:00
Pau Espin Pedrol
992c9bd1ce radioInterface: Operate on real Tx power attenuation rather than on device specific gains
All the Tx gain related APIs are left out of reach from radioInterface,
and in there we simply interact with radioDevice passing the attenuation
received from TRXC.

Prior gain logic is moved in base radiodevice class, with the idea that
the setTxGain() and related functions will be dropped over time in each
sublcass in favour of an specific implementation of the
SetPowerAttenuation API.

Change-Id: I4f8a1bcbed74aa9310306b97b0b1bfb02f7855e6
2020-06-09 11:43:32 +02:00
Pau Espin Pedrol
056ce136e6 UHDDevice: Implement getNominalTxPower() based on TxFrequency
The table with nominal UHD Tx Gains and real transmit power is filled
with values measured experimentally. More information can be found in
OS#4583.

Related: OS#4583

Change-Id: If7ef5bf95ffe4afe5864c0f051853aa38b9639eb
2020-06-09 11:43:24 +02:00
Pau Espin Pedrol
0e09e7c98a Transceiver: Implement TRXC cmd NOMTXPOWER
It allows the BTS to retrieve the nominal transmit output power value of
each TRX in order to compute attenuation later on and apply it through
SETPOWER or ADJPOWER TRXC commands.

Change-Id: I1d7efe56e008d8d60e23f9a85aa40809f7f84d9c
2020-06-08 15:49:36 +02:00
Pau Espin Pedrol
1b3a8881eb Transceiver: Fix extra space in RSP NOISELEV error
Change-Id: I35c2f3b3b9358ddb64a53f36969621d45bb243f8
2020-05-29 16:15:18 +02:00
Philipp Maier
fdefbfac39 Transceiver: Log when sending of CLK indications begins
When the logging category TRXCLK is set to info osmo-trx prints a
logline that informs about the sending of clock indications. In practice
this those log lines are often used to identify that osmo-trx and
osmo-bts are running properly, so it would be helpful, even in
productive use, if there would be an information in the log that the
sending of clock indications has begun. However, the regular printing of
the clock indication log line would soon flood the log. So, lets have an
addional log line that logs only once when the transceiver starts and
quickly informs at loglevel NOTICE that clock indications are now sent.

Change-Id: I6aa88943b76c9a2bf7aed60d6a3d325c1f27820a
Related: OS#2577
2020-05-26 22:49:02 +02:00
Philipp Maier
5e16f79f0f doc: switch log levels to notice
Some of the example configs have loglevels set to info. This is too
verbose, lets make sure all loglevels are set to notice

Change-Id: Ief82b85d9ff0e0e94eaabd255ebea961396fff32
2020-05-23 11:50:47 +00:00
Oliver Smith
f3155e33b9 Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
Change-Id: Ie192c9b516ff98f2b1ab8e7927da55a0c1e9eb56
2020-05-22 13:48:11 +02:00
Oliver Smith
7bbe19ee9d contrib: integrate RPM spec
Remove OpenSUSE bug report link, set version to @VERSION@, make it build
with CentOS 8 etc.

Disable lms, usrp1 for CentOS 8.

Related: OS#4550
Change-Id: Ie27fcc4f9033f0049507d9dcc295541ac0744c73
2020-05-19 17:05:30 +02:00
Oliver Smith
f669bf43e7 contrib: import RPM spec
Copy the RPM spec file from:
https://build.opensuse.org/project/show/home:mnhauke:osmocom:nightly

Related: OS#4550
Change-Id: I694fcd888778ab68d13165f4d0bf65e5d6870fb4
2020-05-19 17:04:19 +02:00
Pau Espin Pedrol
4a575b02b5 Use OSMO_FD_READ instead of deprecated BSC_FD_READ
New define is available since libosmocore 1.1.0, and we already require
1.3.0, so no need to update dependenices.
Let's change it to avoid people re-using old BSC_FD_READ symbol when
copy-pasting somewhere else.

Change-Id: I868baf575b77c448b3115701e70d439de89b0fb3
2020-05-09 18:54:20 +02:00
Harald Welte
cf35c37c94 prbs-tool: Don't require C99
from a Debian8 build:

[  256s] prbs-tool.c: In function 'apply_errors_prbs':
[  256s] prbs-tool.c:190:2: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
[  256s]   for (int i = 0; i < sizeof(pchan->prbs_u)-4; i++) {
[  256s]   ^

Change-Id: I8541fce50405525efffb12210a269e0ab8a687ab
2020-05-07 23:55:56 +02:00
Harald Welte
6e369348b0 utils: Ensure content of this directory is included in 'make dist'
The python + matlab should be part of every source release

Change-Id: I9814a9a352dbee03177ef9e8dfd19bc2baf0ca07
2020-05-02 22:34:27 +02:00
Harald Welte
546516d79c prbs-tool: Add error simulation capabilities
The tool can now simulate:
* lost bursts on the TRX->BTS interface
* zeroed/overwritten bursts on the TRX->BTS interface
* errors in the TCH codec frames before passing them to the encoder

Change-Id: I0b52c2af6d973669ac233bf9868400e497496460
TODO: Ability to introduce errors in certain classes of the bits only.
2020-05-02 22:32:51 +02:00
Harald Welte
6879bb0db9 PRBS tool sending PRBS sequence to TRX
Change-Id: I2300f909bbfda10a7053320edfd1deaea763759a
2020-05-02 22:32:34 +02:00
Eric
a7143bf7a1 transceiver: get rid of the ctrl threads
There is no need to have n threads handle n ctrl sockets, since they all
will immediately respond to commands, so handle them from the existing
main osmo select loop.

Care must be taken to ensure that calls from within the command handler
do not block, or at least don't block too long, which currently is the
case.

Change-Id: I642a34451e1825eafecf71a902df916ccee7944c
2020-04-14 19:10:51 +00:00
Philipp Maier
4ffdca10d4 doc: apply an rssi-offset of 28 by default.
Set an rssi offset of 28 in the example configs to make sure that the
power control loop gets RSSI values that match at least half way the
reality when the 1800 Mhz band is used. For other bands the value will
be different (See also related osmocom ticket)

Change-Id: I62725fe454f54e2c7cb7550dadb1e6fc94337d78
Related: OS#4468
2020-04-14 17:16:23 +00:00
Eric
1a26b4f085 transceiver: check the right vector
Change-Id: I03800ae094c35c306fa4ca29f84e71d958ffdbdc
2020-04-14 13:17:25 +00:00
Eric
c5d5586fbd configure.ac: fix libtool issue with clang and sanitizer
As pointed out at https://github.com/libexpat/libexpat/issues/312
libtool does not play nice with clang sanitizer builds at all.
For those builds LD shoud be set to clang too (and LDFLAGS needs the
sanitizer flags as well), because the clang compiler driver knows how
linking to the sanitizer libs works, but then at a later stage libtool
fails to actually produce the shared libraries and the build fails. This
is fixed by this patch.

Addtionally LD_LIBRARY_PATH has no effect on conftest runs during
configure time, so the rpath needs to be set to the asan library path to
ensure the configure run does not fail due to a missing asan library,
i.e.:

SANS='-fsanitize=memory -fsanitize-recover=all -shared-libsan'
export CC=clang-10
ASANPATH=$(dirname `$CC -print-file-name=libclang_rt.asan-x86_64.so`)
export LDFLAGS="-Wl,-rpath,$ASANPATH $SANS $LDFLAGS"

Change-Id: If3d9465068b2c654b935fc3d9ab41d799d5e02e8
2020-04-11 18:33:42 +00:00
Philipp Maier
cc971aa1a6 doc: do not set the base-port of the trx
In current config files a base port for osmo-trx is set. Lets remove
this setting so that compiled-in default (which is the same value)
is used.

Change-Id: I105d1c51424836daa6893e83a81c83cc7ac6afd4
2020-04-01 10:21:50 +00:00
Philipp Maier
748d8edbf8 debug: use LOGL_NOTICE for log category DDEV
The log category DDEV ueses LOGL_INFO as debug level. This is too
verbose, lets use LOGL_NOTICE instead

Change-Id: I56d45ce5c3f55574491ffa6e4d902d6ba7499d46
Related: OS#2577
2020-03-25 12:36:15 +01:00
Pau Espin Pedrol
dfc6e5ffc7 radioDevice: Drop unused isControl param from WriteSamples API
The out "isControl" parameter is only used by internal callers of
USRPDevice, and not used at all by any user of the generic API
(radioInterface*.cpp). Hence, we can get rid of it and keep it as a flag
for an internal API of USRPDevice.

Change-Id: I843384e24b76cdd28a95f9ee4e95e6157098e4a3
2020-03-12 19:35:47 +01:00
Pau Espin Pedrol
f8c0c464b8 radioDevice: Drop unused RSSI param from readSamples API
The out "RSSI" parameter is only filled by USRPDevice, and not used at
all by any user of the API (radioInterface*.cpp).

RSSI seems to be computed nowadays in the common path in
Transceiver::pullRadioVector().

Change-Id: I06c2ea5a9891d170bc468f952bbf2a7e64d95784
2020-03-12 19:34:28 +01:00
Pau Espin Pedrol
93707d0227 cosmetic: fix several typos found by codespell
Change-Id: Id1f6766572fd313463201e6d03964965f227db25
2020-02-25 17:03:00 +01:00
Pau Espin Pedrol
5291e8a654 debug.h: Fix print format of chan in CLOGCHAN
Under armv7l arch, size_t is actually an unsigned int and not a long
unsigned int, and compiler errors:

CommonLibs/debug.h:28:24: error: format ‘%lu’ expects argument of type
‘long unsigned int’, but argument 8 has type ‘size_t {aka unsigned int}’ [-Werror=format=]

Change-Id: I7f6ded5a984570b5267916d6c84eb7d019db73a8
2020-02-19 18:08:20 +01:00
Pau Espin Pedrol
7a07de1efd debug.h: Avoid printing pthread_t type
Using %lu for pthread_t was wrong on armv7l arch. Even worse, according
to pthread_self() man page, pthread_t cannot be assumed to be of a simple
type and hence printable:
"""
POSIX.1 allows an implementation wide freedom in choosing the type used
to represent a thread ID; for example, representation using either an
arithmetic  type  or a structure is permitted.
"""

Let's use gettid() instead. According to glibc documentation:
"""
The pid_t data type is a signed integer type which is capable of
representing a process ID. In the GNU C Library, this is an int.
"""
It may not be the same on other libc's though, so let's better cast to a
long int just in case.

Accordign to gettid() man, the libc function was only added recently
during glibc 2.30, however the system call has been around for quite
some time (linux 2.4.11). Let's accomodate use udner non-glibc or older
versions of it by having a direct syscall fallback.

Change-Id: I40265fd4c62e550014ba3ff3335ca053c5bc01f2
2020-02-19 18:08:20 +01:00
Pau Espin Pedrol
fd67262df8 contrib/jenkins.sh: Reorder sanity checks
Change-Id: Idfe12148aa7a8030bdaf56d11c1547ebc3f56d14
2020-02-19 11:53:30 +01:00
Pau Espin Pedrol
0569845a08 lms: Initial multi-arfcn support
With current state multi-arfcn can be used (eg. I can place a call
between 2 phones using TRX1 and sustain for as long as wanted), but from
time to time (around every 20seconds), a burst of Tx packed dropped
events from LimeSuite appears.

LimeNet-micro coefficients have yet not been tested.

Related: OS#4362
Change-Id: I7e67d90a8126546eeeeba376f816ec5d158d4712
2020-01-15 15:46:14 +01:00
Pau Espin Pedrol
c69b87f9bd lms: Make ts_offset and smpl rate coefs device-specific
Right now the values are the same for all devices, but they will differ
in forthcoming commits once multi-arfcn support is added.

Change-Id: I262d3a71848fc3070473e29e42820848e7591d02
2020-01-15 15:46:14 +01:00
Pau Espin Pedrol
a7bf6cd8a4 lms: Store device type specific parameters in one place
Add an enum containing each supported device type (LimeSDR-USB,
LimeSDR-Mini and LimeNet-Micro) plus "unknown", to leave some room for
yet-to-come devices to run with some generic parameters without
rebuilding osmo-trx.

Each device type is assigned a dev_desc structure, and all of them are
put in HashMap, similar to what's already done in UHDDevice.cpp.

Device type is infered from string provided by LMS_GetDeviceInfo(), as
it was already done before in several places. From now on, we only need
to parse the string once since we store the device type after first
during open time.

Later on, more fields will be moved to device-type specific structure,
such as Tx timing offset, clock rate, etc.

Change-Id: I7658615787c5bc41c365bab9c11733b701ac2ae5
2020-01-15 15:45:29 +01:00
Pau Espin Pedrol
e7f6a27ab6 lms: Move rx_buffers allocation to constructor
Release is done in destructor, so let's move allocation to constructor
since there's really no need to have them in open() which is already
quite complex and large.

Change-Id: I8a4fd973590c4c165abd8f2837b2da8fc14a2066
2020-01-15 15:35:01 +01:00
Pau Espin Pedrol
a979f5f32b lms: Make reference to std::vector unambiguous
Change-Id: Ieebdbd3d5082a02aea2441e6737783370511cbc1
2020-01-15 15:34:49 +01:00
Pau Espin Pedrol
b0e54265ad lms: Change radioDevice constructor arg name to avoid masking instance attr
channel number mangling based on multi-arfcn feature being enabled was
moved to generic radioDevice() to reuse code. Hence, the generic parent
constructor sets this->chans to 1 if multi-arfcn feature is requested.
However, LMSDevice constructor argument had same name as the class
instance attribute, taking preference. As a result, if multi-arfcn is
enabled in LMSDevice, the generic constructor first sets this->chans=1
but afterwards LMSDEvice constructor keeps calling .resize() with the
argument value "chans" instead of using this->chans.

Let's rename the argument in all radioDevice child class constructors to
avoid potential future bugs in all of them.

Change-Id: Id6c837e9133f22783dd92a81dfcc493e51bf2d21
2020-01-13 16:13:28 +01:00
Pau Espin Pedrol
62c9280590 lms: Improve smpl_buf error logging
Change-Id: I511abe2c333443b978a3767bd7b7e320e07c4930
2020-01-13 14:35:06 +01:00
Pau Espin Pedrol
1421adbc61 smpl_buf: Fix str_code() param and print unknown error val
Change-Id: I95fadac15b9ad337ebc7cfb44a20dcf803ff8a47
2020-01-13 14:34:19 +01:00
Pau Espin Pedrol
dccc82491c lms: Drop unused define
Change-Id: Iaf3361ed29dd552e5e52b62bc738fa20c6b583fe
2020-01-07 16:21:12 +01:00
Pau Espin Pedrol
bf58370675 lms: Move initialization of field started to constructor
Change-Id: I135a2ff4a419775169452be1128c7b30f7d638ad
2020-01-07 16:10:34 +01:00
Pau Espin Pedrol
7c84925ea4 doc: Update vty reference xml file
Change-Id: Ib2707204cbba6df813ffc08d7098093cf4393da0
2020-01-07 16:04:04 +01:00
Pau Espin Pedrol
fd99c6ce05 radioInterfaceMulti: Fail to tune on freq not following multi-arfcn restrictions
multi-arfcn feature uses a hardcoded disposition of logical channels on
a physical channel. Logical channels in the phisical channel are
separated by MCBTS_SPACING Hz, that is 4 GSM ARFCNs.

As a result, multi-arfcn restricts the TRX ARFCN setup to the following:
ARFCN(TRX0)=N, ARFCN(TRX1)=N+1*4, ARFCN(TRX2)=N+2*4, ...

Let's make sure radioInterfaceMulti verifies the requested Rx/Tx
frequencies for each logical channel over TRXC match the restriction
explained above. It will check freq going to be set is indeed separated
by MCBTS_SPACING from already set channels, making sure the ARFCN series
is consistent.

Otherwise, before this patch, one could set in osmo-bsc:
ARFCN(TRX0)=N, ARFCN(TRX1)=N+2

and osmo-trx would silently ack the related Rx/TxTUNE TRXC commands, but
actually still transmit on ARFCN N+4 instead. As a result, in this
scenario TRX!=0 were unusable with multi-arfcn.

Related: OS#4207
Change-Id: I2f3d66a611d3a489b3e4d9431994f4ec77b4460f
2020-01-07 16:04:04 +01:00
Pau Espin Pedrol
e947db8d98 doc: clarify number of channels on B210 with multi-arfcn enabled
Change-Id: I082d4d8c346f1be1569fe63baa856029e439cb2c
2020-01-07 16:04:04 +01:00
Pau Espin Pedrol
9279e0e123 uhd: Improve some logging lines printing UHD pretty-print output
Change-Id: If5aba28aaf8a3312d89b3e963184f9f20966d199
2020-01-07 16:04:04 +01:00
Pau Espin Pedrol
84231bd8b7 uhd: Use DEVDRV log category and support UHD >=3.11 logging framework
Change-Id: I36f1ff7d425a2144fb512ff393af02741eb4a3d4
2020-01-07 16:04:04 +01:00
Pau Espin Pedrol
aebbfe0ee7 Make logging category DLMS generic and reusable for other backends
Make sure old configs using "logging level lms <level>" are still accepted.
Initialization order of VTY componenets need to be resorted since newly
introduced command requires logging VTY node to be already setup
beforehand.

Change-Id: Ia195a74a62a8a3dd6267fb1359acaa5628208d8e
2020-01-07 16:04:04 +01:00
Pau Espin Pedrol
da7fee8ea8 Bump version: 1.1.1.38-9f2b-dirty → 1.2.0
Change-Id: I9009eb44e7d8100294da139300480fc3a2f6b616
2020-01-03 19:54:00 +01:00
Pau Espin Pedrol
9f2baf3e04 Transceiver.cpp: Introduce and use new logging categories
Take the chance to clean up logging lines in this file:
* Use LOGCHAN in more places where chan is useful
* Replace inherited (old osmo-trx) categories such as WARNING with
osmocom ones.

Change-Id: Ic8c218f050f35d48046ccf1561fb0bfc505d4f63
2019-12-20 14:19:35 +01:00
Pau Espin Pedrol
0a2a40f43c uhd: use value already cached in tmp variable
Change-Id: I4568eaed6db3da12f83f2f503a50032f7bfb482c
2019-12-19 13:52:57 +01:00
Harald Welte
501d053b70 trx: exit() on unsupported positional arguments on command line
Change-Id: Ifeea65a359e9ca307efb2c721fd0fb6f0959e976
2019-12-03 21:41:38 +01:00
Pau Espin Pedrol
0fafe03199 Transceiver: Fix wrong response upon CMD HANDOVER failure
Change-Id: I9d3f120b1696a9ce92c81097d04e81dbb717287d
2019-11-27 13:17:59 +01:00
Alexander Chemeris
9a87d90c1e vty: Simplify filler burst settings and improve help and readability.
In the command line options time, filler table/filer burts settings
were a bit difficult to undertand because the number of one-letter
settings was limited. Now, with VTY configuration, there is no reason
to keep it so difficult.

Also, after the previous commit it was no longer posible to enable
random 8-PSK filler bursts. With this patch you can configure all
supported filler bursts in a simple and logical way.

Change-Id: I752eb2c1162d084e8769181f2fcd6c0877663448
2019-10-21 08:41:07 +00:00
Martin Hauke
066fd04f47 Fix common misspellings and typos
Change-Id: I4ec7accb1912c052b446be7c399bed32a8c62253
2019-10-17 08:06:19 +00:00
Alexander Chemeris
aeaba02e02 vty: Don't enable random filler bursts automatically with EDGE.
The EGPRS switch in the VTY config enables 8-PSK burst detection on
uplink. Enabling it shouldn't turn on filler bursts.

Change-Id: I2786c768e038b769a80c8b78fe58cfa09eb322a9
2019-10-15 12:00:55 +00:00
Pau Espin Pedrol
b7e992703c Use new libosmocore logging lock API
Since libosmocore Id7711893b34263baacac6caf4d489467053131bb, a new API
log_enable_multithread() is available which takes care of protecting
logging infrastructure from us (and actually does it correctly since we
cannot protect internal libosmocore structures from osmo-trx).

Let's drop all mutex related code from osmo-trx logging infra and simply
rely on libosmocore's.

Related: OS#4088
Change-Id: I519d0f30bce871005ca26b90177ea4aa4839360a
2019-10-09 19:15:49 +02:00
Pau Espin Pedrol
928141b7d6 radioInterfaceMulti: write frequency offset direction (rx/tx) in log line
Change-Id: I7b89426e5d7d5e7570d4ef800a30c7b74bd09b82
2019-09-30 12:18:31 +02:00
Pau Espin Pedrol
e503c988d8 radioInterface: Atomically fetch and change underrun variable
Otherwise, it could happen that underrun events are lost:
TxLower (isUnderrun):	RxLower (pullBuffer):
read(underrun)
			read(underrun)
			write(underrun, |val) [maybe underrun becomes TRUE]
write(underrun, false)

Similary, it could happen the other direction if atomic was only applied
to isUnderrun:
TxLower (isUnderrun):	RxLower (pullBuffer):
			read(underrun) -> true
read(underrun)-> true
write(underrun, false)
			write(underrun, true|val) where val=false

So in here isUnderrun would return true twice while it should only
return one.

Change-Id: I684e0a5d2a9583a161d5a6593559b3a9e7cd57e3
2019-09-20 19:17:22 +02:00
Pau Espin Pedrol
ee2ba19cec Move multi-ARFCN chan amount modification from UHDDevice to parent class
This way switch is applied correctly to parent structures and features
can be used later by other children classes (other devices).

Change-Id: I24d6c66bb3195ba2513b4a67daa14cdfbacdce6d
2019-09-20 19:17:22 +02:00
Pau Espin Pedrol
80d053acb9 radioInterface: Mark setRxGain as virtual
Otherwise the parent function is always called even if the iface is
radioInterfaceMult.

Change-Id: Ie41efab1e60b88677bbd1ec333ea656794503a5a
2019-09-20 19:17:22 +02:00
Timo Jacobus
18a615176e Transceiver: Fixed copying of history into and from channelizer buffer.
In multi arfcn mode, osmo-trx would drop some bursts because it couldn't detect it
and would emit idle burst instead. Specificaly detection of peak in correlation
vector failed. Correcting copying of history in pullBuffer method fixes this issue.

[Re-worked by Pau Espin Pedrol <pespin@sysmocom.de>]

Fixes: 57df2362f0eca0a330aad3e18906046dfadb9c8b
Change-Id: I93e43f6868cd67e69fc59d2980a03550d2505bf8
2019-09-20 19:17:22 +02:00
Pau Espin Pedrol
25383a3610 radioInterface{Multi,Resamp}: Fix successful writeSamples() masking underrun from readSamples()
The only who should be setting class instance value "underrun" to false
is isUnderrun().
Similar fixes were already applied lately to radioInterface.cpp.

Change-Id: I3239b1df4536c080365106b3e4daa523b57f5dff
2019-09-13 18:53:29 +02:00
Pau Espin Pedrol
e2ac20a96e UHDDevice: Drop unneeded MULTI_ARFCN checks
After previous changes, radioInterfaceMulti is expected to handle channel
conversion correctly, so it will always use chan 0 for all these
functions. This simplifies code in radioDevice avoiding need to add
checks to all devices supporting multi-arfcn in the future.

Change-Id: Ib2cd50a6ceaeedc6aaf3e1bb51d33b52911b6eba
2019-09-13 17:54:27 +02:00
Pau Espin Pedrol
62845241a2 radioInterfaceMulti: Override setTxGain() to avoid chan!=0 calls
Change-Id: I7e67f660c3b0b009db59b405de603f6058021802
2019-09-13 17:50:10 +02:00
Pau Espin Pedrol
2ab921812e radioDevice: Introduce getTxGain() API
It will be used in later commits by radioInterfaceMulti.

Change-Id: Ie3caca8971ed1e5370dfed6fb60716a24e7d82a5
2019-09-13 17:34:46 +02:00
Pau Espin Pedrol
752055c7c1 radioInterface: Remove unusued getRxGain()
Only the radioDevice->getRxGain() is called from inside
radioInterfaceMulti, so the API in radioInterface is not used at all.

Change-Id: Icc4e9a7ebfdafe7c72c535752a5e379d12592c9a
2019-09-13 17:34:46 +02:00
Pau Espin Pedrol
705a348326 LMSDevice: Return previous txGain/rxGain if setting value failed
Change-Id: I11e853e11bec99fc88e81642f9b2cd87d5815398
2019-09-13 17:33:14 +02:00
Pau Espin Pedrol
331c88ae82 USRPDevice: Return previous txGain if setting value failed
Change-Id: I0d8fd51586ef01141d4e5896f0fc3029a22743f8
2019-09-13 17:33:14 +02:00
Pau Espin Pedrol
ca0892d822 USRPDevice: Fix setRxGain return on error and getRxGain() returning always 0
field rxGain is set to 0 during constructor and never set after that
point.

Change-Id: I7fae7a315e5ab98a15c27628a88a92226ef89469
2019-09-13 17:32:03 +02:00
Pau Espin Pedrol
17e6cd0394 radioInterfaceMulti: Check equals zero explicitly
It's not a pointer check or a boolean expression, in here we really
check chan index is 0, so it's more clear doing so this way like it's
done in all other places.

Change-Id: I83b14487d14ba8272f58796f640f58a88891e532
2019-09-13 16:20:46 +02:00
Pau Espin Pedrol
a801ae5d94 radioInterface: Rename mRadio to mDevice
Previous naming is ready confusing, because "Radio" is actually the
common term between radioInterface and radioDevice, and it looks like
it's referring to radioInterface rather than radioDevice. On the other
hand, mDevice cleary states it refers to the radioDevice item.

Change-Id: I708bb1992a156fb63334f5590f2c6648ca27495e
2019-09-13 15:59:31 +02:00
Pau Espin Pedrol
923b4bc9a2 Transceiver: Don't stop TRX if pulling from OFF timeslot
BTS may have any timeslot disabled, or may have not yet sent initial
SETSLOT cmd to properly configure the timeslot.

Change-Id: Icf62e5d1200c7a440f255bb46023cdbf61532b7f
2019-09-09 10:27:04 +02:00
Pau Espin Pedrol
0d56d75dbb Transceiver: pullRadioVector(): Fix use of uninitialized value bi->tn
Change-Id: Ia0f2b5a51040663d7e8219e6ed51e0513b876548
2019-09-09 10:20:58 +02:00
Pau Espin Pedrol
94c5241403 Transceiver: Log error condition no burst in pullRadioVector()
Change-Id: I4f180cc852582b131ba28a8139215335f7ba567d
2019-09-06 14:37:36 +02:00
Pau Espin Pedrol
e3a2516280 Transceiver: Use LOGCHAN in logRxBurst to unify log format
Change-Id: Iec33ab73a9bf90fd0bff9ba453c32ea11bf0670e
2019-09-06 14:37:36 +02:00
Pau Espin Pedrol
1fba10409b Transceiver: Fix logging TN and version
Since tn is declared as uint8_t, it's actually a char, and by default
c++'s ostream& operator<<(ostream&, unsigned char) tries to print chars
with its ASCII visible character instead of numeric value.

Change-Id: I534158e8e1719ad19a9cde7c747a8f8ad5a01a2b
2019-09-06 14:33:59 +02:00
Pau Espin Pedrol
77f3396d04 device: Use LOGCHAN in set_antennas()
Change-Id: I3099498e3a3f26b53d55a96a36cc056f7b25b27a
2019-08-26 17:13:23 +02:00
Pau Espin Pedrol
e0010fa425 lms: Log available antennas if requested antenna fails
Related: OS#3343
Change-Id: Icd328e85b0a75ef67f371a7ed72638053b1854f9
2019-08-26 17:13:17 +02:00
Pau Espin Pedrol
bfc1d0bed7 Transceiver: Enable EDGE detection only on PDCH timeslots
Related: OS#3664
Change-Id: Id16248a1c03f9bc9f323c707857cdf3bf34c4e3e
2019-08-26 16:34:49 +02:00
Pau Espin Pedrol
76ff96e210 Transceiver: exit process when BTS drops connection
We don't want to keep osmo-trx running in a started state once the BTS
controlling it becomes unavailable. If a socket towards the BTS fails,
it means the BTS is gone and the best thing to do is to stop the process
(alternatively we could go back to stopped state instead, and wait for
BTS to re-connect, fur so far this action is good enough).

Related: OS#4170
Change-Id: I2ccbe3c17b39fb792ea7810f840235c348054d66
2019-08-26 15:55:49 +02:00
Pau Espin Pedrol
4e6ec4554d Transceiver: Fix idle ul burst indications being dropped
pullRadioVector() should return true on idle frames because those
indications may be handled by upper layers (TRXDv1). Clarify return code
in function documentation.

Change-Id: If592ed1c04cf7e995f656b313f60edd4d40d1bfd
2019-08-26 15:45:56 +02:00
Pau Espin Pedrol
e4166be76f Transceiver: Clean up receival of downlink bursts
Use a packed structure to clearly indicate what is contained in the
received buffer.

Change-Id: I4d8c0e3c0c717699889f79e50c778d14b6058f2d
2019-08-26 14:34:09 +02:00
Pau Espin Pedrol
e7195ac7d0 Transceiver: Check return value when binding IP addr for clock socket
No need to continue further since anyway we'll end up exiting.

Change-Id: Id8b38b40df5744beb705d560defb06532cf0fd44
2019-08-26 10:55:08 +02:00
Pau Espin Pedrol
ca6a78e193 Transceiver: fix segfault during init if IP addr binding fails
If osmo-trx is started and IP addr binding fails (ie because the IP
address is not assigned in the system), it will try to access a
heap-allocated Thread instance which was not initialized (because init()
function returned earlier).

Fixes: OS#4147
Change-Id: I19f9745cd026c0ff6581895a66bf91b40113b07d
2019-08-26 10:50:20 +02:00
Pau Espin Pedrol
67aa91b2c0 Drop old setPriority related code
This code is not needed anymore since we are setting SCHED_RR scheduler
with a real time priority in main thread during startup, so all threads
will inherit same rt priority, which should be enough to keep the
process working reliably even on high system loads (from non rt
processes).

osmo-trx was tested to be reliable during test with stress-ng as
explained in related ticket below.

Related: OS#2344
Change-Id: I3a88946dd71e9aeeaac9d19d396e2236c302b608
2019-08-21 13:00:41 +02:00
Pau Espin Pedrol
3eed8ebb0d osmo-trx: log to stderr on signal received
Since osmo-trx it's a big multithreaded process and shutdown sequence
can be complex, better use stderr to log signal received events to make
sure log is outputted straigh away and not buffered. In general stdout
is usually line-buffered, but buffering strategy can be more
conservative if output is for instance redirected to a file.

Change-Id: I70ba86919d1f7df41ef3db4916317d27697a025c
2019-08-14 16:26:47 +02:00
Pau Espin Pedrol
d0cbb16a93 Bump version: 1.1.0-dirty → 1.1.1
Patch release to have debian/patches/build-for-debian8.patch applying
correctly again.

Change-Id: I27caf077abc400e9661549886bb8f7827dd299bb
2019-08-08 13:00:06 +02:00
Pau Espin Pedrol
e774d52504 Bump version: 1.0.0.104-72a7 → 1.1.0
Change-Id: Ifd5abfb03015e9233814eb9d843ce2e218987283
2019-08-07 21:12:56 +02:00
Pau Espin Pedrol
72a75f3e43 Require newer version of libosmocore to avoid build failure
Older commit started using osmo_timerd_* APIs which are only available
starting libosmocore 0.12.0, but configure.ac still states 0.11.0 is
accepted, which is incorrect.

Fixes: 4456b6f132
Change-Id: I71743b8a10edb10af51ad8e9289c53e432199b97
2019-08-07 21:11:47 +02:00
Pau Espin Pedrol
27424a39ee Transceiver: Add missing include netinet/in.h
Previous commit started using IPPROTO_UDP without including required
include. Newer versions of libosmocore's osmocom/core/socket.h include
that header so the define is present, but older versions of libosmocore
(such as 0.12.0) don't, so let's include it explicitly (the correct
thing to do).

Fixes: b9d2515704
Change-Id: I67ddf550f3a7fc6a650e1e1d9bde0bbb28785104
2019-08-07 21:10:47 +02:00
Pau Espin Pedrol
c7ac63afa5 Drop old README information, provide new updated README
Previous content in README file is actually a description of the TRXD
and TRXC protocols, and it has already been moved to the User Manual
some time ago. INSTALLATION contained README related information, but it
was really out of date.

So this commit basically drops those two files and provides a new
README.md with content taken from Osmocom's OsmoTRX project wiki page.

Change-Id: I3df00799ce80aa4af43225e69a408ba2cbc444db
2019-08-01 15:17:30 +00:00
Pau Espin Pedrol
cbc02086d5 Move std_inband.rbf under device/usrp1/ dir
This file is only used by USRP1, so let's move it there and avoid
processing it in Makefiles if build for USRP1 is not requested at
configure time.

Change-Id: Ibb40ba487581e76d2ae3e8a420d631670f876cf0
2019-08-01 13:46:00 +02:00
Pau Espin Pedrol
3d29b4d5b0 Move README.DFEsymbolspaced to utils/matlab
Change-Id: Icccc18688ee54e669cf3452b08747b3509042fa2
2019-08-01 13:46:00 +02:00
Pau Espin Pedrol
06d3ba0445 Move Transceiver52/README to UserManual
Change-Id: Ib5a56cfe0c27d027bc0c60abda89e646a80849de
2019-08-01 13:46:00 +02:00
Pau Espin Pedrol
8a784c7145 Move matlab files under utils/matlab
Change-Id: I15b687fbf436d662b264cb00f72b367ccd64b962
2019-08-01 13:46:00 +02:00
Pau Espin Pedrol
7758542087 Move inband-signaling-usb documentation to UserManual
Change-Id: I4d6ef1f54f3d6c5a73ce00dc4640bd698f96842b
2019-08-01 13:46:00 +02:00
Pau Espin Pedrol
68a78099a0 lms: Drop rx_underruns rate ctr, add tx_drop_* rate ctr
After discussion in [1] and further look at the code, it became obvios
rx_underrun events are not happening in general for any SDR (don't
exist), so let's drop that counter. Instead, add Tx Dropped Packet counters,
which were not accounted prior to this commit.

[1] bde55afd29

Change-Id: Iff1535c219a4695a511d383d7c4b06ef6eff959d
2019-08-01 13:45:55 +02:00
Pau Espin Pedrol
50c78dfe85 jenkins.sh: Workaround libusrp build race conditon
When submitting patches to osmo-trx in gerrit, sometimes the jenkins job
fails due to libusrp failing to build. I never have this issue in on my
workstation.

Let's disable parallel make and see if we can avoid it for now.

Related: OS#3970
Change-Id: I24bc54f5872e8edb9fab5b88055a00cebe1a6911
2019-07-30 15:06:24 +02:00
Pau Espin Pedrol
207911bcde usrp1: don't check for non-null underrun pointer
The pointer can't never be null, so avoid checking it.

Change-Id: I12e14641713a6494bc89570f02cecfc6f8fd4b5e
2019-07-29 20:42:56 +02:00
Pau Espin Pedrol
2c673e0f3e radioInterface: Clarify how underruns are handled driving a radioDevice
The underrun parameter in radioDevice's readSamples() is not a "Rx
Underrun" event, but rather it's used to retrieve a "Tx Underrun" which
on some SDRs (like USRP1) seems to be (so far) available only at
readSamples() times.

Thus, underrun parameter for both readSamples() and writeSamples() is
actually flagging the same event, and should be ORed in pushBuffer() as
it's already done in pullBuffer(). Otherwise if implementation is
setting the underrun pointer to false, it could erase the flag being
marked by the counterpart function before isUnderrun() is called (which
is the one responsible to clear the flag).

Change-Id: Id549489fc1485e0d762818c8e682aaddd5041f1c
2019-07-29 20:42:56 +02:00
Pau Espin Pedrol
b4c749b32b Remove unused autogen.sh
autoreconf is used instead, as done in all of the osmocom projects.

Change-Id: I87676cdf6818b4250f478962baf96ad5f28564d5
2019-07-29 15:50:59 +02:00
Pau Espin Pedrol
c641f781dc Remove empty ChangeLog fnd NEWS files
We already have debian/changelog for same purpose. This file is empty
and doesn't exist on other osmocom projects.

Change-Id: I5a90107476ca116bebc8569f4eb1db0fa25807a6
2019-07-29 15:50:46 +02:00
Vadim Yanitskiy
6b30ab0c34 manuals/configuration.adoc: fix copy-paste error in config example
Change-Id: If9de32eed8170038c8c177c8996c78846dddb624
2019-07-24 23:08:19 +07:00
Pau Espin Pedrol
720b912ba9 Transceiver: Clean up code passing parameters to threads
TransceiverChannel naming was misleading there. It's simply a data type
used to pass 2 parameters through the void* of the thread entry
function, so let's clearly specify is a storage for thread params.
Furthermore, we don't need a full C++ class for that, let's simply use a
struct.

Change-Id: I6e3898a8a66520cc5b2a7df9b9ae01b0b272387f
2019-07-23 09:06:01 +00:00
Pau Espin Pedrol
c3325b9aeb Transceiver: Store TRXD version per channel
The setting is negotiatied by osmo-bts-trx on each channel, so let's
keep and use state per channel instead of overwriting the state from
different channels.
Take the chance to change related log lines to also print the channel
number.

Change-Id: If9cf95e89d38d0155ab48b8c0977ca5f381c2aad
2019-07-23 09:06:01 +00:00
Pau Espin Pedrol
88f86a14ba Bind CTRL port to IP addr specified in VTY config
Before this commit, osmo-trx was always setting its CTRL socket to
listen on 127.0.0.1.

Change-Id: I61a06c1b9c20a906e7030f824a93370d041be7b9
2019-07-22 22:15:24 +00:00
Pau Espin Pedrol
21d03d3912 Add SPDX annotation
Related: OS#3515
Change-Id: I3719bd8dc015569ecd81928fc079e27593cdca09
2019-07-22 12:06:26 +02:00
Pau Espin Pedrol
bdb970e495 cosmetic: Fix trailing whitespace in several files
Change-Id: Ifafb68353960fc5046661854ccfb8d783b0efb14
2019-07-22 12:03:39 +02:00
Pau Espin Pedrol
e6319ed32a debian/copyright: Add missing file Utils.* to LGPL-2.1+ list
Change-Id: I36b8b8be48ae8676688786f39008d08b61011ede
2019-07-22 11:59:53 +02:00
Pau Espin Pedrol
1830705e67 debian/copyright: Update wrong paths in license list
Those paths were moved into a subdir a while ago, but this file was not
updated at the time.

Change-Id: I1857338b7a19e2a37f62386ceb4a1fad988272ba
2019-07-22 11:22:48 +02:00
Pau Espin Pedrol
46d0be06ab debian/copyright: Remove non existent radioInterfaceDiversity.cpp from list
Change-Id: I5cfbbafd411e580421f86df6817f91261aceda7e
2019-07-22 11:21:28 +02:00
Harald Welte
2896cecefb radioInterface.cpp: Fix missing member initialization of RadioInterface()
Change-Id: I7264ef35dbe6d3522858eae5b47d150aa1ffe334
Closes: CID#169594
2019-07-21 15:46:06 +00:00
Harald Welte
5c6ca1739f CorrelationSequence: fix initialization of class members
Change-Id: Ia72395f8805e9e2cd700ad1e559a8aa62124aaec
Closes: CID#149371
2019-07-21 15:46:04 +00:00
Harald Welte
80ca1de44a ChannelizerBase: fix initialization of class members
Change-Id: I8c047c8f98e928a62dca1d7b8c003502727c086e
Closes: CID#149374
2019-07-21 15:46:01 +00:00
Harald Welte
2a3d8ba71a Timeval: Restore output stream flags after changing them
Change-Id: I866505f29ed56d8f3ba3aaba70c0d82479987c64
Closes: CID#149361
2019-07-21 15:45:58 +00:00
Vadim Yanitskiy
6fa906c280 trxd_fill_common(): fix TRXD header version coding
The header version field is 4 bit long, so the mask 0x07 == 0b111
is wrong, it should actually be 0x0f == 0b1111.

Change-Id: I290931559ce01cf6e43470b18855c46808d6c2a5
2019-07-20 19:39:18 +07:00
Harald Welte
a7ba484fb2 proto_trxd.c: Use bit-wise AND, not boolean AND
Change-Id: I974c91be7cc119b44c2fb0c53d08009c87de7bf1
Related: CID#202038
2019-07-20 10:13:18 +02:00
Pau Espin Pedrol
758381bad4 Transceiver: Initialize mExtRACH in constructor
Doing so should make Coverity happy:
>>>     CID 200212:  Uninitialized members  (UNINIT_CTOR)
>>>     Non-static class member "mExtRACH" is not initialized in this constructor nor in any functions that it calls.

The current status is actually harmless since the field will be set
during init() time, and the variable is never used before init() is
called.

Fixes: Coverity CID#200212
Change-Id: I17286570a9a6db695a75147e5cbb18c9da7d0fe6
2019-07-19 14:58:32 +02:00
Vadim Yanitskiy
56c5f2959b driveTxPriorityQueue(): enrich logging message
Change-Id: If25c2171f7d1ab98d65f0dbf93d0d8a5a635caf7
2019-07-19 14:58:32 +02:00
Vadim Yanitskiy
dd571c6db1 driveTxPriorityQueue(): check if message header format is supported
Change-Id: I17abf95f5e23236abccc50476cd59931580f5cd3
2019-07-19 14:58:32 +02:00
Vadim Yanitskiy
b31232537a driveTxPriorityQueue(): use trxd_hdr_common for message parsing
Change-Id: If6a93e2b7fc9ada55edbdd16352cd4f7040e3d2a
2019-07-19 14:58:32 +02:00
Vadim Yanitskiy
8d771d24e7 driveTxPriorityQueue(): cosmetic: use proper type for TDMA TN
Change-Id: I8396004616754f84fb465c972fde9e91b18cc49b
2019-07-19 14:58:32 +02:00
Pau Espin Pedrol
cf6113b2fe Transceiver: Support TRXD v1
Related: OS#4006
Change-Id: I53db2678458a7377c87875b58b58b76a1b900517
2019-07-19 14:58:29 +02:00
Pau Espin Pedrol
13c81098f8 Transceiver: Support SETFORMAT command
Only old v0 is supported so far.

Related: OS#4006
Change-Id: If9fc22f9987238a5ff870df7718de4efc9e04289
2019-07-19 11:44:13 +00:00
Pau Espin Pedrol
15fa64bce4 Transceiver: Move out TRXD socket send code to prepare for TRXDv1
Only old v0 is supported so far. TRXD protocol related data/logic is
moved to its own file out of Transceiver class. Code is refactored so it
can be re-used later by TRXDv1.

Related: OS#4006
Change-Id: I5786dd44b076202c6f1a6e82405670e8605797ed
2019-07-19 11:44:13 +00:00
Pau Espin Pedrol
c9202ab0be Logger: global Log mutex is now available from C code
This way the C++ logging API can still be used while allowing for C
files to use the same mutex.

Change-Id: I473e57479f8ae98a84ad00b76ff338f79f732236
2019-07-19 11:44:13 +00:00
Sylvain Munaut
b49a42e70b sigProcLib: Add C/I (Carrier-to-Interference ratio) computation
Related: OS#4006
Change-Id: Ib4ceec553f2e5f77bf3f6777724968456a180f5e
2019-07-19 11:44:13 +00:00
Pau Espin Pedrol
c3d68c159f sigProcLib: detectAnyBurst(): make TSC used to detect burst available to caller
This value will be sent in TRXDv1 protocol.

Related: OS#4006
Change-Id: I603b7b52f957cf897b036dbaeb22c01a55de08c3
2019-07-19 11:44:13 +00:00
Pau Espin Pedrol
7ee2d10113 sigProcLib: detectAnyBurst() family: Use struct to gather all out params
Currently we have 2 out parameters, but in forthcoming commits will add
a third one. All those functions already have too many parameters, so
let's put together all the output params in a struct to pass them easily
and make it easier to understand they are the estimated output values.

Related: OS#4006
Change-Id: I05cfa0ceaa2e633a5e6e404e2eae497ff4442dea
2019-07-19 11:44:13 +00:00
Ruben Undheim
252564b50e Fix spelling discovered by lintian
Change-Id: I5ab9b9c7c47d0d6e674c1f5242e2b3a05006293e
2019-07-17 10:58:22 +00:00
Oliver Smith
2ded53c440 contrib/jenkins.sh: run "make maintainer-clean"
Related: OS#3047
Change-Id: I6d541b47e68f5a8a61ac139a3ea85a9cb33856c1
2019-07-10 13:26:21 +02:00
Pau Espin Pedrol
95c8318d5d Transceiver: Support pulling idle frames in pullRadioVector()
This logic will be used once we support TRXDv1, where idle indications
are sent through the socket.

Related: OS#4006
Change-Id: I46404f6e4055b6d3af3afffb0dfe4a19502917aa
2019-07-03 16:03:21 +02:00
Pau Espin Pedrol
9bb24a1103 Transceiver: pullRadioVector(): Move initialization of var to start of function
This will be needed upon forthcoming refactor to support idle frames,
which will add a goto return. Otherwise compiler complains:

error: jump to label ret_idle [-fpermissive]
note:   crosses initialization of unsigned int max_toa

Change-Id: Icd2793adc7b73a795184639b95fb5da336909b59
2019-07-03 15:49:38 +02:00
Pau Espin Pedrol
d6dbb1b987 Transceiver: Simplify code on early error return when calling detectAnyBurst
We get rid of one branch and simplify code logic.

Change-Id: I026e35262bfe42c3d23ebdc06d84e4908a8380e2
2019-07-03 15:49:38 +02:00
Pau Espin Pedrol
be9cd66020 Transceiver: Avoid noise calculation formula in 2 branches in pullRadioVector
Makes code easier to follow and will help in forthcoming refactoring
once idle frames are supported.

Change-Id: I56c84e9684ca460efd6c983d7e95d8e455bcac69
2019-07-03 15:49:38 +02:00
Pau Espin Pedrol
b9d2515704 Transceiver: replace UDPSocket with libosmocore socket API
We have a good socket API in libosmocore, let's drop osmo-trx socket API
and use libosmocore's one instead of maintaining the two of them.

Change-Id: Ib19856a3e0a7607f63436c4a80b1381a3f318764
2019-07-02 15:07:25 +02:00
Pau Espin Pedrol
7dc07b9425 Transceiver: Get rid of SoftVector in struct trx_ul_burst_ind
Make the interface using trx_ul_burst_ind more implementation agnostic
as well as easier to use. For instance, we don't care about SoftVector
size one returned from pullRadioVector(); we want to use nbits instead.
As a result, we no longer spend time normalizing guard periods. While at
it, change vectorSLicer to return void since it always returns true.

Change-Id: I726e5a98a43367a22c9a4ca5cbd9eb87e6765c7a
2019-07-02 15:05:17 +02:00
Pau Espin Pedrol
07ddce5c1f Transceiver: Drop use of GSM::Time from trx_ul_burst_ind
Use of that class is really not needed since we don't need to do any
calculation with those values, so we can simply store the final values
in the struct.

Related: OS#4006
Change-Id: Iadf2683d7f52138a2248598641f3b702252f325d
2019-07-02 15:05:17 +02:00
Pau Espin Pedrol
25ae190dc6 Transceiver: Move soft bits normalization to pullRadioVector()
That's where all the filling logic happens, while in driveReceiveFIFO we
mostly want to take the burst, generate a message and sent it over the
socket.

Related: OS#4006
Change-Id: Ibfb48877af4ff5ef0f56390901669c8353beaf48
2019-07-02 15:05:10 +02:00
Pau Espin Pedrol
607a414967 Transceiver: Move calculation of normalized values (rssiOffset) to pullRadioVector()
That's where all the filling logic happens, while in driveReceiveFIFO we
mostly want to take the burst, generate a message and sent it over the
socket.
In pullRadioVector this way we always provide normalized values based on
user configuration (VTY rssi-offset).

Related: OS#4006
Change-Id: I1ee28daf21dc287bec564d45d58086d63655c0f6
2019-07-02 15:04:40 +02:00
Pau Espin Pedrol
0e67cf24eb Transceiver: Move nbits burst size calculation to pullRadioVector()
That's where all the filling logic happens, while in driveReceiveFIFO we
mostly want to take the burst, generate a message and sent it over the
socket.

Related: OS#4006
Change-Id: Ib1df10c40d737954904290f57d58b1c77d65f82e
2019-07-02 15:04:29 +02:00
Pau Espin Pedrol
ff6aeb7f62 Transceiver: Drop unused rssi_valid struct field
That field is actually never used. Furthermore, if pullRadioVector()
returns false, then the caller should consider the 'trx_ul_burst_ind'
structure as uninitialized. Moreover, RSSI is mandatory - we cannot send
burst indications without it.

Related: OS#4006
Change-Id: Ia109298aebe8ba4750a39338ba7962555903cd82
2019-07-02 15:04:24 +02:00
Pau Espin Pedrol
ddd18a5e33 Transceiver: refactor: gather uplink burst parameters in struct
A new struct trx_ul_burst_ind is introduced, which will handle
information filled by lower layers upon decoding of uplink bursts.

Methods pullRadioVector() and logRxBurst() are adapted to use that
struct. This way it's easier to understand in/out parameters and it's
also easier to add further parameters to be filled in in the future.

Related: OS#4006
Change-Id: I7e590fb1c0901de627e782f183251c20f4f68d48
2019-07-01 16:13:21 +02:00
Pau Espin Pedrol
778b30a530 Introduce structs to encode TRXD packets
This will ease adding new protocol versions in the future.

Related: OS#4006
Change-Id: I67ffede171eddde436f9057191ed76015a8ea6eb
2019-07-01 16:13:10 +02:00
Pau Espin Pedrol
e9ce77b871 trx_{vty,rate_ctr}: Set proper license AGPLv3+
Take the chance to improve text with author, SPDX tag and fix incorrect
copyright dates.

Related: OS#3515
Change-Id: Ic745312ed07db205b1cdc0f2fa130000319354c5
2019-06-25 12:40:17 +02:00
Pau Espin Pedrol
c27d9f88df Remove AUTHORS file
License of this file doesn't match the license stated in COPYING and in
most source code files (GPLv3 vs AGPLv3). Furthermore, we don't really
maintain this file, so let's drop it to avoid non-up-to-date content
which may introduce confusion.

Related: OS#3515
Change-Id: I536a145cb7696af8e9dbd3065ee5e5f493217ac6
2019-06-25 12:40:17 +02:00
Eric Wild
ac0487eb66 Add option to set stack size in config file, default == 0 == OS default
Change-Id: Id752f6b5ce9a96a67cd1ff835687ce0e03d3a50d
2019-06-17 14:41:34 +02:00
Pau Espin Pedrol
6a305feb0f Add VTY commands to set error ctr thresholds
osmo-trx will validate over time that those thresholds are not reached.
If they are reached, osmo-trx will die. As a result, osmo-bts-trx will
notice and will end up notifying the BSC about it (for instance because
it will also restart its process).

For instance:
"""
ctr-error-threshold rx_drop_events 2 minute
ctr-error-threshold rx_underruns 10 second
"""

In those cases above, osmo-trx will die if rate_ctr rx_drop_events went
to a value higher than 2 per minute, or it will die to if rx_underruns
went higher than 10 per second.

Change-Id: I4bcf44dbf064e2e86dfc3b8a2ad18fea76fbd51a
2019-06-11 14:28:17 +00:00
Pau Espin Pedrol
bde55afd29 lms: Fix stream_stats checks with overrun/underrun
It was initially thought that underruns/overrun fields were
increasing-over-time values.
However, after reading LimeSuite code, it seems overrun and
underrun fields are actually reset upon every call to
LMS_GetStreamStatus().

Related: osmo-trx.git 9281771256
Related: https://github.com/myriadrf/LimeSuite/issues/265
Change-Id: I677232a7b12ee83d26aa34d92f76a91d4b5a63a6
2019-06-09 06:55:13 +00:00
Pau Espin Pedrol
4c50bf435b lms: Drop unusued variable masterClockRate
Change-Id: I19192925d008046f474615a0476b52ddee9a9d78
2019-06-06 19:44:22 +00:00
Pau Espin Pedrol
63e872a701 doc: vty: Update trx_vty_reference.xml
Change-Id: I2587cd47ee48e979de447f7a0f4d79bb5fac0592
2019-06-05 12:50:38 +02:00
Pau Espin Pedrol
b426e4abb4 Rename and move STOP signal from Transceiver to main
The callback actually belongs there, since it's the code/thread in main the one
actually in charge of stopping everything. It simplifies current code,
and more important, allows for new clients of this signal to use it.
This callback will also be used in forthcoming commits by code
controlling rate_ctr thresholds to stop the process if the VTY
configured threshold is used.

Change-Id: Id4159e64225c6606fef34a74b24f37c3a071aceb
2019-06-05 12:50:38 +02:00
Pau Espin Pedrol
4456b6f132 Add rate_ctr support to store/retrieve SDR errors through VTY
Introduce a unified implementation-agnostic interface for radioDevice to
signal SDR error counters to upper layers and manage them.
This patch only implements counters for osmo-trx-lms (other devices will
show all counters unchanged during time).

Sample use through VTY:
"""
OsmoTRX> show rate-counters
osmo-trx statistics 0:
   device:rx_underruns:          0 (0/s 0/m 0/h 0/d) Number of Rx underruns
    device:rx_overruns:          0 (0/s 0/m 0/h 0/d) Number of Rx overruns
   device:tx_underruns:          0 (0/s 0/m 0/h 0/d) Number of Tx underruns
 device:rx_drop_events:          4 (0/s 2/m 3/h 0/d) Number of times Rx samples were dropped by HW
device:rx_drop_samples:        513 (0/s 196/m 425/h 0/d) Number of Rx samples dropped by HW
"""

Change-Id: I78b158141697e5714d04db8b9ccc96f31f34f439
2019-06-05 12:50:38 +02:00
Oliver Smith
76a5013c91 debian: create -doc subpackage with pdf manuals
I have verified, that the resulting debian packages build in my own OBS
namespace (see the -doc packages):
https://download.opensuse.org/repositories/home:/osmith42/Debian_9.0/all/
https://build.opensuse.org/project/show/home:osmith42

Depends: Ib7251cca9116151e473798879375cd5eb48ff3ad (osmo-ci)
Related: OS#3899
Change-Id: I34858a18a34fc467f274ac164697a242f4cf0df8
2019-05-29 12:14:24 +02:00
Pau Espin Pedrol
9281771256 lms: Fix stream_stats checks with droppedPackets
Existing code had a typo (value was assigned from wrong variable).
Furthermore, it was experimentally found that:
while underrun/overrun are documented as "FIFO overrun
count" in LimeSuite.h, it seems droppedPackets ("Number of dropped
packets by HW") is not actually an incrementing counter like the others,
but simply a value set every time LMS_RecvStream() is called. Since we
are actually interested in keeping the count over time, adjust code to
achieve that.

Change-Id: Id93d33400e11360b9536f56a31904328549cfbbf
2019-05-24 17:01:13 +02:00
Pau Espin Pedrol
dcbcfa58e4 lms: Use smpl_buf to recover from timestamp jumps
Also take the chance to make sure we handle properly short reads (keep
reading again).

Both scenarios can be tested by running osmo-trx-lms and then using
on a terminal:
sudo kill -STOP `pidof osmo-trx-lms`; sleep 0.5; sudo kill -CONT `pidof osmo-trx-lms`

Fixes: OS#3339
Change-Id: Idfc4e69acc30afb11440b6b9cbdcfa09ff920265
2019-05-06 11:23:36 +02:00
Pau Espin Pedrol
b5def414b8 smpl_buf: Move it to device/common and create libdevice_common.la
Since in next commit osmo-trx-lms starts using smpl_buf.cpp, it seems
some automake step doesn't like including a cpp file twice from a
different directory, since race conditions can occur building it.
Instead we define the dependency by first building a static lib and then
using it on each libdevice.la (one per device type).

We already do the similar under arch/ subdir, where we have a common/
subdir and then one subdir and lib per architecture.

Change-Id: I465ad0f6d5569bb3006d711c8fd0df14391fcf35
2019-05-06 11:23:18 +02:00
Pau Espin Pedrol
fc73c073a1 Introduce LOGCHAN macro to standarize logging channel info
Change-Id: I67d869499aa16af58c863ca7b74c356bcd979936
2019-05-06 11:21:43 +02:00
Pau Espin Pedrol
a7919265f5 smpl_buf: Remove dbg log line with duplicated info
Change-Id: Ia2423707210a364fa6827b92cca087ced99b088b
2019-05-04 20:36:07 +02:00
Pau Espin Pedrol
9b394e0cc0 smpl_buf: Remove unused clk_rt variable (fixup)
Last commit removed use of the clkr_rt variable but forgot to remove the
variable itself.

Fixes: 580c48b7d5
Fixes: Coverity CID 198370
Change-Id: Ida1fc5b7b338fbeb2a7c6258f36b02da93ff2186
2019-05-04 20:05:06 +02:00
Pau Espin Pedrol
580c48b7d5 smpl_buf: Remove unused clk_rt variable
During 87b7d098e5 we dropped support for
UHD specific functionalitites, and so clk_rt is not needed anymore.

Change-Id: I37403e085ed6a541bbdecf64f1f9a821ff2753a4
2019-05-03 14:38:51 +02:00
Pau Espin Pedrol
7214fde085 device: Drop unused numberRead/numberWritten APIs
It's really not used, so let's drop unused code and simplify work for
new to come device drivers implementation.

Change-Id: I0d18f9c2584771e2f7b3d5c6b016e764e02855ff
2019-05-03 13:50:50 +02:00
Pau Espin Pedrol
51509b3895 Move smpl_buf out of uhd dir to re-use it in other devices
Change-Id: I39ac8435072cff8d4dac786b31ff4af9b61a77fe
2019-05-03 13:50:50 +02:00
Pau Espin Pedrol
ef192d303c uhd: Avoid reallocation of buffers every read
Buffer size is based on num of chans and rxBuffer size is based on num
of chans and rx_spp, and both are available and set during open(), so no
need to waste time allocating and freeing them everytime we read from
the device.

Change-Id: I8c881c9c303c80f323825d85a924d74b76d2ce47
2019-05-03 13:50:50 +02:00
Pau Espin Pedrol
ac927b2690 cosmetic: uhd: Use loglevel ERROR instead of ERR
ERR is osmo-trx legacy level, which actually converts to osmocom's
ERROR, so let's use that one directly.

Change-Id: I82f6f89a725bea7f7acfa455c20cf922cc3f8a00
2019-05-03 13:50:50 +02:00
Pau Espin Pedrol
3e9179a55e uhd: smpl_buf: Use TIMESTAMP type in str_status
Other related functions use "TIMESTAMP timestamp" so let's use same
stuff in that function.

Change-Id: I016b1a7f8db379caebc1409ca11e5ae8b759d2d4
2019-05-03 13:50:50 +02:00
Pau Espin Pedrol
87b7d098e5 uhd: smpl_buf: Drop UHD specifics out back to UHDDevice
This way smpl_buf can be re-used later by other non-UHD drivers.

Change-Id: I94061328d46a550d4147121d85baffa29c700c45
2019-05-03 13:50:50 +02:00
Pau Espin Pedrol
7bef2346c4 cosmetic: uhd: Move smpl_buf out of UHDDevice, move UHDDevice class definition to .h
* move class definition to .h file, like we do for other devices.
* move smpl_buf class to a different file inside uhd/.
* Preparation work to have smpl_buf being used in a generic way for
devices other than UHD (LMS).

Change-Id: Ib4594320da9bb7f6e9f52e7d70d11ecd11106aae
2019-05-03 13:50:47 +02:00
Pau Espin Pedrol
2876785f50 lms: Catch and log dropped packets by HW during recv
Change-Id: I23554d95b0aff585024610fc12920c9da4f3ba9e
2019-04-25 20:16:10 +02:00
Pau Espin Pedrol
713b4d81cd lms: Remove unused var m_last_tx_overruns
Change-Id: I2104205b2af7cd6c86075d5cc4f0f36bde5e5311
2019-04-25 20:16:10 +02:00
Pau Espin Pedrol
b96d9ddee3 lms: Remove references to ALERT loglevel
ALERT log level is not Osmocom standard level, it's just a define in
osmo-trx to keep compatibility with old code.

Same goes for one reference to "ERR" intead of "ERROR".

Change-Id: I0e171a8ac8a8bfa804ac97fba3d73efcfa6424b4
2019-04-25 20:16:10 +02:00
Pau Espin Pedrol
048c3ba300 lms: Log underrun/overrun events
Change-Id: I8c6b1d3e8515153e5d4079cc6620901ef8ce2449
2019-04-25 20:16:10 +02:00
Pau Espin Pedrol
75cb0b9dd6 Move duplicated thread_enable_cancel to CommonLibs
Change-Id: I1a479b59bdda01233273dfa919bd678edbe34708
2019-04-25 19:33:58 +02:00
Pau Espin Pedrol
46324d3597 cosmetic: Threads.h: Remove trailing whitespace
Change-Id: I0ae6e435a7f0480c3eaa08dccfe824456f33b015
2019-04-25 19:33:11 +02:00
Pau Espin Pedrol
bab1583a2c lms: Improve log during flush recv error
Change-Id: Id45d42599738efd6a5d89787c75779838a979330
2019-04-25 19:26:24 +02:00
Pau Espin Pedrol
541496b65b lms: flush_recv: alloc buf on stack instead of heap
No need to use the heap here since buffer is only used as a temporary
trash. Using the stack is quicker.

Change-Id: Iede8dc0903ee3865a52c8e2fd811bcde444fee33
2019-04-25 19:22:11 +02:00
Joachim Steiger
c785fb130a lms: properly call close if set_antennas() fails, add some comments
Change-Id: I9ebe986ee3a15842a15853424ee98e9a2fa6a5df
2019-04-17 18:24:11 +00:00
Joachim Steiger
2875290d95 lms: add device type detection and device specific gains
add device dependant max gain setup - limesdr mini and limenet micro need slightly reduced maximum gains to get a PASS on phase error measurements
rework clock reference setup - external clock needs to be selected before calling LMS_Init(), internal can only be set after.
remove now unused compat_LMS_VCTCXO* functions - we do not set the VCTXCO directly anymore

Change-Id: I3cf905b0a84bc1ec200891762a6646141ee37181
2019-04-17 18:24:11 +00:00
Joachim Steiger
4ce4555d0e lms: move LMS_GetLPFBWRange and LMS_Calibrate calls from open to start
bandwidth, freqency, gain stages need to be set before calibration can be successful

Change-Id: I1090effdf0f43e5183a402e4c1a1ffe5abdefd37
2019-04-17 18:24:11 +00:00
Joachim Steiger
2d130fb15d lms: move LMS_EnableChannel from Start/Stop to Open/Close device
move enable: it is important that channels are actually enabled before applying any configuration (besides external clock)
move disable: move to close, so channels are not disabled and not enabled again while osmotrx is active.

Change-Id: I82878913254ce15a85db8d006e13d5eb639793e9
2019-04-17 18:24:11 +00:00
Joachim Steiger
6c5f4bae46 lms: Remove wrong unused code copied from -uhd
Change-Id: I2bc7fcfa429d1f82c2d8e95d31dfed367f2b3f9d
2019-04-17 18:24:11 +00:00
Harald Welte
71df42550a use BSC_FD_READ and not OSMO_FD_READ
We haven't even released any tagged version of libosmocore yet which
includes support for the renamed OSMO_FD_READ constant.  Let's avoid
any breakage and use the new constants only with considerable delay,
at the very least only when released libosmocore versions provide it.

Change-Id: Idb57077b2a4b2a71dd5d75a24ded8bb5887da188
2019-04-16 17:18:58 +02:00
Vadim Yanitskiy
24f05ea1f7 doc/configuration.adoc: fix incorrect number of physical RF channels for B210
Change-Id: I58e2bf5dd99e1655ebd2ad80f6ed2bb178f0e88d
2019-04-11 07:34:04 +00:00
Tom Tsou
d280045884 multi-ARFCN: fix maximum number of carriers limitation
Maximum number of carriers is fixed to 3 channels on a single
physical RF channel in multi-ARFCN mode. For some reason, it
was limited to 5.

Let's fix this, and also follow this limitation in the
following VTY command handlers:

  - cfg_multi_arfcn_cmd,
  - cfg_chan_cmd.

Change-Id: I66a1462f368458afd313ee6f0bc0abc496dde817
2019-04-11 07:33:40 +00:00
Pau Espin Pedrol
5e6f3e0cad osmo-trx: Check return code of osmo_fd_register
Fixes Coverity CID 197513.
Change-Id: I93fbcb062439a547379aaecba283d107fdc9cb59
2019-04-02 11:45:06 +02:00
Pau Espin Pedrol
21032b75c0 osmo-trx: Use signalfd to serialize signals in main thread ctx
This should avoid prolematic scenarios where different signal handlers
are running on different thread in parallel. Furthermore, we make sure
those signals are always run by main loop thread.

Change-Id: I9b9d9793be9af11dbe433e0ce09b7ac57a3bdfb5
2019-03-29 19:20:08 +01:00
Pau Espin Pedrol
d01c7b98b6 osmo-trx: Avoid handling signals after shutdown triggered
Recently a blocked osmo-trx process was found after ending SIGTERM to
it.
Apparently one thread was handling SIGTERM and calling fprintf()
(grabbing libc lock) while another thread was handling another signal
and also grabbing similar lock. Both thread looked deadlocked there.
Probably this change doesn't fix the block on its own, but at least
simplifies scenarios inside signal ctx which can go wrong.

Change-Id: If91621913b8b03d8a0f4c863be0b0d479f97e8a1
2019-03-29 18:51:28 +01:00
Sylvain Munaut
158ea5bc66 tests: Re-enable the convolve_test by default
Change-Id: Ia26ef75bb11482fc0db3b790db1c93c8b74229d1
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-01-24 20:02:54 +00:00
Sylvain Munaut
3733ed5097 tests: Rework the convolve_test
Besides just general cleanup, the major changes are :
 - Fully internal generation of reference data that doesn't
   depend on glibc or even on any floating point math
 - Golden results are included in a .h
   Due to varying precision of different implementation or
   architecture, any kind of textual compare is impossible, so
   we include golden values and compare results of both the
   'base' implementation the potentially 'optimized' one again
   this set of values with a small error tolerance

Change-Id: I4e203d2c4b778af77d630ed15d4cef6b0c0eb76d
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-01-24 20:02:46 +00:00
Vadim Yanitskiy
a8b3565246 VTY: add extended (11-bit) RACH detection toggle
Since I838c21db29c54f1924dd478c2b34b46b70aab2cd we have both TS1
and TS2 synch. sequences, in addition to "default" TS0. Let's
finally introduce the VTY configuration parameter, that can
be used to toggle optional detection of both TS1 and TS2.

Note: we keep this optional because of potentially bad impact on
performance. There's no point in paying the performance penalty
unless upper levels (BTS, PCU) actually make use of it.

Change-Id: I1aee998d83b06692d76a83f79748f9129a2547e8
Related: OS#3054
2019-01-24 15:47:48 +01:00
Sylvain Munaut
a3934a11a4 convolve: Remove support for step, offset parameters
- Those are not used any where
 - Those are not supported by the sse/neon accelerated versions
 - And I see very little use cases for those.

Change-Id: Ic850269a0ed5d98c0ea68980afd31016ed555b48
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-01-21 10:34:51 +01:00
Sylvain Munaut
acf804c034 arm/convolve: Fix the vfp4 real convolution for h_len=12
Change-Id: Ic73f0746edd3f1f22bb1d79d4c64aa740691dd48
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-01-21 10:34:51 +01:00
Harald Welte
d20b7fa579 Bump version: 0.4.0.125-7c78 → 1.0.0
Change-Id: Ibb888f55a1ab27088d5f21ee8ad699f4f747abde
2019-01-20 20:54:40 +01:00
Harald Welte
77e18352fb cosmetic: Don't call the SDR "USRP" in error message
Transceiver.cpp is used for all SDR hardware we support, not just USRP.

Change-Id: I9b7ddb0d679f111407704048ef3ddd964db49441
2019-01-11 22:42:29 +01:00
Harald Welte
f97d75b355 usrp1: Fix formatting of log message (missing space)
Change-Id: I378a8081a224acda3ee2af9b6aa0d680de884695
2019-01-11 22:42:29 +01:00
Harald Welte
a944001873 usrp1: Remove uninitialized skipRx logic
There appears to have been some logic to operate a USRP1 in
transmit-only GSM mode.  This is achieved using the skipRx member
of the transceiver object.  However, there's nobody that ever
initializes it properly, and hence the feature is not possible to
use anyway.

I don't think this has any valid use case, so let's remove it.

Change-Id: I616193f1e9aaefbf4ceb26761657811093f28b6f
2019-01-11 21:46:45 +01:00
Oliver Smith
42c165605a LMSDeviceTest: fix link errors on OBS
Link LMSDeviceTest against LMS_LIBS, so it does not only compile on
Debian, but also on Ubuntu and openSUSE. Thanks to roox for figuring
this out.

Related: OS#3654
Change-Id: I6980d4290f623485a77db10fea6d17de0321c092
2018-12-17 09:43:45 +00:00
Pau Espin Pedrol
affd351787 configure.ac: check boost only if USRP1 support is enabled
boost is only used in USRPDevice class.

It looks like it can be removed entirely quite easily, since only
boost::shared_ptr is used for 2 variables. That's left for somebody with
the device and willingness to test the changes.

Change-Id: I4c3fa3ff58fd552d0cb4c4cf2033615d84c07c96
2018-12-14 20:05:36 +00:00
Pau Espin Pedrol
03b11620d9 lms: Fix build against LimeSuite > 18.10
LimeSuite dc124e4e2ed9b549b142410af172f0592f9f0c23 > 18.10 broke API
compatibility.

OS#3729
Change-Id: Idf500a5b39a857233f728c6a4316c00a99374556
2018-12-14 13:30:07 +01:00
Pau Espin Pedrol
25185886f0 TimevalTest: Make test deterministic with fake time
Change-Id: I74e577a0142fb6d1ef3630e02aff9910b191bff9
2018-12-13 13:58:24 +00:00
Pau Espin Pedrol
47031405f5 Timeval: Move to osmo_clock_gettime
Change-Id: I24da3e1136c5396062662be1d10b07b4d97cfc2e
2018-12-13 13:58:24 +00:00
Pau Espin Pedrol
0646b3ce75 Timeval: Move implementation to use clock_gettime and timespec
According to gettimeofday manual:
"Applications should use the clock_gettime() function instead of the
obsolescent gettimeofday() function."

Furthermore, it may be desirable in the future to use other clocks such
as monotonic.

Change-Id: I2286998c5eefbf3c3dfb105c223daec7a1083803
2018-12-13 13:58:24 +00:00
Pau Espin Pedrol
46cf9efc8e Timeval: passed() returns true if time is equal
Change-Id: I96a9d26657f85447609693bc6932d218d354b84a
2018-12-13 13:58:24 +00:00
Oliver Smith
871713bf6a LMSDevice: make use of dev-args in osmo-trx.cfg
Allow selecting a specific LimeSDR device by setting dev-args in the
config file. Split up the given dev-args address by comma and select
the device where all substrings can be found.

I could not test this with real hardware, but I have added a test case
to make sure this works as expected.

Related: OS#3654
Change-Id: Ib9aaa066a01bf9de3f78234d7ada884d6f28c852
2018-12-13 11:07:02 +01:00
Oliver Smith
8d9a05ce5b osmo-trx.cpp: move comma_delimited_to_vector() to Utils.cpp
Make the "opt" argument const. This function will also be used by
LMSDevice.cpp in a follow-up commit.

Related: OS#3654
Change-Id: If3f0f682ca453c2b0a06175ec9626567932cfce6
2018-12-12 17:26:32 +01:00
Pau Espin Pedrol
fe865f45d7 lms: Do {under,over}run checks even if LMS_RecvStream fails
Under failure, it could still be that stream status is updated, so let's
father that in all cases.

Change-Id: I4e2b8be06d2993db1bab233948a8ee774b8ac4ee
2018-12-07 11:18:32 +01:00
Pau Espin Pedrol
e5b6664419 lms: Move {under,over}run checks into separate method
Change-Id: I7f450aa79f6285d14826c40ecfdd9490d00509ef
2018-12-07 11:18:28 +01:00
Pau Espin Pedrol
1595ddaa5f transceiver: Log TRXCTRL iface responses towards osmo-bts-trx
Change-Id: I8128c42e63ab1fcd2a58812f3b7cf94435b5bbd8
2018-12-07 11:15:10 +01:00
Pau Espin Pedrol
441d82add9 Add TRXCTRL log category
This log category is applied to messages related to TRX CTRL socket
interface, and it's printed in yellow, same color used in osmo-bts-trx
for TRX category (so same messages are printed with same color in both
sides).

Change-Id: I98ec5e416272783ad3fbadf70478a4e48ae64983
2018-12-07 11:15:02 +01:00
Oliver Smith
867cea575b contrib: fix makedistcheck with disabled systemd
EXTRA_DIST files need to be distributed, no matter if the systemd option
is configured or not.

Change-Id: I2e417f4c453987df1ac04f0ff41bf000da4b5c49
2018-12-06 16:31:30 +00:00
Pau Espin Pedrol
2f53ea4cf2 transceiver: log chan on CTRL command received
Change-Id: Ia3b2a35e03a8aaddd6efebc8db2ccca872f51f20
2018-12-05 19:43:46 +00:00
Pau Espin Pedrol
138caaf09d lms: Improve Set{Rx,Tx}{Gain,Freq} logging
Change-Id: I6713a27c5f74beb7fcfdd712fcf695afccbc3d76
2018-12-05 19:43:46 +00:00
Pau Espin Pedrol
3fadcad33e lms: Allow setting Tx/RxFreq for lchan!=0
Related: OS#3346
Change-Id: I9dd0bb41d1863111d28947fc0d7c7e7ecfaf5fa8
2018-12-05 19:43:46 +00:00
Pau Espin Pedrol
eaa0144dcb lms: Allow setting Tx/RxGain for chan!=0
Related: OS#3346
Change-Id: I5fae92a7ed5e2d92be12b9dfd33fc56195030c0b
2018-12-05 19:43:46 +00:00
Pau Espin Pedrol
f7331764ac SigProcLib: Improve Vector buffer allocation mess
Original issue: In order to use SSE instructions, 16-byte aligned memory
chunks are needed, and C++ version < C++11 doesn't provide for a native
new/delete store. For that reason, memalign() must be used in the
implementation of convolve_h_alloc() for some buffers.
On the other side, The C++ code relies on C++ "new T[]" operator to
allocate a chunk of memory containing an array of class instances. As
classes are complex types, they cannot be allocated through C structures
(calling malloc). Experimentally can be seen too that it's unreliable
and the process will crash during startup if malloc() is used and then a
Complex<> deferred from it.

Previous implementation allowed for use of convolve_h_alloc or new[]
based on how the (signal)Vector is called, because then the buffer is
not going to be managed internally. But that's unreliable since resize()
calling resize() on it could use "delete" operator on a malloc'ed
buffer, and end up having a new new[] allocated buffer. It was also
found that some of the callers were actually leaking memory through ASan (because the
buffer is not managed by the Vector instance).

IMHO best option would be to rewrite all this code using C structures
and malloc/free exclusively, since it would make all this cod eeasier to
maintain.

But for now, let's extend the Vector class to allow specifying an
external alloc/free function and let the Vector instance take care of
the ownership of the buffer in all scenarios.

Change-Id: Ie484a4762a7f77fe1b105188ea03a6f025730b82
2018-12-05 19:41:34 +00:00
Oliver Smith
800c029c70 jenkins.sh: run "make distcheck"
Run distcheck in CI to be consistent with other Osmocom projects.

Change-Id: I7d3fa0fe12e13ca13d3330158425718e5c34d00d
2018-12-05 16:26:35 +01:00
Oliver Smith
522cbe91d3 contrib/jenkins.sh: build and publish manuals
Add new environment variables WITH_MANUALS and PUBLISH to control if
the manuals should be built and uploaded. Describe all environment vars
on top of the file.

When WITH_MANUALS is set, install osmo-gsm-manuals like any other
dependency and add --enable-manuals to the configure flags (for "make"
and "make distcheck"). Add the bin subdir of the installed files to
PATH, so osmo-gsm-manuals-check-depends can be used by ./configure.

Related: OS#3385
Change-Id: I54fdd18e405b2c84762ea06d91359867ceec8184
2018-12-05 13:10:38 +01:00
Pau Espin Pedrol
ed361f9912 lms: Close device on LMS_Init failure
Change-Id: I0b307452a9e122a0ea39a46f096423c9a5293d30
2018-12-04 15:57:37 +00:00
Pau Espin Pedrol
2d085e290b osmo-trx: Change some lines to use libosmocore logging instead of cout
Change-Id: I66e3c37014ba12cd002e5b678bc0a6026f5dfc7e
2018-12-04 15:57:37 +00:00
Pau Espin Pedrol
5cea18e5cb lms: Make sure LMS_Close is called when Device is torn down
This change fixes lots of memory leaks inside libLimeSuite as
announced by ASan after exiting the osmo-trx process (throgh
CTRL+C for instance).

This way also we make sure libLimeSuite can communicate with the HW and
close whatever subsystems were enabled during LMS_Open time.

Change-Id: I56ffb87079e34aa2d0322fd2ca6429742f9f7640
2018-12-04 15:57:37 +00:00
Oliver Smith
4adc4eb8d0 Fix DISTCHECK_CONFIGURE_FLAGS override
Set AM_DISTCHECK_CONFIGURE_FLAGS in Makefile.am instead of
DISTCHECK_CONFIGURE_FLAGS. This is the recommended way from the
automake manual, as otherwise the flag can't be changed by the user
anymore.

Related: OS#3718
Change-Id: I725026cd2dda333085a263c503058aac4305197d
2018-12-04 15:41:40 +01:00
Pau Espin Pedrol
41c68aa41c PointerFIFO: Fix memleak of ListNode
Found by ASan. when PointerFIFO::release() is called, alloicated node
being released is actually stored into an internal list for later-reuse
without having to access memory allocator. However, nodes from this
list are never freed.

Change-Id: I40e5e28603cde67005d9d92772967b05465ea2b8
2018-12-03 12:59:12 +00:00
Pau Espin Pedrol
39e0bbacca radioInterface: Fix memleak during close()
destructors of pointers created through "new" must be destroyed manually
through "delete".

Change-Id: I10d37579f16bec89cc762f200a8951218305c708
2018-12-03 12:20:07 +01:00
Pau Espin Pedrol
b4ea7b5211 lms: Destroy streams on device stop
They are recreated during start(). Actually, if they are not stopped
here, during start() after stop(), LMS_SetupStream() will fail because
it will detect the streams are already opened.

Change-Id: I70d47c287aabdabc5dc1304a942d130aeb10bdc5
2018-12-03 11:34:25 +01:00
Pau Espin Pedrol
69869bd58f lms: Fix start after stop of device
Change-Id: I56358a1d1601853bc6dd2e6bb5f80798d0ba84b2
2018-12-03 11:19:52 +01:00
d0gtail
ebb37693a5 UHDDevice: log exception information on device open failure
Change-Id: Ia84ddcf50cc83f9326b22bfdfb4f259b4e0bc5f1
2018-12-02 20:01:26 +00:00
Harald Welte
55928f23cb lms: Set Rx gain to midpoint, as comment suggests.
So far, the Rx gain was set to 34 dB, wile the comment stated it
would be set to half-point, which is 73/2=36dB.  Let's adjust the
code to match the comment.

Change-Id: Idc646def53b83faf4e6c011fb595fa436e223b32
2018-11-29 13:26:37 +01:00
Harald Welte
0277b58f6d lms: User correct scale factor for transmit samples
Due to (I believe) a copy+paste mistake from the USRP1 code,
we were using only a scale range of up to 9830 when transmitting
samples, rather than the full 16 bit signed integer range up to
32767.

As a result, we were loosing almost two bits (MSBs) of resolution
as well as a lot of transmit power.

This changes the scale factor to 0.707 (1/sqrt(2)).

Please note that the much higher DAC output level means that the analog
gain should be reduced.  The theoretic range of up to 73dB should not
be used, but Lime Microsystems suggest a value of 61..67 dB.  This can
be achieved by using a "osmotrx tx-attenuation" value of 6..12 inside
the osmo-bts-trx configuration file.

Related: OS#3341
Related: OS#3342
Change-Id: I71702feaa11f53e7614a6938a984dd748405474a
2018-11-29 13:23:08 +01:00
Oliver Smith
be8a83f681 build manuals moved here from osmo-gsm-manuals.git
Moved to doc/manuals/, with full commit history, in preceding merge commit.
Now incorporate in the build system.

Build with:

$ autoreconf -fi
$ ./configure --enable-manuals
$ make

Shared files from osmo-gsm-manuals.git are found automatically if
- the repository is checked out in ../osmo-gsm-manuals; or
- if it osmo-gsm-manuals was installed with "make install"; or
- OSMO_GSM_MANUALS_DIR is set.

Related: OS#3385
Change-Id: I2762171af0bf719a34ba12a0c2e4dcc206098beb
2018-11-27 18:36:41 +01:00
Neels Hofmeyr
d9a460dce9 Merge history from osmo-gsm-manuals.git 2018-11-27 18:36:29 +01:00
Pau Espin Pedrol
f570b4af62 osmotrx: Introduce code architecture chapter
Change-Id: I21084e6315d79a1adcb305e12343da218837dc31
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
46560ea254 osmotrx: Create a common chapter for section documenting backends
Change-Id: I6bea1ccca4ce72b92641a36f9f5894ac9a6cae72
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
038ab45137 osmotrx: configuration: Add section to document multi-arfcn feature
Change-Id: Id04c7f7c36d8a8be8145ef8009ece26ef1a7cdff
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
6b50b62b12 osmotrx: Write initial documentation for several supported devices
Change-Id: I902b01ca661416eb9705afac8a34ec8d2fb13789
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
3984256273 osmotrx: Split Device specific section from backend one
Device specific sections will be added to this new chapter.

Change-Id: Id96cbf857e2ef92d9ad2cb58fd18132f981447d7
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
d06172ce32 trx: Add Hardware device support section
Change-Id: I87fc54cf1751f31a3e92d6503625e984f9a6130f
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
762c951faa trx: Add Hardware architecture support section
Change-Id: I38388bcb2ea7c0481052d3bca589cb34965ea7fa
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
e47d7e964a trx: Add reference to project wiki page in overfiew section
Change-Id: I83cbd67909c42f4ed4857834e23c07ad4e2e22aa
2018-11-27 18:36:18 +01:00
Harald Welte
3cee25ac68 vty-ref: Update URI of docbook 5.0 schema
... to match the /etc/xml/catalog file on debian (no "www" in hostname)

Change-Id: Id9f3579c7f2bc3af13fe30b5268f249b6f59ed0d
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
0bd0782a39 Introduce chapter trx_if.adoc and add it to OsmoTRX and OsmoBTS
This chapter defines the protocol used between osmo-trx and
osmo-bts-trx.

Most of the text comes originally from osmo-trx.git/README, as it's the
only known documentation of the protocol other than the code itself.

Change-Id: I56c418eef0f826ae1aadbed5b151fbed241c7885
2018-11-27 18:36:18 +01:00
Pau Espin Pedrol
8072650406 Introduce OsmoTRX manual
Change-Id: I19ee9d6cda02fb7200c96c0ac129e69825b096cd
2018-11-27 18:36:18 +01:00
Neels Hofmeyr
c6541e6c26 Importing history from osmo-gsm-manuals.git 2018-11-27 18:36:03 +01:00
Pau Espin Pedrol
1e2c0105e2 lms: Apply LMS->OSMO log level conversion
Change-Id: I3a8fbcc7cacebc7038c60175a8ae43b21f713cbb
2018-11-23 14:39:51 +01:00
Pau Espin Pedrol
32b3c2e4b2 lms: Use LimeSuite.h log level defines instead of hardcoded values
Change-Id: Iee693da1a0fa1db23deafa8d3845c04171e24799
2018-11-23 14:39:06 +01:00
Pau Espin Pedrol
1c4bbadda6 UHDDevice: setRxGain on chan 0 when using multi-arfcn
When using multi-arfcn feature, several logical channels (arfcn) are multiplxed
into one physical transceiver, as can be seen in
uhd_device::set_channels.

As a result, when multi-arfcn is enabled some properties are actually
shared for those logical channels, and internally mapped to the first
(only existing) channel, and per-channel internal array variables are allocated
accordingly (size() == 1).

When setting RxGain, we need to set the correct existing physical
channel. Same check is done in getRxGain, and then we apply the RxGain correctly and
we avoid outputing an error "Requested non-existent channel" immediatelly after.

Change-Id: I5b02bb1ef6450dc48be7b8058d96a5691847d3cc
2018-11-19 11:47:37 +01:00
Pau Espin Pedrol
08dfe237c8 ChannelizerBase: Fix ASan alloc-dealloc-mismatch
Fixes following Adress Sanitizer warning:
=================================================================
==27120==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete) on 0x60c00003d900
    #0 0x7f2f216de421 in operator delete(void*, unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cc:151
    #1 0x561641ce18b7 in ChannelizerBase::~ChannelizerBase() (/build/new/out/bin/osmo-trx-uhd+0x4a8b7)
    #2 0x561641ce1cad in Channelizer::~Channelizer() (/build/new/out/bin/osmo-trx-uhd+0x4acad)
    #3 0x561641cd5160 in RadioInterfaceMulti::close() (/build/new/out/bin/osmo-trx-uhd+0x3e160)
    #4 0x561641cd5047 in RadioInterfaceMulti::~RadioInterfaceMulti() (/build/new/out/bin/osmo-trx-uhd+0x3e047)
    #5 0x561641cd5093 in RadioInterfaceMulti::~RadioInterfaceMulti() (/build/new/out/bin/osmo-trx-uhd+0x3e093)
    #6 0x561641ca3fdd in trx_stop() (/build/new/out/bin/osmo-trx-uhd+0xcfdd)
    #7 0x561641ca4b32 in main (/build/new/out/bin/osmo-trx-uhd+0xdb32)
    #8 0x7f2f1f555222 in __libc_start_main (/usr/lib/libc.so.6+0x24222)
    #9 0x561641ca195d in _start (/build/new/out/bin/osmo-trx-uhd+0xa95d)

0x60c00003d900 is located 0 bytes inside of 128-byte region [0x60c00003d900,0x60c00003d980)
allocated by thread T0 here:
    #0 0x7f2f216dcf19 in operator new[](unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cc:93
    #1 0x561641ce142d in ChannelizerBase::init() (/build/new/out/bin/osmo-trx-uhd+0x4a42d)
    #2 0x561641cd5865 in RadioInterfaceMulti::init(int) (/build/new/out/bin/osmo-trx-uhd+0x3e865)
    #3 0x561641ca1cb7 in makeRadioInterface(trx_ctx*, RadioDevice*, int) (/build/new/out/bin/osmo-trx-uhd+0xacb7)
    #4 0x561641ca44c6 in trx_start(trx_ctx*) (/build/new/out/bin/osmo-trx-uhd+0xd4c6)
    #5 0x561641ca4b05 in main (/build/new/out/bin/osmo-trx-uhd+0xdb05)
    #6 0x7f2f1f555222 in __libc_start_main (/usr/lib/libc.so.6+0x24222)

SUMMARY: AddressSanitizer: alloc-dealloc-mismatch /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cc:151 in operator delete(void*, unsigned long)
==27120==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
==27120==ABORTING

Change-Id: Ib7c98ae478f319573dd86a0d2cb264f676bb3859
2018-11-01 18:23:32 +01:00
Vadim Yanitskiy
444ff34396 sigProcLib: add a CorrType for extended (11-bit) RACH
This is a preparatory change that enables a possibility to choose
the amount of synch. sequences to be used for Access Burst (RACH)
detection. The VTY flag will be introduced in further changes.

There are two correlation types now:

  - RACH (default) - TS0 only;
  - EXT_RACH - all TS0, TS1, and TS2 together.

Change-Id: Ia4f20524350bb8c380d7e10360758eddae8b03e9
Related: OS#3054
2018-10-24 19:28:47 +00:00
Vadim Yanitskiy
a79bc70737 sigProcLib: introduce both TS1 and TS2 RACH synch. sequences
According to 3GPP TS 05.02, section 5.2.7, there are three
synch. sequences for Access Bursts:

  - TS0: GSM, GMSK (default),
  - TS1: EGPRS, 8-PSK,
  - TS2: EGPRS, GMSK.

Let's prepare everythyng to be able to detect all TS0-3 synch.
sequences, but keep detection of both TS1 and TS2 disabled
until the corresponding VTY option is introduced.

Change-Id: I838c21db29c54f1924dd478c2b34b46b70aab2cd
Related: OS#3054
2018-10-24 19:28:47 +00:00
Oliver Smith
a439fed166 Add long parameters (--help, --version, ...)
Makes osmo-trx-* more consistent with other Osmocom programs, and
allows an unified test for not having "UNKNOWN" in --version.

Related: OS#3578
Change-Id: I90cf01d972aa10b48c59b67a1e7f82a4255ef526
2018-10-23 11:34:43 +00:00
Harald Welte
8fb0c3dce4 trx_validate_config(): Fix validation of rx_sps
Change-Id: I7e932cff59335add09c76caba6f9ac1e7cf69022
Fixes: Coverity CID#188871
2018-10-21 13:48:26 +02:00
Harald Welte
f5e1cf8790 SocketsTest.testReaderIP(): Zero terminate received buffer
Change-Id: Icd144e672ab15cfb0955897dd6eb529c56908eba
2018-10-21 12:14:55 +02:00
Pau Espin Pedrol
e7d267f178 jenkins.sh: Enable build of osmo-trx-lms
Change-Id: Idfa7ce566ad69b181bcadeee7ff023c77ecd4d6b
2018-10-09 14:08:41 +02:00
Pau Espin Pedrol
06f3b622b8 examples: Use logging level 'set-all' instead of 'all'
Change-Id: Ic52ce0defc774acb8e24947ed22cf2a56b8b0bb0
2018-10-05 16:49:23 +02:00
Pau Espin Pedrol
74bcc562a9 Transciever: Log values causing Tx underrun
Change-Id: I68e18075eade55034567d96fc774d00a794afeeb
2018-10-02 17:30:28 +02:00
Pau Espin Pedrol
55dd2aa5ab CommonLibs/Makefile.am: Specify libcommon_la_LIBADD
This way the dependencies are passed after the .la object, which seems
to be the correct order. Some setups may fail to find some symbols from
libosmocore otherwise (OBS i586).

Change-Id: I22c80055bcffd4179a0a8ca76533ba7aaa38c859
2018-10-02 09:34:55 +02:00
Pau Espin Pedrol
5b60c98769 Use pthread_setname_np to name threads
osmo-trx can start a considerable amount of threads that can make
debugging it challenging at least. By using phtread_setname_np, the
system sets a meaningful name to the thread which can be seen while
debugging with gdb or by printing /proc/$pid/task/$tid/comm.

Now we also log system TID when setting the name so we can identify
different tasks in /proc even if pthread_setname_np fails.

Change-Id: I84711739c3e224cb383fd12b6db933785b28209e
2018-09-28 23:17:57 +00:00
Harald Welte
207d8a2624 ensure well-formed example config files
Change-Id: I9be2bab3b88a96e94e463e5ab22f9814bd6de950
2018-09-25 18:51:51 +00:00
Vadim Yanitskiy
92fc186450 device/lms/LMSDevice.cpp: fix compilation warning
The following warning was observed with GCC 4.8.5:

  make[4]: Entering directory `.../osmo-trx/Transceiver52M/device/lms'
    CXX      LMSDevice.lo
  LMSDevice.cpp: In member function 'LMSDevice::writeSamples()':
  LMSDevice.cpp:582:22: warning: 'rc' may be used uninitialized
                        in this function [-Wmaybe-uninitialized]
    samplesWritten += rc;

Let's fix this by zero-initializing 'rc'.

Change-Id: I4b4a061fc12e5fd1db8d1087d8e0c46ff1e23412
2018-09-20 16:17:19 +07:00
Pau Espin Pedrol
4d179abfd0 cosmetic: Use proper whitespace in several for loops
Change-Id: I82bdeb8a3fa38f3d125e8cbccc3eddbf2b8d8f58
2018-09-13 14:27:48 +00:00
Pau Espin Pedrol
6fdfb68b9e Install sample cfg file to /etc/osmocom
Change-Id: Ib871a3cd14386ef6e6b512a3d66e7e7a839295a5
2018-09-12 20:51:29 +02:00
Pau Espin Pedrol
5ac2cb3662 Install systemd services with autotools
Change-Id: Ia1a4fb62dee35737ece1f3501f352501eba2449e
2018-09-12 14:17:26 +02:00
Pau Espin Pedrol
f4ee021b8c jenkins.sh: Add --enable-werror flag to osmo-trx configure step
This way we catch newly introduced compilation warnings in osmo-trx.

Change-Id: I7effaf243fd6e7fe69728cfce5f97e0b5bd4743c
2018-09-10 10:33:39 +02:00
Pau Espin Pedrol
e62555370e Vector: Copy arrays in a sane way for non-trivially copyable types
Avoids this type of compilation warnings:
‘void* memcpy(void*, const void*, size_t)’ writing to an object of non-trivially copyable type ‘class Complex<float>’; use copy-assignment or copy-initialization instead [-Werror=class-memaccess]

Change-Id: I9724454dfb7b87f74f39074e4004580ac3b5fe5c
2018-09-10 10:33:34 +02:00
Pau Espin Pedrol
1f15152968 radioInterfaceMulti:pullBuffer: Sanely convert float array to complex array
Fixes this type of compilation warning:
‘void* memcpy(void*, const void*, size_t)’ writing to an object of non-trivially copyable type ‘class Complex<float>’; use copy-assignment or copy-initialization instead [-Werror=class-memaccess]

Change-Id: Ibb2380a0a335ce798fe87221519fbbebade53054
2018-09-10 10:30:06 +02:00
Pau Espin Pedrol
21ce05c54f cosmetic: Fix trailing whitespace in several files
Change-Id: Ibf5a69f0a3a309e87814635fd903b114fe68890c
2018-09-10 10:30:06 +02:00
Pau Espin Pedrol
5e68cde779 SigProcLib: Use available copyTo Vector API instead of memcopy
This change allows to remove some wrong use of code as per compilation
warning:
osmo-trx/Transceiver52M/sigProcLib.cpp:1266:40: error:
‘void* memcpy(void*, const void*, size_t)’ writing to an object of non-trivially copyable type ‘class Complex<float>’; use copy-assignment or copy-initialization instead [-Werror=class-memaccess]
   midMidamble->size() * sizeof(complex));

Change-Id: Id446711349bec70fa4e7c8efe0f7f9faf7e4f277
2018-09-10 10:30:06 +02:00
Pau Espin Pedrol
1f4a009c67 UHHDDevice: Replace deprecated header uhd/utils/thread_priority.hpp
Fixes compilation warning:
In file included from osmo-trx/Transceiver52M/device/uhd/UHDDevice.cpp:31:
/usr/include/uhd/utils/thread_priority.hpp:10:17: note: #pragma message: This header is deprecated - please use <uhd/utils/thread.hpp> instead.

Header was moved in uhd.git c33928d2bbdd27688c3475e77fc461e7d16eba5a.

Change-Id: I6299df48a5e14c54eaa07288d166c705eb9ebdbe
2018-09-10 10:30:06 +02:00
Harald Welte
544ce0d6b7 update git-version-gen to generate proper version numbers
We don't want the version of the last tagged version, but the version
number uniquely representing the current HEAD.  Use the script from
libosmocore.

I suspect that this somehow got broken in commit 00d5114717

Related: OS#3517
Change-Id: Iba3212aa417dce4240c5c27eb4f12afcd9c95e5b
2018-09-04 18:01:35 +00:00
Pau Espin Pedrol
b148d05542 configure.ac: Specify default language as C++
This is useful if we add more AC_CHECK_HEADER or similar configure tests including
C++ header files or required C++ features, since otherwise gcc is used
by default and test fail.

Change-Id: Iee757c78b72290c5d2a4c31339800a4e72b6be23
2018-09-04 18:00:57 +00:00
Pau Espin Pedrol
970096932e radioInterface: Fix variable storing integer return value
Change-Id: I0a0a06a6d16a228cfcb7bd746bab2d79f10ce244
2018-09-04 16:35:27 +02:00
Pau Espin Pedrol
db936b9b55 osmo-trx: Add osmo_signal to stop whole transceiver chain correctly on error
Transceiver::stop() can only be called from either CTRL iface thread or
from main thread (running osmocom loop). That's because stop attempts to
cancel and then join all the other threads, which would then lock if
attempting to stop from some of them.
As a result, the best option is to indicate to the user of the
transceiver option (osmo-trx.cpp) to stop it in a correct fashion by
destroying the object from the main thread.

Change-Id: Iac1d2dbe2328e735db2d4b933cb67b1af1babca1
2018-09-04 16:35:23 +02:00
Pau Espin Pedrol
49ad759072 lms: Return error on device read timeout
If LImeSDR device is unplugged or its fw crashes during operation,
reading from the device will fail and will first receive short reads and
finally 0 byte reads. Let's quickly notify these events to upper layers
instead of trying to process the buffer and checking timestamps for
something we know it's already not useful.

Related: OS#3340
Change-Id: Ib1af8cdd6cdadf581b039882add4049eea45a0f7
2018-09-03 18:53:52 +02:00
Pau Espin Pedrol
8e498bfd35 radioInterface: forward errors from RadioDevice to Transceiver in recv path
Change-Id: Id7b08b19d6575c79b4d57db656a17ff05bb61ee9
2018-09-03 18:53:52 +02:00
Pau Espin Pedrol
46444637c6 cosmetic: Fix trailing whitespace
Change-Id: Ia647cfed0acb35adeb9b3b7824170d06c0369ef7
2018-09-03 18:53:41 +02:00
Pau Espin Pedrol
86be40b4eb Logger: Disable pthread cancel point inside Logger destructor
pthread_cancel is implemented in c++ using exception handlers. In
destructor of Log object, the log function is called which will
eventually call fputs() to write to a file. Since that function is
considered a cancelation point, if pthread_cancel has been called the
exception handler will start unstacking frames and calling destructors
in the process. At some point this will cause a runtime exception in c++
which will call std::terminate() to abort the process.

The solution is thus to avoid starting the cancellation process inside the
destructor.

This behavior was spotted while calling the destructor of Transceiver
object in forthcoming patches.

See a more detailed example here:
https://skaark.wordpress.com/2010/08/26/pthread_cancel-considered-harmful/

Change-Id: I71ca90f3fbc73df58b878a03361f7b7831d838b4
2018-09-03 15:22:53 +02:00
Pau Espin Pedrol
288d8af070 configure.ac: Add --enable-werror option
Change-Id: Ib2782aecd400398bf36427f255c2a427ef781e06
2018-08-30 17:30:15 +02:00
Pau Espin Pedrol
aae403f0c9 vty: Fix typo in gpsdo clock reference type
Change-Id: I3f553c2cec9689524728cacb15b7daaff8166925
2018-08-27 16:50:19 +02:00
Harald Welte
5cc8858d8f logging: Introduce new "DDEV" category for device-specific code
The DMAIN category got too overloaded.  Let's have the code in
Transceive52M/device/* use the new DDEV category.

Also, in some cases the log levels have been adjusted to ensure
that enabling INFO level should not result in a complete overflow
of messages during normal operation.

Change-Id: I844fe4a75bf277cd3cc5bd8fa06e06ad97b2ea95
2018-08-17 19:57:40 +02:00
Pau Espin Pedrol
70d0344b31 configure.ac: Fix typo in with-lms help string
Change-Id: I7777d027fffa50dddf3f0a3c0bf2173aa8497be3
2018-08-17 17:17:05 +02:00
Alexander Couzens
62002fb8ac debian: add patches for debian8
The osmocom-nightly/release can create debian8 package by patching
rules and control files

Change-Id: I261302d2ed16e76540073589504e7426e23d00a1
2018-08-09 05:02:36 +02:00
Harald Welte
03b3c30533 Fix config file saving of {tx,rx}-path VTY config strings
We were missing one indent level when writing the rx-path and tx-path

Change-Id: I5d5b02c71d39220cabc2a23d059908ef3c6350e0
Closes: OS#3435
2018-07-31 15:48:18 +02:00
Pau Espin Pedrol
a4b569d936 debian: Explicitly enable osmo-trx-uhd build
osmotrxuhd is already being built since it's enabled by default, but
let's make it more explicit that we are building it too.

Change-Id: Ie9c224485cce047cd3ee4600ff7fbdb082355cdc
2018-06-25 17:02:22 +02:00
Pau Espin Pedrol
eb0945d85d debian: Enable build of osmo-trx-lms
Change-Id: I4711e97c844e582601a588fdc359fc020bcee001
2018-06-25 16:09:25 +02:00
Pau Espin Pedrol
f968507912 Use correct paths when installing example files
Fixes: c7756e73b7
Change-Id: If55d14768727c7119d86da60413861674dd3538b
2018-06-25 12:57:17 +02:00
Pau Espin Pedrol
58c89fb8d6 lms: Allow values diff than 34dB to be set by setRxGain()
Until now, setRxGain in LMSDevice did not take into account the setter
parameter and was always using hardcoded 34dB, which was experimentally
found to be a good default value.

Let's force that value during initialization, but still allow the upper
layers (controlled by BTS) to set different values. osmo-bts only sends
a SETRXGAIN command (which calls setRxGain in osmo-trx) if a value is
explicitly set in its VTY config, so we are on the safe side if the user
doesn't explicitly configure a desired dB.

Change-Id: I5684e675281a3f581855dbb56d199a6fe238a712
2018-06-20 07:41:16 +00:00
Pau Espin Pedrol
16e7e20f85 Add -V param to print version
Change-Id: I9f2d6c4b1a508aceb1ccc0559f0902eedf2ec5af
2018-06-20 07:38:36 +00:00
Pau Espin Pedrol
c7756e73b7 debian: Add cfg file examples for osmo-trx-{lms,uhd}
Sort cfg files according to their osmo-trx binary.
Install them during make install.
Add the installed cfg files to related debian packages.

Change-Id: I905cdac30b441e4df0a3f5c0924d1637b9f67b90
2018-06-19 11:31:45 +02:00
Pau Espin Pedrol
7ed686b223 contrib: Add systemd services for all backends
Change-Id: I38a7ff7b9dafc3d6aa0426777036e3d7666045a7
2018-06-19 11:05:04 +02:00
Pau Espin Pedrol
2ab6ddb0de debian: Add package osmo-trx-lms
Change-Id: I3213c66907fbf0c7e531835b4993fa1bdc89edc3
2018-06-19 11:05:04 +02:00
Harald Welte
b229439b31 usrp1: Fail in case of unsupported configuration
There might be some configuration that's not supported by osmo-bts-usrp1,
and we should reject that properly.

Change-Id: Ic7308ce0c57439fe97668bd31801c4bf76b797ad
Closes: OS#3348
2018-06-14 12:38:09 +02:00
Harald Welte
ffb3301bd8 lms: Fail in case of unsupported configuration
There might be some configuration that's not supported by osmo-bts-lms,
and we should reject that properly.

Change-Id: I6f82edce589030a4407f6150fb7e8abe6417c1f2
Closes: OS#3347
2018-06-14 12:38:09 +02:00
Harald Welte
62b7900fd7 lms: Fix coding style
In Change-Id Ib2fca81b76d027b08e2891056fa076d071597783 we introduced
some coding style violations.  Let's make newly-added code follows
standard Osmocom coding style.

Change-Id: Ib7ddd275014f03a2eed3cddc02b1356e2b00c0bc
2018-06-14 12:38:09 +02:00
Harald Welte
61707e8b23 radioDevice: better encapsulation in base class
It's not good style to have the derived classes initialize members
inherited from the base class using "this->foo = bar".  Rather, let's
make the base class have a constructor, and call that constructor to
initialize the members of the base class.

While doing this
* rename 'offset' to 'lo_offset' to avoid confusion with timestamp offset
* move 'InterfaceType' into the base class
* move 'chans' into the base class
* move 'rx_sps' into the base class
* mark base class members as 'protected'

Change-Id: Ib885675a7612a392aa7f75fca81269ddcff2f6ab
2018-06-14 12:38:04 +02:00
Harald Welte
ce70ba529c radioDevice: Move tx_sps from derived into base class
All three derived classes use a tx_sps member, let's move this into
the base class.

Change-Id: I73b4aa2705c5049561e2d7b21301a0d2b3c96ced
2018-06-13 23:46:27 +02:00
Harald Welte
cfb9dac70d lms: Call set_antennas() during open() method
Without this call, the antenna/path configuration is not applied.

Change-Id: I0bca58266b59f1315ec72b6407fe4f4495aff678
2018-06-13 23:46:27 +02:00
Harald Welte
105a61e689 lms: Fix support for rx_paths / tx_paths
Before this patch, any configuration in osmo-trx.cfg regarding the rx
and tx "antenna" (path) would have been completely ignored, as the
radioDevice::make() function would simply drop those arguments to the
floor.

Change-Id: Ie50f854abbc9dcf351cddc052d10206382e1d5d3
2018-06-13 23:46:27 +02:00
Harald Welte
2407314f2e move set_antennas() from UHD to generic radioDevice base class
Change-Id: I806143e9db21f0be4dcc6a376b3a630be7aeb3ba
2018-06-13 23:46:27 +02:00
Zydrunas Tamosevicius
ff4418539c lms: Reduce Rx gain from 47 to 34 dB
Initially, Rx gain was hardcoded to be 47. This was too high for our
setup and we were constantly getting "clipping detected" messages.

Reducing Rx gain to 34 solved the issue. However, it looks like gains
should be controlled through configuration files.

Change-Id: I30580f18c4ad630c09f725b1d24c125fc3119809
2018-06-13 21:45:32 +00:00
Zydrunas Tamosevicius
0494d05916 lms: fix LMS_StartStream() handling for multiple channels
LMS_StartStream() (in LMSDevice::start()) was moved to separate loop. It
is because LMS_SetupStream() would fail for second channel if streaming
has already been started (LMS_StartStream()) for single channel
configuration.

Change-Id: I6704bb92864aa81417507c4ae24a22f41dc529c1
2018-06-13 21:45:32 +00:00
Zydrunas Tamosevicius
fd268b6f5a lms: Reduce log level of "send buffer of len ..."
Log level of "send buffer of len ..." messages was changed as it was
causing problems on some machines.

Change-Id: I605d50e81966c7bd169b27788d62af6fb54c84e1
2018-06-13 21:45:32 +00:00
Zydrunas Tamosevicius
43f3678b40 lms: Use same timestamp offset like when using LimeSDR via UHD
The tx timestamp offset was not set. We set it to the same value as it
was in UHD interface for LimeSDR

Change-Id: I78bc40cd575097f71a5f82b63467fa81c3f8d837
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
6493dc838b lms: Check LPBFW to set is within supported range
As of LimeSuite 618fbb9c3188b36d75ad5785a97b8887dcc468f6, it seems 5e6
is within the returned range, but LMS_SetLPFBW fails anyway.

See for more information: https://github.com/myriadrf/LimeSuite/issues/184

Change-Id: I967e7da7c0e3e8138b76733ee4a0e6311d20b62e
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
f7905ac548 lms: Makefile.am: Reorder params to fix link issue
It seems the order in which static code and -lfoo is passed to the
linker matters.

This commit is a lms specific follow-up of commit
2a8183bdf0.

Change-Id: I59c20d268ecac4c22689124165c47295bd9176d4
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
0c27938d44 LMSDevice: Fix setup failure with LimeSuite > 18.04.1
Fixes: https://github.com/myriadrf/LimeSuite/issues/184

Change-Id: Ia9f37995cd10d19d6820e3e12b8ee8f3efbff5d4
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
587916e810 LMSDevice: Set correct values for Max{Tx,Rx}Gain
Change-Id: I3b3a7080a69e15d8d6770186810d922227439099
2018-06-13 21:45:32 +00:00
Harald Welte
79024867de LMSDevice: Reduce Rx logging verbosity: Only log unexpected timestamps
Change-Id: I06b35efb7368616b9f4d348da574cd524ffe3ea6
2018-06-13 21:45:32 +00:00
Harald Welte
4aec1f1cf5 LMS_Device: Set ts_offset to 0.
I'm not quite sure what the ts_offset is for, but by using "0"
we are now receiving exactly the timestamp that we're expecting:

LMSDevice.cpp:486 [tid=140576250332928] chan 0 recv buffer of len 2500 expect 305ed0 got 305ed0 (305ed0) diff=0

Change-Id: I270c94945b1af9662cfc468cfda1ae3af3ac0a27
2018-06-13 21:45:32 +00:00
Harald Welte
68f054169b LMSDevice: Fix initial timestamp offset of 2500
ts_initial must not point to the timestamp of the first sample
in the last "flush" sample buffer, but to the first timestamp we
expect in the next buffer.

Change-Id: I23af62870544d4c6cf5f6e2d6578936603bceb91
2018-06-13 21:45:32 +00:00
Harald Welte
ea8be22e50 LMSDevice: Set low-pass filters to smallest possible option
Rx 1.4 MHz, Tx 5MHz.  Both massively too wide for GSM, but there's
no smaller band-width available.

Change-Id: I9723c9a2ea77f65bfa9d796d7c44adc2417e89cf
2018-06-13 21:45:32 +00:00
Harald Welte
a5054b398b LMSDevice: Typo fix: s/Internal/External
Change-Id: Icacfe6da90a89c7f00d62c580948fb913998eaa7
2018-06-13 21:45:32 +00:00
Harald Welte
a438114173 LMSDevice: Print sample rate range + actual sample rate after setting it
Change-Id: I19c1a5b2d2431b8d39e277244e313f6e559e4d25
2018-06-13 21:45:32 +00:00
Harald Welte
9cb4f27112 LMSDevice: Call LMS_Init() before setting sample rate
LMS_Init() will override basically all device settings with their
default value, including the sample rate.  We hence have to make sure
to call it before any other API function that changes the device config
such as sample rate, frequency, filter bandwidth, ...

Change-Id: I4cdbae8406b5e1e93da491e90f8bad41d4be748b
2018-06-13 21:45:32 +00:00
Harald Welte
c38e45e9dc update .gitignore to include osmo-trx-lms
Change-Id: I52efd2f71eb61baa80427ab9f7b518f17d514792
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
1f50fedb5f build: Add support for LimeSuite device backend
Change-Id: I239e1b37263a62b374d84974c9347e3654072e87
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
c7a0bf1ffc lms: Several improvements and compilation/runtime fixes
Continuation of initial work done on LimeSuite support from Harald.

Change-Id: Ib2fca81b76d027b08e2891056fa076d071597783
2018-06-13 21:45:32 +00:00
Harald Welte
940738e86a Initial work towards direct LimeSuite support in OsmoTRX
This is work in progress towards a direct LimeSuite driver in OsmoTRX,
bypassing the currently rather complex stack of wrappers by going
through UHD, SoapyUHD, SoapySDR and LimeSuite.

Change-Id: Iaef29c4c2585ef8c2f94866c9591919f538c1a2d
2018-06-13 21:45:32 +00:00
Pau Espin Pedrol
8c1e2bddff examples: Set rt-prio 18 and print file basename
Change-Id: I16fbdd46f2d9b6f3e79a4bb357f6a7fbed14244a
2018-06-12 18:23:40 +02:00
Vadim Yanitskiy
01eea0aa42 trx_vty.c: fix: use CONFIG_NODE as parent by default
There are some configuration nodes, which are handled by extenral
libraries, such as libosmoctrl. So, when switching back to the
parent node, this should be kept in mind.

Instead of aborting, let's got to the CONFIG_NODE by default.

Fixes: OS#3250
Change-Id: Ia0600a46d19825806e5aed9257b6c57c3907808b
2018-05-09 15:19:56 +07:00
Pau Espin Pedrol
55df1e43e3 UHDDevice: Fix setup failure with LimeSuite > 18.04.1
Fixes: https://github.com/myriadrf/LimeSuite/issues/184

Change-Id: I48ead8b8996981263297b66c0c7d3d0972261316
2018-05-08 20:49:04 +02:00
Pau Espin Pedrol
e9424e241f doc: examples: Add umtrx sample config
Change-Id: Id38de0bbbe75e5e6bbb0de2eecb7d1984786d528
2018-05-04 14:01:50 +00:00
Pau Espin Pedrol
d0ac926b56 Bump version: 0.3.0-dirty → 0.4.0
Change-Id: Ifc469bce89d52012e1f876c847b4535360a602ad
2018-05-03 16:23:30 +02:00
Pau Espin Pedrol
00d5114717 git-version-gen: Take into account tags not in master
Latest tag 0.3.0 was created in a release branch instead of master. As a
result, git describe doesn't show them. Let's instead reuse git command used in
osmo-ci to get latest tag from tag list when OBS latest repository is
built.

Change-Id: I3e461d4270b5e6d4c42126df4deef5651dca1e27
2018-05-02 21:29:05 +00:00
Philipp Maier
3a496f3b8a doc: add example config for usrp B200 series
Change-Id: I1a80ddd9ca9b143e9c89618616f30fe3f3547d7b
2018-05-02 18:41:34 +02:00
Harald Welte
fad2e09840 osmo-trx: s/GSM Core Address/GSM BTS Address/
The TRX connects to the BTS, not to the "Core".  The Core network
is miles away...

Change-Id: I6de2f708fc7a7df7dea16314b7dfa4ab82f15b2c
2018-04-28 21:43:40 +02:00
Harald Welte
e09e80f5ee update .gitignore for new executable names
Change-Id: Id698024485176e5201ca92c72b1bd1d5914aff32
2018-04-28 21:43:36 +02:00
Harald Welte
2e276e7edd debian/control: Add build dependency to libusrp-dev
Change-Id: I9593c9e45d304b7ffc94474e94450da418838513
2018-04-28 14:38:16 +02:00
Harald Welte
dffc21725c debian: Ensure USRP1 firmware is part of osmo-trx-usrp1
The std_inband.rbf files are required to operate USRP1 with timestamps

Change-Id: I9b3e937ea1941953dcdcaf57cfec9575cd5a8a9c
2018-04-28 14:22:57 +02:00
Harald Welte
96f0f2cf7e debian/rules: Make sure we always require libusrp
Change-Id: Id9c9188a24617f83efa0e1fcf54f9e0dd223e365
2018-04-28 14:21:14 +02:00
Harald Welte
225b16d48e debian/control: Remove "Maintainer" from binary package section
This resolves the following warning:
dpkg-source: warning: unknown information field 'Maintainer' in input data in package's section of control info file

Change-Id: I7a8d8c54eabccc5cedf7ad0a2bccf91f32f1bfdf
2018-04-28 14:21:14 +02:00
Harald Welte
0ebbb2ed2e Revert "debian: Remove osmo-trx-usrp1 until we can build libusrp1.deb"
This reverts commit 295b938d51, as we now
have libusrp built in OBS

Change-Id: Ia1311f1e236e6aea4acc08d3f234d53e46789cf9
2018-04-28 14:21:14 +02:00
Pau Espin Pedrol
2fea950644 build: Fix OBS build for ARM
Change-Id: Ic6b408d684e2bb58af71ec04ced7e73e0d38ffcd
2018-04-28 01:44:39 +02:00
Pau Espin Pedrol
d0a97a5f73 debian: Fix OBS build
osmo-trx is a metapackage, no need for .install file.
Debug files are always put into osmo-trx-dbg, no osmo-trx-*-dbg.

Change-Id: I160dd83b265dcda52762a9f9c7eac9337928da35
2018-04-28 01:38:30 +02:00
Pau Espin Pedrol
295b938d51 debian: Remove osmo-trx-usrp1 until we can build libusrp1.deb
Change-Id: I43163755a29014fe1f098e994f8df79d853c90f8
2018-04-28 01:38:30 +02:00
Pau Espin Pedrol
e8605202ab jenkins.sh: Enable build of osmo-trx-usrp1
Change-Id: I44a978fdd7fac683520be3586d84783e5e13de5f
2018-04-28 01:38:30 +02:00
Pau Espin Pedrol
2a8183bdf0 build: More OBS build failure fixes
It seems the order in which static code and -lfoo is passed to the
linker matters.

Change-Id: I3b25be0154053ae8eb5f0a24c39fb9a229130fcf
2018-04-28 01:38:30 +02:00
Pau Espin Pedrol
478f82f47e build: Fix make distcheck
Change-Id: I1fa5e34b44331cd56408ea7ad4483dcf6443b259
2018-04-27 11:34:11 +02:00
Pau Espin Pedrol
f37b0ad652 Transceiver: log timing info of stale bursts
Change-Id: I043fd8199253bdf3912c7aec2ccf98f8cbe54251
2018-04-25 20:14:55 +02:00
Pau Espin Pedrol
3b78cbfdc1 Logger: Print correct source file and line number
Before this commit, always Logger.cpp:53 was being printed.

Change-Id: Ie5c64b4961c7c41d23484784a93eda5e08331f08
2018-04-25 16:45:34 +02:00
Pau Espin Pedrol
f3d7f443a0 Build one osmo-trx binary for each device support enabled
Same way as we do in osmo-bts. After this commit, osmo-trx no longer
exists. Instead, osmo-trx-uhd and osmo-trx-usrp1 are generated based on
configure flags enabled.

A new flag --with(out)-uhd has been added to enable/disable build of
osmo-trx with UHD backend. It is left enabled by default to keep
compatibility with older build scripts. Binary with USRP1 backend must
still be manually enabled with --with-usrp1 flag.

Change-Id: Iea8c0d7434762713a53440d29bf3ebd84accb262
2018-04-24 19:17:22 +02:00
Pau Espin Pedrol
e564f0fd84 Transceiver: Move device specific code to radioDevice class
Change-Id: Ibcf258d8bf8595e286682e0bc59391b239ea7642
2018-04-24 18:46:48 +02:00
Pau Espin Pedrol
0fc20d14b3 Move device specific code out of radioInterface
This way code of radioInterface is independent of the device and doesn't
need to be rebuild for each device.

Change-Id: Id104e1edef02f863b6465ced5b4241050dc188f9
2018-04-24 18:46:48 +02:00
Pau Espin Pedrol
a4316ee4c5 Change configure define USRP1 to DEVICE_USRP1
Similar as we do for ARCH_*, it's easier to find those are related to
device support features.

Change-Id: Iba238bff689b8f944af76120402c0fa2e29a70de
2018-04-24 18:46:48 +02:00
Pau Espin Pedrol
2128a308eb Move device specific files to device subdir
Change-Id: Ib42fef14bf4c7b779f44d99711a35c18b32a4c21
2018-04-24 18:46:48 +02:00
Pau Espin Pedrol
43fedb656b Move arch specific fiels to arch subdir
Take the chance to update some includes using files available in that
subdir to have them ina more uniform way.

Change-Id: Ibda3c54fd4dc3f6b845cc373f1a1e6b758c1ea82
2018-04-24 15:22:59 +02:00
Pau Espin Pedrol
53bdb7f82a configure.ac: Add --enable-sanitize option
Change-Id: I1b5154a47bb2f66103ac254a0f422e8a80b2d3e0
2018-04-16 15:17:48 +00:00
Pau Espin Pedrol
6462dd3963 tests: Makefile.am: Fix typo in include path
Change-Id: I036f1f587f2a5eaf93ec8fb619bf76b571c1633a
2018-04-16 15:35:57 +02:00
Pau Espin Pedrol
e1977fcd22 use osmo_init_logging2()
Change-Id: I2c28e6e6e3eb9f587680b34330e03408e32c2b94
2018-04-16 14:50:55 +02:00
Alexander Couzens
f97296e0ce jenkins.sh: change qemu-img default location to $HOME/qemu-img instead of /opt/qemu-img
Change-Id: I56f314d78c0ca968b1fef9a91ecd540a7cc8fa86
2018-04-12 09:23:28 +00:00
Martin Hauke
20259cb307 configure.ac: Fix typo
Unbreak git-version-gen when used with .tarball-version

Change-Id: Id836c6822daf1f6835a8c869624b4b40dde47f3a
2018-04-08 19:53:37 +02:00
Alexander Couzens
ffa4e5938c jenkins.sh: cleanup always the workspace
It was broken before becaues of checking emptyness against literal string
will never be zero.
However it should be cleaned always because the script is executed
recursive which would also end up, never being executed.

Change-Id: Ib228ff247a72b21b12e8dd4cbe3afe3e858c89d3
2018-03-27 13:37:39 +02:00
Vadim Yanitskiy
c0c6d70fe9 Transceiver.cpp: prevent out-of-range array access
There was no a simple range check for both (NO)HANDOVER commands,
so an out-of-range access was possible. For example, a command:

  CMD HANDOVER 0 -3

might enable EDGE at run-time, because:

  a[i] == *(a + i)

Let's fix this.

Change-Id: I24a5f70e8e8097f218d7cbdef8cb10df2c35416f
2018-03-14 21:12:32 +00:00
Vadim Yanitskiy
8c6c5d2bcd Transceiver.cpp: fix incorrect format string for SETTSC
Change-Id: If69a478121a31aa7df945548cc17271c476d6a6b
2018-03-14 21:12:32 +00:00
Vadim Yanitskiy
a62fcf786a Transceiver.cpp: use pointer arithmetics for CMD parsing
It looks like the author of control command parsing code was not
familar with simple pointer arithmetics, so excessive amount of
memory and useless memcopying was used to parse a single command.

Let's introduce two pointers, one of which will point to the
beginning of a command, another to the beginning of its arguments.
Also, let's simplify the command matching by using a separate
function called 'MATCH_CMD'.

Change-Id: I226ca0771e63228cf5e04ef9766057d4107fdd11
2018-03-14 21:12:31 +00:00
Vadim Yanitskiy
4d9b59c3ef Transceiver.cpp: properly zero-terminate received commands
Previously it was assumed that a sender should zero-terminate
each command being sent. Otherwise, this could cause to printing
garbage. Let's do this manually, using the length of received
data as a position for '\0'.

Change-Id: I69f413f33156c38a853efc5a8cdc66fbfb0ca6af
2018-03-14 21:12:30 +00:00
Vadim Yanitskiy
bd0efb0bea Transceiver.cpp: use a define for the MAX_PACKET_LENGTH
No need to keep this value on stack.

Change-Id: If9ffb03b9e7b642f45732ba5938977bca271f1c7
2018-03-14 21:12:30 +00:00
Pau Espin Pedrol
8fbbd656c7 Build Transceiver52M/common as an .la lib
Stop picking files from that directory on different places as it causes
dependency issues during make distclean/maintainer-clean.

Fixes: OS#3029

Change-Id: I81bb4251d18fce978d27849b621b20f541caab0b
2018-03-08 14:53:13 +01:00
Pau Espin Pedrol
b35cba613a Makefile.am: Avoid using subdir if arch is not required
There's no need in going a level deeper if we already know nothing's
going to be done. This way we also get cleaner make outputs.

Reference: https://www.gnu.org/software/automake/manual/html_node/Conditional-Subdirectories.html#Conditional-Subdirectories

Related: OS#3029

Change-Id: I3ff57ab14edc575904e8137929a0ef02c95e03af
2018-03-07 19:46:42 +01:00
Pau Espin Pedrol
8dffadb8da osmo-trx: Re-introduce -l cmd line parameter
Parameter -l to set the terminal logging levle was removed in
3da1f8352e, but afterwards it was decided
to keep the cmd line options for a bit more to easy migration to VTY
cfg.

The command line no longer accepts keywords ("DEBUG", "INFO", etc.) but
log level numbers, due to libosmocore APIs log_parse_level and
log_level_str being marked as deprecated and for internal use only.

Keep in mind the log level is overridden by VTY cfg if any line sets log
levels for log stderr in there.

Explicit cast to unsigned int for loglvel is issued to avoid iostream
printing it as a char.

Change-Id: I91c35ecded177b7976045d9b693855adb9e18f8a
2018-03-06 18:41:29 +01:00
Pau Espin Pedrol
408f25081e osmo-trx: Use VTY cfg structures while still allowing cmd line options
Existing cmd line options are kept for a while to give people some time
to move to use VTY cfg. All new cfg options should be set only through
VTY. VTY options take preference (override) over cmd line options.
Deprecated options are removed from help message to dissuade users from
keep using them.

Steps to drop cmd line options in the future:
- Drop comma_delimited_to_vector, print_deprecated
- Drop all options in handle_options marked with print_deprecated.
- Set "-c" param to do the same as "-C", to keep compatibility with old
param and still use same naming as all other osmocom projects.
- Remove the hack in main() to set 1 channel implicitly by default.

Change-Id: Ib8de1a5da4b3c0b6a49e00033f616e1d66656adf
2018-03-05 20:12:40 +01:00
Pau Espin Pedrol
2001550f7d doc: Add sample cfg file for LimeSDR
Change-Id: I16de70eac0fd79107b8317af37201e6da834c169
2018-03-05 19:55:02 +01:00
Pau Espin Pedrol
a3ab8c263d vty: Implement VTY cfg parsing for current parameters
At this stage, osmo-trx still uses the cmdline parameters top run the
device, but it is already able to parse all the same parameters from a
cfg file through the VTY and filling a trx_ctx structure which will be
later used to drive the device. Device config can be printed in the VTY
with "show trx".

Change-Id: Ie084c1b30b63f91c6e7640832ec1797d9e813832
2018-03-05 19:55:02 +01:00
Pau Espin Pedrol
efac20b6bb Move enums required by VTY to a separate header
This patch is a preparation for next patches, which add full VTY cfg
support.

Change-Id: I3d5b0576aa96869756f1629a40306c0043b6304b
2018-03-05 17:16:05 +01:00
Pau Espin Pedrol
0bbd8922ea osmo-trx.cpp: Move trx start and stop to helper functions
Make main() smaller, and make it easier to replace cmdline parameters in
following commits.

Change-Id: I10eaaafe38ace2b7bb095a0ad1db70d6c06ee03b
2018-03-05 17:14:32 +01:00
Alexander Couzens
28b8cc6283 jenkins.sh: fix the download url if the qemu image wasn't setup
Download the image from yesterday because linuxcontainers only contains the images of the last 3 days.

Change-Id: I75e270b7255c1cd7fca1674111b0f19fc7bba74f
2018-03-02 08:58:31 +00:00
Alexander Huemer
3f52f0e6c5 Fix USRP1 build with support for setting Rx/TxAntenna
The USRP1 build was broken by commit 77ce99ac67.

Commit 77ce99ac67 broke the USRP1 build

Change-Id: I28585947d5662cdd580a814cce54a5d9aa30eeb8
2018-02-27 22:35:37 +01:00
Pau Espin Pedrol
3da1f8352e Logger: Use libosmocore logging system
We still need an intermediate class Logger due to osmo-trx being
multi-threaded and requiring to have a lock to use libosmocore, which is
not thread safe.

Change-Id: I30baac89f53e927f8699d0586b43cccf88ecd493
2018-02-27 07:11:11 +00:00
Pau Espin Pedrol
5ea1817dc2 Add initial support for logging, vty, ctrl
Up to this point, the logging system, vty and ctrl are initialized and
can be used fine, though they don't have a lot of use yet.

Depends on libosmocore Change-Id Ib79cdb62d45d8c78445c7b064e58eb7e9faeccf9

Related: OS#2184

Change-Id: I08982c37b4f873966304b3cfb38a10ee86eb3dad
2018-02-27 07:10:50 +00:00
Pau Espin Pedrol
49d42e979e debian: Depend on libtalloc and libosmocore
Change-Id: If4bf03d164e9d19a8a21399a2c74b2984c48cc70
2018-02-26 00:56:10 +01:00
Pau Espin Pedrol
3a3b220751 osmo-trx: Set up talloc ctx
Change-Id: I67f1980fc615ab74371cbe1c4f83e987381299bc
2018-02-22 20:04:47 +01:00
Pau Espin Pedrol
ab22f4c421 osmo-trx: set up signals using libosmocore helpers
Change-Id: I86e78cd6054d0deff1b1aa061299d9f307e2a352
2018-02-22 20:04:47 +01:00
Pau Espin Pedrol
8b843e5bed Depend on libosmocore
Change-Id: If345c89293fcd7d1ad4f17214eea339951f25a5d
2018-02-22 20:04:47 +01:00
Pau Espin Pedrol
c92dad32dd configure.ac: Check for pkg-config
Change-Id: I1a851181a99f2f35ea4ff1b38c7afe27a04e5f18
2018-02-20 20:32:27 +01:00
Pau Espin Pedrol
61837c0420 Logger: Remove gLogToConsole flag
No code is using it and we always lock to console anyways.

Change-Id: I5fde99c6af5a845e635b5d27abab855682071f14
2018-02-20 20:32:27 +01:00
Pau Espin Pedrol
f83e11fefd Logger: Remove unused includes
Change-Id: I4d26c0b4f36ee3c66ed1a9e2e9fa2fa8272da16d
2018-02-20 20:32:27 +01:00
Pau Espin Pedrol
01aff88ce9 Logger: Drop support to log into file
This feature is currently not being used, so let's simplify current code
to move to libosmocore logging system in the future.

Change-Id: If2c77c776823f595130edac963be953026049423
2018-02-20 20:32:27 +01:00
Pau Espin Pedrol
11d50d950c Logger: Drop syslog support
This feature is currently not being used, so let's drop it to make it
easier to integrate into libosmocore logging system in the future.

Change-Id: I8282745ef0282d41599eaf94fe460a1d29b18e2a
2018-02-20 20:32:21 +01:00
Pau Espin Pedrol
8bd111c942 Logger: get rid of alarm APIs
It's only used internally inside the Logger module, and in case there's
an "alarm" (level more than critical) we still print on cerr, so we can
just rely on our system catching stderr instead of stdout to handle it.

Change-Id: I6d6df1578c3a4c1a37bd0d69952d443f62eed2ab
2018-02-20 18:26:45 +01:00
Pau Espin Pedrol
3808e479aa Logger: Remove unused logging macros
Change-Id: I1133e181183bec8dabe2fa77d0385f783458503f
2018-02-20 18:14:20 +01:00
Pau Espin Pedrol
bd45a979f8 Logger: Drop unused gLogEarly
Change-Id: I2c8f24fbf453e0a94d7a95c3df7cc75f0e4bd456
2018-02-20 18:14:20 +01:00
Pau Espin Pedrol
b7095c7bc5 UHDDevice: Initialize async_event_thrd in constructor
Fixes coverity CID 182757.
It's actually a false warning because "async_event_thrd" member is
protected by other member "started", so in practice it's never going to
be used before being initialized in start().

Change-Id: I5d5739bc9d08fe533e4d44c3992005a14e568a4f
2018-02-09 16:20:39 +01:00
Pau Espin Pedrol
77ce99ac67 Add support to set Rx/TxAntenna
Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.

In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.

Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.

One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW

Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.

One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW

Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
2018-02-07 13:43:42 +01:00
Pau Espin Pedrol
f58cd8ac83 Fix whitespace
Change-Id: Icda84caa998614ce6c15d5118f8c5c1568ba9a79
2018-02-05 13:04:41 +01:00
Max
99eb07e232 tests: null-terminate buffer
Initialize temporary buffer with 0 to make sure that it's
null-terminated.

Change-Id: Icdde701839e35d3131605ea5a11882af21c8939a
Fixes: CID149362
2018-01-31 11:34:59 +01:00
Pau Espin Pedrol
89be118a3b Remove unneeded libdl dependency
Closes: OS#1929

Change-Id: I0caea2a2a8e6bd07432fd73bae72b42b1ce022cd
2018-01-23 18:15:24 +00:00
Alexander Huemer
6fafd33b13 Unbreak ./configure --with-usrp1 build
Change-Id: I49b385594271ae64a48d4d39ee9fe26d7c95bd30
2018-01-20 23:24:20 +01:00
Pau Espin Pedrol
6e55d51747 tests: convolve: Disable due to difference in output in different archs
Let's disable this test in order to have passing jenkins jobs until we
find a better way to properly test this for different architectures.

Change-Id: I2320309bc8c1c20e2de6ef2e0f17472c68de80cb
2018-01-16 11:33:50 +01:00
Pau Espin Pedrol
6cae1d7b4b contrib/jenkins.sh: Use qemu+proot+debootstrap to run tests with ARM instruction set
The following logic doesn't require root access to run the tests, which
means we can easily run it inside jenkins.

Change-Id: Iba3f4de008662805d8ffc46e1f473e407b088fb8
2018-01-15 18:21:17 +01:00
Pau Espin Pedrol
28ce315a32 tests: TimevalTest: refactor and avoid double comparison
Before this patch, the experession assert(then_secondws==then.seconds())
was failing in x86 architecture (and passing when adding a fprintf to
debug it). Avoid comparing the double values with == as that's usually a
bad idea, since the processor can output slightly different results for
the same operation depending on how it is optimized. Use timespec()
instead to check the invariant. Take the chance to refactor some
variables around to make the test easier to read.

Change-Id: Id4324be8ece86d371b1acb46bbd97856dfed241d
2018-01-15 11:49:10 +01:00
Pau Espin Pedrol
10d76b6863 tests: SocketsTest: Fail test on write fail
Change-Id: Ib6b778a2225339ebd2eaa80b3fca6ee8d8646b23
2018-01-15 10:47:13 +01:00
Pau Espin Pedrol
708b8b44ae tests: SocketsTest: Avoid hang forever if test fails
Change-Id: Ia95e216a2ab6d397ab02c828b70f2b95d1671257
2018-01-15 10:46:42 +01:00
Pau Espin Pedrol
cb0fc9b21a tests: SocketTests: Pick OS-assigned instead of setting one manually
This fixes failures if the port is already being taken by other apps or
if this test is run several times concurrently in the same system.

Change-Id: Iea213375e489a56cf8ed3e47fe814e17c288803e
2018-01-15 10:35:11 +01:00
Pau Espin Pedrol
8639fee504 Remove UDDSocket class
This class is not used anymore in osmo-trx, so we can safely remove it.

Change-Id: I67f90aa3d6a2a5e92292436d10928e0705c8f8ff
2018-01-11 20:17:43 +01:00
Pau Espin Pedrol
ca46896cfe .gitignore: Add missing test related files
Change-Id: I7a82a2c0c97bbfa4877f148c89d121b4c3476176
2018-01-11 20:17:40 +01:00
Pau Espin Pedrol
4a25d6b8f6 arm/convert.c: Add missing convert_init implementation
osmo-trx.cpp calls convert_init, which in case of building using
--with-neon is not implemented and the compiler stops with an error.

Error was introduced in 7e07cf2346.

Related: OS#2720

Change-Id: I9840d374d13b525b97f978ea0c5ed9e8421072a0
2018-01-11 18:45:12 +01:00
Pau Espin Pedrol
79baee3a8f arm/convert.c: Fix compilation error
Commit fe9769833f aiming at cleaning stuff
introduced a compilation error.

Related: OS#2720

Change-Id: I6ce6e5ec3fdb1e3e8818e2cb674470ad54e38afb
2018-01-11 18:45:12 +01:00
Pau Espin Pedrol
c2ba427b52 tests: Migrate convtest util to autotest infrastructure
Change-Id: Ie682abf7e83de436d0f37f9f6e0664cb2f4d0c9e
2018-01-11 18:45:12 +01:00
Pau Espin Pedrol
611212676b Move ARCH_LA to Makefile.common
It will later be used by other directories too (tests/Transceiver52M).

Change-Id: I0ca9b7fc5e1377db971cb7da0b3496ba8d61c716
2018-01-10 12:32:33 +01:00
Pau Espin Pedrol
4ebb289c90 utils/convolvtest: Remove uneeded libosmocore dependency
Change-Id: I1742146c31cadec8ce8afbbdae5777f076b212d4
2018-01-10 11:54:34 +01:00
Pau Espin Pedrol
2f376a3edf tests: Sockets: adapt to have reproducible output and enable autotest
Change-Id: I5414076c6846b849973bcdeb3f2358b28dcb004c
2018-01-10 11:31:22 +01:00
Pau Espin Pedrol
2edbe4d366 Sockets.cpp: Fix initialization of UDD socket
Without this line, destination address for a UDD socket is left with
incorrect value AF_UNSPEC. Later on when calling DatagramSocket:write(),
sendto() fails with EINVAL.

This commit fixes test SocketsTest.cpp.

Change-Id: I6e1b7e743a781abdcf69aa9842b30be893633433
2018-01-10 11:29:16 +01:00
Pau Espin Pedrol
a3694bd303 tests: Log: adapt to have reproducible output and enable autotest
Change-Id: I77c40230503acadef5f64ab2624cd872f9782b98
2018-01-10 11:29:16 +01:00
Pau Espin Pedrol
2652f2bc39 tests: Timeval: adapt to have reproducible output and enable autotest
Change-Id: I1a79892ba3c934879a171789e0edb357277acae4
2018-01-10 11:29:13 +01:00
Pau Espin Pedrol
93d9b114b7 tests: InterThread: adapt to have reproducible output and enable autotest
Change-Id: I05d4067890b526bd72d2eb31cf76de43ee11e80f
2018-01-10 11:25:42 +01:00
Pau Espin Pedrol
2ac788b2c3 Set up GNU Autotest infrastructure
Test files are moved from CommonLibs/ to tests/CommonLibs/.
Some tests are disabled in autotest because they generate timedate
related output which cannot exactly match against expected output.

Change-Id: I3d6ba625968be09297642d18090c496490e9b8fc
2018-01-10 11:17:32 +01:00
Pau Espin Pedrol
d36ef2f57b cosmetic: AUTHORS: fix trailing whitespace
Change-Id: I92d9ad9a0fd69e88928a8f57920d39dcda67d59d
2018-01-10 11:14:31 +01:00
Pau Espin Pedrol
caf2abc58f Remove Configuration module and libsqlite dependency
Change-Id: I823aea91367d586507bbf352f1b6f25bdd635baa
2018-01-09 15:26:50 +01:00
Pau Espin Pedrol
de1685f6d7 Drop use of ConfigurationTable gConfig
After latest changes, it is not being used anymore.

Change-Id: I43a49aee94e3239194ad9742fb6374324acac0de
2018-01-09 15:26:50 +01:00
Pau Espin Pedrol
f3837d26f9 Logger: Stop using Log.File and Log.Level from config
This is a required step towards getting rid of ConfigurationTable class
and libsqlite dependency.

As a side effect, support for different log levels for different files
is dropped, but it's not something really being used and we will end up
dropping current logging system in favour of osmocom's one in the future
anyway.

Change-Id: I51cb12d1ab7e103e78190ac71a70fb5bb1d9ff51
2018-01-09 15:26:49 +01:00
Pau Espin Pedrol
ddf4743306 Logger: Stop using Log.Alarms.Max from config
This is a first step towards removing ConfigurationTable class and
sqlite3 dependency.

Change-Id: Idcd789afe668a5c0271352f1d20d2efda826213a
2018-01-09 15:26:49 +01:00
Pau Espin Pedrol
82f83ced73 cosmetic: Remove trailing whitespace
Change-Id: I64c8dbad3fc42bcb8dd4ac9b16bbd9c59a0cf5d5
2018-01-09 15:26:49 +01:00
Max
cff4ed9b4c Update license notes
* replace references to OpenBTS with OsmoTRX
* drop trademark notice
* drop outdated example

Change-Id: I144f96c507bfe48df350fb0350edbeba87126462
Related: OS#2600
2018-01-05 10:07:08 +00:00
Max
6ec26bb788 Update legal disclaimer
* drop trademark passage
* add link to OpenBTS website and corresponding attribution
* replace OpenBTS references with OsmoTRX

Change-Id: Ia40df831649cdb68898db9ca77868c422a8d631d
Related: OS#2600
2018-01-04 15:17:27 +01:00
Max
a1ff991402 Update installation instructions
* remove references to OpenBTS
* update URLs
* remove unnecessary requirements

Change-Id: I6ec26beaaa74dd3d98f27d110055a8f0cdd3c991
Related: OS#2600
2018-01-04 14:31:54 +01:00
Max
d09843c692 Remove unused headers
Change-Id: Idadb17aeb85b011d114ffc1d81c920544bac1989
2018-01-04 14:31:54 +01:00
Max
e5448ff972 Remove outdated references to OpenBTS
Change-Id: I2df613bf59af28e2f44a520d0ee953932bcf4d7e
2018-01-04 13:41:06 +01:00
Max
e48c1367dc Mark release target as virtual
Change-Id: Iee747faa3171663f1874a5eacddd56607de55297
2018-01-04 13:40:42 +01:00
Piotr Krysik
aa60dda99a UHDDevice.cpp: add USRP B205mini support
The B205mini is similar to the B200mini and runs OsmoTRX just
fine, so let's make OsmoTRX recogonize and support it too.

Change-Id: Iee575121248ea541f7abc49055e49ec2d30904c0
2017-12-04 00:32:33 +07:00
Harald Welte
1468a5c3dc SocketsTest: Fix printing of non-nul-terminated string
Change-Id: I33d0ddf851d84b81ab5252e3755422170cee54ee
Fixes: Coverity CID#149363
2017-11-07 20:32:09 +00:00
Neels Hofmeyr
b0e1bd8c22 jenkins: use osmo-clean-workspace.sh before and after build
See osmo-ci change I2409b2928b4d7ebbd6c005097d4ad7337307dd93 for rationale.

Depends: I2409b2928b4d7ebbd6c005097d4ad7337307dd93
Change-Id: I609f7c7c88b49f26e2e48e1f1cffed76d9e6fb5e
2017-10-31 09:24:58 +00:00
Harald Welte
78e1cd20e2 Tag/Release 0.2.0
This is the first real tagged Osmocom release of OsmoTRX.

  [ Alexander Chemeris ]
  * EDGE: Add support for UmTRX.
  * Common: Get rid of a compilation warning.
  * Common: Make sure gLogEarly() log to the same facilities as the normal log.
  * transceiver: Properly handle MAXDLY.
  * transceiver: Add an option to generate random Access Bursts.
  * osmo-trx: Output Rx SPS as a part of configuration output.
  * transceiver: Do not pass transceiver state struct to function where it's not used.
  * makefile: Fix build from an external path.
  * radioDevice: GSMRATE macro must have parentheses around its definition.
  * uhd: Fix comment.
  * radioInterface: Initialize power scale with a meaningful default.
  * transceiver: Log channel number in DEBUG output of demoded bursts.
  * transceiver: Add an option to emulate a RACH delay in random filler mode.
  * UHD: Initial LimeSDR support.
  * CommonLibs: Remove unused files.
  * sigProcLib: Typo sybols -> symbols
  * radioBuffer: Remove extra ; at the end of inline function definitions.
  * sigProcLib: Fix documentation, sync argument names in .cpp and .h files.
  * sigProcLib: make energyDetect() simpler by returning actual energy.
  * sigProcLib: Rename demodulateBurst() to demodGmskBurst() for clarity.
  * sigProcLib: Slice SoftVector instead of signalVector for GMSK demod.
  * Call vectorSlicer() right before packing bits for transmission to osmo-bts.
  * CommonLibs: Print soft bits with less confidence to console when printing a soft vector.
  * BitVector: Remove convolutional codec - we don't use it in osmo-trx.
  * BitVector: Convert SoftVector from 0..1 to -1..+1 soft bits.
  * signalVector: Implement segment().
  * vector: Introduce segmentMove() method to move data inside of a vector.
  * vector: Introduce shrink() function to shrink vector size without loosing data.
  * Move CorrType type from Transceiver to sigProcLib.
  * sigProcLib: rename signalError type to SignalError.
  * Move Transceiver::detectBurst() to sigProcLib to make it reusable.
  * Move BURST_THRESH from Transceiver.cpp to sigProcLib.h to make it reusable.
  * sigProcLib: Add operator<< to print CorrType to a string.
  * sigProcLib.h: Fix whitespaces. No non-whitespace changes.
  * Move Transceiver::demodulate() to sigProcLib to make it reusable.
  * sigProcLib: constify signalVector arguments for detectBurst() functions.
  * sigProcLib: Constify demodulation functions burst argument.
  * sigProcLib: Fix number of tail bits in random Normal Bursts and zero Stealing Bits.
  * Configuration: Variables allocated with 'new' must be freed with 'delete'.
  * BitVector: Remove Generator class.
  * PRBS: a Pseudo-random binary sequence (PRBS) generator class.

  [ Tom Tsou ]
  * EDGE: Fix USRP B210 device support
  * uhd: Correct timing alignment in 8-PSK and GMSK downlink bursts
  * EDGE: Fix demodulation slicer input
  * common: Restrict UDP binding to localhost only
  * common: Add mandatory length field to UDP receive calls
  * uhd: Update default E3XX settings
  * uhd: Set default Tx sampling to 4 sps
  * uhd: Make device offset check a private method
  * uhd: Set minimum UHD version requirement for E3XX
  * sigproc: Expand RACH, TSC, and EDGE correlation windows
  * transceiver: Do not report error on SETTSC when radio is on
  * transceiver: Add Rx samples-per-symbol option
  * radioInterface: Convert diversity argument to general type
  * iface: Add inner ring-buffer implementation
  * mcbts: Add multi-ARFCN channelizing filters
  * mcbts: Add multi-ARFCN radio support
  * sigproc: Adjust burst detection threshold criteria
  * egprs: Enable 8-PSK length vectors on the Tx interface
  * egprs: Enable 8-PSK burst detection when EDGE is enabled
  * transceiver: Remove HANDOVER warnings
  * mcbts: Allow out of order channel setup
  * radioInterface: Fix multi-channel buffer index bug
  * uhd: Add command line option for GPS reference
  * transceiver: Fix mixed GSMK / 8-PSK transmission
  * transceiver: Fix 4 SPS receive TOA value
  * sigproc: Fix missing 8-PSK tail symbols
  * uhd: Update USRP2/N200/N210 for 4 SPS Rx
  * sigproc: Match differential GMSK start/end bits to tail bits
  * uhd: Add missing B200 sample timing for 4 SPS receive
  * transceiver: Fix command build warning
  * uhd: Set minimum supported version to 3.9.0
  * uhd: Add X300 sample timing for 4 SPS
  * Revert "uhd: Set minimum supported version to 3.9.0"
  * uhd: Add support for UHD-3.11 logging control
  * uhd: Increase MC-BTS FPGA clock rate to 51.2 MHz
  * Resampler: Fix initialization return checking
  * sigProcLib: Remove unreachable code and no-effect checks
  * sigProcLib: Check return status on downsampling
  * sigProcLib: Fix negative value check on unsigned value
  * Resampler: Fix non-array delete for filter taps
  * Transceiver: Remove unsigned negative compares
  * Configuration: Fix const and signedness compile warnings
  * config: Remove OpenBTS style sqlite configuration
  * radioInterface: Remove UmTRX 'diversity' option
  * build: Require and check for gcc C++11 support
  * uhd: Use map container for for device parameter access
  * sigProcLib: Remove unused functions from public interface
  * uhd: Add non-UmTRX channel swap support
  * uhd: Fix Tx-RX timing offset setting
  * uhd: Fix USRP2/N200/N210 device detection
  * transceiver: Fix POWEROFF crash on USRP2/N200/X300 devices
  * sigProcLib: Fix complex/real vector flag in Laurent modulator
  * sigProcLib: Remove heap based signal vector allocations
  * common: Declare explicit Vector move constructor
  * sigProcLib: Remove trigonometric tables
  * sigProcLib: Use explicit NaN check in sinc table generation
  * sigProcLib: Replace dynamically allocated resampling buffers
  * sigProcLib: Specify standard namespace for isnan()
  * uhd: Always specify samples-per-symbol for device lookup
  * LimeSDR: set approximate tx offset value to make GSM work

  [ Neels Hofmeyr ]
  * add basic .gitignore
  * configure.ac: check for boost/config.hpp header
  * The INSTALL file is being overwritten by autoreconf, but it is committed as empty file. As a result, the INSTALL file always shows as modified. Instead, remove INSTALL from git and ignore it.
  * add contrib/jenkins.sh, for gerrit build bot

  [ pierre.baudry ]
  * transceiver: Fix mismatched allocations and deallocations

  [ Holger Hans Peter Freyther ]
  * debian: Require fftw3 header files for osmo-trx

  [ Max ]
  * Add gerrit settings
  * Integrate Debian packaging changes
  * Remove embedded sqlite3
  * Fix building against sqlite3
  * Add autoconf-archive to dependencies
  * debian: remove obsolete dependency
  * deb: remove unused dependency
  * Remove redundant explicit dependency
  * Use release helper from libosmocore

  [ Ruben Undheim ]
  * Do not embed sqlite3 when building

  [ Philipp Maier ]
  * buildenv: Turn off native architecture builds
  * cosmetic: Make parameter lists uniform
  * Add test program to verify convolution implementation
  * ssedetect: Add runtime CPU detection
  * cosmetic: remove code duplication
  * buildenv: Make build CPU invariant
  * buildenv: Split up SSE3 and SSE4.1 code
  * cosmetic: Add info about SSE support

  [ Vadim Yanitskiy ]
  * buildenv: correct the ax_sse macro description
  * buildenv: actually strip unused cpuid functionality
  * buildenv: fix build on systems without SIMD support
  * buildenv: cosmetic changes
  * buildenv: check for __builtin_cpu_supports call support
  * ssedetect: call __builtin_cpu_supports() only if supported

  [ Pau Espin Pedrol ]
  * cosmetic: transciever: Remove trailing whitespaces
  * transceiver: Avoid sending clock indications when trx is not powered on
  * Add -j option to bind to specific address

  [ ignasj ]
  * LimeSDR: Change device detection to work with USB and PCIe versions
  * LimeSDR: change tx window type to TX_WINDOW_FIXED
  * LimeSDR: Fix sample value range

  [ Harald Welte ]
  * Add '-t' command line option to enable SCHED_RR
  * Import git-version-gen and update AC_INIT()

Change-Id: Ibf3be6cc25e9b20d625b1f67972114b7f613f05c
2017-10-28 17:53:25 +02:00
Harald Welte
db9c1b54cb Import git-version-gen and update AC_INIT()
In AC_INIT(), it still stated openbts.  Let's clean this up and use
the same method of version generation that we use in all other osmocom
projects, too.

Change-Id: Ie7ae0585955aebdc3950b1dd8bff0d1fff3be212
2017-10-28 17:51:54 +02:00
Max
099a44abfb Use release helper from libosmocore
See
https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
for details.

Change-Id: Ieb843923d8f534654413be695f2b5f0c87b75520
Related: OS#1861
2017-08-28 12:26:54 +02:00
Pau Espin Pedrol
8c80095017 Add -j option to bind to specific address
Before this patch, the binding of the listening sockets was hardcoded to
a local IP.

Change-Id: I9ba184a1251c823e413a9230943ed263e52142ec
2017-08-16 17:06:54 +02:00
Max
d49a6aa136 Remove redundant explicit dependency
There's no need to explicitly mention library package because
${shlibs:Depends} will take care of it automatically.

Change-Id: Ibd9cfc3673d828122edb85ba9de7ceb77f0299d0
2017-07-20 18:36:11 +00:00
Harald Welte
81486e053c Add '-t' command line option to enable SCHED_RR
SCHED_RR allows us to operate osmo-trx reliable even under exceptionally
high system load, as the realtime scheduler priority will have higher
priority than the other "regular" tasks on the system.

Change-Id: Ia2452b9763960b2be37fbeee9d832554da68a53f
Closes: OS#2344
2017-07-20 18:36:01 +00:00
ignasj
28d8081e25 LimeSDR: Fix sample value range
when "sc16" stream arg is passed to SoapyUHD sample value range is -32768 to 32767

Change-Id: I58b8b6b71648bd9cbc105ddaaa9a7cf0a31b3d47
2017-07-10 11:45:06 +02:00
ignasj
87ed77b937 LimeSDR: change tx window type to TX_WINDOW_FIXED
It seems that TX_WINDOW_USRP1 is for devices that do not support tx
sync to timestamp. LimeSDR supports it. Changing to TX_WINDOW_FIXED
greatly reduces number of "dumping stale buffer" messages

Modified to match current master by Harald Welte.

Change-Id: I8de5b165ccd72a62b0f16655618e24ca740d9637
2017-07-10 09:34:58 +00:00
ignasj
f9d996813d LimeSDR: Change device detection to work with USB and PCIe versions
Modified to match current master by Harald Welte.

Change-Id: Ie43610de0b2196d84caf09717ec8c8ca75ab926d
2017-07-10 09:34:32 +00:00
Max
aa5acc953c deb: remove unused dependency
The libdbd dependency is not used because libsqlite3 is used directly -
adjust debian/control to match.

Change-Id: Id2ab1facad703fa0c1d45084e70d41e73dbad6e7
Related: OS#1929
2017-07-06 08:28:29 +00:00
Pau Espin Pedrol
934da48618 transceiver: Avoid sending clock indications when trx is not powered on
Stop calling writeClockInterface() when receiving commands in Transceiver::driveControl,
otherwise it fools osmo-bts-trx clock skew check because it is always sending a clock
indication with the same fn when it issues any commands during the time in between
CMD POWEROFF and RSP POWERON, because fn is not increased during that period.

Also use mForceClockInterface flag to delay delivery of first IND CLOCK until we start
serving frames, otherwise the first one is sent and only after a long period of time
the next clock indications are sent, when the radio starts to process bursts. That makes
osmo-bts-trx unhappy because it expects to receive an IND CLOCK aprox at least every
400 frames. This way also we send the first IND CLOCK after the RSP POWERON 0 response.

Change-Id: I91b81a4d7627cec39c1814a39ed4be306681b874
2017-07-04 19:15:57 +02:00
Pau Espin Pedrol
7c405a0c1f cosmetic: transciever: Remove trailing whitespaces
Change-Id: Ib3fbe768048b2a34a75ace9688e306720e67019a
2017-07-04 17:23:30 +02:00
Tom Tsou
4cafb0fa15 LimeSDR: set approximate tx offset value to make GSM work
may be fine-tuned in the future

Modified to match current master by Harald Welte.

Change-Id: Ied215ca9e9d9c346c2a654f96785d1b87b075129
2017-06-29 02:26:07 +02:00
Tom Tsou
f611569018 uhd: Always specify samples-per-symbol for device lookup
Fix MCBTS device setup where the map access was failing on the wrong
assumption that all devices support 1-SPS TX-RX operation. Some devices
and/or configurations such as LIMESDR and MCBTS only support running
at 4-SPS.

Even though certain settings (e.g. number of physical channels or the
FPGA clocking rate) are not dependent on the SPS value, we still need to
specify because we use SPS as a parameter for device classification.

Fixes: OS#2341
Change-Id: I56e939285d585cc38efa6c329e30e3acebb734eb
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-27 11:36:34 -07:00
Tom Tsou
354741326c sigProcLib: Specify standard namespace for isnan()
In commit a3dce85f
"sigProcLib: Use explicit NaN check in sinc table generation"

Use of std::isnan(double) was added without namespace specifier,
which may cause build issues depending on whether the C version
isnan() call is available. Add standard namespace to force C++
call usage and potential build issues.

Change-Id: I49328c43fdd690a4e6a2b2e949411aaf5674ead1
2017-06-22 18:03:29 +00:00
Tom Tsou
d2e5c5694e sigProcLib: Replace dynamically allocated resampling buffers
Instead use object allocated STL vectors. This simplifies code,
removes the need to explicitly release buffers, and fixes a
memory leak in destructor deallocation. Also, remove simplified
init and release sub-calls.

Maintain partition filter allocation using memalign() for SIMD
alignment requirements.

Change-Id: Ie836982794c10fb1b6334e40592d44b200454846
2017-06-22 17:39:44 +00:00
Tom Tsou
a3dce85ffc sigProcLib: Use explicit NaN check in sinc table generation
Using "x < 0.01" is a crude check for detecting NaN condition, which
occurs in a sinc call when x = 0 due to divide-by-zero. Use stdlib
isnan() call for this purpose. Also, as the table is created only
once during initialization, use double floats for table value
generation.

Change-Id: I3a838fe3139fa977dfe906246020a14451185714
2017-06-19 17:04:04 +00:00
Tom Tsou
bb0c68ae61 sigProcLib: Remove trigonometric tables
Trigonometric sin/cos tables are unused after initialization.
There is no benefit to implementing lookup tables for run-once
operations. Also perform initial calculations in double width
because there is no penalty for doing so.

Change-Id: I45bba5daf8610cbba6af95b92c2142f2256491ff
2017-06-19 17:03:11 +00:00
Tom Tsou
87d158cc2d common: Declare explicit Vector move constructor
Vector class already has a semantically odd non-const copy
constructor that serves the same function as a C++11 move
constructor. Make the move constructor semantics explicit
and address Coverity at the same time.

Change-Id: I22e0099abe601b0c59beee808f7560837c6977dd
Fixes: Coverity CID 170738
2017-06-19 17:02:41 +00:00
Tom Tsou
7278a87767 sigProcLib: Remove heap based signal vector allocations
The osmo-trx internals rely heavily on dynamic alloction of
I/Q signal vectors. In a number of cases there is no reason
to to use dynamic rather than stack based allocation. Convert
these cases accordingly.

Change-Id: If53da1bf77b5944b6117765fa98ce12e1ccdeede
2017-06-16 17:11:27 +00:00
Tom Tsou
63eef9faf2 sigProcLib: Fix complex/real vector flag in Laurent modulator
The modulator vector to be shaped by Laurent C1 pulse is complex,
but was set as real. The error does not affect behaviour because
we only support complex-complex and complex-real calculations;
real-real convolution is not supported. So in this case the data
vector was already assumed to be complex despite the improper
flag setting.

Change-Id: I03afc6a93a01fde7a9a02e4eb9d201d3ee37d21a
2017-06-16 17:09:09 +00:00
Tom Tsou
d67bd603e9 transceiver: Fix POWEROFF crash on USRP2/N200/X300 devices
Upon issuing POWEROFF command to a running transceiver, UHD
interfacing thread state may become undefined if the device
is stopped with I/O threads still active. Bad behavior is
device dependent with only network based USRP devices
affected. USB based device thread behavior stops and shutdowns
as expected. Tested with N200, X300, and B210.

Tested solutions include the following:

  1. Set pthread_setcanceltype() with PTHREAD_CANCEL_ASYNCHRONOUS
  2. Add sleep delay to allow I/O threads to timeout before
     stopping the device
  3. Wait for I/O threads to join after cancellation before stopping
     the device

This patch resolves the issue by with the third approach. Number 1
is not guaranteed to always work with UHD internals as driver code
may explicitly set thread parameters. Using sleep calls to fix
order-of-operation issues is almost never a good idea.

Change-Id: Ib72ab98a27a02084b040319046c92d1c4157ae4c
2017-06-16 17:03:30 +00:00
Tom Tsou
988a464d5d uhd: Fix USRP2/N200/N210 device detection
Commit 1fb0ce67 "uhd: Use map container for for device parameter access"
inadvertently removed the string identifier for the USRP2 and derived
devices (N200/N210).

Add the missing USRP2 string identifier. Also search for partial string
matches in the UHD provided device and mboard stings. This is necessary
to guarantee that strings such as "N200r3" instead of just "N200" are
sucessfully found.

Tested with N200, X310, B200mini and B210 devices.

Change-Id: Ide4e22418e2cc469418cba018970cb0eb9906697
2017-06-16 17:02:27 +00:00
Tom Tsou
1b6ab7d7ee uhd: Fix Tx-RX timing offset setting
Integer timestamp offset was set to zero due to bad cast-operator
precedence.

Change-Id: Ib1f524cc86416699b3c143e5faddb33d61380767
2017-06-15 16:22:44 -07:00
Tom Tsou
980525c8a9 uhd: Add non-UmTRX channel swap support
Previously an UmTRX-only feature.

Change-Id: I4a0e0c1d69e89993158e948535ad33f54e568d2d
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-14 16:34:46 +00:00
Tom Tsou
70134a01eb sigProcLib: Remove unused functions from public interface
Also remove entirely completely unused calls. Most of these
calls have been around since OpenBTS conception. Nearly a
decade is long enough time for deprecation.

Change-Id: Ifc122aaff23414c363b4b00f99061eed8a6902d0
2017-06-14 16:30:28 +00:00
Tom Tsou
1fb0ce67d8 uhd: Use map container for for device parameter access
OsmoTRX is written in C++ so we might as well use built-in
container types when applicable. Map access allows removal
of significant amounts of special device handling code.

Aggregate device rates and timing offsets into a single
table with access keyed by device/tx-sps/rx-sps tuples.

Change-Id: I8660f75a2b2a13488b913c07637bdd0f5f0f4cf9
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-12 13:47:14 -07:00
Tom Tsou
8ca237b5c2 build: Require and check for gcc C++11 support
It is now 2017. We can and should be able to use C++11 features now.

Change-Id: I96477e4125390b17b43a3705bb1daf98fa01c9bb
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-09 11:19:20 -07:00
Alexander Chemeris
082bbbf8fe PRBS: a Pseudo-random binary sequence (PRBS) generator class.
Implemeted with a Galois LFSR for speed and flexibility compared to Fibonacci version.

Aliases for three popular PRBS' are added for convenience - PRBS9, PRBS15 and PRBS64.

Note that we can't test PRBS64 completely, because the sequence is too long to
be generated.

Change-Id: Ib5331ba5d0b5819929541686fdd87905e2177b74
2017-06-08 18:33:47 +00:00
Vadim Yanitskiy
3bd763d2a1 ssedetect: call __builtin_cpu_supports() only if supported
Some compilers don't support the __builtin_cpu_supports built-in,
so let's make them able to compile the project anyway.

Change-Id: I0c90402d8e4c9f196c54b066ff30891c8de3ad2b
2017-06-08 18:32:29 +00:00
Vadim Yanitskiy
ee57357682 buildenv: check for __builtin_cpu_supports call support
The '__builtin_cpu_supports' is a GCC's built-in function which
returns a positive integer if the run-time CPU supports specified
SIMD feature and returns 0 otherwise.

This change adds a new check, whether compiler supports this call.
See /gcc/X86-Built-in-Functions.html at gcc.gnu.org for reference.

Change-Id: I797f638573e8c3aae39c28abb157ce2ac419f3f7
2017-06-08 18:32:29 +00:00
Vadim Yanitskiy
8537b90dbe buildenv: cosmetic changes
Change-Id: I9c52f2981513fa6322bdf992215e3e099ac3ddee
2017-06-08 18:32:29 +00:00
Vadim Yanitskiy
038fd7fd70 buildenv: fix build on systems without SIMD support
HAVE_SSE3 and HAVE_SSE4_1 were never defined if CPU architecture
doesn't match the (86*|x86_64*|amd64*) condition.

Change-Id: I3350b14dbc91e9b388d0b04a0ed22ba27d436313
2017-06-08 18:32:29 +00:00
Vadim Yanitskiy
0cd246c27a buildenv: actually strip unused cpuid functionality
Despite the macro message says, that cpuid functionality was stripped
it was still partially preset and wasn't used anyhow.

Change-Id: I380bc9c13d29319685781ef27973afe6744fcf3d
2017-06-08 18:32:29 +00:00
Vadim Yanitskiy
61fbf2ec95 buildenv: correct the ax_sse macro description
Change-Id: I4ce65443c8a33ae9add8f6da9d911c3178472ab2
2017-06-08 18:32:29 +00:00
Alexander Chemeris
15f9d95f5f BitVector: Remove Generator class.
It is not used in osmo-trx, because we're not doing FEC or CRC checks.

Change-Id: I1509e785c1187ebdafe5b2518bd298fbbd1cd036
2017-05-30 20:12:58 +00:00
Alexander Chemeris
73dbccda78 Configuration: Variables allocated with 'new' must be freed with 'delete'.
Thank you Valgrind.

Change-Id: I8477e4e37282947f9841cee9002565631ca0c0b6
2017-05-30 19:19:19 +00:00
Alexander Chemeris
5e65b531e0 sigProcLib: Fix number of tail bits in random Normal Bursts and zero Stealing Bits.
This bug only affects generation of normal bursts filled with random bits which
are used in test mode. It doesn't affect operation of osmo-trx during normal
operation. That's why it has stayed unnoticed for so long.

Each Normal Burst has 3 tail bits, not 4.
Also it's better to set stealing bits to 0 for maximum compatibility. We may want to
introduce a selector for each bit whether to set it to 0, to 1 or to a random number.

Change-Id: I0377029556c8b681b3ba3b635bf19572b34546ea
2017-05-29 15:15:36 +03:00
Max
b992d0a515 debian: remove obsolete dependency
This should fix package build for Ubuntu 17.04: obsolete package
hardening-wrapper was removed which cause .deb build failure.
The dependency on it is incorrect to begin with because we use
DEB_BUILD_MAINT_OPTIONS instead.

Change-Id: I3ea72b4123a280a846086d083c4f3189d611f8cf
2017-05-19 17:26:31 +00:00
Tom Tsou
d6ae8648ff radioInterface: Remove UmTRX 'diversity' option
The 'diversity' option was an experimental 2 antenna receiver
implementation for UmTRX. The implementation has not been
maintained and current working status is unknown.

In addition to code rot, Coverity is triggering errors in the
associated code sections.

Removal of code cleans up many cases of special handling that
were necessary to accommodate the implementation.

Change-Id: I46752ccf5dbcffbec806081dec03e69a0fbdcdb7
2017-05-19 17:25:44 +00:00
Philipp Maier
e51a8f029e cosmetic: Add info about SSE support
The osmo-trx binary outputs no info about its SSE support status.
This commits adds some putput that informs about the SSE of the
binary and also tells which of the SSE levels the CPU supports.

Change-Id: Iacc83fd668c31644e0efb3e18962cf2870ed1daf
2017-05-19 17:23:20 +00:00
Philipp Maier
e8ae9fcf38 buildenv: Split up SSE3 and SSE4.1 code
Currently we find SSE3 and SSE4.1 code mixed togehter along with
generic code in one file. This introduces the risk that the
compiler exidantly mixes SSE4.1 instructions into an SSE3, or
even worse into a generic code path.

This commit splits the SSE3 and SSE4.1 code into separate files
and compiles them with the matching target options.

Change-Id: I846e190e92f1258cd412d1b2d79b539e204e04b3
2017-05-19 17:21:45 +00:00
Philipp Maier
f5bf33b287 buildenv: Make build CPU invariant
Currently the build environment checks which extension the current
CPU supports and picks the compiler flags accordingly.

If the build is happening on a machine that does not support the
extensions we need (SSE3, SSE4.1), the binary will lack those
extensions, even if its intended to be used on a more powerful
machine that would support the extensions.

This commit removes the CPU tests from the build process.

Change-Id: Ic913aa13c23c348ae62e78c9dfd6ed8b0a62798c
2017-05-19 17:19:39 +00:00
Philipp Maier
fe9769833f cosmetic: remove code duplication
The ARM and the X86 implementation of the conversion functions share
the same, non cpu specific implementation in separate files.

This commit removes the code duplication by putting the generic
implementation into a convert_base.c, similar to to convolve_base.c

Change-Id: Ic8d8534a343e27cde79ddc85be4998ebd0cb6e5c
2017-05-19 17:16:37 +00:00
Philipp Maier
7e07cf2346 ssedetect: Add runtime CPU detection
The current implementation can select the SSE support level during
compiletime only.

This commit adds functionality to automatically detect and switch
the SSE support level and automatically switch the Implementation
if the CPU does not support the required SSE level.

Change-Id: Iba74f8a6e4e921ff31e4bd9f0c7c881fe547423a
2017-05-19 17:12:45 +00:00
Philipp Maier
dfe0aef184 Add test program to verify convolution implementation
Convolution is a complex process and we should be able to verify
if computing results change when the implementation is touched.

This commit adds a test program that executes some testcases.
The testcases are crafted in a way that every implmentation
(several different ones for SSE) is executed once. The output
can be compared against the included .ok file.

Change-Id: Ic702ecb356c652fbcd76bee689717fb5d3526fe9
2017-05-19 16:57:25 +00:00
Philipp Maier
131f82bfac cosmetic: Make parameter lists uniform
The non-sse implementation and the sse implementation of the convert
and convolve functions have different parameter lists. This makes it
difficult to use function pointers in order to select the right
function depending on the SSE-Level and CPU.

This commit uniformizes the parameter lists in preparation for
planned runtime cpu detection support

Change-Id: Ice063b89791537c4b591751f12f5ef5c413a2d27
2017-05-02 17:17:57 +00:00
Philipp Maier
78b5627fa1 buildenv: Turn off native architecture builds
The compiler option -march=native instructs the compiler to auto-optimize
the code for the current build architecture. This is fine for building
and using locally, but contraproductive when generating binary packages.

This commit replaces -march=native with $(SIMD_FLAGS), which contains a
collection of supported SIMD options, so we won't loose the SSE support.

Change-Id: I3df4b8db9692016115edbe2247beeec090715687
2017-05-02 10:21:25 +00:00
Tom Tsou
de116e90c0 config: Remove OpenBTS style sqlite configuration
OpenBTS relies on reading in configuration values from the OpenBTS.config
sqlite3 database. This configuration method is not maintained and not
recommended for Osmocom or OpenBTS use. Command line setup is the
recommended approach.

Note that when the osmo-trx logging mechanism is replaced, the sqlite
dependency will be removed.

Change-Id: I95d7b771fde976818bee76f89163e72c3a44ecdd
2017-04-10 06:54:40 +00:00
Tom Tsou
15da7e1f7e Configuration: Fix const and signedness compile warnings
Change-Id: I701559814b2aee6f84f10e612f128da40f6a51c1
2017-04-03 18:55:02 -07:00
Tom Tsou
6031734f44 Transceiver: Remove unsigned negative compares
Change-Id: I49f30699786c52736ef334dae61f7bbd65d878d5
Fixes: Coverity CID 149353, 149356
2017-04-03 18:06:48 +00:00
Tom Tsou
5d2a36a113 Resampler: Fix non-array delete for filter taps
Change-Id: I59cdb01809da5940c74aaae9d17f413aefbf04b2
Fixes: Coverity CID 149349
2017-04-03 18:06:48 +00:00
Tom Tsou
2af14407a8 sigProcLib: Fix negative value check on unsigned value
Convert negative value check on unsigned value to zero check
to avoid potential divide-by-zero error condition.

Change-Id: Ib0d7d1bceb5fe66e69345db93a74e3e0773a2257
Fixes: Coverity CID 165059
2017-03-31 21:43:31 +00:00
Tom Tsou
92bdfb86ac sigProcLib: Check return status on downsampling
Improper length values will cause the polyphase resampler
rotation to fail. Check return and return NULL on error.

Change-Id: I3ad22f9fd7a20754f589c04258dcca3770474a9b
Fixes: Coverity CID 165235
2017-03-31 21:41:04 +00:00
Tom Tsou
ae91f13ecb sigProcLib: Remove unreachable code and no-effect checks
Unreachable path and negative value inspection on unsigned
types.

Change-Id: If53b4b03550b0a7656c808cfe96806252153eb2f
Fixes: Coverity CID 165239, 165238, 165236
2017-03-31 21:41:03 +00:00
Tom Tsou
9d53ecf666 Resampler: Fix initialization return checking
Greater-than comparison was used on boolean type.

Change-Id: Ia3b71b3a06b34a6fd781bf197ecf9d5cc1711d13
2017-03-31 21:40:23 +00:00
Alexander Chemeris
e0c12189d4 sigProcLib: Constify demodulation functions burst argument.
demodCommon() used to scale input vector in place which changed original data.
That's a bad practice and is not really necessary, so I've changed the code to
scale burst after it's copied to a new vector during a delay operation.

Change-Id: Ic45f71b634e48808356d68925bb9f5783e0bf0d3
2017-03-28 14:24:22 +00:00
Alexander Chemeris
1470fcdb5a sigProcLib: constify signalVector arguments for detectBurst() functions.
Change-Id: Ic033371a387353eb12b1827a0eb16c00c07da88a
2017-03-28 14:24:07 +00:00
Alexander Chemeris
6e1dffd486 Move Transceiver::demodulate() to sigProcLib to make it reusable.
Change-Id: I2cad47160e53f65612bd1da8998c83a0a22bce9b
2017-03-28 14:23:56 +00:00
Alexander Chemeris
0229d22d2e sigProcLib.h: Fix whitespaces. No non-whitespace changes.
The file seem to be using "2 spaces" indent, bt some lines are using
tabs which breaks formatting.

Change-Id: I7718cca45c245c9e91250ab2877f5436d4029698
2017-03-28 14:23:44 +00:00
Alexander Chemeris
f7717acd0c sigProcLib: Add operator<< to print CorrType to a string.
Change-Id: I3d68cbdab8fb504d7f155029654a576d318a201e
2017-03-28 14:23:35 +00:00
Alexander Chemeris
b34e60c105 Move BURST_THRESH from Transceiver.cpp to sigProcLib.h to make it reusable.
Change-Id: I5a888890e26858c0fbb2ddb7ef23cb0fd66a64b4
2017-03-28 14:22:01 +00:00
Alexander Chemeris
4e6c938024 Move Transceiver::detectBurst() to sigProcLib to make it reusable.
Change-Id: I3cbe8e6e4f39dde02c945e6c9086c040e276845c
2017-03-24 14:59:24 -07:00
Alexander Chemeris
4aa548f0c2 sigProcLib: rename signalError type to SignalError.
Change-Id: I1a5ae6e87d4c69945053fdefec185d0fb1a26399
2017-03-24 19:54:04 +00:00
Alexander Chemeris
f9e78beea5 Move CorrType type from Transceiver to sigProcLib.
Required to move Transceiver::detectBurst to sigProcLib.

Change-Id: I3e0e74a98bbca4d19657f50a5fb447f078663c9b
2017-03-24 19:54:04 +00:00
Alexander Chemeris
f0189c47be vector: Introduce shrink() function to shrink vector size without loosing data.
Change-Id: I9c0ac2715aea1a90c9e6ebcd982522b80a547099
2017-03-24 01:25:06 +00:00
Alexander Chemeris
c708816be1 vector: Introduce segmentMove() method to move data inside of a vector.
Change-Id: I2f3f4267b4137a0bc031f27e0f896fba9b9f3433
2017-03-24 01:24:23 +00:00
Alexander Chemeris
e56bf3a0e5 signalVector: Implement segment().
Change-Id: I6fe3aae53fb2fa5bb7637e976de6059eabe08202
2017-03-24 01:22:40 +00:00
Alexander Chemeris
38b69871ae BitVector: Convert SoftVector from 0..1 to -1..+1 soft bits.
This makes code simpler and will allow us send -127..127 soft bits towards
osmo-bts instead of 0..255 bits.

Change-Id: I16ecc3d4c829dcf0f619ad995bc9d4a4ed8af0a4
2017-03-22 18:31:22 +00:00
Alexander Chemeris
7db522b6d9 BitVector: Remove convolutional codec - we don't use it in osmo-trx.
Now we have more fexibility in how we represent SoftVector, since we
no longer depend on the particular convolutional codec implementation.

Change-Id: I3006b6a26c5eff59dbe9c034f689961802f1d0d0
2017-03-22 18:31:17 +00:00
Alexander Chemeris
ae09b04e26 CommonLibs: Print soft bits with less confidence to console when printing a soft vector.
We use other symbols to show that these bits has less confidence:
o and . for 0 with less confidence
| and ' for 1 with less confidence

Change-Id: I747a17568ee48f1f3163e8dfab2e450af85e6435
2017-03-22 18:31:12 +00:00
Alexander Chemeris
b61c610cd9 Call vectorSlicer() right before packing bits for transmission to osmo-bts.
vectorSlicer() converts soft-bits from -1..+1 to 0..1 while we want
to keep SoftVector in -1..+1 mode until the last minute, because at some
point we'll want to transmit -1..+1 to osmo-bts instead of converting it
from 0..1 back to -1..+1 on the osmo-bts side.

Plus it removes code duplication - we call it once instead of twice.

Change-Id: Idd6ddd7ac219afb0df055a692632678b66373764
2017-03-22 18:31:07 +00:00
Alexander Chemeris
132fb247b1 sigProcLib: Slice SoftVector instead of signalVector for GMSK demod.
This makes it similar to 8-PSK demod and also saves a bit of lines ofcode and
should give us a tiny improvement in performance.

Ideally we need to remove vector slicing at all, because in osmo-bts-trx
we convert back to +-1.0 again (actually to +-127, but it doesn't mater).
So we should rather transmit +-1.0 values to avoid double conversion.

Change-Id: If9ed6f0f80fbe88c994b2f9c3cae91d0d57f4442
2017-03-22 18:31:03 +00:00
Alexander Chemeris
1c0b8b355c sigProcLib: Rename demodulateBurst() to demodGmskBurst() for clarity.
Change-Id: Ibcef8d7d4a2c06865bed7e4091ccc8dbbd494d77
2017-03-22 18:30:53 +00:00
Alexander Chemeris
1dd05cf35a sigProcLib: make energyDetect() simpler by returning actual energy.
Change-Id: I9bf97f2dc03fea9bebcf43198dfb05f6e4694e9c
2017-03-22 18:09:00 +00:00
Alexander Chemeris
14d13b67dc sigProcLib: Fix documentation, sync argument names in .cpp and .h files.
Documentation in sigProcLib.h was noticeably out of sync with the actual
implementation - e.g. not all arguments were documented and arguments
which are already removed are still in the documentation. Also argument
names were different between declaration in .h and implementation in .cpp
which was confusing.

I've fixed this for detect*Burst() functions.

Change-Id: I4dfd07125d9a1e9a42a78b79faff539f003deb16
2017-03-20 18:42:32 +00:00
Alexander Chemeris
89bca9b2de radioBuffer: Remove extra ; at the end of inline function definitions.
Change-Id: I8911adf0a0bb1ae828ac9cdf1a76c904639f6c06
2017-03-20 18:41:02 +00:00
Alexander Chemeris
9270a5aa2e sigProcLib: Typo sybols -> symbols
Change-Id: I8cbef852374d0458c4f4ad4be0df0aa998e3796a
2017-03-20 17:36:06 +00:00
Alexander Chemeris
4793f4679b CommonLibs: Remove unused files.
Change-Id: I2bfb45a1c7d01785bdb30204dba38c683a4288a9
2017-03-20 17:32:04 +00:00
Max
802b86502d Add autoconf-archive to dependencies
We use AX_EXT in ./configure for checking CPU features anyway, so it's
better to add it as explicit dependency.

Related: OS#1923
Change-Id: I7ba48e1df4ede8b477574da3faa15fd02e15c69b
2017-03-14 18:49:55 +01:00
Tom Tsou
a93f789e50 uhd: Increase MC-BTS FPGA clock rate to 51.2 MHz
Addresses following issues where UHD 3.9 and likely other UHD versions
would report a master clock (FPGA) rate error. Update MC-BTS FPGA clock
for B200 and B210 to 51.2 MHz, which is supported by all UHD versions.
Only B200/B210 is supported for MC-BTS operation.

https://osmocom.org/issues/1963
https://osmocom.org/issues/1648

ALERT UHDDevice.cpp:548:set_master_clk: Failed to set master clock rate
ALERT UHDDevice.cpp:549:set_master_clk: Requested clock rate 3.2e+06
ALERT UHDDevice.cpp:550:set_master_clk: Actual clock rate 5e+06

Change-Id: I78fb2c0959abd0e666628ba39f433162aafb067e
2017-03-07 17:54:06 -08:00
Tom Tsou
72bf762b42 uhd: Add support for UHD-3.11 logging control
The logging API changes in UHD-3.11, which causes build failure if
not properly handled.

Change-Id: I223ebb9fae3f4061e0cb37c05263c1b569e8f628
2017-03-07 14:25:05 -08:00
Max
2dee3e996e Fix building against sqlite3
* Explicitly check for sqlite3 at configure stage, remove old include
  dir, fix header inclusion.
* Use configure results for linking instead of hardcoded linker option
  for sqlite.
* Add dependency on -dev package for .deb

Change-Id: I6d7f697d67651f02ceb77fc4da4317b64fa47f9e
Fixes: OS#1928
2017-01-26 17:06:06 +01:00
Max
1f1cebb2e5 Remove embedded sqlite3
Previous patch switches to using system-wide sqlite3 so it's safe to
remove local copy now.

Change-Id: Ie8e751cc62132fe1f7748ccd78c5d48469027329
2017-01-24 15:15:30 +01:00
Ruben Undheim
d1b28bd766 Do not embed sqlite3 when building
Change-Id: If5edadc04c3ff953b451676e55ad3d00d4e43c82
2017-01-24 15:15:24 +01:00
Max
833e97e9ba Integrate Debian packaging changes
debian/control:
    * restructure to make it easier to incorporate further changes
    * update package descriptions
    * update project URL

debian/rules:
    * use proper hardening syntax

debian/copyright: update to match Debian format

Change-Id: I9a89e7311c8632ae26ac2e6c02d1e427d94b1608
Related: OS#1694
2017-01-24 15:14:32 +01:00
Max
e6d059f0c9 Add gerrit settings
Make it simple to setup and use this repo with 'git review' command.

Change-Id: I6bbe65cc09e086685995f084a07a646a7d60b93c
2017-01-24 15:03:48 +01:00
Holger Hans Peter Freyther
012a1b345b debian: Require fftw3 header files for osmo-trx
Install missing development package to get osmo-trx to build.

Change-Id: Id80937724d5e4da4ed555cbabfcd3e2457cb2a19
2017-01-24 14:47:10 +01:00
Tom Tsou
80cb08071b Revert "uhd: Set minimum supported version to 3.9.0"
This reverts commit 93ca09ea61.

Ettus Research recommends the use of 3.9 series of UHD releases,
but requiring this version has lead to issues with broken OBS and
packaged binaries by Debian, Ubuntu, and other distributions.

Change-Id: Ie6b175ac6d46d091937380c79fdd0125b16ec75f
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-01-19 13:48:15 -08:00
Tom Tsou
44c7f41d75 uhd: Add X300 sample timing for 4 SPS
Previously only 4/1 and 1/1 configurations Tx/Tx samples-per-symbol
were supported.

Change-Id: I9153171fe3af95e1cb0d9d35a9287dfde155d184
2017-01-11 13:30:42 -08:00
pierre.baudry
9436fbbf3c transceiver: Fix mismatched allocations and deallocations
The behaviour of a mismatched pair of allocation and deallocation is undefined
Also fixes a memory leak if malloc fails (which stops the application anyway)

Change-Id: I9c8bbade8531e8c9c02dcd43bac38cb954b3c89f
2016-10-26 08:54:13 +02:00
Tom Tsou
93ca09ea61 uhd: Set minimum supported version to 3.9.0
Versions of UHD prior to 3.9.0 are no longer supported.

Rather then backport and ifdef UHD version specific API and
behavioral changes, set minimum support to the current LTS
release, which is 3.9.0.

Change-Id: Id7d15b52cd4e45f1d856a6ef3a84832a28f2dd04
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-10-25 18:48:52 +00:00
Tom Tsou
365bc38bee transceiver: Fix command build warning
Place conditional brackets on handover table reset. Reset table
only on successful start or restart.

Change-Id: I74032b49785bd68835a0a68cb0f14cdaab4fcd26
2016-10-25 18:48:25 +00:00
Tom Tsou
43242efc85 uhd: Add missing B200 sample timing for 4 SPS receive
Only B210 timing was previously set in the timing table.

Change-Id: Idc8d1be8201ad086c57dd9b3d6d72d277306cd2b
2016-10-18 11:30:09 -07:00
Neels Hofmeyr
76b98cf236 add contrib/jenkins.sh, for gerrit build bot
Change-Id: If8887525b0062090e9445a35e32b03e3b8e7eede
2016-10-17 17:53:26 +02:00
Tom Tsou
aa15d62a8c sigproc: Match differential GMSK start/end bits to tail bits
Invert the initial and trailing diffential bits in the 4 sps
GMSK modulator to fix power-time mask irregularity at start
and end of burst. GSM tail bits are always zero, so we can
safely use fixed bit values.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-08-11 14:44:57 -07:00
Neels Hofmeyr
2e5e2c537b The INSTALL file is being overwritten by autoreconf, but it is committed
as empty file. As a result, the INSTALL file always shows as modified.
Instead, remove INSTALL from git and ignore it.
2016-08-08 11:55:41 -07:00
Tom Tsou
8f0ccf618d uhd: Update USRP2/N200/N210 for 4 SPS Rx
Requires changing the radioInterface API to pass in Rx side SPS
value. Update the (deprecated) diversity configuration to match
as well.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-20 16:36:27 -07:00
Tom Tsou
06676ead63 sigproc: Fix missing 8-PSK tail symbols
Agilent E4406A measurement of TSC synchronized RF envelope measurement.
showed failing power levels at the tail end of EDGE bursts. Regression
traced back to following commit.

Commit d2b070369d
"uhd: Correct timing alignment in 8-PSK and GMSK downlink bursts"

In the patch, the EDGE burst was delayed one symbol, but erroneously
truncated at the tail end causing the failing RF envelope measurement.

The missing tail symbol did not appear to affect end-to-end EGPRS tests.
This patch corrects the truncation.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-19 12:56:24 -07:00
Tom Tsou
4609f3285c transceiver: Fix 4 SPS receive TOA value
The time-of-arrival (TOA) value out of sigProc is specified
in symbols or, equivalently, 1 sample per symbol and does
not need to be normalized.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-19 11:30:49 -07:00
Tom Tsou
7c741ec6a6 transceiver: Fix mixed GSMK / 8-PSK transmission
Input burst construction was declared static causing the first
downlink burst from upstream to determine subsequent burst size
and modulation. Consequently, fixed sequence EGPRS tests would
pass, however, switching between 8-PSK and GMSK bursts would
fail with only one modulation type being transmitted.

Internally generated test sequences '-r' option were not affected
because the bursts are not received through the socket interface.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-19 11:26:05 -07:00
Tom Tsou
2f3e60bc1f uhd: Add command line option for GPS reference
Unlike earlier versions of UHD, the current release (3.9.2)
does not automatically select on-board GPSDO as the reference
source. Modify the command line settings to allow explicit
selection of GPS in addition to the external setting.

Simultaneous GPS and external reference settingis disallowed.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-17 19:34:22 -07:00
Alexander Chemeris
cbfef6e40a UHD: Initial LimeSDR support.
Only EDGE mode is currently supported. Traditional 1 SPS Rx / 4 SPS Tx
mode requires different sampling rates which is not currently working.

RF performance is also sub-optimal and requires more tuning.
2016-07-12 16:26:51 -07:00
Tom Tsou
b577ef014f radioInterface: Fix multi-channel buffer index bug
Discrete RF multi-channel was using hard coded buffer index
on the channel iteration for transmit sample conversion. End
result was segmentation fault on dual RF channel devices with
both channels active (Ettus B210 and UmTRX).

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-12 16:11:13 -07:00
Tom Tsou
c37594f3b9 mcbts: Allow out of order channel setup
Previous checks on multi-channel TSC and ARFCN settings would fail
if channels were initialized out of order. Namely, if channel 0
was not configured first, osmo-trx would error on the control
interface leading osmo-bts to fail.

Allow global TSC setting on all channels with added logging notice.
Notify if channel frequency is unexpected - which may happen if
channels are setup out of order - but do no report as error.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-08 14:46:25 -07:00
Tom Tsou
ffee30d190 transceiver: Remove HANDOVER warnings
These warnings simply echo the socket command arguments with no
indication of any unexpected or improper operation.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-07 19:39:18 -07:00
Neels Hofmeyr
24575a6530 configure.ac: check for boost/config.hpp header 2016-07-05 15:43:19 -07:00
Neels Hofmeyr
1e9801411b add basic .gitignore 2016-07-05 15:42:35 -07:00
Tom Tsou
64464e6c34 egprs: Enable 8-PSK burst detection when EDGE is enabled
The command line EDGE option will enable 8-PSK burst
detection on any slot where a normal burst is expected.
The burst search order is 8-PSK first followed by GMSK.

EDGE will force 4 SPS sampling on Tx and Rx. Along with
twice the search correlation from 8-PSK and GMSK, EDGE
will increase CPU utilization. Whether the increase is
notable or not is dependent on the particular machine.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:50:02 -07:00
Tom Tsou
e88710881b egprs: Enable 8-PSK length vectors on the Tx interface
Allow EGPRS 8-PSK length bit vectors of length 444 (148 * 3)
to pass in through the Tx socket interface. Length is the sole
factor in determining whether to modulate a bit vector using
GMSK or 8-PSK.

Tested with 8-PSK training sequences with random payload
originating from osmo-bts. Output verified with Agilent E4406A.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:16:03 -07:00
Tom Tsou
a84e162672 sigproc: Adjust burst detection threshold criteria
Reduce the burst detection threshold to pass more bursts to upper
layers, but force stricter requirements on the computation itself.
For the latter, we now require at least 5 samples (rather than 2)
to compute a peak-to-average value.

End result is increased burst detection at low SNR conditions with
a small increase in false positive bursts when no signal is present.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:14:29 -07:00
Tom Tsou
7676427816 mcbts: Add multi-ARFCN radio support
Add new radio interface "radioInterfaceMulti" for multi-carrier
support.

Only USRP B200/B210 devices are supported because of sample
rate requirements (3.2 Msps).

Only 4 SPS operation Tx/RX is supported.

8-PSK is supported.

Other options may be added at a later time

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:14:15 -07:00
Tom Tsou
35222296fe mcbts: Add multi-ARFCN channelizing filters
Introduce polyphase channelizer (Rx) and synthesis (Tx) filterbanks,
which serve as the signal processing backend for multi-carrier GSM.

Fast Fourier Transform (FFT) is used internally. FFTW is added as
a new build dependency.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:07:27 -07:00
Tom Tsou
28670fb5da iface: Add inner ring-buffer implementation
Two buffers, inner and outer, are used in the transceiver
implementation. The outer buffer interfaces with the device receive
interface to guarantee timestamp aligned and contiguously allocated
sample buffers. The inner buffer absorbs vector size differences between
GSM bursts (156 or 157 samples) and the resampler interface (typically
fixed multiples of 65).

Reimplement the inner buffer with a ring buffer that allows fixed size
segments on the outer (resampler) portion and variable lengths (GSM
side) on the inner side. Compared to the previous stack-like version,
this implementation removes unnecessary copying of buffer contents.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:03:11 -07:00
Tom Tsou
05c6feb71d radioInterface: Convert diversity argument to general type
Rather than a simple bool type, convert the diversity switch
to the device interface specifer:

  enum InterfaceType {
    NORMAL,
    RESAMP_64M,
    RESAMP_100M,
    DIVERSITY,
  };

The more general specifier allows passing in special cases
other then selection diversity such as multi-ARFCN support.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:03:03 -07:00
Tom Tsou
2e4ed10722 transceiver: Add Rx samples-per-symbol option
Previous approach was to enable 4 SPS on the receive path only
for EDGE use, which is not a requirement for 4 SPS operation.
Make the 4 SPS configuration setting directly settable.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-07-01 03:02:56 -07:00
Tom Tsou
c8c4eac55e transceiver: Do not report error on SETTSC when radio is on
OsmoTRX does not support the use of multiple TSC settings per
internal TRX instance. There should not be an error to modifiy
the TSC value after POWERON. Setting TSC value on TRX channels
other then 0 is a NOP operation that should only error if the
requested TSC differs from that of TRX channel 0.

Reported-by: Max <msuraev@sysmocom.de>
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-28 17:08:34 -07:00
Alexander Chemeris
37c52c79cf transceiver: Add an option to emulate a RACH delay in random filler mode.
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-22 15:18:13 -07:00
Alexander Chemeris
58e9591f9e transceiver: Log channel number in DEBUG output of demoded bursts.
Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-22 14:28:22 -07:00
Alexander Chemeris
19174f581b radioInterface: Initialize power scale with a meaningful default.
Right now if you forget to send "POWER" control command, osmo-trx
will transmitt zeros. This is counter-intuitive and I've spent several
hours debugging this "issue". The issue may happen easily, because
osmo-bts doesn't send "POWER" command if there is no "power" setting
in the configuration file. Given that "POWER" command actually sets
attenuation, it's percieved as optional and in absence of it should
default to "POWER 0" (no attenuation), which translates to power
scale being 1.0.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-22 14:28:07 -07:00
Alexander Chemeris
1ba69e7762 uhd: Fix comment.
It's osmo-trx, not OpenBTS anymore.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-22 14:27:38 -07:00
Alexander Chemeris
f931cf226b radioDevice: GSMRATE macro must have parentheses around its definition.
So we had the following define:
   #define GSMRATE       1625e3/6

Now, I wanted to use it in the following expression:
   3.0/GSMRATE
which turns into:
   3.0/1625e3/6
while what I really wanted is:
   3.0/(1625e3/6) = 3.0/1625e3*6

To avoid this, all macros with calculations must be enclosed in parentheses.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-22 14:27:24 -07:00
Alexander Chemeris
e476231deb makefile: Fix build from an external path.
When you build from an external path, compiler can't find convert.h
include, because it was specified relative to the current directory.
Change this to specify the include dit relative to the Makefile
location.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-22 14:27:00 -07:00
Tom Tsou
e90c24c8d5 sigproc: Expand RACH, TSC, and EDGE correlation windows
Slightly widen the search range to accommodate timing jitter
on certain classes of devices. The expanded range minimizes
the possibility of missing bursts that arrive too early or
too late due to timing error.

Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2016-06-21 16:19:54 -07:00
268 changed files with 27811 additions and 158228 deletions

521
.clang-format Normal file
View File

@@ -0,0 +1,521 @@
# SPDX-License-Identifier: GPL-2.0
#
# clang-format configuration file. Intended for clang-format >= 4.
#
# For more information, see:
#
# Documentation/process/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
#AfterExternBlock: false # Unknown to clang-format-5.0
BeforeCatch: false
BeforeElse: false
IndentBraces: false
#SplitEmptyFunction: true # Unknown to clang-format-4.0
#SplitEmptyRecord: true # Unknown to clang-format-4.0
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
#CompactNamespaces: false # Unknown to clang-format-4.0
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
#FixNamespaceComments: false # Unknown to clang-format-4.0
# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | sort | uniq
ForEachMacros:
- 'apei_estatus_for_each_section'
- 'ata_for_each_dev'
- 'ata_for_each_link'
- '__ata_qc_for_each'
- 'ata_qc_for_each'
- 'ata_qc_for_each_raw'
- 'ata_qc_for_each_with_internal'
- 'ax25_for_each'
- 'ax25_uid_for_each'
- '__bio_for_each_bvec'
- 'bio_for_each_bvec'
- 'bio_for_each_integrity_vec'
- '__bio_for_each_segment'
- 'bio_for_each_segment'
- 'bio_for_each_segment_all'
- 'bio_list_for_each'
- 'bip_for_each_vec'
- 'bitmap_for_each_clear_region'
- 'bitmap_for_each_set_region'
- 'blkg_for_each_descendant_post'
- 'blkg_for_each_descendant_pre'
- 'blk_queue_for_each_rl'
- 'bond_for_each_slave'
- 'bond_for_each_slave_rcu'
- 'bpf_for_each_spilled_reg'
- 'btree_for_each_safe128'
- 'btree_for_each_safe32'
- 'btree_for_each_safe64'
- 'btree_for_each_safel'
- 'card_for_each_dev'
- 'cgroup_taskset_for_each'
- 'cgroup_taskset_for_each_leader'
- 'cpufreq_for_each_entry'
- 'cpufreq_for_each_entry_idx'
- 'cpufreq_for_each_valid_entry'
- 'cpufreq_for_each_valid_entry_idx'
- 'css_for_each_child'
- 'css_for_each_descendant_post'
- 'css_for_each_descendant_pre'
- 'device_for_each_child_node'
- 'dma_fence_chain_for_each'
- 'drm_atomic_crtc_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane'
- 'drm_atomic_crtc_state_for_each_plane_state'
- 'drm_atomic_for_each_plane_damage'
- 'drm_client_for_each_connector_iter'
- 'drm_client_for_each_modeset'
- 'drm_connector_for_each_possible_encoder'
- 'drm_for_each_bridge_in_chain'
- 'drm_for_each_connector_iter'
- 'drm_for_each_crtc'
- 'drm_for_each_encoder'
- 'drm_for_each_encoder_mask'
- 'drm_for_each_fb'
- 'drm_for_each_legacy_plane'
- 'drm_for_each_plane'
- 'drm_for_each_plane_mask'
- 'drm_for_each_privobj'
- 'drm_mm_for_each_hole'
- 'drm_mm_for_each_node'
- 'drm_mm_for_each_node_in_range'
- 'drm_mm_for_each_node_safe'
- 'flow_action_for_each'
- 'for_each_active_dev_scope'
- 'for_each_active_drhd_unit'
- 'for_each_active_iommu'
- 'for_each_available_child_of_node'
- 'for_each_bio'
- 'for_each_board_func_rsrc'
- 'for_each_bvec'
- 'for_each_card_auxs'
- 'for_each_card_auxs_safe'
- 'for_each_card_components'
- 'for_each_card_pre_auxs'
- 'for_each_card_prelinks'
- 'for_each_card_rtds'
- 'for_each_card_rtds_safe'
- 'for_each_cgroup_storage_type'
- 'for_each_child_of_node'
- 'for_each_clear_bit'
- 'for_each_clear_bit_from'
- 'for_each_cmsghdr'
- 'for_each_compatible_node'
- 'for_each_component_dais'
- 'for_each_component_dais_safe'
- 'for_each_comp_order'
- 'for_each_console'
- 'for_each_cpu'
- 'for_each_cpu_and'
- 'for_each_cpu_not'
- 'for_each_cpu_wrap'
- 'for_each_dev_addr'
- 'for_each_dev_scope'
- 'for_each_displayid_db'
- 'for_each_dma_cap_mask'
- 'for_each_dpcm_be'
- 'for_each_dpcm_be_rollback'
- 'for_each_dpcm_be_safe'
- 'for_each_dpcm_fe'
- 'for_each_drhd_unit'
- 'for_each_dss_dev'
- 'for_each_efi_handle'
- 'for_each_efi_memory_desc'
- 'for_each_efi_memory_desc_in_map'
- 'for_each_element'
- 'for_each_element_extid'
- 'for_each_element_id'
- 'for_each_endpoint_of_node'
- 'for_each_evictable_lru'
- 'for_each_fib6_node_rt_rcu'
- 'for_each_fib6_walker_rt'
- 'for_each_free_mem_pfn_range_in_zone'
- 'for_each_free_mem_pfn_range_in_zone_from'
- 'for_each_free_mem_range'
- 'for_each_free_mem_range_reverse'
- 'for_each_func_rsrc'
- 'for_each_hstate'
- 'for_each_if'
- 'for_each_iommu'
- 'for_each_ip_tunnel_rcu'
- 'for_each_irq_nr'
- 'for_each_link_codecs'
- 'for_each_link_platforms'
- 'for_each_lru'
- 'for_each_matching_node'
- 'for_each_matching_node_and_match'
- 'for_each_member'
- 'for_each_memblock'
- 'for_each_memblock_type'
- 'for_each_memcg_cache_index'
- 'for_each_mem_pfn_range'
- 'for_each_mem_range'
- 'for_each_mem_range_rev'
- 'for_each_migratetype_order'
- 'for_each_msi_entry'
- 'for_each_msi_entry_safe'
- 'for_each_net'
- 'for_each_net_continue_reverse'
- 'for_each_netdev'
- 'for_each_netdev_continue'
- 'for_each_netdev_continue_rcu'
- 'for_each_netdev_continue_reverse'
- 'for_each_netdev_feature'
- 'for_each_netdev_in_bond_rcu'
- 'for_each_netdev_rcu'
- 'for_each_netdev_reverse'
- 'for_each_netdev_safe'
- 'for_each_net_rcu'
- 'for_each_new_connector_in_state'
- 'for_each_new_crtc_in_state'
- 'for_each_new_mst_mgr_in_state'
- 'for_each_new_plane_in_state'
- 'for_each_new_private_obj_in_state'
- 'for_each_node'
- 'for_each_node_by_name'
- 'for_each_node_by_type'
- 'for_each_node_mask'
- 'for_each_node_state'
- 'for_each_node_with_cpus'
- 'for_each_node_with_property'
- 'for_each_of_allnodes'
- 'for_each_of_allnodes_from'
- 'for_each_of_cpu_node'
- 'for_each_of_pci_range'
- 'for_each_old_connector_in_state'
- 'for_each_old_crtc_in_state'
- 'for_each_old_mst_mgr_in_state'
- 'for_each_oldnew_connector_in_state'
- 'for_each_oldnew_crtc_in_state'
- 'for_each_oldnew_mst_mgr_in_state'
- 'for_each_oldnew_plane_in_state'
- 'for_each_oldnew_plane_in_state_reverse'
- 'for_each_oldnew_private_obj_in_state'
- 'for_each_old_plane_in_state'
- 'for_each_old_private_obj_in_state'
- 'for_each_online_cpu'
- 'for_each_online_node'
- 'for_each_online_pgdat'
- 'for_each_pci_bridge'
- 'for_each_pci_dev'
- 'for_each_pci_msi_entry'
- 'for_each_populated_zone'
- 'for_each_possible_cpu'
- 'for_each_present_cpu'
- 'for_each_prime_number'
- 'for_each_prime_number_from'
- 'for_each_process'
- 'for_each_process_thread'
- 'for_each_property_of_node'
- 'for_each_registered_fb'
- 'for_each_reserved_mem_region'
- 'for_each_rtd_codec_dai'
- 'for_each_rtd_codec_dai_rollback'
- 'for_each_rtd_components'
- 'for_each_set_bit'
- 'for_each_set_bit_from'
- 'for_each_set_clump8'
- 'for_each_sg'
- 'for_each_sg_dma_page'
- 'for_each_sg_page'
- 'for_each_sibling_event'
- 'for_each_subelement'
- 'for_each_subelement_extid'
- 'for_each_subelement_id'
- '__for_each_thread'
- 'for_each_thread'
- 'for_each_wakeup_source'
- 'for_each_zone'
- 'for_each_zone_zonelist'
- 'for_each_zone_zonelist_nodemask'
- 'fwnode_for_each_available_child_node'
- 'fwnode_for_each_child_node'
- 'fwnode_graph_for_each_endpoint'
- 'gadget_for_each_ep'
- 'genradix_for_each'
- 'genradix_for_each_from'
- 'hash_for_each'
- 'hash_for_each_possible'
- 'hash_for_each_possible_rcu'
- 'hash_for_each_possible_rcu_notrace'
- 'hash_for_each_possible_safe'
- 'hash_for_each_rcu'
- 'hash_for_each_safe'
- 'hctx_for_each_ctx'
- 'hlist_bl_for_each_entry'
- 'hlist_bl_for_each_entry_rcu'
- 'hlist_bl_for_each_entry_safe'
- 'hlist_for_each'
- 'hlist_for_each_entry'
- 'hlist_for_each_entry_continue'
- 'hlist_for_each_entry_continue_rcu'
- 'hlist_for_each_entry_continue_rcu_bh'
- 'hlist_for_each_entry_from'
- 'hlist_for_each_entry_from_rcu'
- 'hlist_for_each_entry_rcu'
- 'hlist_for_each_entry_rcu_bh'
- 'hlist_for_each_entry_rcu_notrace'
- 'hlist_for_each_entry_safe'
- '__hlist_for_each_rcu'
- 'hlist_for_each_safe'
- 'hlist_nulls_for_each_entry'
- 'hlist_nulls_for_each_entry_from'
- 'hlist_nulls_for_each_entry_rcu'
- 'hlist_nulls_for_each_entry_safe'
- 'i3c_bus_for_each_i2cdev'
- 'i3c_bus_for_each_i3cdev'
- 'ide_host_for_each_port'
- 'ide_port_for_each_dev'
- 'ide_port_for_each_present_dev'
- 'idr_for_each_entry'
- 'idr_for_each_entry_continue'
- 'idr_for_each_entry_continue_ul'
- 'idr_for_each_entry_ul'
- 'in_dev_for_each_ifa_rcu'
- 'in_dev_for_each_ifa_rtnl'
- 'inet_bind_bucket_for_each'
- 'inet_lhash2_for_each_icsk_rcu'
- 'key_for_each'
- 'key_for_each_safe'
- 'klp_for_each_func'
- 'klp_for_each_func_safe'
- 'klp_for_each_func_static'
- 'klp_for_each_object'
- 'klp_for_each_object_safe'
- 'klp_for_each_object_static'
- 'kvm_for_each_memslot'
- 'kvm_for_each_vcpu'
- 'list_for_each'
- 'list_for_each_codec'
- 'list_for_each_codec_safe'
- 'list_for_each_continue'
- 'list_for_each_entry'
- 'list_for_each_entry_continue'
- 'list_for_each_entry_continue_rcu'
- 'list_for_each_entry_continue_reverse'
- 'list_for_each_entry_from'
- 'list_for_each_entry_from_rcu'
- 'list_for_each_entry_from_reverse'
- 'list_for_each_entry_lockless'
- 'list_for_each_entry_rcu'
- 'list_for_each_entry_reverse'
- 'list_for_each_entry_safe'
- 'list_for_each_entry_safe_continue'
- 'list_for_each_entry_safe_from'
- 'list_for_each_entry_safe_reverse'
- 'list_for_each_prev'
- 'list_for_each_prev_safe'
- 'list_for_each_safe'
- 'llist_for_each'
- 'llist_for_each_entry'
- 'llist_for_each_entry_safe'
- 'llist_for_each_safe'
- 'mci_for_each_dimm'
- 'media_device_for_each_entity'
- 'media_device_for_each_intf'
- 'media_device_for_each_link'
- 'media_device_for_each_pad'
- 'nanddev_io_for_each_page'
- 'netdev_for_each_lower_dev'
- 'netdev_for_each_lower_private'
- 'netdev_for_each_lower_private_rcu'
- 'netdev_for_each_mc_addr'
- 'netdev_for_each_uc_addr'
- 'netdev_for_each_upper_dev_rcu'
- 'netdev_hw_addr_list_for_each'
- 'nft_rule_for_each_expr'
- 'nla_for_each_attr'
- 'nla_for_each_nested'
- 'nlmsg_for_each_attr'
- 'nlmsg_for_each_msg'
- 'nr_neigh_for_each'
- 'nr_neigh_for_each_safe'
- 'nr_node_for_each'
- 'nr_node_for_each_safe'
- 'of_for_each_phandle'
- 'of_property_for_each_string'
- 'of_property_for_each_u32'
- 'pci_bus_for_each_resource'
- 'ping_portaddr_for_each_entry'
- 'plist_for_each'
- 'plist_for_each_continue'
- 'plist_for_each_entry'
- 'plist_for_each_entry_continue'
- 'plist_for_each_entry_safe'
- 'plist_for_each_safe'
- 'pnp_for_each_card'
- 'pnp_for_each_dev'
- 'protocol_for_each_card'
- 'protocol_for_each_dev'
- 'queue_for_each_hw_ctx'
- 'radix_tree_for_each_slot'
- 'radix_tree_for_each_tagged'
- 'rbtree_postorder_for_each_entry_safe'
- 'rdma_for_each_block'
- 'rdma_for_each_port'
- 'resource_list_for_each_entry'
- 'resource_list_for_each_entry_safe'
- 'rhl_for_each_entry_rcu'
- 'rhl_for_each_rcu'
- 'rht_for_each'
- 'rht_for_each_entry'
- 'rht_for_each_entry_from'
- 'rht_for_each_entry_rcu'
- 'rht_for_each_entry_rcu_from'
- 'rht_for_each_entry_safe'
- 'rht_for_each_from'
- 'rht_for_each_rcu'
- 'rht_for_each_rcu_from'
- '__rq_for_each_bio'
- 'rq_for_each_bvec'
- 'rq_for_each_segment'
- 'scsi_for_each_prot_sg'
- 'scsi_for_each_sg'
- 'sctp_for_each_hentry'
- 'sctp_skb_for_each'
- 'shdma_for_each_chan'
- '__shost_for_each_device'
- 'shost_for_each_device'
- 'sk_for_each'
- 'sk_for_each_bound'
- 'sk_for_each_entry_offset_rcu'
- 'sk_for_each_from'
- 'sk_for_each_rcu'
- 'sk_for_each_safe'
- 'sk_nulls_for_each'
- 'sk_nulls_for_each_from'
- 'sk_nulls_for_each_rcu'
- 'snd_array_for_each'
- 'snd_pcm_group_for_each_entry'
- 'snd_soc_dapm_widget_for_each_path'
- 'snd_soc_dapm_widget_for_each_path_safe'
- 'snd_soc_dapm_widget_for_each_sink_path'
- 'snd_soc_dapm_widget_for_each_source_path'
- 'tb_property_for_each'
- 'tcf_exts_for_each_action'
- 'udp_portaddr_for_each_entry'
- 'udp_portaddr_for_each_entry_rcu'
- 'usb_hub_for_each_child'
- 'v4l2_device_for_each_subdev'
- 'v4l2_m2m_for_each_dst_buf'
- 'v4l2_m2m_for_each_dst_buf_safe'
- 'v4l2_m2m_for_each_src_buf'
- 'v4l2_m2m_for_each_src_buf_safe'
- 'virtio_device_for_each_vq'
- 'xa_for_each'
- 'xa_for_each_marked'
- 'xa_for_each_range'
- 'xa_for_each_start'
- 'xas_for_each'
- 'xas_for_each_conflict'
- 'xas_for_each_marked'
- 'xbc_array_for_each_value'
- 'xbc_for_each_key_value'
- 'xbc_node_for_each_array_value'
- 'xbc_node_for_each_child'
- 'xbc_node_for_each_key_value'
- 'zorro_for_each_dev'
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
#IndentPPDirectives: None # Unknown to clang-format-5.0
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
#SortUsingDeclarations: false # Unknown to clang-format-4.0
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
SpaceBeforeParens: ControlStatements
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...

88
.gitignore vendored Normal file
View File

@@ -0,0 +1,88 @@
# build results
*.o
*.lo
*.la
Transceiver52M/osmo-trx-uhd
Transceiver52M/osmo-trx-usrp1
Transceiver52M/osmo-trx-lms
Transceiver52M/osmo-trx-ipc
Transceiver52M/osmo-trx-blade
Transceiver52M/osmo-trx-ipc2
Transceiver52M/osmo-trx-syncthing-blade
Transceiver52M/osmo-trx-syncthing-uhd
Transceiver52M/osmo-trx-syncthing-ipc
Transceiver52M/osmo-trx-ms-blade
Transceiver52M/osmo-trx-ms-uhd
Transceiver52M/osmo-trx-ms-ipc
Transceiver52M/device/ipc/uhddev_ipc.cpp
.clang-format
# tests
tests/CommonLibs/BitVectorTest
tests/CommonLibs/F16Test
tests/CommonLibs/InterthreadTest
tests/CommonLibs/LogTest
tests/CommonLibs/RegexpTest
tests/CommonLibs/SocketsTest
tests/CommonLibs/TimevalTest
tests/CommonLibs/URLEncodeTest
tests/CommonLibs/VectorTest
tests/CommonLibs/PRBSTest
tests/Transceiver52M/convolve_test
tests/Transceiver52M/LMSDeviceTest
Transceiver52M/device/ipc/ipc-driver-test
# automake/autoconf
*.in
.deps
.libs
.dirstamp
*~
Makefile
config.log
config.status
config.h
config.guess
config.sub
config/*
configure
compile
aclocal.m4
autom4te.cache
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1
INSTALL
tests/package.m4
tests/testsuite
tests/atconfig
tests/testsuite.dir
tests/testsuite.log
# vim
*.sw?
# manuals
doc/manuals/*.html
doc/manuals/*.svg
doc/manuals/*.pdf
doc/manuals/*__*.png
doc/manuals/*.check
doc/manuals/generated/
doc/manuals/vty/osmotrx-*-vty-reference.xml
doc/manuals/vty/osmotrx-*-vty-reference.xml.inc.gen
doc/manuals/vty/osmotrx-*-vty-reference.xml.inc.merged
doc/manuals/common
doc/manuals/build
contrib/osmo-trx.spec
!contrib/osmo-trx.spec.in
utils/osmo-prbs-tool
/.qtc_clangd/*
/.cache/*
/.vscode/*

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "osmocom-bb"]
path = osmocom-bb
url = https://gitea.osmocom.org/phone-side/osmocom-bb.git
branch = a4aac5c3554559c2c994609f90b92a9daf6e8a89

3
.gitreview Normal file
View File

@@ -0,0 +1,3 @@
[gerrit]
host=gerrit.osmocom.org
project=osmo-trx

192
AUTHORS
View File

@@ -1,192 +0,0 @@
#
# Copyright 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
David A. Burgess, dburgess@kestrelsp.com:
CLI/CLI.cpp
CLI/CLI.h
CommonLibs/Assert.h
CommonLibs/BitVector.cpp
CommonLibs/BitVectorTest.cpp
CommonLibs/Configuration.cpp
CommonLibs/Configuration.h
CommonLibs/ConfigurationTest.cpp
CommonLibs/Interthread.h
CommonLibs/InterthreadTest.cpp
CommonLibs/LinkedLists.cpp
CommonLibs/LinkedLists.h
CommonLibs/Regexp.h
CommonLibs/RegexpTest.cpp
CommonLibs/Sockets.cpp
CommonLibs/Sockets.h
CommonLibs/SocketsTest.cpp
CommonLibs/Threads.cpp
CommonLibs/Threads.h
CommonLibs/Timeval.cpp
CommonLibs/Timeval.h
CommonLibs/TimevalTest.cpp
CommonLibs/Vector.h
CommonLibs/VectorTest.cpp
Control/CallControl.cpp
Control/ControlCommon.cpp
Control/ControlCommon.h
Control/FACCHDispatch.cpp
Control/MobilityManagement.cpp
Control/PagerTest.cpp
Control/RadioResource.cpp
Control/SDCCHDispatch.cpp
GSM/GSM610Tables.cpp
GSM/GSM610Tables.h
GSM/GSMCommon.cpp
GSM/GSMCommon.h
GSM/GSMConfig.h
GSM/GSML1FEC.cpp
GSM/GSML1FEC.h
GSM/GSML2LAPDm.cpp
GSM/GSML2LAPDm.h
GSM/GSML3CCElements.cpp
GSM/GSML3CCElements.h
GSM/GSML3CCMessages.cpp
GSM/GSML3CCMessages.h
GSM/GSML3CommonElements.cpp
GSM/GSML3CommonElements.h
GSM/GSML3MMElements.cpp
GSM/GSML3MMElements.h
GSM/GSML3MMMessages.cpp
GSM/GSML3MMMessages.h
GSM/GSML3Message.cpp
GSM/GSML3Message.h
GSM/GSML3RRElements.cpp
GSM/GSML3RRElements.h
GSM/GSML3RRMessages.cpp
GSM/GSML3RRMessages.h
GSM/GSMLogicalChannel.h
GSM/GSMTDMA.cpp
GSM/GSMTDMA.h
GSM/GSMTransfer.cpp
GSM/GSMTransfer.h
LICENSEBLOCK
SIP/SIPEngine.h
SIP/SIPInterface.h
SMS/SMSMessages.cpp
SMS/SMSMessages.h
SMS/SMSTransfer.cpp
SMS/SMSTransfer.h
TRXManager/TRXManager.cpp
Transceiver/Complex.h
apps/OpenBTS900.cpp
apps/OpenBTS850.cpp
apps/OpenBTS25c3.cpp
tests/AGCHTest.cpp
tests/BeaconTest.cpp
tests/CallTest.cpp
tests/CallTest2.cpp
tests/LAPDmTest.cpp
tests/LoopbackTest.cpp
tests/RegistrationTest.cpp
tests/TRXSimulator.cpp
Harvind S. Samra, hssamra@kestrelsp.com:
Control/PagerTest.cpp
Control/RadioResource.cpp
GSM/GSMConfig.h
GSM/GSMTransfer.h
LICENSEBLOCK
Transceiver/ComplexTest.cpp
Transceiver/Transceiver.cpp
Transceiver/Transceiver.h
Transceiver/USRPDevice.cpp
Transceiver/USRPDevice.h
Transceiver/USRPping.cpp
Transceiver/radioInterface.cpp
Transceiver/radioInterface.h
Transceiver/rcvLPF_651.h
Transceiver/runTransceiver.cpp
Transceiver/sendLPF_961.h
Transceiver/sigProcLib.cpp
Transceiver/sigProcLib.h
Transceiver/sigProcLibTest.cpp
Transceiver/sweepGenerator.cpp
Transceiver/testRadio.cpp
Raffi Sevlian, raffisev@gmail.com:
Control/CallControl.cpp
Control/ControlCommon.cpp
Control/ControlCommon.h
Control/FACCHDispatch.cpp
Control/MobilityManagement.cpp
Control/PagerTest.cpp
Control/RadioResource.cpp
GSM/GSMCommon.h
GSM/GSMConfig.h
GSM/GSML1FEC.h
GSM/GSML3CCElements.cpp
GSM/GSML3CCElements.h
GSM/GSML3CCMessages.cpp
GSM/GSML3CCMessages.h
GSM/GSML3CommonElements.cpp
GSM/GSML3CommonElements.h
GSM/GSML3MMElements.cpp
GSM/GSML3MMElements.h
GSM/GSML3MMMessages.cpp
GSM/GSML3MMMessages.h
GSM/GSML3Message.cpp
GSM/GSML3Message.h
GSM/GSML3RRElements.cpp
GSM/GSML3RRElements.h
GSM/GSML3RRMessages.cpp
GSM/GSML3RRMessages.h
GSM/GSMLogicalChannel.h
GSM/GSMSAPMux.cpp
GSM/GSMSAPMux.h
GSM/GSMTransfer.h
LICENSEBLOCK
SIP/SIPEngine.cpp
SIP/SIPInterface.cpp
SIP/SIPInterface.h
SIP/SIPMessage.cpp
SIP/SIPMessage.h
SIP/SIPUtility.cpp
SIP/SIPUtility.h
SMS/CMMessage.cpp
SMS/CMMessage.h
SMS/CMProcessor.cpp
SMS/CMProcessor.h
SMS/CMTest.cpp
SMS/RLMessage.cpp
SMS/RLMessage.h
SMS/RLProcessor.cpp
SMS/RLProcessor.h
SMS/SMSMessages.cpp
SMS/SMSMessages.h
SMS/SMSProcessors.cpp
SMS/SMSProcessors.h
SMS/SMSTransfer.cpp
SMS/SMSTransfer.h
SMS/TLMessage.cpp
SMS/TLMessage.h
SMS/TLProcessor.cpp
SMS/TLProcessor.h
TRXManager/TRXManager.h
Alon Levy, alonlevy1@gmail.com
RRLPMessages.cpp
RRLPMessages.h
RRLPTest.cpp

30
COPYING
View File

@@ -666,23 +666,23 @@ For more information on this, and how to apply and follow the GNU AGPL, see
=========================================================================
This marks the end of the AGPLv3 text. The following text is appended to the
same file for convience but constituting a distinct document, not part of the
same file for convenience but constituting a distinct document, not part of the
actual AGPL text and not part of an attempt to create a deriviative work based
on the AGPLv3 text.
=========================================================================
ADDITIONAL TERMS TO THE AGPLv3 LICENSE FOR OPENBTS
ADDITIONAL TERMS TO THE AGPLv3 LICENSE FOR OsmoTRX
Permissive Terms Supplementing the License
1. Remote Interaction Through IP Networks.
OpenBTS includes an implementation of the GSM network cellular air interface,
OsmoTRX is an implementation of the GSM network cellular air interface,
as well as other interfaces to IP networks. The interaction of cellular
handsets with the OpenBTS software is considered "remote network interaction"
handsets with the OsmoTRX software is considered "remote network interaction"
for the purposes of the Affero General Public License and cellular users are
subject to the source code access requirements of Section 13 of AGPLv3 ("Remote
Network Interaction; Use with the GNU General Public License").
@@ -694,17 +694,6 @@ interfaces other than the GSM air interface from the requirements of Section 13
is an additional permission granted to you.
Non-Permissive Terms Supplementing The License
1. Trademarks.
"OpenBTS" is a trademark of Range Networks, Inc., registered with
the US Patent and Trademark Office. Your use of OpenBTS software under a GPL
license does not include the right to use the OpenBTS trademark in commerce.
This additional non-permissive term is consistent with Section 7 of the AGPLv3
license.
END OF ADDITIONAL TERMS
@@ -712,13 +701,8 @@ END OF ADDITIONAL TERMS
How to comply with Section 13 of the AGPLv3 license.
The recommended method for compliance with Section 13 of the AGPLv3 license is
to deliver a text message to each handset that attaches to the OpenBTS cellular
network. At a minimum, that text message should include the string "OpenBTS
AGPLv3" and a URL that can be used to access the OpenBTS source code. This
to deliver a text message to each handset that attaches to the cellular
network which uses OsmoTRX. At a minimum, that text message should include the string
"OsmoTRX AGPLv3" and a URL that can be used to access the OsmoBTS source code. This
message need not be delivered to handsets that are denied registration with the
network, since those handsets have been denied service.
In OpenBTS 2.6, such text messages can be delivered with the "Welcome Message"
feature. See the OpenBTS.config.example file for more information on the use of
this feature for AGPLv3 compliance.

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2008, 2009 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@@ -30,12 +31,13 @@
#include <iostream>
#include <stdio.h>
#include <sstream>
#include <math.h>
using namespace std;
/**
Apply a Galois polymonial to a binary seqeunce.
Apply a Galois polymonial to a binary sequence.
@param val The input sequence.
@param poly The polynomial.
@param order The order of the polynomial.
@@ -199,49 +201,6 @@ void BitVector::LSB8MSB()
uint64_t BitVector::syndrome(Generator& gen) const
{
gen.clear();
const char *dp = mStart;
while (dp<mEnd) gen.syndromeShift(*dp++);
return gen.state();
}
uint64_t BitVector::parity(Generator& gen) const
{
gen.clear();
const char *dp = mStart;
while (dp<mEnd) gen.encoderShift(*dp++);
return gen.state();
}
void BitVector::encode(const ViterbiR2O4& coder, BitVector& target)
{
size_t sz = size();
assert(sz*coder.iRate() == target.size());
// Build a "history" array where each element contains the full history.
uint32_t history[sz];
uint32_t accum = 0;
for (size_t i=0; i<sz; i++) {
accum = (accum<<1) | bit(i);
history[i] = accum;
}
// Look up histories in the pre-generated state table.
char *op = target.begin();
for (size_t i=0; i<sz; i++) {
unsigned index = coder.cMask() & history[i];
for (unsigned g=0; g<coder.iRate(); g++) {
*op++ = coder.stateTable(g,index);
}
}
}
unsigned BitVector::sum() const
{
unsigned sum = 0;
@@ -287,148 +246,12 @@ ostream& operator<<(ostream& os, const BitVector& hv)
ViterbiR2O4::ViterbiR2O4()
{
assert(mDeferral < 32);
mCoeffs[0] = 0x019;
mCoeffs[1] = 0x01b;
computeStateTables(0);
computeStateTables(1);
computeGeneratorTable();
}
void ViterbiR2O4::initializeStates()
{
for (unsigned i=0; i<mIStates; i++) clear(mSurvivors[i]);
for (unsigned i=0; i<mNumCands; i++) clear(mCandidates[i]);
}
void ViterbiR2O4::computeStateTables(unsigned g)
{
assert(g<mIRate);
for (unsigned state=0; state<mIStates; state++) {
// 0 input
uint32_t inputVal = state<<1;
mStateTable[g][inputVal] = applyPoly(inputVal, mCoeffs[g], mOrder+1);
// 1 input
inputVal |= 1;
mStateTable[g][inputVal] = applyPoly(inputVal, mCoeffs[g], mOrder+1);
}
}
void ViterbiR2O4::computeGeneratorTable()
{
for (unsigned index=0; index<mIStates*2; index++) {
mGeneratorTable[index] = (mStateTable[0][index]<<1) | mStateTable[1][index];
}
}
void ViterbiR2O4::branchCandidates()
{
// Branch to generate new input states.
const vCand *sp = mSurvivors;
for (unsigned i=0; i<mNumCands; i+=2) {
// extend and suffix
const uint32_t iState0 = (sp->iState) << 1; // input state for 0
const uint32_t iState1 = iState0 | 0x01; // input state for 1
const uint32_t oStateShifted = (sp->oState) << mIRate; // shifted output
const float cost = sp->cost;
sp++;
// 0 input extension
mCandidates[i].cost = cost;
mCandidates[i].oState = oStateShifted | mGeneratorTable[iState0 & mCMask];
mCandidates[i].iState = iState0;
// 1 input extension
mCandidates[i+1].cost = cost;
mCandidates[i+1].oState = oStateShifted | mGeneratorTable[iState1 & mCMask];
mCandidates[i+1].iState = iState1;
}
}
void ViterbiR2O4::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost)
{
const float *cTab[2] = {matchCost,mismatchCost};
for (unsigned i=0; i<mNumCands; i++) {
vCand& thisCand = mCandidates[i];
// We examine input bits 2 at a time for a rate 1/2 coder.
const unsigned mismatched = inSample ^ (thisCand.oState);
thisCand.cost += cTab[mismatched&0x01][1] + cTab[(mismatched>>1)&0x01][0];
}
}
void ViterbiR2O4::pruneCandidates()
{
const vCand* c1 = mCandidates; // 0-prefix
const vCand* c2 = mCandidates + mIStates; // 1-prefix
for (unsigned i=0; i<mIStates; i++) {
if (c1[i].cost < c2[i].cost) mSurvivors[i] = c1[i];
else mSurvivors[i] = c2[i];
}
}
const ViterbiR2O4::vCand& ViterbiR2O4::minCost() const
{
int minIndex = 0;
float minCost = mSurvivors[0].cost;
for (unsigned i=1; i<mIStates; i++) {
const float thisCost = mSurvivors[i].cost;
if (thisCost>=minCost) continue;
minCost = thisCost;
minIndex=i;
}
return mSurvivors[minIndex];
}
const ViterbiR2O4::vCand& ViterbiR2O4::step(uint32_t inSample, const float *probs, const float *iprobs)
{
branchCandidates();
getSoftCostMetrics(inSample,probs,iprobs);
pruneCandidates();
return minCost();
}
uint64_t Parity::syndrome(const BitVector& receivedCodeword)
{
return receivedCodeword.syndrome(*this);
}
void Parity::writeParityWord(const BitVector& data, BitVector& parityTarget, bool invert)
{
uint64_t pWord = data.parity(*this);
if (invert) pWord = ~pWord;
parityTarget.fillField(0,pWord,size());
}
SoftVector::SoftVector(const BitVector& source)
{
resize(source.size());
for (size_t i=0; i<size(); i++) {
if (source.bit(i)) mStart[i]=1.0F;
else mStart[i]=0.0F;
else mStart[i]=-1.0F;
}
}
@@ -438,102 +261,20 @@ BitVector SoftVector::sliced() const
size_t sz = size();
BitVector newSig(sz);
for (size_t i=0; i<sz; i++) {
if (mStart[i]>0.5F) newSig[i]=1;
if (mStart[i]>0.0F) newSig[i]=1;
else newSig[i] = 0;
}
return newSig;
}
void SoftVector::decode(ViterbiR2O4 &decoder, BitVector& target) const
{
const size_t sz = size();
const unsigned deferral = decoder.deferral();
const size_t ctsz = sz + deferral*decoder.iRate();
assert(sz <= decoder.iRate()*target.size());
// Build a "history" array where each element contains the full history.
uint32_t history[ctsz];
{
BitVector bits = sliced();
uint32_t accum = 0;
for (size_t i=0; i<sz; i++) {
accum = (accum<<1) | bits.bit(i);
history[i] = accum;
}
// Repeat last bit at the end.
for (size_t i=sz; i<ctsz; i++) {
accum = (accum<<1) | (accum & 0x01);
history[i] = accum;
}
}
// Precompute metric tables.
float matchCostTable[ctsz];
float mismatchCostTable[ctsz];
{
const float *dp = mStart;
for (size_t i=0; i<sz; i++) {
// pVal is the probability that a bit is correct.
// ipVal is the probability that a bit is incorrect.
float pVal = dp[i];
if (pVal>0.5F) pVal = 1.0F-pVal;
float ipVal = 1.0F-pVal;
// This is a cheap approximation to an ideal cost function.
if (pVal<0.01F) pVal = 0.01;
if (ipVal<0.01F) ipVal = 0.01;
matchCostTable[i] = 0.25F/ipVal;
mismatchCostTable[i] = 0.25F/pVal;
}
// pad end of table with unknowns
for (size_t i=sz; i<ctsz; i++) {
matchCostTable[i] = 0.5F;
mismatchCostTable[i] = 0.5F;
}
}
{
decoder.initializeStates();
// Each sample of history[] carries its history.
// So we only have to process every iRate-th sample.
const unsigned step = decoder.iRate();
// input pointer
const uint32_t *ip = history + step - 1;
// output pointers
char *op = target.begin();
const char *const opt = target.end();
// table pointers
const float* match = matchCostTable;
const float* mismatch = mismatchCostTable;
size_t oCount = 0;
while (op<opt) {
// Viterbi algorithm
assert(match-matchCostTable<sizeof(matchCostTable)/sizeof(matchCostTable[0])-1);
assert(mismatch-mismatchCostTable<sizeof(mismatchCostTable)/sizeof(mismatchCostTable[0])-1);
const ViterbiR2O4::vCand &minCost = decoder.step(*ip, match, mismatch);
ip += step;
match += step;
mismatch += step;
// output
if (oCount>=deferral) *op++ = (minCost.iState >> deferral)&0x01;
oCount++;
}
}
}
// (pat) Added 6-22-2012
float SoftVector::getEnergy(float *plow) const
{
const SoftVector &vec = *this;
int len = vec.size();
float avg = 0; float low = 1;
for (int i = 0; i < len; i++) {
float bit = vec[i];
float energy = 2*((bit < 0.5) ? (0.5-bit) : (bit-0.5));
float energy = fabsf(vec[i]);
if (energy < low) low = energy;
avg += energy/len;
}
@@ -545,8 +286,12 @@ float SoftVector::getEnergy(float *plow) const
ostream& operator<<(ostream& os, const SoftVector& sv)
{
for (size_t i=0; i<sv.size(); i++) {
if (sv[i]<0.25) os << "0";
else if (sv[i]>0.75) os << "1";
if (sv[i]<-0.5) os << "0";
else if (sv[i]<-0.25) os << "o";
else if (sv[i]<0.0) os << ".";
else if (sv[i]>0.5) os << "1";
else if (sv[i]>0.25) os << "|";
else if (sv[i]>0.0) os << "'";
else os << "-";
}
return os;

View File

@@ -1,6 +1,8 @@
/*
* Copyright 2008, 2009 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -30,201 +32,6 @@
#include <stdint.h>
class BitVector;
class SoftVector;
/** Shift-register (LFSR) generator. */
class Generator {
private:
uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent.
uint64_t mState; ///< shift register state. LSB is most recent.
uint64_t mMask; ///< mask for reading state
unsigned mLen; ///< number of bits used in shift register
unsigned mLen_1; ///< mLen - 1
public:
Generator(uint64_t wCoeff, unsigned wLen)
:mCoeff(wCoeff),mState(0),
mMask((1ULL<<wLen)-1),
mLen(wLen),mLen_1(wLen-1)
{ assert(wLen<64); }
void clear() { mState=0; }
/**@name Accessors */
//@{
uint64_t state() const { return mState & mMask; }
unsigned size() const { return mLen; }
//@}
/**
Calculate one bit of a syndrome.
This is in the .h for inlining.
*/
void syndromeShift(unsigned inBit)
{
const unsigned fb = (mState>>(mLen_1)) & 0x01;
mState = (mState<<1) ^ (inBit & 0x01);
if (fb) mState ^= mCoeff;
}
/**
Update the generator state by one cycle.
This is in the .h for inlining.
*/
void encoderShift(unsigned inBit)
{
const unsigned fb = ((mState>>(mLen_1)) ^ inBit) & 0x01;
mState <<= 1;
if (fb) mState ^= mCoeff;
}
};
/** Parity (CRC-type) generator and checker based on a Generator. */
class Parity : public Generator {
protected:
unsigned mCodewordSize;
public:
Parity(uint64_t wCoefficients, unsigned wParitySize, unsigned wCodewordSize)
:Generator(wCoefficients, wParitySize),
mCodewordSize(wCodewordSize)
{ }
/** Compute the parity word and write it into the target segment. */
void writeParityWord(const BitVector& data, BitVector& parityWordTarget, bool invert=true);
/** Compute the syndrome of a received sequence. */
uint64_t syndrome(const BitVector& receivedCodeword);
};
/**
Class to represent convolutional coders/decoders of rate 1/2, memory length 4.
This is the "workhorse" coder for most GSM channels.
*/
class ViterbiR2O4 {
private:
/**name Lots of precomputed elements so the compiler can optimize like hell. */
//@{
/**@name Core values. */
//@{
static const unsigned mIRate = 2; ///< reciprocal of rate
static const unsigned mOrder = 4; ///< memory length of generators
//@}
/**@name Derived values. */
//@{
static const unsigned mIStates = 0x01 << mOrder; ///< number of states, number of survivors
static const uint32_t mSMask = mIStates-1; ///< survivor mask
static const uint32_t mCMask = (mSMask<<1) | 0x01; ///< candidate mask
static const uint32_t mOMask = (0x01<<mIRate)-1; ///< ouput mask, all iRate low bits set
static const unsigned mNumCands = mIStates*2; ///< number of candidates to generate during branching
static const unsigned mDeferral = 6*mOrder; ///< deferral to be used
//@}
//@}
/** Precomputed tables. */
//@{
uint32_t mCoeffs[mIRate]; ///< polynomial for each generator
uint32_t mStateTable[mIRate][2*mIStates]; ///< precomputed generator output tables
uint32_t mGeneratorTable[2*mIStates]; ///< precomputed coder output table
//@}
public:
/**
A candidate sequence in a Viterbi decoder.
The 32-bit state register can support a deferral of 6 with a 4th-order coder.
*/
typedef struct candStruct {
uint32_t iState; ///< encoder input associated with this candidate
uint32_t oState; ///< encoder output associated with this candidate
float cost; ///< cost (metric value), float to support soft inputs
} vCand;
/** Clear a structure. */
void clear(vCand& v)
{
v.iState=0;
v.oState=0;
v.cost=0;
}
private:
/**@name Survivors and candidates. */
//@{
vCand mSurvivors[mIStates]; ///< current survivor pool
vCand mCandidates[2*mIStates]; ///< current candidate pool
//@}
public:
unsigned iRate() const { return mIRate; }
uint32_t cMask() const { return mCMask; }
uint32_t stateTable(unsigned g, unsigned i) const { return mStateTable[g][i]; }
unsigned deferral() const { return mDeferral; }
ViterbiR2O4();
/** Set all cost metrics to zero. */
void initializeStates();
/**
Full cycle of the Viterbi algorithm: branch, metrics, prune, select.
@return reference to minimum-cost candidate.
*/
const vCand& step(uint32_t inSample, const float *probs, const float *iprobs);
private:
/** Branch survivors into new candidates. */
void branchCandidates();
/** Compute cost metrics for soft-inputs. */
void getSoftCostMetrics(uint32_t inSample, const float *probs, const float *iprobs);
/** Select survivors from the candidate set. */
void pruneCandidates();
/** Find the minimum cost survivor. */
const vCand& minCost() const;
/**
Precompute the state tables.
@param g Generator index 0..((1/rate)-1)
*/
void computeStateTables(unsigned g);
/**
Precompute the generator outputs.
mCoeffs must be defined first.
*/
void computeGeneratorTable();
};
class BitVector : public Vector<char> {
@@ -282,16 +89,6 @@ class BitVector : public Vector<char> {
void zero() { fill(0); }
/**@name FEC operations. */
//@{
/** Calculate the syndrome of the vector with the given Generator. */
uint64_t syndrome(Generator& gen) const;
/** Calculate the parity word for the vector with the given Generator. */
uint64_t parity(Generator& gen) const;
/** Encode the signal with the GSM rate 1/2 convolutional encoder. */
void encode(const ViterbiR2O4& encoder, BitVector& target);
//@}
/** Invert 0<->1. */
void invert();
@@ -427,23 +224,20 @@ class SoftVector: public Vector<float> {
const SoftVector tail(size_t start) const { return segment(start,size()-start); }
//@}
/** Decode soft symbols with the GSM rate-1/2 Viterbi decoder. */
void decode(ViterbiR2O4 &decoder, BitVector& target) const;
// (pat) How good is the SoftVector in the sense of the bits being solid?
// Result of 1 is perfect and 0 means all the bits were 0.5
// How good is the SoftVector in the sense of the bits being solid?
// Result of 1 is perfect and 0 means all the bits were 0.0
// If plow is non-NULL, also return the lowest energy bit.
float getEnergy(float *low=0) const;
/** Fill with "unknown" values. */
void unknown() { fill(0.5F); }
void unknown() { fill(0.0F); }
/** Return a hard bit value from a given index by slicing. */
bool bit(size_t index) const
{
const float *dp = mStart+index;
assert(dp<mEnd);
return (*dp)>0.5F;
return (*dp)>0.0F;
}
/** Slice the whole signal into bits. */

View File

@@ -1,88 +0,0 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 "BitVector.h"
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
BitVector v1("0000111100111100101011110000");
cout << v1 << endl;
v1.LSB8MSB();
cout << v1 << endl;
ViterbiR2O4 vCoder;
BitVector v2(v1.size()*2);
v1.encode(vCoder,v2);
cout << v2 << endl;
SoftVector sv2(v2);
cout << sv2 << endl;
for (unsigned i=0; i<sv2.size()/4; i++) sv2[random()%sv2.size()]=0.5;
cout << sv2 << endl;
BitVector v3(v1.size());
sv2.decode(vCoder,v3);
cout << v3 << endl;
cout << v3.segment(3,4) << endl;
BitVector v4(v3.segment(0,4),v3.segment(8,4));
cout << v4 << endl;
BitVector v5("000011110000");
int r1 = v5.peekField(0,8);
int r2 = v5.peekField(4,4);
int r3 = v5.peekField(4,8);
cout << r1 << ' ' << r2 << ' ' << r3 << endl;
cout << v5 << endl;
v5.fillField(0,0xa,4);
int r4 = v5.peekField(0,8);
cout << v5 << endl;
cout << r4 << endl;
v5.reverse8();
cout << v5 << endl;
BitVector mC = "000000000000111100000000000001110000011100001101000011000000000000000111000011110000100100001010000010100000101000001010000010100000010000000000000000000000000000000000000000000000001100001111000000000000000000000000000000000000000000000000000010010000101000001010000010100000101000001010000001000000000000000000000000110000111100000000000001110000101000001100000001000000000000";
SoftVector mCS(mC);
BitVector mU(mC.size()/2);
mCS.decode(vCoder,mU);
cout << "c=" << mCS << endl;
cout << "u=" << mU << endl;
unsigned char ts[9] = "abcdefgh";
BitVector tp(70);
cout << "ts=" << ts << endl;
tp.unpack(ts);
cout << "tp=" << tp << endl;
tp.pack(ts);
cout << "ts=" << ts << endl;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,422 +0,0 @@
/*
* Copyright 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011, 2012 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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/>.
*/
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#include "sqlite3util.h"
#include <assert.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <regex.h>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <Threads.h>
#include <stdint.h>
/** A class for configuration file errors. */
class ConfigurationTableError {};
extern char gCmdName[]; // Gotta be global, gotta be char*, gotta love it.
/** An exception thrown when a given config key isn't found. */
class ConfigurationTableKeyNotFound : public ConfigurationTableError {
private:
std::string mKey;
public:
ConfigurationTableKeyNotFound(const std::string& wKey)
:mKey(wKey)
{ }
const std::string& key() const { return mKey; }
};
class ConfigurationRecord {
private:
std::string mValue;
long mNumber;
bool mDefined;
public:
ConfigurationRecord(bool wDefined=true):
mDefined(wDefined)
{ }
ConfigurationRecord(const std::string& wValue):
mValue(wValue),
mNumber(strtol(wValue.c_str(),NULL,0)),
mDefined(true)
{ }
ConfigurationRecord(const char* wValue):
mValue(std::string(wValue)),
mNumber(strtol(wValue,NULL,0)),
mDefined(true)
{ }
const std::string& value() const { return mValue; }
long number() const { return mNumber; }
bool defined() const { return mDefined; }
float floatNumber() const;
};
/** A string class that uses a hash function for comparison. */
class HashString : public std::string {
protected:
uint64_t mHash;
void computeHash();
public:
HashString(const char* src)
:std::string(src)
{
computeHash();
}
HashString(const std::string& src)
:std::string(src)
{
computeHash();
}
HashString()
{
mHash=0;
}
HashString& operator=(std::string& src)
{
std::string::operator=(src);
computeHash();
return *this;
}
HashString& operator=(const char* src)
{
std::string::operator=(src);
computeHash();
return *this;
}
bool operator==(const HashString& other)
{
return mHash==other.mHash;
}
bool operator<(const HashString& other)
{
return mHash<other.mHash;
}
bool operator>(const HashString& other)
{
return mHash<other.mHash;
}
uint64_t hash() const { return mHash; }
};
typedef std::map<std::string, ConfigurationRecord> ConfigurationRecordMap;
typedef std::map<HashString, ConfigurationRecord> ConfigurationMap;
class ConfigurationKey;
typedef std::map<std::string, ConfigurationKey> ConfigurationKeyMap;
/**
A class for maintaining a configuration key-value table,
based on sqlite3 and a local map-based cache.
Thread-safe, too.
*/
class ConfigurationTable {
private:
sqlite3* mDB; ///< database connection
ConfigurationMap mCache; ///< cache of recently access configuration values
mutable Mutex mLock; ///< control for multithreaded access to the cache
std::vector<std::string> (*mCrossCheck)(const std::string&); ///< cross check callback pointer
public:
ConfigurationKeyMap mSchema;///< definition of configuration default values and validation logic
ConfigurationTable(const char* filename = ":memory:", const char *wCmdName = 0, ConfigurationKeyMap wSchema = ConfigurationKeyMap());
/** Generate an up-to-date example sql file for new installs. */
std::string getDefaultSQL(const std::string& program, const std::string& version);
/** Generate an up-to-date TeX snippet. */
std::string getTeX(const std::string& program, const std::string& version);
/** Return true if the key is used in the table. */
bool defines(const std::string& key);
/** Return true if the application's schema knows about this key. */
bool keyDefinedInSchema(const std::string& name);
/** Return true if the provided value validates correctly against the defined schema. */
bool isValidValue(const std::string& name, const std::string& val);
/** Return true if the provided value validates correctly against the defined schema. */
bool isValidValue(const std::string& name, const int val) { std::stringstream ss; ss << val; return isValidValue(name, ss.str()); }
/** Return a map of all similar keys in the defined schema. */
ConfigurationKeyMap getSimilarKeys(const std::string& snippet);
/** Return true if this key is identified as static. */
bool isStatic(const std::string& key);
/**
Get a string parameter from the table.
Throw ConfigurationTableKeyNotFound if not found.
*/
std::string getStr(const std::string& key);
/**
Get a boolean from the table.
Return false if NULL or 0, true otherwise.
*/
bool getBool(const std::string& key);
/**
Get a numeric parameter from the table.
Throw ConfigurationTableKeyNotFound if not found.
*/
long getNum(const std::string& key);
/**
Get a vector of strings from the table.
*/
std::vector<std::string> getVectorOfStrings(const std::string& key);
/**
Get a float from the table.
Throw ConfigurationTableKeyNotFound if not found.
*/
float getFloat(const std::string& key);
/**
Get a numeric vector from the table.
*/
std::vector<unsigned> getVector(const std::string& key);
/** Get length of a vector */
unsigned getVectorLength(const std::string &key)
{ return getVector(key).size(); }
/** Set or change a value in the table. */
bool set(const std::string& key, const std::string& value);
/** Set or change a value in the table. */
bool set(const std::string& key, long value);
/** Create an entry in the table, no value though. */
bool set(const std::string& key);
/**
Remove an entry from the table.
Will not alter required values.
@param key The key of the item to be removed.
@return true if anything was actually removed.
*/
bool remove(const std::string& key);
/** Search the table, dumping to a stream. */
void find(const std::string& pattern, std::ostream&) const;
/** Return all key/value pairs stored in the ConfigurationTable */
ConfigurationRecordMap getAllPairs() const;
/** Define the callback to purge the cache whenever the database changes. */
void setUpdateHook(void(*)(void *,int ,char const *,char const *,sqlite3_int64));
/** Define the callback for cross checking. */
void setCrossCheckHook(std::vector<std::string> (*wCrossCheck)(const std::string&));
/** Execute the application specific value cross checking logic. */
std::vector<std::string> crossCheck(const std::string& key);
/** purege cache if it exceeds a certain age */
void checkCacheAge();
/** Delete all records from the cache. */
void purge();
private:
/**
Attempt to lookup a record, cache if needed.
Throw ConfigurationTableKeyNotFound if not found.
Caller should hold mLock because the returned reference points into the cache.
*/
const ConfigurationRecord& lookup(const std::string& key);
};
typedef std::map<HashString, std::string> HashStringMap;
class SimpleKeyValue {
protected:
HashStringMap mMap;
public:
/** Take a C string "A=B" and set map["A"]="B". */
void addItem(const char*);
/** Take a C string "A=B C=D E=F ..." and add all of the pairs to the map. */
void addItems(const char*s);
/** Return a reference to the string at map["key"]. */
const char* get(const char*) const;
};
class ConfigurationKey {
public:
enum VisibilityLevel
{
CUSTOMER,
CUSTOMERSITE,
CUSTOMERTUNE,
CUSTOMERWARN,
DEVELOPER,
FACTORY
};
enum Type
{
BOOLEAN,
CHOICE_OPT,
CHOICE,
CIDR_OPT,
CIDR,
FILEPATH_OPT,
FILEPATH,
IPADDRESS_OPT,
IPADDRESS,
IPANDPORT,
MIPADDRESS_OPT,
MIPADDRESS,
PORT_OPT,
PORT,
REGEX_OPT,
REGEX,
STRING_OPT,
STRING,
VALRANGE
};
private:
std::string mName;
std::string mDefaultValue;
std::string mUnits;
VisibilityLevel mVisibility;
Type mType;
std::string mValidValues;
bool mIsStatic;
std::string mDescription;
public:
ConfigurationKey(const std::string& wName, const std::string& wDefaultValue, const std::string& wUnits, const VisibilityLevel wVisibility, const Type wType, const std::string& wValidValues, bool wIsStatic, const std::string& wDescription):
mName(wName),
mDefaultValue(wDefaultValue),
mUnits(wUnits),
mVisibility(wVisibility),
mType(wType),
mValidValues(wValidValues),
mIsStatic(wIsStatic),
mDescription(wDescription)
{ }
ConfigurationKey()
{ }
const std::string& getName() const { return mName; }
const std::string& getDefaultValue() const { return mDefaultValue; }
void updateDefaultValue(const std::string& newValue) { mDefaultValue = newValue; }
void updateDefaultValue(const int newValue) { std::stringstream ss; ss << newValue; updateDefaultValue(ss.str()); }
const std::string& getUnits() const { return mUnits; }
const VisibilityLevel& getVisibility() const { return mVisibility; }
const Type& getType() const { return mType; }
const std::string& getValidValues() const { return mValidValues; }
bool isStatic() const { return mIsStatic; }
const std::string& getDescription() const { return mDescription; }
static bool isValidIP(const std::string& ip);
static void getMinMaxStepping(const ConfigurationKey &key, std::string &min, std::string &max, std::string &stepping);
template<class T> static bool isInValRange(const ConfigurationKey &key, const std::string& val, const bool isInteger);
static const std::string visibilityLevelToString(const VisibilityLevel& visibility);
static const std::string typeToString(const ConfigurationKey::Type& type);
static void printKey(const ConfigurationKey &key, const std::string& currentValue, std::ostream& os);
static void printDescription(const ConfigurationKey &key, std::ostream& os);
static const std::string getARFCNsString();
};
#endif
// vim: ts=4 sw=4

View File

@@ -1,149 +0,0 @@
/*
* Copyright 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 "Configuration.h"
#include <iostream>
#include <string>
using namespace std;
ConfigurationKeyMap getConfigurationKeys();
ConfigurationTable gConfig("exampleconfig.db","test", getConfigurationKeys());
void purgeConfig(void*,int,char const*, char const*, sqlite3_int64)
{
//cout << "update hook" << endl;
gConfig.purge();
}
int main(int argc, char *argv[])
{
gConfig.setUpdateHook(purgeConfig);
char *keys[5] = {"key1", "key2", "key3", "key4", "key5"};
for (int i=0; i<5; i++) {
gConfig.set(keys[i],i);
}
for (int i=0; i<5; i++) {
cout << "table[" << keys[i] << "]=" << gConfig.getStr(keys[i]) << endl;
cout << "table[" << keys[i] << "]=" << gConfig.getNum(keys[i]) << endl;
}
for (int i=0; i<5; i++) {
cout << "defined table[" << keys[i] << "]=" << gConfig.defines(keys[i]) << endl;
}
gConfig.set("key5","100 200 300 400 ");
std::vector<unsigned> vect = gConfig.getVector("key5");
cout << "vect length " << vect.size() << ": ";
for (unsigned i=0; i<vect.size(); i++) cout << " " << vect[i];
cout << endl;
std::vector<string> svect = gConfig.getVectorOfStrings("key5");
cout << "vect length " << svect.size() << ": ";
for (unsigned i=0; i<svect.size(); i++) cout << " " << svect[i] << ":";
cout << endl;
cout << "bool " << gConfig.getBool("booltest") << endl;
gConfig.set("booltest",1);
cout << "bool " << gConfig.getBool("booltest") << endl;
gConfig.set("booltest",0);
cout << "bool " << gConfig.getBool("booltest") << endl;
gConfig.getStr("newstring");
gConfig.getNum("numnumber");
SimpleKeyValue pairs;
pairs.addItems(" a=1 b=34 dd=143 ");
cout<< pairs.get("a") << endl;
cout<< pairs.get("b") << endl;
cout<< pairs.get("dd") << endl;
gConfig.set("fkey","123.456");
float fval = gConfig.getFloat("fkey");
cout << "fkey " << fval << endl;
cout << "search fkey:" << endl;
gConfig.find("fkey",cout);
cout << "search fkey:" << endl;
gConfig.find("fkey",cout);
gConfig.remove("fkey");
cout << "search fkey:" << endl;
gConfig.find("fkey",cout);
try {
gConfig.getNum("supposedtoabort");
} catch (ConfigurationTableKeyNotFound) {
cout << "ConfigurationTableKeyNotFound exception successfully caught." << endl;
}
}
ConfigurationKeyMap getConfigurationKeys()
{
ConfigurationKeyMap map;
ConfigurationKey *tmp;
tmp = new ConfigurationKey("booltest","0",
"",
ConfigurationKey::DEVELOPER,
ConfigurationKey::BOOLEAN,
"",
false,
""
);
map[tmp->getName()] = *tmp;
free(tmp);
tmp = new ConfigurationKey("numnumber","42",
"",
ConfigurationKey::DEVELOPER,
ConfigurationKey::VALRANGE,
"0-100",
false,
""
);
map[tmp->getName()] = *tmp;
free(tmp);
tmp = new ConfigurationKey("newstring","new string value",
"",
ConfigurationKey::DEVELOPER,
ConfigurationKey::STRING,
"",
false,
""
);
map[tmp->getName()] = *tmp;
free(tmp);
return map;
}

View File

@@ -1,210 +0,0 @@
/*
* Copyright 2009 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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/>.
*/
#ifndef F16_H
#define F16_H
#include <stdint.h>
#include <ostream>
/** Round a float to the appropriate F16 value. */
inline int32_t _f16_round(float f)
{
if (f>0.0F) return (int32_t)(f+0.5F);
if (f<0.0F) return (int32_t)(f-0.5F);
return 0;
}
/** A class for F15.16 fixed point arithmetic with saturation. */
class F16 {
private:
int32_t mV;
public:
F16() {}
F16(int i) { mV = i<<16; }
F16(float f) { mV = _f16_round(f*65536.0F); }
F16(double f) { mV = _f16_round((float)f*65536.0F); }
int32_t& raw() { return mV; }
const int32_t& raw() const { return mV; }
float f() const { return mV/65536.0F; }
//operator float() const { return mV/65536.0F; }
//operator int() const { return mV>>16; }
F16 operator=(float f)
{
mV = _f16_round(f*65536.0F);
return *this;
}
F16 operator=(int i)
{
mV = i<<16;
return *this;
}
F16 operator=(const F16& other)
{
mV = other.mV;
return mV;
}
F16 operator+(const F16& other) const
{
F16 retVal;
retVal.mV = mV + other.mV;
return retVal;
}
F16& operator+=(const F16& other)
{
mV += other.mV;
return *this;
}
F16 operator-(const F16& other) const
{
F16 retVal;
retVal.mV = mV - other.mV;
return retVal;
}
F16& operator-=(const F16& other)
{
mV -= other.mV;
return *this;
}
F16 operator*(const F16& other) const
{
F16 retVal;
int64_t p = (int64_t)mV * (int64_t)other.mV;
retVal.mV = p>>16;
return retVal;
}
F16& operator*=(const F16& other)
{
int64_t p = (int64_t)mV * (int64_t)other.mV;
mV = p>>16;
return *this;
}
F16 operator*(float f) const
{
F16 retVal;
retVal.mV = mV * f;
return retVal;
}
F16& operator*=(float f)
{
mV *= f;
return *this;
}
F16 operator/(const F16& other) const
{
F16 retVal;
int64_t pV = (int64_t)mV << 16;
retVal.mV = pV / other.mV;
return retVal;
}
F16& operator/=(const F16& other)
{
int64_t pV = (int64_t)mV << 16;
mV = pV / other.mV;
return *this;
}
F16 operator/(float f) const
{
F16 retVal;
retVal.mV = mV / f;
return retVal;
}
F16& operator/=(float f)
{
mV /= f;
return *this;
}
bool operator>(const F16& other) const
{
return mV>other.mV;
}
bool operator<(const F16& other) const
{
return mV<other.mV;
}
bool operator==(const F16& other) const
{
return mV==other.mV;
}
bool operator>(float f) const
{
return (mV/65536.0F) > f;
}
bool operator<(float f) const
{
return (mV/65536.0F) < f;
}
bool operator==(float f) const
{
return (mV/65536.0F) == f;
}
};
inline std::ostream& operator<<(std::ostream& os, const F16& v)
{
os << v.f();
return os;
}
#endif

View File

@@ -1,55 +0,0 @@
/*
* Copyright 2009 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 "F16.h"
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
F16 a = 2.5;
F16 b = 1.5;
F16 c = 2.5 * 1.5;
F16 d = c + a;
F16 e = 10;
cout << a << ' ' << b << ' ' << c << ' ' << d << ' ' << e << endl;
a *= 3;
b *= 0.3;
c *= e;
cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
a /= 3;
b /= 0.3;
c = d * 0.05;
cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
F16 f = a/d;
cout << f << ' ' << f+0.5 << endl;
}

View File

@@ -1,6 +1,8 @@
/*
* Copyright 2008, 2011 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -45,7 +47,7 @@
// (pat) The elements in the queue are type T*, and
// the Fifo class implements the underlying queue.
// The default is class PointerFIFO, which does not place any restrictions on the type of T,
// and is implemented by allocating auxilliary structures for the queue,
// and is implemented by allocating auxiliary structures for the queue,
// or SingleLinkedList, which implements the queue using an internal pointer in type T,
// which must implement the functional interface of class SingleLinkListNode,
// namely: functions T*next() and void setNext(T*).
@@ -53,7 +55,7 @@ template <class T, class Fifo=PointerFIFO> class InterthreadQueue {
protected:
Fifo mQ;
Fifo mQ;
mutable Mutex mLock;
mutable Signal mWriteSignal;
@@ -160,7 +162,7 @@ template <class T, class Fifo=PointerFIFO> class InterthreadQueue2 {
protected:
Fifo mQ;
Fifo mQ;
mutable Mutex mLock;
mutable Signal mWriteSignal;
@@ -256,7 +258,7 @@ template <class T, class Fifo=PointerFIFO> class InterthreadQueue2 {
// This recurs (and the InterthreadQueue fills up with data)
// until the read thread's accumulated temporary priority causes it to
// get a second pre-emptive activation over the writing thread,
// resulting in bursts of activity by the read thread.
// resulting in bursts of activity by the read thread.
{ ScopedLock lock(mLock);
mQ.put(val);
}
@@ -281,7 +283,7 @@ template <class T> class InterthreadQueueWithWait {
protected:
PointerFIFO mQ;
PointerFIFO mQ;
mutable Mutex mLock;
mutable Signal mWriteSignal;
mutable Signal mReadSignal;

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@@ -29,6 +30,25 @@
#include "LinkedLists.h"
PointerFIFO::~PointerFIFO()
{
ListNode *node, *next;
node = mHead;
while (node != NULL) {
next = node->next();
delete node;
node = next;
}
node = mFreeList;
while (node != NULL) {
next = node->next();
delete node;
node = next;
}
}
void PointerFIFO::push_front(void* val) // by pat
{
// Pat added this routine for completeness, but never used or tested.

View File

@@ -1,7 +1,10 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under multiple licenses; see the COPYING file in
* the main directory for licensing information for this specific distribution.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@@ -70,6 +73,7 @@ class PointerFIFO {
:mHead(NULL),mTail(NULL),mFreeList(NULL),
mSize(0)
{}
~PointerFIFO();
unsigned size() const { return mSize; }
unsigned totalSize() const { return 0; } // Not used in this version.

View File

@@ -1,69 +0,0 @@
/*
* Copyright 2009 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 <iostream>
#include <iterator>
#include "Logger.h"
#include "Configuration.h"
ConfigurationTable gConfig;
//ConfigurationTable gConfig("example.config");
void printAlarms()
{
std::ostream_iterator<std::string> output( std::cout, "\n" );
std::list<std::string> alarms = gGetLoggerAlarms();
std::cout << "# alarms = " << alarms.size() << std::endl;
std::copy( alarms.begin(), alarms.end(), output );
}
int main(int argc, char *argv[])
{
gLogInit("LogTest","NOTICE",LOG_LOCAL7);
LOG(EMERG) << " testing the logger.";
LOG(ALERT) << " testing the logger.";
LOG(CRIT) << " testing the logger.";
LOG(ERR) << " testing the logger.";
LOG(WARNING) << " testing the logger.";
LOG(NOTICE) << " testing the logger.";
LOG(INFO) << " testing the logger.";
LOG(DEBUG) << " testing the logger.";
std::cout << "\n\n\n";
std::cout << "testing Alarms\n";
std::cout << "you should see three lines:" << std::endl;
printAlarms();
std::cout << "----------- generating 20 alarms ----------" << std::endl;
for (int i = 0 ; i < 20 ; ++i) {
LOG(ALERT) << i;
}
std::cout << "you should see ten lines with the numbers 10..19:" << std::endl;
printAlarms();
}

View File

@@ -1,8 +1,7 @@
/*
* Copyright 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011, 2012 Range Networks, Inc.
* Copyright (C) 2018 sysmocom - s.f.m.c. GmbH
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@@ -30,276 +29,35 @@
#include <fstream>
#include <string>
#include <stdarg.h>
#include <sys/time.h> // For gettimeofday
#include "Configuration.h"
#include "Logger.h"
#include "Threads.h" // pat added
using namespace std;
// Switches to enable/disable logging targets
// MUST BE DEFINED BEFORE gConfig FOR gLogEarly() TO WORK CORRECTLY
bool gLogToConsole = true;
bool gLogToSyslog = false;
FILE *gLogToFile = NULL;
Mutex gLogToLock;
// Reference to a global config table, used all over the system.
extern ConfigurationTable gConfig;
/**@ The global alarms table. */
//@{
Mutex alarmsLock;
list<string> alarmsList;
void addAlarm(const string&);
//@}
// (pat) If Log messages are printed before the classes in this module are inited
// (which happens when static classes have constructors that do work)
// the OpenBTS just crashes.
// Prevent that by setting sLoggerInited to true when this module is inited.
static bool sLoggerInited = 0;
static struct CheckLoggerInitStatus {
CheckLoggerInitStatus() { sLoggerInited = 1; }
} sCheckloggerInitStatus;
/** Names of the logging levels. */
const char *levelNames[] = {
"EMERG", "ALERT", "CRIT", "ERR", "WARNING", "NOTICE", "INFO", "DEBUG"
};
int numLevels = 8;
int levelStringToInt(const string& name)
std::ostream& operator<<(std::ostream& os, std::ostringstream& ss)
{
// Reverse search, since the numerically larger levels are more common.
for (int i=numLevels-1; i>=0; i--) {
if (name == levelNames[i]) return i;
}
// Common substitutions.
if (name=="INFORMATION") return 6;
if (name=="WARN") return 4;
if (name=="ERROR") return 3;
if (name=="CRITICAL") return 2;
if (name=="EMERGENCY") return 0;
// Unknown level.
return -1;
return os << ss.str();
}
/** Given a string, return the corresponding level name. */
int lookupLevel(const string& key)
{
string val = gConfig.getStr(key);
int level = levelStringToInt(val);
if (level == -1) {
string defaultLevel = gConfig.mSchema["Log.Level"].getDefaultValue();
level = levelStringToInt(defaultLevel);
_LOG(CRIT) << "undefined logging level (" << key << " = \"" << val << "\") defaulting to \"" << defaultLevel << ".\" Valid levels are: EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO or DEBUG";
gConfig.set(key, defaultLevel);
}
return level;
}
int getLoggingLevel(const char* filename)
{
// Default level?
if (!filename) return lookupLevel("Log.Level");
// This can afford to be inefficient since it is not called that often.
const string keyName = string("Log.Level.") + string(filename);
if (gConfig.defines(keyName)) return lookupLevel(keyName);
return lookupLevel("Log.Level");
}
int gGetLoggingLevel(const char* filename)
{
// This is called a lot and needs to be efficient.
static Mutex sLogCacheLock;
static map<uint64_t,int> sLogCache;
static unsigned sCacheCount;
static const unsigned sCacheRefreshCount = 1000;
if (filename==NULL) return gGetLoggingLevel("");
HashString hs(filename);
uint64_t key = hs.hash();
sLogCacheLock.lock();
// Time for a cache flush?
if (sCacheCount>sCacheRefreshCount) {
sLogCache.clear();
sCacheCount=0;
}
// Is it cached already?
map<uint64_t,int>::const_iterator where = sLogCache.find(key);
sCacheCount++;
if (where!=sLogCache.end()) {
int retVal = where->second;
sLogCacheLock.unlock();
return retVal;
}
// Look it up in the config table and cache it.
// FIXME: Figure out why unlock and lock below fix the config table deadlock.
// (pat) Probably because getLoggingLevel may call LOG recursively via lookupLevel().
sLogCacheLock.unlock();
int level = getLoggingLevel(filename);
sLogCacheLock.lock();
sLogCache.insert(pair<uint64_t,int>(key,level));
sLogCacheLock.unlock();
return level;
}
// copies the alarm list and returns it. list supposed to be small.
list<string> gGetLoggerAlarms()
{
alarmsLock.lock();
list<string> ret;
// excuse the "complexity", but to use std::copy with a list you need
// an insert_iterator - copy technically overwrites, doesn't insert.
insert_iterator< list<string> > ii(ret, ret.begin());
copy(alarmsList.begin(), alarmsList.end(), ii);
alarmsLock.unlock();
return ret;
}
/** Add an alarm to the alarm list. */
void addAlarm(const string& s)
{
alarmsLock.lock();
alarmsList.push_back(s);
unsigned maxAlarms = gConfig.getNum("Log.Alarms.Max");
while (alarmsList.size() > maxAlarms) alarmsList.pop_front();
alarmsLock.unlock();
}
Log::~Log()
{
if (mDummyInit) return;
// Anything at or above LOG_CRIT is an "alarm".
// Save alarms in the local list and echo them to stderr.
if (mPriority <= LOG_ERR) {
if (sLoggerInited) addAlarm(mStream.str().c_str());
cerr << mStream.str() << endl;
}
// Current logging level was already checked by the macro. So just log.
// Log to syslog
if (gLogToSyslog) {
syslog(mPriority, "%s", mStream.str().c_str());
}
// Log to file and console
if (gLogToConsole||gLogToFile) {
int mlen = mStream.str().size();
int neednl = (mlen==0 || mStream.str()[mlen-1] != '\n');
ScopedLock lock(gLogToLock);
if (gLogToConsole) {
// The COUT() macro prevents messages from stomping each other but adds uninteresting thread numbers,
// so just use std::cout.
std::cout << mStream.str();
if (neednl) std::cout<<"\n";
}
if (gLogToFile) {
fputs(mStream.str().c_str(),gLogToFile);
if (neednl) {fputc('\n',gLogToFile);}
fflush(gLogToFile);
}
}
int old_state;
int mlen = mStream.str().size();
int neednl = (mlen==0 || mStream.str()[mlen-1] != '\n');
const char *fmt = neednl ? "%s\n" : "%s";
/* print related function called inside a C++ destructor, use pthread_setcancelstate() APIs.
See osmo-trx commit 86be40b4eb762d5c12e8e3f7388ca9f254e77b36 for more information */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
LOGPSRC(mCategory, mPriority, filename, line, fmt, mStream.str().c_str());
pthread_setcancelstate(old_state, NULL);
}
Log::Log(const char* name, const char* level, int facility)
{
mDummyInit = true;
gLogInit(name, level, facility);
}
ostringstream& Log::get()
{
assert(mPriority<numLevels);
mStream << levelNames[mPriority] << ' ';
return mStream;
}
void gLogInit(const char* name, const char* level, int facility)
{
// Set the level if one has been specified.
if (level) {
gConfig.set("Log.Level",level);
}
// Both the transceiver and OpenBTS use this same facility, but only OpenBTS/OpenNodeB may use this log file:
string str = gConfig.getStr("Log.File");
if (gLogToFile==NULL && str.length() && 0==strncmp(gCmdName,"Open",4)) {
const char *fn = str.c_str();
if (fn && *fn && strlen(fn)>3) { // strlen because a garbage char is getting in sometimes.
gLogToFile = fopen(fn,"w"); // New log file each time we start.
if (gLogToFile) {
time_t now;
time(&now);
fprintf(gLogToFile,"Starting at %s",ctime(&now));
fflush(gLogToFile);
std::cout << "Logging to file: " << fn << "\n";
}
}
}
// Open the log connection.
openlog(name,0,facility);
}
void gLogEarly(int level, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (gLogToSyslog) {
va_list args_copy;
va_copy(args_copy, args);
vsyslog(level | LOG_USER, fmt, args_copy);
va_end(args_copy);
}
if (gLogToConsole) {
va_list args_copy;
va_copy(args_copy, args);
vprintf(fmt, args_copy);
printf("\n");
va_end(args_copy);
}
if (gLogToFile) {
va_list args_copy;
va_copy(args_copy, args);
vfprintf(gLogToFile, fmt, args_copy);
fprintf(gLogToFile, "\n");
va_end(args_copy);
}
va_end(args);
}
// vim: ts=4 sw=4

View File

@@ -2,6 +2,8 @@
* Copyright 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -23,72 +25,47 @@
*/
// (pat) WARNING is stupidly defined in /usr/local/include/osipparser2/osip_const.h.
// This must be outside the #ifndef LOGGER_H to fix it as long as Logger.h included after the above file.
#ifdef WARNING
#undef WARNING
#endif
#ifndef LOGGER_H
#define LOGGER_H
#include <syslog.h>
#include <stdint.h>
#include <stdio.h>
#include <sstream>
#include <list>
#include <map>
#include <string>
#define _LOG(level) \
Log(LOG_##level).get() << pthread_self() \
<< timestr() << " " __FILE__ ":" << __LINE__ << ":" << __FUNCTION__ << ": "
extern "C" {
#include <osmocom/core/logging.h>
#include "debug.h"
}
#define IS_LOG_LEVEL(wLevel) (gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
#ifdef NDEBUG
#define LOG(wLevel) \
if (LOG_##wLevel!=LOG_DEBUG && IS_LOG_LEVEL(wLevel)) _LOG(wLevel)
#else
#define LOG(wLevel) \
if (IS_LOG_LEVEL(wLevel)) _LOG(wLevel)
/* Translation for old log statements */
#ifndef LOGL_ALERT
#define LOGL_ALERT LOGL_FATAL
#endif
#ifndef LOGL_ERR
#define LOGL_ERR LOGL_ERROR
#endif
#ifndef LOGL_WARNING
#define LOGL_WARNING LOGL_NOTICE
#endif
// pat: And for your edification here are the 'levels' as defined in syslog.h:
// LOG_EMERG 0 system is unusable
// LOG_ALERT 1 action must be taken immediately
// LOG_CRIT 2 critical conditions
// LOG_ERR 3 error conditions
// LOG_WARNING 4 warning conditions
// LOG_NOTICE 5 normal, but significant, condition
// LOG_INFO 6 informational message
// LOG_DEBUG 7 debug-level message
#define LOG(level) \
Log(DMAIN, LOGL_##level, __BASE_FILE__, __LINE__).get()
// (pat) added - print out a var and its name.
// Use like this: int descriptive_name; LOG(INFO)<<LOGVAR(descriptive_name);
#define LOGVAR2(name,val) " " << name << "=" << (val)
#define LOGVAR(var) (" " #var "=") << var
#define LOGHEX(var) (" " #var "=0x") << hex << ((unsigned)var) << dec
#define LOGHEX2(name,val) " " << name << "=0x" << hex << ((unsigned)(val)) << dec
// These are kind of cheesy, but you can use for bitvector
#define LOGBV2(name,val) " " << name << "=(" << val<<" size:"<<val.size()<<")"
#define LOGBV(bv) LOGBV2(#bv,bv)
#define LOGVARRANGE(name,cur,lo,hi) " "<<name <<"=("<<(cur) << " range:"<<(lo) << " to "<<(hi) <<")"
#define LOGC(category, level) \
Log(category, LOGL_##level, __BASE_FILE__, __LINE__).get()
#define LOGLV(category, level) \
Log(category, level, __BASE_FILE__, __LINE__).get()
#define OBJLOG(wLevel) \
LOG(wLevel) << "obj: " << this << ' '
#define LOGSRC(category, level, file, line) \
Log(category, level, file, line).get()
#define LOG_ASSERT(x) { if (!(x)) LOG(EMERG) << "assertion " #x " failed"; } assert(x);
#include "Threads.h" // must be after defines above, if these files are to be allowed to use LOG()
#include "Utils.h"
#define LOGCHAN(chan, category, level) \
Log(category, LOGL_##level, __BASE_FILE__, __LINE__).get() << "[chan=" << chan << "] "
/**
A C++ stream-based thread-safe logger.
Derived from Dr. Dobb's Sept. 2007 issue.
Updated to use syslog.
This object is NOT the global logger;
every log record is an object of this class.
*/
@@ -98,42 +75,27 @@ class Log {
protected:
std::ostringstream mStream; ///< This is where we buffer up the log entry.
int mPriority; ///< Priority of current report.
bool mDummyInit;
std::ostringstream mStream; ///< This is where we buffer up the log entry.
int mCategory; ///< Priority of current report.
int mPriority; ///< Category of current report.
const char *filename; ///< Source File Name of current report.
int line; ///< Line number in source file of current report.
public:
Log(int wPriority)
:mPriority(wPriority), mDummyInit(false)
Log(int wCategory, int wPriority, const char* filename, int line)
: mCategory(wCategory), mPriority(wPriority),
filename(filename), line(line)
{ }
Log(const char* name, const char* level=NULL, int facility=LOG_USER);
// Most of the work is in the destructor.
/** The destructor actually generates the log entry. */
~Log();
std::ostringstream& get();
};
extern bool gLogToConsole; // Output log messages to stdout
extern bool gLogToSyslog; // Output log messages to syslog
std::list<std::string> gGetLoggerAlarms(); ///< Get a copy of the recent alarm list.
/**@ Global control and initialization of the logging system. */
//@{
/** Initialize the global logging system. */
void gLogInit(const char* name, const char* level=NULL, int facility=LOG_USER);
/** Get the logging level associated with a given file. */
int gGetLoggingLevel(const char *filename=NULL);
/** Allow early logging when still in constructors */
void gLogEarly(int level, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
//@}
std::ostream& operator<<(std::ostream& os, std::ostringstream& ss);
#endif

View File

@@ -22,92 +22,35 @@
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread
EXTRA_DIST = \
example.config \
README.common
AM_CXXFLAGS = -Wall -O3 -g -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS)
AM_CFLAGS = $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS)
noinst_LTLIBRARIES = libcommon.la
libcommon_la_SOURCES = \
BitVector.cpp \
LinkedLists.cpp \
Sockets.cpp \
Threads.cpp \
Timeval.cpp \
Reporting.cpp \
Logger.cpp \
Configuration.cpp \
sqlite3util.cpp \
URLEncode.cpp \
Utils.cpp
noinst_PROGRAMS = \
BitVectorTest \
InterthreadTest \
SocketsTest \
TimevalTest \
RegexpTest \
VectorTest \
ConfigurationTest \
LogTest \
URLEncodeTest \
F16Test
# ReportingTest
Utils.cpp \
trx_rate_ctr.cpp \
trx_vty.c \
debug.c
libcommon_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBOSMOVTY_LIBS)
noinst_HEADERS = \
BitVector.h \
PRBS.h \
Interthread.h \
LinkedLists.h \
Sockets.h \
Threads.h \
Timeval.h \
Regexp.h \
Vector.h \
Configuration.h \
Reporting.h \
F16.h \
URLEncode.h \
Utils.h \
Logger.h \
sqlite3util.h
URLEncodeTest_SOURCES = URLEncodeTest.cpp
URLEncodeTest_LDADD = libcommon.la
BitVectorTest_SOURCES = BitVectorTest.cpp
BitVectorTest_LDADD = libcommon.la $(SQLITE_LA)
InterthreadTest_SOURCES = InterthreadTest.cpp
InterthreadTest_LDADD = libcommon.la
InterthreadTest_LDFLAGS = -lpthread
SocketsTest_SOURCES = SocketsTest.cpp
SocketsTest_LDADD = libcommon.la
SocketsTest_LDFLAGS = -lpthread
TimevalTest_SOURCES = TimevalTest.cpp
TimevalTest_LDADD = libcommon.la
VectorTest_SOURCES = VectorTest.cpp
VectorTest_LDADD = libcommon.la $(SQLITE_LA)
RegexpTest_SOURCES = RegexpTest.cpp
RegexpTest_LDADD = libcommon.la
ConfigurationTest_SOURCES = ConfigurationTest.cpp
ConfigurationTest_LDADD = libcommon.la $(SQLITE_LA)
# ReportingTest_SOURCES = ReportingTest.cpp
# ReportingTest_LDADD = libcommon.la $(SQLITE_LA)
LogTest_SOURCES = LogTest.cpp
LogTest_LDADD = libcommon.la $(SQLITE_LA)
F16Test_SOURCES = F16Test.cpp
MOSTLYCLEANFILES += testSource testDestination
Utils.h \
trx_rate_ctr.h \
trx_vty.h \
debug.h \
osmo_signal.h \
config_defs.h

View File

@@ -1,111 +0,0 @@
/*
* Copyright 2011 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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.
*/
#ifndef _MEMORYLEAK_
#define _MEMORYLEAK_ 1
#include <map>
#include "ScalarTypes.h"
#include "Logger.h"
namespace Utils {
struct MemStats {
// Enumerates the classes that are checked.
// Redundancies are ok, for example, we check BitVector and also
// several descendants of BitVector.
enum MemoryNames {
mZeroIsUnused,
mVector,
mVectorData,
mBitVector,
mByteVector,
mByteVectorData,
mRLCRawBlock,
mRLCUplinkDataBlock,
mRLCMessage,
mRLCMsgPacketDownlinkDummyControlBlock, // Redundant with RLCMessage
mTBF,
mLlcEngine,
mSgsnDownlinkMsg,
mRachInfo,
mPdpPdu,
mFECDispatchInfo,
mL3Frame,
msignalVector,
mSoftVector,
mScramblingCode,
mURlcDownSdu,
mURlcPdu,
// Must be last:
mMax,
};
int mMemTotal[mMax]; // In elements, not bytes.
int mMemNow[mMax];
const char *mMemName[mMax];
MemStats();
void memChkNew(MemoryNames memIndex, const char *id);
void memChkDel(MemoryNames memIndex, const char *id);
void text(std::ostream &os);
// We would prefer to use an unordered_map, but that requires special compile switches.
// What a super great language.
typedef std::map<std::string,Int_z> MemMapType;
MemMapType mMemMap;
};
extern struct MemStats gMemStats;
extern int gMemLeakDebug;
// This is a memory leak detector.
// Use by putting RN_MEMCHKNEW and RN_MEMCHKDEL in class constructors/destructors,
// or use the DEFINE_MEMORY_LEAK_DETECTOR class and add the defined class
// as an ancestor to the class to be memory leak checked.
struct MemLabel {
std::string mccKey;
virtual ~MemLabel() {
Int_z &tmp = Utils::gMemStats.mMemMap[mccKey]; tmp = tmp - 1;
}
};
#if RN_DISABLE_MEMORY_LEAK_TEST
#define RN_MEMCHKNEW(type)
#define RN_MEMCHKDEL(type)
#define RN_MEMLOG(type,ptr)
#define DEFINE_MEMORY_LEAK_DETECTOR_CLASS(subClass,checkerClass) \
struct checkerClass {};
#else
#define RN_MEMCHKNEW(type) { Utils::gMemStats.memChkNew(Utils::MemStats::m##type,#type); }
#define RN_MEMCHKDEL(type) { Utils::gMemStats.memChkDel(Utils::MemStats::m##type,#type); }
#define RN_MEMLOG(type,ptr) { \
static std::string key = format("%s_%s:%d",#type,__FILE__,__LINE__); \
(ptr)->/* MemCheck##type:: */ mccKey = key; \
Utils::gMemStats.mMemMap[key]++; \
}
// TODO: The above assumes that checkclass is MemCheck ## subClass
#define DEFINE_MEMORY_LEAK_DETECTOR_CLASS(subClass,checkerClass) \
struct checkerClass : public virtual Utils::MemLabel { \
checkerClass() { RN_MEMCHKNEW(subClass); } \
virtual ~checkerClass() { \
RN_MEMCHKDEL(subClass); \
} \
};
#endif
} // namespace Utils
#endif

108
CommonLibs/PRBS.h Normal file
View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#ifndef PRBS_H
#define PRBS_H
#include <stdint.h>
#include <assert.h>
/** Pseudo-random binary sequence (PRBS) generator (a Galois LFSR implementation). */
class PRBS {
public:
PRBS(unsigned wLen, uint64_t wCoeff, uint64_t wState = 0x01)
: mCoeff(wCoeff), mStartState(wState), mState(wState), mLen(wLen)
{ assert(wLen<=64); }
/**@name Accessors */
//@{
uint64_t coeff() const { return mCoeff; }
uint64_t state() const { return mState; }
void state(uint64_t state) { mState = state & mask(); }
unsigned size() const { return mLen; }
//@}
/**
Calculate one bit of a PRBS
*/
unsigned generateBit()
{
const unsigned result = mState & 0x01;
processBit(result);
return result;
}
/**
Update the generator state by one bit.
If you want to synchronize your PRBS to a known state, call this function
size() times passing your PRBS to it bit by bit.
*/
void processBit(unsigned inBit)
{
mState >>= 1;
if (inBit) mState ^= mCoeff;
}
/** Return true when PRBS is wrapping through initial state */
bool isFinished() const { return mStartState == mState; }
protected:
uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent.
uint64_t mStartState; ///< initial shift register state.
uint64_t mState; ///< shift register state.
unsigned mLen; ///< number of bits used in shift register
/** Return mask for the state register */
uint64_t mask() const { return (mLen==64)?0xFFFFFFFFFFFFFFFFUL:((1<<mLen)-1); }
};
/**
A standard 9-bit based pseudorandom binary sequence (PRBS) generator.
Polynomial: x^9 + x^5 + 1
*/
class PRBS9 : public PRBS {
public:
PRBS9(uint64_t wState = 0x01)
: PRBS(9, 0x0110, wState)
{}
};
/**
A standard 15-bit based pseudorandom binary sequence (PRBS) generator.
Polynomial: x^15 + x^14 + 1
*/
class PRBS15 : public PRBS {
public:
PRBS15(uint64_t wState = 0x01)
: PRBS(15, 0x6000, wState)
{}
};
/**
A standard 64-bit based pseudorandom binary sequence (PRBS) generator.
Polynomial: x^64 + x^63 + x^61 + x^60 + 1
*/
class PRBS64 : public PRBS {
public:
PRBS64(uint64_t wState = 0x01)
: PRBS(64, 0xD800000000000000ULL, wState)
{}
};
#endif // PRBS_H

View File

@@ -1,64 +0,0 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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/>.
*/
#ifndef REGEXPW_H
#define REGEXPW_H
#include <regex.h>
#include <iostream>
#include <stdlib.h>
class Regexp {
private:
regex_t mRegex;
public:
Regexp(const char* regexp, int flags=REG_EXTENDED)
{
int result = regcomp(&mRegex, regexp, flags);
if (result) {
char msg[256];
regerror(result,&mRegex,msg,255);
std::cerr << "Regexp compilation of " << regexp << " failed: " << msg << std::endl;
abort();
}
}
~Regexp()
{ regfree(&mRegex); }
bool match(const char *text, int flags=0) const
{ return regexec(&mRegex, text, 0, NULL, flags)==0; }
};
#endif

View File

@@ -1,145 +0,0 @@
/**@file Module for performance-reporting mechanisms. */
/*
* Copyright 2012 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 "Reporting.h"
#include "Logger.h"
#include <stdio.h>
#include <string.h>
static const char* createReportingTable = {
"CREATE TABLE IF NOT EXISTS REPORTING ("
"NAME TEXT UNIQUE NOT NULL, "
"VALUE INTEGER DEFAULT 0, "
"CLEAREDTIME INTEGER NOT NULL, "
"UPDATETIME INTEGER DEFAULT 0 "
")"
};
ReportingTable::ReportingTable(const char* filename)
{
gLogEarly(LOG_INFO | mFacility, "opening reporting table from path %s", filename);
// Connect to the database.
int rc = sqlite3_open(filename,&mDB);
if (rc) {
gLogEarly(LOG_EMERG | mFacility, "cannot open reporting database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
sqlite3_close(mDB);
mDB = NULL;
return;
}
// Create the table, if needed.
if (!sqlite3_command(mDB,createReportingTable)) {
gLogEarly(LOG_EMERG | mFacility, "cannot create reporting table in database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
}
}
bool ReportingTable::create(const char* paramName)
{
char cmd[200];
sprintf(cmd,"INSERT OR IGNORE INTO REPORTING (NAME,CLEAREDTIME) VALUES (\"%s\",%ld)", paramName, time(NULL));
if (!sqlite3_command(mDB,cmd)) {
gLogEarly(LOG_CRIT|mFacility, "cannot create reporting parameter %s, error message: %s", paramName, sqlite3_errmsg(mDB));
return false;
}
return true;
}
bool ReportingTable::incr(const char* paramName)
{
char cmd[200];
sprintf(cmd,"UPDATE REPORTING SET VALUE=VALUE+1, UPDATETIME=%ld WHERE NAME=\"%s\"", time(NULL), paramName);
if (!sqlite3_command(mDB,cmd)) {
gLogEarly(LOG_CRIT|mFacility, "cannot increment reporting parameter %s, error message: %s", paramName, sqlite3_errmsg(mDB));
return false;
}
return true;
}
bool ReportingTable::max(const char* paramName, unsigned newVal)
{
char cmd[200];
sprintf(cmd,"UPDATE REPORTING SET VALUE=MAX(VALUE,%u), UPDATETIME=%ld WHERE NAME=\"%s\"", newVal, time(NULL), paramName);
if (!sqlite3_command(mDB,cmd)) {
gLogEarly(LOG_CRIT|mFacility, "cannot maximize reporting parameter %s, error message: %s", paramName, sqlite3_errmsg(mDB));
return false;
}
return true;
}
bool ReportingTable::clear(const char* paramName)
{
char cmd[200];
sprintf(cmd,"UPDATE REPORTING SET VALUE=0, UPDATETIME=0, CLEAREDTIME=%ld WHERE NAME=\"%s\"", time(NULL), paramName);
if (!sqlite3_command(mDB,cmd)) {
gLogEarly(LOG_CRIT|mFacility, "cannot clear reporting parameter %s, error message: %s", paramName, sqlite3_errmsg(mDB));
return false;
}
return true;
}
bool ReportingTable::create(const char* baseName, unsigned minIndex, unsigned maxIndex)
{
size_t sz = strlen(baseName);
for (unsigned i = minIndex; i<=maxIndex; i++) {
char name[sz+10];
sprintf(name,"%s.%u",baseName,i);
if (!create(name)) return false;
}
return true;
}
bool ReportingTable::incr(const char* baseName, unsigned index)
{
char name[strlen(baseName)+10];
sprintf(name,"%s.%u",baseName,index);
return incr(name);
}
bool ReportingTable::max(const char* baseName, unsigned index, unsigned newVal)
{
char name[strlen(baseName)+10];
sprintf(name,"%s.%u",baseName,index);
return max(name,newVal);
}
bool ReportingTable::clear(const char* baseName, unsigned index)
{
char name[strlen(baseName)+10];
sprintf(name,"%s.%u",baseName,index);
return clear(name);
}

View File

@@ -1,86 +0,0 @@
/**@file Module for performance-reporting mechanisms. */
/*
* Copyright 2012 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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/>.
*/
#ifndef REPORTING_H
#define REPORTING_H
#include <sqlite3util.h>
#include <ostream>
/**
Collect performance statistics into a database.
Parameters are counters or max/min trackers, all integer.
*/
class ReportingTable {
private:
sqlite3* mDB; ///< database connection
int mFacility; ///< rsyslogd facility
public:
/**
Open the database connection;
create the table if it does not exist yet.
*/
ReportingTable(const char* filename);
/** Create a new parameter. */
bool create(const char* paramName);
/** Create an indexed parameter set. */
bool create(const char* baseBame, unsigned minIndex, unsigned maxIndex);
/** Increment a counter. */
bool incr(const char* paramName);
/** Increment an indexed counter. */
bool incr(const char* baseName, unsigned index);
/** Take a max of a parameter. */
bool max(const char* paramName, unsigned newVal);
/** Take a max of an indexed parameter. */
bool max(const char* paramName, unsigned index, unsigned newVal);
/** Clear a value. */
bool clear(const char* paramName);
/** Clear an indexed value. */
bool clear(const char* paramName, unsigned index);
/** Dump the database to a stream. */
void dump(std::ostream&) const;
};
#endif
// vim: ts=4 sw=4

View File

@@ -1,136 +0,0 @@
/*
* Copyright 2011 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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.
*/
#ifndef SCALARTYPES_H
#define SCALARTYPES_H
#include <iostream> // For size_t
#include <stdint.h>
//#include "GSMCommon.h" // Was included for Z100Timer
// We dont bother to define *= /= etc.; you'll have to convert: a*=b; to: a=a*b;
#define _INITIALIZED_SCALAR_BASE_FUNCS(Classname,Basetype,Init) \
Classname() : value(Init) {} \
Classname(Basetype wvalue) { value = wvalue; } /* Can set from basetype. */ \
operator Basetype(void) const { return value; } /* Converts from basetype. */ \
Basetype operator=(Basetype wvalue) { return value = wvalue; } \
Basetype* operator&() { return &value; }
#define _INITIALIZED_SCALAR_ARITH_FUNCS(Basetype) \
Basetype operator++() { return ++value; } \
Basetype operator++(int) { return value++; } \
Basetype operator--() { return --value; } \
Basetype operator--(int) { return value--; } \
Basetype operator+=(Basetype wvalue) { return value = value + wvalue; } \
Basetype operator-=(Basetype wvalue) { return value = value - wvalue; }
#define _INITIALIZED_SCALAR_FUNCS(Classname,Basetype,Init) \
_INITIALIZED_SCALAR_BASE_FUNCS(Classname,Basetype,Init) \
_INITIALIZED_SCALAR_ARITH_FUNCS(Basetype)
#define _DECLARE_SCALAR_TYPE(Classname_i,Classname_z,Basetype) \
template <Basetype Init> \
struct Classname_i { \
Basetype value; \
_INITIALIZED_SCALAR_FUNCS(Classname_i,Basetype,Init) \
}; \
typedef Classname_i<0> Classname_z;
// Usage:
// Where 'classname' is one of the types listed below, then:
// classname_z specifies a zero initialized type;
// classname_i<value> initializes the type to the specified value.
// We also define Float_z.
_DECLARE_SCALAR_TYPE(Int_i, Int_z, int)
_DECLARE_SCALAR_TYPE(Char_i, Char_z, signed char)
_DECLARE_SCALAR_TYPE(Int16_i, Int16_z, int16_t)
_DECLARE_SCALAR_TYPE(Int32_i, Int32_z, int32_t)
_DECLARE_SCALAR_TYPE(UInt_i, UInt_z, unsigned)
_DECLARE_SCALAR_TYPE(UChar_i, UChar_z, unsigned char)
_DECLARE_SCALAR_TYPE(UInt16_i, UInt16_z, uint16_t)
_DECLARE_SCALAR_TYPE(UInt32_i, UInt32_z, uint32_t)
_DECLARE_SCALAR_TYPE(Size_t_i, Size_t_z, size_t)
// Bool is special because it cannot accept some arithmetic funcs
//_DECLARE_SCALAR_TYPE(Bool_i, Bool_z, bool)
template <bool Init>
struct Bool_i {
bool value;
_INITIALIZED_SCALAR_BASE_FUNCS(Bool_i,bool,Init)
};
typedef Bool_i<0> Bool_z;
// float is special, because C++ does not permit the template initalization:
struct Float_z {
float value;
_INITIALIZED_SCALAR_FUNCS(Float_z,float,0)
};
struct Double_z {
double value;
_INITIALIZED_SCALAR_FUNCS(Double_z,double,0)
};
class ItemWithValueAndWidth {
public:
virtual unsigned getValue() const = 0;
virtual unsigned getWidth() const = 0;
};
// A Range Networks Field with a specified width.
// See RLCMessages.h for examples.
template <int Width=32, unsigned Init=0>
class Field_i : public ItemWithValueAndWidth
{
public:
unsigned value;
_INITIALIZED_SCALAR_FUNCS(Field_i,unsigned,Init)
unsigned getWidth() const { return Width; }
unsigned getValue() const { return value; }
};
// Synonym for Field_i, but no way to do it.
template <int Width, unsigned Init=0>
class Field_z : public ItemWithValueAndWidth
{
public:
unsigned value;
_INITIALIZED_SCALAR_FUNCS(Field_z,unsigned,Init)
unsigned getWidth() const { return Width; }
unsigned getValue() const { return value; }
};
// This is an uninitialized field.
template <int Width=32, unsigned Init=0>
class Field : public ItemWithValueAndWidth
{
public:
unsigned value;
_INITIALIZED_SCALAR_FUNCS(Field,unsigned,Init)
unsigned getWidth() const { return Width; }
unsigned getValue() const { return value; }
};
// A Z100Timer with an initial value specified.
//template <int Init>
//class Z100Timer_i : public GSM::Z100Timer {
// public:
// Z100Timer_i() : GSM::Z100Timer(Init) {}
//};
#endif

View File

@@ -1,333 +0,0 @@
/*
* Copyright 2008, 2010 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 <config.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstdio>
#include <sys/select.h>
#include "Threads.h"
#include "Sockets.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
bool resolveAddress(struct sockaddr_in *address, const char *hostAndPort)
{
assert(address);
assert(hostAndPort);
char *copy = strdup(hostAndPort);
char *colon = strchr(copy,':');
if (!colon) return false;
*colon = '\0';
char *host = copy;
unsigned port = strtol(colon+1,NULL,10);
bool retVal = resolveAddress(address,host,port);
free(copy);
return retVal;
}
bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned short port)
{
assert(address);
assert(host);
// FIXME -- Need to ignore leading/trailing spaces in hostname.
struct hostent *hp;
int h_errno_local;
#ifdef HAVE_GETHOSTBYNAME2_R
struct hostent hostData;
char tmpBuffer[2048];
// There are different flavors of gethostbyname_r(), but
// latest Linux use the following form:
if (gethostbyname2_r(host, AF_INET, &hostData, tmpBuffer, sizeof(tmpBuffer), &hp, &h_errno_local)!=0) {
CERR("WARNING -- gethostbyname2_r() failed for " << host << ", " << hstrerror(h_errno_local));
return false;
}
#else
static Mutex sGethostbynameMutex;
// gethostbyname() is NOT thread-safe, so we should use a mutex here.
// Ideally it should be a global mutex for all non thread-safe socket
// operations and it should protect access to variables such as
// global h_errno.
sGethostbynameMutex.lock();
hp = gethostbyname(host);
h_errno_local = h_errno;
sGethostbynameMutex.unlock();
#endif
if (hp==NULL) {
CERR("WARNING -- gethostbyname() failed for " << host << ", " << hstrerror(h_errno_local));
return false;
}
if (hp->h_addrtype != AF_INET) {
CERR("WARNING -- gethostbyname() resolved " << host << " to something other then AF_INET");
return false;
}
address->sin_family = hp->h_addrtype;
assert(sizeof(address->sin_addr) == hp->h_length);
memcpy(&(address->sin_addr), hp->h_addr_list[0], hp->h_length);
address->sin_port = htons(port);
return true;
}
DatagramSocket::DatagramSocket()
{
memset(mDestination, 0, sizeof(mDestination));
}
void DatagramSocket::nonblocking()
{
fcntl(mSocketFD,F_SETFL,O_NONBLOCK);
}
void DatagramSocket::blocking()
{
fcntl(mSocketFD,F_SETFL,0);
}
void DatagramSocket::close()
{
::close(mSocketFD);
}
DatagramSocket::~DatagramSocket()
{
close();
}
int DatagramSocket::write( const char * message, size_t length )
{
assert(length<=MAX_UDP_LENGTH);
int retVal = sendto(mSocketFD, message, length, 0,
(struct sockaddr *)mDestination, addressSize());
if (retVal == -1 ) perror("DatagramSocket::write() failed");
return retVal;
}
int DatagramSocket::writeBack( const char * message, size_t length )
{
assert(length<=MAX_UDP_LENGTH);
int retVal = sendto(mSocketFD, message, length, 0,
(struct sockaddr *)mSource, addressSize());
if (retVal == -1 ) perror("DatagramSocket::write() failed");
return retVal;
}
int DatagramSocket::write( const char * message)
{
size_t length=strlen(message)+1;
return write(message,length);
}
int DatagramSocket::writeBack( const char * message)
{
size_t length=strlen(message)+1;
return writeBack(message,length);
}
int DatagramSocket::send(const struct sockaddr* dest, const char * message, size_t length )
{
assert(length<=MAX_UDP_LENGTH);
int retVal = sendto(mSocketFD, message, length, 0, dest, addressSize());
if (retVal == -1 ) perror("DatagramSocket::send() failed");
return retVal;
}
int DatagramSocket::send(const struct sockaddr* dest, const char * message)
{
size_t length=strlen(message)+1;
return send(dest,message,length);
}
int DatagramSocket::read(char* buffer, size_t length)
{
socklen_t addr_len = sizeof(mSource);
int rd_length = recvfrom(mSocketFD, (void *) buffer, length, 0,
(struct sockaddr*) &mSource, &addr_len);
if ((rd_length==-1) && (errno!=EAGAIN)) {
perror("DatagramSocket::read() failed");
throw SocketError();
}
return rd_length;
}
int DatagramSocket::read(char* buffer, size_t length, unsigned timeout)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(mSocketFD,&fds);
struct timeval tv;
tv.tv_sec = timeout/1000;
tv.tv_usec = (timeout%1000)*1000;
int sel = select(mSocketFD+1,&fds,NULL,NULL,&tv);
if (sel<0) {
perror("DatagramSocket::read() select() failed");
throw SocketError();
}
if (sel==0) return -1;
if (FD_ISSET(mSocketFD,&fds)) return read(buffer, length);
return -1;
}
UDPSocket::UDPSocket(unsigned short wSrcPort)
:DatagramSocket()
{
open(wSrcPort);
}
UDPSocket::UDPSocket(unsigned short wSrcPort,
const char * wDestIP, unsigned short wDestPort )
:DatagramSocket()
{
open(wSrcPort);
destination(wDestPort, wDestIP);
}
void UDPSocket::destination( unsigned short wDestPort, const char * wDestIP )
{
resolveAddress((sockaddr_in*)mDestination, wDestIP, wDestPort );
}
void UDPSocket::open(unsigned short localPort)
{
// create
mSocketFD = socket(AF_INET,SOCK_DGRAM,0);
if (mSocketFD<0) {
perror("socket() failed");
throw SocketError();
}
// pat added: This lets the socket be reused immediately, which is needed if OpenBTS crashes.
int on = 1;
setsockopt(mSocketFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
// bind
struct sockaddr_in address;
size_t length = sizeof(address);
bzero(&address,length);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
address.sin_port = htons(localPort);
if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
perror("bind() failed");
throw SocketError();
}
}
unsigned short UDPSocket::port() const
{
struct sockaddr_in name;
socklen_t nameSize = sizeof(name);
int retVal = getsockname(mSocketFD, (struct sockaddr*)&name, &nameSize);
if (retVal==-1) throw SocketError();
return ntohs(name.sin_port);
}
UDDSocket::UDDSocket(const char* localPath, const char* remotePath)
:DatagramSocket()
{
if (localPath!=NULL) open(localPath);
if (remotePath!=NULL) destination(remotePath);
}
void UDDSocket::open(const char* localPath)
{
// create
mSocketFD = socket(AF_UNIX,SOCK_DGRAM,0);
if (mSocketFD<0) {
perror("socket() failed");
throw SocketError();
}
// bind
struct sockaddr_un address;
size_t length = sizeof(address);
bzero(&address,length);
address.sun_family = AF_UNIX;
strcpy(address.sun_path,localPath);
unlink(localPath);
if (bind(mSocketFD,(struct sockaddr*)&address,length)<0) {
perror("bind() failed");
throw SocketError();
}
}
void UDDSocket::destination(const char* remotePath)
{
struct sockaddr_un* unAddr = (struct sockaddr_un*)mDestination;
strcpy(unAddr->sun_path,remotePath);
}
// vim:ts=4:sw=4

View File

@@ -1,193 +0,0 @@
/*
* Copyright 2008, 2010 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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/>.
*/
#ifndef SOCKETS_H
#define SOCKETS_H
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <errno.h>
#include <list>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#define MAX_UDP_LENGTH 1500
/** A function to resolve IP host names. */
bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned short port);
/** Resolve an address of the form "<host>:<port>". */
bool resolveAddress(struct sockaddr_in *address, const char *hostAndPort);
/** An exception to throw when a critical socket operation fails. */
class SocketError {};
#define SOCKET_ERROR {throw SocketError(); }
/** Abstract class for connectionless sockets. */
class DatagramSocket {
protected:
int mSocketFD; ///< underlying file descriptor
char mDestination[256]; ///< address to which packets are sent
char mSource[256]; ///< return address of most recent received packet
public:
/** An almost-does-nothing constructor. */
DatagramSocket();
virtual ~DatagramSocket();
/** Return the address structure size for this socket type. */
virtual size_t addressSize() const = 0;
/**
Send a binary packet.
@param buffer The data bytes to send to mDestination.
@param length Number of bytes to send, or strlen(buffer) if defaulted to -1.
@return number of bytes written, or -1 on error.
*/
int write( const char * buffer, size_t length);
/**
Send a C-style string packet.
@param buffer The data bytes to send to mDestination.
@return number of bytes written, or -1 on error.
*/
int write( const char * buffer);
/**
Send a binary packet.
@param buffer The data bytes to send to mSource.
@param length Number of bytes to send, or strlen(buffer) if defaulted to -1.
@return number of bytes written, or -1 on error.
*/
int writeBack(const char * buffer, size_t length);
/**
Send a C-style string packet.
@param buffer The data bytes to send to mSource.
@return number of bytes written, or -1 on error.
*/
int writeBack(const char * buffer);
/**
Receive a packet.
@param buffer A char[MAX_UDP_LENGTH] procured by the caller.
@return The number of bytes received or -1 on non-blocking pass.
*/
int read(char* buffer, size_t length);
/**
Receive a packet with a timeout.
@param buffer A char[MAX_UDP_LENGTH] procured by the caller.
@param maximum wait time in milliseconds
@return The number of bytes received or -1 on timeout.
*/
int read(char* buffer, size_t length, unsigned timeout);
/** Send a packet to a given destination, other than the default. */
int send(const struct sockaddr *dest, const char * buffer, size_t length);
/** Send a C-style string to a given destination, other than the default. */
int send(const struct sockaddr *dest, const char * buffer);
/** Make the socket non-blocking. */
void nonblocking();
/** Make the socket blocking (the default). */
void blocking();
/** Close the socket. */
void close();
};
/** UDP/IP User Datagram Socket */
class UDPSocket : public DatagramSocket {
public:
/** Open a USP socket with an OS-assigned port and no default destination. */
UDPSocket( unsigned short localPort=0);
/** Given a full specification, open the socket and set the dest address. */
UDPSocket( unsigned short localPort,
const char * remoteIP, unsigned short remotePort);
/** Set the destination port. */
void destination( unsigned short wDestPort, const char * wDestIP );
/** Return the actual port number in use. */
unsigned short port() const;
/** Open and bind the UDP socket to a local port. */
void open(unsigned short localPort=0);
/** Give the return address of the most recently received packet. */
const struct sockaddr_in* source() const { return (const struct sockaddr_in*)mSource; }
size_t addressSize() const { return sizeof(struct sockaddr_in); }
};
/** Unix Domain Datagram Socket */
class UDDSocket : public DatagramSocket {
public:
UDDSocket(const char* localPath=NULL, const char* remotePath=NULL);
void destination(const char* remotePath);
void open(const char* localPath);
/** Give the return address of the most recently received packet. */
const struct sockaddr_un* source() const { return (const struct sockaddr_un*)mSource; }
size_t addressSize() const { return sizeof(struct sockaddr_un); }
};
#endif
// vim:ts=4:sw=4

View File

@@ -1,103 +0,0 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 "Sockets.h"
#include "Threads.h"
#include <stdio.h>
#include <stdlib.h>
static const int gNumToSend = 10;
void *testReaderIP(void *)
{
UDPSocket readSocket(5934, "localhost", 5061);
readSocket.nonblocking();
int rc = 0;
while (rc<gNumToSend) {
char buf[MAX_UDP_LENGTH];
int count = readSocket.read(buf, MAX_UDP_LENGTH);
if (count>0) {
COUT("read: " << buf);
rc++;
} else {
sleep(2);
}
}
return NULL;
}
void *testReaderUnix(void *)
{
UDDSocket readSocket("testDestination");
readSocket.nonblocking();
int rc = 0;
while (rc<gNumToSend) {
char buf[MAX_UDP_LENGTH];
int count = readSocket.read(buf, MAX_UDP_LENGTH);
if (count>0) {
COUT("read: " << buf);
rc++;
} else {
sleep(2);
}
}
return NULL;
}
int main(int argc, char * argv[] )
{
Thread readerThreadIP;
readerThreadIP.start(testReaderIP,NULL);
Thread readerThreadUnix;
readerThreadUnix.start(testReaderUnix,NULL);
UDPSocket socket1(5061, "127.0.0.1",5934);
UDDSocket socket1U("testSource","testDestination");
COUT("socket1: " << socket1.port());
// give the readers time to open
sleep(1);
for (int i=0; i<gNumToSend; i++) {
socket1.write("Hello IP land");
socket1U.write("Hello Unix domain");
sleep(1);
}
readerThreadIP.join();
readerThreadUnix.join();
}
// vim: ts=4 sw=4

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@@ -24,16 +25,22 @@
*/
#include <string.h>
#include <sys/types.h>
#include "Threads.h"
#include "Timeval.h"
#include "Logger.h"
extern "C" {
#include <osmocom/core/thread.h>
}
using namespace std;
#ifndef HAVE_ATOMIC_OPS
pthread_mutex_t atomic_ops_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
Mutex gStreamLock; ///< Global lock to control access to cout and cerr.
@@ -42,7 +49,7 @@ void lockCout()
{
gStreamLock.lock();
Timeval entryTime;
cout << entryTime << " " << pthread_self() << ": ";
cout << entryTime << " " << osmo_gettid() << ": ";
}
@@ -57,7 +64,7 @@ void lockCerr()
{
gStreamLock.lock();
Timeval entryTime;
cerr << entryTime << " " << pthread_self() << ": ";
cerr << entryTime << " " << osmo_gettid() << ": ";
}
void unlockCerr()
@@ -102,6 +109,25 @@ void Signal::wait(Mutex& wMutex, unsigned timeout) const
pthread_cond_timedwait(&mSignal,&wMutex.mMutex,&waitTime);
}
void set_selfthread_name(const char *name)
{
pthread_t selfid = pthread_self();
pid_t tid = osmo_gettid();
if (pthread_setname_np(selfid, name) == 0) {
LOG(INFO) << "Thread "<< selfid << " (task " << tid << ") set name: " << name;
} else {
char buf[256];
int err = errno;
char* err_str = strerror_r(err, buf, sizeof(buf));
LOG(NOTICE) << "Thread "<< selfid << " (task " << tid << ") set name \"" << name << "\" failed: (" << err << ") " << err_str;
}
}
void thread_enable_cancel(bool cancel)
{
cancel ? pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) :
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
}
void Thread::start(void *(*task)(void*), void *arg)
{
@@ -110,8 +136,10 @@ void Thread::start(void *(*task)(void*), void *arg)
// (pat) Moved initialization to constructor to avoid crash in destructor.
//res = pthread_attr_init(&mAttrib);
//assert(!res);
res = pthread_attr_setstacksize(&mAttrib, mStackSize);
assert(!res);
if (mStackSize != 0) {
res = pthread_attr_setstacksize(&mAttrib, mStackSize);
assert(!res);
}
res = pthread_create(&mThread, &mAttrib, task, arg);
assert(!res);
}

View File

@@ -1,6 +1,8 @@
/*
* Copyright 2008, 2011 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -26,6 +28,8 @@
#ifndef THREADS_H
#define THREADS_H
#include "config.h"
#include <pthread.h>
#include <iostream>
#include <assert.h>
@@ -55,7 +59,7 @@ void unlockCout(); ///< call after writing cout
#define OBJDCOUT(text) {}
#else
#define DCOUT(text) { COUT(__FILE__ << ":" << __LINE__ << " " << text); }
#define OBJDCOUT(text) { DCOUT(this << " " << text); }
#define OBJDCOUT(text) { DCOUT(this << " " << text); }
#endif
//@}
//@}
@@ -141,6 +145,9 @@ class Signal {
#define START_THREAD(thread,function,argument) \
thread.start((void *(*)(void*))function, (void*)argument);
void set_selfthread_name(const char *name);
void thread_enable_cancel(bool cancel);
/** A C++ wrapper for pthread threads. */
class Thread {
@@ -150,12 +157,12 @@ class Thread {
pthread_attr_t mAttrib;
// FIXME -- Can this be reduced now?
size_t mStackSize;
public:
/** Create a thread in a non-running state. */
Thread(size_t wStackSize = (65536*4)):mThread((pthread_t)0) {
Thread(size_t wStackSize = 0):mThread((pthread_t)0) {
pthread_attr_init(&mAttrib); // (pat) moved this here.
mStackSize=wStackSize;
}
@@ -179,12 +186,34 @@ class Thread {
}
}
/** Send cancelation to thread */
/** Send cancellation to thread */
void cancel() { pthread_cancel(mThread); }
};
#ifdef HAVE_ATOMIC_OPS
#define osmo_trx_sync_fetch_and_and(ptr, value) __sync_fetch_and_and((ptr), (value))
#define osmo_trx_sync_or_and_fetch(ptr, value) __sync_or_and_fetch((ptr), (value))
#else
extern pthread_mutex_t atomic_ops_mutex;
static inline int osmo_trx_sync_fetch_and_and(int *ptr, int value)
{
pthread_mutex_lock(&atomic_ops_mutex);
int tmp = *ptr;
*ptr &= value;
pthread_mutex_unlock(&atomic_ops_mutex);
return tmp;
}
static inline int osmo_trx_sync_or_and_fetch(int *ptr, int value)
{
int tmp;
pthread_mutex_lock(&atomic_ops_mutex);
*ptr |= value;
tmp = *ptr;
pthread_mutex_unlock(&atomic_ops_mutex);
return tmp;
}
#endif
#endif
// vim: ts=4 sw=4

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@@ -27,43 +28,49 @@
#include "Timeval.h"
extern "C" {
#include <osmocom/core/timer.h>
}
using namespace std;
void Timeval::now()
{
osmo_clock_gettime(CLOCK_REALTIME, &mTimespec);
}
void Timeval::future(unsigned offset)
{
now();
unsigned sec = offset/1000;
unsigned msec = offset%1000;
mTimeval.tv_usec += msec*1000;
mTimeval.tv_sec += sec;
if (mTimeval.tv_usec>1000000) {
mTimeval.tv_usec -= 1000000;
mTimeval.tv_sec += 1;
mTimespec.tv_nsec += msec*1000*1000;
mTimespec.tv_sec += sec;
if (mTimespec.tv_nsec > 1000*1000*1000) {
mTimespec.tv_nsec -= 1000*1000*1000;
mTimespec.tv_sec += 1;
}
}
struct timespec Timeval::timespec() const
{
struct timespec retVal;
retVal.tv_sec = mTimeval.tv_sec;
retVal.tv_nsec = 1000 * (long)mTimeval.tv_usec;
return retVal;
return mTimespec;
}
bool Timeval::passed() const
{
Timeval nowTime;
if (nowTime.mTimeval.tv_sec < mTimeval.tv_sec) return false;
if (nowTime.mTimeval.tv_sec > mTimeval.tv_sec) return true;
if (nowTime.mTimeval.tv_usec > mTimeval.tv_usec) return true;
if (nowTime.mTimespec.tv_sec < mTimespec.tv_sec) return false;
if (nowTime.mTimespec.tv_sec > mTimespec.tv_sec) return true;
if (nowTime.mTimespec.tv_nsec >= mTimespec.tv_nsec) return true;
return false;
}
double Timeval::seconds() const
{
return ((double)mTimeval.tv_sec) + 1e-6*((double)mTimeval.tv_usec);
return ((double)mTimespec.tv_sec) + 1e-9*((double)mTimespec.tv_nsec);
}
@@ -72,24 +79,25 @@ long Timeval::delta(const Timeval& other) const
{
// 2^31 milliseconds is just over 4 years.
int32_t deltaS = other.sec() - sec();
int32_t deltaUs = other.usec() - usec();
return 1000*deltaS + deltaUs/1000;
int32_t deltaNs = other.nsec() - nsec();
return 1000*deltaS + deltaNs/1000000;
}
ostream& operator<<(ostream& os, const Timeval& tv)
{
os.setf( ios::fixed, ios::floatfield );
ios_base::fmtflags flags_backup = os.setf( ios::fixed, ios::floatfield );
os << tv.seconds();
os.flags( flags_backup );
return os;
}
ostream& operator<<(ostream& os, const struct timespec& ts)
{
os << ts.tv_sec << "," << ts.tv_nsec;
os << ts.tv_sec << "," << ts.tv_nsec/1000;
return os;
}

View File

@@ -1,6 +1,8 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -42,12 +44,12 @@ class Timeval {
private:
struct timeval mTimeval;
struct timespec mTimespec;
public:
/** Set the value to gettimeofday. */
void now() { gettimeofday(&mTimeval,NULL); }
/** Set the value to current time. */
void now();
/** Set the value to gettimeofday plus an offset. */
void future(unsigned ms);
@@ -55,16 +57,18 @@ class Timeval {
//@{
Timeval(unsigned sec, unsigned usec)
{
mTimeval.tv_sec = sec;
mTimeval.tv_usec = usec;
mTimespec.tv_sec = sec;
mTimespec.tv_nsec = usec*1000;
}
Timeval(const struct timeval& wTimeval)
:mTimeval(wTimeval)
{}
{
mTimespec.tv_sec = wTimeval.tv_sec;
mTimespec.tv_nsec = wTimeval.tv_sec*1000;
}
/**
Create a Timeval offset into the future.
Create a Timespec offset into the future.
@param offset milliseconds
*/
Timeval(unsigned offset=0) { future(offset); }
@@ -76,10 +80,11 @@ class Timeval {
/** Return total seconds. */
double seconds() const;
uint32_t sec() const { return mTimeval.tv_sec; }
uint32_t usec() const { return mTimeval.tv_usec; }
uint32_t sec() const { return mTimespec.tv_sec; }
uint32_t usec() const { return mTimespec.tv_nsec / 1000; }
uint32_t nsec() const { return mTimespec.tv_nsec; }
/** Return differnce from other (other-self), in ms. */
/** Return difference from other (other-self), in ms. */
long delta(const Timeval& other) const;
/** Elapsed time in ms. */
@@ -88,11 +93,11 @@ class Timeval {
/** Remaining time in ms. */
long remaining() const { return -elapsed(); }
/** Return true if the time has passed, as per gettimeofday. */
/** Return true if the time has passed, as per clock_gettime(CLOCK_REALTIME). */
bool passed() const;
/** Add a given number of minutes to the time. */
void addMinutes(unsigned minutes) { mTimeval.tv_sec += minutes*60; }
void addMinutes(unsigned minutes) { mTimespec.tv_sec += minutes*60; }
};

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 "Timeval.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
Timeval then(10000);
cout << then.elapsed() << endl;
while (!then.passed()) {
cout << "now: " << Timeval() << " then: " << then << " remaining: " << then.remaining() << endl;
usleep(500000);
}
cout << "now: " << Timeval() << " then: " << then << " remaining: " << then.remaining() << endl;
}

View File

@@ -1,28 +0,0 @@
/* Copyright 2011, Range Networks, Inc. */
#include <URLEncode.h>
#include <string>
#include <string.h>
#include <ctype.h>
using namespace std;
//based on javascript encodeURIComponent()
string URLEncode(const string &c)
{
static const char *digits = "01234567890ABCDEF";
string retVal="";
for (size_t i=0; i<c.length(); i++)
{
const char ch = c[i];
if (isalnum(ch) || strchr("-_.!~'()",ch)) {
retVal += ch;
} else {
retVal += '%';
retVal += digits[(ch>>4) & 0x0f];
retVal += digits[ch & 0x0f];
}
}
return retVal;
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2011 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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 <string>
std::string URLEncode(const std::string&);

View File

@@ -1,17 +0,0 @@
#include "URLEncode.h"
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
string test = string("Testing: !@#$%^&*() " __DATE__ " " __TIME__);
cout << test << endl;
cout << URLEncode(test) << endl;
}

View File

@@ -1,211 +1,34 @@
/*
* Copyright 2011 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
* Copyright 2018 sysmocom - s.f.m.c. GmbH
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
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.
*/
#include <vector>
#include <string>
#include <sstream>
#include <unistd.h> // For usleep
#include <sys/time.h> // For gettimeofday
#include <stdio.h> // For vsnprintf
#include <ostream> // For ostream
#include <sstream> // For ostringstream
#include <string.h> // For strcpy
//#include "GSMCommon.h"
#include "Utils.h"
#include "MemoryLeak.h"
namespace Utils {
MemStats gMemStats;
int gMemLeakDebug = 0;
MemStats::MemStats()
std::vector<std::string> comma_delimited_to_vector(const char* opt)
{
memset(mMemNow,0,sizeof(mMemNow));
memset(mMemTotal,0,sizeof(mMemTotal));
memset(mMemName,0,sizeof(mMemName));
}
std::string str = std::string(opt);
std::vector<std::string> result;
std::stringstream ss(str);
void MemStats::text(std::ostream &os)
{
os << "Structs current total:\n";
for (int i = 0; i < mMax; i++) {
os << "\t" << (mMemName[i] ? mMemName[i] : "unknown") << " " << mMemNow[i] << " " << mMemTotal[i] << "\n";
while( ss.good() )
{
std::string substr;
getline(ss, substr, ',');
result.push_back(substr);
}
return result;
}
void MemStats::memChkNew(MemoryNames memIndex, const char *id)
{
/*std::cout << "new " #type "\n";*/
mMemNow[memIndex]++;
mMemTotal[memIndex]++;
mMemName[memIndex] = id;
}
void MemStats::memChkDel(MemoryNames memIndex, const char *id)
{
/*std::cout << "del " #type "\n";*/
mMemNow[memIndex]--;
if (mMemNow[memIndex] < 0) {
LOG(ERR) << "Memory underflow on type "<<id;
if (gMemLeakDebug) assert(0);
mMemNow[memIndex] += 100; // Prevent another message for a while.
}
}
std::ostream& operator<<(std::ostream& os, std::ostringstream& ss)
{
return os << ss.str();
}
std::ostream &osprintf(std::ostream &os, const char *fmt, ...)
{
va_list ap;
char buf[300];
va_start(ap,fmt);
int n = vsnprintf(buf,300,fmt,ap);
va_end(ap);
if (n >= (300-4)) { strcpy(&buf[(300-4)],"..."); }
os << buf;
return os;
}
std::string format(const char *fmt, ...)
{
va_list ap;
char buf[300];
va_start(ap,fmt);
int n = vsnprintf(buf,300,fmt,ap);
va_end(ap);
if (n >= (300-4)) { strcpy(&buf[(300-4)],"..."); }
return std::string(buf);
}
// Return time in seconds with high resolution.
// Note: In the past I found this to be a surprisingly expensive system call in linux.
double timef()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_usec / 1000000.0 + tv.tv_sec;
}
const std::string timestr()
{
struct timeval tv;
struct tm tm;
gettimeofday(&tv,NULL);
localtime_r(&tv.tv_sec,&tm);
unsigned tenths = tv.tv_usec / 100000; // Rounding down is ok.
return format(" %02d:%02d:%02d.%1d",tm.tm_hour,tm.tm_min,tm.tm_sec,tenths);
}
// High resolution sleep for the specified time.
// Return FALSE if time is already past.
void sleepf(double howlong)
{
if (howlong <= 0.00001) return; // Less than 10 usecs, forget it.
usleep((useconds_t) (1000000.0 * howlong));
}
//bool sleepuntil(double untilwhen)
//{
//double now = timef();
//double howlong = untilwhen - now; // Fractional time in seconds.
// We are not worrying about overflow because all times should be in the near future.
//if (howlong <= 0.00001) return false; // Less than 10 usecs, forget it.
//sleepf(sleeptime);
//}
std::string Text2Str::str() const
{
std::ostringstream ss;
text(ss);
return ss.str();
}
std::ostream& operator<<(std::ostream& os, const Text2Str *val)
{
std::ostringstream ss;
if (val) {
val->text(ss);
os << ss.str();
} else {
os << "(null)";
}
return os;
}
// Greatest Common Denominator.
// This is by Doug Brown.
int gcd(int x, int y)
{
if (x > y) {
return x % y == 0 ? y : gcd(y, x % y);
} else {
return y % x == 0 ? x : gcd(x, y % x);
}
}
// Split a C string into an argc,argv array in place; the input string is modified.
// Returns argc, and places results in argv, up to maxargc elements.
// The final argv receives the rest of the input string from maxargc on,
// even if it contains additional splitchars.
// The correct idiom for use is to make a copy of your string, like this:
// char *copy = strcpy((char*)alloca(the_string.length()+1),the_string.c_str());
// char *argv[2];
// int argc = cstrSplit(copy,argv,2,NULL);
// If you want to detect the error of too many arguments, add 1 to argv, like this:
// char *argv[3];
// int argc = cstrSplit(copy,argv,3,NULL);
// if (argc == 3) { error("too many arguments"; }
int cstrSplit(char *in, char **pargv,int maxargc, const char *splitchars)
{
if (splitchars == NULL) { splitchars = " \t\r\n"; } // Default is any space.
int argc = 0;
while (argc < maxargc) {
while (*in && strchr(splitchars,*in)) {in++;} // scan past any splitchars
if (! *in) return argc; // return if finished.
pargv[argc++] = in; // save ptr to start of arg.
in = strpbrk(in,splitchars); // go to end of arg.
if (!in) return argc; // return if finished.
*in++ = 0; // zero terminate this arg.
}
return argc;
}
std::ostream& operator<<(std::ostream& os, const Statistic<int> &stat) { stat.text(os); return os; }
std::ostream& operator<<(std::ostream& os, const Statistic<unsigned> &stat) { stat.text(os); return os; }
std::ostream& operator<<(std::ostream& os, const Statistic<float> &stat) { stat.text(os); return os; }
std::ostream& operator<<(std::ostream& os, const Statistic<double> &stat) { stat.text(os); return os; }
std::string replaceAll(const std::string input, const std::string search, const std::string replace)
{
std::string output = input;
int index = 0;
while (true) {
index = output.find(search, index);
if (index == std::string::npos) {
break;
}
output.replace(index, replace.length(), replace);
index += replace.length();
}
return output;
}
};

View File

@@ -1,148 +1,22 @@
/*
* Copyright 2011 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
* Copyright 2018 sysmocom - s.f.m.c. GmbH
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
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.
*/
#pragma once
#ifndef GPRSUTILS_H
#define GPRSUTILS_H
#include <stdint.h>
#include <stdarg.h>
#include <vector>
#include <string>
#include <string.h>
#include <math.h> // for sqrtf
#include "Logger.h"
namespace Utils {
extern double timef(); // high resolution time
extern const std::string timestr(); // A timestamp to print in messages.
extern void sleepf(double howlong); // high resolution sleep
extern int gcd(int x, int y);
// It is irritating to create a string just to interface to the brain-damaged
// C++ stream class, but this is only used for debug messages.
std::string format(const char *fmt, ...) __attribute__((format (printf,1,2)));
int cstrSplit(char *in, char **pargv,int maxargc, const char *splitchars=NULL);
// For classes with a text() function, provide a function to return a String,
// and also a standard << stream function that takes a pointer to the object.
// We dont provide the function that takes a reference to the object
// because it is too highly overloaded and generally doesnt work.
class Text2Str {
public:
virtual void text(std::ostream &os) const = 0;
std::string str() const;
};
std::ostream& operator<<(std::ostream& os, const Text2Str *val);
#if 0
// Generic Activity Timer. Lots of controls to make everybody happy.
class ATimer {
double mStart;
//bool mActive;
double mLimitTime;
public:
ATimer() : mStart(0), mLimitTime(0) { }
ATimer(double wLimitTime) : mStart(0), mLimitTime(wLimitTime) { }
void start() { mStart=timef(); }
void stop() { mStart=0; }
bool active() { return !!mStart; }
double elapsed() { return timef() - mStart; }
bool expired() { return elapsed() > mLimitTime; }
};
#endif
struct BitSet {
unsigned mBits;
void setBit(unsigned whichbit) { mBits |= 1<<whichbit; }
void clearBit(unsigned whichbit) { mBits &= ~(1<<whichbit); }
unsigned getBit(unsigned whichbit) const { return mBits & (1<<whichbit); }
bool isSet(unsigned whichbit) const { return mBits & (1<<whichbit); }
unsigned bits() const { return mBits; }
operator int(void) const { return mBits; }
BitSet() { mBits = 0; }
};
// Store current, min, max and compute running average and standard deviation.
template<class Type> struct Statistic {
Type mCurrent, mMin, mMax; // min,max optional initialization so you can print before adding any values.
unsigned mCnt;
double mSum;
//double mSum2; // sum of squares.
// (Type) cast needed in case Type is an enum, stupid language.
Statistic() : mCurrent((Type)0), mMin((Type)0), mMax((Type)0), mCnt(0), mSum(0) /*,mSum2(0)*/ {}
// Set the current value and add a statisical point.
void addPoint(Type val) {
mCurrent = val;
if (mCnt == 0 || val < mMin) {mMin = val;}
if (mCnt == 0 || val > mMax) {mMax = val;}
mCnt++;
mSum += val;
//mSum2 += val * val;
}
Type getCurrent() const { // Return current value.
return mCnt ? mCurrent : 0;
}
double getAvg() const { // Return average.
return mCnt==0 ? 0 : mSum/mCnt;
};
//float getSD() const { // Return standard deviation. Use low precision square root function.
// return mCnt==0 ? 0 : sqrtf(mCnt * mSum2 - mSum*mSum) / mCnt;
//}
void text(std::ostream &os) const { // Print everything in parens.
os << "("<<mCurrent;
if (mMin != mMax) { // Not point in printing all this stuff if min == max.
os <<LOGVAR2("min",mMin)<<LOGVAR2("max",mMax)<<LOGVAR2("avg",getAvg());
if (mCnt <= 999999) {
os <<LOGVAR2("N",mCnt);
} else { // Shorten this up:
char buf[10], *ep;
sprintf(buf,"%.3g",round(mCnt));
if ((ep = strchr(buf,'e')) && ep[1] == '+') { strcpy(ep+1,ep+2); }
os << LOGVAR2("N",buf);
}
// os<<LOGVAR2("sd",getSD()) standard deviation not interesting
}
os << ")";
// " min="<<mMin <<" max="<<mMax <<format(" avg=%4g sd=%3g)",getAvg(),getSD());
}
// Not sure if this works:
//std::string statStr() const {
// return (std::string)mCurrent + " min=" + (std::string) mMin +" max="+(string)mMax+ format(" avg=%4g sd=%3g",getAvg(),getSD());
//}
};
// This I/O mechanism is so dumb:
std::ostream& operator<<(std::ostream& os, const Statistic<int> &stat);
std::ostream& operator<<(std::ostream& os, const Statistic<unsigned> &stat);
std::ostream& operator<<(std::ostream& os, const Statistic<float> &stat);
std::ostream& operator<<(std::ostream& os, const Statistic<double> &stat);
// Yes, they botched and left this out:
std::ostream& operator<<(std::ostream& os, std::ostringstream& ss);
std::ostream &osprintf(std::ostream &os, const char *fmt, ...) __attribute__((format (printf,2,3)));
std::string replaceAll(const std::string input, const std::string search, const std::string replace);
}; // namespace
using namespace Utils;
#endif
std::vector<std::string> comma_delimited_to_vector(const char* opt);

View File

@@ -2,6 +2,8 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -32,11 +34,19 @@
#include <string.h>
#include <iostream>
#include <assert.h>
// We cant use Logger.h in this file...
#include <stdlib.h>
#ifndef __OPTIMIZE__
#define assert_no_opt(x) assert(x)
#else
#define assert_no_opt(x)
#endif
// We can't use Logger.h in this file...
extern int gVectorDebug;
#define BVDEBUG(msg) if (gVectorDebug) {std::cout << msg;}
typedef void (*vector_free_func)(void* wData);
typedef void *(*vector_alloc_func)(size_t newSize);
/**
A simplified Vector template with aliases.
@@ -60,6 +70,8 @@ template <class T> class Vector {
T* mData; ///< allocated data block, if any
T* mStart; ///< start of useful data
T* mEnd; ///< end of useful data + 1
vector_alloc_func mAllocFunc; ///< function used to alloc new mData during resize.
vector_free_func mFreeFunc; ///< function used to free mData.
public:
@@ -74,8 +86,8 @@ template <class T> class Vector {
/** Return the size of the Vector. */
size_t size() const
{
assert(mStart>=mData);
assert(mEnd>=mStart);
assert_no_opt(mStart>=mData);
assert_no_opt(mEnd>=mStart);
return mEnd - mStart;
}
@@ -85,13 +97,30 @@ template <class T> class Vector {
/** Change the size of the Vector, discarding content. */
void resize(size_t newSize)
{
if (mData!=NULL) delete[] mData;
if (mData!=NULL) {
if (mFreeFunc)
mFreeFunc(mData);
else
delete[] mData;
}
if (newSize==0) mData=NULL;
else mData = new T[newSize];
else {
if (mAllocFunc)
mData = (T*) mAllocFunc(newSize);
else
mData = new T[newSize];
}
mStart = mData;
mEnd = mStart + newSize;
}
/** Reduce addressable size of the Vector, keeping content. */
void shrink(size_t newSize)
{
assert_no_opt(newSize <= mEnd - mStart);
mEnd = mStart + newSize;
}
/** Release memory and clear pointers. */
void clear() { resize(0); }
@@ -100,7 +129,7 @@ template <class T> class Vector {
void clone(const Vector<T>& other)
{
resize(other.size());
memcpy(mData,other.mStart,other.bytes());
other.copyTo(*this);
}
@@ -109,29 +138,31 @@ template <class T> class Vector {
//@{
/** Build an empty Vector of a given size. */
Vector(size_t wSize=0):mData(NULL) { resize(wSize); }
Vector(size_t wSize=0, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
:mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
{ resize(wSize); }
/** Build a Vector by shifting the data block. */
Vector(Vector<T>& other)
:mData(other.mData),mStart(other.mStart),mEnd(other.mEnd)
/** Build a Vector by moving another. */
Vector(Vector<T>&& other)
:mData(other.mData),mStart(other.mStart),mEnd(other.mEnd), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc)
{ other.mData=NULL; }
/** Build a Vector by copying another. */
Vector(const Vector<T>& other):mData(NULL) { clone(other); }
Vector(const Vector<T>& other):mData(NULL), mAllocFunc(other.mAllocFunc), mFreeFunc(other.mFreeFunc) { clone(other); }
/** Build a Vector with explicit values. */
Vector(T* wData, T* wStart, T* wEnd)
:mData(wData),mStart(wStart),mEnd(wEnd)
Vector(T* wData, T* wStart, T* wEnd, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
:mData(wData),mStart(wStart),mEnd(wEnd), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
{ }
/** Build a vector from an existing block, NOT to be deleted upon destruction. */
Vector(T* wStart, size_t span)
:mData(NULL),mStart(wStart),mEnd(wStart+span)
Vector(T* wStart, size_t span, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
:mData(NULL),mStart(wStart),mEnd(wStart+span),mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
{ }
/** Build a Vector by concatenation. */
Vector(const Vector<T>& other1, const Vector<T>& other2)
:mData(NULL)
Vector(const Vector<T>& other1, const Vector<T>& other2, vector_alloc_func wAllocFunc=NULL, vector_free_func wFreeFunc=NULL)
:mData(NULL), mAllocFunc(wAllocFunc), mFreeFunc(wFreeFunc)
{
resize(other1.size()+other2.size());
memcpy(mStart, other1.mStart, other1.bytes());
@@ -155,6 +186,8 @@ template <class T> class Vector {
mData=other.mData;
mStart=other.mStart;
mEnd=other.mEnd;
mAllocFunc=other.mAllocFunc;
mFreeFunc=other.mFreeFunc;
other.mData=NULL;
}
@@ -171,7 +204,7 @@ template <class T> class Vector {
{
T* wStart = mStart + start;
T* wEnd = wStart + span;
assert(wEnd<=mEnd);
assert_no_opt(wEnd<=mEnd);
return Vector<T>(NULL,wStart,wEnd);
}
@@ -180,7 +213,7 @@ template <class T> class Vector {
{
T* wStart = mStart + start;
T* wEnd = wStart + span;
assert(wEnd<=mEnd);
assert_no_opt(wEnd<=mEnd);
return Vector<T>(NULL,wStart,wEnd);
}
@@ -197,10 +230,15 @@ template <class T> class Vector {
*/
void copyToSegment(Vector<T>& other, size_t start, size_t span) const
{
T* base = other.mStart + start;
assert(base+span<=other.mEnd);
assert(mStart+span<=mEnd);
memcpy(base,mStart,span*sizeof(T));
unsigned int i;
T* dst = other.mStart + start;
T* src = mStart;
assert_no_opt(dst+span<=other.mEnd);
assert_no_opt(mStart+span<=mEnd);
for (i = 0; i < span; i++, src++, dst++)
*dst = *src;
/*TODO if not non-trivially copiable type class, optimize:
memcpy(dst,mStart,span*sizeof(T)); */
}
/** Copy all of this Vector to a segment of another Vector. */
@@ -217,11 +255,26 @@ template <class T> class Vector {
void segmentCopyTo(Vector<T>& other, size_t start, size_t span) const
{
const T* base = mStart + start;
assert(base+span<=mEnd);
assert(other.mStart+span<=other.mEnd);
assert_no_opt(base+span<=mEnd);
assert_no_opt(other.mStart+span<=other.mEnd);
memcpy(other.mStart,base,span*sizeof(T));
}
/**
Move (copy) a segment of this vector into a different position in the vector
@param from Start point from which to copy.
@param to Start point to which to copy.
@param span The number of elements to copy.
*/
void segmentMove(size_t from, size_t to, size_t span)
{
const T* baseFrom = mStart + from;
T* baseTo = mStart + to;
assert_no_opt(baseFrom+span<=mEnd);
assert_no_opt(baseTo+span<=mEnd);
memmove(baseTo,baseFrom,span*sizeof(T));
}
void fill(const T& val)
{
T* dp=mStart;
@@ -232,7 +285,7 @@ template <class T> class Vector {
{
T* dp=mStart+start;
T* end=dp+length;
assert(end<=mEnd);
assert_no_opt(end<=mEnd);
while (dp<end) *dp++=val;
}
@@ -244,13 +297,13 @@ template <class T> class Vector {
T& operator[](size_t index)
{
assert(mStart+index<mEnd);
assert_no_opt(mStart+index<mEnd);
return mStart[index];
}
const T& operator[](size_t index) const
{
assert(mStart+index<mEnd);
assert_no_opt(mStart+index<mEnd);
return mStart[index];
}
@@ -260,7 +313,7 @@ template <class T> class Vector {
T* end() { return mEnd; }
bool isOwner() { return !!mData; } // Do we own any memory ourselves?
//@}
};

60
CommonLibs/config_defs.h Normal file
View File

@@ -0,0 +1,60 @@
#pragma once
/*
* This file contains structures used by both VTY (C, dir CommonLibs) and
* osmo-trx (CXX, dir Transceiver52)
*/
#include <stdbool.h>
enum FillerType {
FILLER_DUMMY,
FILLER_ZERO,
FILLER_NORM_RAND,
FILLER_EDGE_RAND,
FILLER_ACCESS_RAND,
};
enum ReferenceType {
REF_INTERNAL,
REF_EXTERNAL,
REF_GPS,
};
/* Maximum number of physical RF channels */
#define TRX_CHAN_MAX 8
struct trx_ctx;
struct trx_chan {
struct trx_ctx *trx; /* backpointer */
unsigned int idx; /* channel index */
char *rx_path;
char *tx_path;
};
struct trx_cfg {
char *bind_addr;
char *remote_addr;
char *dev_args;
unsigned int base_port;
unsigned int tx_sps;
unsigned int rx_sps;
unsigned int rtsc;
unsigned int rach_delay;
enum ReferenceType clock_ref;
enum FillerType filler;
bool multi_arfcn;
double offset;
double freq_offset_khz;
double rssi_offset;
int ul_fn_offset;
bool force_rssi_offset; /* Force value set in VTY? */
bool swap_channels;
bool ext_rach;
bool egprs;
unsigned int sched_rr;
unsigned int stack_size;
unsigned int num_chans;
struct trx_chan chans[TRX_CHAN_MAX];
};

83
CommonLibs/debug.c Normal file
View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2018-2019 sysmocom - s.f.m.c. GmbH
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
*
* Author: Pau Espin Pedrol <pespin@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/>.
* See the COPYING file in the main directory for details.
*/
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include "debug.h"
/* default categories */
static const struct log_info_cat default_categories[] = {
[DMAIN] = {
.name = "DMAIN",
.description = "Main generic category",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DTRXCLK] = {
.name = "DTRXCLK",
.description = "TRX Master Clock",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DTRXCTRL] = {
.name = "DTRXCTRL",
.description = "TRX CTRL interface",
.color = "\033[1;33m",
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DTRXDDL] = {
.name = "DTRXDDL",
.description = "TRX Data interface Downlink",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DTRXDUL] = {
.name = "DTRXDUL",
.description = "TRX CTRL interface Uplink",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DDEV] = {
.name = "DDEV",
.description = "Device/Driver specific code",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DDEVDRV] = {
.name = "DDEVDRV",
.description = "Logging from external device driver library implementing lower level specifics",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DCTR] = {
.name = "DCTR",
.description = "Rate counter related logging",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
};
const struct log_info log_info = {
.cat = default_categories,
.num_cat = ARRAY_SIZE(default_categories),
};

23
CommonLibs/debug.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/logging.h>
extern const struct log_info log_info;
/* Debug Areas of the code */
enum {
DMAIN,
DTRXCLK,
DTRXCTRL,
DTRXDDL,
DTRXDUL,
DDEV,
DDEVDRV,
DCTR,
};
#define CLOGCHAN(chan, category, level, fmt, args...) do { \
LOGP(category, level, "[chan=%zu] " fmt, chan, ##args); \
} while(0)

71
CommonLibs/osmo_signal.h Normal file
View File

@@ -0,0 +1,71 @@
/* Generic signalling/notification infrastructure */
/* (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
*
* 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/>.
*
*/
#pragma once
#include <osmocom/core/signal.h>
/* Signalling subsystems */
enum signal_subsystems {
SS_MAIN,
SS_DEVICE,
};
/* SS_MAIN signals */
enum SS_MAIN {
S_MAIN_STOP_REQUIRED, /* TRX fatal error, it should be stopped */
};
/* SS_DEVICE signals */
enum SS_DEVICE {
/* Device internal counters changed. Counters are provided as cb data
(struct device_counters). Must be sent with PTHREAD_CANCEL_DISABLE
to avoid deadlocks in case osmo-trx process is asked to exit. */
S_DEVICE_COUNTER_CHANGE,
S_TRX_COUNTER_CHANGE, /* same, but for Transceiver class */
};
/* signal cb for signal <SS_DEVICE,S_DEVICE_COUNTER_CHANGE> */
struct device_counters {
size_t chan;
unsigned int rx_overruns;
unsigned int tx_underruns;
unsigned int rx_dropped_events;
unsigned int rx_dropped_samples;
unsigned int tx_dropped_events;
unsigned int tx_dropped_samples;
};
/* signal cb for signal <SS_DEVICE,S_TRX_COUNTER_CHANGE> */
struct trx_counters {
size_t chan;
unsigned int tx_stale_bursts;
unsigned int tx_unavailable_bursts;
unsigned int tx_trxd_fn_repeated;
unsigned int tx_trxd_fn_outoforder;
unsigned int tx_trxd_fn_skipped;
unsigned int rx_empty_burst;
unsigned int rx_clipping;
unsigned int rx_no_burst_detected;
};

View File

@@ -1,154 +0,0 @@
/*
* Copyright 2010 Kestrel Signal Processing, Inc.
* All rights reserved.
*/
#include "sqlite3.h"
#include "sqlite3util.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
// Wrappers to sqlite operations.
// These will eventually get moved to commonlibs.
int sqlite3_prepare_statement(sqlite3* DB, sqlite3_stmt **stmt, const char* query)
{
int src = SQLITE_BUSY;
while (src==SQLITE_BUSY) {
src = sqlite3_prepare_v2(DB,query,strlen(query),stmt,NULL);
if (src==SQLITE_BUSY) {
usleep(100000);
}
}
if (src) {
fprintf(stderr,"sqlite3_prepare_v2 failed for \"%s\": %s\n",query,sqlite3_errmsg(DB));
sqlite3_finalize(*stmt);
}
return src;
}
int sqlite3_run_query(sqlite3* DB, sqlite3_stmt *stmt)
{
int src = SQLITE_BUSY;
while (src==SQLITE_BUSY) {
src = sqlite3_step(stmt);
if (src==SQLITE_BUSY) {
usleep(100000);
}
}
if ((src!=SQLITE_DONE) && (src!=SQLITE_ROW)) {
fprintf(stderr,"sqlite3_run_query failed: %s: %s\n", sqlite3_sql(stmt), sqlite3_errmsg(DB));
}
return src;
}
bool sqlite3_exists(sqlite3* DB, const char *tableName,
const char* keyName, const char* keyData)
{
size_t stringSize = 100 + strlen(tableName) + strlen(keyName) + strlen(keyData);
char query[stringSize];
sprintf(query,"SELECT * FROM %s WHERE %s == \"%s\"",tableName,keyName,keyData);
// Prepare the statement.
sqlite3_stmt *stmt;
if (sqlite3_prepare_statement(DB,&stmt,query)) return false;
// Read the result.
int src = sqlite3_run_query(DB,stmt);
sqlite3_finalize(stmt);
// Anything there?
return (src == SQLITE_ROW);
}
bool sqlite3_single_lookup(sqlite3* DB, const char *tableName,
const char* keyName, const char* keyData,
const char* valueName, unsigned &valueData)
{
size_t stringSize = 100 + strlen(valueName) + strlen(tableName) + strlen(keyName) + strlen(keyData);
char query[stringSize];
sprintf(query,"SELECT %s FROM %s WHERE %s == \"%s\"",valueName,tableName,keyName,keyData);
// Prepare the statement.
sqlite3_stmt *stmt;
if (sqlite3_prepare_statement(DB,&stmt,query)) return false;
// Read the result.
int src = sqlite3_run_query(DB,stmt);
bool retVal = false;
if (src == SQLITE_ROW) {
valueData = (unsigned)sqlite3_column_int64(stmt,0);
retVal = true;
}
sqlite3_finalize(stmt);
return retVal;
}
// This function returns an allocated string that must be free'd by the caller.
bool sqlite3_single_lookup(sqlite3* DB, const char* tableName,
const char* keyName, const char* keyData,
const char* valueName, char* &valueData)
{
valueData=NULL;
size_t stringSize = 100 + strlen(valueName) + strlen(tableName) + strlen(keyName) + strlen(keyData);
char query[stringSize];
sprintf(query,"SELECT %s FROM %s WHERE %s == \"%s\"",valueName,tableName,keyName,keyData);
// Prepare the statement.
sqlite3_stmt *stmt;
if (sqlite3_prepare_statement(DB,&stmt,query)) return false;
// Read the result.
int src = sqlite3_run_query(DB,stmt);
bool retVal = false;
if (src == SQLITE_ROW) {
const char* ptr = (const char*)sqlite3_column_text(stmt,0);
if (ptr) valueData = strdup(ptr);
retVal = true;
}
sqlite3_finalize(stmt);
return retVal;
}
// This function returns an allocated string that must be free'd by tha caller.
bool sqlite3_single_lookup(sqlite3* DB, const char* tableName,
const char* keyName, unsigned keyData,
const char* valueName, char* &valueData)
{
valueData=NULL;
size_t stringSize = 100 + strlen(valueName) + strlen(tableName) + strlen(keyName) + 20;
char query[stringSize];
sprintf(query,"SELECT %s FROM %s WHERE %s == %u",valueName,tableName,keyName,keyData);
// Prepare the statement.
sqlite3_stmt *stmt;
if (sqlite3_prepare_statement(DB,&stmt,query)) return false;
// Read the result.
int src = sqlite3_run_query(DB,stmt);
bool retVal = false;
if (src == SQLITE_ROW) {
const char* ptr = (const char*)sqlite3_column_text(stmt,0);
if (ptr) valueData = strdup(ptr);
retVal = true;
}
sqlite3_finalize(stmt);
return retVal;
}
bool sqlite3_command(sqlite3* DB, const char* query)
{
// Prepare the statement.
sqlite3_stmt *stmt;
if (sqlite3_prepare_statement(DB,&stmt,query)) return false;
// Run the query.
int src = sqlite3_run_query(DB,stmt);
sqlite3_finalize(stmt);
return src==SQLITE_DONE;
}

View File

@@ -1,29 +0,0 @@
#ifndef SQLITE3UTIL_H
#define SQLITE3UTIL_H
#include <sqlite3.h>
int sqlite3_prepare_statement(sqlite3* DB, sqlite3_stmt **stmt, const char* query);
int sqlite3_run_query(sqlite3* DB, sqlite3_stmt *stmt);
bool sqlite3_single_lookup(sqlite3* DB, const char *tableName,
const char* keyName, const char* keyData,
const char* valueName, unsigned &valueData);
bool sqlite3_single_lookup(sqlite3* DB, const char* tableName,
const char* keyName, const char* keyData,
const char* valueName, char* &valueData);
// This function returns an allocated string that must be free'd by the caller.
bool sqlite3_single_lookup(sqlite3* DB, const char* tableName,
const char* keyName, unsigned keyData,
const char* valueName, char* &valueData);
bool sqlite3_exists(sqlite3* DB, const char* tableName,
const char* keyName, const char* keyData);
/** Run a query, ignoring the result; return true on success. */
bool sqlite3_command(sqlite3* DB, const char* query);
#endif

409
CommonLibs/trx_rate_ctr.cpp Normal file
View File

@@ -0,0 +1,409 @@
/*
* Copyright (C) 2019 sysmocom - s.f.m.c. GmbH
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
*
* Author: Pau Espin Pedrol <pespin@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/>.
* See the COPYING file in the main directory for details.
*/
/*
* rate_ctr API uses several osmocom select loop features, and as a result,
* calls to it must be done through the main thread (the one running the osmocom
* loop in osmo-trx).
* Since read/write from/to SDR is done in separate threads (even read and write
* each use a different thread), we must use some sort of message passing system
* between main thread feeding rate_ctr structures and the Rx/Tx threads
* generating the events.
* The idea is that upon read/write issues, lower layers (SDR APIs) provide us with
* underrun/overrun/droppedPackets information, and in that case we pass that up
* the stack through signal <SS_DEVICE,S_DEVICE_COUNTER_CHANGE> with signal_cb
* being a pointer to a "struct device_counters" structure, which contains
* device (implementation agnostic) statful counters for different kind of
* statistics.
* That signal is processed here in device_sig_cb, where a copy of the "struct
* device_counters" structure is held and the main thread is instructed through
* a timerfd to update rate_ctr APIs against this copy. All this is done inside
* a mutex to avoid different race conditions (between Rx andTx threads, and
* between Rx/Tx and main thread). For the same reason, callers of signal
* <SS_DEVICE,S_DEVICE_COUNTER_CHANGE> (device_sig_cb), that is Rx/Tx threads,
* must do so with PTHREAD_CANCEL_DISABLE, in order to avoid possible deadlocks
* in case the main thread decides to cancel other threads due to a shutdown
* operation (fi SIGKILL received)
*/
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <arpa/inet.h>
extern "C" {
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/select.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/timer.h>
#include "osmo_signal.h"
#include "trx_vty.h"
#include "trx_rate_ctr.h"
}
#include "Threads.h"
#include "Logger.h"
/* Used in dev_ctrs_pending, when set it means that channel slot contains unused
(non-pending) counter data */
#define PENDING_CHAN_NONE SIZE_MAX
static void *trx_rate_ctr_ctx;
static struct rate_ctr_group** rate_ctrs;
static struct device_counters* dev_ctrs_pending;
static struct trx_counters* trx_ctrs_pending;
static size_t chan_len;
static struct osmo_fd dev_rate_ctr_timerfd;
static struct osmo_fd trx_rate_ctr_timerfd;
static Mutex dev_rate_ctr_mutex;
static Mutex trx_rate_ctr_mutex;
struct osmo_timer_list threshold_timer;
static LLIST_HEAD(threshold_list);
static unsigned int threshold_timer_sched_secs;
static bool threshold_initied;
const struct value_string rate_ctr_intv[] = {
{ RATE_CTR_INTV_SEC, "per-second" },
{ RATE_CTR_INTV_MIN, "per-minute" },
{ RATE_CTR_INTV_HOUR, "per-hour" },
{ RATE_CTR_INTV_DAY, "per-day" },
{ 0, NULL }
};
const struct value_string trx_chan_ctr_names[] = {
{ TRX_CTR_DEV_RX_OVERRUNS, "rx_overruns" },
{ TRX_CTR_DEV_TX_UNDERRUNS, "tx_underruns" },
{ TRX_CTR_DEV_RX_DROP_EV, "rx_drop_events" },
{ TRX_CTR_DEV_RX_DROP_SMPL, "rx_drop_samples" },
{ TRX_CTR_DEV_TX_DROP_EV, "tx_drop_events" },
{ TRX_CTR_DEV_TX_DROP_SMPL, "tx_drop_samples" },
{ TRX_CTR_TRX_TX_STALE_BURSTS, "tx_stale_bursts" },
{ TRX_CTR_TRX_TX_UNAVAILABLE_BURSTS, "tx_unavailable_bursts" },
{ TRX_CTR_TRX_TRXD_FN_REPEATED, "tx_trxd_fn_repeated" },
{ TRX_CTR_TRX_TRXD_FN_OUTOFORDER, "tx_trxd_fn_outoforder" },
{ TRX_CTR_TRX_TRXD_FN_SKIPPED, "tx_trxd_fn_skipped" },
{ TRX_CTR_TRX_RX_EMPTY_BURST, "rx_empty_burst" },
{ TRX_CTR_TRX_RX_CLIPPING, "rx_clipping" },
{ TRX_CTR_TRX_RX_NO_BURST_DETECTED, "rx_no_burst_detected" },
{ 0, NULL }
};
static const struct rate_ctr_desc trx_chan_ctr_desc[] = {
[TRX_CTR_DEV_RX_OVERRUNS] = { "device:rx_overruns", "Number of Rx overruns in FIFO queue" },
[TRX_CTR_DEV_TX_UNDERRUNS] = { "device:tx_underruns", "Number of Tx underruns in FIFO queue" },
[TRX_CTR_DEV_RX_DROP_EV] = { "device:rx_drop_events", "Number of times Rx samples were dropped by HW" },
[TRX_CTR_DEV_RX_DROP_SMPL] = { "device:rx_drop_samples", "Number of Rx samples dropped by HW" },
[TRX_CTR_DEV_TX_DROP_EV] = { "device:tx_drop_events", "Number of times Tx samples were dropped by HW" },
[TRX_CTR_DEV_TX_DROP_SMPL] = { "device:tx_drop_samples", "Number of Tx samples dropped by HW" },
[TRX_CTR_TRX_TX_STALE_BURSTS] = { "trx:tx_stale_bursts", "Number of Tx burts dropped by TRX due to arriving too late" },
[TRX_CTR_TRX_TX_UNAVAILABLE_BURSTS] = { "trx:tx_unavailable_bursts","Number of Tx burts unavailable (not enqueued) at the time they should be transmitted" },
[TRX_CTR_TRX_TRXD_FN_REPEATED] = { "trx:tx_trxd_fn_repeated", "Number of Tx burts received from TRXD with repeated FN" },
[TRX_CTR_TRX_TRXD_FN_OUTOFORDER] = { "trx:tx_trxd_fn_outoforder","Number of Tx burts received from TRXD with a past FN" },
[TRX_CTR_TRX_TRXD_FN_SKIPPED] = { "trx:tx_trxd_fn_skipped", "Number of Tx burts potentially skipped due to FN jumps" },
[TRX_CTR_TRX_RX_EMPTY_BURST] = { "trx:rx_empty_burst", "Number of Rx bursts empty" },
[TRX_CTR_TRX_RX_CLIPPING] = { "trx:rx_clipping", "Number of Rx bursts discarded due to clipping" },
[TRX_CTR_TRX_RX_NO_BURST_DETECTED] = { "trx:rx_no_burst_detected", "Number of Rx burts discarded due to burst detection error" },
};
static const struct rate_ctr_group_desc trx_chan_ctr_group_desc = {
.group_name_prefix = "trx:chan",
.group_description = "osmo-trx statistics",
.class_id = OSMO_STATS_CLASS_GLOBAL,
.num_ctr = ARRAY_SIZE(trx_chan_ctr_desc),
.ctr_desc = trx_chan_ctr_desc,
};
static int dev_rate_ctr_timerfd_cb(struct osmo_fd *ofd, unsigned int what) {
size_t chan;
struct rate_ctr *ctr;
LOGC(DCTR, INFO) << "Main thread is updating Device counters";
dev_rate_ctr_mutex.lock();
for (chan = 0; chan < chan_len; chan++) {
if (dev_ctrs_pending[chan].chan == PENDING_CHAN_NONE)
continue;
LOGCHAN(chan, DCTR, DEBUG) << "rate_ctr update";
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_DEV_RX_OVERRUNS);
rate_ctr_add(ctr, dev_ctrs_pending[chan].rx_overruns - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_DEV_TX_UNDERRUNS);
rate_ctr_add(ctr, dev_ctrs_pending[chan].tx_underruns - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_DEV_RX_DROP_EV);
rate_ctr_add(ctr, dev_ctrs_pending[chan].rx_dropped_events - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_DEV_RX_DROP_SMPL);
rate_ctr_add(ctr, dev_ctrs_pending[chan].rx_dropped_samples - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_DEV_TX_DROP_EV);
rate_ctr_add(ctr, dev_ctrs_pending[chan].tx_dropped_events - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_DEV_TX_DROP_SMPL);
rate_ctr_add(ctr, dev_ctrs_pending[chan].tx_dropped_samples - ctr->current);
/* Mark as done */
dev_ctrs_pending[chan].chan = PENDING_CHAN_NONE;
}
if (osmo_timerfd_disable(&dev_rate_ctr_timerfd) < 0)
LOGC(DCTR, ERROR) << "Failed to disable timerfd";
dev_rate_ctr_mutex.unlock();
return 0;
}
static int trx_rate_ctr_timerfd_cb(struct osmo_fd *ofd, unsigned int what) {
size_t chan;
struct rate_ctr *ctr;
LOGC(DCTR, INFO) << "Main thread is updating Transceiver counters";
trx_rate_ctr_mutex.lock();
for (chan = 0; chan < chan_len; chan++) {
if (trx_ctrs_pending[chan].chan == PENDING_CHAN_NONE)
continue;
LOGCHAN(chan, DCTR, DEBUG) << "rate_ctr update";
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_TX_STALE_BURSTS);
rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_stale_bursts - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_TX_UNAVAILABLE_BURSTS);
rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_unavailable_bursts - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_TRXD_FN_REPEATED);
rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_trxd_fn_repeated - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_TRXD_FN_OUTOFORDER);
rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_trxd_fn_outoforder - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_TRXD_FN_SKIPPED);
rate_ctr_add(ctr, trx_ctrs_pending[chan].tx_trxd_fn_skipped - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_RX_EMPTY_BURST);
rate_ctr_add(ctr, trx_ctrs_pending[chan].rx_empty_burst - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_RX_CLIPPING);
rate_ctr_add(ctr, trx_ctrs_pending[chan].rx_clipping - ctr->current);
ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], TRX_CTR_TRX_RX_NO_BURST_DETECTED);
rate_ctr_add(ctr, trx_ctrs_pending[chan].rx_no_burst_detected - ctr->current);
/* Mark as done */
trx_ctrs_pending[chan].chan = PENDING_CHAN_NONE;
}
if (osmo_timerfd_disable(&trx_rate_ctr_timerfd) < 0)
LOGC(DCTR, ERROR) << "Failed to disable timerfd";
trx_rate_ctr_mutex.unlock();
return 0;
}
/* Callback function to be called every time we receive a signal from DEVICE */
static int device_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct device_counters *dev_ctr;
struct trx_counters *trx_ctr;
/* Delay sched around 20 ms, in case we receive several calls from several
* channels batched */
struct timespec next_sched = {.tv_sec = 0, .tv_nsec = 20*1000*1000};
/* no automatic re-trigger */
struct timespec intv_sched = {.tv_sec = 0, .tv_nsec = 0};
char err_buf[256];
switch (signal) {
case S_DEVICE_COUNTER_CHANGE:
dev_ctr = (struct device_counters *)signal_data;
LOGCHAN(dev_ctr->chan, DCTR, INFO) << "Received counter change from radioDevice";
dev_rate_ctr_mutex.lock();
dev_ctrs_pending[dev_ctr->chan] = *dev_ctr;
if (osmo_timerfd_schedule(&dev_rate_ctr_timerfd, &next_sched, &intv_sched) < 0) {
LOGC(DCTR, ERROR) << "Failed to schedule timerfd: " << errno
<< " = "<< strerror_r(errno, err_buf, sizeof(err_buf));
}
dev_rate_ctr_mutex.unlock();
break;
case S_TRX_COUNTER_CHANGE:
trx_ctr = (struct trx_counters *)signal_data;
LOGCHAN(trx_ctr->chan, DCTR, INFO) << "Received counter change from Transceiver";
trx_rate_ctr_mutex.lock();
trx_ctrs_pending[trx_ctr->chan] = *trx_ctr;
if (osmo_timerfd_schedule(&trx_rate_ctr_timerfd, &next_sched, &intv_sched) < 0) {
LOGC(DCTR, ERROR) << "Failed to schedule timerfd: " << errno
<< " = "<< strerror_r(errno, err_buf, sizeof(err_buf));
}
trx_rate_ctr_mutex.unlock();
break;
default:
break;
}
return 0;
}
/************************************
* ctr_threshold APIs
************************************/
static const char* ctr_threshold_2_vty_str(struct ctr_threshold *ctr)
{
static char buf[256];
int rc = 0;
rc += snprintf(buf, sizeof(buf), "ctr-error-threshold %s", get_value_string(trx_chan_ctr_names, ctr->ctr_id));
rc += snprintf(buf + rc, sizeof(buf) - rc, " %d %s", ctr->val, get_value_string(rate_ctr_intv, ctr->intv));
return buf;
}
static void threshold_timer_cb(void *data)
{
struct ctr_threshold *ctr_thr;
struct rate_ctr *rate_ctr;
size_t chan;
LOGC(DCTR, DEBUG) << "threshold_timer_cb fired!";
llist_for_each_entry(ctr_thr, &threshold_list, list) {
for (chan = 0; chan < chan_len; chan++) {
rate_ctr = rate_ctr_group_get_ctr(rate_ctrs[chan], ctr_thr->ctr_id);
LOGCHAN(chan, DCTR, INFO) << "checking threshold: " << ctr_threshold_2_vty_str(ctr_thr)
<< " ("<< rate_ctr->intv[ctr_thr->intv].rate << " vs " << ctr_thr->val << ")";
if (rate_ctr->intv[ctr_thr->intv].rate >= ctr_thr->val) {
LOGCHAN(chan, DCTR, FATAL) << "threshold reached, stopping! " << ctr_threshold_2_vty_str(ctr_thr)
<< " ("<< rate_ctr->intv[ctr_thr->intv].rate << " vs " << ctr_thr->val << ")";
osmo_signal_dispatch(SS_MAIN, S_MAIN_STOP_REQUIRED, NULL);
return;
}
}
}
osmo_timer_schedule(&threshold_timer, threshold_timer_sched_secs, 0);
}
static size_t ctr_threshold_2_seconds(struct ctr_threshold *ctr)
{
size_t mult = 0;
switch (ctr->intv) {
case RATE_CTR_INTV_SEC:
mult = 1;
break;
case RATE_CTR_INTV_MIN:
mult = 60;
break;
case RATE_CTR_INTV_HOUR:
mult = 60*60;
break;
case RATE_CTR_INTV_DAY:
mult = 60*60*24;
break;
default:
OSMO_ASSERT(false);
}
return mult;
}
static void threshold_timer_update_intv() {
struct ctr_threshold *ctr, *min_ctr;
size_t secs, min_secs;
/* Avoid scheduling timer until itself and other structures are prepared
by trx_rate_ctr_init */
if (!threshold_initied)
return;
if (llist_empty(&threshold_list)) {
osmo_timer_del(&threshold_timer);
return;
}
min_ctr = llist_first_entry(&threshold_list, struct ctr_threshold, list);
min_secs = ctr_threshold_2_seconds(min_ctr);
llist_for_each_entry(ctr, &threshold_list, list) {
secs = ctr_threshold_2_seconds(ctr);
if (min_secs > secs)
min_secs = secs;
}
threshold_timer_sched_secs = OSMO_MAX((int)(min_secs / 2 - 1), 1);
LOGC(DCTR, INFO) << "New ctr-error-threshold check interval: "
<< threshold_timer_sched_secs << " seconds";
osmo_timer_schedule(&threshold_timer, threshold_timer_sched_secs, 0);
}
/* Init rate_ctr subsystem. Expected to be called during process start by main thread before VTY is ready */
void trx_rate_ctr_init(void *ctx, struct trx_ctx* trx_ctx)
{
size_t i;
trx_rate_ctr_ctx = ctx;
chan_len = trx_ctx->cfg.num_chans;
dev_ctrs_pending = (struct device_counters*) talloc_zero_size(ctx, chan_len * sizeof(struct device_counters));
trx_ctrs_pending = (struct trx_counters*) talloc_zero_size(ctx, chan_len * sizeof(struct trx_counters));
rate_ctrs = (struct rate_ctr_group**) talloc_zero_size(ctx, chan_len * sizeof(struct rate_ctr_group*));
for (i = 0; i < chan_len; i++) {
dev_ctrs_pending[i].chan = PENDING_CHAN_NONE;
trx_ctrs_pending[i].chan = PENDING_CHAN_NONE;
rate_ctrs[i] = rate_ctr_group_alloc(ctx, &trx_chan_ctr_group_desc, i);
if (!rate_ctrs[i]) {
LOGCHAN(i, DCTR, ERROR) << "Failed to allocate rate ctr";
exit(1);
}
}
dev_rate_ctr_timerfd.fd = -1;
if (osmo_timerfd_setup(&dev_rate_ctr_timerfd, dev_rate_ctr_timerfd_cb, NULL) < 0) {
LOGC(DCTR, ERROR) << "Failed to setup timerfd";
exit(1);
}
trx_rate_ctr_timerfd.fd = -1;
if (osmo_timerfd_setup(&trx_rate_ctr_timerfd, trx_rate_ctr_timerfd_cb, NULL) < 0) {
LOGC(DCTR, ERROR) << "Failed to setup timerfd";
exit(1);
}
osmo_signal_register_handler(SS_DEVICE, device_sig_cb, NULL);
/* Now set up threshold checks */
threshold_initied = true;
osmo_timer_setup(&threshold_timer, threshold_timer_cb, NULL);
threshold_timer_update_intv();
}
void trx_rate_ctr_threshold_add(struct ctr_threshold *ctr)
{
struct ctr_threshold *new_ctr;
new_ctr = talloc_zero(trx_rate_ctr_ctx, struct ctr_threshold);
*new_ctr = *ctr;
LOGC(DCTR, NOTICE) << "Adding new threshold check: " << ctr_threshold_2_vty_str(new_ctr);
llist_add(&new_ctr->list, &threshold_list);
threshold_timer_update_intv();
}
int trx_rate_ctr_threshold_del(struct ctr_threshold *del_ctr)
{
struct ctr_threshold *ctr;
llist_for_each_entry(ctr, &threshold_list, list) {
if (ctr->intv != del_ctr->intv ||
ctr->ctr_id != del_ctr->ctr_id ||
ctr->val != del_ctr->val)
continue;
LOGC(DCTR, NOTICE) << "Deleting threshold check: " << ctr_threshold_2_vty_str(del_ctr);
llist_del(&ctr->list);
talloc_free(ctr);
threshold_timer_update_intv();
return 0;
}
return -1;
}
void trx_rate_ctr_threshold_write_config(struct vty *vty, char *indent_prefix)
{
struct ctr_threshold *ctr;
llist_for_each_entry(ctr, &threshold_list, list) {
vty_out(vty, "%s%s%s", indent_prefix, ctr_threshold_2_vty_str(ctr), VTY_NEWLINE);
}
}

38
CommonLibs/trx_rate_ctr.h Normal file
View File

@@ -0,0 +1,38 @@
#pragma once
#include <osmocom/core/rate_ctr.h>
#include <osmocom/vty/command.h>
enum TrxCtr {
TRX_CTR_DEV_RX_OVERRUNS,
TRX_CTR_DEV_TX_UNDERRUNS,
TRX_CTR_DEV_RX_DROP_EV,
TRX_CTR_DEV_RX_DROP_SMPL,
TRX_CTR_DEV_TX_DROP_EV,
TRX_CTR_DEV_TX_DROP_SMPL,
TRX_CTR_TRX_TX_STALE_BURSTS,
TRX_CTR_TRX_TX_UNAVAILABLE_BURSTS,
TRX_CTR_TRX_TRXD_FN_REPEATED,
TRX_CTR_TRX_TRXD_FN_OUTOFORDER,
TRX_CTR_TRX_TRXD_FN_SKIPPED,
TRX_CTR_TRX_RX_EMPTY_BURST,
TRX_CTR_TRX_RX_CLIPPING,
TRX_CTR_TRX_RX_NO_BURST_DETECTED,
};
struct ctr_threshold {
/*! Linked list of all counter groups in the system */
struct llist_head list;
enum rate_ctr_intv intv;
enum TrxCtr ctr_id;
uint32_t val;
};
extern const struct value_string rate_ctr_intv[];
extern const struct value_string trx_chan_ctr_names[];
struct trx_ctx;
void trx_rate_ctr_init(void *ctx, struct trx_ctx* trx_ctx);
void trx_rate_ctr_threshold_add(struct ctr_threshold *ctr);
int trx_rate_ctr_threshold_del(struct ctr_threshold *del_ctr);
void trx_rate_ctr_threshold_write_config(struct vty *vty, char *indent_prefix);

814
CommonLibs/trx_vty.c Normal file
View File

@@ -0,0 +1,814 @@
/*
* Copyright (C) 2018-2019 sysmocom - s.f.m.c. GmbH
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
*
* Author: Pau Espin Pedrol <pespin@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/>.
* See the COPYING file in the main directory for details.
*/
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/misc.h>
#include "trx_rate_ctr.h"
#include "trx_vty.h"
#include "../config.h"
static struct trx_ctx* g_trx_ctx;
const struct value_string clock_ref_names[] = {
{ REF_INTERNAL, "internal" },
{ REF_EXTERNAL, "external" },
{ REF_GPS, "gpsdo" },
{ 0, NULL }
};
const struct value_string filler_names[] = {
{ FILLER_DUMMY, "Dummy bursts (C0 only)" },
{ FILLER_ZERO, "Empty bursts" },
{ FILLER_NORM_RAND, "GMSK Normal Bursts with random payload" },
{ FILLER_EDGE_RAND, "8-PSK Normal Bursts with random payload" },
{ FILLER_ACCESS_RAND, "Access Bursts with random payload" },
{ 0, NULL }
};
static const struct value_string filler_types[] = {
{ FILLER_DUMMY, "dummy" },
{ FILLER_ZERO, "zero" },
{ FILLER_NORM_RAND, "random-nb-gmsk" },
{ FILLER_EDGE_RAND, "random-nb-8psk" },
{ FILLER_ACCESS_RAND, "random-ab" },
{ 0, NULL }
};
static const struct value_string filler_docs[] = {
{ FILLER_DUMMY, "Send a Dummy Burst on C0 (TRX0) and empty burst on other channels" },
{ FILLER_ZERO, "Send an empty burst (default)" },
{ FILLER_NORM_RAND, "Send a GMSK modulated Normal Burst with random bits (spectrum mask testing)" },
{ FILLER_EDGE_RAND, "Send an 8-PSK modulated Normal Burst with random bits (spectrum mask testing)" },
{ FILLER_ACCESS_RAND, "Send an Access Burst with random bits (Rx/Tx alignment testing)" },
{ 0, NULL }
};
struct trx_ctx *trx_from_vty(struct vty *v)
{
/* It can't hurt to force callers to continue to pass the vty instance
* to this function, in case we'd like to retrieve the global
* trx instance from the vty at some point in the future. But
* until then, just return the global pointer, which should have been
* initialized by trx_vty_init().
*/
OSMO_ASSERT(g_trx_ctx);
return g_trx_ctx;
}
enum trx_vty_node {
TRX_NODE = _LAST_OSMOVTY_NODE + 1,
CHAN_NODE,
};
static struct cmd_node trx_node = {
TRX_NODE,
"%s(config-trx)# ",
1,
};
static struct cmd_node chan_node = {
CHAN_NODE,
"%s(config-trx-chan)# ",
1,
};
DEFUN(cfg_trx, cfg_trx_cmd,
"trx",
"Configure the TRX\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
if (!trx)
return CMD_WARNING;
vty->node = TRX_NODE;
return CMD_SUCCESS;
}
DEFUN(cfg_bind_ip, cfg_bind_ip_cmd,
"bind-ip " VTY_IPV4_CMD,
"Set the IP address for the local bind\n"
"IPv4 Address\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
osmo_talloc_replace_string(trx, &trx->cfg.bind_addr, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_remote_ip, cfg_remote_ip_cmd,
"remote-ip " VTY_IPV4_CMD,
"Set the IP address for the remote BTS\n"
"IPv4 Address\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
osmo_talloc_replace_string(trx, &trx->cfg.remote_addr, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_base_port, cfg_base_port_cmd,
"base-port <1-65535>",
"Set the TRX Base Port\n"
"TRX Base Port\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.base_port = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_dev_args, cfg_dev_args_cmd,
"dev-args DESC",
"Set the device-specific arguments to pass to the device\n"
"Device-specific arguments\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
osmo_talloc_replace_string(trx, &trx->cfg.dev_args, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_tx_sps, cfg_tx_sps_cmd,
"tx-sps (1|4)",
"Set the Tx Samples-per-Symbol\n"
"Tx Samples-per-Symbol\n"
"1 Sample-per-Symbol\n"
"4 Samples-per-Symbol\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.tx_sps = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_rx_sps, cfg_rx_sps_cmd,
"rx-sps (1|4)",
"Set the Rx Samples-per-Symbol\n"
"Rx Samples-per-Symbol\n"
"1 Sample-per-Symbol\n"
"4 Samples-per-Symbol\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.rx_sps = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_clock_ref, cfg_clock_ref_cmd,
"clock-ref (internal|external|gpsdo)",
"Set the Reference Clock\n"
"Enable internal reference (default)\n"
"Enable external 10 MHz reference\n"
"Enable GPSDO reference\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.clock_ref = get_string_value(clock_ref_names, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_multi_arfcn, cfg_multi_arfcn_cmd,
"multi-arfcn (disable|enable)",
"Multi-ARFCN transceiver mode (default=disable)\n"
"Enable multi-ARFCN mode\n" "Disable multi-ARFCN mode\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
if (strcmp("disable", argv[0]) == 0) {
trx->cfg.multi_arfcn = false;
return CMD_SUCCESS;
}
if (trx->cfg.num_chans > TRX_MCHAN_MAX) {
vty_out(vty, "Up to %i channels are supported for multi-TRX mode%s",
TRX_MCHAN_MAX, VTY_NEWLINE);
return CMD_WARNING;
}
trx->cfg.multi_arfcn = true;
return CMD_SUCCESS;
}
DEFUN(cfg_offset, cfg_offset_cmd,
"offset FLOAT",
"Set the baseband frequency offset (default=0, auto)\n"
"Baseband Frequency Offset\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.offset = atof(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_freq_offset, cfg_freq_offset_cmd,
"freq-offset FLOAT",
"Apply an artificial offset to Rx/Tx carrier frequency\n"
"Frequency offset in kHz (e.g. -145300)\n",
CMD_ATTR_HIDDEN)
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.freq_offset_khz = atof(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_rssi_offset, cfg_rssi_offset_cmd,
"rssi-offset FLOAT [relative]",
"Set the RSSI to dBm offset in dB (default=0)\n"
"RSSI to dBm offset in dB\n"
"Add to the default rssi-offset value instead of completely replacing it\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.rssi_offset = atof(argv[0]);
trx->cfg.force_rssi_offset = (argc == 1);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_ul_fn_offset, cfg_ul_fn_offset_cmd,
"ul-fn-offset <-10-10>",
"Adjusts the uplink frame FN by the specified amount\n"
"Frame Number offset\n",
CMD_ATTR_HIDDEN)
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.ul_fn_offset = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_swap_channels, cfg_swap_channels_cmd,
"swap-channels (disable|enable)",
"Swap primary and secondary channels of the PHY (if any)\n"
"Do not swap primary and secondary channels (default)\n"
"Swap primary and secondary channels\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
if (strcmp("disable", argv[0]) == 0) {
trx->cfg.swap_channels = false;
} else if (strcmp("enable", argv[0]) == 0) {
trx->cfg.swap_channels = true;
} else {
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_egprs, cfg_egprs_cmd,
"egprs (disable|enable)",
"EGPRS (8-PSK demodulation) support (default=disable)\n"
"Disable EGPRS (8-PSK demodulation) support\n"
"Enable EGPRS (8-PSK demodulation) support\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
if (strcmp("disable", argv[0]) == 0) {
trx->cfg.egprs = false;
} else if (strcmp("enable", argv[0]) == 0) {
trx->cfg.egprs = true;
} else {
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_ext_rach, cfg_ext_rach_cmd,
"ext-rach (disable|enable)",
"11-bit Access Burst correlation support (default=disable)\n"
"Disable 11-bit Access Burst (TS1 & TS2) correlation\n"
"Enable 11-bit Access Burst (TS1 & TS2) correlation\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
if (strcmp("disable", argv[0]) == 0)
trx->cfg.ext_rach = false;
if (strcmp("enable", argv[0]) == 0)
trx->cfg.ext_rach = true;
return CMD_SUCCESS;
}
DEFUN_DEPRECATED(cfg_rt_prio, cfg_rt_prio_cmd,
"rt-prio <1-32>",
"Set the SCHED_RR real-time priority\n"
"Real time priority\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.sched_rr = atoi(argv[0]);
vty_out (vty, "%% 'rt-prio %u' is deprecated, use 'policy rr %u' under 'sched' node instead%s",
trx->cfg.sched_rr, trx->cfg.sched_rr, VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(cfg_stack_size, cfg_stack_size_cmd,
"stack-size <0-2147483647>",
"Set the stack size per thread in BYTE, 0 = OS default\n"
"Stack size per thread in BYTE\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.stack_size = atoi(argv[0]);
return CMD_SUCCESS;
}
#define CFG_FILLER_DOC_STR \
"Filler burst settings\n"
DEFUN(cfg_filler, cfg_filler_type_cmd,
"AUTO-GENERATED", "AUTO-GENERATED")
{
struct trx_ctx *trx = trx_from_vty(vty);
// trx->cfg.filler is unsigned, so we need an interim int var to detect errors
int type = get_string_value(filler_types, argv[0]);
if (type < 0) {
trx->cfg.filler = FILLER_ZERO;
return CMD_WARNING;
}
trx->cfg.filler = type;
return CMD_SUCCESS;
}
DEFUN(cfg_test_rtsc, cfg_filler_tsc_cmd,
"filler tsc <0-7>",
CFG_FILLER_DOC_STR
"Set the TSC for GMSK/8-PSK Normal Burst random fillers. Used only with 'random-nb-gmsk' and"
" 'random-nb-8psk' filler types. (default=0)\n"
"TSC\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.rtsc = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_test_rach_delay, cfg_filler_rach_delay_cmd,
"filler access-burst-delay <0-68>",
CFG_FILLER_DOC_STR
"Set the delay for Access Burst random fillers. Used only with 'random-ab' filler type. (default=0)\n"
"RACH delay in symbols\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx->cfg.rach_delay = atoi(argv[0]);
return CMD_SUCCESS;
}
static int vty_ctr_name_2_id(const char* str) {
size_t i;
for (i = 0; trx_chan_ctr_names[i].str; i++) {
if (strstr(trx_chan_ctr_names[i].str, str)) {
return i;
}
}
return -1;
}
static int vty_intv_name_2_id(const char* str) {
size_t i;
for (i = 0; rate_ctr_intv[i].str; i++) {
if (strcmp(rate_ctr_intv[i].str, str) == 0) {
return i;
}
}
return -1;
}
#define THRESHOLD_ARGS "(rx_overruns|tx_underruns|rx_drop_events|rx_drop_samples|tx_drop_events|tx_drop_samples|tx_stale_bursts|tx_unavailable_bursts|tx_trxd_fn_repeated|tx_trxd_fn_outoforder|tx_trxd_fn_skipped)"
#define THRESHOLD_STR_VAL(s) "Set threshold value for rate_ctr device:" OSMO_STRINGIFY_VAL(s) "\n"
#define THRESHOLD_STRS \
THRESHOLD_STR_VAL(rx_overruns) \
THRESHOLD_STR_VAL(tx_underruns) \
THRESHOLD_STR_VAL(rx_drop_events) \
THRESHOLD_STR_VAL(rx_drop_samples) \
THRESHOLD_STR_VAL(tx_drop_events) \
THRESHOLD_STR_VAL(tx_drop_samples) \
THRESHOLD_STR_VAL(tx_stale_bursts) \
THRESHOLD_STR_VAL(tx_unavailable_bursts) \
THRESHOLD_STR_VAL(tx_trxd_fn_repeated) \
THRESHOLD_STR_VAL(tx_trxd_fn_outoforder) \
THRESHOLD_STR_VAL(tx_trxd_fn_skipped) \
""
#define INTV_ARGS "(per-second|per-minute|per-hour|per-day)"
#define INTV_STR_VAL(s) "Threshold value sampled " OSMO_STRINGIFY_VAL(s) "\n"
#define INTV_STRS \
INTV_STR_VAL(per-second) \
INTV_STR_VAL(per-minute) \
INTV_STR_VAL(per-hour) \
INTV_STR_VAL(per-day)
DEFUN_ATTR(cfg_ctr_error_threshold, cfg_ctr_error_threshold_cmd,
"ctr-error-threshold " THRESHOLD_ARGS " <0-65535> " INTV_ARGS,
"Threshold rate for error counter\n"
THRESHOLD_STRS
"Value to set for threshold\n"
INTV_STRS,
CMD_ATTR_IMMEDIATE)
{
int rc;
struct ctr_threshold ctr;
struct trx_ctx *trx = trx_from_vty(vty);
rc = vty_ctr_name_2_id(argv[0]);
if (rc < 0) {
vty_out(vty, "No valid ctr_name found for ctr-error-threshold %s%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
ctr.ctr_id = (enum TrxCtr)rc;
ctr.val = atoi(argv[1]);
rc = vty_intv_name_2_id(argv[2]);
if (rc < 0) {
vty_out(vty, "No valid time frame found for ctr-error-threshold %s %d %s%s",
argv[0], ctr.val, argv[2], VTY_NEWLINE);
return CMD_WARNING;
}
ctr.intv = (enum rate_ctr_intv) rc;
trx_rate_ctr_threshold_add(&ctr);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_no_ctr_error_threshold, cfg_no_ctr_error_threshold_cmd,
"no ctr-error-threshold " THRESHOLD_ARGS " <0-65535> " INTV_ARGS,
NO_STR "Threshold rate for error counter\n"
THRESHOLD_STRS
"Value to set for threshold\n"
INTV_STRS,
CMD_ATTR_IMMEDIATE)
{
int rc;
struct ctr_threshold ctr;
struct trx_ctx *trx = trx_from_vty(vty);
rc = vty_ctr_name_2_id(argv[0]);
if (rc < 0) {
vty_out(vty, "No valid ctr_name found for ctr-error-threshold %s%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
ctr.ctr_id = (enum TrxCtr)rc;
ctr.val = atoi(argv[1]);
rc = vty_intv_name_2_id(argv[2]);
if (rc < 0) {
vty_out(vty, "No valid time frame found for ctr-error-threshold %s %d %s%s",
argv[0], ctr.val, argv[2], VTY_NEWLINE);
return CMD_WARNING;
}
ctr.intv = (enum rate_ctr_intv) rc;
if (trx_rate_ctr_threshold_del(&ctr) < 0) {
vty_out(vty, "no ctr-error-threshold: Entry to delete not found%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_chan, cfg_chan_cmd,
"chan <0-100>",
"Select a channel to configure\n"
"Channel index\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
int idx = atoi(argv[0]);
if (idx >= TRX_CHAN_MAX) {
vty_out(vty, "Chan list full.%s", VTY_NEWLINE);
return CMD_WARNING;
} else if (trx->cfg.multi_arfcn && trx->cfg.num_chans >= TRX_MCHAN_MAX) {
vty_out(vty, "Up to %i channels are supported for multi-TRX mode%s",
TRX_MCHAN_MAX, VTY_NEWLINE);
return CMD_WARNING;
}
if (trx->cfg.num_chans < idx) { /* Unexisting or creating non-consecutive */
vty_out(vty, "Non-existent or non-consecutive chan %d.%s",
idx, VTY_NEWLINE);
return CMD_WARNING;
} else if (trx->cfg.num_chans == idx) { /* creating it */
trx->cfg.num_chans++;
trx->cfg.chans[idx].trx = trx;
trx->cfg.chans[idx].idx = idx;
}
vty->node = CHAN_NODE;
vty->index = &trx->cfg.chans[idx];
return CMD_SUCCESS;
}
DEFUN(cfg_chan_rx_path, cfg_chan_rx_path_cmd,
"rx-path NAME",
"Set the Rx Path\n"
"Rx Path name\n")
{
struct trx_chan *chan = vty->index;
if (chan->trx->cfg.multi_arfcn && chan->idx > 0) {
vty_out(vty, "%% Setting 'rx-path' for chan %u in multi-ARFCN mode "
"does not make sense, because only chan 0 is used%s",
chan->idx, VTY_NEWLINE);
}
osmo_talloc_replace_string(chan->trx, &chan->rx_path, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_chan_tx_path, cfg_chan_tx_path_cmd,
"tx-path NAME",
"Set the Tx Path\n"
"Tx Path name\n")
{
struct trx_chan *chan = vty->index;
if (chan->trx->cfg.multi_arfcn && chan->idx > 0) {
vty_out(vty, "%% Setting 'tx-path' for chan %u in multi-ARFCN mode "
"does not make sense, because only chan 0 is used%s",
chan->idx, VTY_NEWLINE);
}
osmo_talloc_replace_string(chan->trx, &chan->tx_path, argv[0]);
return CMD_SUCCESS;
}
static int dummy_config_write(struct vty *v)
{
return CMD_SUCCESS;
}
static int config_write_trx(struct vty *vty)
{
struct trx_chan *chan;
int i;
struct trx_ctx *trx = trx_from_vty(vty);
vty_out(vty, "trx%s", VTY_NEWLINE);
if (trx->cfg.bind_addr)
vty_out(vty, " bind-ip %s%s", trx->cfg.bind_addr, VTY_NEWLINE);
if (trx->cfg.remote_addr)
vty_out(vty, " remote-ip %s%s", trx->cfg.remote_addr, VTY_NEWLINE);
if (trx->cfg.base_port != DEFAULT_TRX_PORT)
vty_out(vty, " base-port %u%s", trx->cfg.base_port, VTY_NEWLINE);
if (trx->cfg.dev_args)
vty_out(vty, " dev-args %s%s", trx->cfg.dev_args, VTY_NEWLINE);
if (trx->cfg.tx_sps != DEFAULT_TX_SPS)
vty_out(vty, " tx-sps %u%s", trx->cfg.tx_sps, VTY_NEWLINE);
if (trx->cfg.rx_sps != DEFAULT_RX_SPS)
vty_out(vty, " rx-sps %u%s", trx->cfg.rx_sps, VTY_NEWLINE);
if (trx->cfg.clock_ref != REF_INTERNAL)
vty_out(vty, " clock-ref %s%s", get_value_string(clock_ref_names, trx->cfg.clock_ref), VTY_NEWLINE);
vty_out(vty, " multi-arfcn %s%s", trx->cfg.multi_arfcn ? "enable" : "disable", VTY_NEWLINE);
if (trx->cfg.offset != 0)
vty_out(vty, " offset %f%s", trx->cfg.offset, VTY_NEWLINE);
if (trx->cfg.freq_offset_khz != 0)
vty_out(vty, " freq-offset %f%s", trx->cfg.freq_offset_khz, VTY_NEWLINE);
if (!(trx->cfg.rssi_offset == 0 && !trx->cfg.force_rssi_offset))
vty_out(vty, " rssi-offset %f%s%s", trx->cfg.rssi_offset,
trx->cfg.force_rssi_offset ? " relative": "", VTY_NEWLINE);
vty_out(vty, " swap-channels %s%s", trx->cfg.swap_channels ? "enable" : "disable", VTY_NEWLINE);
vty_out(vty, " egprs %s%s", trx->cfg.egprs ? "enable" : "disable", VTY_NEWLINE);
vty_out(vty, " ext-rach %s%s", trx->cfg.ext_rach ? "enable" : "disable", VTY_NEWLINE);
if (trx->cfg.sched_rr != 0)
vty_out(vty, " rt-prio %u%s", trx->cfg.sched_rr, VTY_NEWLINE);
if (trx->cfg.filler != FILLER_ZERO)
vty_out(vty, " filler type %s%s", get_value_string(filler_types, trx->cfg.filler), VTY_NEWLINE);
if (trx->cfg.rtsc > 0)
vty_out(vty, " filler tsc %u%s", trx->cfg.rtsc, VTY_NEWLINE);
if (trx->cfg.rach_delay > 0)
vty_out(vty, " filler access-burst-delay %u%s", trx->cfg.rach_delay, VTY_NEWLINE);
if (trx->cfg.stack_size != 0)
vty_out(vty, " stack-size %u%s", trx->cfg.stack_size, VTY_NEWLINE);
if (trx->cfg.ul_fn_offset != 0)
vty_out(vty, " ul-fn-offset %d%s", trx->cfg.ul_fn_offset, VTY_NEWLINE);
trx_rate_ctr_threshold_write_config(vty, " ");
for (i = 0; i < trx->cfg.num_chans; i++) {
chan = &trx->cfg.chans[i];
vty_out(vty, " chan %u%s", chan->idx, VTY_NEWLINE);
if (chan->rx_path)
vty_out(vty, " rx-path %s%s", chan->rx_path, VTY_NEWLINE);
if (chan->tx_path)
vty_out(vty, " tx-path %s%s", chan->tx_path, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
static void trx_dump_vty(struct vty *vty, struct trx_ctx *trx)
{
struct trx_chan *chan;
int i;
vty_out(vty, "TRX Config:%s", VTY_NEWLINE);
vty_out(vty, " Local IP: %s%s", trx->cfg.bind_addr, VTY_NEWLINE);
vty_out(vty, " Remote IP: %s%s", trx->cfg.remote_addr, VTY_NEWLINE);
vty_out(vty, " TRX Base Port: %u%s", trx->cfg.base_port, VTY_NEWLINE);
vty_out(vty, " Device args: %s%s", trx->cfg.dev_args, VTY_NEWLINE);
vty_out(vty, " Tx Samples-per-Symbol: %u%s", trx->cfg.tx_sps, VTY_NEWLINE);
vty_out(vty, " Rx Samples-per-Symbol: %u%s", trx->cfg.rx_sps, VTY_NEWLINE);
vty_out(vty, " Filler Burst Type: %s%s", get_value_string(filler_names, trx->cfg.filler), VTY_NEWLINE);
vty_out(vty, " Filler Burst TSC: %u%s", trx->cfg.rtsc, VTY_NEWLINE);
vty_out(vty, " Filler Burst RACH Delay: %u%s", trx->cfg.rach_delay, VTY_NEWLINE);
vty_out(vty, " Clock Reference: %s%s", get_value_string(clock_ref_names, trx->cfg.clock_ref), VTY_NEWLINE);
vty_out(vty, " Multi-Carrier: %s%s", trx->cfg.multi_arfcn ? "Enabled" : "Disabled", VTY_NEWLINE);
vty_out(vty, " Tuning offset: %f%s", trx->cfg.offset, VTY_NEWLINE);
vty_out(vty, " RSSI to dBm offset: %f%s", trx->cfg.rssi_offset, VTY_NEWLINE);
vty_out(vty, " Swap channels: %s%s", trx->cfg.swap_channels ? "Enabled" : "Disabled", VTY_NEWLINE);
vty_out(vty, " EDGE support: %s%s", trx->cfg.egprs ? "Enabled" : "Disabled", VTY_NEWLINE);
vty_out(vty, " Extended RACH support: %s%s", trx->cfg.ext_rach ? "Enabled" : "Disabled", VTY_NEWLINE);
vty_out(vty, " Real Time Priority: %u (%s)%s", trx->cfg.sched_rr,
trx->cfg.sched_rr ? "Enabled" : "Disabled", VTY_NEWLINE);
vty_out(vty, " Stack size per Thread in BYTE (0 = OS default): %u%s", trx->cfg.stack_size, VTY_NEWLINE);
vty_out(vty, " Channels: %u%s", trx->cfg.num_chans, VTY_NEWLINE);
for (i = 0; i < trx->cfg.num_chans; i++) {
chan = &trx->cfg.chans[i];
vty_out(vty, " Channel %u:%s", chan->idx, VTY_NEWLINE);
if (chan->rx_path)
vty_out(vty, " Rx Path: %s%s", chan->rx_path, VTY_NEWLINE);
if (chan->tx_path)
vty_out(vty, " Tx Path: %s%s", chan->tx_path, VTY_NEWLINE);
}
}
DEFUN(show_trx, show_trx_cmd,
"show trx",
SHOW_STR "Display information on the TRX\n")
{
struct trx_ctx *trx = trx_from_vty(vty);
trx_dump_vty(vty, trx);
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)
{
switch (vty->node) {
case TRX_NODE:
vty->node = CONFIG_NODE;
vty->index = NULL;
vty->index_sub = NULL;
break;
case CHAN_NODE:
vty->node = TRX_NODE;
vty->index = NULL;
vty->index_sub = NULL;
break;
default:
vty->node = CONFIG_NODE;
vty->index = NULL;
vty->index_sub = NULL;
}
return vty->node;
}
static const char trx_copyright[] =
"Copyright (C) 2007-2014 Free Software Foundation, Inc.\r\n"
"Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>\r\n"
"Copyright (C) 2013-2019 Fairwaves, Inc.\r\n"
"Copyright (C) 2015 Ettus Research LLC\r\n"
"Copyright (C) 2017-2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
"This is free software: you are free to change and redistribute it.\r\n"
"There is NO WARRANTY, to the extent permitted by law.\r\n";
struct vty_app_info g_vty_info = {
.name = "OsmoTRX",
.version = PACKAGE_VERSION,
.copyright = trx_copyright,
.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 * trx = talloc_zero(talloc_ctx, struct trx_ctx);
trx->cfg.bind_addr = talloc_strdup(trx, DEFAULT_TRX_IP);
trx->cfg.remote_addr = talloc_strdup(trx, DEFAULT_TRX_IP);
trx->cfg.base_port = DEFAULT_TRX_PORT;
trx->cfg.tx_sps = DEFAULT_TX_SPS;
trx->cfg.rx_sps = DEFAULT_RX_SPS;
trx->cfg.filler = FILLER_ZERO;
trx->cfg.rssi_offset = 0.0f;
return trx;
}
int trx_vty_init(struct trx_ctx* trx)
{
cfg_filler_type_cmd.string = vty_cmd_string_from_valstr(trx, filler_types,
"filler type (", "|", ")", 0);
cfg_filler_type_cmd.doc = vty_cmd_string_from_valstr(trx, filler_docs,
CFG_FILLER_DOC_STR "What to do when there is nothing to send "
"(filler type, default=zero)\n", "\n", "", 0);
g_trx_ctx = trx;
install_element_ve(&show_trx_cmd);
install_element(CONFIG_NODE, &cfg_trx_cmd);
install_node(&trx_node, config_write_trx);
install_element(TRX_NODE, &cfg_bind_ip_cmd);
install_element(TRX_NODE, &cfg_remote_ip_cmd);
install_element(TRX_NODE, &cfg_base_port_cmd);
install_element(TRX_NODE, &cfg_dev_args_cmd);
install_element(TRX_NODE, &cfg_tx_sps_cmd);
install_element(TRX_NODE, &cfg_rx_sps_cmd);
install_element(TRX_NODE, &cfg_clock_ref_cmd);
install_element(TRX_NODE, &cfg_multi_arfcn_cmd);
install_element(TRX_NODE, &cfg_offset_cmd);
install_element(TRX_NODE, &cfg_freq_offset_cmd);
install_element(TRX_NODE, &cfg_rssi_offset_cmd);
install_element(TRX_NODE, &cfg_swap_channels_cmd);
install_element(TRX_NODE, &cfg_egprs_cmd);
install_element(TRX_NODE, &cfg_ext_rach_cmd);
install_element(TRX_NODE, &cfg_rt_prio_cmd);
install_element(TRX_NODE, &cfg_filler_type_cmd);
install_element(TRX_NODE, &cfg_filler_tsc_cmd);
install_element(TRX_NODE, &cfg_filler_rach_delay_cmd);
install_element(TRX_NODE, &cfg_ctr_error_threshold_cmd);
install_element(TRX_NODE, &cfg_no_ctr_error_threshold_cmd);
install_element(TRX_NODE, &cfg_stack_size_cmd);
install_element(TRX_NODE, &cfg_chan_cmd);
install_element(TRX_NODE, &cfg_ul_fn_offset_cmd);
install_node(&chan_node, dummy_config_write);
install_element(CHAN_NODE, &cfg_chan_rx_path_cmd);
install_element(CHAN_NODE, &cfg_chan_tx_path_cmd);
logging_vty_add_deprecated_subsys(g_trx_ctx, "lms");
return 0;
}

41
CommonLibs/trx_vty.h Normal file
View File

@@ -0,0 +1,41 @@
#pragma once
#include <osmocom/vty/command.h>
#include "config_defs.h"
extern struct vty_app_info g_vty_info;
extern const struct value_string clock_ref_names[];
extern const struct value_string filler_names[];
/* Maximum number of carriers in multi-ARFCN mode */
#define TRX_MCHAN_MAX 3
/* Samples-per-symbol for downlink path
* 4 - Uses precision modulator (more computation, less distortion)
* 1 - Uses minimized modulator (less computation, more distortion)
*
* Other values are invalid. Receive path (uplink) is always
* downsampled to 1 sps. Default to 4 sps for all cases.
*/
#define DEFAULT_TX_SPS 4
/*
* Samples-per-symbol for uplink (receiver) path
* Do not modify this value. EDGE configures 4 sps automatically on
* B200/B210 devices only. Use of 4 sps on the receive path for other
* configurations is not supported.
*/
#define DEFAULT_RX_SPS 1
/* Default configuration parameters */
#define DEFAULT_TRX_PORT 5700
#define DEFAULT_TRX_IP "127.0.0.1"
#define DEFAULT_CHANS 1
struct trx_ctx {
struct trx_cfg cfg;
};
int trx_vty_init(struct trx_ctx* trx);
struct trx_ctx *vty_trx_ctx_alloc(void *talloc_ctx);

View File

@@ -2,6 +2,8 @@
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2011 Range Networks, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -54,7 +56,10 @@ const BitVector GSM::gEdgeTrainingSequence[] = {
const BitVector GSM::gDummyBurst("0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000");
const BitVector GSM::gRACHSynchSequence("01001011011111111001100110101010001111000");
/* 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::gRACHSynchSequenceTS1("01010100111110001000011000101111001001101"); /* EGPRS, 8-PSK */
const BitVector GSM::gRACHSynchSequenceTS2("11101111001001110101011000001101101110111"); /* EGPRS, GMSK */
// |-head-||---------midamble----------------------||--------------data----------------||t|
const BitVector GSM::gRACHBurst("0011101001001011011111111001100110101010001111000110111101111110000111001001010110011000");

View File

@@ -2,6 +2,8 @@
/*
* Copyright 2008-2011 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: AGPL-3.0+
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
@@ -52,7 +54,9 @@ extern const BitVector gEdgeTrainingSequence[];
extern const BitVector gDummyBurst;
/** Random access burst synch. sequence */
extern const BitVector gRACHSynchSequence;
extern const BitVector gRACHSynchSequenceTS0;
extern const BitVector gRACHSynchSequenceTS1;
extern const BitVector gRACHSynchSequenceTS2;
/** Random access burst synch. sequence, GSM 05.02 5.2.7 */
extern const BitVector gRACHBurst;
@@ -164,7 +168,7 @@ class Time {
unsigned newTN = (mTN + other.mTN) % 8;
uint64_t newFN = (mFN+other.mFN + (mTN + other.mTN)/8) % gHyperframe;
return Time(newFN,newTN);
}
}
int operator-(const Time& other) const
{

View File

@@ -1,33 +0,0 @@
Installation Requirements
OpenBTS compiles to a simple Unix binary and does not require special
installation.
One some systems (Ubuntu), you will need to define LIBS = -lpthread prior to
running configure.
To run OpenBTS, the following should be installed:
Asterisk (http://www.asterisk.org), running SIP on port 5060.
libosip2 (http://www.gnu.org/software/osip/)
libortp (http://freshmeat.net/projects/ortp/)
libusrp (http://gnuradio.org).
This is part of the GNURadio installation.
It is the only part used by OpenBTS.
OpenBTS logs to syslogd as facility LOG_LOCAL7. Please set your /etc/syslog.conf
accordingly.
For information on specific executables, see tests/README.tests and
apps/README.apps.
See http://gnuradio.org/redmine/wiki/gnuradio/OpenBTS/BuildingAndRunning for more
information.

20
LEGAL
View File

@@ -1,5 +1,8 @@
OpenBTS
The OsmoTRX project is direved from OpenBTS transceiver code. See http://openbts.org/ for details.
The related copyrights:
Most parts copyright 2008-2011 Free Software Foundation.
Some parts copyright 2010 Kestrel Signal Processing, Inc.
Some parts copyright 2011 Range Networks, Inc.
@@ -12,17 +15,9 @@ patented technologies. The user of this software is required to take whatever
actions are necessary to avoid patent infringement.
Trademark
"OpenBTS" is a registered trademark of Range Networks, Inc. (Range), a
California corporation. Range reserves the right to control the use of this
trademark. Do not use this trademark in commerce without permission and do not
rebrand OpenBTS under a different trademark.
Telecom and Radio Spectrum Laws
The primary function of OpenBTS is the provision of telecommunications service
The primary function of OsmoTRX is the provision of telecommunications service
over a radio link. This activity is heavily regulated nearly everywhere in
the world. Users of this software are expected to comply with local and national
regulations in the jurisdictions where this sortware is used with radio equipment.
@@ -39,7 +34,7 @@ The legal restrictions listed here are not necessarily exhaustive.
Note to US Government Users
The OpenBTS software applications and associated documentation are "Commercial
The OsmoTRX software applications and associated documentation are "Commercial
Item(s)," as that term is defined at 48 C.F.R. Section 2.101, consisting of
"Commercial Computer Software" and "Commercial Computer Software Documentation,"
as such terms are used in 48 C.F.R. 12.212 or 48 C.F.R. 227.7202, as
@@ -54,13 +49,12 @@ and AGPLv3.
Note to US Government Contractors
GPL is not compatible with "government purpose rights" (GPR). If you receive
OpenBTS software under a GPL and deliver it under GPR, you will be in violation
OsmoTRX software under a GPL and deliver it under GPR, you will be in violation
of GPL and possibly subject to enforcement actions by the original authors and
copyright holders, including the Free Software Foundation, Inc.
Software Licensing and Distribution
A subset of OpenBTS is distributed publicly under AGPLv3. Range reserves the right to
distribute most of this source code other licenses as well. See the COPYING file
The OsmoTRX is distributed publicly under AGPLv3. See the COPYING file
for more information on the license for this distribution.

View File

@@ -22,24 +22,42 @@ include $(top_srcdir)/Makefile.common
ACLOCAL_AMFLAGS = -I config
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(USB_INCLUDES) $(WITH_INCLUDES)
AM_CXXFLAGS = -Wall -pthread -ldl
#AM_CXXFLAGS = -Wall -O2 -NDEBUG -pthread -ldl
#AM_CFLAGS = -Wall -O2 -NDEBUG -pthread -ldl
AM_CXXFLAGS = -Wall -pthread
#AM_CXXFLAGS = -Wall -O2 -NDEBUG -pthread
#AM_CFLAGS = -Wall -O2 -NDEBUG -pthread
SUBDIRS =
if ENABLE_MS_TRX
SUBDIRS += osmocom-bb/src/host/trxcon
endif
# Order must be preserved
SUBDIRS = \
sqlite3 \
SUBDIRS += \
osmocom-bb/src/host/trxcon \
CommonLibs \
GSM \
Transceiver52M
Transceiver52M \
contrib \
tests \
utils \
doc \
$(NULL)
EXTRA_DIST = \
autogen.sh \
INSTALLATION \
LEGAL \
COPYING \
README
README.md \
contrib/osmo-trx.spec.in \
debian \
$(NULL)
AM_DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
.PHONY: release
@RELMAKE@
dox: FORCE
doxygen doxconfig

View File

@@ -18,21 +18,21 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
top_srcdir = $(abs_top_srcdir)
top_builddir = $(abs_top_builddir)
COMMON_INCLUDEDIR = $(top_srcdir)/CommonLibs
GSM_INCLUDEDIR = $(top_srcdir)/GSM
SQLITE_INCLUDEDIR = $(top_srcdir)/sqlite3
STD_DEFINES_AND_INCLUDES = \
$(SVNDEV) \
-I$(COMMON_INCLUDEDIR) \
-I$(GSM_INCLUDEDIR) \
-I$(SQLITE_INCLUDEDIR)
-I$(GSM_INCLUDEDIR)
COMMON_LA = $(top_builddir)/CommonLibs/libcommon.la
GSM_LA = $(top_builddir)/GSM/libGSM.la
SQLITE_LA = $(top_builddir)/sqlite3/libsqlite.la -ldl
if ARCH_ARM
ARCH_LA = $(top_builddir)/Transceiver52M/arch/arm/libarch.la
else
ARCH_LA = $(top_builddir)/Transceiver52M/arch/x86/libarch.la
endif
MOSTLYCLEANFILES = *~

0
NEWS
View File

116
README
View File

@@ -1,116 +0,0 @@
This is the interface to the transcevier.
Each TRX Manager UDP socket interface represents a single ARFCN.
Each of these per-ARFCN interfaces is a pair of UDP sockets, one for control and one for data.
Give a base port B (5700), the master clock interface is at port P=B.
The TRX-side control interface for C(N) is on port P=B+2N+1 and the data interface is on an odd numbered port P=B+2N+2.
The corresponding core-side interface for every socket is at P+100.
For any given build, the number of ARFCN interfaces can be fixed.
Indications on the Master Clock Interface
The master clock interface is output only (from the radio).
Messages are "indications".
CLOCK gives the current value of the transceiver clock to be used by the core.
This message is sent whenever a trasmission packet arrives that is too late or too early. The clock value is NOT the current transceiver time. It is a time setting the the core should use to give better packet arrival times.
IND CLOCK <totalFrames>
Commands on the Per-ARFCN Control Interface
The per-ARFCN control interface uses a command-reponse protocol.
Commands are NULL-terminated ASCII strings, one per UDP socket.
Each command has a corresponding response.
Every command is of the form:
CMD <cmdtype> [params]
The <cmdtype> is the actual command.
Parameters are optional depending on the commands type.
Every response is of the form:
RSP <cmdtype> <status> [result]
The <status> is 0 for success and a non-zero error code for failure.
Successful responses may include results, depending on the command type.
Power Control
POWEROFF shuts off transmitter power and stops the demodulator.
CMD POWEROFF
RSP POWEROFF <status>
POWERON starts the transmitter and starts the demodulator. Initial power level is very low.
This command fails if the transmitter and receiver are not yet tuned.
This command fails if the transmit or receive frequency creates a conflict with another ARFCN that is already runnng.
If the transceiver is already on, it response with success to this command.
CMD POWERON
RSP POWERON <status>
SETPOWER sets output power in dB wrt full scale.
This command fails if the transmitter and receiver are not running.
CMD SETPOWER <dB>
RSP SETPOWER <status> <dB>
ADJPOWER adjusts power by the given dB step. Response returns resulting power level wrt full scale.
This command fails if the transmitter and receiver are not running.
CMD ADJPOWER <dBStep>
RSP ADJPOWER <status> <dBLevel>
Tuning Control
RXTUNE tunes the receiver to a given frequency in kHz.
This command fails if the receiver is already running.
(To re-tune you stop the radio, re-tune, and restart.)
This command fails if the transmit or receive frequency creates a conflict with another ARFCN that is already runnng.
CMD RXTUNE <kHz>
RSP RXTUNE <status> <kHz>
TXTUNE tunes the transmitter to a given frequency in kHz.
This command fails if the transmitter is already running.
(To re-tune you stop the radio, re-tune, and restart.)
This command fails if the transmit or receive frequency creates a conflict with another ARFCN that is already runnng.
CMD TXTUNE <kHz>
RSP TXTUNE <status> <kHz>
Timeslot Control
SETSLOT sets the format of the uplink timeslots in the ARFCN.
The <timeslot> indicates the timeslot of interest.
The <chantype> indicates the type of channel that occupies the timeslot.
A chantype of zero indicates the timeslot is off.
CMD SETSLOT <timeslot> <chantype>
RSP SETSLOT <status> <timeslot> <chantype>
Messages on the per-ARFCN Data Interface
Messages on the data interface carry one radio burst per UDP message.
Received Data Burst
1 byte timeslot index
4 bytes GSM frame number, big endian
1 byte RSSI in -dBm
2 bytes correlator timing offset in 1/256 symbol steps, 2's-comp, big endian
148 bytes soft symbol estimates, 0 -> definite "0", 255 -> definite "1"
Transmit Data Burst
1 byte timeslot index
4 bytes GSM frame number, big endian
1 byte transmit level wrt ARFCN max, -dB (attenuation)
148 bytes output symbol values, 0 & 1

64
README.md Normal file
View File

@@ -0,0 +1,64 @@
About OsmoTRX
=============
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"
OsmoTRX is originally based on the transceiver code from the
[OpenBTS](https://osmocom.org/projects/osmobts/wiki/OpenBTS) project, but setup
to operate independently with the purpose of using with non-OpenBTS software and
projects, specifically within the Osmocom stack. Used together with
[OsmoBTS](https://osmocom.org/projects/osmobts/wiki) you can get a pretty
standard GSM BTS with Abis interface as per the relevant 3GPP specifications.
Homepage
--------
The official homepage of the project is
<https://osmocom.org/projects/osmotrx/wiki/OsmoTRX>
GIT Repository
--------------
You can clone from the official osmo-trx.git repository using
git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-trx`
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-trx>
Documentation
-------------
Doxygen-generated API documentation is generated during the build process, but
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
<https://ftp.osmocom.org/docs/latest/osmotrx-usermanual.pdf>.
Mailing List
------------
Discussions related to OsmoTRX are happening on the openbsc@lists.osmocom.org
mailing list, please see <https://lists.osmocom.org/mailman/listinfo/openbsc>
for subscription options and the list archive.
Please observe the [Osmocom Mailing List
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
when posting.
Contributing
------------
Our coding standards are described at
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
We us a gerrit based patch submission/review process for managing contributions.
Please see <https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit>
for more details
The current patch queue for OsmoTRX can be seen at
<https://gerrit.osmocom.org/q/project:osmo-trx+status:open>

View File

@@ -0,0 +1,109 @@
/*
* Polyphase channelizer
*
* Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
* Copyright (C) 2015 Ettus Research LLC
*
* SPDX-License-Identifier: AGPL-3.0+
*
* 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/>.
* See the COPYING file in the main directory for details.
*/
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include <cstdio>
#include "Channelizer.h"
extern "C" {
#include "fft.h"
#include "convolve.h"
}
static void deinterleave(const float *in, size_t ilen,
float **out, size_t olen, size_t m)
{
size_t i, n;
for (i = 0; i < olen; i++) {
for (n = 0; n < m; n++) {
out[m - 1 - n][2 * i + 0] = in[2 * (i * m + n) + 0];
out[m - 1 - n][2 * i + 1] = in[2 * (i * m + n) + 1];
}
}
}
size_t Channelizer::inputLen() const
{
return blockLen * m;
}
size_t Channelizer::outputLen() const
{
return blockLen;
}
float *Channelizer::outputBuffer(size_t chan) const
{
if (chan >= m)
return NULL;
return hInputs[chan];
}
/*
* Implementation based on material found in:
*
* "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
* Prentice Hall, 2006."
*/
bool Channelizer::rotate(const float *in, size_t len)
{
size_t hSize = 2 * hLen * sizeof(float);
if (!checkLen(blockLen, len))
return false;
deinterleave(in, len, hInputs, blockLen, m);
/*
* Convolve through filterbank while applying and saving sample history
*/
for (size_t i = 0; i < m; i++) {
memcpy(&hInputs[i][2 * -hLen], hist[i], hSize);
memcpy(hist[i], &hInputs[i][2 * (blockLen - hLen)], hSize);
convolve_real(hInputs[i], blockLen,
subFilters[i], hLen,
hOutputs[i], blockLen,
0, blockLen);
}
cxvec_fft(fftHandle);
return true;
}
/* Setup channelizer parameters */
Channelizer::Channelizer(size_t m, size_t blockLen, size_t hLen)
: ChannelizerBase(m, blockLen, hLen)
{
}
Channelizer::~Channelizer()
{
}

View File

@@ -0,0 +1,34 @@
#ifndef _CHANNELIZER_RX_H_
#define _CHANNELIZER_RX_H_
#include "ChannelizerBase.h"
class Channelizer : public ChannelizerBase {
public:
/** Constructor for channelizing filter bank
@param m number of physical channels
@param blockLen number of samples per output of each iteration
@param hLen number of taps in each constituent filter path
*/
Channelizer(size_t m, size_t blockLen, size_t hLen = 16);
~Channelizer();
/* Return required input and output buffer lengths */
size_t inputLen() const;
size_t outputLen() const;
/** Rotate "input commutator" and drive samples through filterbank
@param in complex input vector
@param iLen number of samples in buffer (must match block length)
@return false on error and true otherwise
*/
bool rotate(const float *in, size_t iLen);
/** Get buffer for an output path
@param chan channel number of filterbank
@return NULL on error and pointer to buffer otherwise
*/
float *outputBuffer(size_t chan) const;
};
#endif /* _CHANNELIZER_RX_H_ */

View File

@@ -0,0 +1,255 @@
/*
* Polyphase channelizer
*
* Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
* Copyright (C) 2015 Ettus Research LLC
*
* SPDX-License-Identifier: AGPL-3.0+
*
* 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/>.
* See the COPYING file in the main directory for details.
*/
#include <malloc.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include <cstdio>
#include "Logger.h"
#include "ChannelizerBase.h"
extern "C" {
#include "fft.h"
}
static float sinc(float x)
{
if (x == 0.0f)
return 0.999999999999f;
return sin(M_PI * x) / (M_PI * x);
}
/*
* There are more efficient reversal algorithms, but we only reverse at
* initialization so we don't care.
*/
static void reverse(float *buf, size_t len)
{
float tmp[2 * len];
memcpy(tmp, buf, 2 * len * sizeof(float));
for (size_t i = 0; i < len; i++) {
buf[2 * i + 0] = tmp[2 * (len - 1 - i) + 0];
buf[2 * i + 1] = tmp[2 * (len - 1 - i) + 1];
}
}
/*
* Create polyphase filterbank
*
* Implementation based material found in,
*
* "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
* Prentice Hall, 2006."
*/
bool ChannelizerBase::initFilters()
{
size_t protoLen = m * hLen;
float *proto;
float sum = 0.0f, scale = 0.0f;
float midpt = (float) (protoLen - 1.0) / 2.0;
/*
* Allocate 'M' partition filters and the temporary prototype
* filter. Coefficients are real only and must be 16-byte memory
* aligned for SSE usage.
*/
proto = new float[protoLen];
if (!proto)
return false;
subFilters = (float **) malloc(sizeof(float *) * m);
if (!subFilters) {
delete[] proto;
return false;
}
for (size_t i = 0; i < m; i++) {
subFilters[i] = (float *)
memalign(16, hLen * 2 * sizeof(float));
}
/*
* Generate the prototype filter with a Blackman-harris window.
* Scale coefficients with DC filter gain set to unity divided
* by the number of channels.
*/
float a0 = 0.35875;
float a1 = 0.48829;
float a2 = 0.14128;
float a3 = 0.01168;
for (size_t i = 0; i < protoLen; i++) {
proto[i] = sinc(((float) i - midpt) / (float) m);
proto[i] *= a0 -
a1 * cos(2 * M_PI * i / (protoLen - 1)) +
a2 * cos(4 * M_PI * i / (protoLen - 1)) -
a3 * cos(6 * M_PI * i / (protoLen - 1));
sum += proto[i];
}
scale = (float) m / sum;
/*
* Populate partition filters and reverse the coefficients per
* convolution requirements.
*/
for (size_t i = 0; i < hLen; i++) {
for (size_t n = 0; n < m; n++) {
subFilters[n][2 * i + 0] = proto[i * m + n] * scale;
subFilters[n][2 * i + 1] = 0.0f;
}
}
for (size_t i = 0; i < m; i++)
reverse(subFilters[i], hLen);
delete[] proto;
return true;
}
bool ChannelizerBase::initFFT()
{
size_t size;
if (fftInput || fftOutput || fftHandle)
return false;
size = blockLen * m * 2 * sizeof(float);
fftInput = (float *) fft_malloc(size);
memset(fftInput, 0, size);
size = (blockLen + hLen) * m * 2 * sizeof(float);
fftOutput = (float *) fft_malloc(size);
memset(fftOutput, 0, size);
if (!fftInput | !fftOutput) {
LOG(ALERT) << "Memory allocation error";
return false;
}
fftHandle = init_fft(0, m, blockLen, blockLen + hLen,
fftInput, fftOutput, hLen);
return true;
}
bool ChannelizerBase::mapBuffers()
{
if (!fftHandle) {
LOG(ALERT) << "FFT buffers not initialized";
return false;
}
hInputs = (float **) malloc(sizeof(float *) * m);
hOutputs = (float **) malloc(sizeof(float *) * m);
if (!hInputs | !hOutputs)
return false;
for (size_t i = 0; i < m; i++) {
hInputs[i] = &fftOutput[2 * (i * (blockLen + hLen) + hLen)];
hOutputs[i] = &fftInput[2 * (i * blockLen)];
}
return true;
}
/*
* Setup filterbank internals
*/
bool ChannelizerBase::init()
{
/*
* Filterbank coefficients, fft plan, history, and output sample
* rate conversion blocks
*/
if (!initFilters()) {
LOG(ALERT) << "Failed to initialize channelizing filter";
return false;
}
hist = (float **) malloc(sizeof(float *) * m);
for (size_t i = 0; i < m; i++) {
hist[i] = new float[2 * hLen];
memset(hist[i], 0, 2 * hLen * sizeof(float));
}
if (!initFFT()) {
LOG(ALERT) << "Failed to initialize FFT";
return false;
}
mapBuffers();
return true;
}
/* Check vector length validity */
bool ChannelizerBase::checkLen(size_t innerLen, size_t outerLen)
{
if (outerLen != innerLen * m) {
LOG(ALERT) << "Invalid outer length " << innerLen
<< " is not multiple of " << blockLen;
return false;
}
if (innerLen != blockLen) {
LOG(ALERT) << "Invalid inner length " << outerLen
<< " does not equal " << blockLen;
return false;
}
return true;
}
/*
* Setup channelizer parameters
*/
ChannelizerBase::ChannelizerBase(size_t m, size_t blockLen, size_t hLen)
: subFilters(NULL), hInputs(NULL), hOutputs(NULL), hist(NULL),
fftInput(NULL), fftOutput(NULL), fftHandle(NULL)
{
this->m = m;
this->hLen = hLen;
this->blockLen = blockLen;
}
ChannelizerBase::~ChannelizerBase()
{
free_fft(fftHandle);
for (size_t i = 0; i < m; i++) {
free(subFilters[i]);
delete[] hist[i];
}
free(subFilters);
fft_free(fftInput);
fft_free(fftOutput);
free(hInputs);
free(hOutputs);
free(hist);
}

View File

@@ -0,0 +1,39 @@
#ifndef _CHANNELIZER_BASE_H_
#define _CHANNELIZER_BASE_H_
class ChannelizerBase {
protected:
ChannelizerBase(size_t m, size_t blockLen, size_t hLen);
~ChannelizerBase();
/* Channelizer parameters */
size_t m;
size_t hLen;
size_t blockLen;
/* Channelizer filterbank sub-filters */
float **subFilters;
/* Input/Output buffers */
float **hInputs, **hOutputs, **hist;
float *fftInput, *fftOutput;
/* Pointer to opaque FFT instance */
struct fft_hdl *fftHandle;
/* Initializer internals */
bool initFilters();
bool initFFT();
void releaseFilters();
/* Map overlapped FFT and filter I/O buffers */
bool mapBuffers();
/* Buffer length validity checking */
bool checkLen(size_t innerLen, size_t outerLen);
public:
/* Initialize channelizer/synthesis filter internals */
bool init();
};
#endif /* _CHANNELIZER_BASE_H_ */

View File

@@ -5,7 +5,7 @@ unlike the built-in complex<> templates, these inline most operations for speed
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

View File

@@ -21,78 +21,186 @@
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES) -I./common
AM_CXXFLAGS = -ldl -lpthread
SUBDIRS = arch device
SUBDIRS = arm x86
AM_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES) -I${srcdir}/arch/common -I${srcdir}/device/common -I$(top_srcdir)/osmocom-bb/src/host/trxcon/include/
AM_CXXFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS) -I$(top_srcdir)/osmocom-bb/src/host/trxcon/include/
AM_CFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS) -I$(top_srcdir)/osmocom-bb/src/host/trxcon/include/
if ARCH_ARM
ARCH_LA = arm/libarch.la
else
ARCH_LA = x86/libarch.la
endif
if USRP1
AM_CPPFLAGS += $(USRP_CFLAGS)
else
AM_CPPFLAGS += $(UHD_CFLAGS)
endif
rev2dir = $(datadir)/usrp/rev2
rev4dir = $(datadir)/usrp/rev4
dist_rev2_DATA = std_inband.rbf
dist_rev4_DATA = std_inband.rbf
EXTRA_DIST = \
README \
README.Talgorithm
noinst_LTLIBRARIES = libtransceiver.la
noinst_LTLIBRARIES = libtransceiver_common.la
COMMON_SOURCES = \
radioInterface.cpp \
radioVector.cpp \
radioClock.cpp \
radioBuffer.cpp \
sigProcLib.cpp \
signalVector.cpp \
Transceiver.cpp
Transceiver.cpp \
ChannelizerBase.cpp \
Channelizer.cpp \
Synthesis.cpp \
proto_trxd.c \
grgsm_vitac/grgsm_vitac.cpp \
grgsm_vitac/viterbi_detector.cc
libtransceiver_la_SOURCES = \
libtransceiver_common_la_SOURCES = \
$(COMMON_SOURCES) \
Resampler.cpp \
radioInterfaceResamp.cpp \
radioInterfaceDiversity.cpp
bin_PROGRAMS = osmo-trx
radioInterfaceMulti.cpp
noinst_HEADERS = \
Complex.h \
radioInterface.h \
radioVector.h \
radioClock.h \
radioDevice.h \
radioBuffer.h \
sigProcLib.h \
signalVector.h \
Transceiver.h \
USRPDevice.h \
Resampler.h \
common/convolve.h \
common/convert.h \
common/scale.h \
common/mult.h
ChannelizerBase.h \
Channelizer.h \
Synthesis.h \
proto_trxd.h \
grgsm_vitac/viterbi_detector.h \
grgsm_vitac/constants.h
osmo_trx_SOURCES = osmo-trx.cpp
osmo_trx_LDADD = \
libtransceiver.la \
COMMON_LDADD = \
libtransceiver_common.la \
$(ARCH_LA) \
$(GSM_LA) \
$(COMMON_LA) $(SQLITE_LA)
$(COMMON_LA) \
$(FFTWF_LIBS) \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCODING_LIBS) \
$(LIBOSMOCTRL_LIBS) \
$(LIBOSMOVTY_LIBS)
if USRP1
libtransceiver_la_SOURCES += USRPDevice.cpp
osmo_trx_LDADD += $(USRP_LIBS)
else
libtransceiver_la_SOURCES += UHDDevice.cpp
osmo_trx_LDADD += $(UHD_LIBS)
TRXCON_LDADD = \
$(top_builddir)/osmocom-bb/src/host/trxcon/src/.libs/libl1sched.a \
$(top_builddir)/osmocom-bb/src/host/trxcon/src/.libs/libtrxcon.a
MS_SOURCES = \
ms/sch.c \
ms/ms.cpp \
ms/ms_rx_lower.cpp
noinst_HEADERS += \
ms/ms.h \
ms/bladerf_specific.h \
ms/uhd_specific.h \
ms/ms_upper.h \
ms/itrq.h
bin_PROGRAMS =
if DEVICE_UHD
bin_PROGRAMS += osmo-trx-uhd
osmo_trx_uhd_SOURCES = osmo-trx.cpp
osmo_trx_uhd_LDADD = \
$(builddir)/device/uhd/libdevice.la \
$(COMMON_LDADD) \
$(UHD_LIBS)
osmo_trx_uhd_CPPFLAGS = $(AM_CPPFLAGS) $(UHD_CFLAGS)
if ENABLE_MS_TRX
bin_PROGRAMS += osmo-trx-ms-uhd
osmo_trx_ms_uhd_SOURCES = $(MS_SOURCES) ms/ms_upper.cpp ms/l1ctl_server.c ms/logging.cpp ms/l1ctl_server_cb.cpp
osmo_trx_ms_uhd_LDADD = \
$(builddir)/device/uhd/libdevice.la \
$(COMMON_LDADD) \
$(UHD_LIBS) \
$(TRXCON_LDADD)
osmo_trx_ms_uhd_CPPFLAGS = $(AM_CPPFLAGS) $(UHD_CFLAGS) -DBUILDUHD
bin_PROGRAMS += osmo-trx-syncthing-uhd
osmo_trx_syncthing_uhd_SOURCES = $(MS_SOURCES) ms/ms_rx_burst_test.cpp
osmo_trx_syncthing_uhd_LDADD = \
$(builddir)/device/uhd/libdevice.la \
$(COMMON_LDADD) \
$(UHD_LIBS) \
$(TRXCON_LDADD)
osmo_trx_syncthing_uhd_CPPFLAGS = $(AM_CPPFLAGS) $(UHD_CFLAGS) -DSYNCTHINGONLY -DBUILDUHD
endif
endif
if DEVICE_USRP1
bin_PROGRAMS += osmo-trx-usrp1
osmo_trx_usrp1_SOURCES = osmo-trx.cpp
osmo_trx_usrp1_LDADD = \
$(builddir)/device/usrp1/libdevice.la \
$(COMMON_LDADD) \
$(USRP_LIBS)
osmo_trx_usrp1_CPPFLAGS = $(AM_CPPFLAGS) $(USRP_CFLAGS)
endif
if DEVICE_LMS
bin_PROGRAMS += osmo-trx-lms
osmo_trx_lms_SOURCES = osmo-trx.cpp
osmo_trx_lms_LDADD = \
$(builddir)/device/lms/libdevice.la \
$(COMMON_LDADD) \
$(LMS_LIBS)
osmo_trx_lms_CPPFLAGS = $(AM_CPPFLAGS) $(LMS_CFLAGS)
endif
if DEVICE_BLADE
bin_PROGRAMS += osmo-trx-blade
osmo_trx_blade_SOURCES = osmo-trx.cpp
osmo_trx_blade_LDADD = \
$(builddir)/device/bladerf/libdevice.la \
$(COMMON_LDADD) \
$(BLADE_LIBS)
osmo_trx_blade_CPPFLAGS = $(AM_CPPFLAGS) $(LMS_CFLAGS)
if ENABLE_MS_TRX
bin_PROGRAMS += osmo-trx-ms-blade
osmo_trx_ms_blade_SOURCES = $(MS_SOURCES) ms/ms_upper.cpp ms/l1ctl_server.c ms/logging.cpp ms/l1ctl_server_cb.cpp
osmo_trx_ms_blade_LDADD = \
$(builddir)/device/bladerf/libdevice.la \
$(COMMON_LDADD) \
$(BLADE_LIBS) \
$(TRXCON_LDADD)
osmo_trx_ms_blade_CPPFLAGS = $(AM_CPPFLAGS) $(BLADE_CFLAGS) -DBUILDBLADE
bin_PROGRAMS += osmo-trx-syncthing-blade
osmo_trx_syncthing_blade_SOURCES = $(MS_SOURCES) ms/ms_rx_burst_test.cpp
osmo_trx_syncthing_blade_LDADD = \
$(builddir)/device/bladerf/libdevice.la \
$(COMMON_LDADD) \
$(BLADE_LIBS) \
$(TRXCON_LDADD)
osmo_trx_syncthing_blade_CPPFLAGS = $(AM_CPPFLAGS) $(BLADE_CFLAGS) -DSYNCTHINGONLY -DBUILDBLADE -I../device/ipc
endif
endif
if DEVICE_IPC
bin_PROGRAMS += osmo-trx-ipc
osmo_trx_ipc_SOURCES = osmo-trx.cpp
osmo_trx_ipc_LDADD = \
$(builddir)/device/ipc/libdevice.la \
$(COMMON_LDADD)
osmo_trx_ipc_CPPFLAGS = $(AM_CPPFLAGS)
# bin_PROGRAMS += osmo-trx-ipc2
# osmo_trx_ipc2_SOURCES = osmo-trx.cpp
# osmo_trx_ipc2_LDADD = \
# $(builddir)/device/ipc2/libdevice.la \
# $(COMMON_LDADD)
# osmo_trx_ipc2_CPPFLAGS = $(AM_CPPFLAGS)
# if ENABLE_MS_TRX
# bin_PROGRAMS += osmo-trx-ms-ipc
# osmo_trx_ms_ipc_SOURCES = $(MS_SOURCES) ms/ms_upper.cpp
# osmo_trx_ms_ipc_LDADD = \
# $(COMMON_LDADD) \
# $(TRXCON_LDADD)
# osmo_trx_ms_ipc_CPPFLAGS = $(AM_CPPFLAGS) -DBUILDIPC -I./device/ipc2 -I../device/ipc2
# bin_PROGRAMS += osmo-trx-syncthing-ipc
# osmo_trx_syncthing_ipc_SOURCES = $(MS_SOURCES) ms/ms_rx_burst_test.cpp
# osmo_trx_syncthing_ipc_LDADD = $(COMMON_LDADD)
# osmo_trx_syncthing_ipc_CPPFLAGS = $(AM_CPPFLAGS) -DSYNCTHINGONLY -DBUILDIPC -I./device/ipc2 -I../device/ipc2
# endif
endif

View File

@@ -1,35 +0,0 @@
The Transceiver
The transceiver consists of three modules:
--- transceiver
--- radioInterface
--- USRPDevice
The USRPDevice module is basically a driver that reads/writes
packets to a USRP with two RFX900 daughterboards, board
A is the Tx chain and board B is the Rx chain.
The radioInterface module is basically an interface b/w the
transceiver and the USRP. It operates the basestation clock
based upon the sample count of received USRP samples. Packets
from the USRP are queued and segmented into GSM bursts that are
passed up to the transceiver; bursts from the transceiver are
passed down to the USRP.
The transceiver basically operates "layer 0" of the GSM stack,
performing the modulation, detection, and demodulation of GSM
bursts. It communicates with the GSM stack via three UDP sockets,
one socket for data, one for control messages, and one socket to
pass clocking information. The transceiver contains a priority
queue to sort to-be-transmitted bursts, and a filler table to fill
in timeslots that do not have bursts in the priority queue. The
transceiver tries to stay ahead of the basestation clock, adapting
its latency when underruns are reported by the radioInterface/USRP.
Received bursts (from the radioInterface) pass through a simple
energy detector, a RACH or midamble correlator, and a DFE-based demodulator.
NOTE: There's a SWLOOPBACK #define statement, where the USRP is replaced
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.
This was very useful in early testing, and still may be useful in testing basic
Transceiver and radioInterface functionality.

View File

@@ -2,6 +2,8 @@
* Rational Sample Rate Conversion
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
@@ -22,6 +20,7 @@
#include <string.h>
#include <malloc.h>
#include <iostream>
#include <algorithm>
#include "Resampler.h"
@@ -35,6 +34,8 @@ extern "C" {
#define MAX_OUTPUT_LEN 4096
using namespace std;
static float sinc(float x)
{
if (x == 0.0)
@@ -43,37 +44,24 @@ static float sinc(float x)
return sin(M_PI * x) / (M_PI * x);
}
bool Resampler::initFilters(float bw)
void Resampler::initFilters(float bw)
{
size_t proto_len = p * filt_len;
float *proto, val, cutoff;
float cutoff;
float sum = 0.0f, scale = 0.0f;
float midpt = (float) (proto_len - 1.0) / 2.0;
/*
/*
* Allocate partition filters and the temporary prototype filter
* according to numerator of the rational rate. Coefficients are
* real only and must be 16-byte memory aligned for SSE usage.
*/
proto = new float[proto_len];
if (!proto)
return false;
auto proto = vector<float>(p * filt_len);
for (auto &part : partitions)
part = (complex<float> *) memalign(16, filt_len * sizeof(complex<float>));
partitions = (float **) malloc(sizeof(float *) * p);
if (!partitions) {
free(proto);
return false;
}
for (size_t i = 0; i < p; i++) {
partitions[i] = (float *)
memalign(16, filt_len * 2 * sizeof(float));
}
/*
/*
* Generate the prototype filter with a Blackman-harris window.
* Scale coefficients with DC filter gain set to unity divided
* by the number of filter partitions.
* by the number of filter partitions.
*/
float a0 = 0.35875;
float a1 = 0.48829;
@@ -85,49 +73,29 @@ bool Resampler::initFilters(float bw)
else
cutoff = (float) q;
for (size_t i = 0; i < proto_len; i++) {
float midpt = (proto.size() - 1) / 2.0;
for (size_t i = 0; i < proto.size(); i++) {
proto[i] = sinc(((float) i - midpt) / cutoff * bw);
proto[i] *= a0 -
a1 * cos(2 * M_PI * i / (proto_len - 1)) +
a2 * cos(4 * M_PI * i / (proto_len - 1)) -
a3 * cos(6 * M_PI * i / (proto_len - 1));
a1 * cos(2 * M_PI * i / (proto.size() - 1)) +
a2 * cos(4 * M_PI * i / (proto.size() - 1)) -
a3 * cos(6 * M_PI * i / (proto.size() - 1));
sum += proto[i];
}
scale = p / sum;
/* Populate filter partitions from the prototype filter */
for (size_t i = 0; i < filt_len; i++) {
for (size_t n = 0; n < p; n++) {
partitions[n][2 * i + 0] = proto[i * p + n] * scale;
partitions[n][2 * i + 1] = 0.0f;
}
for (size_t n = 0; n < p; n++)
partitions[n][i] = complex<float>(proto[i * p + n] * scale);
}
/* For convolution, we store the filter taps in reverse */
for (size_t n = 0; n < p; n++) {
for (size_t i = 0; i < filt_len / 2; i++) {
val = partitions[n][2 * i];
partitions[n][2 * i] = partitions[n][2 * (filt_len - 1 - i)];
partitions[n][2 * (filt_len - 1 - i)] = val;
}
}
delete proto;
return true;
}
void Resampler::releaseFilters()
{
if (partitions) {
for (size_t i = 0; i < p; i++)
free(partitions[i]);
}
free(partitions);
partitions = NULL;
/* Store filter taps in reverse */
for (auto &part : partitions)
reverse(&part[0], &part[filt_len]);
}
#ifndef __OPTIMIZE__
static bool check_vec_len(int in_len, int out_len, int p, int q)
{
if (in_len % q) {
@@ -158,46 +126,24 @@ static bool check_vec_len(int in_len, int out_len, int p, int q)
return true;
}
#endif
void Resampler::computePath()
{
for (int i = 0; i < MAX_OUTPUT_LEN; i++) {
in_index[i] = (q * i) / p;
out_path[i] = (q * i) % p;
}
}
int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len)
int Resampler::rotate(const float *in, size_t in_len, float *out, size_t out_len)
{
int n, path;
int hist_len = filt_len - 1;
#ifndef __OPTIMIZE__
if (!check_vec_len(in_len, out_len, p, q))
return -1;
if (history_on) {
memcpy(&in[-2 * hist_len],
history, hist_len * 2 * sizeof(float));
} else {
memset(&in[-2 * hist_len], 0,
hist_len * 2 * sizeof(float));
}
#endif
/* Generate output from precomputed input/output paths */
for (size_t i = 0; i < out_len; i++) {
n = in_index[i];
path = out_path[i];
n = in_index[i];
path = out_path[i];
convolve_real(in, in_len,
partitions[path], filt_len,
&out[2 * i], out_len - i,
n, 1, 1, 0);
}
/* Save history */
if (history_on) {
memcpy(history, &in[2 * (in_len - hist_len)],
hist_len * 2 * sizeof(float));
reinterpret_cast<float *>(partitions[path]),
filt_len, &out[2 * i], out_len - i,
n, 1);
}
return out_len;
@@ -205,20 +151,18 @@ int Resampler::rotate(float *in, size_t in_len, float *out, size_t out_len)
bool Resampler::init(float bw)
{
size_t hist_len = filt_len - 1;
if (p == 0 || q == 0 || filt_len == 0) return false;
/* Filterbank filter internals */
if (initFilters(bw) < 0)
return false;
/* History buffer */
history = new float[2 * hist_len];
memset(history, 0, 2 * hist_len * sizeof(float));
initFilters(bw);
/* Precompute filterbank paths */
in_index = new size_t[MAX_OUTPUT_LEN];
out_path = new size_t[MAX_OUTPUT_LEN];
computePath();
int i = 0;
for (auto &index : in_index)
index = (q * i++) / p;
i = 0;
for (auto &path : out_path)
path = (q * i++) % p;
return true;
}
@@ -228,14 +172,8 @@ size_t Resampler::len()
return filt_len;
}
void Resampler::enableHistory(bool on)
{
history_on = on;
}
Resampler::Resampler(size_t p, size_t q, size_t filt_len)
: in_index(NULL), out_path(NULL), partitions(NULL),
history(NULL), history_on(true)
: in_index(MAX_OUTPUT_LEN), out_path(MAX_OUTPUT_LEN), partitions(p)
{
this->p = p;
this->q = q;
@@ -244,9 +182,6 @@ Resampler::Resampler(size_t p, size_t q, size_t filt_len)
Resampler::~Resampler()
{
releaseFilters();
delete history;
delete in_index;
delete out_path;
for (auto &part : partitions)
free(part);
}

View File

@@ -2,6 +2,8 @@
* Rational Sample Rate Conversion
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,31 +13,30 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _RESAMPLER_H_
#define _RESAMPLER_H_
#include <vector>
#include <complex>
class Resampler {
public:
/* Constructor for rational sample rate conversion
* @param p numerator of resampling ratio
* @param q denominator of resampling ratio
* @param filt_len length of each polyphase subfilter
* @param filt_len length of each polyphase subfilter
*/
Resampler(size_t p, size_t q, size_t filt_len = 16);
~Resampler();
/* Initilize resampler filterbank.
/* Initialize resampler filterbank.
* @param bw bandwidth factor on filter generation (pre-window)
* @return false on error, zero otherwise
*
* Automatic setting is to compute the filter to prevent aliasing with
* a Blackman-Harris window. Adjustment is made through a bandwith
* a Blackman-Harris window. Adjustment is made through a bandwidth
* factor to shift the cutoff and/or the constituent filter lengths.
* Calculation of specific rolloff factors or 3-dB cutoff points is
* left as an excersize for the reader.
@@ -52,32 +53,22 @@ public:
* Input and output vector lengths must of be equal multiples of the
* rational conversion rate denominator and numerator respectively.
*/
int rotate(float *in, size_t in_len, float *out, size_t out_len);
int rotate(const float *in, size_t in_len, float *out, size_t out_len);
/* Get filter length
* @return number of taps in each filter partition
* @return number of taps in each filter partition
*/
size_t len();
/*
* Enable/disable history
*/
void enableHistory(bool on);
private:
size_t p;
size_t q;
size_t filt_len;
size_t *in_index;
size_t *out_path;
std::vector<size_t> in_index;
std::vector<size_t> out_path;
std::vector<std::complex<float> *> partitions;
float **partitions;
float *history;
bool history_on;
bool initFilters(float bw);
void releaseFilters();
void computePath();
void initFilters(float bw);
};
#endif /* _RESAMPLER_H_ */

View File

@@ -0,0 +1,123 @@
/*
* Polyphase synthesis filter
*
* Copyright (C) 2012-2014 Tom Tsou <tom@tsou.cc>
* Copyright (C) 2015 Ettus Research LLC
*
* SPDX-License-Identifier: AGPL-3.0+
*
* 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/>.
* See the COPYING file in the main directory for details.
*/
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include <cstdio>
#include <iostream>
#include "Synthesis.h"
extern "C" {
#include "fft.h"
#include "convolve.h"
}
static void interleave(float **in, size_t ilen,
float *out, size_t m)
{
size_t i, n;
for (i = 0; i < ilen; i++) {
for (n = 0; n < m; n++) {
out[2 * (i * m + n) + 0] = in[n][2 * i + 0];
out[2 * (i * m + n) + 1] = in[n][2 * i + 1];
}
}
}
size_t Synthesis::inputLen() const
{
return blockLen;
}
size_t Synthesis::outputLen() const
{
return blockLen * m;
}
float *Synthesis::inputBuffer(size_t chan) const
{
if (chan >= m)
return NULL;
return hOutputs[chan];
}
bool Synthesis::resetBuffer(size_t chan)
{
if (chan >= m)
return false;
memset(hOutputs[chan], 0, blockLen * 2 * sizeof(float));
return true;
}
/*
* Implementation based on material found in:
*
* "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
* Prentice Hall, 2006."
*/
bool Synthesis::rotate(float *out, size_t len)
{
size_t hSize = 2 * hLen * sizeof(float);
if (!checkLen(blockLen, len)) {
std::cout << "Length fail" << std::endl;
exit(1);
return false;
}
cxvec_fft(fftHandle);
/*
* Convolve through filterbank while applying and saving sample history
*/
for (size_t i = 0; i < m; i++) {
memcpy(&hInputs[i][2 * -hLen], hist[i], hSize);
memcpy(hist[i], &hInputs[i][2 * (blockLen - hLen)], hSize);
convolve_real(hInputs[i], blockLen,
subFilters[i], hLen,
hOutputs[i], blockLen,
0, blockLen);
}
/* Interleave into output vector */
interleave(hOutputs, blockLen, out, m);
return true;
}
Synthesis::Synthesis(size_t m, size_t blockLen, size_t hLen)
: ChannelizerBase(m, blockLen, hLen)
{
}
Synthesis::~Synthesis()
{
}

View File

@@ -0,0 +1,35 @@
#ifndef _SYNTHESIS_H_
#define _SYNTHESIS_H_
#include "ChannelizerBase.h"
class Synthesis : public ChannelizerBase {
public:
/** Constructor for synthesis filterbank
@param m number of physical channels
@param blockLen number of samples per output of each iteration
@param hLen number of taps in each constituent filter path
*/
Synthesis(size_t m, size_t blockLen, size_t hLen = 16);
~Synthesis();
/* Return required input and output buffer lengths */
size_t inputLen() const;
size_t outputLen() const;
/** Rotate "output commutator" and drive samples through filterbank
@param out complex output vector
@param oLen number of samples in buffer (must match block length * m)
@return false on error and true otherwise
*/
bool rotate(float *out, size_t oLen);
/** Get buffer for an input path
@param chan channel number of filterbank
@return NULL on error and pointer to buffer otherwise
*/
float *inputBuffer(size_t chan) const;
bool resetBuffer(size_t chan);
};
#endif /* _SYNTHESIS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,8 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
*
* SPDX-License-Identifier: GPL-3.0+
*
* This software is distributed under the terms of the GNU Public License.
* See the COPYING file in the main directory for details.
*
@@ -25,27 +27,24 @@
#include "radioInterface.h"
#include "Interthread.h"
#include "GSMCommon.h"
#include "Sockets.h"
#include <sys/types.h>
#include <sys/socket.h>
extern "C" {
#include <osmocom/core/signal.h>
#include <osmocom/core/select.h>
#include "config_defs.h"
}
class Transceiver;
extern Transceiver *transceiver;
/** Channel descriptor for transceiver object and channel number pair */
struct TransceiverChannel {
TransceiverChannel(Transceiver *trx, int num)
{
this->trx = trx;
this->num = num;
}
~TransceiverChannel()
{
}
Transceiver *trx;
size_t num;
struct TrxChanThParams {
Transceiver *trx;
size_t num;
};
/** Internal transceiver state variables */
@@ -54,7 +53,7 @@ struct TransceiverState {
~TransceiverState();
/* Initialize a multiframe slot in the filler table */
bool init(int filler, size_t sps, float scale, size_t rtsc);
bool init(FillerType filler, size_t sps, float scale, size_t rtsc, unsigned rach_delay);
int chanType[8];
@@ -64,6 +63,7 @@ struct TransceiverState {
/* The filler table */
signalVector *fillerTable[102][8];
int fillerModulus[8];
FillerType mFiller;
bool mRetrans;
/* Most recent channel estimate of all timeslots */
@@ -80,34 +80,39 @@ struct TransceiverState {
/* Received noise energy levels */
float mNoiseLev;
noiseVector mNoises;
avgVector mNoises;
/* Shadowed downlink attenuation */
int mPower;
/* RF emission and reception disabled, as per NM Administrative State Locked */
bool mMuted;
/* counters */
struct trx_counters ctrs;
/* Used to keep track of lost and out of order frames */
bool first_dl_fn_rcv[8];
GSM::Time last_dl_time_rcv[8];
};
/** The Transceiver class, responsible for physical layer of basestation */
class Transceiver {
public:
/** Transceiver constructor
@param wBasePort base port number of UDP sockets
@param TRXAddress IP address of the TRX manager, as a string
@param wSPS number of samples per GSM symbol
/** Transceiver constructor
@param cfg VTY populated config
@param wTransmitLatency initial setting of transmit latency
@param radioInterface associated radioInterface object
*/
Transceiver(int wBasePort,
const char *TRXAddress,
size_t tx_sps, size_t rx_sps, size_t chans,
Transceiver(const struct trx_cfg *cfg,
GSM::Time wTransmitLatency,
RadioInterface *wRadioInterface,
double wRssiOffset);
RadioInterface *wRadioInterface);
/** Destructor */
~Transceiver();
/** Start the control loop */
bool init(int filler, size_t rtsc);
bool init(void);
/** attach the radioInterface receive FIFO */
bool receiveFIFO(VectorFIFO *wFIFO, size_t chan)
@@ -120,7 +125,7 @@ public:
}
/** accessor for number of channels */
size_t numChans() const { return mChans; };
size_t numChans() const { return cfg->num_chans; };
/** Codes for channel combinations */
typedef enum {
@@ -142,30 +147,31 @@ public:
LOOPBACK ///< similar go VII, used in loopback testing
} ChannelCombination;
/** Codes for burst types of received bursts*/
typedef enum {
OFF, ///< timeslot is off
TSC, ///< timeslot should contain a normal burst
RACH, ///< timeslot should contain an access burst
EDGE, ///< timeslot should contain an EDGE burst
IDLE ///< timeslot is an idle (or dummy) burst
} CorrType;
enum FillerType {
FILLER_DUMMY,
FILLER_ZERO,
FILLER_NORM_RAND,
FILLER_EDGE_RAND,
FILLER_ACCESS_RAND,
};
private:
int mBasePort;
std::string mAddr;
struct ctrl_msg {
char data[101];
ctrl_msg() {};
};
std::vector<UDPSocket *> mDataSockets; ///< socket for writing to/reading from GSM core
std::vector<UDPSocket *> mCtrlSockets; ///< socket for writing/reading control commands from GSM core
UDPSocket mClockSocket; ///< socket for writing clock updates to GSM core
struct ctrl_sock_state {
osmo_fd conn_bfd;
std::deque<ctrl_msg> txmsgqueue;
ctrl_sock_state() {
conn_bfd.fd = -1;
}
~ctrl_sock_state() {
if(conn_bfd.fd >= 0) {
close(conn_bfd.fd);
conn_bfd.fd = -1;
osmo_fd_unregister(&conn_bfd);
}
}
};
const struct trx_cfg *cfg; ///< VTY populated config
std::vector<int> mDataSockets; ///< socket for writing to/reading from GSM core
std::vector<ctrl_sock_state> mCtrlSockets; ///< socket for writing/reading control commands from GSM core
int mClockSocket; ///< socket for writing clock updates to GSM core
std::vector<VectorQueue> mTxPriorityQueues; ///< priority queue of transmit bursts received from GSM core
std::vector<VectorFIFO *> mReceiveFIFO; ///< radioInterface FIFO of receive bursts
@@ -173,20 +179,17 @@ private:
std::vector<Thread *> mRxServiceLoopThreads; ///< thread to pull bursts into receive FIFO
Thread *mRxLowerLoopThread; ///< thread to pull bursts into receive FIFO
Thread *mTxLowerLoopThread; ///< thread to push bursts into transmit FIFO
std::vector<Thread *> mControlServiceLoopThreads; ///< thread to process control messages from GSM core
std::vector<Thread *> mTxPriorityQueueServiceLoopThreads; ///< thread to process transmit bursts from GSM core
GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
GSM::Time mLatencyUpdateTime; ///< last time latency was updated
GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
RadioInterface *mRadioInterface; ///< associated radioInterface object
double txFullScale; ///< full scale input to radio
double rxFullScale; ///< full scale output to radio
double rssiOffset; ///< RSSI to dBm conversion offset
/** modulate and add a burst to the transmit queue */
void addRadioVector(size_t chan, BitVector &bits,
int RSSI, GSM::Time &wTime);
@@ -198,9 +201,7 @@ private:
void pushRadioVector(GSM::Time &nowTime);
/** Pull and demodulate a burst from the receive FIFO */
SoftVector *pullRadioVector(GSM::Time &wTime, double &RSSI, bool &isRssiValid,
double &timingOffset, double &noise,
size_t chan = 0);
int pullRadioVector(size_t chan, struct trx_ul_burst_ind *ind);
/** Set modulus for specific timeslot */
void setModulus(size_t timeslot, size_t chan);
@@ -209,21 +210,17 @@ private:
CorrType expectedCorrType(GSM::Time currTime, size_t chan);
/** send messages over the clock socket */
void writeClockInterface(void);
bool writeClockInterface(void);
/** Detectbursts */
int detectBurst(signalVector &burst,
complex &amp, float &toa, CorrType type);
static int ctrl_sock_cb(struct osmo_fd *bfd, unsigned int flags);
int ctrl_sock_write(int chan);
void ctrl_sock_send(ctrl_msg& m, int chan);
/** drive handling of control messages from GSM core */
int ctrl_sock_handle_rx(int chan);
/** Demodulate burst and output soft bits */
SoftVector *demodulate(signalVector &burst,
complex amp, float toa, CorrType type);
int mSPSTx; ///< number of samples per Tx symbol
int mSPSRx; ///< number of samples per Rx symbol
size_t mChans;
bool mOn; ///< flag to indicate that transceiver is powered on
bool mForceClockInterface; ///< flag to indicate whether IND CLOCK shall be sent unconditionally after transceiver is started
bool mHandover[8][8]; ///< expect handover to the timeslot/subslot
double mTxFreq; ///< the transmit frequency
double mRxFreq; ///< the receive frequency
@@ -232,63 +229,48 @@ private:
unsigned mMaxExpectedDelayNB; ///< maximum expected time-of-arrival offset in GSM symbols for Normal Bursts
unsigned mWriteBurstToDiskMask; ///< debug: bitmask to indicate which timeslots to dump to disk
std::vector<unsigned> mVersionTRXD; ///< Format version to use for TRXD protocol communication, per channel
std::vector<TransceiverState> mStates;
/** Start and stop I/O threads through the control socket API */
bool start();
void stop();
/** Protect destructor accessable stop call */
/** Protect destructor accessible stop call */
Mutex mLock;
protected:
/** drive lower receive I/O and burst generation */
void driveReceiveRadio();
bool driveReceiveRadio();
/** drive demodulation of GSM bursts */
void driveReceiveFIFO(size_t chan);
bool driveReceiveFIFO(size_t chan);
/** drive transmission of GSM bursts */
void driveTxFIFO();
/** drive handling of control messages from GSM core */
void driveControl(size_t chan);
/**
drive modulation and sorting of GSM bursts from GSM core
@return true if a burst was transferred successfully
*/
bool driveTxPriorityQueue(size_t chan);
friend void *RxUpperLoopAdapter(TransceiverChannel *);
friend void *TxUpperLoopAdapter(TransceiverChannel *);
friend void *RxLowerLoopAdapter(Transceiver *);
friend void *TxLowerLoopAdapter(Transceiver *);
friend void *ControlServiceLoopAdapter(TransceiverChannel *);
friend void *RxUpperLoopAdapter(TrxChanThParams *params);
friend void *TxUpperLoopAdapter(TrxChanThParams *params);
friend void *RxLowerLoopAdapter(Transceiver *transceiver);
friend void *TxLowerLoopAdapter(Transceiver *transceiver);
double rssiOffset(size_t chan);
void reset();
/** set priority on current thread */
void setPriority(float prio = 0.5) { mRadioInterface->setPriority(prio); }
void logRxBurst(SoftVector *burst, GSM::Time time, double dbm,
double rssi, double noise, double toa);
void logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi);
};
void *RxUpperLoopAdapter(TransceiverChannel *);
void *RxUpperLoopAdapter(TrxChanThParams *params);
/** Main drive threads */
void *RxLowerLoopAdapter(Transceiver *);
void *TxLowerLoopAdapter(Transceiver *);
/** control message handler thread loop */
void *ControlServiceLoopAdapter(TransceiverChannel *);
void *RxLowerLoopAdapter(Transceiver *transceiver);
void *TxLowerLoopAdapter(Transceiver *transceiver);
/** transmit queueing thread loop */
void *TxUpperLoopAdapter(TransceiverChannel *);
void *TxUpperLoopAdapter(TrxChanThParams *params);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
include $(top_srcdir)/Makefile.common
SUBDIRS = common
if ARCH_ARM
SUBDIRS += arm
else
SUBDIRS += x86
endif

View File

@@ -1,17 +1,17 @@
if ARCH_ARM
if ARCH_ARM_A15
ARCH_FLAGS = -mfpu=neon-vfpv4
else
ARCH_FLAGS = -mfpu=neon
endif
AM_CFLAGS = -Wall $(ARCH_FLAGS) -std=gnu99 -I../common
AM_CFLAGS = -Wall $(ARCH_FLAGS) -std=gnu99 -I${srcdir}/../common
AM_CCASFLAGS = $(ARCH_FLAGS)
noinst_LTLIBRARIES = libarch.la
libarch_la_LIBADD = $(top_builddir)/Transceiver52M/arch/common/libarch_common.la
libarch_la_SOURCES = \
../common/convolve_base.c \
convert.c \
convert_neon.S \
convolve.c \
@@ -20,4 +20,3 @@ libarch_la_SOURCES = \
scale_neon.S \
mult.c \
mult_neon.S
endif

View File

@@ -2,6 +2,8 @@
* NEON type conversions
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <malloc.h>
@@ -28,19 +26,9 @@
void neon_convert_ps_si16_4n(short *, const float *, const float *, int);
void neon_convert_si16_ps_4n(float *, const short *, int);
#ifndef HAVE_NEON
static void convert_si16_ps(float *out, const short *in, int len)
{
for (int i = 0; i < len; i++)
out[i] = in[i];
void convert_init(void) {
}
static void convert_ps_si16(short *out, const float *in, float scale, int len)
{
for (int i = 0; i < len; i++)
out[i] = in[i] * scale;
}
#else
/* 4*N 16-bit signed integer conversion with remainder */
static void neon_convert_si16_ps(float *out,
const short *in,
@@ -67,7 +55,6 @@ static void neon_convert_ps_si16(short *out,
for (int i = 0; i < len % 4; i++)
out[start + i] = (short) (in[start + i] * (*scale));
}
#endif
void convert_float_short(short *out, const float *in, float scale, int len)
{
@@ -79,7 +66,7 @@ void convert_float_short(short *out, const float *in, float scale, int len)
else
neon_convert_ps_si16_4n(out, in, q, len >> 2);
#else
convert_ps_si16(out, in, scale, len);
base_convert_float_short(out, in, scale, len);
#endif
}
@@ -91,6 +78,6 @@ void convert_short_float(float *out, const short *in, int len)
else
neon_convert_si16_ps_4n(out, in, len >> 2);
#else
convert_si16_ps(out, in, len);
base_convert_short_float(out, in, len);
#endif
}

View File

@@ -2,6 +2,8 @@
* NEON type conversions
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
.syntax unified

View File

@@ -2,6 +2,8 @@
* NEON Convolution
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <malloc.h>
@@ -29,17 +27,15 @@
int _base_convolve_real(float *x, int x_len,
float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset);
int start, int len);
int _base_convolve_complex(float *x, int x_len,
float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset);
int start, int len);
int bounds_check(int x_len, int h_len, int y_len,
int start, int len, int step);
int start, int len);
#ifdef HAVE_NEON
/* Calls into NEON assembler */
@@ -58,39 +54,43 @@ static void neon_conv_cmplx_4n(float *x, float *h, float *y, int h_len, int len)
}
#endif
/* API: Initialize convolve module */
void convolve_init(void)
{
/* Stub */
return;
}
/* API: Aligned complex-real */
int convolve_real(float *x, int x_len,
float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset)
int start, int len)
{
void (*conv_func)(float *, float *, float *, int) = NULL;
if (bounds_check(x_len, h_len, y_len, start, len, step) < 0)
if (bounds_check(x_len, h_len, y_len, start, len) < 0)
return -1;
memset(y, 0, len * 2 * sizeof(float));
#ifdef HAVE_NEON
if (step <= 4) {
switch (h_len) {
case 4:
conv_func = neon_conv_real4;
break;
case 8:
conv_func = neon_conv_real8;
break;
case 12:
conv_func = neon_conv_real12;
break;
case 16:
conv_func = neon_conv_real16;
break;
case 20:
conv_func = neon_conv_real20;
break;
}
switch (h_len) {
case 4:
conv_func = neon_conv_real4;
break;
case 8:
conv_func = neon_conv_real8;
break;
case 12:
conv_func = neon_conv_real12;
break;
case 16:
conv_func = neon_conv_real16;
break;
case 20:
conv_func = neon_conv_real20;
break;
}
#endif
if (conv_func) {
@@ -100,7 +100,7 @@ int convolve_real(float *x, int x_len,
_base_convolve_real(x, x_len,
h, h_len,
y, y_len,
start, len, step, offset);
start, len);
}
return len;
@@ -111,18 +111,17 @@ int convolve_real(float *x, int x_len,
int convolve_complex(float *x, int x_len,
float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset)
int start, int len)
{
void (*conv_func)(float *, float *, float *, int, int) = NULL;
if (bounds_check(x_len, h_len, y_len, start, len, step) < 0)
if (bounds_check(x_len, h_len, y_len, start, len) < 0)
return -1;
memset(y, 0, len * 2 * sizeof(float));
#ifdef HAVE_NEON
if (step <= 4 && !(h_len % 4))
if (!(h_len % 4))
conv_func = neon_conv_cmplx_4n;
#endif
if (conv_func) {
@@ -132,7 +131,7 @@ int convolve_complex(float *x, int x_len,
_base_convolve_complex(x, x_len,
h, h_len,
y, y_len,
start, len, step, offset);
start, len);
}
return len;

View File

@@ -2,6 +2,8 @@
* NEON Convolution
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
@@ -92,8 +90,8 @@ neon_conv_real12:
vld2.32 {q8-q9}, [r4], r6
vld2.32 {q10-q11}, [r5], r6
#ifdef HAVE_NEON_FMA
vfma.f32 q1, q6, q0
vfma.f32 q3, q7, q0
vmul.f32 q1, q6, q0
vmul.f32 q3, q7, q0
vfma.f32 q1, q8, q2
vfma.f32 q3, q9, q2
vfma.f32 q1, q10, q4

View File

@@ -2,6 +2,8 @@
* NEON scaling
* Copyright (C) 2012,2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <malloc.h>

View File

@@ -1,7 +1,9 @@
/*
* NEON complex multiplication
* NEON complex multiplication
* Copyright (C) 2012,2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
.syntax unified

View File

@@ -2,6 +2,8 @@
* NEON scaling
* Copyright (C) 2012,2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <malloc.h>

View File

@@ -2,6 +2,8 @@
* ARM NEON Scaling
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
.syntax unified

View File

@@ -0,0 +1,15 @@
AM_CFLAGS = -Wall -std=gnu99
noinst_LTLIBRARIES = libarch_common.la
noinst_HEADERS = \
convolve.h \
convert.h \
scale.h \
mult.h \
fft.h
libarch_common_la_SOURCES = \
convolve_base.c \
convert_base.c \
fft.c

View File

@@ -2,6 +2,14 @@
#define _CONVERT_H_
void convert_float_short(short *out, const float *in, float scale, int len);
void convert_short_float(float *out, const short *in, int len);
void base_convert_float_short(short *out, const float *in,
float scale, int len);
void base_convert_short_float(float *out, const short *in, int len);
void convert_init(void);
#endif /* _CONVERT_H_ */

View File

@@ -0,0 +1,31 @@
/*
* Conversion
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#include "convert.h"
void base_convert_float_short(short *out, const float *in,
float scale, int len)
{
for (int i = 0; i < len; i++)
out[i] = in[i] * scale;
}
void base_convert_short_float(float *out, const short *in, int len)
{
for (int i = 0; i < len; i++)
out[i] = in[i];
}

View File

@@ -1,30 +1,28 @@
#ifndef _CONVOLVE_H_
#define _CONVOLVE_H_
void *convolve_h_alloc(int num);
void *convolve_h_alloc(size_t num);
int convolve_real(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset);
int start, int len);
int convolve_complex(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset);
int start, int len);
int base_convolve_real(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset);
int start, int len);
int base_convolve_complex(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset);
int start, int len);
void convolve_init(void);
#endif /* _CONVOLVE_H_ */

View File

@@ -2,6 +2,8 @@
* Convolution
* Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -11,10 +13,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <malloc.h>
@@ -41,17 +39,17 @@ static void mac_cmplx(const float *x, const float *h, float *y)
/* Base vector complex-complex multiply and accumulate */
static void mac_real_vec_n(const float *x, const float *h, float *y,
int len, int step, int offset)
int len)
{
for (int i = offset; i < len; i += step)
for (int i=0; i<len; i++)
mac_real(&x[2 * i], &h[2 * i], y);
}
/* Base vector complex-complex multiply and accumulate */
static void mac_cmplx_vec_n(const float *x, const float *h, float *y,
int len, int step, int offset)
int len)
{
for (int i = offset; i < len; i += step)
for (int i=0; i<len; i++)
mac_cmplx(&x[2 * i], &h[2 * i], y);
}
@@ -59,14 +57,12 @@ static void mac_cmplx_vec_n(const float *x, const float *h, float *y,
int _base_convolve_real(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset)
int start, int len)
{
for (int i = 0; i < len; i++) {
mac_real_vec_n(&x[2 * (i - (h_len - 1) + start)],
h,
&y[2 * i], h_len,
step, offset);
&y[2 * i], h_len);
}
return len;
@@ -76,14 +72,13 @@ int _base_convolve_real(const float *x, int x_len,
int _base_convolve_complex(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset)
int start, int len)
{
for (int i = 0; i < len; i++) {
mac_cmplx_vec_n(&x[2 * (i - (h_len - 1) + start)],
h,
&y[2 * i],
h_len, step, offset);
h_len);
}
return len;
@@ -91,10 +86,10 @@ int _base_convolve_complex(const float *x, int x_len,
/* Buffer validity checks */
int bounds_check(int x_len, int h_len, int y_len,
int start, int len, int step)
int start, int len)
{
if ((x_len < 1) || (h_len < 1) ||
(y_len < 1) || (len < 1) || (step < 1)) {
(y_len < 1) || (len < 1)) {
fprintf(stderr, "Convolve: Invalid input\n");
return -1;
}
@@ -113,10 +108,9 @@ int bounds_check(int x_len, int h_len, int y_len,
int base_convolve_real(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset)
int start, int len)
{
if (bounds_check(x_len, h_len, y_len, start, len, step) < 0)
if (bounds_check(x_len, h_len, y_len, start, len) < 0)
return -1;
memset(y, 0, len * 2 * sizeof(float));
@@ -124,17 +118,16 @@ int base_convolve_real(const float *x, int x_len,
return _base_convolve_real(x, x_len,
h, h_len,
y, y_len,
start, len, step, offset);
start, len);
}
/* API: Non-aligned (no SSE) complex-complex */
int base_convolve_complex(const float *x, int x_len,
const float *h, int h_len,
float *y, int y_len,
int start, int len,
int step, int offset)
int start, int len)
{
if (bounds_check(x_len, h_len, y_len, start, len, step) < 0)
if (bounds_check(x_len, h_len, y_len, start, len) < 0)
return -1;
memset(y, 0, len * 2 * sizeof(float));
@@ -142,11 +135,11 @@ int base_convolve_complex(const float *x, int x_len,
return _base_convolve_complex(x, x_len,
h, h_len,
y, y_len,
start, len, step, offset);
start, len);
}
/* Aligned filter tap allocation */
void *convolve_h_alloc(int len)
void *convolve_h_alloc(size_t len)
{
#ifdef HAVE_SSE3
return memalign(16, len * 2 * sizeof(float));

View File

@@ -0,0 +1,114 @@
/*
* Fast Fourier transform
*
* Copyright (C) 2012 Tom Tsou <tom@tsou.cc>
*
* SPDX-License-Identifier: LGPL-2.1+
*
* 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/>.
* See the COPYING file in the main directory for details.
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <fftw3.h>
#include "fft.h"
struct fft_hdl {
float *fft_in;
float *fft_out;
int len;
fftwf_plan fft_plan;
};
/*! \brief Initialize FFT backend
* \param[in] reverse FFT direction
* \param[in] m FFT length
* \param[in] istride input stride count
* \param[in] ostride output stride count
* \param[in] in input buffer (FFTW aligned)
* \param[in] out output buffer (FFTW aligned)
* \param[in] ooffset initial offset into output buffer
*
* If the reverse is non-NULL, then an inverse FFT will be used. This is a
* wrapper for advanced non-contiguous FFTW usage. See FFTW documentation for
* further details.
*
* http://www.fftw.org/doc/Advanced-Complex-DFTs.html
*
* It is currently unknown how the offset of the output buffer affects FFTW
* memory alignment.
*/
struct fft_hdl *init_fft(int reverse, int m, int istride, int ostride,
float *in, float *out, int ooffset)
{
int rank = 1;
int n[] = { m };
int howmany = istride;
int idist = 1;
int odist = 1;
int *inembed = n;
int *onembed = n;
fftwf_complex *obuffer, *ibuffer;
struct fft_hdl *hdl = (struct fft_hdl *) malloc(sizeof(struct fft_hdl));
if (!hdl)
return NULL;
int direction = FFTW_FORWARD;
if (reverse)
direction = FFTW_BACKWARD;
ibuffer = (fftwf_complex *) in;
obuffer = (fftwf_complex *) out + ooffset;
hdl->fft_in = in;
hdl->fft_out = out;
hdl->fft_plan = fftwf_plan_many_dft(rank, n, howmany,
ibuffer, inembed, istride, idist,
obuffer, onembed, ostride, odist,
direction, FFTW_MEASURE);
return hdl;
}
void *fft_malloc(size_t size)
{
return fftwf_malloc(size);
}
void fft_free(void *ptr)
{
free(ptr);
}
/*! \brief Free FFT backend resources
*/
void free_fft(struct fft_hdl *hdl)
{
fftwf_destroy_plan(hdl->fft_plan);
free(hdl);
}
/*! \brief Run multiple DFT operations with the initialized plan
* \param[in] hdl handle to an initialized fft struct
*
* Input and output buffers are configured with init_fft().
*/
int cxvec_fft(struct fft_hdl *hdl)
{
fftwf_execute(hdl->fft_plan);
return 0;
}

View File

@@ -0,0 +1,13 @@
#ifndef _FFT_H_
#define _FFT_H_
struct fft_hdl;
struct fft_hdl *init_fft(int reverse, int m, int istride, int ostride,
float *in, float *out, int ooffset);
void *fft_malloc(size_t size);
void fft_free(void *ptr);
void free_fft(struct fft_hdl *hdl);
int cxvec_fft(struct fft_hdl *hdl);
#endif /* _FFT_H_ */

View File

@@ -0,0 +1,33 @@
AM_CFLAGS = -Wall -std=gnu99 -I${srcdir}/../common
noinst_LTLIBRARIES = libarch.la
noinst_LTLIBRARIES += libarch_sse_3.la
noinst_LTLIBRARIES += libarch_sse_4_1.la
noinst_HEADERS = \
convert_sse_3.h \
convert_sse_4_1.h \
convolve_sse_3.h
libarch_la_LIBADD = $(top_builddir)/Transceiver52M/arch/common/libarch_common.la
# SSE 3 specific code
if HAVE_SSE3
libarch_sse_3_la_SOURCES = \
convert_sse_3.c \
convolve_sse_3.c
libarch_sse_3_la_CFLAGS = $(AM_CFLAGS) -msse3
libarch_la_LIBADD += libarch_sse_3.la
endif
# SSE 4.1 specific code
if HAVE_SSE4_1
libarch_sse_4_1_la_SOURCES = \
convert_sse_4_1.c
libarch_sse_4_1_la_CFLAGS = $(AM_CFLAGS) -msse4.1
libarch_la_LIBADD += libarch_sse_4_1.la
endif
libarch_la_SOURCES = \
convert.c \
convolve.c

View File

@@ -0,0 +1,79 @@
/*
* SSE type conversions
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#include <malloc.h>
#include <string.h>
#include "convert.h"
#include "convert_sse_3.h"
#include "convert_sse_4_1.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Architecture dependent function pointers */
struct convert_cpu_context {
void (*convert_si16_ps_16n) (float *, const short *, int);
void (*convert_si16_ps) (float *, const short *, int);
void (*convert_scale_ps_si16_16n)(short *, const float *, float, int);
void (*convert_scale_ps_si16_8n)(short *, const float *, float, int);
void (*convert_scale_ps_si16)(short *, const float *, float, int);
};
static struct convert_cpu_context c;
void convert_init(void)
{
c.convert_scale_ps_si16_16n = base_convert_float_short;
c.convert_scale_ps_si16_8n = base_convert_float_short;
c.convert_scale_ps_si16 = base_convert_float_short;
c.convert_si16_ps_16n = base_convert_short_float;
c.convert_si16_ps = base_convert_short_float;
#ifdef HAVE___BUILTIN_CPU_SUPPORTS
#ifdef HAVE_SSE4_1
if (__builtin_cpu_supports("sse4.1")) {
c.convert_si16_ps_16n = &_sse_convert_si16_ps_16n;
c.convert_si16_ps = &_sse_convert_si16_ps;
}
#endif
#ifdef HAVE_SSE3
if (__builtin_cpu_supports("sse3")) {
c.convert_scale_ps_si16_16n = _sse_convert_scale_ps_si16_16n;
c.convert_scale_ps_si16_8n = _sse_convert_scale_ps_si16_8n;
c.convert_scale_ps_si16 = _sse_convert_scale_ps_si16;
}
#endif
#endif
}
void convert_float_short(short *out, const float *in, float scale, int len)
{
if (!(len % 16))
c.convert_scale_ps_si16_16n(out, in, scale, len);
else if (!(len % 8))
c.convert_scale_ps_si16_8n(out, in, scale, len);
else
c.convert_scale_ps_si16(out, in, scale, len);
}
void convert_short_float(float *out, const short *in, int len)
{
if (!(len % 16))
c.convert_si16_ps_16n(out, in, len);
else
c.convert_si16_ps(out, in, len);
}

View File

@@ -0,0 +1,103 @@
/*
* SSE type conversions
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#include <malloc.h>
#include <string.h>
#include "convert_sse_3.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SSE3
#include <xmmintrin.h>
#include <emmintrin.h>
/* 8*N single precision floats scaled and converted to 16-bit signed integer */
void _sse_convert_scale_ps_si16_8n(short *restrict out,
const float *restrict in,
float scale, int len)
{
__m128 m0, m1, m2;
__m128i m4, m5;
for (int i = 0; i < len / 8; i++) {
/* Load (unaligned) packed floats */
m0 = _mm_loadu_ps(&in[8 * i + 0]);
m1 = _mm_loadu_ps(&in[8 * i + 4]);
m2 = _mm_load1_ps(&scale);
/* Scale */
m0 = _mm_mul_ps(m0, m2);
m1 = _mm_mul_ps(m1, m2);
/* Convert */
m4 = _mm_cvtps_epi32(m0);
m5 = _mm_cvtps_epi32(m1);
/* Pack and store */
m5 = _mm_packs_epi32(m4, m5);
_mm_storeu_si128((__m128i *) & out[8 * i], m5);
}
}
/* 8*N single precision floats scaled and converted with remainder */
void _sse_convert_scale_ps_si16(short *restrict out,
const float *restrict in, float scale, int len)
{
int start = len / 8 * 8;
_sse_convert_scale_ps_si16_8n(out, in, scale, len);
for (int i = 0; i < len % 8; i++)
out[start + i] = in[start + i] * scale;
}
/* 16*N single precision floats scaled and converted to 16-bit signed integer */
void _sse_convert_scale_ps_si16_16n(short *restrict out,
const float *restrict in,
float scale, int len)
{
__m128 m0, m1, m2, m3, m4;
__m128i m5, m6, m7, m8;
for (int i = 0; i < len / 16; i++) {
/* Load (unaligned) packed floats */
m0 = _mm_loadu_ps(&in[16 * i + 0]);
m1 = _mm_loadu_ps(&in[16 * i + 4]);
m2 = _mm_loadu_ps(&in[16 * i + 8]);
m3 = _mm_loadu_ps(&in[16 * i + 12]);
m4 = _mm_load1_ps(&scale);
/* Scale */
m0 = _mm_mul_ps(m0, m4);
m1 = _mm_mul_ps(m1, m4);
m2 = _mm_mul_ps(m2, m4);
m3 = _mm_mul_ps(m3, m4);
/* Convert */
m5 = _mm_cvtps_epi32(m0);
m6 = _mm_cvtps_epi32(m1);
m7 = _mm_cvtps_epi32(m2);
m8 = _mm_cvtps_epi32(m3);
/* Pack and store */
m5 = _mm_packs_epi32(m5, m6);
m7 = _mm_packs_epi32(m7, m8);
_mm_storeu_si128((__m128i *) & out[16 * i + 0], m5);
_mm_storeu_si128((__m128i *) & out[16 * i + 8], m7);
}
}
#endif

View File

@@ -0,0 +1,30 @@
/*
* SSE type conversions
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#pragma once
/* 8*N single precision floats scaled and converted to 16-bit signed integer */
void _sse_convert_scale_ps_si16_8n(short *restrict out,
const float *restrict in,
float scale, int len);
/* 8*N single precision floats scaled and converted with remainder */
void _sse_convert_scale_ps_si16(short *restrict out,
const float *restrict in, float scale, int len);
/* 16*N single precision floats scaled and converted to 16-bit signed integer */
void _sse_convert_scale_ps_si16_16n(short *restrict out,
const float *restrict in,
float scale, int len);

View File

@@ -0,0 +1,73 @@
/*
* SSE type conversions
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#include <malloc.h>
#include <string.h>
#include "convert_sse_4_1.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SSE4_1
#include <smmintrin.h>
/* 16*N 16-bit signed integer converted to single precision floats */
void _sse_convert_si16_ps_16n(float *restrict out,
const short *restrict in, int len)
{
__m128i m0, m1, m2, m3, m4, m5;
__m128 m6, m7, m8, m9;
for (int i = 0; i < len / 16; i++) {
/* Load (unaligned) packed floats */
m0 = _mm_loadu_si128((__m128i *) & in[16 * i + 0]);
m1 = _mm_loadu_si128((__m128i *) & in[16 * i + 8]);
/* Unpack */
m2 = _mm_cvtepi16_epi32(m0);
m4 = _mm_cvtepi16_epi32(m1);
m0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1, 0, 3, 2));
m1 = _mm_shuffle_epi32(m1, _MM_SHUFFLE(1, 0, 3, 2));
m3 = _mm_cvtepi16_epi32(m0);
m5 = _mm_cvtepi16_epi32(m1);
/* Convert */
m6 = _mm_cvtepi32_ps(m2);
m7 = _mm_cvtepi32_ps(m3);
m8 = _mm_cvtepi32_ps(m4);
m9 = _mm_cvtepi32_ps(m5);
/* Store */
_mm_storeu_ps(&out[16 * i + 0], m6);
_mm_storeu_ps(&out[16 * i + 4], m7);
_mm_storeu_ps(&out[16 * i + 8], m8);
_mm_storeu_ps(&out[16 * i + 12], m9);
}
}
/* 16*N 16-bit signed integer conversion with remainder */
void _sse_convert_si16_ps(float *restrict out,
const short *restrict in, int len)
{
int start = len / 16 * 16;
_sse_convert_si16_ps_16n(out, in, len);
for (int i = 0; i < len % 16; i++)
out[start + i] = in[start + i];
}
#endif

View File

@@ -0,0 +1,24 @@
/*
* SSE type conversions
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*/
#pragma once
/* 16*N 16-bit signed integer converted to single precision floats */
void _sse_convert_si16_ps_16n(float *restrict out,
const short *restrict in, int len);
/* 16*N 16-bit signed integer conversion with remainder */
void _sse_convert_si16_ps(float *restrict out,
const short *restrict in, int len);

Some files were not shown because too many files have changed in this diff Show More