Merge branch 'working_mac'

master
ismagom 10 years ago
commit 1979ca2bcc

@ -1,20 +1,20 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# 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.
#
# srsLTE 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.
# GNU Affero General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
@ -75,7 +75,7 @@ macro(ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(${flag} ${have})
if(${have})
add_definitions(${flag})
add_definitions(${flag})
endif(${have})
endmacro(ADD_CXX_COMPILER_FLAG_IF_AVAILABLE)
@ -128,24 +128,11 @@ ADD_CUSTOM_TARGET(uninstall
########################################################################
# Macro to add -fPIC property to static libs
########################################################################
MACRO(LIBLTE_SET_PIC)
MACRO(SRSLTE_SET_PIC)
IF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" )
SET_TARGET_PROPERTIES(${ARGV} PROPERTIES COMPILE_FLAGS -fPIC)
ENDIF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" )
ENDMACRO(LIBLTE_SET_PIC)
########################################################################
# A macro for passing lists between different directories
# through an internal cache variable.
########################################################################
MACRO (APPEND_INTERNAL_LIST LIST_NAME VALUE)
# If the list in not in the cache, create it.
IF (${LIST_NAME})
SET (${LIST_NAME} "${${LIST_NAME}};${VALUE}" CACHE INTERNAL "Internal variable")
ELSE (${LIST_NAME})
SET (${LIST_NAME} "${VALUE}" CACHE INTERNAL "Internal variable")
ENDIF (${LIST_NAME})
ENDMACRO (APPEND_INTERNAL_LIST)
ENDMACRO(SRSLTE_SET_PIC)
########################################################################
# Print summary
@ -156,15 +143,12 @@ MESSAGE(STATUS "Building for version: ${VERSION}")
########################################################################
# Add general includes and dependencies
########################################################################
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/common/include)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/srslte/include/)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cuhd/include)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/mex/include)
########################################################################
# Add the subdirectories
########################################################################
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(cuhd)
ADD_SUBDIRECTORY(srslte)
add_subdirectory(mex)
ADD_SUBDIRECTORY(mex)
ADD_SUBDIRECTORY(srsapps)

@ -1,165 +1,661 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.

@ -16,8 +16,8 @@ FIND_LIBRARY(
HINTS $ENV{UHD_DIR}/lib
PATHS /usr/local/lib
/usr/lib
/usr/local/lib64
/usr/local/lib32
/usr/local/lib64
/usr/local/lib32
)
INCLUDE(FindPackageHandleStandardArgs)

@ -0,0 +1,52 @@
# - Try to find openLTE's liblte
find_package(PkgConfig)
pkg_check_modules(PC_OPENLTE QUIET srslte)
set(OPENLTE_DEFINITIONS ${PC_OPENLTE_CFLAGS_OTHER})
FIND_PATH(
OPENLTE_LIBLTE_DIRS
NAMES liblte_common.h typedefs.h
HINTS ${PC_OPENLTE_SRCDIR}/liblte/hdr
${PC_OPENLTE_INCLUDEDIR}
${PC_OPENLTE_INCLUDE_DIRS}
$ENV{OPENLTE_DIR}/liblte/hdr
PATHS /usr/local/include
/usr/include
)
FIND_PATH(
OPENLTE_COMMON_DIRS
NAMES typedefs.h
HINTS ${PC_OPENLTE_SRCDIR}/cmn_hdr
${PC_OPENLTE_INCLUDEDIR}
${PC_OPENLTE_INCLUDE_DIRS}
$ENV{OPENLTE_DIR}/liblte/hdr
PATHS /usr/local/include
/usr/include
)
FIND_LIBRARY(
OPENLTE_LIBRARIES
NAMES lte
HINTS ${PC_OPENLTE_BUILDDIR}/liblte
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
$ENV{OPENLTE_DIR}/lib
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
IF(OPENLTE_LIBLTE_DIRS AND OPENLTE_COMMON_DIRS)
SET(OPENLTE_INCLUDE_DIRS ${OPENLTE_LIBLTE_DIRS} ${OPENLTE_COMMON_DIRS})
ENDIF(OPENLTE_LIBLTE_DIRS AND OPENLTE_COMMON_DIRS)
message(STATUS "OPENLTE LIBRARIES " ${OPENLTE_LIBRARIES})
message(STATUS "OPENLTE INCLUDE DIRS " ${OPENLTE_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENLTE DEFAULT_MSG OPENLTE_LIBRARIES OPENLTE_INCLUDE_DIRS)
MARK_AS_ADVANCED(OPENLTE_LIBRARIES OPENLTE_INCLUDE_DIRS)

@ -1,42 +0,0 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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 3 of
# the License, or (at your option) any later version.
#
# srsLTE 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.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# Install headers
########################################################################
INSTALL(DIRECTORY include/ DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
########################################################################
# Add headers to cmake project (useful for IDEs)
########################################################################
SET(HEADERS_ALL "")
FILE(GLOB headers *)
FOREACH (_header ${headers})
IF(IS_DIRECTORY ${_header})
FILE(GLOB_RECURSE tmp "${_header}/*.h")
LIST(APPEND HEADERS_ALL ${tmp})
ENDIF(IS_DIRECTORY ${_header})
ENDFOREACH()
ADD_CUSTOM_TARGET (add_common_headers SOURCES ${HEADERS_ALL})

@ -1,48 +0,0 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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 3 of
# the License, or (at your option) any later version.
#
# srsLTE 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.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# Install headers
########################################################################
INSTALL(DIRECTORY include/
DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
########################################################################
# Add headers to cmake project (useful for IDEs)
########################################################################
SET(HEADERS_ALL "")
FILE(GLOB headers *)
FOREACH (_header ${headers})
IF(IS_DIRECTORY ${_header})
FILE(GLOB_RECURSE tmp "${_header}/*.h")
LIST(APPEND HEADERS_ALL ${tmp})
ENDIF(IS_DIRECTORY ${_header})
ENDFOREACH()
ADD_CUSTOM_TARGET (add_cuhd_headers SOURCES ${HEADERS_ALL})
########################################################################
# Add the subdirectories
########################################################################
ADD_SUBDIRECTORY(lib)

@ -1,41 +0,0 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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 3 of
# the License, or (at your option) any later version.
#
# srsLTE 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.
#
# A copy of the GNU Lesser General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
FIND_PACKAGE(UHD)
IF(UHD_FOUND)
ADD_LIBRARY(cuhd SHARED cuhd_imp.cpp cuhd_utils.c radio_uhd.cc)
INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS})
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
TARGET_LINK_LIBRARIES(cuhd ${UHD_LIBRARIES})
LIBLTE_SET_PIC(cuhd)
APPEND_INTERNAL_LIST(OPTIONAL_LIBS cuhd)
INSTALL(TARGETS cuhd DESTINATION ${LIBRARY_DIR})
MESSAGE(STATUS " cuhd UHD C wrapper will be installed.")
ELSE(UHD_FOUND)
MESSAGE(STATUS " UHD driver not found. CUHD library is not generated")
ENDIF(UHD_FOUND)

@ -1,79 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include "srslte/cuhd/cuhd.h"
#include "srslte/utils/vector.h"
#include "srslte/utils/debug.h"
int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) {
int i, j;
int ret = -1;
_Complex float *buffer;
double f;
buffer = calloc(nsamp, sizeof(_Complex float));
if (!buffer) {
goto free_and_exit;
}
cuhd_set_rx_gain(uhd, 20.0);
cuhd_set_rx_srate(uhd, fs);
for (i=0;i<nof_bands;i++) {
cuhd_stop_rx_stream(uhd);
f = (double) freqs[i];
cuhd_set_rx_freq(uhd, f);
cuhd_rx_wait_lo_locked(uhd);
usleep(10000);
cuhd_start_rx_stream(uhd);
/* discard first samples */
for (j=0;j<2;j++) {
if (cuhd_recv(uhd, buffer, nsamp, 1) != nsamp) {
goto free_and_exit;
}
}
rssi[i] = srslte_vec_avg_power_cf(buffer, nsamp);
printf("[%3d]: Freq %4.1f Mhz - RSSI: %3.2f dBm\r", i, f/1000000, 10*log10f(rssi[i]) + 30); fflush(stdout);
if (SRSLTE_VERBOSE_ISINFO()) {
printf("\n");
}
}
cuhd_stop_rx_stream(uhd);
ret = 0;
free_and_exit:
free(buffer);
return ret;
}

@ -1,12 +1,18 @@
function cfo = cfo_estimate_cp(input, Nsyms, sym_len, cp0_len, cp_len)
function cfo = cfo_estimate_cp(input_slot, Nsyms, sym_len, cp0_len, cp_len)
r=zeros(Nsyms, 1);
r(1)=sum(input(1:cp0_len).*conj(input(1+sym_len:cp0_len+sym_len)));
s=cp0_len+sym_len+1;
e=cp0_len+sym_len+cp_len;
for i=2:Nsyms
r(i)=sum(input(s:e).*conj(input(s+sym_len:e+sym_len)));
s=s+sym_len+cp_len;
e=e+sym_len+cp_len;
% Start correlating from the end. Nsyms is the number of symbols to
% correlate starting from the end.
s=length(input_slot)-sym_len-cp_len;
e=length(input_slot)-sym_len;
for i=1:Nsyms
r(i)=sum(input_slot(s:e).*conj(input_slot(s+sym_len:e+sym_len)));
if (i < 7)
s=s-sym_len-cp_len;
e=e-sym_len-cp_len;
else
s=s-sym_len-cp0_len;
e=e-sym_len-cp0_len;
end
end
cfo=-angle(mean(r))/2/pi;
cfo=-angle(mean(r))/pi;

@ -1,27 +1,26 @@
%clear;
M=1000;
clear;
sym_len=128;
x=lte(1:M*15360*sym_len/2048*2000/1536);
%x=read_complex('../../../eclipse_osldlib/test.dat');
%y=resample(x,99839996,100000000);
input=resample(x,1536,2000);
%input=x;
%input=y(1:M*15360*sym_len/2048);
%input=resample(x,3840000,1920000);
hflen = (sym_len/128)*1920*5;
samp_rate = (sym_len/128)*1920000;
N_id_2=1;
input=read_complex('../../build/lte_signal.dat', hflen*200);
cp0_len=160*sym_len/2048;
cp1_len=144*sym_len/2048;
slots=reshape(input,15360*sym_len/2048,[]);
[n m]=size(slots);
%t = (0:length(input)-1).'/samp_rate;
%input = input .* exp(-1i*2*pi*2000.0*t);
subframes=reshape(input,hflen,[]);
[n m]=size(subframes);
cfo=zeros(m,1);
output=zeros(size(input));
cfdl=struct('NDLRB',6,'CyclicPrefix','Normal','DuplexMode','FDD');
cfo=zeros(m,2);
for i=1:m
cfo(i)=cfo_estimate(slots(:,i),7,sym_len,cp1_len,cp1_len);
t=(i-1)*n+1:i*n;
%output(t)=input(t).*exp(-1i*2*pi*cfo(i)*t/sym_len);
[toffset, cfo(i,2)] = find_pss(subframes(:,i),N_id_2);
cfo(i,1) = lteFrequencyOffset(cfdl,subframes(:,i),toffset)/15000;
end
plot(cfo)
plot(cfo*15000)
legend('Matlab','PSS-based')
disp(mean(cfo)*15)

@ -1,55 +0,0 @@
function [ s0_m0 z1_m0 ] = compute_m0( m0)
%COMPUTE_S Summary of this function goes here
% Detailed explanation goes here
% Generate s_tilda
x_s_tilda(0+1) = 0;
x_s_tilda(1+1) = 0;
x_s_tilda(2+1) = 0;
x_s_tilda(3+1) = 0;
x_s_tilda(4+1) = 1;
for(i_hat=0:25)
x_s_tilda(i_hat+5+1) = mod((x_s_tilda(i_hat+2+1) + x_s_tilda(i_hat+1)), 2);
end
for(idx=0:30)
s_tilda(idx+1) = 1 - 2*x_s_tilda(idx+1);
end
% Generate c_tilda
x_c_tilda(0+1) = 0;
x_c_tilda(1+1) = 0;
x_c_tilda(2+1) = 0;
x_c_tilda(3+1) = 0;
x_c_tilda(4+1) = 1;
for(i_hat=0:25)
x_c_tilda(i_hat+5+1) = mod((x_c_tilda(i_hat+3+1) + x_c_tilda(i_hat+1)), 2);
end
for(idx=0:30)
c_tilda(idx+1) = 1 - 2*x_c_tilda(idx+1);
end
% Generate z_tilda
x_z_tilda(0+1) = 0;
x_z_tilda(1+1) = 0;
x_z_tilda(2+1) = 0;
x_z_tilda(3+1) = 0;
x_z_tilda(4+1) = 1;
for(i_hat=0:25)
x_z_tilda(i_hat+5+1) = mod((x_z_tilda(i_hat+4+1) + x_z_tilda(i_hat+2+1) + x_z_tilda(i_hat+1+1) + x_z_tilda(i_hat+1)), 2);
end
for(idx=0:30)
z_tilda(idx+1) = 1 - 2*x_z_tilda(idx+1);
end
% Generate s0_m0 and s1_m1
for(n=0:30)
s0_m0(n+1) = s_tilda(mod(n + m0, 31)+1);
end
% Generate z1_m0 and z1_m1
for(n=0:30)
z1_m0(n+1) = z_tilda(mod(n + mod(m0, 8), 31)+1);
end
end

@ -1,49 +0,0 @@
function [ s1_m1 ] = compute_m1( m1, N_id_2)
%COMPUTE_S Summary of this function goes here
% Detailed explanation goes here
% Generate s_tilda
x_s_tilda(0+1) = 0;
x_s_tilda(1+1) = 0;
x_s_tilda(2+1) = 0;
x_s_tilda(3+1) = 0;
x_s_tilda(4+1) = 1;
for(i_hat=0:25)
x_s_tilda(i_hat+5+1) = mod((x_s_tilda(i_hat+2+1) + x_s_tilda(i_hat+1)), 2);
end
for(idx=0:30)
s_tilda(idx+1) = 1 - 2*x_s_tilda(idx+1);
end
% Generate c_tilda
x_c_tilda(0+1) = 0;
x_c_tilda(1+1) = 0;
x_c_tilda(2+1) = 0;
x_c_tilda(3+1) = 0;
x_c_tilda(4+1) = 1;
for(i_hat=0:25)
x_c_tilda(i_hat+5+1) = mod((x_c_tilda(i_hat+3+1) + x_c_tilda(i_hat+1)), 2);
end
for(idx=0:30)
c_tilda(idx+1) = 1 - 2*x_c_tilda(idx+1);
end
% Generate z_tilda
x_z_tilda(0+1) = 0;
x_z_tilda(1+1) = 0;
x_z_tilda(2+1) = 0;
x_z_tilda(3+1) = 0;
x_z_tilda(4+1) = 1;
for(i_hat=0:25)
x_z_tilda(i_hat+5+1) = mod((x_z_tilda(i_hat+4+1) + x_z_tilda(i_hat+2+1) + x_z_tilda(i_hat+1+1) + x_z_tilda(i_hat+1)), 2);
end
for(idx=0:30)
z_tilda(idx+1) = 1 - 2*x_z_tilda(idx+1);
end
% Generate s0_m0 and s1_m1
for(n=0:30)
s1_m1(n+1) = s_tilda(mod(n + m1, 31)+1);
end
end

@ -1,57 +0,0 @@
function [out] = convfft(z1,z2)
%CONVFFT FFT-based convolution and polynomial multiplication.
% C = CONVFFT(A, B) convolves vectors A and B. The resulting
% vector is length LENGTH(A)+LENGTH(B)-1.
% If A and B are vectors of polynomial coefficients, convolving
% them is equivalent to multiplying the two polynomials.
%
% Please contribute if you find this software useful.
% Report bugs to luigi.rosa@tiscali.it
%
%*****************************************************************
% Luigi Rosa
% Via Centrale 27
% 67042 Civita di Bagno
% L'Aquila --- ITALY
% email luigi.rosa@tiscali.it
% mobile +39 340 3463208
% http://utenti.lycos.it/matlab
%*****************************************************************
%
z1x=size(z1,1);
z1y=size(z1,2);
z2x=size(z2,1);
z2y=size(z2,2);
if (~isa(z1,'double'))||(~isa(z2,'double'))||(ndims(z1)>2)||(ndims(z2)>2)
disp('Error: input vector must be unidimensional double array');
out=[];
return;
else
if ((z1x>1)&&(z1y>1)) || ((z2x>1)&&(z2y>1))
out=[];
disp('Error: input vectors are double matrices');
return;
else
if (z1x==1)&&(z1y>1)
z1=z1';
z1x=z1y;
end
if (z2x==1)&&(z2y>1)
z2=z2';
z2x=z2y;
end
if (any(any(imag(z1))))||(any(any(imag(z2))))
out=(ifft(fft(z1,z1x+z2x-1).*fft(z2,z1x+z2x-1)));
else
out=real(ifft(fft(z1,z1x+z2x-1).*fft(z2,z1x+z2x-1)));
end
end
end

@ -1,82 +0,0 @@
function [coarse_start freq_offset] = find_coarse_time_and_freq_offset(in, N_cp_l_else)
% Decompose input
in_re = real(in);
in_im = imag(in);
abs_corr = zeros(1,960);
for(slot=0:10)
for(n=1:40:960)
corr_re = 0;
corr_im = 0;
for(z=1:N_cp_l_else)
index = (slot*960) + n-1 + z;
corr_re = corr_re + in_re(index)*in_re(index+128) + in_im(index)*in_im(index+128);
corr_im = corr_im + in_re(index)*in_im(index+128) - in_im(index)*in_re(index+128);
end
abs_corr(n) = abs_corr(n) + corr_re*corr_re + corr_im*corr_im;
end
end
% Find first and second max
abs_corr_idx = zeros(1,2);
for(m=0:1)
abs_corr_max = 0;
for(n=1:480)
if(abs_corr((m*480)+n) > abs_corr_max)
abs_corr_max = abs_corr((m*480)+n);
abs_corr_idx(m+1) = (m*480)+n;
end
end
end
% Fine correlation and fraction frequency offset
abs_corr = zeros(1,960);
corr_freq_err = zeros(1,960);
for(slot=1:10)
for(idx=1:2)
if((abs_corr_idx(idx) - 40) < 1)
abs_corr_idx(idx) = 41;
end
if((abs_corr_idx(idx) + 40) > 960)
abs_corr_idx(idx) = 960 - 40;
end
for(n=abs_corr_idx(idx)-40:abs_corr_idx(idx)+40)
corr_re = 0;
corr_im = 0;
for(z=1:N_cp_l_else)
index = (slot*960) + n-1 + z;
corr_re = corr_re + in_re(index)*in_re(index+128) + in_im(index)*in_im(index+128);
corr_im = corr_im + in_re(index)*in_im(index+128) - in_im(index)*in_re(index+128);
end
abs_corr(n) = abs_corr(n) + corr_re*corr_re + corr_im*corr_im;
corr_freq_err(n) = corr_freq_err(n) + atan2(corr_im, corr_re)/(128*2*pi*(0.0005/960));
end
end
end
% Find first and second max
abs_corr_idx = zeros(1,2);
for(m=0:1)
abs_corr_max = 0;
for(n=1:480)
if(abs_corr((m*480)+n) > abs_corr_max)
abs_corr_max = abs_corr((m*480)+n);
abs_corr_idx(m+1) = (m*480)+n;
end
end
end
% Determine frequency offset FIXME No integer offset is calculated here
freq_offset = (corr_freq_err(abs_corr_idx(1))/10 + corr_freq_err(abs_corr_idx(2))/10)/2;23
% Determine the symbol start locations from the correlation peaks
% FIXME Needs some work
tmp = abs_corr_idx(1);
while(tmp > 0)
tmp = tmp - 2192;
end
for(n=1:7)
coarse_start(n) = tmp + (n*2192);
end
end

@ -1,31 +1,18 @@
function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot, threshold)
if nargin == 2
doplot = false;
threshold = 0;
end
if nargin == 3
threshold = 0;
end
function [ fs, cfo, p_m, w2] = find_pss( x, N_id_2)
c=lte_pss_zc(N_id_2);
cc=[zeros(33,1); c; zeros(33,1)];
ccf=[0; cc(65:128); cc(2:64)];
ccf=conj(ifft(ccf));
w2=conv(x,ccf);
if (doplot)
%plot(10*log10(abs(w2)));%./mean(abs(w2))));
plot(abs(w2))
%axis([0 length(w2) 0 20])
end
[m i]=max(abs(w2));
fs=i-960;
p_m = m/mean(abs(w2));
if doplot
fprintf('Frame starts at %d, m=%g, p=%g, p/m=%g dB\n',fs, ...
mean(abs(w2)), m, 10*log10(m/mean(abs(w2))));
end
[m, fs]=max(abs(w2));
y=ccf.*x(fs-128:fs-1);
y0=y(1:64);
y1=y(65:length(y));
cfo=angle(conj(sum(y0))*sum(y1))/pi;
p_m = m/mean(abs(w2));
end

@ -6,7 +6,7 @@ clear
plot_noise_estimation_only=false;
SNR_values_db=20;%linspace(0,30,8);
SNR_values_db=10;%linspace(0,30,8);
Nrealizations=1 ;
preEVM = zeros(length(SNR_values_db),Nrealizations);
@ -147,7 +147,7 @@ rxWaveform = rxWaveform(1+offset+2:end,:);
rxGrid = lteOFDMDemodulate(enb,rxWaveform);
rxGrid = rxGrid(:,1:140);
addpath('../../debug/srslte/lib/ch_estimation/test')
addpath('../../build/srslte/lib/ch_estimation/test')
%% Channel Estimation
[estChannel, noiseEst(snr_idx)] = lteDLChannelEstimate(enb,cec,rxGrid);
@ -156,68 +156,69 @@ snrest_srslte = zeros(10,1);
noise_srslte = zeros(10,1);
rsrp = zeros(1,10);
for i=0:9
[d, a, out, snrest_srslte(i+1), noise_srslte(i+1), rsrp(i+1)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid(:,i*14+1:(i+1)*14),[0.1 0.8 0.1],[0.1 0.9],i);
output = [output out];
[d, ~, out] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid);
output = [output out];
%RSRP = [RSRP rsrp];
%meanRSRP(snr_idx)=mean(rsrp);
%SNR_srslte(snr_idx)=mean(snrest_srslte);
%noiseEst_srslte(snr_idx)=mean(noise_srslte);
d=reshape(d, size(estChannel));
plot(1:288,real(reshape(estChannel(:,11:14),1,[])),'b-',...
1:288,real(reshape(d(:,11:14),1,[])),'r-')
% if ~plot_noise_estimation_only
%
% %% MMSE Equalization
% eqGrid_mmse = lteEqualizeMMSE(rxGrid, estChannel, noiseEst(snr_idx));
%
% eqGrid_srslte = reshape(output,size(eqGrid_mmse));
%
% % Analysis
%
% %Compute EVM across all input values EVM of pre-equalized receive signal
% preEqualisedEVM = lteEVM(txGrid,rxGrid);
% fprintf('%d-%d: Pre-EQ: %0.3f%%\n', ...
% snr_idx,nreal,preEqualisedEVM.RMS*100);
%
%
% %EVM of post-equalized receive signal
% postEqualisedEVM_mmse = lteEVM(txGrid,reshape(eqGrid_mmse,size(txGrid)));
% fprintf('%d-%d: MMSE: %0.3f%%\n', ...
% snr_idx,nreal,postEqualisedEVM_mmse.RMS*100);
%
% postEqualisedEVM_srslte = lteEVM(txGrid,reshape(eqGrid_srslte,size(txGrid)));
% fprintf('%d-%d: srslte: %0.3f%%\n', ...
% snr_idx,nreal,postEqualisedEVM_srslte.RMS*100);
%
% preEVM(snr_idx,nreal) = preEqualisedEVM.RMS;
% postEVM_mmse(snr_idx,nreal) = mean([postEqualisedEVM_mmse.RMS]);
% postEVM_srslte(snr_idx,nreal) = mean([postEqualisedEVM_srslte.RMS]);
% end
end
RSRP = [RSRP rsrp];
meanRSRP(snr_idx)=mean(rsrp);
SNR_srslte(snr_idx)=mean(snrest_srslte);
noiseEst_srslte(snr_idx)=mean(noise_srslte);
if ~plot_noise_estimation_only
%% MMSE Equalization
eqGrid_mmse = lteEqualizeMMSE(rxGrid, estChannel, noiseEst(snr_idx));
eqGrid_srslte = reshape(output,size(eqGrid_mmse));
% Analysis
%Compute EVM across all input values EVM of pre-equalized receive signal
preEqualisedEVM = lteEVM(txGrid,rxGrid);
fprintf('%d-%d: Pre-EQ: %0.3f%%\n', ...
snr_idx,nreal,preEqualisedEVM.RMS*100);
%EVM of post-equalized receive signal
postEqualisedEVM_mmse = lteEVM(txGrid,reshape(eqGrid_mmse,size(txGrid)));
fprintf('%d-%d: MMSE: %0.3f%%\n', ...
snr_idx,nreal,postEqualisedEVM_mmse.RMS*100);
postEqualisedEVM_srslte = lteEVM(txGrid,reshape(eqGrid_srslte,size(txGrid)));
fprintf('%d-%d: srslte: %0.3f%%\n', ...
snr_idx,nreal,postEqualisedEVM_srslte.RMS*100);
preEVM(snr_idx,nreal) = preEqualisedEVM.RMS;
postEVM_mmse(snr_idx,nreal) = mean([postEqualisedEVM_mmse.RMS]);
postEVM_srslte(snr_idx,nreal) = mean([postEqualisedEVM_srslte.RMS]);
end
end
end
% subplot(1,2,1)
if ~plot_noise_estimation_only
plot(SNR_values_db, mean(preEVM,2), ...
SNR_values_db, mean(postEVM_mmse,2), ...
SNR_values_db, mean(postEVM_srslte,2))
legend('No Eq','MMSE-lin','MMSE-srslte')
grid on
end
% subplot(1,2,2)
if plot_noise_estimation_only
SNR_matlab = 1./(noiseEst*sqrt(2.0)*enb.CellRefP);
subplot(1,3,1)
plot(SNR_values_db, SNR_values_db, SNR_values_db, 10*log10(SNR_srslte),SNR_values_db, 10*log10(SNR_matlab))
legend('Theory','srsLTE','Matlab')
subplot(1,3,2)
plot(SNR_values_db, 10*log10(noiseTx), SNR_values_db, 10*log10(noiseEst_srslte),SNR_values_db, 10*log10(noiseEst))
legend('Theory','srsLTE','Matlab')
subplot(1,3,3)
plot(1:10*length(SNR_values_db),RSRP,10*(1:length(SNR_values_db)),meanRSRP)
end
%
% % subplot(1,2,1)
%
% if ~plot_noise_estimation_only
% plot(SNR_values_db, mean(preEVM,2), ...
% SNR_values_db, mean(postEVM_mmse,2), ...
% SNR_values_db, mean(postEVM_srslte,2))
% legend('No Eq','MMSE-lin','MMSE-srslte')
% grid on
% end
%
% % subplot(1,2,2)
% if plot_noise_estimation_only
% SNR_matlab = 1./(noiseEst*sqrt(2.0)*enb.CellRefP);
%
% subplot(1,3,1)
% plot(SNR_values_db, SNR_values_db, SNR_values_db, 10*log10(SNR_srslte),SNR_values_db, 10*log10(SNR_matlab))
% legend('Theory','srsLTE','Matlab')
%
% subplot(1,3,2)
% plot(SNR_values_db, 10*log10(noiseTx), SNR_values_db, 10*log10(noiseEst_srslte),SNR_values_db, 10*log10(noiseEst))
% legend('Theory','srsLTE','Matlab')
%
% subplot(1,3,3)
% plot(1:10*length(SNR_values_db),RSRP,10*(1:length(SNR_values_db)),meanRSRP)
% end

@ -2,18 +2,18 @@ clear
ueConfig=struct('NULRB',6,'DuplexMode','FDD','CyclicPrefix','Normal');
prachConfig=struct('Format',0,'SeqIdx',0,'PreambleIdx',0,'CyclicShiftIdx',0,'HighSpeed',0,'TimingOffset',0,'FreqIdx',0,'FreqOffset',0);
addpath('../../debug/lte/phy/lib/phch/test')
addpath('../../debug/srslte/lib/phch/test')
NULRB=[15 25 50 100];
NULRB=[6 15 25 50 100];
% FreqIdx, FreqOffset and TimeOffset need to be tested
for n_rb=1:length(NULRB)
for format=1:3;
for seqIdx=0:17:837
for n_rb=3:length(NULRB)
for format=0;
for seqIdx=7:17:237
fprintf('RB: %d, format %d, seqIdx: %d\n',NULRB(n_rb),format,seqIdx);
for preambleIdx=0:23:63
for CyclicShift=0:6:15
for CyclicShift=1:3:15
%for hs=0:1
hs=0;
ueConfig.NULRB=NULRB(n_rb);
@ -22,12 +22,12 @@ for n_rb=1:length(NULRB)
prachConfig.PreambleIdx=preambleIdx;
prachConfig.CyclicShiftIdx=CyclicShift;
prachConfig.HighSpeed=hs;
prachConfig.FreqIdx=5;
prachConfig.FreqOffest=5;
lib=srslte_prach(ueConfig,prachConfig);
prachConfig.FreqIdx=0;
prachConfig.FreqOffset=0;
lib=srslte_prach(ueConfig,prachConfig)*2.4645;
[mat, info]=ltePRACH(ueConfig,prachConfig);
err=mean(abs(mat(:)-lib(1:length(mat))));
err=mean(abs(mat-lib));
if (err > 10^-3)
disp(err)
error('Error!');

@ -1,20 +1,20 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# 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.
#
# srsLTE 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.
# GNU Affero General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -1,20 +1,20 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# 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.
#
# srsLTE 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.
# GNU Affero General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
@ -41,7 +41,7 @@ if(MATLAB_FOUND)
message(STATUS "Found MATLAB in ${MATLAB_ROOT}")
add_library(srslte_mex SHARED mexutils.c)
install(TARGETS srslte_mex DESTINATION ${LIBRARY_DIR})
liblte_set_pic(srslte_mex)
SRSLTE_SET_PIC(srslte_mex)
include_directories(${MATLAB_INCLUDE_DIR})
endif(MATLAB_FOUND)
@ -50,7 +50,7 @@ if(OCTAVE_FOUND)
if (NOT MATLAB_FOUND)
add_library(srslte_mex SHARED mexutils.c)
install(TARGETS srslte_mex DESTINATION ${LIBRARY_DIR})
liblte_set_pic(srslte_mex)
SRSLTE_SET_PIC(srslte_mex)
endif (NOT MATLAB_FOUND)
include_directories(${OCTAVE_INCLUDE_DIR})
endif(OCTAVE_FOUND)

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -0,0 +1,34 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
########################################################################
# Install headers
########################################################################
remove_definitions(-fvisibility=hidden)
INCLUDE_DIRECTORIES(radio/include/)
INCLUDE_DIRECTORIES(common/include/)
add_subdirectory(radio)
add_subdirectory(common)
add_subdirectory(ue)

@ -0,0 +1,34 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
INSTALL(DIRECTORY include/
DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
FILE(GLOB SOURCES "src/*.cc")
ADD_LIBRARY(srsapps_common SHARED ${SOURCES})
INSTALL(TARGETS srsapps_common DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srsapps_common)
FILE(GLOB HEADERS_ALL "include/srsapps/common/*.h")
ADD_CUSTOM_TARGET (add_srsapps_common_headers SOURCES ${HEADERS_ALL})

@ -0,0 +1,72 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#ifndef BINSEM_H
#define BINSEM_H
/** Implementation of a binary semaphore using POSIX condition variable and mutex
*/
namespace srslte {
class binsem
{
public:
binsem() {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cv, NULL);
state = true;
}
~binsem() {
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cv);
}
void take() {
pthread_mutex_lock(&mutex);
while(!state) {
pthread_cond_wait(&cv, &mutex);
}
state = false;
pthread_mutex_unlock(&mutex);
}
void give() {
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cv);
state = true;
pthread_mutex_unlock(&mutex);
}
private:
pthread_cond_t cv;
pthread_mutex_t mutex;
bool state;
};
}
#endif

@ -0,0 +1,64 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef CONFIG_H
#define CONFIG_H
// Generic helper definitions for shared library support
#if defined _WIN32 || defined __CYGWIN__
#define SRSAPPS_IMPORT __declspec(dllimport)
#define SRSAPPS_EXPORT __declspec(dllexport)
#define SRSAPPS_LOCAL
#else
#if __GNUC__ >= 4
#define SRSAPPS_IMPORT __attribute__ ((visibility ("default")))
#define SRSAPPS_EXPORT __attribute__ ((visibility ("default")))
#else
#define SRSAPPS_IMPORT
#define SRSAPPS_EXPORT
#define SRSAPPS_LOCAL
#endif
#endif
// Define SRSAPPS_API
// is used for the public API symbols.
#ifdef SRSAPPS_DLL_EXPORTS // defined if we are building the SRSAPPS DLL (instead of using it)
#define SRSAPPS_EXPORT
#else
#define SRSAPPS_IMPORT
#endif
// Common error codes
#define SRSAPPS_SUCCESS 0
#define SRSAPPS_ERROR -1
#define SRSAPPS_ERROR_INVALID_INPUTS -2
// cf_t definition
typedef _Complex float cf_t;
#endif // CONFIG_H

@ -0,0 +1,99 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include <string>
/******************************************************************************
* File: log.h
*
* Description: Abstract logging service
*
* Reference:
*****************************************************************************/
#ifndef LOG_H
#define LOG_H
#define Error(fmt, ...) log_h->error(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) log_h->warning(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define Info(fmt, ...) log_h->info(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) log_h->debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
using namespace std;
namespace srslte {
class log
{
public:
log(string service_name_) { service_name = service_name_; tti = 0; level = LOG_LEVEL_NONE; }
// This function shall be called at the start of every tti for printing tti
void step(uint32_t tti_) {
tti = tti_;
}
typedef enum {
LOG_LEVEL_NONE = 0,
LOG_LEVEL_INFO,
LOG_LEVEL_DEBUG
} log_level_t;
void set_level_info() {
level = LOG_LEVEL_INFO;
}
void set_level_debug() {
level = LOG_LEVEL_DEBUG;
}
// Pure virtual methods for logging
virtual void error(string message, ...) = 0;
virtual void warning(string message, ...) = 0;
virtual void info(string message, ...) = 0;
virtual void debug(string message, ...) = 0;
// Same with line and file info
virtual void error(string file, int line, string message, ...) = 0;
virtual void warning(string file, int line, string message, ...) = 0;
virtual void info(string file, int line, string message, ...) = 0;
virtual void debug(string file, int line, string message, ...) = 0;
protected:
string get_service_name() { return service_name; }
uint32_t tti;
log_level_t level;
private:
string service_name;
};
}
#endif

@ -0,0 +1,78 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include <string>
#include <stdarg.h>
#include "srsapps/common/log.h"
/******************************************************************************
* File: log_stout.h
*
* Description: Logging service through standard output. Inherits log interface
*
* Reference:
*****************************************************************************/
#ifndef LOGSTDOUT_H
#define LOGSTDOUT_H
using namespace std;
namespace srslte {
class log_stdout : public log
{
public:
log_stdout(string service_name_) : log(service_name_) { }
void error(string message, ...);
void warning(string message, ...);
void info(string message, ...);
void debug(string message, ...);
// Same with line and file info
void error(string file, int line, string message, ...);
void warning(string file, int line, string message, ...);
void info(string file, int line, string message, ...);
void debug(string file, int line, string message, ...);
private:
typedef enum {
ERROR=0, WARNING, INFO, DEBUG, NOF_LEVELS
} level_t;
void printlog(level_t level, uint32_t tti, string file, int line, string message, va_list args);
void printlog(level_t level, uint32_t tti, string message, va_list args);
};
}
#endif

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,37 +10,43 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include <stdlib.h>
#ifndef PARAMS_H
#define PARAMS_H
namespace srslte {
namespace ue {
class SRSLTE_API params_db
class params_db
{
public:
params_db(uint32_t nof_params_) {
nof_params = nof_params_;
db = new int64_t[nof_params_];
db = new int64_t[nof_params];
for (int i=0;i<nof_params;i++) {
db[i] = 0;
}
}
~params_db() {
delete db;
delete db;
}
void set_param(uint32_t param_idx, int64_t value) {
if (param_idx < nof_params) {
@ -48,7 +54,7 @@ namespace ue {
}
}
int64_t get_param(uint32_t param_idx) {
if (param_idx < nof_params) {
if (param_idx < nof_params) {
return db[param_idx];
} else {
return -1;

@ -0,0 +1,93 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#ifndef QBUFF_H
#define QBUFF_H
/** Implementation of a lock-free single-producer single-consumer queue buffer
* Communication can be pointer-based or stream based.
* Only 1 thread can read and only 1 thread can write.
*
* Writer:
* - Call request, returns a pointer.
* - Writes to memory, up to max_msg_size bytes
* - Call to push() passing message size
* or
* - use send()
*
* Reader:
* - Call to pop, receive pointer and message size
* - Read memory contents
* - Call to release() to release the message buffer
* or
* - use recv()
*/
namespace srslte {
class qbuff
{
public:
qbuff();
~qbuff();
bool init(uint32_t nof_messages, uint32_t max_msg_size);
void* request();
bool push(uint32_t len);
void* pop(uint32_t *len, uint32_t idx);
void* pop(uint32_t *len);
void* pop();
void release();
bool isempty();
bool isfull();
void flush();
bool send(void *buffer, uint32_t msg_size);
int recv(void* buffer, uint32_t buffer_size);
void move_to(qbuff *dst);
uint32_t pending_data();
private:
typedef struct {
bool valid;
uint32_t len;
void *ptr;
} pkt_t;
uint32_t nof_messages;
uint32_t max_msg_size;
uint32_t rp, wp;
pkt_t *packets;
uint8_t *buffer;
};
}
#endif

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,21 +10,23 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
/******************************************************************************
* File: queue.h
@ -34,6 +36,8 @@
* Reference:
*****************************************************************************/
#ifndef QUEUE_H
#define QUEUE_H

@ -0,0 +1,130 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#ifndef TIMERS_H
#define TIMERS_H
namespace srslte {
class timer_callback
{
public:
virtual void timer_expired(uint32_t timer_id) = 0;
};
class timers
{
public:
class timer
{
public:
timer() { counter = 0; timeout = 0; running = false; };
void set(timer_callback *callback_, uint32_t timeout_) {
callback = callback_;
timeout = timeout_;
}
bool is_running() {
return counter < timeout;
}
bool is_expired() {
return counter == timeout;
}
void reset() {
counter = 0;
}
void step() {
if (running) {
counter++;
if (is_expired()) {
callback->timer_expired(id);
}
}
}
void stop() {
running = false;
}
void run() {
running = true;
}
uint32_t id;
private:
timer_callback *callback;
uint32_t timeout;
uint32_t counter;
bool running;
};
timers(uint32_t nof_timers_) {
nof_timers = nof_timers_;
timer_list = new timer[nof_timers];
for (uint32_t i=0;i<nof_timers;i++) {
timer_list[i].id = i;
}
}
~timers() {
delete timer_list;
}
void step_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->step();
}
}
void stop_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->stop();
}
}
void run_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->run();
}
}
void reset_all() {
for (int i=0;i<nof_timers;i++) {
get(i)->reset();
}
}
timer *get(uint32_t i) {
if (i < nof_timers) {
return &timer_list[i];
} else {
printf("Error accessing invalid timer %d (Only %d timers available)\n", i, nof_timers);
return NULL;
}
}
private:
uint32_t nof_timers;
timer *timer_list;
};
}
#endif

@ -1,8 +1,8 @@
/**
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,23 +10,26 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srslte/srslte.h"
#ifndef TTISYNC_H
#define TTISYNC_H
@ -39,7 +42,7 @@ namespace ue {
* The consumer waits while its counter is lower than the producer counter.
* The PHY is the consumer. The MAC is the producer.
*/
class SRSLTE_API tti_sync
class tti_sync
{
public:
tti_sync(uint32_t modulus_)
@ -48,6 +51,7 @@ class SRSLTE_API tti_sync
init_counters(0);
}
virtual void increase() = 0;
virtual void resync() = 0;
virtual uint32_t wait() = 0;
virtual void set_producer_cntr(uint32_t) = 0;
uint32_t get_producer_cntr() { return producer_cntr; }

@ -1,8 +1,8 @@
/**
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,24 +10,26 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include "srslte/ue_itf/tti_sync.h"
#include "srslte/srslte.h"
#include "srsapps/common/tti_sync.h"
#ifndef TTISYNC_CV_H
#define TTISYNC_CV_H
@ -39,13 +41,14 @@ namespace ue {
/* Implements tti_sync interface with condition variables.
*/
class SRSLTE_API tti_sync_cv : public tti_sync
class tti_sync_cv : public tti_sync
{
public:
tti_sync_cv(uint32_t modulus);
~tti_sync_cv();
void increase();
uint32_t wait();
void resync();
void set_producer_cntr(uint32_t producer_cntr);
private:

@ -0,0 +1,137 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include <string>
#include <stdarg.h>
#include <stdio.h>
#include "srsapps/common/log_stdout.h"
using namespace std;
namespace srslte {
const char* level_str[4] = {"[ERROR ",
"[WARN ",
"[INFO ",
"[DEBUG "};
void log_stdout::printlog(level_t type, uint32_t tti, string msg, va_list args) {
printlog(type, tti, string(), -1, msg, args);
}
void log_stdout::printlog(level_t type, uint32_t tti, string file, int line, string msg, va_list args) {
printf("%s %s",level_str[type], get_service_name().c_str());
if (file.length() > 0) {
printf("/%-14s", file.substr(file.find_last_of("/")+1,file.find_last_of(".")-1-file.find_last_of("/")).c_str());
}
if (line >= 0) {
printf(" %5d]: ", tti);
}
vprintf(msg.c_str(), args);
}
void log_stdout::error(string msg, ...)
{
va_list args;
va_start(args, msg);
printlog(ERROR, tti, msg, args);
va_end(args);
}
void log_stdout::info(string msg, ...)
{
if (level >= LOG_LEVEL_INFO) {
va_list args;
va_start(args, msg);
printlog(INFO, tti, msg, args);
va_end(args);
}
}
void log_stdout::debug(string msg, ...)
{
if (level >= LOG_LEVEL_DEBUG) {
va_list args;
va_start(args, msg);
printlog(DEBUG, tti, msg, args);
va_end(args);
}
}
void log_stdout::warning(string msg, ...)
{
va_list args;
va_start(args, msg);
printlog(WARNING, tti, msg, args);
va_end(args);
}
void log_stdout::error(string file, int line, string msg, ...)
{
va_list args;
va_start(args, msg);
printlog(ERROR, tti, file, line, msg, args);
va_end(args);
}
void log_stdout::info(string file, int line, string msg, ...)
{
if (level >= LOG_LEVEL_INFO) {
va_list args;
va_start(args, msg);
printlog(INFO, tti, file, line, msg, args);
va_end(args);
}
}
void log_stdout::debug(string file, int line, string msg, ...)
{
if (level >= LOG_LEVEL_DEBUG) {
va_list args;
va_start(args, msg);
printlog(DEBUG, tti, file, line, msg, args);
va_end(args);
}
}
void log_stdout::warning(string file, int line, string msg, ...)
{
va_list args;
va_start(args, msg);
printlog(WARNING, tti, file, line, msg, args);
va_end(args);
}
}

@ -0,0 +1,213 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "srsapps/common/qbuff.h"
namespace srslte {
qbuff::qbuff()
{
nof_messages=0;
max_msg_size=0;
wp = 0;
rp = 0;
buffer = NULL;
packets = NULL;
}
qbuff::~qbuff()
{
free(buffer);
free(packets);
}
bool qbuff::init(uint32_t nof_messages_, uint32_t max_msg_size_)
{
nof_messages = nof_messages_;
max_msg_size = max_msg_size_;
buffer = (uint8_t*) calloc(nof_messages,max_msg_size);
packets = (pkt_t*) calloc(nof_messages,sizeof(pkt_t));
if (buffer && packets) {
flush();
return true;
} else {
return false;
}
}
void qbuff::flush()
{
wp = 0;
rp = 0;
for (int i=0;i<nof_messages;i++) {
packets[i].valid = false;
packets[i].ptr = &buffer[i*max_msg_size];
packets[i].len = 0;
}
}
bool qbuff::isempty()
{
return !packets[rp].valid;
}
bool qbuff::isfull()
{
return packets[wp].valid;
}
void* qbuff::request()
{
if (!isfull()) {
return packets[wp].ptr;
} else {
return NULL;
}
}
bool qbuff::push(uint32_t len)
{
packets[wp].len = len;
packets[wp].valid = true;
wp += (wp+1 >= nof_messages)?(1-nof_messages):1;
}
void* qbuff::pop()
{
return pop(NULL);
}
void* qbuff::pop(uint32_t* len)
{
if (!isempty()) {
if (len) {
*len = packets[rp].len;
}
return packets[rp].ptr;
} else {
return NULL;
}
}
void* qbuff::pop(uint32_t* len, uint32_t idx)
{
if (idx == 0) {
return pop(len);
} else {
uint32_t rpp = rp;
uint32_t i = 0;
while(i<idx && packets[rpp].valid) {
rpp += (rpp+1 >= nof_messages)?(1-nof_messages):1;
i++;
}
if (packets[rpp].valid) {
if (len) {
*len = packets[rpp].len;
}
return packets[rpp].ptr;
} else {
return NULL;
}
}
}
void qbuff::release()
{
packets[rp].valid = false;
packets[rp].len = 0;
rp += (rp+1 >= nof_messages)?(1-nof_messages):1;
}
bool qbuff::send(void* buffer, uint32_t msg_size)
{
if (msg_size <= max_msg_size) {
void *ptr = request();
if (ptr) {
memcpy(ptr, buffer, msg_size);
push(msg_size);
} else {
return false;
}
} else {
return false;
}
}
uint32_t qbuff::pending_data()
{
uint32_t total_len = 0;
for (int i=0;i<nof_messages;i++) {
total_len += packets[i].len;
}
return total_len;
}
// Move packets between queues with only 1 memcpy
void qbuff::move_to(qbuff *dst) {
uint32_t len;
void *ptr_src = pop(&len);
if (ptr_src) {
void *ptr_dst = dst->request();
if (ptr_dst) {
memcpy(ptr_dst, ptr_src, len);
dst->push(len);
release();
}
}
}
int qbuff::recv(void* buffer, uint32_t buffer_size)
{
uint32_t len;
void *ptr = pop(&len);
if (ptr) {
if (len <= buffer_size) {
memcpy(buffer, ptr, len);
release();
return len;
} else {
return -1;
}
} else {
return 0;
}
}
}

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "srslte/ue_itf/queue.h"
#include "srsapps/common/queue.h"
namespace srslte {
namespace ue {

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -27,7 +27,7 @@
#include <pthread.h>
#include "srslte/ue_itf/tti_sync_cv.h"
#include "srsapps/common/tti_sync_cv.h"
namespace srslte {
namespace ue {
@ -56,6 +56,11 @@ namespace srslte {
return x;
}
void tti_sync_cv::resync()
{
consumer_cntr = producer_cntr;
}
void tti_sync_cv::set_producer_cntr(uint32_t producer_cntr)
{
pthread_mutex_lock(&mutex);

@ -0,0 +1,38 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
FIND_PACKAGE(UHD)
INSTALL(DIRECTORY include/
DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
IF(UHD_FOUND)
FILE(GLOB SOURCES "src/*.cc")
ADD_LIBRARY(srsapps_radio SHARED ${SOURCES})
INSTALL(TARGETS srsapps_radio DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srsapps_radio)
ENDIF(UHD_FOUND)
FILE(GLOB HEADERS_ALL "include/srsapps/radio/*.h")
ADD_CUSTOM_TARGET (add_srsapps_radio_headers SOURCES ${HEADERS_ALL})

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -47,6 +47,7 @@ namespace srslte {
virtual void set_tx_gain(float gain) = 0;
virtual void set_rx_gain(float gain) = 0;
virtual double set_rx_gain_th(float gain) = 0;
virtual void set_tx_freq(float freq) = 0;
virtual void set_rx_freq(float freq) = 0;

@ -1,8 +1,8 @@
/**
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,23 +10,25 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/radio/radio.h"
#include "srslte/srslte.h"
#include "srslte/common/radio.h"
#include "srslte/cuhd/cuhd.h"
#ifndef RADIO_UHD_H
@ -37,11 +39,13 @@ namespace srslte {
/* Interface to the RF frontend.
*/
class SRSLTE_API radio_uhd : public radio
class radio_uhd : public radio
{
public:
bool init();
bool init(char *args);
bool init_agc();
bool init_agc(char *args);
void get_time(srslte_timestamp_t *now);
bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
@ -50,6 +54,8 @@ namespace srslte {
void set_tx_gain(float gain);
void set_rx_gain(float gain);
void set_tx_rx_gain_offset(float offset);
double set_rx_gain_th(float gain);
void set_tx_freq(float freq);
void set_rx_freq(float freq);

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,24 +10,23 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srslte/common/radio.h"
#include "srslte/cuhd/radio_uhd.h"
#include "srsapps/radio/radio_uhd.h"
namespace srslte {
@ -47,6 +46,26 @@ bool radio_uhd::init(char *args)
return true;
}
bool radio_uhd::init_agc()
{
return init_agc((char*) "");
}
void radio_uhd::set_tx_rx_gain_offset(float offset) {
cuhd_set_tx_rx_gain_offset(uhd, offset);
}
bool radio_uhd::init_agc(char *args)
{
printf("Opening UHD device with threaded RX Gain control ...\n");
if (cuhd_open_th(args, &uhd, true)) {
fprintf(stderr, "Error opening uhd\n");
return false;
}
cuhd_set_rx_gain(uhd, 40);
cuhd_set_tx_gain(uhd, 40);
return true;
}
bool radio_uhd::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time)
{
fprintf(stderr, "Not implemented\n");
@ -85,6 +104,12 @@ void radio_uhd::set_rx_gain(float gain)
cur_rx_gain = cuhd_set_rx_gain(uhd, gain);
}
double radio_uhd::set_rx_gain_th(float gain)
{
cur_rx_gain = cuhd_set_rx_gain_th(uhd, gain);
return cur_rx_gain;
}
void radio_uhd::set_rx_srate(float srate)
{
cur_rx_srate = cuhd_set_rx_srate(uhd, srate);

@ -0,0 +1,27 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
INCLUDE_DIRECTORIES(phy/include/)
INCLUDE_DIRECTORIES(mac/include/)
add_subdirectory(phy)
add_subdirectory(mac)

@ -0,0 +1,36 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
INSTALL(DIRECTORY include/
DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
FILE(GLOB SOURCES "src/*.cc")
ADD_LIBRARY(srsapps_ue_mac SHARED ${SOURCES})
INSTALL(TARGETS srsapps_ue_mac DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srsapps_ue_mac)
FILE(GLOB HEADERS_ALL "include/srsapps/ue/mac/*.h")
ADD_CUSTOM_TARGET (add_ue_mac_headers SOURCES ${HEADERS_ALL})
ADD_SUBDIRECTORY(test)

@ -0,0 +1,87 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/common/timers.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/pdu.h"
#include "srsapps/ue/mac/sdu_handler.h"
#ifndef DEMUX_H
#define DEMUX_H
/* Logical Channel Demultiplexing and MAC CE dissassemble */
namespace srslte {
namespace ue {
class demux
{
public:
demux();
void init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_);
void add_sdu_handler(sdu_handler *handler);
void push_pdu(uint8_t *mac_pdu, uint32_t nof_bits);
void push_pdu_bcch(uint8_t *mac_pdu, uint32_t nof_bits);
void push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits);
bool is_temp_crnti_pending();
bool is_contention_resolution_id_pending();
void demultiplex_pending_pdu();
void discard_pending_pdu();
uint64_t get_contention_resolution_id();
private:
sch_pdu mac_msg;
sch_pdu pending_mac_msg;
void process_pdu(sch_pdu *pdu);
bool process_ce(sch_subh *subheader);
uint64_t contention_resolution_id;
bool pending_temp_rnti;
bool has_pending_contention_resolution_id;
phy *phy_h;
log *log_h;
mac_io *mac_io_h;
timers *timers_db;
sdu_handler *sdu_handler_;
};
}
}
#endif

@ -0,0 +1,101 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/common/timers.h"
#include "srsapps/ue/mac/demux.h"
#ifndef DLHARQ_H
#define DLHARQ_H
/* Downlink HARQ entity as defined in 5.3.2 of 36.321 */
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class dl_harq_entity
{
public:
const static uint32_t NOF_HARQ_PROC = 8;
const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC;
dl_harq_entity();
bool init(srslte_cell_t cell, uint32_t max_payload_len, srslte::log *log_h_, timers *timers_, demux *demux_unit);
bool is_sps(uint32_t pid);
void set_harq_info(uint32_t pid, dl_sched_grant *grant);
void receive_data(uint32_t tti, uint32_t pid, dl_buffer *dl_buffer, phy *phy_h);
void reset();
bool is_ack_pending_resolution();
void send_pending_ack_contention_resolution();
private:
class dl_harq_process {
public:
dl_harq_process();
bool init(srslte_cell_t cell, uint32_t max_payload_len, dl_harq_entity *parent);
void set_harq_info(dl_sched_grant *grant);
void receive_data(uint32_t tti, dl_buffer *dl_buffer, phy *phy_h);
void reset();
// Called after the contention resolution is terminated to send pending ACKs, if any
void send_pending_ack_contention_resolution();
uint32_t pid;
private:
bool is_initiated;
dl_harq_entity *harq_entity;
uint8_t *payload;
uint32_t max_payload_len;
dl_sched_grant cur_grant;
dl_sched_grant pending_ack_grant;
ul_buffer *pending_ul_buffer;
bool is_first_tx;
bool is_first_decoded;
bool pending_ack;
srslte::log *log_h;
srslte_softbuffer_rx_t softbuffer;
};
dl_harq_process proc[NOF_HARQ_PROC+1];
timers *timers_db;
demux *demux_unit;
srslte::log *log_h;
int pending_ack_pid;
};
}
}
#endif

@ -0,0 +1,59 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/common/timers.h"
#ifndef DLSPS_H
#define DLSPS_H
/* Downlink Semi-Persistent schedulign (Section 5.10.1) */
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class dl_sps
{
public:
void clear();
void reset(uint32_t tti, dl_sched_grant *grant);
dl_sched_grant *get_pending_grant(uint32_t tti);
private:
};
}
}
#endif

@ -0,0 +1,150 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/common/log.h"
#include "srsapps/common/tti_sync.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/dl_harq.h"
#include "srsapps/ue/mac/ul_harq.h"
#include "srsapps/ue/mac/dl_sps.h"
#include "srsapps/ue/mac/ul_sps.h"
#include "srsapps/common/timers.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/ue/mac/proc_ra.h"
#include "srsapps/ue/mac/proc_sr.h"
#include "srsapps/ue/mac/proc_bsr.h"
#include "srsapps/ue/mac/proc_phr.h"
#include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/demux.h"
#include "srsapps/ue/mac/sdu_handler.h"
#ifndef UEMAC_H
#define UEMAC_H
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class mac : public timer_callback
{
public:
mac() : timers_db((uint32_t) NOF_MAC_TIMERS) {}
bool init(phy *phy_h, tti_sync *ttisync, log *log_h);
void stop();
int get_tti();
void main_radio_loop(); // called after thread creation
void add_sdu_handler(sdu_handler *handler);
bool send_sdu(uint32_t lcid, uint8_t *sdu_payload, uint32_t nbytes);
bool send_ccch_sdu(uint8_t *sdu_payload, uint32_t nbytes);
bool send_dtch0_sdu(uint8_t *sdu_payload, uint32_t nbytes); // SRB0
bool send_dcch0_sdu(uint8_t *sdu_payload, uint32_t nbytes); // DRB0
int recv_sdu(uint32_t lcid, uint8_t *sdu_payload, uint32_t nbytes);
int recv_bcch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes);
int recv_ccch_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes);
int recv_dtch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // SRB0
int recv_dcch0_sdu(uint8_t *sdu_payload, uint32_t buffer_len_nbytes); // DRB0
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void set_param(mac_params::mac_param_t param, int64_t value);
void reconfiguration();
void reset();
void timer_expired(uint32_t timer_id);
enum {
HARQ_RTT = 0,
TIME_ALIGNMENT,
CONTENTION_TIMER,
BSR_TIMER_PERIODIC,
BSR_TIMER_RETX,
NOF_MAC_TIMERS
} mac_timers_t;
private:
// Interaction with PHY
tti_sync *ttisync;
phy *phy_h;
log *log_h;
/* Logical channel (lch) IO */
mac_io mac_io_lch;
mac_params params_db;
pthread_t mac_thread;
static void* mac_thread_fnc(void*);
int tti;
bool started = false;
bool is_synchronized;
bool is_first_temporal;
/* Multiplexing/Demultiplexing Units */
mux mux_unit;
demux demux_unit;
/* DL/UL HARQ */
dl_harq_entity dl_harq;
ul_harq_entity ul_harq;
/* DL/UL Semi-Persistent Sched */
dl_sps dl_sps_assig;
ul_sps ul_sps_assig;
uint32_t get_harq_sps_pid(uint32_t tti);
/* MAC Uplink-related Procedures */
ra_proc ra_procedure;
sr_proc sr_procedure;
bsr_proc bsr_procedure;
phr_proc phr_procedure;
/* Other procedures */
void process_dl_grants(uint32_t tti);
bool process_ul_grants(uint32_t tti);
void receive_pch(uint32_t tti);
/* Functions for MAC Timers */
timers timers_db;
void setup_timers();
void timeAlignmentTimerExpire();
};
}
}
#endif

@ -0,0 +1,112 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <string.h>
#include "srsapps/common/qbuff.h"
#ifndef MACIO_H
#define MACIO_H
/* Manages all MAC buffers including:
* - communication with higher layers through logical channels
* - communication between logical channels buffers and Dissassembly/Assembly unit
* - communication between Dissassembly/Assembly unit and Msg3 buffer
*
* For logical channels, IN means higher layers to MAC. OUT means MAC to higher layers.
*
* See queue.h for instructions on how to manage buffers
*/
namespace srslte {
namespace ue {
class mac_io
{
public:
// list of logical channels
// Keep this order to match LoCH id with RB
typedef enum {
// Downlink (UE MAC -> UE RRC)
MAC_LCH_CCCH_DL = 0, // SRB0
MAC_LCH_DCCH0_DL, // SRB1
MAC_LCH_DCCH1_DL, // SRB2
MAC_LCH_DTCH0_DL, // DRB0
MAC_LCH_DTCH1_DL, // DRB1
MAC_LCH_DTCH2_DL, // DRB2
MAC_LCH_BCCH_DL, // N/A
MAC_LCH_PCCH_DL, // N/A
// Uplink (UE RLC -> UE MAC)
MAC_LCH_CCCH_UL, // SRB0
MAC_LCH_DCCH0_UL, // SRB1
MAC_LCH_DCCH1_UL, // SRB2
MAC_LCH_DTCH0_UL, // DRB0
MAC_LCH_DTCH1_UL, // DRB1
MAC_LCH_DTCH2_UL, // DRB2
MAC_NOF_QUEUES
} mac_lch_t;
const static int NOF_DL_LCH = MAC_LCH_PCCH_DL - MAC_LCH_CCCH_DL;
const static int NOF_UL_LCH = MAC_LCH_DTCH2_UL - MAC_LCH_CCCH_UL;
const static int DEFAULT_MSG_SZ = 8*1024; // 8 Kbytes
const static int DEFAULT_NOF_MESSAGES = 8;
qbuff* get(mac_lch_t ch) {
return get((uint32_t) ch);
}
qbuff* get(int32_t lchid) {
if (lchid < MAC_NOF_QUEUES) {
return &queues[lchid];
} else {
return NULL;
}
}
// Move packets between queues with only 1 memcpy
void move(mac_lch_t src, mac_lch_t dst) {
get(src)->move_to(get(dst));
}
mac_io() {
for (int i=0;i<MAC_NOF_QUEUES;i++) {
queues[i].init(DEFAULT_NOF_MESSAGES, DEFAULT_MSG_SZ);
}
}
private:
qbuff queues[MAC_NOF_QUEUES];
};
}
}
#endif

@ -0,0 +1,103 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srsapps/common/params_db.h"
#ifndef MACPARAMS_H
#define MACPARAMS_H
namespace srslte {
namespace ue {
class mac_params : public params_db
{
public:
mac_params() : params_db(NOF_PARAMS) {}
~mac_params() {}
typedef enum {
// These 4 parameters must be together!!
RNTI_C = 0,
RNTI_SPS,
RNTI_TEMP,
RNTI_RA,
SPS_DL_SCHED_INTERVAL,
SPS_DL_NOF_PROC,
BCCH_SI_WINDOW_ST,
BCCH_SI_WINDOW_LEN,
PCCH_RECEIVE,
CONTENTION_ID, // Transmitted UE Contention ID
TIMER_TIMEALIGN,
// Random Access parameters. See 5.1.1
RA_CONFIGINDEX,
RA_PREAMBLEINDEX,
RA_MASKINDEX,
RA_NOFPREAMBLES,
RA_NOFGROUPAPREAMBLES,
RA_MESSAGEPOWEROFFSETB,
RA_MESSAGESIZEA,
RA_PCMAX,
RA_DELTAPREAMBLEMSG3,
RA_RESPONSEWINDOW,
RA_POWERRAMPINGSTEP,
RA_PREAMBLETRANSMAX,
RA_INITRECEIVEDPOWER,
RA_CONTENTIONTIMER,
SR_PUCCH_CONFIGURED,
SR_TRANS_MAX,
BSR_TIMER_PERIODIC,
BSR_TIMER_RETX,
HARQ_MAXTX,
HARQ_MAXMSG3TX,
PDSCH_RSPOWER,
PDSCH_PB,
NOF_PARAMS,
} mac_param_t;
};
}
}
#endif

@ -0,0 +1,105 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <pthread.h>
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/pdu.h"
#include "srsapps/ue/mac/proc_bsr.h"
#ifndef MUX_H
#define MUX_H
/* Logical Channel Multiplexing and Prioritization + Msg3 Buffer */
namespace srslte {
namespace ue {
class mux
{
public:
mux();
void reset();
void init(log *log_h, mac_io *mac_io_h, bsr_proc *bsr_procedure);
bool is_pending_ccch_sdu();
bool is_pending_any_sdu();
bool is_pending_sdu(uint32_t lcid);
uint8_t* pdu_pop(uint32_t pdu_sz);
bool pdu_move_to_msg3(uint32_t pdu_sz);
void pdu_release();
uint8_t* msg3_pop(uint32_t pdu_sz);
void msg3_flush();
void msg3_transmitted();
bool msg3_is_transmitted();
void append_crnti_ce_next_tx(uint16_t crnti);
void set_priority(uint32_t lcid, uint32_t priority, int PBR_x_tti, uint32_t BSD);
private:
bool assemble_pdu(uint32_t pdu_sz);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu);
bool allocate_sdu(uint32_t lcid, sch_pdu *pdu, uint32_t *sdu_sz);
int64_t Bj[mac_io::NOF_UL_LCH];
int PBR[mac_io::NOF_UL_LCH]; // -1 sets to infinity
uint32_t BSD[mac_io::NOF_UL_LCH];
uint32_t priority[mac_io::NOF_UL_LCH];
uint32_t priority_sorted[mac_io::NOF_UL_LCH];
uint32_t lchid_sorted[mac_io::NOF_UL_LCH];
uint32_t nof_tx_pkts[mac_io::NOF_UL_LCH];
// Mutex for priority setting from outside MAC
pthread_mutex_t mutex;
log *log_h;
mac_io *mac_io_h;
bsr_proc *bsr_procedure;
uint16_t pending_crnti_ce;
/* Msg3 Buffer */
static const uint32_t MSG3_BUFF_SZ = 128;
qbuff msg3_buff;
/* PDU Buffer */
static const uint32_t PDU_BUFF_SZ = 16*1024;
qbuff pdu_buff;
sch_pdu pdu_msg;
bool msg3_has_been_transmitted;
};
}
}
#endif

@ -0,0 +1,293 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/common/log.h"
#include <vector>
#include <stdio.h>
#ifndef MACPDU_H
#define MACPDU_H
/* MAC PDU Packing/Unpacking functions. Section 6 of 36.321 */
namespace srslte {
namespace ue {
template<class SubH>
class pdu
{
public:
pdu(uint32_t max_subheaders_) : subheaders(max_subheaders_) {
max_subheaders = max_subheaders_;
nof_subheaders = 0;
cur_idx = -1;
pdu_len = 0;
rem_len = 0;
for (int i=0;i<max_subheaders;i++) {
subheaders[i].parent = this;
}
}
void fprint(FILE *stream) {
fprintf(stream, "Number of Subheaders: %d\n", nof_subheaders);
for (int i=0;i<nof_subheaders;i++) {
fprintf(stream, " -- Subheader %d: ", i);
subheaders[i].fprint(stream);
}
}
/* Resets the Read/Write position and remaining PDU length */
void reset() {
cur_idx = -1;
rem_len = pdu_len;
}
/* Prepares the PDU for parsing or writing by setting the number of subheaders to 0 and the pdu length */
void init(uint32_t pdu_len_bytes) {
init(pdu_len_bytes, false);
}
void init(uint32_t pdu_len_bytes, bool is_ulsch) {
nof_subheaders = 0;
pdu_len = pdu_len_bytes;
rem_len = pdu_len;
pdu_is_ul = is_ulsch;
reset();
for (int i=0;i<max_subheaders;i++) {
subheaders[i].init();
}
}
bool new_subh() {
if (nof_subheaders < max_subheaders - 1) {
nof_subheaders++;
return true;
} else {
return false;
}
}
bool next() {
if (cur_idx < nof_subheaders - 1) {
cur_idx++;
return true;
} else {
return false;
}
}
SubH* get() {
if (cur_idx >= 0) {
return &subheaders[cur_idx];
}
}
// Section 6.1.2
void parse_packet(uint8_t *ptr) {
uint8_t *init_ptr = ptr;
nof_subheaders = 0;
while(subheaders[nof_subheaders].read_subheader(&ptr)) {
nof_subheaders++;
}
nof_subheaders++;
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].read_payload(&ptr);
}
}
bool is_ul() {
return pdu_is_ul;
}
virtual bool write_packet(uint8_t *ptr) = 0;
protected:
std::vector<SubH> subheaders;
uint32_t pdu_len;
uint32_t rem_len;
int cur_idx;
int nof_subheaders;
uint32_t max_subheaders;
bool pdu_is_ul;
};
template<class SubH>
class subh
{
public:
virtual bool read_subheader(uint8_t** ptr) = 0;
virtual void read_payload(uint8_t **ptr) = 0;
virtual void write_subheader(uint8_t** ptr, bool is_last) = 0;
virtual void write_payload(uint8_t **ptr) = 0;
virtual void fprint(FILE *stream) = 0;
pdu<SubH>* parent;
private:
virtual void init() = 0;
};
class sch_subh : public subh<sch_subh>
{
public:
typedef enum {
PHD_REPORT = 26,
C_RNTI = 27,
CON_RES_ID = 28,
TRUNC_BSR = 28,
TA_CMD = 29,
SHORT_BSR = 29,
DRX_CMD = 30,
LONG_BSR = 30,
PADDING = 31,
SDU = 0
} cetype;
// Reading functions
bool is_sdu();
cetype ce_type();
uint32_t size_plus_header();
void set_payload_size(uint32_t size);
bool read_subheader(uint8_t** ptr);
void read_payload(uint8_t **ptr);
uint32_t get_sdu_lcid();
uint32_t get_sdu_nbytes();
uint8_t* get_sdu_ptr();
uint16_t get_c_rnti();
uint64_t get_con_res_id();
uint8_t get_ta_cmd();
uint8_t get_phd();
// Writing functions
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t **ptr);
bool set_sdu(uint32_t lcid, uint8_t *ptr, uint32_t nof_bytes);
bool set_c_rnti(uint16_t crnti);
bool set_bsr(uint32_t buff_size[4], sch_subh::cetype format);
bool set_con_res_id(uint64_t con_res_id);
bool set_ta_cmd(uint8_t ta_cmd);
bool set_phd(uint8_t phd);
void set_padding();
void init();
void fprint(FILE *stream);
private:
static const int MAX_CE_PAYLOAD_LEN = 8;
uint32_t lcid;
uint32_t nof_bytes;
uint8_t* sdu_payload_ptr;
bool F_bit;
uint8_t ce_payload[MAX_CE_PAYLOAD_LEN*8];
uint32_t sizeof_ce(uint32_t lcid, bool is_ul);
uint8_t buff_size_table(uint32_t buffer_size);
};
class sch_pdu : public pdu<sch_subh>
{
public:
sch_pdu(uint32_t max_rars) : pdu(max_rars) {}
void parse_packet(uint8_t *ptr);
bool write_packet(uint8_t *ptr);
bool has_space_ce(uint32_t nbytes);
bool has_space_sdu(uint32_t nbytes);
uint32_t size();
uint32_t rem_size();
static uint32_t size_plus_header_sdu(uint32_t nbytes);
bool update_space_ce(uint32_t nbytes);
bool update_space_sdu(uint32_t nbytes);
void fprint(FILE *stream);
};
class rar_subh : public subh<rar_subh>
{
public:
static const uint32_t RAR_GRANT_LEN = 20;
// Reading functions
bool read_subheader(uint8_t** ptr);
void read_payload(uint8_t** ptr);
uint32_t get_rapid();
uint32_t get_ta_cmd();
uint16_t get_temp_crnti();
void get_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
// Writing functoins
void write_subheader(uint8_t** ptr, bool is_last);
void write_payload(uint8_t** ptr);
void set_rapid(uint32_t rapid);
void set_ta_cmd(uint32_t ta);
void set_temp_crnti(uint16_t temp_rnti);
void set_sched_grant(uint8_t grant[RAR_GRANT_LEN]);
void init();
void fprint(FILE *stream);
private:
uint8_t grant[RAR_GRANT_LEN];
uint32_t ta;
uint16_t temp_rnti;
uint32_t preamble;
};
class rar_pdu : public pdu<rar_subh>
{
public:
rar_pdu(uint32_t max_rars);
void set_backoff(uint8_t bi);
bool has_backoff();
uint8_t get_backoff();
bool write_packet(uint8_t* ptr);
void fprint(FILE *stream);
private:
bool has_backoff_indicator;
uint8_t backoff_indicator;
};
}
}
#endif

@ -0,0 +1,62 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#ifndef PROC_H
#define PROC_H
/* Interface for a MAC procedure */
namespace srslte {
namespace ue {
class proc
{
public:
proc() {
running = false;
}
void run() {
running = true;
}
void stop() {
running = false;
}
bool is_running() {
return running;
}
virtual void step(uint32_t tti) = 0;
private:
bool running;
};
}
}
#endif

@ -0,0 +1,97 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/proc.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/common/timers.h"
#ifndef PROCBSR_H
#define PROCBSR_H
/* Buffer status report procedure */
namespace srslte {
namespace ue {
class bsr_proc : public proc, timer_callback
{
public:
bsr_proc();
void init(log *log_h, timers *timers_db, mac_params *params_db, mac_io *mac_io_h);
void step(uint32_t tti);
void reset();
void setup_lcg(uint32_t lcid, uint32_t new_lcg);
void set_priority(uint32_t lcid, uint32_t priority);
void timer_expired(uint32_t timer_id);
typedef enum {
LONG_BSR,
SHORT_BSR,
TRUNC_BSR
} bsr_format_t;
typedef struct {
bsr_format_t format;
uint32_t buff_size[4];
} bsr_t;
bool need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t nof_padding_bytes, bsr_t *bsr);
bool need_to_send_sr();
private:
bool is_pending_sr;
mac_params *params_db;
mac_io *mac_io_h;
timers *timers_db;
log *log_h;
bool initiated;
const static int MAX_LCID = 20;
uint32_t lcg[MAX_LCID];
uint32_t priorities[MAX_LCID];
uint32_t find_max_priority_lcid();
enum {NONE, REGULAR, PADDING, PERIODIC} triggered_bsr_type;
bool timer_periodic;
bool timer_retx;
bsr_t pending_bsr;
bool sr_is_sent;
bool check_all_channels();
bool check_highest_channel();
void get_pending_bsr_format(uint32_t nof_padding_bytes);
};
}
}
#endif

@ -0,0 +1,57 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/ue/mac/proc.h"
#ifndef PROCPHR_H
#define PROCPHR_H
/* Power headroom report procedure */
namespace srslte {
namespace ue {
class phr_proc : public proc
{
public:
void step(uint32_t tti) {
if (is_running()) {
fprintf(stderr, "PHR procedure not implemented\n");
}
}
void reset() {
}
};
}
}
#endif

@ -0,0 +1,165 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/common/qbuff.h"
#include "srsapps/ue/mac/proc.h"
#include "srsapps/common/timers.h"
#include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/demux.h"
#include "srsapps/ue/mac/pdu.h"
#ifndef PROCRA_H
#define PROCRA_H
/* Random access procedure as specified in Section 5.1 of 36.321 */
namespace srslte {
namespace ue {
class ra_proc : public proc,timer_callback
{
public:
ra_proc() : rar_pdu_msg(20) {};
bool init(mac_params *params_db, phy *phy_h, log *log_h, timers *timers_db,
mux *mux_unit, demux *demux_unit);
void reset();
void start_pdcch_order();
void start_rlc_order();
void start_mac_order();
void step(uint32_t tti);
bool is_successful();
bool is_response_error();
bool is_contention_resolution();
bool is_error();
bool in_progress();
void pdcch_to_crnti(bool is_ul_grant);
void timer_expired(uint32_t timer_id);
private:
void process_timeadv_cmd(uint32_t ta_cmd);
void step_initialization();
void step_initialization_wait();
void step_resource_selection();
void step_preamble_transmission();
void step_response_reception();
void step_response_error();
void step_backoff_wait();
void step_contention_resolution();
void step_completition();
// Buffer to receive RAR PDU
static const uint32_t MAX_RAR_PDU_LEN = 2048;
uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN];
rar_pdu rar_pdu_msg;
// Random Access parameters provided by higher layers defined in 5.1.1
// They are read from params_db during initialization init()
uint32_t configIndex;
uint32_t nof_preambles;
uint32_t nof_groupA_preambles;
uint32_t nof_groupB_preambles;
uint32_t messagePowerOffsetGroupB;
uint32_t messageSizeGroupA;
uint32_t Pcmax;
uint32_t deltaPreambleMsg3;
uint32_t responseWindowSize;
uint32_t powerRampingStep;
uint32_t preambleTransMax;
uint32_t iniReceivedTargetPower;
int delta_preamble_db;
uint32_t contentionResolutionTimer;
uint32_t maskIndex;
int preambleIndex;
// Internal variables
uint32_t tti;
uint32_t preambleTransmissionCounter;
uint32_t backoff_param_ms;
uint32_t sel_maskIndex;
uint32_t sel_preamble;
uint32_t backoff_interval_start;
uint32_t backoff_inteval;
int received_target_power_dbm;
uint32_t ra_rnti;
uint8_t payload[256]; // 56 bits is often enough
enum {
IDLE = 0,
INITIALIZATION, // Section 5.1.1
INITIALIZATION_WAIT,
RESOURCE_SELECTION, // Section 5.1.2
PREAMBLE_TRANSMISSION, // Section 5.1.3
RESPONSE_RECEPTION, // Section 5.1.4
RESPONSE_ERROR,
BACKOFF_WAIT,
CONTENTION_RESOLUTION, // Section 5.1.5
COMPLETION, // Section 5.1.6
RA_PROBLEM // Section 5.1.5 last part
} state;
typedef enum {RA_GROUP_A, RA_GROUP_B} ra_group_t;
ra_group_t last_msg3_group;
bool msg3_transmitted;
bool first_rar_received;
void read_params();
phy *phy_h;
log *log_h;
mac_params *params_db;
timers *timers_db;
mux *mux_unit;
demux *demux_unit;
pthread_t pt_init_prach;
uint64_t transmitted_contention_id;
uint16_t transmitted_crnti;
enum {
PDCCH_CRNTI_NOT_RECEIVED = 0,
PDCCH_CRNTI_UL_GRANT,
PDCCH_CRNTI_DL_GRANT
} pdcch_to_crnti_received;
enum {
PDCCH_ORDER = 0,
RLC_ORDER,
MAC_ORDER
} start_mode;
};
}
}
#endif

@ -0,0 +1,65 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdint.h>
#include "srsapps/ue/mac/proc.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/mac/mac_params.h"
#ifndef PROCSR_H
#define PROCSR_H
/* Scheduling Request procedure as defined in 5.4.4 of 36.321 */
namespace srslte {
namespace ue {
class sr_proc : public proc
{
public:
sr_proc();
void init(log *log_h, mac_params *params_db, phy *phy_h);
void step(uint32_t tti);
void reset();
void start();
bool need_random_access();
private:
uint32_t sr_counter;
uint32_t dsr_transmax;
bool is_pending_sr;
mac_params *params_db;
phy *phy_h;
log *log_h;
bool initiated;
};
}
}
#endif

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,21 +10,30 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/config.h"
#ifndef SDUHANDLER_H
#define SDUHANDLER_H
class sdu_handler
{
public:
virtual void notify_new_sdu(uint32_t lcid) = 0;
};
#endif
SRSLTE_API int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp);

@ -0,0 +1,108 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mux.h"
#include "srsapps/common/timers.h"
#ifndef ULHARQ_H
#define ULHARQ_H
/* Uplink HARQ entity as defined in 5.4.2 of 36.321 */
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class ul_harq_entity
{
public:
const static uint32_t NOF_HARQ_PROC = 8;
static uint32_t pidof(uint32_t tti);
bool init(srslte_cell_t cell, mac_params *params_db, log *log_h, timers* timers_, mux *mux_unit);
void reset();
void reset_ndi();
bool is_sps(uint32_t pid);
void run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_);
void run_tti(uint32_t tti, phy *phy_);
private:
class ul_harq_process {
public:
ul_harq_process();
bool init(srslte_cell_t cell, ul_harq_entity *parent);
void reset();
void reset_ndi();
void generate_retx(uint32_t tti_tx, ul_buffer *ul);
void generate_retx(uint32_t tti_tx, ul_sched_grant *ul_grant, ul_buffer *ul);
void generate_new_tx(uint32_t tti_tx, uint8_t *payload, bool is_msg3, ul_sched_grant* grant, ul_buffer *ul);
uint32_t get_rv();
bool has_grant();
ul_sched_grant *get_grant();
void set_harq_feedback(bool ack);
bool get_ndi();
uint32_t last_tx_tti();
private:
uint32_t current_tx_nb;
uint32_t current_irv;
bool harq_feedback;
bool ndi;
log *log_h;
ul_harq_entity *harq_entity;
ul_sched_grant cur_grant;
bool is_grant_configured;
srslte_softbuffer_tx_t softbuffer;
bool is_msg3;
bool is_initiated;
uint32_t tti_last_tx;
void generate_tx(uint32_t tti_tx, uint8_t *pdu_payload, ul_buffer* ul);
};
timers *timers_db;
mux *mux_unit;
ul_harq_process proc[NOF_HARQ_PROC];
log *log_h;
mac_params *params_db;
};
}
}
#endif

@ -0,0 +1,59 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/common/timers.h"
#ifndef ULSPS_H
#define ULSPS_H
/* Uplink Semi-Persistent schedulign (Section 5.10.2) */
namespace srslte {
namespace ue {
typedef _Complex float cf_t;
class ul_sps
{
public:
void clear() {}
void reset(uint32_t tti, sched_grant *grant) {}
ul_sched_grant *get_pending_grant(uint32_t tti) { return NULL; }
private:
};
}
}
#endif

@ -0,0 +1,203 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/demux.h"
namespace srslte {
namespace ue {
demux::demux() : mac_msg(20),pending_mac_msg(20)
{
contention_resolution_id = 0;
pending_temp_rnti = false;
has_pending_contention_resolution_id = false;
sdu_handler_ = NULL;
}
void demux::init(phy* phy_h_, log* log_h_, mac_io* mac_io_h_, timers* timers_db_)
{
phy_h = phy_h_;
log_h = log_h_;
mac_io_h = mac_io_h_;
timers_db = timers_db_;
}
void demux::add_sdu_handler(sdu_handler* handler)
{
sdu_handler_ = handler;
}
bool demux::is_temp_crnti_pending()
{
return pending_temp_rnti;
}
bool demux::is_contention_resolution_id_pending() {
return has_pending_contention_resolution_id;
}
uint64_t demux::get_contention_resolution_id()
{
uint64_t x = contention_resolution_id;
contention_resolution_id = 0;
has_pending_contention_resolution_id = false;
return x;
}
/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through
* the MAC in transparent mode
*/
void demux::push_pdu_bcch(uint8_t *mac_pdu, uint32_t nof_bits)
{
mac_io_h->get(mac_io::MAC_LCH_BCCH_DL)->send(mac_pdu, nof_bits);
Debug("Pushed BCCH MAC PDU in transparent mode\n");
}
/* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will
* remain in buffer until demultiplex_pending_pdu() is called.
* This features is provided to enable the Random Access Procedure to decide
* wether the PDU shall pass to upper layers or not, which depends on the
* Contention Resolution result
*/
void demux::push_pdu_temp_crnti(uint8_t *mac_pdu, uint32_t nof_bits)
{
if (!pending_temp_rnti) {
// Unpack DLSCH MAC PDU
pending_mac_msg.init(nof_bits/8);
pending_mac_msg.parse_packet(mac_pdu);
// Look for Contention Resolution UE ID
while(pending_mac_msg.next()) {
if (pending_mac_msg.get()->ce_type() == sch_subh::CON_RES_ID) {
contention_resolution_id = pending_mac_msg.get()->get_con_res_id();
has_pending_contention_resolution_id = true;
Info("Found Contention Resolution ID CE\n");
}
}
pending_mac_msg.reset();
pending_temp_rnti = true;
Info("Saved MAC PDU with Temporal C-RNTI in buffer\n");
} else {
Warning("Error pushing PDU with Temporal C-RNTI: Another PDU is still in pending\n");
}
}
/* Demultiplexing of logical channels and dissassemble of MAC CE */
void demux::push_pdu(uint8_t *mac_pdu, uint32_t nof_bits)
{
// Unpack DLSCH MAC PDU
mac_msg.init(nof_bits/8);
mac_msg.parse_packet(mac_pdu);
process_pdu(&mac_msg);
Debug("Normal MAC PDU processed\n");
}
void demux::discard_pending_pdu()
{
pending_temp_rnti = false;
pending_mac_msg.reset();
}
void demux::demultiplex_pending_pdu()
{
if (pending_temp_rnti) {
process_pdu(&pending_mac_msg);
discard_pending_pdu();
Info("Temporal C-RNTI MAC PDU processed\n");
} else {
Error("Error demultiplex pending PDU: No pending PDU\n");
}
}
void demux::process_pdu(sch_pdu *pdu_msg)
{
Info("Processing PDU\n");
while(pdu_msg->next()) {
if (pdu_msg->get()->is_sdu()) {
// Route logical channel
if (pdu_msg->get()->get_sdu_lcid() <= mac_io::MAC_LCH_DTCH2_DL) {
qbuff *dest_lch = mac_io_h->get(pdu_msg->get()->get_sdu_lcid());
if (dest_lch) {
dest_lch->send(pdu_msg->get()->get_sdu_ptr(), pdu_msg->get()->get_sdu_nbytes()*8);
Info("Sent MAC SDU len=%d bytes to lchid=%d\n",
pdu_msg->get()->get_sdu_nbytes(), pdu_msg->get()->get_sdu_lcid());
} else {
Error("Getting destination channel LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
}
} else {
Warning("Received SDU for unsupported LCID=%d\n", pdu_msg->get()->get_sdu_lcid());
}
// Process MAC Control Element
} else {
if (!process_ce(pdu_msg->get())) {
Warning("Received Subheader with invalid or unkonwn LCID\n");
}
}
}
/* notify handler if registred */
if (sdu_handler_) {
pdu_msg->reset();
while(pdu_msg->next()) {
if (pdu_msg->get()->is_sdu()) {
sdu_handler_->notify_new_sdu(pdu_msg->get()->get_sdu_lcid());
}
}
}
}
bool demux::process_ce(sch_subh *subh) {
switch(subh->ce_type()) {
case sch_subh::CON_RES_ID:
contention_resolution_id = subh->get_c_rnti();
Debug("Saved Contention Resolution ID=%d\n", contention_resolution_id);
break;
case sch_subh::TA_CMD:
phy_h->set_timeadv(subh->get_ta_cmd());
// Start or restart timeAlignmentTimer
timers_db->get(mac::TIME_ALIGNMENT)->reset();
timers_db->get(mac::TIME_ALIGNMENT)->run();
Debug("Set TimeAdvance Command %d\n", subh->get_ta_cmd());
break;
case sch_subh::PADDING:
break;
default:
Error("MAC CE 0x%x not supported\n", subh->ce_type());
break;
}
return true;
}
}
}

@ -0,0 +1,223 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/dl_sched_grant.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/dl_harq.h"
namespace srslte {
namespace ue {
/***********************************************************
*
* HARQ ENTITY
*
*********************************************************/
dl_harq_entity::dl_harq_entity()
{
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
proc[i].pid = i;
}
pending_ack_pid = -1;
}
bool dl_harq_entity::init(srslte_cell_t cell, uint32_t max_payload_len, log* log_h_, timers* timers_, demux *demux_unit_)
{
timers_db = timers_;
demux_unit = demux_unit_;
log_h = log_h_;
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
if (!proc[i].init(cell, max_payload_len, this)) {
return false;
}
}
return true;
}
bool dl_harq_entity::is_sps(uint32_t pid)
{
return false;
}
void dl_harq_entity::set_harq_info(uint32_t pid, dl_sched_grant* grant)
{
proc[pid%(NOF_HARQ_PROC+1)].set_harq_info(grant);
}
void dl_harq_entity::receive_data(uint32_t tti, uint32_t pid, dl_buffer* dl_buffer, phy* phy_h)
{
proc[pid%(NOF_HARQ_PROC+1)].receive_data(tti, dl_buffer, phy_h);
}
void dl_harq_entity::reset()
{
for (uint32_t i=0;i<NOF_HARQ_PROC+1;i++) {
proc[i].reset();
}
}
bool dl_harq_entity::is_ack_pending_resolution()
{
return pending_ack_pid >= 0;
}
void dl_harq_entity::send_pending_ack_contention_resolution()
{
if (is_ack_pending_resolution()) {
proc[pending_ack_pid].send_pending_ack_contention_resolution();
pending_ack_pid = -1;
}
}
/***********************************************************
*
* HARQ PROCESS
*
*********************************************************/
dl_harq_entity::dl_harq_process::dl_harq_process() : cur_grant(0),pending_ack_grant(0) {
is_first_tx = true;
is_first_decoded = true;
is_initiated = false;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
payload = NULL;
max_payload_len = 0;
}
void dl_harq_entity::dl_harq_process::reset() {
is_first_tx = true;
is_first_decoded = true;
bzero(&cur_grant, sizeof(srslte::ue::dl_sched_grant));
if (is_initiated) {
srslte_softbuffer_rx_reset(&softbuffer);
}
}
void dl_harq_entity::dl_harq_process::send_pending_ack_contention_resolution()
{
if (pending_ul_buffer) {
Info("Generating Pending ACK=%d for UL TTI=%d\n", pending_ack, pending_ul_buffer->tti);
pending_ul_buffer->generate_ack(pending_ack, &pending_ack_grant);
}
}
void dl_harq_entity::dl_harq_process::receive_data(uint32_t tti, srslte::ue::dl_buffer *dl_buffer, phy *phy_h)
{
bool ack = false;
pending_ul_buffer = NULL;
if (payload) {
if (cur_grant.get_tbs() <= max_payload_len) {
Info("Decoding PDSCH data TBS=%d, RV=%d\n", cur_grant.get_tbs(), cur_grant.get_rv());
if (dl_buffer->decode_data(&cur_grant, &softbuffer, payload)) {
Info("Decoded OK\n");
// RX OK
if (pid == HARQ_BCCH_PID) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.get_tbs()/8);
harq_entity->demux_unit->push_pdu_bcch(payload, cur_grant.get_tbs());
is_first_tx = true;
} else {
if (is_first_decoded) {
if (cur_grant.is_temp_rnti()) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.get_tbs()/8);
harq_entity->demux_unit->push_pdu_temp_crnti(payload, cur_grant.get_tbs());
} else {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.get_tbs()/8);
harq_entity->demux_unit->push_pdu(payload, cur_grant.get_tbs());
}
}
ack = true;
}
} else {
Warning("Decoded Error\n");
// RX NOK
ack = false;
}
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(mac::TIME_ALIGNMENT)->is_expired()) {
// Do not generate ACK
Debug("Not generating ACK\n");
} else {
if (cur_grant.is_temp_rnti()) {
// Postpone ACK after contention resolution is resolved
pending_ack = ack;
pending_ul_buffer = phy_h->get_ul_buffer(tti+4);
harq_entity->pending_ack_pid = pid;
memcpy(&pending_ack_grant, &cur_grant, sizeof(dl_sched_grant));
Debug("ACK pending contention resolution\n");
} else {
Debug("Generating ACK\n");
// Generate ACK
srslte::ue::ul_buffer *ul_buffer = phy_h->get_ul_buffer(tti+4);
ul_buffer->generate_ack(ack, &cur_grant);
}
}
} else {
fprintf(stderr, "Error with DL grant. TBS (%d) exceeds payload buffer length (%d)\n", cur_grant.get_tbs(), max_payload_len);
}
}
}
// Implement 5.3.2.2
void dl_harq_entity::dl_harq_process::set_harq_info(srslte::ue::dl_sched_grant* new_grant) {
bool is_new_transmission = false;
if (new_grant->get_ndi() && !cur_grant.get_ndi() || is_first_tx) {
is_new_transmission = true;
is_first_decoded = true;
is_first_tx = false;
Debug("Set HARQ Info for new transmission\n");
} else {
is_new_transmission = false;
Debug("Set HARQ Info for retransmission\n");
}
if (is_new_transmission || cur_grant.get_tbs() != new_grant->get_tbs()) {
Debug("Reset softbuffer RX\n");
srslte_softbuffer_rx_reset(&softbuffer);
}
if (new_grant->get_tbs() <= max_payload_len) {
memcpy(&cur_grant, new_grant, sizeof(srslte::ue::dl_sched_grant));
} else {
fprintf(stderr, "Error with DL grant. TBS (%d) exceeds payload buffer length (%d)\n", new_grant->get_tbs(), max_payload_len);
}
}
bool dl_harq_entity::dl_harq_process::init(srslte_cell_t cell, uint32_t max_payload_len_, dl_harq_entity *parent) {
max_payload_len = max_payload_len_;
if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating soft buffer\n");
return false;
} else {
is_initiated = true;
harq_entity = parent;
log_h = harq_entity->log_h;
payload = (uint8_t*) srslte_vec_malloc(sizeof(uint8_t) * max_payload_len);
return payload?true:false;
}
}
}
}

@ -0,0 +1,48 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/mac/dl_sps.h"
namespace srslte {
namespace ue {
dl_sched_grant* dl_sps::get_pending_grant(uint32_t tti)
{
return NULL;
}
void dl_sps::reset(uint32_t tti, dl_sched_grant* grant)
{
}
void dl_sps::clear()
{
}
}
}

@ -0,0 +1,524 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <string.h>
#include <strings.h>
#include <pthread.h>
#include <unistd.h>
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mac_params.h"
namespace srslte {
namespace ue {
bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
{
started = false;
ttisync = ttisync_;
phy_h = phy_h_;
log_h = log_h_;
tti = 0;
is_synchronized = false;
bsr_procedure.init(log_h, &timers_db, &params_db, &mac_io_lch);
mux_unit.init(log_h, &mac_io_lch, &bsr_procedure);
demux_unit.init(phy_h, log_h, &mac_io_lch, &timers_db);
ra_procedure.init(&params_db, phy_h, log_h, &timers_db, &mux_unit, &demux_unit);
sr_procedure.init(log_h, &params_db, phy_h);
reset();
pthread_attr_t attr;
struct sched_param param;
param.sched_priority = sched_get_priority_min(SCHED_FIFO) ;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
if (!pthread_create(&mac_thread, &attr, mac_thread_fnc, this)) {
started = true;
} else {
perror("pthread_create");
}
return started;
}
void mac::stop()
{
started = false;
pthread_join(mac_thread, NULL);
}
int mac::get_tti()
{
if (is_synchronized) {
return (int) tti;
} else {
return -1;
}
}
// Implement Section 5.8
void mac::reconfiguration()
{
}
// Implement Section 5.9
void mac::reset()
{
timers_db.stop_all();
timeAlignmentTimerExpire();
ul_harq.reset_ndi();
mux_unit.msg3_flush();
mux_unit.reset();
ra_procedure.stop();
ra_procedure.reset();
sr_procedure.stop();
sr_procedure.reset();
bsr_procedure.stop();
bsr_procedure.reset();
phr_procedure.stop();
phr_procedure.reset();
dl_harq.reset();
params_db.set_param(mac_params::RNTI_TEMP, 0);
}
void* mac::mac_thread_fnc(void *arg) {
srslte::ue::mac* mac = static_cast<srslte::ue::mac*>(arg);
mac->main_radio_loop();
return NULL;
}
void mac::main_radio_loop() {
setup_timers();
while(1) {
if (!is_synchronized) {
srslte_cell_t cell;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
if (phy_h->decode_mib_best(&cell, bch_payload)) {
// Print MIB
srslte_cell_fprint(stdout, &cell, phy_h->get_current_tti()/10);
// Init HARQ for this cell
Info("Init UL/DL HARQ\n");
ul_harq.init(cell, &params_db, log_h, &timers_db, &mux_unit);
dl_harq.init(cell, 8*1024, log_h, &timers_db, &demux_unit);
// Set the current PHY cell to the detected cell
Info("Setting up PHY for cell_id=%d\n", cell.id);
if (phy_h->set_cell(cell)) {
Info("Starting RX streaming\n");
if (phy_h->start_rxtx()) {
log_h->step(ttisync->wait());
Info("Receiver synchronized\n");
// Send MIB to RRC
mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->send(bch_payload, SRSLTE_BCH_PAYLOAD_LEN);
ttisync->resync();
Info("Wait for AGC, CFO estimation, etc. \n");
for (int i=0;i<1000;i++) {
tti = ttisync->wait();
}
is_synchronized = true;
} else {
Error("Starting PHY receiver\n");
exit(-1);
}
} else {
Error("Setting PHY cell\n");
exit(-1);
}
} else {
Warning("Cell not found\n");
sleep(1);
}
}
if (is_synchronized) {
/* Warning: Here order of invocation of procedures is important!! */
bool ul_resources_available;
tti = ttisync->wait();
log_h->step(tti);
// Step all procedures
bsr_procedure.step(tti);
// Check if BSR procedure need to start SR
if (bsr_procedure.need_to_send_sr()) {
sr_procedure.start();
}
sr_procedure.step(tti);
// Check SR if we need to start RA
if (sr_procedure.need_random_access()) {
ra_procedure.start_mac_order();
}
ra_procedure.step(tti);
//phr_procedure.step(tti);
// Receive PCH, if requested
receive_pch(tti);
// Process DL grants always
process_dl_grants(tti);
// Process UL grants if RA procedure is done and we have pending data or in contention resolution
if (ra_procedure.is_contention_resolution() ||
ra_procedure.is_successful() && mux_unit.is_pending_ccch_sdu())
{
ul_resources_available = process_ul_grants(tti);
}
// Send pending HARQ ACK, if any, and contention resolution is resolved
if (dl_harq.is_ack_pending_resolution()) {
ra_procedure.step(tti);
if (ra_procedure.is_successful() || ra_procedure.is_response_error()) {
Info("Sending pending ACK for contention resolution\n");
dl_harq.send_pending_ack_contention_resolution();
}
}
timers_db.step_all();
// Check if there is pending CCCH SDU in Multiplexing Unit
if (mux_unit.is_pending_ccch_sdu()) {
// Start RA procedure
if (!ra_procedure.in_progress() && !ra_procedure.is_successful()) {
Info("Starting RA procedure by RLC order\n");
ra_procedure.start_rlc_order();
}
}
}
}
}
void mac::add_sdu_handler(sdu_handler *handler) {
demux_unit.add_sdu_handler(handler);
}
void mac::setup_timers()
{
if (params_db.get_param(mac_params::TIMER_TIMEALIGN) > 0) {
timers_db.get(TIME_ALIGNMENT)->set(this, params_db.get_param(mac_params::TIMER_TIMEALIGN));
}
}
static sched_grant::rnti_type_t rnti_type(int rnti_param_id) {
switch(rnti_param_id) {
case mac_params::RNTI_C:
return sched_grant::RNTI_TYPE_CRNTI;
case mac_params::RNTI_TEMP:
return sched_grant::RNTI_TYPE_TEMP;
case mac_params::RNTI_SPS:
return sched_grant::RNTI_TYPE_SPS;
case mac_params::RNTI_RA:
return sched_grant::RNTI_TYPE_RA;
}
}
uint32_t mac::get_harq_sps_pid(uint32_t tti) {
uint32_t nof_proc = ((uint32_t) params_db.get_param(mac_params::SPS_DL_NOF_PROC));
return tti/params_db.get_param(mac_params::SPS_DL_SCHED_INTERVAL)%nof_proc;
}
void mac::timer_expired(uint32_t timer_id)
{
switch(timer_id) {
case TIME_ALIGNMENT:
timeAlignmentTimerExpire();
break;
default:
break;
}
}
/* Function called on expiry of TimeAlignmentTimer */
void mac::timeAlignmentTimerExpire() {
dl_harq.reset();
ul_harq.reset();
dl_sps_assig.clear();
ul_sps_assig.clear();
}
// Receive PCH when requested as defined in Section 5.5
void mac::receive_pch(uint32_t tti) {
if (params_db.get_param(mac_params::PCCH_RECEIVE)) {
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
dl_sched_grant pch_grant(sched_grant::RNTI_TYPE_PRNTI, SRSLTE_PRNTI);
if (dl_buffer->get_dl_grant(&pch_grant)) {
qbuff *pcch_buff = mac_io_lch.get(mac_io::MAC_LCH_PCCH_DL);
uint8_t *ptr = (uint8_t*) pcch_buff->request();
if (ptr && pch_grant.get_tbs() <= mac_io_lch.DEFAULT_MSG_SZ) {
if (dl_buffer->decode_data(&pch_grant, ptr)) {
pcch_buff->release();
} else {
Warning("Error decoding PCH\n");
}
} else {
Error("Error getting pointer from PCCH buffer\n");
}
} else {
Debug("No P-RNTI grant found while looking for PCH messages\n");
}
}
}
/* This function controls DL Grant Assignment as specified in Section 5.3.1 in 36.321
* and issues commands to DL harq operation
*/
void mac::process_dl_grants(uint32_t tti) {
// Get DL buffer for this TTI
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
// 5.3.1 DL Assignment reception
for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_RA;i++) {
// Check C-RNTI, SPS-RNTI and Temporal RNTI
if (params_db.get_param(i) != 0) {
dl_sched_grant ue_grant(rnti_type(i), params_db.get_param(i));
if (dl_buffer->get_dl_grant(&ue_grant)) {
// If PDCCH for C-RNTI and RA procedure in Contention Resolution, notify it
if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) {
ra_procedure.pdcch_to_crnti(false);
}
if (i != mac_params::RNTI_SPS) {
uint32_t harq_pid = ue_grant.get_harq_process();
if (i == mac_params::RNTI_TEMP) {
ue_grant.set_ndi(is_first_temporal);
is_first_temporal = false;
}
if (i == mac_params::RNTI_C && dl_harq.is_sps(harq_pid)) {
ue_grant.set_ndi(true);
}
Info("Processing DL grant TBS=%d, RNTI=%d, RV=%d\n", ue_grant.get_tbs(), ue_grant.get_rnti(), ue_grant.get_rv());
dl_harq.set_harq_info(harq_pid, &ue_grant);
dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h);
} else {
uint32_t harq_pid = get_harq_sps_pid(tti);
if (ue_grant.get_ndi()) {
ue_grant.set_ndi(false);
dl_harq.set_harq_info(harq_pid, &ue_grant);
dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h);
} else {
if (ue_grant.is_sps_release()) {
dl_sps_assig.clear();
if (timers_db.get(TIME_ALIGNMENT)->is_running()) {
//phy_h->send_sps_ack();
Warning("PHY Send SPS ACK not implemented\n");
}
} else {
dl_sps_assig.reset(tti, &ue_grant);
ue_grant.set_ndi(true);
dl_harq.set_harq_info(harq_pid, &ue_grant);
}
}
}
}
}
}
/* Process configured DL assingments (SPS) */
dl_sched_grant *sps_grant = dl_sps_assig.get_pending_grant(tti);
if (sps_grant != NULL) {
Info("Processing SPS grant\n");
uint32_t harq_pid = get_harq_sps_pid(tti);
sps_grant->set_ndi(true);
dl_harq.set_harq_info(harq_pid, sps_grant);
dl_harq.receive_data(tti, harq_pid, dl_buffer, phy_h);
}
/* Process SI-RNTI */
uint32_t si_window_start = params_db.get_param(mac_params::BCCH_SI_WINDOW_ST);
uint32_t si_window_length = params_db.get_param(mac_params::BCCH_SI_WINDOW_LEN);
if (tti >= si_window_start && tti < (si_window_start + si_window_length)) {
// Exclude subf 5 and sfn%2==0 unless it's a SIB1 message (window_length=1) (This is defined in 36.331 Sec 5.2.3)
if (!(phy_h->tti_to_subf(si_window_length) != 1 &&
phy_h->tti_to_subf(si_window_start) == 5 && (phy_h->tti_to_SFN(tti)%2) == 0))
{
Info("Searching for DL grant for SI-RNTI window_st=%d, window_len=%d\n", si_window_start, si_window_length);
dl_sched_grant si_grant(sched_grant::RNTI_TYPE_SIRNTI, SRSLTE_SIRNTI);
if (dl_buffer->get_dl_grant(&si_grant)) {
uint32_t k;
if (phy_h->tti_to_subf(si_window_start) == 5) { // This is SIB1, k is different
k = (phy_h->tti_to_SFN(tti)/2)%4;
} else {
k = phy_h->tti_to_subf(tti)%4;
}
si_grant.set_rv(((uint32_t) ceilf((float)1.5*k))%4);
Info("DL grant found, sending to HARQ with RV: %d\n", si_grant.get_rv());
dl_harq.set_harq_info(dl_harq_entity::HARQ_BCCH_PID, &si_grant);
dl_harq.receive_data(tti, dl_harq_entity::HARQ_BCCH_PID, dl_buffer, phy_h);
params_db.set_param(mac_params::BCCH_SI_WINDOW_ST, 0);
params_db.set_param(mac_params::BCCH_SI_WINDOW_LEN, 0);
} else {
Warning("DL grant not found\n");
}
}
}
}
/* UL Grant reception and processin as defined in Section 5.4.1 in 36.321 */
bool mac::process_ul_grants(uint32_t tti) {
// Get DL buffer for this TTI to look for DCI grants
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
//if (timers_db.get(TIME_ALIGNMENT)->is_running()) {
if (1) {
for (int i = mac_params::RNTI_C;i<=mac_params::RNTI_TEMP;i++) {
// Check C-RNTI, SPS-RNTI and Temporal C-RNTI
if (params_db.get_param(i) != 0) {
ul_sched_grant ul_grant(rnti_type(i), params_db.get_param(i));
if (dl_buffer->get_ul_grant(&ul_grant)) {
if (ul_grant.is_from_rar()) {
dl_buffer->discard_pending_rar_grant();
}
if (ra_procedure.is_contention_resolution() && i == mac_params::RNTI_C) {
ra_procedure.pdcch_to_crnti(true);
}
if (i == mac_params::RNTI_C || i == mac_params::RNTI_TEMP || ra_procedure.is_running()) {
if (i == mac_params::RNTI_C && ul_harq.is_sps(tti)) {
ul_grant.set_ndi(true);
}
Info("Found UL Grant TBS=%d RNTI=%d is_from_rar=%d\n", ul_grant.get_tbs(), params_db.get_param(i), ul_grant.is_from_rar());
ul_harq.run_tti(tti, &ul_grant, phy_h);
return true;
}
else if (i == mac_params::RNTI_SPS) {
if (ul_grant.get_ndi()) {
ul_grant.set_ndi(false);
ul_harq.run_tti(tti, &ul_grant, phy_h);
} else {
if (ul_grant.is_sps_release()) {
ul_sps_assig.clear();
} else {
ul_sps_assig.reset(tti, &ul_grant);
ul_grant.set_ndi(true);
ul_harq.run_tti(tti, &ul_grant, phy_h);
return true;
}
}
}
}
}
}
/* Process configured UL assingments (SPS) */
ul_sched_grant *sps_grant = ul_sps_assig.get_pending_grant(tti);
if (sps_grant != NULL) {
sps_grant->set_ndi(true);
ul_harq.run_tti(tti, sps_grant, phy_h);
return true;
}
}
ul_harq.run_tti(tti, phy_h);
return false;
}
int mac::recv_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
{
if (lcid <= mac_io::MAC_LCH_PCCH_DL) {
return mac_io_lch.get(lcid)->recv(sdu_payload, nbytes);
} else {
Error("Receiving SDU: Invalid lcid=%d\n", lcid);
return -1;
}
}
int mac::recv_bcch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_BCCH_DL)->recv(sdu_payload, buffer_len_nbytes);
}
int mac::recv_ccch_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_DL)->recv(sdu_payload, buffer_len_nbytes);
}
int mac::recv_dtch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
}
int mac::recv_dcch0_sdu(uint8_t* sdu_payload, uint32_t buffer_len_nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_DL)->recv(sdu_payload, buffer_len_nbytes);
}
bool mac::send_sdu(uint32_t lcid, uint8_t* sdu_payload, uint32_t nbytes)
{
lcid += mac_io::MAC_LCH_CCCH_UL;
if (lcid <= mac_io::MAC_LCH_DTCH2_UL) {
return mac_io_lch.get(lcid)->send(sdu_payload, nbytes);
} else {
Error("Receiving SDU: Invalid lcid=%d\n", lcid);
return -1;
}
}
bool mac::send_ccch_sdu(uint8_t* sdu_payload, uint32_t nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_CCCH_UL)->send(sdu_payload, nbytes);
}
bool mac::send_dtch0_sdu(uint8_t* sdu_payload, uint32_t nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_DTCH0_UL)->send(sdu_payload, nbytes);
}
bool mac::send_dcch0_sdu(uint8_t* sdu_payload, uint32_t nbytes)
{
return mac_io_lch.get(mac_io::MAC_LCH_DCCH0_UL)->send(sdu_payload, nbytes);
}
void mac::set_param(mac_params::mac_param_t param, int64_t value)
{
params_db.set_param((uint32_t) param, value);
}
void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD)
{
mux_unit.set_priority(mac_io::MAC_LCH_CCCH_UL+lcid, priority, PBR_x_tti, BSD);
bsr_procedure.setup_lcg(lcid, lcg);
bsr_procedure.set_priority(lcid, priority);
}
}
}

@ -0,0 +1,347 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/mac/mux.h"
#include "srsapps/ue/mac/mac.h"
namespace srslte {
namespace ue {
#define IO_IDX(lch) (lch + mac_io::MAC_LCH_CCCH_UL)
#define UL_IDX(lch) (lch - mac_io::MAC_LCH_CCCH_UL)
mux::mux() : pdu_msg(20)
{
msg3_buff.init(1, MSG3_BUFF_SZ);
pdu_buff.init(1, PDU_BUFF_SZ);
bzero(nof_tx_pkts, sizeof(uint32_t) * mac_io::NOF_UL_LCH);
pthread_mutex_init(&mutex, NULL);
msg3_has_been_transmitted = false;
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
priority[i] = 1;
priority_sorted[i] = 1;
PBR[i] = -1; // -1 is infinite
BSD[i] = 10;
lchid_sorted[i] = i;
}
}
void mux::init(log *log_h_, mac_io *mac_io_h_, bsr_proc *bsr_procedure_)
{
log_h = log_h_;
mac_io_h = mac_io_h_;
bsr_procedure = bsr_procedure_;
}
void mux::reset()
{
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
Bj[i] = 0;
}
}
bool mux::is_pending_ccch_sdu()
{
return is_pending_sdu(0);
}
bool mux::is_pending_any_sdu()
{
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
if (!mac_io_h->get(i)->isempty()) {
return true;
}
}
return false;
}
bool mux::is_pending_sdu(uint32_t lch_id) {
lch_id += (uint32_t) mac_io::MAC_LCH_CCCH_UL;
if (lch_id < mac_io::MAC_NOF_QUEUES) {
return !mac_io_h->get(lch_id)->isempty();
}
}
void mux::set_priority(uint32_t lch_id, uint32_t set_priority, int set_PBR, uint32_t set_BSD)
{
pthread_mutex_lock(&mutex);
if (lch_id < mac_io::NOF_UL_LCH) {
priority[lch_id] = set_priority;
PBR[lch_id] = set_PBR;
BSD[lch_id] = set_BSD;
// Insert priority in sorted idx array
int new_index = 0;
while(set_priority > priority_sorted[new_index] && new_index < mac_io::NOF_UL_LCH) {
new_index++;
}
int old_index = 0;
while(lch_id != lchid_sorted[old_index] && new_index < mac_io::NOF_UL_LCH) {
old_index++;
}
if (new_index == mac_io::NOF_UL_LCH) {
Error("Can't find LchID=%d in sorted list\n", lch_id);
return;
}
// Replace goes in one direction or the other
int add=new_index>old_index?1:-1;
for (int i=old_index;i!=new_index;i+=add) {
priority_sorted[i] = priority_sorted[i+add];
lchid_sorted[i] = lchid_sorted[i+add];
}
priority_sorted[new_index] = set_priority;
lchid_sorted[new_index] = lch_id;
}
pthread_mutex_unlock(&mutex);
}
void mux::pdu_release()
{
pdu_buff.release();
}
bool mux::pdu_move_to_msg3(uint32_t pdu_sz)
{
if (pdu_buff.isempty()) {
if (assemble_pdu(pdu_sz)) {
if (pdu_buff.pending_data() < MSG3_BUFF_SZ) {
pdu_buff.move_to(&msg3_buff);
return true;
} else {
pdu_buff.release();
Error("Assembled PDU size exceeds Msg3 buffer size\n");
return false;
}
} else {
Error("Assembling PDU\n");
return false;
}
} else {
Error("Generating PDU: PDU pending in buffer for transmission\n");
return false;
}
}
// Multiplexing and logical channel priorization as defined in Section 5.4.3
uint8_t* mux::pdu_pop(uint32_t pdu_sz)
{
if (pdu_buff.isempty()) {
if (assemble_pdu(pdu_sz)) {
return (uint8_t*) pdu_buff.pop();
} else {
return NULL;
}
} else {
Error("Generating PDU: PDU pending in buffer for transmission\n");
return NULL;
}
}
void mux::append_crnti_ce_next_tx(uint16_t crnti) {
pending_crnti_ce = crnti;
}
sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) {
switch(format) {
case bsr_proc::LONG_BSR:
return sch_subh::LONG_BSR;
case bsr_proc::SHORT_BSR:
return sch_subh::SHORT_BSR;
case bsr_proc::TRUNC_BSR:
return sch_subh::TRUNC_BSR;
}
}
bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
uint8_t *buff = (uint8_t*) pdu_buff.request();
if (!buff) {
Error("Assembling PDU: Buffer is not available\n");
return false;
}
// Make sure pdu_sz is byte-aligned
pdu_sz_nbits = 8*(pdu_sz_nbits/8);
// Acquire mutex. Cannot change priorities, PBR or BSD after assemble finishes
pthread_mutex_lock(&mutex);
// Update Bj
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
// Add PRB unless it's infinity
if (PBR[i] >= 0) {
Bj[i] += PBR[i];
}
if (Bj[i] >= BSD[i]) {
Bj[i] = BSD[i];
}
}
// Logical Channel Procedure
uint32_t sdu_sz = 0;
pdu_msg.init(pdu_sz_nbits/8, true);
// MAC control element for C-RNTI or data from UL-CCCH
if (!allocate_sdu(UL_IDX(mac_io::MAC_LCH_CCCH_UL), &pdu_msg)) {
if (pending_crnti_ce) {
if (pdu_msg.new_subh()) {
pdu_msg.next();
if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) {
Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n");
}
}
}
}
pending_crnti_ce = 0;
bsr_proc::bsr_t bsr;
bool send_bsr_normal = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_sz_nbits/8, 0, &bsr);
// MAC control element for BSR, with exception of BSR included for padding;
if (send_bsr_normal) {
pdu_msg.next();
pdu_msg.get()->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format));
}
// MAC control element for PHR
// TODO
// data from any Logical Channel, except data from UL-CCCH;
// first only those with positive Bj
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
bool res = true;
while ((Bj[i] > 0 || PBR[i] < 0) && res) {
res = allocate_sdu(lchid_sorted[i], &pdu_msg, &sdu_sz);
if (res && PBR[i] >= 0) {
Bj[i] -= sdu_sz;
}
}
}
// If resources remain, allocate regardless of their Bj value
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
while (allocate_sdu(lchid_sorted[i], &pdu_msg));
}
// MAC control element for BSR included for padding.
bool send_bsr_padding = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_sz_nbits/8, pdu_msg.rem_size(), &bsr);
if (send_bsr_padding) {
pdu_msg.next();
pdu_msg.get()->set_bsr(bsr.buff_size, bsr_format_convert(bsr.format));
}
pthread_mutex_unlock(&mutex);
/* Release all SDUs */
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
while(nof_tx_pkts[i] > 0) {
mac_io_h->get(IO_IDX(i))->release();
nof_tx_pkts[i]--;
}
}
Info("Assembled MAC PDU msg size %d bytes\n", pdu_msg.size());
/* Generate MAC PDU and save to buffer */
if (pdu_msg.write_packet(buff)) {
pdu_buff.push(pdu_sz_nbits);
} else {
Error("Writing PDU message to packet\n");
return false;
}
return true;
}
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg)
{
return allocate_sdu(lcid, pdu_msg, NULL);
}
bool mux::allocate_sdu(uint32_t lcid, sch_pdu *pdu_msg, uint32_t *sdu_sz)
{
// Get n-th pending SDU pointer and length
uint32_t buff_len;
uint8_t *buff_ptr = (uint8_t*) mac_io_h->get(mac_io::MAC_LCH_CCCH_UL + lcid)->pop(&buff_len, nof_tx_pkts[lcid]);
if (buff_ptr) { // there is pending SDU to allocate
if (sdu_sz) {
*sdu_sz = buff_len;
}
if (pdu_msg->new_subh()) { // there is space for a new subheader
pdu_msg->next();
if (pdu_msg->get()->set_sdu(lcid, buff_ptr, buff_len/8)) { // new SDU could be added
// Increase number of pop'ed packets from queue
nof_tx_pkts[lcid]++;
return true;
}
}
}
return false;
}
void mux::msg3_flush()
{
msg3_buff.flush();
msg3_has_been_transmitted = false;
}
void mux::msg3_transmitted()
{
msg3_has_been_transmitted = true;
}
bool mux::msg3_is_transmitted()
{
return msg3_has_been_transmitted;
}
/* Returns a pointer to the Msg3 buffer */
uint8_t* mux::msg3_pop(uint32_t TB_size)
{
uint32_t len;
uint8_t *msg3 = (uint8_t*) msg3_buff.pop(&len);
if (len < TB_size) {
// Pad with zeros without exceeding maximum buffer size
if (TB_size <= MSG3_BUFF_SZ) {
bzero(&msg3[len], (TB_size-len)*sizeof(uint8_t));
} else {
Error("Requested TB size from Msg3 buffer exceeds buffer size (%d>%d)\n", TB_size, MSG3_BUFF_SZ);
return NULL;
}
}
return msg3;
}
}
}

@ -0,0 +1,610 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include "srsapps/ue/mac/pdu.h"
#include "srslte/srslte.h"
namespace srslte {
namespace ue {
void sch_pdu::fprint(FILE* stream)
{
fprintf(stream, "MAC SDU for UL/DL-SCH. ");
pdu::fprint(stream);
}
void sch_subh::fprint(FILE* stream)
{
if (is_sdu()) {
fprintf(stream, "SDU LCHID=%d, SDU nof_bytes=%d\n", lcid, nof_bytes);
} else {
switch(lcid) {
case C_RNTI:
fprintf(stream, "C-RNTI CE: %d\n", get_c_rnti());
break;
case CON_RES_ID:
fprintf(stream, "Contention Resolution ID CE: 0x%lx\n", get_con_res_id());
break;
case TA_CMD:
fprintf(stream, "Time Advance Command CE: %d\n", get_ta_cmd());
break;
case PADDING:
fprintf(stream, "PADDING\n");
}
}
}
void sch_pdu::parse_packet(uint8_t *ptr)
{
pdu::parse_packet(ptr);
// Correct size for last SDU
if (nof_subheaders > 0) {
uint32_t read_len = 0;
for (int i=0;i<nof_subheaders-1;i++) {
read_len += subheaders[i].size_plus_header();
}
if (pdu_len-read_len-1 >= 0) {
subheaders[nof_subheaders-1].set_payload_size(pdu_len-read_len-1);
} else {
fprintf(stderr,"Reading MAC PDU: negative payload for last subheader\n");
}
}
}
// Section 6.1.2
bool sch_pdu::write_packet(uint8_t* ptr)
{
uint8_t *init_ptr = ptr;
// Add single or two-byte padding if required
if (rem_len == 1 || rem_len == 2) {
sch_subh padding;
padding.set_padding();
for (int i=0;i<rem_len;i++) {
padding.write_subheader(&ptr, false);
}
rem_len = 0;
}
// Find last SDU or CE
int last_sdu = nof_subheaders-1;
while(!subheaders[last_sdu].is_sdu() && last_sdu >= 0) {
last_sdu--;
}
int last_ce = nof_subheaders-1;
while(subheaders[last_ce].is_sdu() && last_ce >= 0) {
last_ce--;
}
int last_sh = subheaders[last_sdu].is_sdu()?last_sdu:last_ce;
// Write subheaders for MAC CE first
for (int i=0;i<nof_subheaders;i++) {
if (!subheaders[i].is_sdu()) {
subheaders[i].write_subheader(&ptr, i==last_sh);
}
}
// Then for SDUs
for (int i=0;i<nof_subheaders;i++) {
if (subheaders[i].is_sdu()) {
subheaders[i].write_subheader(&ptr, i==last_sh);
}
}
// Write payloads in the same order
for (int i=0;i<nof_subheaders;i++) {
if (!subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr);
}
}
for (int i=0;i<nof_subheaders;i++) {
if (subheaders[i].is_sdu()) {
subheaders[i].write_payload(&ptr);
}
}
// Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8);
}
uint32_t sch_pdu::rem_size() {
return rem_len;
}
uint32_t sch_pdu::size()
{
return pdu_len - rem_len;
}
uint32_t sch_pdu::size_plus_header_sdu(uint32_t nbytes)
{
if (nbytes < 128) {
return nbytes + 2;
} else {
return nbytes + 3;
}
}
bool sch_pdu::has_space_ce(uint32_t nbytes)
{
if (rem_len >= nbytes + 1) {
return true;
} else {
return false;
}
}
bool sch_pdu::has_space_sdu(uint32_t nbytes)
{
if (rem_len >= size_plus_header_sdu(nbytes)) {
return true;
} else {
return false;
}
}
bool sch_pdu::update_space_ce(uint32_t nbytes)
{
if (has_space_ce(nbytes)) {
rem_len -= nbytes + 1;
}
}
bool sch_pdu::update_space_sdu(uint32_t nbytes)
{
if (has_space_sdu(nbytes)) {
rem_len -= size_plus_header_sdu(nbytes);
}
}
void sch_subh::init()
{
lcid = 0;
nof_bytes = 0;
sdu_payload_ptr = NULL;
bzero(ce_payload, sizeof(uint8_t) * MAX_CE_PAYLOAD_LEN);
}
sch_subh::cetype sch_subh::ce_type()
{
if (lcid >= PHD_REPORT) {
return (cetype) lcid;
} else {
return SDU;
}
}
void sch_subh::set_payload_size(uint32_t size) {
nof_bytes = size;
}
uint32_t sch_subh::size_plus_header() {
if (is_sdu()) {
return sch_pdu::size_plus_header_sdu(nof_bytes);
} else {
return nof_bytes + 1;
}
}
uint32_t sch_subh::sizeof_ce(uint32_t lcid, bool is_ul)
{
if (is_ul) {
switch(lcid) {
case PHD_REPORT:
return 1;
case C_RNTI:
return 2;
case TRUNC_BSR:
return 1;
case SHORT_BSR:
return 1;
case LONG_BSR:
return 3;
case PADDING:
return 0;
}
} else {
switch(lcid) {
case CON_RES_ID:
return 6;
case TA_CMD:
return 1;
case DRX_CMD:
return 0;
case PADDING:
return 0;
}
}
}
bool sch_subh::is_sdu()
{
return ce_type() == SDU;
}
uint16_t sch_subh::get_c_rnti()
{
uint8_t *ptr = ce_payload;
uint16_t ret = (uint16_t) srslte_bit_unpack(&ptr, 16);
return ret;
}
uint64_t sch_subh::get_con_res_id()
{
uint8_t *ptr = ce_payload;
uint64_t ret = (uint64_t) srslte_bit_unpack_l(&ptr, 48);
return ret;
}
uint8_t sch_subh::get_phd()
{
uint8_t *ptr = ce_payload;
ptr += 2;
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6);
return ret;
}
uint8_t sch_subh::get_ta_cmd()
{
uint8_t *ptr = ce_payload;
ptr += 2;
uint8_t ret = (uint8_t) srslte_bit_unpack(&ptr, 6);
return ret;
}
uint32_t sch_subh::get_sdu_lcid()
{
return lcid;
}
uint32_t sch_subh::get_sdu_nbytes()
{
return nof_bytes;
}
uint8_t* sch_subh::get_sdu_ptr()
{
return sdu_payload_ptr;
}
void sch_subh::set_padding()
{
lcid = PADDING;
}
bool sch_subh::set_bsr(uint32_t buff_size[4], sch_subh::cetype format)
{
uint32_t nonzero_lcg=0;
for (int i=0;i<4;i++) {
if (buff_size[i]) {
nonzero_lcg=i;
}
}
uint32_t ce_size = format==LONG_BSR?3:1;
if (((sch_pdu*)parent)->has_space_ce(ce_size)) {
uint8_t *ptr = ce_payload;
if (format==LONG_BSR) {
for (int i=0;i<4;i++) {
srslte_bit_pack(buff_size_table(buff_size[i]), &ptr, 6);
}
} else {
srslte_bit_pack(nonzero_lcg, &ptr, 2);
srslte_bit_pack(buff_size_table(buff_size[nonzero_lcg]), &ptr, 6);
}
lcid = format;
((sch_pdu*)parent)->update_space_ce(ce_size);
return true;
} else {
return false;
}
}
bool sch_subh::set_c_rnti(uint16_t crnti)
{
if (((sch_pdu*)parent)->has_space_ce(2)) {
*((uint16_t*) ce_payload) = crnti;
lcid = C_RNTI;
uint8_t *ptr = ce_payload;
srslte_bit_pack(crnti, &ptr, 16);
((sch_pdu*)parent)->update_space_ce(2);
return true;
} else {
return false;
}
}
bool sch_subh::set_con_res_id(uint64_t con_res_id)
{
if (((sch_pdu*)parent)->has_space_ce(6)) {
uint8_t *ptr = ce_payload;
srslte_bit_pack_l(con_res_id, &ptr, 48);
lcid = CON_RES_ID;
((sch_pdu*)parent)->update_space_ce(6);
return true;
} else {
return false;
}
}
bool sch_subh::set_phd(uint8_t phd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
uint8_t *ptr = ce_payload;
srslte_bit_pack(0, &ptr, 2);
srslte_bit_pack(phd, &ptr, 6);
lcid = PHD_REPORT;
((sch_pdu*)parent)->update_space_ce(1);
return true;
} else {
return false;
}
}
bool sch_subh::set_sdu(uint32_t lcid_, uint8_t* ptr, uint32_t nof_bytes_)
{
if (((sch_pdu*)parent)->has_space_sdu(nof_bytes_)) {
sdu_payload_ptr = ptr;
nof_bytes = nof_bytes_;
lcid = lcid_;
((sch_pdu*)parent)->update_space_sdu(nof_bytes_);
return true;
} else {
return false;
}
}
bool sch_subh::set_ta_cmd(uint8_t ta_cmd)
{
if (((sch_pdu*)parent)->has_space_ce(1)) {
uint8_t *ptr = ce_payload;
srslte_bit_pack(0, &ptr, 2);
srslte_bit_pack(ta_cmd, &ptr, 6);
lcid = TA_CMD;
((sch_pdu*)parent)->update_space_ce(1);
return true;
} else {
return false;
}
}
// Section 6.2.1
void sch_subh::write_subheader(uint8_t** ptr, bool is_last)
{
if (is_sdu()) {
// MAC SDU: R/R/E/LCID/F/L subheader
srslte_bit_pack(0, ptr, 2); // R, R
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
// 2nd and 3rd octet
if (!is_last) {
srslte_bit_pack(F_bit?1:0, ptr, 1); // F
srslte_bit_pack(nof_bytes, ptr, nof_bytes<128?7:15); // L
}
} else {
// MAC CE: R/R/E/LCID MAC Subheader
srslte_bit_pack(0, ptr, 2); // R, R
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(lcid, ptr, 5); // LCID
}
}
void sch_subh::write_payload(uint8_t** ptr)
{
uint8_t *src;
if (is_sdu()) {
src = sdu_payload_ptr;
} else {
src = ce_payload;
}
memcpy(*ptr, src, nof_bytes*8*sizeof(uint8_t));
*ptr += nof_bytes*8;
}
bool sch_subh::read_subheader(uint8_t** ptr)
{
// Skip R
*ptr += 2;
bool e_bit = srslte_bit_unpack(ptr, 1)?true:false;
lcid = srslte_bit_unpack(ptr, 5);
if (is_sdu()) {
if (e_bit) {
F_bit = srslte_bit_unpack(ptr, 1)?true:false;
nof_bytes = srslte_bit_unpack(ptr, F_bit?7:15);
} else {
nof_bytes = 0;
F_bit = 0;
}
} else {
nof_bytes = sizeof_ce(lcid, parent->is_ul());
}
return e_bit;
}
void sch_subh::read_payload(uint8_t** ptr)
{
if (is_sdu()) {
sdu_payload_ptr = *ptr;
} else {
memcpy(ce_payload, *ptr, 8*nof_bytes*sizeof(uint8_t));
}
*ptr += nof_bytes*8;
}
void rar_pdu::fprint(FILE* stream)
{
fprintf(stream, "MAC PDU for RAR. ");
if (has_backoff_indicator) {
fprintf(stream, "Backoff Indicator %d. ", backoff_indicator);
}
pdu::fprint(stream);
}
void rar_subh::fprint(FILE* stream)
{
fprintf(stream, "RAPID: %d, Temp C-RNTI: %d, TA: %d, UL Grant: ", preamble, temp_rnti, ta);
srslte_vec_fprint_hex(stream, grant, 20);
}
rar_pdu::rar_pdu(uint32_t max_rars_) : pdu(max_rars_)
{
backoff_indicator = 0;
has_backoff_indicator = false;
}
uint8_t rar_pdu::get_backoff()
{
return backoff_indicator;
}
bool rar_pdu::has_backoff()
{
return has_backoff_indicator;
}
void rar_pdu::set_backoff(uint8_t bi)
{
has_backoff_indicator = true;
backoff_indicator = bi;
}
// Section 6.1.5
bool rar_pdu::write_packet(uint8_t* ptr)
{
// Write Backoff Indicator, if any
if (has_backoff_indicator) {
if (nof_subheaders > 0) {
srslte_bit_pack(1, &ptr, 1); // E
srslte_bit_pack(0, &ptr, 1); // T
srslte_bit_pack(0, &ptr, 2); // R, R
srslte_bit_pack(backoff_indicator, &ptr, 4);
}
}
// Write RAR subheaders
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].write_subheader(&ptr, i==nof_subheaders-1);
}
// Write payload
for (int i=0;i<nof_subheaders;i++) {
subheaders[i].write_payload(&ptr);
}
// Set paddint to zeros (if any)
bzero(ptr, rem_len*sizeof(uint8_t)*8);
}
void rar_subh::init()
{
bzero(grant, sizeof(uint8_t) * RAR_GRANT_LEN);
ta = 0;
temp_rnti = 0;
}
uint32_t rar_subh::get_rapid()
{
return preamble;
}
void rar_subh::get_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
{
memcpy(grant_, &grant, sizeof(uint8_t)*RAR_GRANT_LEN);
}
uint32_t rar_subh::get_ta_cmd()
{
return ta;
}
uint16_t rar_subh::get_temp_crnti()
{
return temp_rnti;
}
void rar_subh::set_rapid(uint32_t rapid)
{
preamble = rapid;
}
void rar_subh::set_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
{
memcpy(&grant, grant_, sizeof(uint8_t)*RAR_GRANT_LEN);
}
void rar_subh::set_ta_cmd(uint32_t ta_)
{
ta = ta_;
}
void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
{
temp_rnti = temp_rnti_;
}
// Section 6.2.2
void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
{
srslte_bit_pack(is_last?0:1, ptr, 1); // E
srslte_bit_pack(1, ptr, 1); // T
srslte_bit_pack(preamble, ptr, 6); // RAPID
}
// Section 6.2.3
void rar_subh::write_payload(uint8_t** ptr)
{
srslte_bit_pack(0, ptr, 1); // R
srslte_bit_pack(ta, ptr, 11); // Timing Adv Cmd
memcpy(*ptr, grant, 20*sizeof(uint8_t)); // UL grant
*ptr += 20;
srslte_bit_pack(temp_rnti, ptr, 16); // Temp C-RNTI
}
void rar_subh::read_payload(uint8_t** ptr)
{
*ptr += 1; // R
ta = srslte_bit_unpack(ptr, 11); // Timing Adv Cmd
memcpy(grant, *ptr, 20*sizeof(uint8_t)); // UL Grant
*ptr += 20;
temp_rnti = srslte_bit_unpack(ptr, 16); // Temp C-RNTI
}
bool rar_subh::read_subheader(uint8_t** ptr)
{
bool e_bit = srslte_bit_unpack(ptr, 1); // E
bool type = srslte_bit_unpack(ptr, 1); // T
if (type) {
preamble = srslte_bit_unpack(ptr, 6); // RAPID
} else {
// Read Backoff
*ptr += 2; // R, R
((rar_pdu*)parent)->set_backoff((uint8_t) srslte_bit_unpack(ptr, 4));
}
return e_bit;
}
// Table 6.1.3.1-1 Buffer size levels for BSR
uint32_t btable[61] = {
10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132,
1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304,
42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125};
uint8_t sch_subh::buff_size_table(uint32_t buffer_size) {
if (buffer_size == 0) {
return 0;
} else if (buffer_size > 150000) {
return 63;
} else {
for (int i=0;i<61;i++) {
if (buffer_size > btable[i]) {
return 1+i;
}
}
return 62;
}
}
}
}

@ -0,0 +1,280 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/mac/proc_bsr.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mux.h"
namespace srslte {
namespace ue {
bsr_proc::bsr_proc()
{
initiated = false;
timer_periodic = false;
timer_retx = false;
for (int i=0;i<MAX_LCID;i++) {
lcg[i] = 0;
priorities[i] = 0;
}
}
void bsr_proc::init(log* log_h_, timers *timers_db_, mac_params* params_db_, mac_io *mac_io_h_)
{
log_h = log_h;
params_db = params_db_;
mac_io_h = mac_io_h_;
timers_db = timers_db_;
initiated = true;
}
void bsr_proc::reset()
{
triggered_bsr_type = NONE;
}
/* Process Periodic BSR */
void bsr_proc::timer_expired(uint32_t timer_id) {
switch(timer_id) {
case mac::BSR_TIMER_PERIODIC:
if (triggered_bsr_type == NONE) {
// Check condition 4 in Sec 5.4.5
if (check_all_channels()) {
triggered_bsr_type = PERIODIC;
}
}
break;
case mac::BSR_TIMER_RETX:
// Check condition 3 in Sec 5.4.5
if (check_all_channels()) {
triggered_bsr_type = REGULAR;
sr_is_sent = false; // Enable reTx of SR
}
break;
}
}
/* Checks condition 1 for Regular BSR reporting */
bool bsr_proc::check_highest_channel() {
uint32_t lcg_with_data = 0;
uint32_t pending_data = 0;
uint32_t min_priority_group[4]={99, 99, 99, 99};
bool trigger_bsr = true;
// Check if data arrived for a LCG
for (uint32_t group=0;group<4;group++) {
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
if (lcg[group] == i) {
if (priorities[i] < min_priority_group[group]) {
min_priority_group[group] = priorities[i];
}
pending_data = mac_io_h->get(i)->pending_data();
if (pending_data > 0) {
lcg_with_data = group;
}
}
}
}
if (pending_data) {
// If no data is available belonging to any of the logical channels belonging to any other LCG
for (uint32_t group=0;group<4 && trigger_bsr;group++) {
if (group != lcg_with_data) {
for (int i=0;i<mac_io::NOF_UL_LCH && trigger_bsr;i++) {
if (lcg[group] == i) {
if (mac_io_h->get(i)->pending_data() && priorities[i] > min_priority_group[group]) {
trigger_bsr=false;
}
}
}
}
}
}
return trigger_bsr;
}
bool bsr_proc::check_all_channels() {
bool ret = false;
bzero(&pending_bsr, sizeof(bsr_t));
for (int i=0;i<mac_io_h->NOF_UL_LCH;i++) {
uint32_t n = mac_io_h->get(i)->pending_data();
pending_bsr.buff_size[lcg[i]] += n;
if (n > 0) {
ret = true;
}
}
return ret;
}
void bsr_proc::get_pending_bsr_format(uint32_t nof_padding_bytes) {
uint32_t nof_lcg=0;
for (int i=0;i<4;i++) {
if (pending_bsr.buff_size[i] > 0) {
nof_lcg++;
}
}
if (triggered_bsr_type == PADDING) {
if (nof_padding_bytes < 4) {
// If space only for short
if (nof_lcg > 1) {
pending_bsr.format = TRUNC_BSR;
uint32_t max_prio_ch = find_max_priority_lcid();
for (int i=0;i<4;i++) {
if (lcg[max_prio_ch] != i) {
pending_bsr.buff_size[i] = 0;
}
}
} else {
pending_bsr.format = SHORT_BSR;
}
} else {
// If space for long BSR
pending_bsr.format = LONG_BSR;
}
} else {
pending_bsr.format = SHORT_BSR;
if (nof_lcg > 1) {
pending_bsr.format = LONG_BSR;
}
}
}
// Checks if Regular BSR must be assembled, as defined in 5.4.5
// Padding BSR is assembled when called by mux_unit when UL grant is received
// Periodic BSR is triggered by the expiration of the timers
void bsr_proc::step(uint32_t tti)
{
if (!initiated) {
return;
}
if (!timer_periodic) {
if (params_db->get_param(mac_params::BSR_TIMER_PERIODIC)) {
timer_periodic = true;
timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, params_db->get_param(mac_params::BSR_TIMER_PERIODIC));
}
}
if (!timer_retx) {
if (params_db->get_param(mac_params::BSR_TIMER_RETX)) {
timer_retx = true;
timers_db->get(mac::BSR_TIMER_RETX)->set(this, params_db->get_param(mac_params::BSR_TIMER_RETX));
}
}
// Check condition 1 in Sec 5.4.5
if (triggered_bsr_type == NONE) {
if (check_highest_channel()) {
triggered_bsr_type = REGULAR;
}
}
}
bool bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t nof_grant_bytes, uint32_t nof_padding_bytes, bsr_t *bsr)
{
bool ret = false;
if (triggered_bsr_type == NONE) {
// If enough space for at least truncated BSR
if (nof_padding_bytes >= 2) {
// Check condition 2 in Sec 5.4.5
if (check_all_channels()) {
triggered_bsr_type = PADDING;
}
}
}
if (triggered_bsr_type != NONE) {
// If no more data is pending and there is no space for MAC CE
uint32_t nof_pending_bytes = 0;
for (int i=0;i<4;i++) {
nof_pending_bytes += pending_bsr.buff_size[i];
}
// Do not include BSR CE if the UL grant can accomodate all pending data but is not sufficient
// to additionally accomodate the BSR MAC CE plus its header
uint32_t bsr_sz_plus_header = 1 + pending_bsr.format == LONG_BSR?3:1;
if (nof_pending_bytes + bsr_sz_plus_header == nof_grant_bytes) {
// if nof_pending_bytes + bsr_sz_plus_header > nof_grant_bytes, BSR has higher priority than data
return false;
}
get_pending_bsr_format(nof_padding_bytes);
// Instruct MUX unit to generate MAC CE
ret = true;
memcpy(bsr, &pending_bsr, sizeof(bsr_t));
if (timer_periodic && pending_bsr.format != TRUNC_BSR) {
timers_db->get(mac::BSR_TIMER_PERIODIC)->reset();
timers_db->get(mac::BSR_TIMER_PERIODIC)->run();
}
// Cancel all triggered BSR
triggered_bsr_type = NONE;
}
// Restart or Start ReTX timer
if (timer_retx) {
timers_db->get(mac::BSR_TIMER_RETX)->reset();
timers_db->get(mac::BSR_TIMER_RETX)->run();
}
return ret;
}
bool bsr_proc::need_to_send_sr() {
if (!sr_is_sent && triggered_bsr_type == REGULAR) {
sr_is_sent = true;
return true;
}
return false;
}
void bsr_proc::setup_lcg(uint32_t lcid, uint32_t new_lcg)
{
if (lcid < MAX_LCID && new_lcg < 4) {
lcg[lcid] = new_lcg;
}
}
void bsr_proc::set_priority(uint32_t lcid, uint32_t priority) {
if (lcid < MAX_LCID) {
priorities[lcid] = priority;
}
}
uint32_t bsr_proc::find_max_priority_lcid() {
uint32_t max_prio = 0, max_idx = 0;
for (int i=0;i<MAX_LCID;i++) {
if (priorities[i] > max_prio) {
max_prio = priorities[i];
max_idx = i;
}
}
return max_idx;
}
}
}

@ -0,0 +1,524 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac_io.h"
#include "srsapps/ue/mac/proc_ra.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/mux.h"
/* Random access procedure as specified in Section 5.1 of 36.321 */
namespace srslte {
namespace ue {
// Table 7.2-1. Backoff Parameter values
uint32_t backoff_table[16] = {0, 10, 20, 30, 40, 60, 80, 120, 160, 240, 320, 480, 960, 960, 960, 960};
// Table 7.6-1: DELTA_PREAMBLE values.
int delta_preamble_db_table[5] = {0, 0, -3, -3, 8};
bool ra_proc::init(mac_params* params_db_, phy* phy_h_, srslte::log* log_h_, srslte::timers* timers_db_,
mux* mux_unit_, demux* demux_unit_)
{
phy_h = phy_h_;
log_h = log_h_;
params_db = params_db_;
timers_db = timers_db_;
mux_unit = mux_unit_;
demux_unit= demux_unit_;
reset();
}
void ra_proc::reset() {
state = IDLE;
}
void ra_proc::read_params() {
// Read initialization parameters
configIndex = params_db->get_param(mac_params::RA_CONFIGINDEX);
preambleIndex = params_db->get_param(mac_params::RA_PREAMBLEINDEX);
maskIndex = params_db->get_param(mac_params::RA_MASKINDEX);
nof_preambles = params_db->get_param(mac_params::RA_NOFPREAMBLES);
if (!nof_preambles || nof_preambles > 64) {
nof_preambles = 64;
}
nof_groupA_preambles = params_db->get_param(mac_params::RA_NOFGROUPAPREAMBLES);
if (!nof_groupA_preambles) {
nof_groupA_preambles = nof_preambles;
}
if (nof_groupA_preambles > nof_preambles) {
nof_groupA_preambles = nof_preambles;
}
nof_groupB_preambles = nof_preambles - nof_groupA_preambles;
if (nof_groupB_preambles) {
messagePowerOffsetGroupB = params_db->get_param(mac_params::RA_MESSAGEPOWEROFFSETB);
messageSizeGroupA = params_db->get_param(mac_params::RA_MESSAGESIZEA);
Pcmax = params_db->get_param(mac_params::RA_PCMAX);
deltaPreambleMsg3 = params_db->get_param(mac_params::RA_DELTAPREAMBLEMSG3);
}
responseWindowSize = params_db->get_param(mac_params::RA_RESPONSEWINDOW);
powerRampingStep = params_db->get_param(mac_params::RA_POWERRAMPINGSTEP);
preambleTransMax = params_db->get_param(mac_params::RA_PREAMBLETRANSMAX);
iniReceivedTargetPower = params_db->get_param(mac_params::RA_INITRECEIVEDPOWER);
contentionResolutionTimer = params_db->get_param(mac_params::RA_CONTENTIONTIMER);
delta_preamble_db = delta_preamble_db_table[configIndex%5];
if (contentionResolutionTimer > 0) {
timers_db->get(mac::CONTENTION_TIMER)->set(this, contentionResolutionTimer);
}
}
bool ra_proc::in_progress()
{
return (state > IDLE && state != COMPLETION);
}
bool ra_proc::is_successful() {
return state == COMPLETION;
}
bool ra_proc::is_response_error() {
return state == RESPONSE_ERROR;
}
bool ra_proc::is_contention_resolution() {
return state == CONTENTION_RESOLUTION;
}
bool ra_proc::is_error() {
return state == RA_PROBLEM;
}
uint32_t interval(uint32_t x1, uint32_t x2) {
if (x1 > x2) {
return x1-x2;
} else {
return 10240-x2+x1;
}
}
const char* state_str[11] = {"Idle",
"RA Initializat.: ",
"RA Initial.Wait: ",
"RA ResSelection: ",
"RA PreambleTx : ",
"RA PreambleRx : ",
"RA ResponseErr : ",
"RA BackoffWait : ",
"RA ContentResol: ",
"RA Completed : ",
"RA Problem : "};
#define rError(fmt, ...) Error("%s" fmt, state_str[state], ##__VA_ARGS__)
#define rInfo(fmt, ...) Info("%s" fmt, state_str[state], ##__VA_ARGS__)
#define rDebug(fmt, ...) Debug("%s" fmt, state_str[state], ##__VA_ARGS__)
// Process Timing Advance Command as defined in Section 5.2
void ra_proc::process_timeadv_cmd(uint32_t ta) {
if (preambleIndex > 0) {
// Preamble not selected by UE MAC
phy_h->set_timeadv_rar(ta);
timers_db->get(mac::TIME_ALIGNMENT)->reset();
timers_db->get(mac::TIME_ALIGNMENT)->run();
Info("Applying RAR TA CMD %d\n", ta);
} else {
// Preamble selected by UE MAC
if (!timers_db->get(mac::TIME_ALIGNMENT)->is_running()) {
phy_h->set_timeadv_rar(ta);
timers_db->get(mac::TIME_ALIGNMENT)->run();
Info("Applying RAR TA CMD %d\n", ta);
} else {
// Ignore TA CMD
Warning("Ignoring RAR TA CMD because timeAlignmentTimer still running\n");
}
}
}
void* init_prach_thread(void *arg) {
phy* phy_h = (phy*) arg;
printf("thread initiating prach\n");
if (phy_h->init_prach()) {
return (void*) 0;
} else {
return (void*) -1;
}
}
void ra_proc::step_initialization() {
read_params();
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
transmitted_contention_id = 0;
preambleTransmissionCounter = 1;
first_rar_received = true;
mux_unit->msg3_flush();
backoff_param_ms = 0;
if (pthread_create(&pt_init_prach, NULL, init_prach_thread, phy_h)) {
perror("pthread_create");
state = RA_PROBLEM;
} else {
state = INITIALIZATION_WAIT;
}
}
void ra_proc::step_initialization_wait() {
int n = pthread_kill(pt_init_prach, 0);
if (n) {
void *status;
pthread_join(pt_init_prach, &status);
if (status) {
rError("Initializing PRACH on PHY\n");
state = RA_PROBLEM;
} else {
rInfo("PRACH init OK\n");
state = RESOURCE_SELECTION;
}
}
}
void ra_proc::step_resource_selection() {
ra_group_t sel_group;
if (preambleIndex > 0) {
// Preamble is chosen by Higher layers (ie Network)
sel_maskIndex = maskIndex;
sel_preamble = (uint32_t) preambleIndex%nof_preambles;
} else {
// Preamble is chosen by MAC UE
if (!msg3_transmitted) {
if (nof_groupB_preambles > 0) { // Check also messageSizeGroupA and pathloss (Pcmax,deltaPreamble and powerOffset)
sel_group = RA_GROUP_B;
} else {
sel_group = RA_GROUP_A;
}
last_msg3_group = sel_group;
} else {
sel_group = last_msg3_group;
}
if (sel_group == RA_GROUP_A) {
sel_preamble = rand()%(nof_groupA_preambles-1);
} else {
sel_preamble = nof_groupA_preambles + rand()%(nof_groupB_preambles-1);
}
sel_maskIndex = 0;
}
rInfo("Selected preambleIndex=%d maskIndex=%d nof_GroupApreambles=%d\n", sel_preamble, sel_maskIndex,nof_groupA_preambles);
state = PREAMBLE_TRANSMISSION;
}
void ra_proc::step_preamble_transmission() {
received_target_power_dbm = iniReceivedTargetPower +
delta_preamble_db +
(preambleTransmissionCounter-1)*powerRampingStep;
phy_h->send_prach(sel_preamble, sel_maskIndex - 1, received_target_power_dbm);
rInfo("Selected received_target_power_dbm=%d dBm\n", received_target_power_dbm);
state = RESPONSE_RECEPTION;
}
void ra_proc::step_response_reception() {
int ra_tti = phy_h->get_prach_transmitted_tti();
if (ra_tti > 0) {
ra_rnti = 1+ra_tti%10; // f_id=0 for FDD
dl_sched_grant rar_grant(ra_rnti);
uint32_t interval_ra = interval(tti, ra_tti);
// Try to decode RAR only within the RA response window
if (interval_ra >= 3 && interval_ra <= 3+responseWindowSize) {
// Get DL grant for RA-RNTI
dl_buffer *dl_buffer = phy_h->get_dl_buffer(tti);
if (dl_buffer->get_dl_grant(&rar_grant))
{
rInfo("DL grant found RA-RNTI=%d\n", ra_rnti);
if (rar_grant.get_tbs() > MAX_RAR_PDU_LEN) {
rError("RAR PDU exceeds local RAR PDU buffer (%d>%d)\n", rar_grant.get_tbs(), MAX_RAR_PDU_LEN);
state = RESPONSE_ERROR;
return;
}
// Decode packet
dl_buffer->reset_softbuffer();
if (dl_buffer->decode_data(&rar_grant, rar_pdu_buffer)) {
rDebug("RAR decoded successfully TBS=%d\n", rar_grant.get_tbs());
rar_pdu_msg.init(rar_grant.get_tbs()/8);
rar_pdu_msg.parse_packet(rar_pdu_buffer);
// Set Backoff parameter
if (rar_pdu_msg.has_backoff()) {
backoff_param_ms = backoff_table[rar_pdu_msg.get_backoff()%16];
} else {
backoff_param_ms = 0;
}
while(rar_pdu_msg.next()) {
if (rar_pdu_msg.get()->get_rapid() == sel_preamble) {
rInfo("Received RAPID=%d\n", sel_preamble);
process_timeadv_cmd(rar_pdu_msg.get()->get_ta_cmd());
// FIXME: Indicate received target power
//phy_h->set_target_power_rar(iniReceivedTargetPower, (preambleTransmissionCounter-1)*powerRampingStep);
// Indicate grant to PHY layer. RAR grants have 6 sf delay (4 is the default delay)
uint8_t grant[rar_subh::RAR_GRANT_LEN];
rar_pdu_msg.get()->get_sched_grant(grant);
phy_h->get_dl_buffer(tti+2)->set_rar_grant(grant);
if (preambleIndex > 0) {
// Preamble selected by Network
state = COMPLETION;
} else {
// Preamble selected by UE MAC
params_db->set_param(mac_params::RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti());
if (first_rar_received) {
first_rar_received = false;
// Save transmitted C-RNTI (if any)
transmitted_crnti = params_db->get_param(mac_params::RNTI_C);
// Save transmitted UE contention id, as defined by higher layers
transmitted_contention_id = params_db->get_param(mac_params::CONTENTION_ID);
params_db->set_param(mac_params::CONTENTION_ID, 0);
// If we have a C-RNTI, tell Mux unit to append C-RNTI CE if no CCCH SDU transmission
if (transmitted_crnti) {
mux_unit->append_crnti_ce_next_tx(transmitted_crnti);
}
// Get TransportBlock size for the grant
ul_sched_grant msg3_grant(sched_grant::RNTI_TYPE_TEMP, rar_pdu_msg.get()->get_temp_crnti());
phy_h->get_dl_buffer(tti+2)->get_ul_grant(&msg3_grant);
// Move MAC PDU from Multiplexing and assembly unit to Msg3
rInfo("Generating Msg3 for TBS=%d\n", msg3_grant.get_tbs());
mux_unit->pdu_move_to_msg3(msg3_grant.get_tbs()); // 56 is the minimum grant provided
}
rDebug("Going to Contention Resolution state\n");
state = CONTENTION_RESOLUTION;
// Start contention resolution timer
timers_db->get(mac::CONTENTION_TIMER)->reset();
timers_db->get(mac::CONTENTION_TIMER)->run();
}
} else {
rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid());
}
}
}
}
srslte_verbose = SRSLTE_VERBOSE_NONE;
}
if (interval_ra > 3+responseWindowSize && interval_ra < 10000) {
rInfo("Timeout while trying to receive RAR\n");
state = RESPONSE_ERROR;
}
}
}
void ra_proc::step_response_error() {
preambleTransmissionCounter++;
if (preambleTransmissionCounter == preambleTransMax + 1) {
rError("Maximum number of transmissions reached (%d)\n", preambleTransMax);
state = RA_PROBLEM;
} else {
backoff_interval_start = tti;
if (backoff_param_ms) {
backoff_inteval = rand()%backoff_param_ms;
} else {
backoff_inteval = 0;
}
if (backoff_inteval) {
rInfo("Backoff wait interval %d\n", backoff_inteval);
state = BACKOFF_WAIT;
} else {
rInfo("Transmitting inmediatly\n");
state = RESOURCE_SELECTION;
}
}
}
void ra_proc::step_backoff_wait() {
if (interval(tti, backoff_interval_start) >= backoff_inteval) {
state = RESOURCE_SELECTION;
}
}
void ra_proc::step_contention_resolution() {
// If Msg3 has been sent
if (mux_unit->msg3_is_transmitted()) {
msg3_transmitted = true;
if (pdcch_to_crnti_received != PDCCH_CRNTI_NOT_RECEIVED)
{
rInfo("PDCCH for C-RNTI received\n");
// Random Access initiated by MAC itself or PDCCH order (transmission of MAC C-RNTI CE)
if (start_mode == MAC_ORDER && pdcch_to_crnti_received == PDCCH_CRNTI_UL_GRANT ||
start_mode == PDCCH_ORDER)
{
timers_db->get(mac::CONTENTION_TIMER)->stop();
params_db->set_param(mac_params::RNTI_TEMP, 0);
state = COMPLETION;
}
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
} else if (demux_unit->is_temp_crnti_pending())
{
rInfo("MAC PDU with Temporal C-RNTI has been decoded\n");
// Random Access initiated by RRC by the transmission of CCCH SDU
if (demux_unit->is_contention_resolution_id_pending()) {
rInfo("MAC PDU Contains Contention Resolution ID CE\n");
// MAC PDU successfully decoded and contains MAC CE contention Id
uint64_t rx_contention_id = demux_unit->get_contention_resolution_id();
timers_db->get(mac::CONTENTION_TIMER)->stop();
if (transmitted_contention_id == rx_contention_id) {
rInfo("MAC PDU Contention Resolution ID matches the one transmitted in CCCH SDU\n");
// UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3
params_db->set_param(mac_params::RNTI_C, params_db->get_param(mac_params::RNTI_TEMP));
// finish the disassembly and demultiplexing of the MAC PDU
demux_unit->demultiplex_pending_pdu();
state = COMPLETION;
} else {
rInfo("Transmitted UE Contention Id differs from received Contention ID (0x%lx != 0x%lx)\n", transmitted_contention_id, rx_contention_id);
// Discard MAC PDU
demux_unit->discard_pending_pdu();
// Contention Resolution not successfully is like RAR not successful
// FIXME: Need to flush Msg3 HARQ buffer. Why?
state = RESPONSE_ERROR;
}
params_db->set_param(mac_params::RNTI_TEMP, 0);
}
}
} else {
rDebug("Msg3 not yet transmitted\n");
}
}
void ra_proc::step_completition() {
params_db->set_param(mac_params::RA_PREAMBLEINDEX, 0);
params_db->set_param(mac_params::RA_MASKINDEX, 0);
mux_unit->msg3_flush();
msg3_transmitted = false;
}
void ra_proc::step(uint32_t tti_)
{
tti = tti_;
if (is_running()) {
switch(state) {
case IDLE:
break;
case INITIALIZATION:
step_initialization();
break;
case INITIALIZATION_WAIT:
step_initialization_wait();
break;
case RESOURCE_SELECTION:
step_resource_selection();
break;
case PREAMBLE_TRANSMISSION:
step_preamble_transmission();
break;
case RESPONSE_RECEPTION:
step_response_reception();
break;
case RESPONSE_ERROR:
step_response_error();
break;
case BACKOFF_WAIT:
step_backoff_wait();
break;
case CONTENTION_RESOLUTION:
step_contention_resolution();
break;
case COMPLETION:
step_completition();
break;
}
}
}
void ra_proc::start_mac_order()
{
if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) {
start_mode = MAC_ORDER;
state = INITIALIZATION;
run();
}
}
void ra_proc::start_pdcch_order()
{
if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) {
start_mode = PDCCH_ORDER;
state = INITIALIZATION;
run();
}
}
void ra_proc::start_rlc_order()
{
if (state == IDLE || state == COMPLETION || state == RA_PROBLEM) {
start_mode = RLC_ORDER;
state = INITIALIZATION;
run();
}
}
// Contention Resolution Timer is expired (Section 5.1.5)
void ra_proc::timer_expired(uint32_t timer_id)
{
rInfo("Contention Resolution Timer expired. Going to Response Error\n");
params_db->set_param(mac_params::RNTI_TEMP, 0);
state = RESPONSE_ERROR;
}
void ra_proc::pdcch_to_crnti(bool is_uplink_grant) {
if (is_uplink_grant) {
pdcch_to_crnti_received = PDCCH_CRNTI_UL_GRANT;
} else {
pdcch_to_crnti_received = PDCCH_CRNTI_DL_GRANT;
}
}
}
}

@ -0,0 +1,92 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/mac/proc_sr.h"
#include "srsapps/ue/mac/mac_params.h"
namespace srslte {
namespace ue {
sr_proc::sr_proc() {
initiated = false;
}
void sr_proc::init(log* log_h_, mac_params* params_db_, phy* phy_h_)
{
log_h = log_h_;
params_db = params_db_;
phy_h = phy_h_;
initiated = true;
}
void sr_proc::reset()
{
is_pending_sr = false;
phy_h->send_sr(false);
}
void sr_proc::step(uint32_t tti)
{
if (initiated) {
if (is_pending_sr) {
if (sr_counter < dsr_transmax) {
sr_counter++;
phy_h->send_sr(true);
} else {
reset();
}
}
}
}
bool sr_proc::need_random_access() {
if (initiated) {
if (sr_counter == dsr_transmax && dsr_transmax > 0 ||
!params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) {
return true;
} else {
return false;
}
}
}
void sr_proc::start()
{
if (initiated) {
if (params_db->get_param(mac_params::SR_PUCCH_CONFIGURED)) {
if (!is_pending_sr) {
sr_counter = 0;
dsr_transmax = params_db->get_param(mac_params::SR_TRANS_MAX);
}
}
}
}
}
}

@ -0,0 +1,286 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/mac/mac_params.h"
#include "srsapps/ue/mac/mac.h"
#include "srsapps/ue/mac/ul_harq.h"
namespace srslte {
namespace ue {
/***********************************************************
*
* HARQ ENTITY
*
*********************************************************/
bool ul_harq_entity::init(srslte_cell_t cell, mac_params *params_db_, log *log_h_, timers *timers_db_, mux *mux_unit_) {
log_h = log_h_;
mux_unit = mux_unit_;
params_db = params_db_;
timers_db = timers_db_;
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
if (!proc[i].init(cell, this)) {
return false;
}
}
return true;
}
uint32_t ul_harq_entity::pidof(uint32_t tti) {
return (uint32_t) tti%NOF_HARQ_PROC;
}
void ul_harq_entity::reset() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset();
}
}
void ul_harq_entity::reset_ndi() {
for (uint32_t i=0;i<NOF_HARQ_PROC;i++) {
proc[i].reset_ndi();
}
}
bool ul_harq_entity::is_sps(uint32_t pid) {
return false;
}
// Called with no UL grant
void ul_harq_entity::run_tti(uint32_t tti, phy *phy_h) {
run_tti(tti, NULL, phy_h);
}
// Implements Section 5.4.2.1
// Called with UL grant
void ul_harq_entity::run_tti(uint32_t tti, ul_sched_grant *grant, phy *phy_h)
{
uint32_t tti_tx = (tti+4)%10240;
uint32_t pid = pidof(tti_tx);
// Receive and route HARQ feedbacks
int tti_harq = (int) tti - 4;
if (tti_harq < 0) {
tti_harq += 10240;
}
uint32_t pid_harq = pidof(tti_harq);
if (proc[pid_harq].has_grant() && proc[pid_harq].last_tx_tti() <= tti_harq) {
Info("Receiving HARQ feedback for PID=%d, TTI last TX %d, TTI harq %d\n", pid_harq, proc[pid_harq].last_tx_tti(), tti_harq);
proc[pid_harq].set_harq_feedback(phy_h->get_dl_buffer(tti)->decode_ack(proc[pid_harq].get_grant()));
}
if (grant) {
if ((grant->is_temp_rnti() && grant->get_ndi() != proc[pid].get_ndi()) ||
(grant->is_crnti() && !proc[pid].has_grant()) ||
grant->is_from_rar())
{
// New transmission
uint8_t* msg3_ptr = (uint8_t*) mux_unit->msg3_pop(grant->get_tbs());
// Uplink grant in a RAR
if (grant->is_from_rar()) {
if (msg3_ptr) {
Info("Generating New Msg3 Transmission for PID=%d TTI=%d\n", pid, tti_tx);
proc[pid].generate_new_tx(tti_tx, msg3_ptr, true, grant, phy_h->get_ul_buffer(tti_tx));
mux_unit->msg3_transmitted();
} else {
Warning("UL RAR grant available but no Msg3 on buffer\n");
}
// Normal UL grant
} else {
// Request a MAC PDU from the Multiplexing & Assemble Unit
Info("Generating New Transmission for PID=%d TTI=%d\n", pid, tti_tx);
uint8_t* mac_pdu = mux_unit->pdu_pop(grant->get_tbs());
if (mac_pdu) {
proc[pid].generate_new_tx(tti_tx, mac_pdu, false, grant, phy_h->get_ul_buffer(tti_tx));
mux_unit->pdu_release();
} else {
Warning("Uplink grant with MAC PDU available in Multiplex Unit\n");
}
}
} else {
// Adaptive Re-TX
Info("Generating Adaptive Retransmission for PID=%d RV=%d\n", pid, proc[pid].get_rv());
proc[pid].generate_retx(tti_tx, grant, phy_h->get_ul_buffer(tti_tx));
}
} else if (proc[pid].has_grant()) {
// Non-Adaptive Re-Tx
Info("Generating Non-adaptive Retransmission for PID=%d RV=%d\n", pid, proc[pid].get_rv());
proc[pid].generate_retx(tti_tx, phy_h->get_ul_buffer(tti_tx));
}
}
/***********************************************************
*
* HARQ PROCESS
*
*********************************************************/
static int rv_of_irv[4] = {0, 2, 3, 1};
static int irv_of_rv[4] = {0, 3, 1, 2};
ul_harq_entity::ul_harq_process::ul_harq_process() : cur_grant(0) {
current_tx_nb = 0;
current_irv = 0;
is_initiated = false;
is_grant_configured = false;
tti_last_tx = 0;
bzero(&cur_grant, sizeof(ul_sched_grant));
}
void ul_harq_entity::ul_harq_process::reset() {
current_tx_nb = 0;
current_irv = 0;
tti_last_tx = 0;
is_grant_configured = false;
bzero(&cur_grant, sizeof(ul_sched_grant));
if (is_initiated) {
srslte_softbuffer_tx_reset(&softbuffer);
}
}
bool ul_harq_entity::ul_harq_process::has_grant() {
return is_grant_configured;
}
void ul_harq_entity::ul_harq_process::reset_ndi() {
ndi = false;
}
bool ul_harq_entity::ul_harq_process::get_ndi()
{
return ndi;
}
uint32_t ul_harq_entity::ul_harq_process::get_rv()
{
return rv_of_irv[current_irv%4];
}
ul_sched_grant* ul_harq_entity::ul_harq_process::get_grant()
{
return &cur_grant;
}
void ul_harq_entity::ul_harq_process::set_harq_feedback(bool ack) {
harq_feedback = ack;
// UL packet successfully delivered
if (ack) {
Info("HARQ = ACK for UL transmission. Discarting TB.\n");
reset();
} else {
Info("HARQ = NACK for UL transmission\n");
}
}
bool ul_harq_entity::ul_harq_process::init(srslte_cell_t cell, ul_harq_entity *parent) {
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating soft buffer\n");
return false;
} else {
is_initiated = true;
harq_entity = parent;
log_h = harq_entity->log_h;
return true;
}
}
// Retransmission with or w/o grant (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_sched_grant* grant, ul_buffer* ul)
{
current_tx_nb++;
if (grant) {
// HARQ entity requests an adaptive transmission
memcpy(&cur_grant, grant, sizeof(ul_sched_grant));
current_irv = irv_of_rv[grant->get_rv()%4];
harq_feedback = false;
generate_tx(tti_tx, NULL, ul);
} else {
// HARQ entity requests a non-adaptive transmission
if (!harq_feedback) {
generate_tx(tti_tx, NULL, ul);
}
}
// On every Msg3 retransmission, restart mac-ContentionResolutionTimer as defined in Section 5.1.5
if (is_msg3) {
harq_entity->timers_db->get(mac::CONTENTION_TIMER)->reset();
}
}
void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, ul_buffer* ul)
{
generate_retx(tti_tx, NULL, ul);
}
// New transmission (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, uint8_t *pdu_payload, bool is_msg3_, ul_sched_grant* ul_grant, ul_buffer* ul)
{
if (ul_grant && pdu_payload) {
srslte_softbuffer_tx_reset(&softbuffer);
// Store the uplink grant
memcpy(&cur_grant, ul_grant, sizeof(ul_sched_grant));
harq_feedback = false;
is_grant_configured = true;
current_tx_nb = 0;
current_irv = 0;
is_msg3 = is_msg3_;
generate_tx(tti_tx, pdu_payload, ul);
}
}
// Transmission of pending frame (Section 5.4.2.2)
void ul_harq_entity::ul_harq_process::generate_tx(uint32_t tti_tx, uint8_t *pdu_payload, ul_buffer* ul)
{
cur_grant.set_rv(get_rv());
ul->set_current_tx_nb(current_tx_nb);
ul->generate_data(&cur_grant, &softbuffer, pdu_payload);
current_irv = (current_irv+1)%4;
tti_last_tx = tti_tx;
if (is_msg3) {
if (current_tx_nb == harq_entity->params_db->get_param(mac_params::HARQ_MAXMSG3TX)) {
Info("Maximum number of ReTX for Msg3 reached (%d). Discarting TB.\n", harq_entity->params_db->get_param(mac_params::HARQ_MAXMSG3TX));
reset();
}
} else {
if (current_tx_nb == harq_entity->params_db->get_param(mac_params::HARQ_MAXTX)) {
Info("Maximum number of ReTX reached (%d). Discarting TB.\n", harq_entity->params_db->get_param(mac_params::HARQ_MAXTX));
reset();
}
}
}
uint32_t ul_harq_entity::ul_harq_process::last_tx_tti()
{
return tti_last_tx;
}
}
}

@ -0,0 +1,28 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
FIND_PACKAGE(openLTE)
IF(UHD_FOUND AND OPENLTE_FOUND)
INCLUDE_DIRECTORIES(${OPENLTE_INCLUDE_DIRS})
ADD_EXECUTABLE(mac_test mac_test.cc)
TARGET_LINK_LIBRARIES(mac_test srsapps_ue_mac srsapps_ue_phy srsapps_radio srslte ${OPENLTE_LIBRARIES} srslte_uhd)
ENDIF(UHD_FOUND AND OPENLTE_FOUND)

@ -0,0 +1,359 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <unistd.h>
#include "liblte_rrc.h"
#include "srsapps/radio/radio_uhd.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/tti_sync_cv.h"
#include "srsapps/common/log_stdout.h"
#include "srsapps/ue/mac/mac.h"
/**********************************************************************
* Program arguments processing
***********************************************************************/
typedef struct {
float uhd_rx_freq;
float uhd_tx_freq;
float uhd_rx_gain;
float uhd_tx_gain;
int verbose;
}prog_args_t;
void args_default(prog_args_t *args) {
args->uhd_rx_freq = -1.0;
args->uhd_tx_freq = -1.0;
args->uhd_rx_gain = -1; // set to autogain
args->uhd_tx_gain = -1;
args->verbose = 0;
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [gv] -f rx_frequency (in Hz) -F tx_frequency (in Hz)\n", prog);
printf("\t-g UHD RX gain [Default AGC]\n");
printf("\t-G UHD TX gain [Default same as RX gain (AGC)]\n");
printf("\t-v [increase verbosity, default none]\n");
}
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "gGfFv")) != -1) {
switch (opt) {
case 'g':
args->uhd_rx_gain = atof(argv[optind]);
break;
case 'G':
args->uhd_tx_gain = atof(argv[optind]);
break;
case 'f':
args->uhd_rx_freq = atof(argv[optind]);
break;
case 'F':
args->uhd_tx_freq = atof(argv[optind]);
break;
case 'v':
args->verbose++;
break;
default:
usage(args, argv[0]);
exit(-1);
}
}
if (args->uhd_rx_freq < 0 || args->uhd_tx_freq < 0) {
usage(args, argv[0]);
exit(-1);
}
}
// Determine SI messages scheduling as in 36.331 5.2.3 Acquisition of an SI message
uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) {
return (period*10*(1+tti/(period*10))+x)%10240; // the 1 means next opportunity
}
void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::ue::mac *mac, srslte::ue::phy *phy) {
// RACH-CONFIGCOMMON
if (sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.present) {
mac->set_param(srslte::ue::mac_params::RA_NOFGROUPAPREAMBLES,
liblte_rrc_message_size_group_a_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.size_of_ra]);
mac->set_param(srslte::ue::mac_params::RA_MESSAGESIZEA,
liblte_rrc_message_size_group_a_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_size]);
mac->set_param(srslte::ue::mac_params::RA_MESSAGEPOWEROFFSETB,
liblte_rrc_message_power_offset_group_b_num[sib2->rr_config_common_sib.rach_cnfg.preambles_group_a_cnfg.msg_pwr_offset_group_b]);
}
mac->set_param(srslte::ue::mac_params::RA_NOFPREAMBLES,
liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles]);
mac->set_param(srslte::ue::mac_params::RA_POWERRAMPINGSTEP,
liblte_rrc_power_ramping_step_num[sib2->rr_config_common_sib.rach_cnfg.pwr_ramping_step]);
mac->set_param(srslte::ue::mac_params::RA_INITRECEIVEDPOWER,
liblte_rrc_preamble_initial_received_target_power_num[sib2->rr_config_common_sib.rach_cnfg.preamble_init_rx_target_pwr]);
mac->set_param(srslte::ue::mac_params::RA_PREAMBLETRANSMAX,
liblte_rrc_preamble_trans_max_num[sib2->rr_config_common_sib.rach_cnfg.preamble_trans_max]);
mac->set_param(srslte::ue::mac_params::RA_RESPONSEWINDOW,
liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size]);
mac->set_param(srslte::ue::mac_params::RA_CONTENTIONTIMER,
liblte_rrc_mac_contention_resolution_timer_num[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]);
mac->set_param(srslte::ue::mac_params::HARQ_MAXMSG3TX,
sib2->rr_config_common_sib.rach_cnfg.max_harq_msg3_tx);
printf("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms\n",
liblte_rrc_number_of_ra_preambles_num[sib2->rr_config_common_sib.rach_cnfg.num_ra_preambles],
liblte_rrc_ra_response_window_size_num[sib2->rr_config_common_sib.rach_cnfg.ra_resp_win_size],
liblte_rrc_mac_contention_resolution_timer_num[sib2->rr_config_common_sib.rach_cnfg.mac_con_res_timer]);
// PDSCH ConfigCommon
mac->set_param(srslte::ue::mac_params::PDSCH_RSPOWER,
sib2->rr_config_common_sib.pdsch_cnfg.rs_power);
mac->set_param(srslte::ue::mac_params::PDSCH_PB,
sib2->rr_config_common_sib.pdsch_cnfg.p_b);
// PUSCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUSCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUSCH_EN_64QAM,
sib2->rr_config_common_sib.pusch_cnfg.enable_64_qam);
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_OFFSET,
sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset);
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_N_SB,
sib2->rr_config_common_sib.pusch_cnfg.n_sb);
phy->set_param(srslte::ue::phy_params::PUSCH_HOPPING_INTRA_SF,
sib2->rr_config_common_sib.pusch_cnfg.hopping_mode == LIBLTE_RRC_HOPPING_MODE_INTRA_AND_INTER_SUBFRAME?1:0);
phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_HOPPING_EN,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled?1:0);
phy->set_param(srslte::ue::phy_params::PUSCH_RS_SEQUENCE_HOPPING_EN,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled?1:0);
phy->set_param(srslte::ue::phy_params::PUSCH_RS_CYCLIC_SHIFT,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift);
phy->set_param(srslte::ue::phy_params::PUSCH_RS_GROUP_ASSIGNMENT,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch);
printf("Set PUSCH ConfigCommon: HopOffset=%d, RSGroup=%d, RSNcs=%d, N_sb=%d\n",
sib2->rr_config_common_sib.pusch_cnfg.pusch_hopping_offset,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.group_assignment_pusch,
sib2->rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift,
sib2->rr_config_common_sib.pusch_cnfg.n_sb);
// PUCCH ConfigCommon
phy->set_param(srslte::ue::phy_params::PUCCH_BETA, 10);
phy->set_param(srslte::ue::phy_params::PUCCH_DELTA_SHIFT,
liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift]);
phy->set_param(srslte::ue::phy_params::PUCCH_CYCLIC_SHIFT,
sib2->rr_config_common_sib.pucch_cnfg.n_cs_an);
phy->set_param(srslte::ue::phy_params::PUCCH_N_PUCCH_1,
sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an);
phy->set_param(srslte::ue::phy_params::PUCCH_N_RB_2,
sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi);
printf("Set PUCCH ConfigCommon: DeltaShift=%d, CyclicShift=%d, N1=%d, NRB=%d\n",
liblte_rrc_delta_pucch_shift_num[sib2->rr_config_common_sib.pucch_cnfg.delta_pucch_shift],
sib2->rr_config_common_sib.pucch_cnfg.n_cs_an,
sib2->rr_config_common_sib.pucch_cnfg.n1_pucch_an,
sib2->rr_config_common_sib.pucch_cnfg.n_rb_cqi);
// PRACH Configcommon
phy->set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX,
sib2->rr_config_common_sib.prach_cnfg.root_sequence_index);
phy->set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag?1:0);
phy->set_param(srslte::ue::phy_params::PRACH_FREQ_OFFSET,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset);
phy->set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config);
phy->set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index);
printf("Set PRACH ConfigCommon: SeqIdx=%d, HS=%d, FreqOffset=%d, ZC=%d, ConfigIndex=%d\n",
sib2->rr_config_common_sib.prach_cnfg.root_sequence_index,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.high_speed_flag?1:0,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_freq_offset,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.zero_correlation_zone_config,
sib2->rr_config_common_sib.prach_cnfg.prach_cnfg_info.prach_config_index);
}
void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac *mac, srslte::ue::phy *phy) {
mac->set_param(srslte::ue::mac_params::HARQ_MAXTX,
liblte_rrc_max_harq_tx_num[msg->rr_cnfg.mac_main_cnfg.explicit_value.ulsch_cnfg.max_harq_tx]);
phy->set_param(srslte::ue::phy_params::SR_PUCCH_RESINDEX,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx);
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
mac->set_param(srslte::ue::mac_params::SR_TRANS_MAX,
liblte_rrc_dsr_trans_max_num[msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.dsr_trans_max]);
mac->set_param(srslte::ue::mac_params::SR_PUCCH_CONFIGURED, 1);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_ACK, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ack_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_CQI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_cqi_idx);
phy->set_param(srslte::ue::phy_params::UCI_I_OFFSET_RI, msg->rr_cnfg.phy_cnfg_ded.pusch_cnfg_ded.beta_offset_ri_idx);
}
int main(int argc, char *argv[])
{
prog_args_t prog_args;
srslte::ue::tti_sync_cv ttisync(10240);
srslte::radio_uhd radio_uhd;
srslte::ue::phy phy;
srslte::ue::mac mac;
srslte::log_stdout mac_log("MAC"), phy_log("PHY");
parse_args(&prog_args, argc, argv);
switch (prog_args.verbose) {
case 1:
mac_log.set_level_info();
phy_log.set_level_info();
break;
case 2:
mac_log.set_level_debug();
phy_log.set_level_debug();
break;
}
// Init Radio and PHY
if (prog_args.uhd_rx_gain > 0 && prog_args.uhd_tx_gain > 0) {
radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_rx_gain);
radio_uhd.set_tx_gain(prog_args.uhd_tx_gain);
phy.init(&radio_uhd, &ttisync, &phy_log);
} else {
radio_uhd.init_agc();
radio_uhd.set_tx_rx_gain_offset(-10);
phy.init_agc(&radio_uhd, &ttisync, &phy_log);
}
// Init MAC
mac.init(&phy, &ttisync, &mac_log);
// Set RX freq
radio_uhd.set_rx_freq(prog_args.uhd_rx_freq);
radio_uhd.set_tx_freq(prog_args.uhd_tx_freq);
LIBLTE_BIT_MSG_STRUCT bit_msg;
LIBLTE_RRC_MIB_STRUCT bch_msg;
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg;
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
uint32_t si_window_len, sib2_period;
int tti;
enum {START, SIB1, SIB2, CONNECT} state = START;
int n;
while(1) {
switch(state) {
case START:
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
if (n > 0) {
bit_msg.N_bits = n;
liblte_rrc_unpack_bcch_bch_msg(&bit_msg, &bch_msg);
printf("MIB received %d bytes, BW=%s\n", n, liblte_rrc_dl_bandwidth_text[bch_msg.dl_bw]);
state = SIB1;
}
break;
case SIB1:
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
if (n > 0) {
bit_msg.N_bits = n;
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg);
si_window_len = liblte_rrc_si_window_length_num[dlsch_msg.sibs[0].sib.sib1.si_window_length];
sib2_period = liblte_rrc_si_periodicity_num[dlsch_msg.sibs[0].sib.sib1.sched_info[0].si_periodicity];
printf("SIB1 received %d bytes, CellID=%d, si_window=%d, sib2_period=%d\n",
n/8, dlsch_msg.sibs[0].sib.sib1.cell_id&0xfff, si_window_len, sib2_period);
state = SIB2;
} else {
tti = mac.get_tti();
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, 2, 5));
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_LEN, 1);
}
break;
case SIB2:
n = mac.recv_bcch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
if (n > 0) {
// Process SIB2
bit_msg.N_bits = n;
liblte_rrc_unpack_bcch_dlsch_msg(&bit_msg, &dlsch_msg);
printf("SIB2 received %d bytes\n", n/8);
setup_mac_phy_sib2(&dlsch_msg.sibs[0].sib.sib2, &mac, &phy);
// Prepare ConnectionRequest packet
ul_ccch_msg.msg_type = LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ;
ul_ccch_msg.msg.rrc_con_req.ue_id_type = LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE;
ul_ccch_msg.msg.rrc_con_req.ue_id.random = 1000;
ul_ccch_msg.msg.rrc_con_req.cause = LIBLTE_RRC_CON_REQ_EST_CAUSE_MO_DATA;
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, &bit_msg);
uint64_t uecri=0;
uint8_t *ue_cri_ptr = (uint8_t*) &uecri;
uint32_t nbytes = bit_msg.N_bits/8;
uint8_t *ptr = bit_msg.msg;
for (int i=0;i<nbytes;i++) {
ue_cri_ptr[nbytes-i-1] = (uint8_t) srslte_bit_unpack(&ptr, 8);
}
mac.set_param(srslte::ue::mac_params::CONTENTION_ID, uecri);
// Send ConnectionRequest Packet
printf("Send ConnectionRequest %d bytes\n", nbytes);
mac.send_ccch_sdu(bit_msg.msg, bit_msg.N_bits);
state = CONNECT;
} else {
tti = mac.get_tti();
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_ST, sib_start_tti(tti, sib2_period, 0));
mac.set_param(srslte::ue::mac_params::BCCH_SI_WINDOW_LEN, si_window_len);
}
break;
case CONNECT:
// Waint for Connection Setup
n = mac.recv_ccch_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE);
if (n > 0) {
printf("ConnSetup received %d bytes\n", n/8);
bit_msg.N_bits = n;
liblte_rrc_unpack_dl_ccch_msg(&bit_msg, &dl_ccch_msg);
printf("Response: %s\n", liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg.msg_type]);
switch (dl_ccch_msg.msg_type) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
// Process ConnectionSetup
process_connsetup(&dl_ccch_msg.msg.rrc_con_setup, &mac, &phy);
break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
mac.set_param(srslte::ue::mac_params::RNTI_C, 0);
break;
}
// exit(0);
}
break;
}
usleep(10000);
}
}

@ -0,0 +1,38 @@
#
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE 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.
#
# srsLTE 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.
#
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
INSTALL(DIRECTORY include/
DESTINATION "${INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE
)
FILE(GLOB SOURCES "src/*.cc")
ADD_LIBRARY(srsapps_ue_phy SHARED ${SOURCES})
TARGET_LINK_LIBRARIES(srsapps_ue_phy srsapps_common)
INSTALL(TARGETS srsapps_ue_phy DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srsapps_ue_phy)
FILE(GLOB HEADERS_ALL "include/srsapps/ue/phy/*.h")
ADD_CUSTOM_TARGET (add_ue_phy_headers SOURCES ${HEADERS_ALL})
ADD_SUBDIRECTORY(test)

@ -1,8 +1,8 @@
/**
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,26 +10,29 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/ue_itf/ul_sched_grant.h"
#include "srslte/ue_itf/dl_sched_grant.h"
#include "srslte/ue_itf/phy_params.h"
#include "srsapps/common/log.h"
#include "srsapps/common/queue.h"
#include "srsapps/ue/phy/ul_sched_grant.h"
#include "srsapps/ue/phy/dl_sched_grant.h"
#include "srsapps/ue/phy/phy_params.h"
#ifndef UEDLBUFFER_H
#define UEDLBUFFER_H
@ -40,38 +43,27 @@ namespace ue {
/* Class for the processing of Downlink buffers. The MAC obtains a buffer for a given TTI and then
* gets ul/dl scheduling grants and/or processes phich/pdsch channels
*/
class SRSLTE_API dl_buffer : public queue::element {
class dl_buffer : public queue::element {
public:
typedef enum {
PDCCH_UL_SEARCH_CRNTI = 0,
PDCCH_UL_SEARCH_RA_PROC,
PDCCH_UL_SEARCH_SPS,
PDCCH_UL_SEARCH_TEMPORAL,
PDCCH_UL_SEARCH_TPC_PUSCH,
PDCCH_UL_SEARCH_TPC_PUCCH
} pdcch_ul_search_t;
typedef enum {
PDCCH_DL_SEARCH_CRNTI = 0,
PDCCH_DL_SEARCH_SIRNTI,
PDCCH_DL_SEARCH_PRNTI,
PDCCH_DL_SEARCH_RARNTI,
PDCCH_DL_SEARCH_TEMPORAL,
PDCCH_DL_SEARCH_SPS
} pdcch_dl_search_t;
int buffer_id;
bool init_cell(srslte_cell_t cell, phy_params *params_db);
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h_);
void free_cell();
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time);
bool get_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant);
bool get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant);
bool get_ul_grant(ul_sched_grant *grant);
bool get_dl_grant(dl_sched_grant *grant);
void discard_pending_rar_grant();
void set_rar_grant(srslte_dci_rar_grant_t *rar_grant);
void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]);
void reset_softbuffer();
bool decode_ack(ul_sched_grant *pusch_grant);
bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK
bool decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload);
private:
phy_params *params_db;
log *log_h;
srslte_cell_t cell;
srslte_ue_dl_t ue_dl;
srslte_phich_t phich;
@ -79,6 +71,8 @@ namespace ue {
uint32_t cfi;
bool sf_symbols_and_ce_done;
bool pdcch_llr_extracted;
bool pending_rar_grant;
srslte_dci_rar_grant_t rar_grant;
};
}
}

@ -1,8 +1,8 @@
/**
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,24 +10,27 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <string.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srsapps/ue/phy/sched_grant.h"
#ifndef UEDLSCHEDGRANT_H
#define UEDLSCHEDGRANT_H
@ -36,9 +39,10 @@ namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class SRSLTE_API dl_sched_grant : public sched_grant {
class dl_sched_grant : public sched_grant {
public:
dl_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {}
dl_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
uint32_t get_rv() {

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,30 +10,34 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srslte/ue_itf/tti_sync.h"
#include "srslte/ue_itf/dl_buffer.h"
#include "srslte/ue_itf/ul_buffer.h"
#include "srslte/ue_itf/prach.h"
#include "srslte/ue_itf/phy_params.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/common/radio.h"
#include "srsapps/common/log.h"
#include "srsapps/common/tti_sync.h"
#include "srsapps/ue/phy/dl_buffer.h"
#include "srsapps/ue/phy/ul_buffer.h"
#include "srsapps/ue/phy/prach.h"
#include "srsapps/ue/phy/phy_params.h"
#include "srsapps/ue/phy/sched_grant.h"
#include "srsapps/common/queue.h"
#include "srsapps/radio/radio.h"
#ifndef UEPHY_H
#define UEPHY_H
@ -56,15 +60,13 @@ namespace ue {
typedef _Complex float cf_t;
class SRSLTE_API phy
class phy
{
public:
phy() {
started = false;
is_sfn_synched = false;
cell_is_set = false;
}
bool init(radio *radio_handler, tti_sync *ttisync);
phy();
void set();
bool init(radio *radio_handler, tti_sync *ttisync, log *log_h);
bool init_agc(radio *radio_handler, tti_sync *ttisync, log *log_h);
void stop();
// These functions can be called only if PHY is in IDLE (ie, not RX/TX)
@ -77,8 +79,16 @@ public:
bool start_rxtx();
bool stop_rxtx();
float get_agc_gain();
// Indicate the PHY to send PRACH as soon as possible
bool init_prach();
bool send_prach(uint32_t preamble_idx);
bool send_prach(uint32_t preamble_idx, int allowed_subframe);
bool send_prach(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm);
// Indicate the PHY to send SR as soon as possible or not
void send_sr(bool enable);
// Returns TTI when PRACH was transmitted. -1 if not yet transmitted
int get_prach_transmitted_tti();
@ -90,7 +100,7 @@ public:
void set_timeadv_rar(uint32_t ta_cmd);
void set_timeadv(uint32_t ta_cmd);
// Generate Msg3 UL grant from RAR
// Convert Msg3 UL grant to ul_sched_grant
void rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant);
// Get status
@ -115,11 +125,12 @@ private:
tti_sync *ttisync;
radio *radio_handler;
log *log_h;
srslte_cell_t cell;
bool cell_is_set;
bool is_sfn_synched;
bool started;
volatile bool started;
srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib;
@ -135,11 +146,20 @@ private:
bool radio_is_streaming;
srslte_timestamp_t last_rx_time;
float cellsearch_cfo;
bool do_agc;
double last_gain;
uint32_t sr_N_offset;
uint32_t sr_periodicity;
bool sr_enabled;
uint32_t sr_n_pucch;
bool sr_is_ready_to_send(uint32_t tti);
bool init_(radio *radio_handler, tti_sync *ttisync, log *log_h, bool do_agc);
static void *phy_thread_fnc(void *arg);
bool decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]);
int sync_sfn();
void run_rx_tx_state();
bool init_radio_handler(char *args);
ul_buffer* get_ul_buffer_adv(uint32_t tti);
};

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,23 +10,25 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srslte/ue_itf/params_db.h"
#include "srsapps/common/params_db.h"
#ifndef PHYPARAMS_H
#define PHYPARAMS_H
@ -35,7 +37,7 @@
namespace srslte {
namespace ue {
class SRSLTE_API phy_params : public params_db
class phy_params : public params_db
{
public:
@ -53,6 +55,7 @@ namespace ue {
CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, // integer that will be divided by 10
PUSCH_BETA,
PUSCH_EN_64QAM,
PUSCH_RS_GROUP_HOPPING_EN,
PUSCH_RS_SEQUENCE_HOPPING_EN,
PUSCH_RS_CYCLIC_SHIFT,
@ -61,7 +64,7 @@ namespace ue {
PUSCH_HOPPING_N_SB,
PUSCH_HOPPING_INTRA_SF,
PUSCH_HOPPING_OFFSET,
PUCCH_BETA,
PUCCH_DELTA_SHIFT,
PUCCH_CYCLIC_SHIFT,
@ -74,6 +77,9 @@ namespace ue {
PUCCH_N_PUCCH_2,
PUCCH_N_PUCCH_SR,
SR_PUCCH_RESINDEX,
SR_CONFIG_INDEX,
UCI_I_OFFSET_ACK,
UCI_I_OFFSET_RI,
UCI_I_OFFSET_CQI,

@ -1,8 +1,8 @@
/**
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,25 +10,28 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srslte/common/radio.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/ue_itf/phy_params.h"
#include "srsapps/radio/radio.h"
#include "srsapps/common/log.h"
#include "srsapps/common/queue.h"
#include "srsapps/ue/phy/phy_params.h"
#ifndef UEPRACH_H
#define UEPRACH_H
@ -36,23 +39,27 @@
namespace srslte {
namespace ue {
class SRSLTE_API prach {
class prach {
public:
prach() {
params_db = NULL;
initiated = false;
signal_buffer = NULL;
}
bool init_cell(srslte_cell_t cell, phy_params *params_db);
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h);
void free_cell();
bool prepare_to_send(uint32_t preamble_idx);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm);
bool is_ready_to_send(uint32_t current_tti);
int get_transmitted_tti();
bool send(srslte::radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
private:
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
phy_params *params_db = NULL;
log *log_h;
int preamble_idx;
int allowed_subframe;
bool initiated = false;
uint32_t len;
cf_t *buffer[64];

@ -0,0 +1,97 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srsapps/common/queue.h"
#ifndef UESCHEDGRANT_H
#define UESCHEDGRANT_H
namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class sched_grant {
public:
typedef enum {
RNTI_TYPE_NOTDEFINED = 0,
RNTI_TYPE_CRNTI,
RNTI_TYPE_RA,
RNTI_TYPE_SPS,
RNTI_TYPE_TEMP,
RNTI_TYPE_SIRNTI,
RNTI_TYPE_PRNTI,
RNTI_TYPE_TPC_PUSCH,
RNTI_TYPE_TPC_PUCCH
} rnti_type_t;
sched_grant(uint16_t rnti_) {
rnti = rnti_;
rnti_type = RNTI_TYPE_NOTDEFINED;
}
sched_grant(rnti_type_t rnti_type_, uint16_t rnti_) {
rnti = rnti_;
rnti_type = rnti_type_;
}
uint16_t get_rnti() {
return rnti;
}
bool is_temp_rnti() {
return rnti_type == RNTI_TYPE_TEMP;
}
bool is_crnti() {
return rnti_type == RNTI_TYPE_CRNTI;
}
bool is_ra_rnti() {
return rnti_type == RNTI_TYPE_RA;
}
bool is_SPS_rnti() {
return rnti_type == RNTI_TYPE_SPS;
}
bool is_sys_rnti() {
return (rnti_type == RNTI_TYPE_SIRNTI || rnti_type == RNTI_TYPE_PRNTI);
}
bool is_tpc_rnti() {
return (rnti_type == RNTI_TYPE_TPC_PUSCH || rnti_type == RNTI_TYPE_TPC_PUCCH);
}
virtual uint32_t get_rv() = 0;
virtual void set_rv(uint32_t rv) = 0;
virtual bool get_ndi() = 0;
virtual void set_ndi(bool value) = 0;
virtual bool is_sps_release() = 0;
virtual uint32_t get_tbs() = 0;
protected:
uint16_t rnti;
rnti_type_t rnti_type;
};
}
}
#endif

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,27 +10,29 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
#include "srslte/common/radio.h"
#include "srslte/ue_itf/queue.h"
#include "srslte/ue_itf/ul_sched_grant.h"
#include "srslte/ue_itf/dl_sched_grant.h"
#include "srslte/ue_itf/phy_params.h"
#include "srsapps/radio/radio.h"
#include "srsapps/common/log.h"
#include "srsapps/common/queue.h"
#include "srsapps/ue/phy/ul_sched_grant.h"
#include "srsapps/ue/phy/dl_sched_grant.h"
#include "srsapps/ue/phy/phy_params.h"
#ifndef UEULBUFFER_H
#define UEULBUFFER_H
@ -42,12 +44,11 @@ namespace ue {
/* Uplink scheduling assignment. The MAC instructs the PHY to prepare an UL packet (PUSCH or PUCCH)
* for transmission. The MAC must call generate_data() to set the packet ready for transmission
*/
class SRSLTE_API ul_buffer : public queue::element {
class ul_buffer : public queue::element {
public:
bool init_cell(srslte_cell_t cell, phy_params *params_db);
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h);
void free_cell();
void set_tti(uint32_t tti);
void set_current_tx_nb(uint32_t current_tx_nb);
bool generate_ack(bool ack, dl_sched_grant *last_dl_grant);
bool generate_ack(bool ack[2]);
@ -56,10 +57,12 @@ namespace ue {
bool uci_ready();
bool generate_data();
bool generate_data(ul_sched_grant *pusch_grant, uint8_t *payload);
bool generate_data(ul_sched_grant *pusch_grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload);
bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time);
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
private:
log *log_h;
phy_params *params_db;
srslte_cell_t cell;
srslte_ue_ul_t ue_ul;

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,24 +10,25 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <string.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srsapps/ue/phy/sched_grant.h"
#ifndef UEULSCHEDGRANT_H
#define UEULSCHEDGRANT_H
@ -36,9 +37,10 @@ namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class SRSLTE_API ul_sched_grant : public sched_grant {
class ul_sched_grant : public sched_grant {
public:
ul_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {}
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
uint32_t get_rv() {
@ -77,7 +79,11 @@ namespace ue {
uint32_t get_n_dmrs() {
return ul_dci.n_dmrs;
}
bool is_from_rar() {
return grant_is_from_rar;
}
bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) {
grant_is_from_rar = false;
if (srslte_dci_msg_to_ul_grant(msg, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
return false;
} else {
@ -88,6 +94,7 @@ namespace ue {
}
}
bool create_from_rar(srslte_dci_rar_grant_t *rar, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) {
grant_is_from_rar = true;
if (srslte_dci_rar_to_ul_grant(rar, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
return false;
} else {
@ -109,6 +116,7 @@ namespace ue {
srslte_ra_ul_dci_t ul_dci;
uint32_t current_tx_nb;
uint16_t rnti;
bool grant_is_from_rar;
};
}

@ -30,21 +30,24 @@
#include <pthread.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srslte/ue_itf/dl_buffer.h"
#include "srslte/ue_itf/phy.h"
#include "srslte/ue_itf/phy_params.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/sched_grant.h"
#include "srsapps/ue/phy/dl_buffer.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/phy_params.h"
namespace srslte {
namespace ue {
bool dl_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_)
bool dl_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
{
log_h = log_h_;
params_db = params_db_;
cell = cell_;
sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false;
pending_rar_grant = false;
tti = 0;
if (!srslte_ue_dl_init(&ue_dl, cell)) {
signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
@ -67,7 +70,6 @@ bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_t
{
bool ret = false;
if (signal_buffer) {
INFO("DL Buffer TTI %d: Receiving packet\n", tti);
cf_t *sf_buffer = NULL;
sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false;
@ -81,52 +83,72 @@ bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_t
return ret;
}
bool dl_buffer::get_ul_grant(pdcch_ul_search_t mode, ul_sched_grant *grant)
void dl_buffer::discard_pending_rar_grant() {
pending_rar_grant = false;
}
bool dl_buffer::get_ul_grant(ul_sched_grant *grant)
{
if (signal_buffer) {
if (!sf_symbols_and_ce_done) {
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
if (pending_rar_grant && grant->is_temp_rnti()) {
return grant->create_from_rar(&rar_grant, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
} else {
if (!sf_symbols_and_ce_done) {
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
sf_symbols_and_ce_done = true;
}
sf_symbols_and_ce_done = true;
}
if (!pdcch_llr_extracted) {
if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) {
if (!pdcch_llr_extracted) {
if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) {
return false;
}
pdcch_llr_extracted = true;
}
srslte_dci_msg_t dci_msg;
if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) {
return false;
}
pdcch_llr_extracted = true;
}
srslte_dci_msg_t dci_msg;
if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti())) {
return false;
}
return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
}
}
}
// Unpack RAR grant as defined in Section 6.2 of 36.213
void dl_buffer::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
{
pending_rar_grant = true;
srslte_dci_rar_grant_unpack(&rar_grant, grant_payload);
}
void dl_buffer::set_rar_grant(srslte_dci_rar_grant_t* rar_grant_)
{
pending_rar_grant = true;
memcpy(&rar_grant, rar_grant_, sizeof(srslte_dci_rar_grant_t));
}
bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, dl_sched_grant *grant)
bool dl_buffer::get_dl_grant(dl_sched_grant *grant)
{
if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Getting DL grant\n", tti);
Debug("DL Buffer TTI %d: Getting DL grant\n", tti);
if (!sf_symbols_and_ce_done) {
INFO("DL Buffer TTI %d: Getting DL grant. Calling fft estimate\n", tti);
Debug("DL Buffer TTI %d: Getting DL grant. Calling fft estimate\n", tti);
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
sf_symbols_and_ce_done = true;
}
if (!pdcch_llr_extracted) {
INFO("DL Buffer TTI %d: Getting DL grant. extracting LLR\n", tti);
Debug("DL Buffer TTI %d: Getting DL grant. extracting LLR\n", tti);
if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) {
return false;
}
pdcch_llr_extracted = true;
}
if (SRSLTE_VERBOSE_ISINFO()) {
if (SRSLTE_VERBOSE_ISDEBUG()) {
srslte_vec_save_file((char*) "ce1", ue_dl.ce[0], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t));
srslte_vec_save_file((char*) "ce2", ue_dl.ce[1], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t));
srslte_vec_save_file((char*) "pdcch_d", ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce*sizeof(cf_t));
@ -156,12 +178,22 @@ bool dl_buffer::decode_ack(ul_sched_grant *grant)
}
}
void dl_buffer::reset_softbuffer()
{
srslte_softbuffer_rx_reset(&ue_dl.softbuffer);
}
bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload)
{
return decode_data(grant, &ue_dl.softbuffer, payload);
}
bool dl_buffer::decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload)
{
if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti);
Debug("DL Buffer TTI %d: Decoding PDSCH\n", tti);
if (!sf_symbols_and_ce_done) {
INFO("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti);
Debug("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti);
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
@ -170,10 +202,10 @@ bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload)
grant->get_pdsch_cfg(tti%10, &ue_dl.pdsch_cfg);
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, &ue_dl.softbuffer, ue_dl.sf_symbols,
int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols,
ue_dl.ce, 0, grant->get_rnti(), payload);
if (SRSLTE_VERBOSE_ISINFO()) {
if (SRSLTE_VERBOSE_ISDEBUG()) {
srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.pdsch_cfg.grant.nof_re*sizeof(cf_t));
}
if (ret == SRSLTE_SUCCESS) {

@ -32,21 +32,42 @@
#include "srslte/srslte.h"
#include "srslte/ue_itf/phy.h"
#include "srslte/ue_itf/prach.h"
#include "srslte/ue_itf/ul_buffer.h"
#include "srslte/ue_itf/dl_buffer.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/prach.h"
#include "srsapps/ue/phy/ul_buffer.h"
#include "srsapps/ue/phy/dl_buffer.h"
namespace srslte {
namespace ue {
bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_)
phy::phy()
{
started = false;
is_sfn_synched = false;
cell_is_set = false;
phy_state = IDLE;
}
bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h) {
return init_(radio_handler_, ttisync_, log_h, false);
}
bool phy::init_agc(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h) {
return init_(radio_handler_, ttisync_, log_h, true);
}
bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h_, bool do_agc_)
{
started = false;
radio_is_streaming = false;
ttisync = ttisync_;
log_h = log_h_;
radio_handler = radio_handler_;
ul_buffer_queue = new queue(6, sizeof(ul_buffer));
dl_buffer_queue = new queue(6, sizeof(dl_buffer));
do_agc = do_agc_;
last_gain = 1e4;
// Set default params
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100);
@ -55,8 +76,7 @@ bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_)
pthread_attr_t attr;
struct sched_param param;
param.sched_priority = 99;
param.sched_priority = sched_get_priority_min(SCHED_FIFO) ;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &param);
@ -93,13 +113,13 @@ radio* phy::get_radio() {
void phy::set_timeadv_rar(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new_rar(ta_cmd);
time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS;
INFO("Set TA RAR: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
Info("Set TA RAR: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
}
void phy::set_timeadv(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new(n_ta, ta_cmd);
time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS;
INFO("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
Info("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
}
void phy::rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant)
@ -114,14 +134,66 @@ void phy::set_param(phy_params::phy_param_t param, int64_t value) {
// FIXME: Add PRACH power control
bool phy::send_prach(uint32_t preamble_idx)
bool phy::send_prach(uint32_t preamble_idx) {
return send_prach(preamble_idx, -1, 0);
}
bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe) {
return send_prach(preamble_idx, allowed_subframe, 0);
}
bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm)
{
if (phy_state == RXTX) {
return prach_buffer.prepare_to_send(preamble_idx);
return prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm);
}
return false;
}
/* Send SR as soon as possible as defined in Section 10.2 of 36.213 */
void phy::send_sr(bool enable)
{
if (enable) {
// Get sr_periodicity and sr_N_offset from table 10.1-5
uint32_t I_sr = params_db.get_param(phy_params::SR_CONFIG_INDEX);
if (I_sr < 5) {
sr_periodicity = 5;
sr_N_offset = I_sr;
} else if (I_sr < 15) {
sr_periodicity = 10;
sr_N_offset = I_sr-5;
} else if (I_sr < 35) {
sr_periodicity = 20;
sr_N_offset = I_sr-15;
} else if (I_sr < 75) {
sr_periodicity = 40;
sr_N_offset = I_sr-35;
} else if (I_sr < 155) {
sr_periodicity = 80;
sr_N_offset = I_sr-75;
} else if (I_sr < 157) {
sr_periodicity = 2;
sr_N_offset = I_sr-155;
} else if (I_sr == 157) {
sr_periodicity = 1;
sr_N_offset = I_sr-157;
} else {
Error("Invalid I_sr=%d\n", I_sr);
return;
}
sr_n_pucch = params_db.get_param(phy_params::SR_PUCCH_RESINDEX);
}
sr_enabled = enable;
}
bool phy::sr_is_ready_to_send(uint32_t tti_) {
if (sr_enabled) {
if ((10*tti_to_SFN(tti_)+tti_to_subf(tti_)-sr_N_offset)%sr_periodicity==0) {
return true;
}
}
return false;
}
int phy::get_prach_transmitted_tti()
{
return prach_buffer.get_transmitted_tti();
@ -147,10 +219,10 @@ bool phy::start_rxtx()
phy_state = RXTX;
return true;
} else {
fprintf(stderr, "Can not change state to RXTX: cell is not set\n");
Error("Can not change state to RXTX: cell is not set\n");
}
} else {
fprintf(stderr, "Can not change state to RXTX: invalid state %d\n", phy_state);
Error("Can not change state to RXTX: invalid state %d\n", phy_state);
}
return false;
}
@ -163,11 +235,16 @@ bool phy::stop_rxtx()
phy_state = IDLE;
return true;
} else {
fprintf(stderr, "Can not change state to RXTX: invalid state %d\n", phy_state);
Error("Can not change state to RXTX: invalid state %d\n", phy_state);
}
return false;
}
float phy::get_agc_gain()
{
return 10*log10(srslte_agc_get_gain(&ue_sync.agc));
}
bool phy::status_is_idle() {
return phy_state == IDLE;
}
@ -196,7 +273,13 @@ void* phy::phy_thread_fnc(void *arg) {
int radio_recv_wrapper_cs(void *h,void *data, uint32_t nsamples, srslte_timestamp_t *rx_time)
{
radio *radio_handler = (radio*) h;
return radio_handler->rx_now(data, nsamples, rx_time);
int n = radio_handler->rx_now(data, nsamples, rx_time);
return n;
}
double callback_set_rx_gain(void *h, double gain) {
radio *radio_handler = (radio*) h;
return radio_handler->set_rx_gain_th(gain);
}
bool phy::set_cell(srslte_cell_t cell_) {
@ -208,29 +291,35 @@ bool phy::set_cell(srslte_cell_t cell_) {
if (!srslte_ue_sync_init(&ue_sync, cell, radio_recv_wrapper_cs, radio_handler))
{
srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo);
if (prach_buffer.init_cell(cell, &params_db)) {
for(uint32_t i=0;i<6;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->init_cell(cell, &params_db);
((dl_buffer*) dl_buffer_queue->get(i))->init_cell(cell, &params_db);
((dl_buffer*) dl_buffer_queue->get(i))->buffer_id = i;
((ul_buffer*) ul_buffer_queue->get(i))->ready();
((dl_buffer*) dl_buffer_queue->get(i))->release();
}
cell_is_set = true;
if (do_agc) {
srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, last_gain);
}
srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo);
for(uint32_t i=0;i<6;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->init_cell(cell, &params_db, log_h);
((dl_buffer*) dl_buffer_queue->get(i))->init_cell(cell, &params_db, log_h);
((dl_buffer*) dl_buffer_queue->get(i))->buffer_id = i;
((ul_buffer*) ul_buffer_queue->get(i))->ready();
((dl_buffer*) dl_buffer_queue->get(i))->release();
}
cell_is_set = true;
} else {
fprintf(stderr, "Error setting cell: initiating ue_sync");
Error("Error setting cell: initiating ue_sync");
}
} else {
fprintf(stderr, "Error setting cell: initiating ue_mib\n");
Error("Error setting cell: initiating ue_mib\n");
}
} else {
fprintf(stderr, "Error setting cell: Invalid state %d\n", phy_state);
Error("Error setting cell: Invalid state %d\n", phy_state);
}
return cell_is_set;
}
bool phy::init_prach() {
return prach_buffer.init_cell(cell, &params_db, log_h);
}
ul_buffer* phy::get_ul_buffer(uint32_t tti)
{
return (ul_buffer*) ul_buffer_queue->get(tti);
@ -243,6 +332,9 @@ ul_buffer* phy::get_ul_buffer_adv(uint32_t tti)
dl_buffer* phy::get_dl_buffer(uint32_t tti)
{
if (tti + 6 < get_current_tti()) {
Warning("Warning access to PHY too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti());
}
return (dl_buffer*) dl_buffer_queue->get(tti);
}
@ -265,6 +357,11 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b
return false;
}
if (do_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain);
}
srslte_ue_cellsearch_set_nof_frames_to_scan(&cs, params_db.get_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES));
srslte_ue_cellsearch_set_threshold(&cs, (float)
params_db.get_param(phy_params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD)/10);
@ -282,23 +379,25 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b
ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell);
}
last_gain = srslte_agc_get_gain(&cs.ue_sync.agc);
radio_handler->stop_rx();
srslte_ue_cellsearch_free(&cs);
if (ret < 0) {
fprintf(stderr, "Error decoding MIB: Error searching PSS\n");
Error("Error decoding MIB: Error searching PSS\n");
return false;
} else if (ret == 0) {
fprintf(stderr, "Error decoding MIB: Could not find any PSS in this frequency\n");
Error("Error decoding MIB: Could not find any PSS in this frequency\n");
return false;
}
// Save result
cell_ptr->id = found_cells[max_peak_cell].cell_id;
cell_ptr->cp = found_cells[max_peak_cell].cp;
cellsearch_cfo = found_cells[max_peak_cell].cfo;
INFO("\nFound CELL ID: %d CP: %s, CFO: %f\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp), cellsearch_cfo);
Info("\nFound CELL ID: %d CP: %s, CFO: %f\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp), cellsearch_cfo);
srslte_ue_mib_sync_t ue_mib_sync;
@ -306,6 +405,10 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b
return false;
}
if (do_agc) {
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, last_gain);
}
/* Find and decode MIB */
uint32_t sfn, sfn_offset;
@ -313,13 +416,15 @@ bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t b
ret = srslte_ue_mib_sync_decode(&ue_mib_sync, params_db.get_param(phy_params::CELLSEARCH_TIMEOUT_MIB_NFRAMES),
bch_payload, &cell_ptr->nof_ports, &sfn_offset);
radio_handler->stop_rx();
last_gain = srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc);
srslte_ue_mib_sync_free(&ue_mib_sync);
if (ret == 1) {
srslte_pbch_mib_unpack(bch_payload, cell_ptr, NULL);
return true;
} else {
printf("Error decoding MIB: Error decoding PBCH\n");
Warning("Error decoding MIB: Error decoding PBCH\n");
return false;
}
}
@ -334,7 +439,7 @@ int phy::sync_sfn(void) {
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer);
if (ret < 0) {
fprintf(stderr, "Error calling ue_sync_get_buffer");
Error("Error calling ue_sync_get_buffer");
return -1;
}
@ -344,7 +449,7 @@ int phy::sync_sfn(void) {
srslte_pbch_decode_reset(&ue_mib.pbch);
int n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding MIB while synchronising SFN");
Error("Error decoding MIB while synchronising SFN");
return -1;
} else if (n == SRSLTE_UE_MIB_FOUND) {
uint32_t sfn;
@ -383,6 +488,7 @@ void phy::run_rx_tx_state()
}
} else {
uint32_t current_tti = ttisync->get_producer_cntr();
log_h->step(current_tti);
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
// Prepare transmission for the next tti
@ -392,6 +498,9 @@ void phy::run_rx_tx_state()
if (prach_buffer.is_ready_to_send(current_tti)) {
prach_buffer.send(radio_handler, cfo, last_rx_time);
}
if (sr_is_ready_to_send(current_tti+ul_buffer::tx_advance_sf)) {
get_ul_buffer_adv(current_tti)->generate_sr();
}
// send ul buffer if we have to
if (get_ul_buffer_adv(current_tti)->is_released() || get_ul_buffer_adv(current_tti)->uci_ready()) {
// Generate PUCCH if no UL grant

@ -30,10 +30,10 @@
#include <pthread.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/ue_itf/prach.h"
#include "srslte/ue_itf/phy.h"
#include "srslte/ue_itf/phy_params.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/prach.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/phy_params.h"
namespace srslte {
namespace ue {
@ -42,10 +42,10 @@ namespace ue {
void prach::free_cell()
{
if (initiated) {
for (uint32_t i=0;i<64;i++) {
for (int i=0;i<64;i++) {
if (buffer[i]) {
free(buffer[i]);
}
free(buffer[i]);
}
}
if (signal_buffer) {
free(signal_buffer);
@ -55,9 +55,10 @@ void prach::free_cell()
}
}
bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
{
cell = cell_;
log_h = log_h_;
params_db = params_db_;
preamble_idx = -1;
if (srslte_prach_init(&prach_obj, srslte_symbol_sz(cell.nof_prb),
@ -69,12 +70,12 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
}
len = prach_obj.N_seq + prach_obj.N_cp;
for (uint32_t i=0;i<64;i++) {
for (int i=0;i<64;i++) {
buffer[i] = (cf_t*) srslte_vec_malloc(len*sizeof(cf_t));
if(!buffer[i]) {
return false;
}
if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])){
}
if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])) {
return false;
}
}
@ -85,12 +86,19 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_)
return initiated;
}
bool prach::prepare_to_send(uint32_t preamble_idx_)
bool prach::prepare_to_send(uint32_t preamble_idx_) {
return prepare_to_send(preamble_idx_, -1, 0);
}
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_) {
return prepare_to_send(preamble_idx_, allowed_subframe_, 0);
}
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, int target_power_dbm)
{
if (initiated && preamble_idx_ < 64) {
preamble_idx = preamble_idx_;
allowed_subframe = allowed_subframe_;
transmitted_tti = -1;
INFO("PRACH Buffer: Prepare to send preamble %d\n", preamble_idx);
Info("PRACH Buffer: Prepare to send preamble %d\n", preamble_idx);
return true;
} else {
return false;
@ -112,15 +120,16 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
srslte_prach_sf_config_t sf_config;
srslte_prach_sf_config(config_idx, &sf_config);
for (int i=0;i<sf_config.nof_sf;i++) {
if ((current_tti%10) == sf_config.sf[i]) {
INFO("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
if ((current_tti%10) == sf_config.sf[i] && allowed_subframe == -1 ||
((current_tti%10) == sf_config.sf[i] && (current_tti%10) == allowed_subframe))
{
Info("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
transmitted_tti = current_tti;
return true;
}
}
}
}
INFO("PRACH Buffer: Not ready to send at tti: %d\n", current_tti_);
return false;
}
@ -140,12 +149,12 @@ bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time)
srslte_timestamp_add(&tx_time, 0, 1e-3*tx_advance_sf);
// Correct CFO before transmission
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 2*cfo / srslte_symbol_sz(cell.nof_prb));
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo /srslte_symbol_sz(cell.nof_prb));
// transmit
radio_handler->tx(signal_buffer, len, tx_time);
INFO("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n", cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs);
//srslte_vec_save_file("prach", buffer[preamble_idx], len*sizeof(cf_t));
Info("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n",
cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs);
preamble_idx = -1;
}

@ -28,18 +28,22 @@
#include <string.h>
#include <strings.h>
#include <pthread.h>
#include <math.h>
#include "srslte/srslte.h"
#include "srslte/ue_itf/sched_grant.h"
#include "srslte/ue_itf/ul_buffer.h"
#include "srslte/ue_itf/phy.h"
#include "srslte/ue_itf/phy_params.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/sched_grant.h"
#include "srsapps/ue/phy/ul_buffer.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/phy_params.h"
namespace srslte {
namespace ue {
bool ul_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_) {
bool ul_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_) {
cell = cell_;
log_h = log_h_;
params_db = params_db_;
current_tx_nb = 0;
if (!srslte_ue_ul_init(&ue_ul, cell)) {
@ -79,9 +83,20 @@ bool ul_buffer::generate_ack(bool ack[2])
uci_pending = true;
}
void ul_buffer::set_current_tx_nb(uint32_t current_tx_nb_)
{
current_tx_nb = current_tx_nb_;
}
bool ul_buffer::generate_cqi_report()
{
return false;
}
bool ul_buffer::generate_sr() {
uci_data.scheduling_request = true;
uci_pending = true;
return true;
}
bool ul_buffer::uci_ready() {
@ -89,12 +104,16 @@ bool ul_buffer::uci_ready() {
}
bool ul_buffer::generate_data() {
ul_sched_grant dummy(0);
return generate_data(&dummy, NULL);
return generate_data(NULL, NULL);
}
bool ul_buffer::generate_data(ul_sched_grant *grant,
uint8_t *payload)
{
generate_data(grant, &ue_ul.softbuffer, payload);
}
bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload)
{
if (is_ready()) {
@ -109,13 +128,15 @@ bool ul_buffer::generate_data(ul_sched_grant *grant,
dmrs_cfg.delta_ss = params_db->get_param(phy_params::PUSCH_RS_GROUP_ASSIGNMENT);
srslte_pusch_hopping_cfg_t pusch_hopping;
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t));
pusch_hopping.n_sb = params_db->get_param(phy_params::PUSCH_HOPPING_N_SB);
pusch_hopping.hop_mode = params_db->get_param(phy_params::PUSCH_HOPPING_INTRA_SF) ?
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = grant->get_current_tx_nb();
if (grant) {
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t));
pusch_hopping.n_sb = params_db->get_param(phy_params::PUSCH_HOPPING_N_SB);
pusch_hopping.hop_mode = params_db->get_param(phy_params::PUSCH_HOPPING_INTRA_SF) ?
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = grant->get_current_tx_nb();
}
srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
@ -124,7 +145,7 @@ bool ul_buffer::generate_data(ul_sched_grant *grant,
pucch_cfg.group_hopping_en = dmrs_cfg.group_hopping_en;
pucch_cfg.N_cs = params_db->get_param(phy_params::PUCCH_CYCLIC_SHIFT);
pucch_cfg.n_rb_2 = params_db->get_param(phy_params::PUCCH_N_RB_2);
srslte_pucch_sched_t pucch_sched;
bzero(&pucch_sched, sizeof(srslte_pucch_sched_t));
pucch_sched.n_cce = last_n_cce;
@ -144,14 +165,24 @@ bool ul_buffer::generate_data(ul_sched_grant *grant,
int n = 0;
// Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (payload) {
if (grant) {
INFO("Encoding PUSCH TBS=%d, rb_start=%d n_prb=%d, rv=%d, rnti=%d\n",
grant->get_tbs(), pusch_cfg.grant.L_prb, pusch_cfg.grant.n_prb[0], grant->get_rv(), grant->get_rnti());
grant->to_pusch_cfg(tti%10, cell.cp, &pusch_cfg);
n = srslte_ue_ul_pusch_encode_cfg(&ue_ul, &pusch_cfg,
payload, uci_data,
softbuffer,
grant->get_rnti(),
signal_buffer);
if (grant->get_rv() == 0) {
bzero(signal_buffer, 7680*sizeof(cf_t));
}
} else {
Info("Encoding PUCCH n_cce=%d, ack=%d\n", last_n_cce, uci_data.uci_ack);
n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer);
}
// Reset UCI data
@ -176,16 +207,32 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo
srslte_timestamp_t tx_time;
srslte_timestamp_copy(&tx_time, &rx_time);
srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec);
INFO("Send PUSCH TTI: %d, CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us\n",
tti, cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb),
// Compute peak
#ifdef compute_peak
if (SRSLTE_VERBOSE_ISINFO()) {
float max = 0;
float *t = (float*) signal_buffer;
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
}
}
}
#endif
Info("TX CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us\n",
cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb),
srslte_timestamp_real(&rx_time),
srslte_timestamp_real(&tx_time), time_adv_sec*1000000);
// Correct CFO before transmission
srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb));
radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time);
//srslte_vec_save_file("pucch_tx", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
ready();
}

@ -1,30 +1,29 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# 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.
#
# srsLTE 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.
# GNU Affero General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND)
IF(${CUHD_FIND} GREATER -1)
IF(UHD_FOUND)
ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc)
TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srslte++ cuhd)
TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ADD_EXECUTABLE(ue_itf_test_prach ue_itf_test_prach.cc)
TARGET_LINK_LIBRARIES(ue_itf_test_prach srslte++ cuhd)
ENDIF(${CUHD_FIND} GREATER -1)
TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ENDIF(UHD_FOUND)

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -28,9 +28,10 @@
#include <unistd.h>
#include "srslte/utils/debug.h"
#include "srslte/ue_itf/phy.h"
#include "srslte/ue_itf/tti_sync_cv.h"
#include "srslte/cuhd/radio_uhd.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log_stdout.h"
#include "srsapps/common/tti_sync_cv.h"
#include "srsapps/radio/radio_uhd.h"
/**********************************************************************
* Program arguments processing
@ -48,15 +49,15 @@ prog_args_t prog_args;
void args_default(prog_args_t *args) {
args->uhd_rx_freq = -1.0;
args->uhd_tx_freq = -1.0;
args->uhd_rx_gain = 60.0;
args->uhd_tx_gain = 40.0;
args->uhd_rx_gain = -1; // set to autogain
args->uhd_tx_gain = -1;
args->continous = false;
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [gGcv] -f rx_frequency -F tx_frequency (in Hz)\n", prog);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_rx_gain);
printf("\t-G UHD TX gain [Default %.2f dB]\n", args->uhd_tx_gain);
printf("\t-g UHD RX gain [Default AGC]\n");
printf("\t-G UHD TX gain [Default same as RX gain (AGC)]\n");
printf("\t-c Run continuously [Default only once]\n");
printf("\t-v [increase verbosity, default none]\n");
}
@ -233,6 +234,8 @@ uint32_t interval(uint32_t x1, uint32_t x2) {
}
}
srslte_softbuffer_rx_t softbuffer;
// This is the MAC implementation
void run_tti(uint32_t tti) {
INFO("MAC running tti: %d\n", tti);
@ -247,7 +250,7 @@ void run_tti(uint32_t tti) {
// Indicate PHY to transmit the PRACH when possible
if (phy.send_prach(preamble_idx)) {
nof_tx_ra++;
state = RAR;
state = RAR;
} else {
fprintf(stderr, "Error sending PRACH\n");
exit(-1);
@ -263,14 +266,12 @@ void run_tti(uint32_t tti) {
INFO("Interval=%u\n", interval_ra);
if (interval_ra >= 3 && interval_ra <= 13) {
// Get DL grant for RA-RNTI=2
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant))
if (dl_buffer->get_dl_grant(&rar_grant))
{
srslte_softbuffer_rx_reset(&softbuffer);
// Decode packet
if (dl_buffer->decode_data(&rar_grant, payload)) {
if (dl_buffer->decode_data(&rar_grant, &softbuffer, payload)) {
rar_unpack(payload, &rar_msg);
if (!prog_args.continous) {
printf("Received RAR for preamble %d\n", rar_msg.RAPID);
}
if (rar_msg.RAPID == preamble_idx) {
INFO("Received RAR at TTI: %d\n", tti);
@ -358,6 +359,7 @@ void run_tti(uint32_t tti) {
state = RA;
}
} else {
srslte_softbuffer_rx_reset(&softbuffer);
state = CONNSETUP;
}
}
@ -366,10 +368,10 @@ void run_tti(uint32_t tti) {
srslte::ue::dl_sched_grant conn_setup_grant(rar_msg.temp_c_rnti);
bool connsetup_recv = false;
// Get DL grant for tmp_rnti
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
if (dl_buffer->get_dl_grant(&conn_setup_grant))
{
// Decode packet
if (dl_buffer->decode_data(&conn_setup_grant, payload)) {
if (dl_buffer->decode_data(&conn_setup_grant, &softbuffer, payload)) {
nof_rx_connsetup++;
state = RA;
nof_rtx_connsetup=0;
@ -397,13 +399,18 @@ void run_tti(uint32_t tti) {
state = RA;
}
}
float gain = prog_args.uhd_rx_gain;
if (gain < 0) {
gain = phy.get_agc_gain();
}
if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) {
printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r",
printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) Gain: %.1f dB\r",
(float) 100*nof_rx_rar/nof_tx_ra,
(float) 100*nof_rx_connsetup/nof_tx_ra,
nof_rx_connsetup, nof_tx_ra);
nof_rx_connsetup, nof_tx_ra, gain);
}
}
int main(int argc, char *argv[])
@ -412,26 +419,31 @@ int main(int argc, char *argv[])
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
srslte::ue::tti_sync_cv ttisync(10240);
srslte::radio_uhd radio_uhd;
srslte::log_stdout log("PHY");
parse_args(&prog_args, argc, argv);
// Init Radio
radio_uhd.init();
// Init PHY
phy.init(&radio_uhd, &ttisync);
// Init Radio and PHY
if (prog_args.uhd_rx_gain > 0 && prog_args.uhd_tx_gain > 0) {
radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_rx_gain);
radio_uhd.set_tx_gain(prog_args.uhd_tx_gain);
phy.init(&radio_uhd, &ttisync, &log);
} else {
radio_uhd.init_agc();
radio_uhd.set_tx_rx_gain_offset(-10);
phy.init_agc(&radio_uhd, &ttisync, &log);
}
// Give it time to create thread
sleep(1);
// Setup PHY parameters
config_phy();
// Set RX freq and gain
phy.get_radio()->set_rx_freq(prog_args.uhd_rx_freq);
phy.get_radio()->set_tx_freq(prog_args.uhd_tx_freq);
phy.get_radio()->set_rx_gain(prog_args.uhd_rx_gain);
phy.get_radio()->set_tx_gain(prog_args.uhd_tx_gain);
// Set RX freq
radio_uhd.set_rx_freq(prog_args.uhd_rx_freq);
radio_uhd.set_tx_freq(prog_args.uhd_tx_freq);
/* Instruct the PHY to decode BCH */
if (!phy.decode_mib_best(&cell, bch_payload)) {
@ -446,6 +458,13 @@ int main(int argc, char *argv[])
exit(-1);
}
if (!phy.init_prach()) {
printf("Error initiating PRACH\n");
exit(-1);
}
srslte_softbuffer_rx_init(&softbuffer, cell);
/* Instruct the PHY to start RX streaming and synchronize */
if (!phy.start_rxtx()) {
printf("Could not start RX\n");

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -28,9 +28,10 @@
#include <unistd.h>
#include "srslte/utils/debug.h"
#include "srslte/ue_itf/phy.h"
#include "srslte/ue_itf/tti_sync_cv.h"
#include "srslte/cuhd/radio_uhd.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log_stdout.h"
#include "srsapps/common/tti_sync_cv.h"
#include "srsapps/radio/radio_uhd.h"
/**********************************************************************
@ -43,12 +44,12 @@ typedef struct {
void args_default(prog_args_t *args) {
args->uhd_freq = -1.0;
args->uhd_gain = 60.0;
args->uhd_gain = -1.0;
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [gv] -f rx_frequency (in Hz)\n", prog);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain);
printf("\t-g UHD RX gain [Default AGC]\n");
printf("\t-v [increase verbosity, default none]\n");
}
@ -84,6 +85,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
srslte::ue::phy phy;
prog_args_t prog_args;
uint32_t total_pkts=0;
uint32_t total_dci=0;
@ -101,7 +103,7 @@ void run_tti(uint32_t tti) {
srslte::ue::dl_buffer *buffer = phy.get_dl_buffer(tti);
// Get DL grant
if (buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_SIRNTI, &grant))
if (buffer->get_dl_grant(&grant))
{
total_dci++;
// MAC sets RV
@ -114,11 +116,15 @@ void run_tti(uint32_t tti) {
}
total_pkts++;
}
float gain = prog_args.uhd_gain;
if (gain < 0) {
gain = phy.get_agc_gain();
}
if (srslte_verbose == SRSLTE_VERBOSE_NONE) {
printf("PDCCH BLER %.1f \%% PDSCH BLER %.1f \%% (total pkts: %5u) \r",
printf("PDCCH BLER %.1f \%% PDSCH BLER %.1f \%% (total pkts: %5u) Gain: %.1f dB\r",
100-(float) 100*total_dci/total_pkts,
(float) 100*total_errors/total_pkts,
total_pkts);
total_pkts, gain);
}
}
@ -126,17 +132,21 @@ int main(int argc, char *argv[])
{
srslte_cell_t cell;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
prog_args_t prog_args;
srslte::ue::tti_sync_cv ttisync(10240);
srslte::radio_uhd radio_uhd;
srslte::log_stdout log("PHY");
parse_args(&prog_args, argc, argv);
// Init Radio
radio_uhd.init();
// Init PHY
phy.init(&radio_uhd, &ttisync);
// Init Radio and PHY
if (prog_args.uhd_gain > 0) {
radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_gain);
phy.init(&radio_uhd, &ttisync, &log);
} else {
radio_uhd.init_agc();
phy.init_agc(&radio_uhd, &ttisync, &log);
}
// Give it time to create thread
sleep(1);

@ -1,20 +1,20 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# 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.
#
# srsLTE 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.
# GNU Affero General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
@ -46,4 +46,3 @@ ADD_CUSTOM_TARGET (add_srslte_headers SOURCES ${HEADERS_ALL})
########################################################################
ADD_SUBDIRECTORY(lib)
ADD_SUBDIRECTORY(examples)
#add_subdirectory(tutorial_examples)

@ -1,20 +1,20 @@
#
# Copyright 2012-2013 The srsLTE Developers. See the
# Copyright 2013-2015 The srsLTE Developers. See the
# COPYRIGHT file at the top-level directory of this distribution.
#
# This file is part of the srsLTE library.
#
# srsLTE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# 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.
#
# srsLTE 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.
# GNU Affero General Public License for more details.
#
# A copy of the GNU Lesser General Public License can be found in
# A copy of the GNU Affero General Public License can be found in
# the LICENSE file in the top-level directory of this distribution
# and at http://www.gnu.org/licenses/.
#
@ -38,36 +38,30 @@ target_link_libraries(ll_example srslte)
add_executable(synch_file synch_file.c)
target_link_libraries(synch_file srslte)
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
#################################################################
# These can be compiled without UHD or graphics support
#################################################################
add_executable(pdsch_ue pdsch_ue.c cuhd_utils.c)
target_link_libraries(pdsch_ue srslte)
add_executable(pdsch_ue pdsch_ue.c)
target_link_libraries(pdsch_ue srslte pthread)
add_executable(pdsch_enodeb pdsch_enodeb.c)
target_link_libraries(pdsch_enodeb srslte pthread)
LIST(FIND OPTIONAL_LIBS cuhd CUHD_FIND)
IF(${CUHD_FIND} EQUAL -1)
SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
SET_TARGET_PROPERTIES(pdsch_enodeb PROPERTIES COMPILE_DEFINITIONS "DISABLE_UHD")
ELSE(${CUHD_FIND} EQUAL -1)
target_link_libraries(pdsch_ue cuhd pthread)
target_link_libraries(pdsch_enodeb cuhd)
ENDIF(${CUHD_FIND} EQUAL -1)
IF(UHD_FOUND)
target_link_libraries(pdsch_ue srslte_uhd)
target_link_libraries(pdsch_enodeb srslte_uhd)
ELSE(UHD_FOUND)
add_definitions(-DDISABLE_UHD)
ENDIF(UHD_FOUND)
FIND_PACKAGE(SRSGUI)
IF(SRSGUI_FOUND)
include_directories(${SRSGUI_INCLUDE_DIRS})
target_link_libraries(pdsch_ue ${SRSGUI_LIBRARIES})
ELSE(SRSGUI_FOUND)
SET_TARGET_PROPERTIES(pdsch_ue PROPERTIES COMPILE_DEFINITIONS "DISABLE_GRAPHICS")
add_definitions(-DDISABLE_GRAPHICS)
ENDIF(SRSGUI_FOUND)
@ -75,25 +69,29 @@ ENDIF(SRSGUI_FOUND)
# These examples need the UHD driver
#################################################################
IF(${CUHD_FIND} GREATER -1)
IF(UHD_FOUND)
add_executable(cell_search cell_search.c cuhd_utils.c)
target_link_libraries(cell_search srslte cuhd )
add_executable(cell_search cell_search.c)
target_link_libraries(cell_search srslte srslte_uhd)
add_executable(prach_ue prach_ue.c cuhd_utils.c)
target_link_libraries(prach_ue srslte cuhd)
add_executable(prach_ue prach_ue.c)
target_link_libraries(prach_ue srslte srslte_uhd)
add_executable(cell_measurement cell_measurement.c cuhd_utils.c)
target_link_libraries(cell_measurement cuhd srslte)
add_executable(cell_measurement cell_measurement.c)
target_link_libraries(cell_measurement srslte srslte_uhd)
add_executable(usrp_capture usrp_capture.c cuhd_utils.c)
target_link_libraries(usrp_capture cuhd srslte)
add_executable(usrp_capture usrp_capture.c)
target_link_libraries(usrp_capture srslte srslte_uhd)
add_executable(usrp_capture_sync usrp_capture_sync.c cuhd_utils.c)
target_link_libraries(usrp_capture_sync cuhd srslte)
add_executable(usrp_capture_sync usrp_capture_sync.c)
target_link_libraries(usrp_capture_sync srslte srslte_uhd)
MESSAGE(STATUS " UHD examples will be installed.")
ELSE(${CUHD_FIND} GREATER -1)
MESSAGE(STATUS " UHD examples NOT INSTALLED: CUHD library not compiled.")
ENDIF(${CUHD_FIND} GREATER -1)
ELSE(UHD_FOUND)
MESSAGE(STATUS " UHD examples NOT INSTALLED.")
ENDIF(UHD_FOUND)
# Add subdirectories
add_subdirectory(tutorial_examples)

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -38,7 +38,7 @@
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "cuhd_utils.h"
#include "srslte/cuhd/cuhd_utils.h"
#define B210_DEFAULT_GAIN 40.0
#define B210_DEFAULT_GAIN_CORREC 110.0 // Gain of the Rx chain when the gain is set to 40
@ -289,7 +289,7 @@ int main(int argc, char **argv) {
rssi_utra = SRSLTE_VEC_CMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,nframes);
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05);
snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&chest),snr,0.05);
snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&chest),snr,0.05);
nframes++;
}

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -37,7 +37,7 @@
#include "srslte/srslte.h"
#include "cuhd_utils.h"
#include "srslte/cuhd/cuhd_utils.h"
#ifndef DISABLE_UHD

@ -1,52 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/srslte.h"
typedef struct SRSLTE_API {
uint32_t max_frames_pbch; // maximum number of 5ms frames to capture for MIB decoding
uint32_t max_frames_pss; // maximum number of 5ms frames to capture for PSS correlation
float threshold; // early-stops cell detection if mean PSR is above this value
float init_agc; // 0 or negative to disable AGC
}cell_search_cfg_t;
int cuhd_mib_decoder(void *uhd,
cell_search_cfg_t *config,
srslte_cell_t *cell);
int cuhd_cell_search(void *uhd,
cell_search_cfg_t *config,
int force_N_id_2,
srslte_cell_t *cell);
int cuhd_search_and_decode_mib(void *uhd,
cell_search_cfg_t *config,
int force_N_id_2,
srslte_cell_t *cell);

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -39,6 +39,8 @@
#ifndef DISABLE_UHD
#include "srslte/cuhd/cuhd.h"
void *uhd;
#else
#warning Compiling pdsch_ue with no UHD support
#endif
char *output_file_name = NULL;
@ -252,7 +254,7 @@ void base_init() {
exit(-1);
}
srslte_pdsch_set_rnti(&pdsch, 1234);
srslte_pdsch_set_rnti(&pdsch, 4660);
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
fprintf(stderr, "Error initiating soft buffer\n");

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -43,14 +43,15 @@
#ifndef DISABLE_UHD
#include "srslte/cuhd/cuhd.h"
#include "cuhd_utils.h"
#include "srslte/cuhd/cuhd_utils.h"
cell_search_cfg_t cell_detect_config = {
5000,
200, // nof_frames_total
10.0 // threshold
};
#else
#warning Compiling pdsch_ue with no UHD support
#endif
//#define STDOUT_COMPACT
@ -63,12 +64,18 @@ sem_t plot_sem;
uint32_t plot_sf_idx=0;
#endif
#define PLOT_CHEST_ARGUMENT
#define PRINT_CHANGE_SCHEDULIGN
/**********************************************************************
* Program arguments processing
***********************************************************************/
typedef struct {
int nof_subframes;
bool disable_plots;
bool disable_plots_except_constellation;
bool disable_cfo;
uint32_t time_offset;
int force_N_id_2;
uint16_t rnti;
char *input_file_name;
@ -86,10 +93,14 @@ typedef struct {
}prog_args_t;
void args_default(prog_args_t *args) {
args->disable_plots = false;
args->disable_plots_except_constellation = false;
args->nof_subframes = -1;
args->rnti = SRSLTE_SIRNTI;
args->force_N_id_2 = -1; // Pick the best
args->input_file_name = NULL;
args->disable_cfo = false;
args->time_offset = 0;
args->file_nof_prb = 6;
args->file_nof_ports = 1;
args->file_cell_id = 0;
@ -104,7 +115,7 @@ void args_default(prog_args_t *args) {
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [agpPcildnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
printf("Usage: %s [agpPcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
#ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD fix RX gain [Default AGC]\n");
@ -116,10 +127,13 @@ void usage(prog_args_t *args, char *prog) {
printf("\t-p nof_prb for input file [Default %d]\n", args->file_nof_prb);
printf("\t-P nof_ports for input file [Default %d]\n", args->file_nof_ports);
printf("\t-c cell_id for input file [Default %d]\n", args->file_cell_id);
printf("\t-r RNTI [Default 0x%x]\n",args->rnti);
printf("\t-r RNTI in Hex [Default 0x%x]\n",args->rnti);
printf("\t-l Force N_id_2 [Default best]\n");
printf("\t-C Disable CFO correction [Default %s]\n", args->disable_cfo?"Disabled":"Enabled");
printf("\t-t Add time offset [Default %d]\n", args->time_offset);
#ifndef DISABLE_GRAPHICS
printf("\t-d disable plots [Default enabled]\n");
printf("\t-D disable all but constellation plots [Default enabled]\n");
#else
printf("\t plots are disabled. Graphics library not available\n");
#endif
@ -134,7 +148,7 @@ void usage(prog_args_t *args, char *prog) {
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "aoglipPcdnvrfuUsS")) != -1) {
while ((opt = getopt(argc, argv, "aoglipPcCtdDnvrfuUsS")) != -1) {
switch (opt) {
case 'i':
args->input_file_name = argv[optind];
@ -154,6 +168,12 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'g':
args->uhd_gain = atof(argv[optind]);
break;
case 'C':
args->disable_cfo = true;
break;
case 't':
args->time_offset = atoi(argv[optind]);
break;
case 'o':
args->uhd_freq_offset = atof(argv[optind]);
break;
@ -164,7 +184,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
args->nof_subframes = atoi(argv[optind]);
break;
case 'r':
args->rnti = atoi(argv[optind]);
args->rnti = strtol(argv[optind], NULL, 16);
break;
case 'l':
args->force_N_id_2 = atoi(argv[optind]);
@ -184,6 +204,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
case 'd':
args->disable_plots = true;
break;
case 'D':
args->disable_plots_except_constellation = true;
break;
case 'v':
srslte_verbose++;
break;
@ -266,14 +289,14 @@ int main(int argc, char **argv) {
/* Set receiver gain */
if (prog_args.uhd_gain > 0) {
printf("Opening UHD device...\n");
if (cuhd_open_th(prog_args.uhd_args, &uhd)) {
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
} else {
printf("Opening UHD device with threaded RX Gain control ...\n");
if (cuhd_open_th(prog_args.uhd_args, &uhd)) {
if (cuhd_open_th(prog_args.uhd_args, &uhd, false)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
@ -371,13 +394,28 @@ int main(int argc, char **argv) {
// Variables for measurements
uint32_t nframes=0;
float rsrp=0.0, rsrq=0.0, snr=0.0;
bool decode_pdsch;
int pdcch_tx=0;
float rsrp=0.0, rsrq=0.0, noise=0.0;
bool decode_pdsch = false;
#ifndef DISABLE_UHD
if (prog_args.uhd_gain < 0) {
srslte_ue_sync_start_agc(&ue_sync, cuhd_set_rx_gain_th, cell_detect_config.init_agc);
}
#endif
#ifdef PRINT_CHANGE_SCHEDULIGN
srslte_ra_dl_dci_t old_dl_dci;
bzero(&old_dl_dci, sizeof(srslte_ra_dl_dci_t));
#endif
ue_sync.correct_cfo = !prog_args.disable_cfo;
/* Set high priority */
struct sched_param param;
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (sched_setscheduler(pthread_self(), SCHED_FIFO, &param)) {
perror("setscheduler");
}
INFO("\nEntering main loop...\n\n", 0);
/* Main loop */
@ -409,9 +447,13 @@ int main(int argc, char **argv) {
break;
case DECODE_PDSCH:
if (prog_args.rnti != SRSLTE_SIRNTI) {
decode_pdsch = true;
if (srslte_ue_sync_get_sfidx(&ue_sync) != 5 && srslte_ue_sync_get_sfidx(&ue_sync) != 0) {
decode_pdsch = true;
} else {
decode_pdsch = false;
}
} else {
/* We are looking for SIB1 Blocks, search only in appropiate places */
/* We are looking for SIB1 Blocks, 2search only in appropiate places */
if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
decode_pdsch = true;
} else {
@ -420,9 +462,9 @@ int main(int argc, char **argv) {
}
if (decode_pdsch) {
if (prog_args.rnti != SRSLTE_SIRNTI) {
n = srslte_ue_dl_decode(&ue_dl, sf_buffer, data_packed, srslte_ue_sync_get_sfidx(&ue_sync));
n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync));
} else {
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data_packed, srslte_ue_sync_get_sfidx(&ue_sync),
n = srslte_ue_dl_decode_rnti_rv(&ue_dl, &sf_buffer[prog_args.time_offset], data_packed, srslte_ue_sync_get_sfidx(&ue_sync),
SRSLTE_SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4);
}
if (n < 0) {
@ -433,65 +475,54 @@ int main(int argc, char **argv) {
srslte_bit_unpack_vector(data_packed, data, n);
srslte_netsink_write(&net_sink, data, 1+(n-1)/8);
}
#ifdef PRINT_CHANGE_SCHEDULIGN
if (ue_dl.dl_dci.mcs_idx != old_dl_dci.mcs_idx ||
memcmp(&ue_dl.dl_dci.type0_alloc, &old_dl_dci.type0_alloc, sizeof(srslte_ra_type0_t)) ||
memcmp(&ue_dl.dl_dci.type1_alloc, &old_dl_dci.type1_alloc, sizeof(srslte_ra_type1_t)) ||
memcmp(&ue_dl.dl_dci.type2_alloc, &old_dl_dci.type2_alloc, sizeof(srslte_ra_type2_t)))
{
memcpy(&old_dl_dci, &ue_dl.dl_dci, sizeof(srslte_ra_dl_dci_t));
fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi);
printf("Format: %s\n", srslte_dci_format_string(ue_dl.dci_format));
srslte_ra_pdsch_fprint(stdout, &old_dl_dci, cell.nof_prb);
srslte_ra_dl_grant_fprint(stdout, &ue_dl.pdsch_cfg.grant);
}
#endif
}
nof_trials++;
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.05);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05);
snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&ue_dl.chest), snr, 0.01);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05);
nframes++;
if (isnan(rsrq)) {
rsrq = 0;
}
if (isnan(snr)) {
snr = 0;
if (isnan(noise)) {
noise = 0;
}
if (isnan(rsrp)) {
rsrp = 0;
}
#ifdef adjust_estimator
/* Adjust channel estimator based on SNR */
if (10*log10(snr) < 5.0) {
float f_low_snr[5]={0.05, 0.15, 0.6, 0.15, 0.05};
srslte_chest_dl_set_filter_freq(&ue_dl.chest, f_low_snr, 5);
} else if (10*log10(snr) < 10.0) {
float f_mid_snr[3]={0.1, 0.8, 0.1};
srslte_chest_dl_set_filter_freq(&ue_dl.chest, f_mid_snr, 3);
} else {
float f_high_snr[3]={0.05, 0.9, 0.05};
srslte_chest_dl_set_filter_freq(&ue_dl.chest, f_high_snr, 3);
}
#endif
}
}
if (srslte_ue_sync_get_sfidx(&ue_sync) != 5 && srslte_ue_sync_get_sfidx(&ue_sync) != 0) {
pdcch_tx++;
}
// Plot and Printf
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
#ifdef STDOUT_COMPACT
printf("SFN: %4d, PDCCH-Miss: %5.2f%% (%d missed), PDSCH-BLER: %5.2f%% (%d errors)\r",
sfn, 100*(1-(float) ue_dl.nof_detected/nof_trials),pdcch_tx-ue_dl.nof_detected,
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,ue_dl.pkt_errors);
#else
float gain = prog_args.uhd_gain;
if (gain < 0) {
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
}
printf("CFO: %+6.2f KHz, SFO: %+6.2f Khz, "
"RSRP: %+5.1f dBm, SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%% Peak: %.2f Gain: %.1f dB\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
10*log10(rsrp*1000)-gain,
10*log10(snr),
printf("CFO: %+6.2f KHz, "
"SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000,
10*log10(rsrp/noise),
100*(1-(float) ue_dl.nof_detected/nof_trials),
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,
srslte_agc_get_output_level(&ue_sync.agc), gain);
#endif
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
}
break;
}
@ -504,8 +535,10 @@ int main(int argc, char **argv) {
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
sem_post(&plot_sem);
if ((sfn%4) == 0 && decode_pdsch) {
plot_sf_idx = srslte_ue_sync_get_sfidx(&ue_sync);
sem_post(&plot_sem);
}
}
#endif
} else if (ret == 0) {
@ -552,7 +585,7 @@ int main(int argc, char **argv) {
//plot_waterfall_t poutfft;
plot_real_t p_sync, pce;
plot_real_t p_sync, pce, pce_arg;
plot_scatter_t pscatequal, pscatequal_pdcch;
float tmp_plot[SRSLTE_SLOT_LEN_RE(SRSLTE_MAX_PRB, SRSLTE_CP_NORM)];
@ -563,38 +596,83 @@ void *plot_thread_run(void *arg) {
int i;
uint32_t nof_re = SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp);
sdrgui_init();
//plot_waterfall_init(&poutfft, SRSLTE_NRE * ue_dl.cell.nof_prb, 1000);
//plot_waterfall_setTitle(&poutfft, "Output FFT - Magnitude");
//plot_waterfall_setPlotYAxisScale(&poutfft, -40, 40);
if (!prog_args.disable_plots_except_constellation) {
plot_real_init(&pce);
plot_real_setTitle(&pce, "Channel Response - Magnitude");
plot_real_setLabels(&pce, "Index", "dB");
plot_real_setYAxisScale(&pce, -40, 40);
#ifdef PLOT_CHEST_ARGUMENT
plot_real_init(&pce_arg);
plot_real_setTitle(&pce_arg, "Channel Response - Argument");
plot_real_setLabels(&pce_arg, "Index", "rad");
plot_real_setYAxisScale(&pce_arg, -1.1*M_PI, 1.1*M_PI);
#endif
plot_real_init(&p_sync);
plot_real_setTitle(&p_sync, "PSS Cross-Corr abs value");
plot_real_setYAxisScale(&p_sync, 0, 1);
plot_scatter_init(&pscatequal_pdcch);
plot_scatter_setTitle(&pscatequal_pdcch, "PDCCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pscatequal_pdcch, -4, 4);
plot_scatter_setYAxisScale(&pscatequal_pdcch, -4, 4);
}
plot_scatter_init(&pscatequal);
plot_scatter_setTitle(&pscatequal, "PDSCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pscatequal, -4, 4);
plot_scatter_setYAxisScale(&pscatequal, -4, 4);
while(1) {
sem_wait(&plot_sem);
uint32_t nof_symbols = ue_dl.pdsch_cfg.grant.nof_re;
for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
if (isinf(tmp_plot[i])) {
tmp_plot[i] = -80;
if (!prog_args.disable_plots_except_constellation) {
for (i = 0; i < nof_re; i++) {
tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i]));
if (isinf(tmp_plot[i])) {
tmp_plot[i] = -80;
}
}
}
for (i = 0; i < SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0); i++) {
tmp_plot2[i] = 20 * log10f(cabsf(ue_dl.chest.pilot_estimates_average[0][i]));
if (isinf(tmp_plot2[i])) {
tmp_plot2[i] = -80;
for (i = 0; i < 4*12*ue_dl.cell.nof_prb; i++) {
tmp_plot2[i] = 20 * log10f(cabsf(ue_dl.ce[0][i]));
if (isinf(tmp_plot2[i])) {
tmp_plot2[i] = -80;
}
}
}
//for (i=0;i<SRSLTE_CP_NSYMB(ue_dl.cell.cp);i++) {
// plot_waterfall_appendNewData(&poutfft, &tmp_plot[i*SRSLTE_NRE*ue_dl.cell.nof_prb], SRSLTE_NRE*ue_dl.cell.nof_prb);
//}
plot_real_setNewData(&pce, tmp_plot2, SRSLTE_REFSIGNAL_NUM_SF(ue_dl.cell.nof_prb,0));
if (!prog_args.input_file_name) {
int max = srslte_vec_max_fi(ue_sync.strack.pss.conv_output_avg, ue_sync.strack.pss.frame_size+ue_sync.strack.pss.fft_size-1);
srslte_vec_sc_prod_fff(ue_sync.strack.pss.conv_output_avg,
1/ue_sync.strack.pss.conv_output_avg[max],
tmp_plot2,
ue_sync.strack.pss.frame_size+ue_sync.strack.pss.fft_size-1);
plot_real_setNewData(&p_sync, tmp_plot2, ue_sync.strack.pss.frame_size);
plot_real_setNewData(&pce, tmp_plot2, 4*12*ue_dl.cell.nof_prb);
if (!prog_args.input_file_name) {
int max = srslte_vec_max_fi(ue_sync.strack.pss.conv_output_avg, ue_sync.strack.pss.frame_size+ue_sync.strack.pss.fft_size-1);
srslte_vec_sc_prod_fff(ue_sync.strack.pss.conv_output_avg,
1/ue_sync.strack.pss.conv_output_avg[max],
tmp_plot2,
ue_sync.strack.pss.frame_size+ue_sync.strack.pss.fft_size-1);
plot_real_setNewData(&p_sync, tmp_plot2, ue_sync.strack.pss.frame_size);
}
#ifdef PLOT_CHEST_ARGUMENT
for (i = 0; i < 2*12*ue_dl.cell.nof_prb; i++) {
tmp_plot2[i] = cargf(ue_dl.ce[0][i]);
}
plot_real_setNewData(&pce_arg, tmp_plot2, 2*12*ue_dl.cell.nof_prb);
#endif
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce);
}
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d, nof_symbols);
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce);
if (plot_sf_idx == 1) {
if (prog_args.net_port_signal > 0) {
@ -610,36 +688,17 @@ void *plot_thread_run(void *arg) {
void init_plots() {
sdrgui_init();
//plot_waterfall_init(&poutfft, SRSLTE_NRE * ue_dl.cell.nof_prb, 1000);
//plot_waterfall_setTitle(&poutfft, "Output FFT - Magnitude");
//plot_waterfall_setPlotYAxisScale(&poutfft, -40, 40);
plot_real_init(&pce);
plot_real_setTitle(&pce, "Channel Response - Magnitude");
plot_real_setLabels(&pce, "Index", "dB");
plot_real_setYAxisScale(&pce, -40, 40);
plot_real_init(&p_sync);
plot_real_setTitle(&p_sync, "PSS Cross-Corr abs value");
plot_real_setYAxisScale(&p_sync, 0, 1);
plot_scatter_init(&pscatequal);
plot_scatter_setTitle(&pscatequal, "PDSCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pscatequal, -4, 4);
plot_scatter_setYAxisScale(&pscatequal, -4, 4);
plot_scatter_init(&pscatequal_pdcch);
plot_scatter_setTitle(&pscatequal_pdcch, "PDCCH - Equalized Symbols");
plot_scatter_setXAxisScale(&pscatequal_pdcch, -4, 4);
plot_scatter_setYAxisScale(&pscatequal_pdcch, -4, 4);
if (sem_init(&plot_sem, 0, 0)) {
perror("sem_init");
exit(-1);
}
pthread_attr_t attr;
struct sched_param param;
param.sched_priority = 0;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
pthread_attr_setschedparam(&attr, &param);
if (pthread_create(&plot_thread, NULL, plot_thread_run, NULL)) {
perror("pthread_create");
exit(-1);

@ -2,7 +2,7 @@
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
@ -10,16 +10,16 @@
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* 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.
*
* srsLTE 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.
* GNU Affero General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
@ -42,7 +42,7 @@
#include "srslte/cuhd/cuhd.h"
#include "cuhd_utils.h"
#include "srslte/cuhd/cuhd_utils.h"
cell_search_cfg_t cell_detect_config = {
5000,
@ -327,6 +327,7 @@ int main(int argc, char **argv) {
printf("Tunning TX receiver to %.3f MHz\n", (double ) prog_args.uhd_tx_freq/1000000);
#ifdef kk
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
@ -335,6 +336,10 @@ int main(int argc, char **argv) {
printf("Cell not found\n");
exit(0);
}
#endif
cell.nof_prb = 50;
cell.id = 1;
cell.nof_ports = 1;
/* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb);
@ -471,7 +476,7 @@ int main(int argc, char **argv) {
cuhd_send_timed(uhd, prach_buffer, prach_buffer_len,
next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue", prach_buffer, prach_buffer_len*sizeof(cf_t));
srslte_vec_save_file("prach_ue.dat", prach_buffer, prach_buffer_len*sizeof(cf_t));
ra_rnti = 2;
rar_window_start = sfn+1;
@ -536,6 +541,8 @@ int main(int argc, char **argv) {
cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue_connreq.dat", ul_signal, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
//cuhd_start_rx_stream(uhd);
state = RECV_CONNSETUP;
conn_setup_trial = 0;

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

Loading…
Cancel
Save