Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Michael Black
OpenXG UE
Commits
5619814b
Commit
5619814b
authored
7 years ago
by
Raymond Knopp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
created new directories for NBIoT and NR and split eNB/gNB/UE
parent
a3edccd7
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
7293 additions
and
0 deletions
+7293
-0
openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c
openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c
+3681
-0
openair1/PHY/LTE_UE_TRANSPORT/pbch_ue.c
openair1/PHY/LTE_UE_TRANSPORT/pbch_ue.c
+631
-0
openair1/PHY/LTE_UE_TRANSPORT/pcfich_ue.c
openair1/PHY/LTE_UE_TRANSPORT/pcfich_ue.c
+312
-0
openair1/PHY/LTE_UE_TRANSPORT/pch_ue.c
openair1/PHY/LTE_UE_TRANSPORT/pch_ue.c
+54
-0
openair1/PHY/LTE_UE_TRANSPORT/phich_ue.c
openair1/PHY/LTE_UE_TRANSPORT/phich_ue.c
+1570
-0
openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c
openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c
+1045
-0
No files found.
openair1/PHY/LTE_UE_TRANSPORT/dci_ue.c
0 → 100755
View file @
5619814b
This source diff could not be displayed because it is too large. You can
view the blob
instead.
This diff is collapsed.
Click to expand it.
openair1/PHY/LTE_UE_TRANSPORT/pbch_ue.c
0 → 100644
View file @
5619814b
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/pbch.c
* \brief Top-level routines for generating and decoding the PBCH/BCH physical/transport channel V8.6 2009-03
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger.fr
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "defs.h"
#include "extern.h"
#include "PHY/extern.h"
#include "PHY/sse_intrin.h"
//#define DEBUG_PBCH 1
//#define DEBUG_PBCH_ENCODING
//#define INTERFERENCE_MITIGATION 1
#define PBCH_A 24
uint16_t
pbch_extract
(
int
**
rxdataF
,
int
**
dl_ch_estimates
,
int
**
rxdataF_ext
,
int
**
dl_ch_estimates_ext
,
uint32_t
symbol
,
uint32_t
high_speed_flag
,
LTE_DL_FRAME_PARMS
*
frame_parms
)
{
uint16_t
rb
,
nb_rb
=
6
;
uint8_t
i
,
j
,
aarx
,
aatx
;
int
*
dl_ch0
,
*
dl_ch0_ext
,
*
rxF
,
*
rxF_ext
;
uint32_t
nsymb
=
(
frame_parms
->
Ncp
==
0
)
?
7
:
6
;
uint32_t
symbol_mod
=
symbol
%
nsymb
;
int
rx_offset
=
frame_parms
->
ofdm_symbol_size
-
3
*
12
;
int
ch_offset
=
frame_parms
->
N_RB_DL
*
6
-
3
*
12
;
int
nushiftmod3
=
frame_parms
->
nushift
%
3
;
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
/*
printf("extract_rbs (nushift %d): symbol_mod=%d, rx_offset=%d, ch_offset=%d\n",frame_parms->nushift,symbol_mod,
(rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2,
LTE_CE_OFFSET+ch_offset+(symbol_mod*(frame_parms->ofdm_symbol_size)));
*/
rxF
=
&
rxdataF
[
aarx
][(
rx_offset
+
(
symbol
*
(
frame_parms
->
ofdm_symbol_size
)))];
rxF_ext
=
&
rxdataF_ext
[
aarx
][
symbol_mod
*
(
6
*
12
)];
for
(
rb
=
0
;
rb
<
nb_rb
;
rb
++
)
{
// skip DC carrier
if
(
rb
==
3
)
{
rxF
=
&
rxdataF
[
aarx
][(
1
+
(
symbol
*
(
frame_parms
->
ofdm_symbol_size
)))];
}
if
((
symbol_mod
==
0
)
||
(
symbol_mod
==
1
))
{
j
=
0
;
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
((
i
!=
nushiftmod3
)
&&
(
i
!=
(
nushiftmod3
+
3
))
&&
(
i
!=
(
nushiftmod3
+
6
))
&&
(
i
!=
(
nushiftmod3
+
9
)))
{
rxF_ext
[
j
++
]
=
rxF
[
i
];
}
}
rxF
+=
12
;
rxF_ext
+=
8
;
}
else
{
for
(
i
=
0
;
i
<
12
;
i
++
)
{
rxF_ext
[
i
]
=
rxF
[
i
];
}
rxF
+=
12
;
rxF_ext
+=
12
;
}
}
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
{
//frame_parms->nb_antenna_ports_eNB;aatx++) {
if
(
high_speed_flag
==
1
)
dl_ch0
=
&
dl_ch_estimates
[(
aatx
<<
1
)
+
aarx
][
LTE_CE_OFFSET
+
ch_offset
+
(
symbol
*
(
frame_parms
->
ofdm_symbol_size
))];
else
dl_ch0
=
&
dl_ch_estimates
[(
aatx
<<
1
)
+
aarx
][
LTE_CE_OFFSET
+
ch_offset
];
dl_ch0_ext
=
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
(
6
*
12
)];
for
(
rb
=
0
;
rb
<
nb_rb
;
rb
++
)
{
// skip DC carrier
// if (rb==3) dl_ch0++;
if
(
symbol_mod
>
1
)
{
memcpy
(
dl_ch0_ext
,
dl_ch0
,
12
*
sizeof
(
int
));
dl_ch0
+=
12
;
dl_ch0_ext
+=
12
;
}
else
{
j
=
0
;
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
((
i
!=
nushiftmod3
)
&&
(
i
!=
(
nushiftmod3
+
3
))
&&
(
i
!=
(
nushiftmod3
+
6
))
&&
(
i
!=
(
nushiftmod3
+
9
)))
{
// printf("PBCH extract i %d j %d => (%d,%d)\n",i,j,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i]));
dl_ch0_ext
[
j
++
]
=
dl_ch0
[
i
];
}
}
dl_ch0
+=
12
;
dl_ch0_ext
+=
8
;
}
}
}
//tx antenna loop
}
return
(
0
);
}
//__m128i avg128;
//compute average channel_level on each (TX,RX) antenna pair
int
pbch_channel_level
(
int
**
dl_ch_estimates_ext
,
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint32_t
symbol
)
{
int16_t
rb
,
nb_rb
=
6
;
uint8_t
aatx
,
aarx
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
avg128
;
__m128i
*
dl_ch128
;
#elif defined(__arm__)
int32x4_t
avg128
;
int16x8_t
*
dl_ch128
;
#endif
int
avg1
=
0
,
avg2
=
0
;
uint32_t
nsymb
=
(
frame_parms
->
Ncp
==
0
)
?
7
:
6
;
uint32_t
symbol_mod
=
symbol
%
nsymb
;
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
//frame_parms->nb_antenna_ports_eNB;aatx++)
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
//clear average level
#if defined(__x86_64__) || defined(__i386__)
avg128
=
_mm_setzero_si128
();
dl_ch128
=
(
__m128i
*
)
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
#elif defined(__arm__)
avg128
=
vdupq_n_s32
(
0
);
dl_ch128
=
(
int16x8_t
*
)
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
#endif
for
(
rb
=
0
;
rb
<
nb_rb
;
rb
++
)
{
#if defined(__x86_64__) || defined(__i386__)
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
0
],
dl_ch128
[
0
]));
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
1
],
dl_ch128
[
1
]));
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
2
],
dl_ch128
[
2
]));
#elif defined(__arm__)
// to be filled in
#endif
dl_ch128
+=
3
;
/*
if (rb==0) {
print_shorts("dl_ch128",&dl_ch128[0]);
print_shorts("dl_ch128",&dl_ch128[1]);
print_shorts("dl_ch128",&dl_ch128[2]);
}
*/
}
avg1
=
(((
int
*
)
&
avg128
)[
0
]
+
((
int
*
)
&
avg128
)[
1
]
+
((
int
*
)
&
avg128
)[
2
]
+
((
int
*
)
&
avg128
)[
3
])
/
(
nb_rb
*
12
);
if
(
avg1
>
avg2
)
avg2
=
avg1
;
//msg("Channel level : %d, %d\n",avg1, avg2);
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
return
(
avg2
);
}
#if defined(__x86_64__) || defined(__i386__)
__m128i
mmtmpP0
,
mmtmpP1
,
mmtmpP2
,
mmtmpP3
;
#elif defined(__arm__)
int16x8_t
mmtmpP0
,
mmtmpP1
,
mmtmpP2
,
mmtmpP3
;
#endif
void
pbch_channel_compensation
(
int
**
rxdataF_ext
,
int
**
dl_ch_estimates_ext
,
int
**
rxdataF_comp
,
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
symbol
,
uint8_t
output_shift
)
{
uint16_t
rb
,
nb_rb
=
6
;
uint8_t
aatx
,
aarx
,
symbol_mod
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
dl_ch128
,
*
rxdataF128
,
*
rxdataF_comp128
;
#elif defined(__arm__)
#endif
symbol_mod
=
(
symbol
>=
(
7
-
frame_parms
->
Ncp
))
?
symbol
-
(
7
-
frame_parms
->
Ncp
)
:
symbol
;
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
//frame_parms->nb_antenna_ports_eNB;aatx++)
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
#if defined(__x86_64__) || defined(__i386__)
dl_ch128
=
(
__m128i
*
)
&
dl_ch_estimates_ext
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
rxdataF128
=
(
__m128i
*
)
&
rxdataF_ext
[
aarx
][
symbol_mod
*
6
*
12
];
rxdataF_comp128
=
(
__m128i
*
)
&
rxdataF_comp
[(
aatx
<<
1
)
+
aarx
][
symbol_mod
*
6
*
12
];
#elif defined(__arm__)
// to be filled in
#endif
for
(
rb
=
0
;
rb
<
nb_rb
;
rb
++
)
{
//printf("rb %d\n",rb);
#if defined(__x86_64__) || defined(__i386__)
// multiply by conjugated channel
mmtmpP0
=
_mm_madd_epi16
(
dl_ch128
[
0
],
rxdataF128
[
0
]);
// print_ints("re",&mmtmpP0);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1
=
_mm_shufflelo_epi16
(
dl_ch128
[
0
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_shufflehi_epi16
(
mmtmpP1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_sign_epi16
(
mmtmpP1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
// print_ints("im",&mmtmpP1);
mmtmpP1
=
_mm_madd_epi16
(
mmtmpP1
,
rxdataF128
[
0
]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0
=
_mm_srai_epi32
(
mmtmpP0
,
output_shift
);
// print_ints("re(shift)",&mmtmpP0);
mmtmpP1
=
_mm_srai_epi32
(
mmtmpP1
,
output_shift
);
// print_ints("im(shift)",&mmtmpP1);
mmtmpP2
=
_mm_unpacklo_epi32
(
mmtmpP0
,
mmtmpP1
);
mmtmpP3
=
_mm_unpackhi_epi32
(
mmtmpP0
,
mmtmpP1
);
// print_ints("c0",&mmtmpP2);
// print_ints("c1",&mmtmpP3);
rxdataF_comp128
[
0
]
=
_mm_packs_epi32
(
mmtmpP2
,
mmtmpP3
);
// print_shorts("rx:",rxdataF128);
// print_shorts("ch:",dl_ch128);
// print_shorts("pack:",rxdataF_comp128);
// multiply by conjugated channel
mmtmpP0
=
_mm_madd_epi16
(
dl_ch128
[
1
],
rxdataF128
[
1
]);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1
=
_mm_shufflelo_epi16
(
dl_ch128
[
1
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_shufflehi_epi16
(
mmtmpP1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_sign_epi16
(
mmtmpP1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
mmtmpP1
=
_mm_madd_epi16
(
mmtmpP1
,
rxdataF128
[
1
]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0
=
_mm_srai_epi32
(
mmtmpP0
,
output_shift
);
mmtmpP1
=
_mm_srai_epi32
(
mmtmpP1
,
output_shift
);
mmtmpP2
=
_mm_unpacklo_epi32
(
mmtmpP0
,
mmtmpP1
);
mmtmpP3
=
_mm_unpackhi_epi32
(
mmtmpP0
,
mmtmpP1
);
rxdataF_comp128
[
1
]
=
_mm_packs_epi32
(
mmtmpP2
,
mmtmpP3
);
// print_shorts("rx:",rxdataF128+1);
// print_shorts("ch:",dl_ch128+1);
// print_shorts("pack:",rxdataF_comp128+1);
if
(
symbol_mod
>
1
)
{
// multiply by conjugated channel
mmtmpP0
=
_mm_madd_epi16
(
dl_ch128
[
2
],
rxdataF128
[
2
]);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1
=
_mm_shufflelo_epi16
(
dl_ch128
[
2
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_shufflehi_epi16
(
mmtmpP1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpP1
=
_mm_sign_epi16
(
mmtmpP1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
mmtmpP1
=
_mm_madd_epi16
(
mmtmpP1
,
rxdataF128
[
2
]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0
=
_mm_srai_epi32
(
mmtmpP0
,
output_shift
);
mmtmpP1
=
_mm_srai_epi32
(
mmtmpP1
,
output_shift
);
mmtmpP2
=
_mm_unpacklo_epi32
(
mmtmpP0
,
mmtmpP1
);
mmtmpP3
=
_mm_unpackhi_epi32
(
mmtmpP0
,
mmtmpP1
);
rxdataF_comp128
[
2
]
=
_mm_packs_epi32
(
mmtmpP2
,
mmtmpP3
);
// print_shorts("rx:",rxdataF128+2);
// print_shorts("ch:",dl_ch128+2);
// print_shorts("pack:",rxdataF_comp128+2);
dl_ch128
+=
3
;
rxdataF128
+=
3
;
rxdataF_comp128
+=
3
;
}
else
{
dl_ch128
+=
2
;
rxdataF128
+=
2
;
rxdataF_comp128
+=
2
;
}
#elif defined(__arm__)
// to be filled in
#endif
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
pbch_detection_mrc
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
uint8_t
symbol
)
{
uint8_t
aatx
,
symbol_mod
;
int
i
,
nb_rb
=
6
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
rxdataF_comp128_0
,
*
rxdataF_comp128_1
;
#elif defined(__arm__)
int16x8_t
*
rxdataF_comp128_0
,
*
rxdataF_comp128_1
;
#endif
symbol_mod
=
(
symbol
>=
(
7
-
frame_parms
->
Ncp
))
?
symbol
-
(
7
-
frame_parms
->
Ncp
)
:
symbol
;
if
(
frame_parms
->
nb_antennas_rx
>
1
)
{
for
(
aatx
=
0
;
aatx
<
4
;
aatx
++
)
{
//frame_parms->nb_antenna_ports_eNB;aatx++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0
=
(
__m128i
*
)
&
rxdataF_comp
[(
aatx
<<
1
)][
symbol_mod
*
6
*
12
];
rxdataF_comp128_1
=
(
__m128i
*
)
&
rxdataF_comp
[(
aatx
<<
1
)
+
1
][
symbol_mod
*
6
*
12
];
#elif defined(__arm__)
rxdataF_comp128_0
=
(
int16x8_t
*
)
&
rxdataF_comp
[(
aatx
<<
1
)][
symbol_mod
*
6
*
12
];
rxdataF_comp128_1
=
(
int16x8_t
*
)
&
rxdataF_comp
[(
aatx
<<
1
)
+
1
][
symbol_mod
*
6
*
12
];
#endif
// MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
for
(
i
=
0
;
i
<
nb_rb
*
3
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0
[
i
]
=
_mm_adds_epi16
(
_mm_srai_epi16
(
rxdataF_comp128_0
[
i
],
1
),
_mm_srai_epi16
(
rxdataF_comp128_1
[
i
],
1
));
#elif defined(__arm__)
rxdataF_comp128_0
[
i
]
=
vhaddq_s16
(
rxdataF_comp128_0
[
i
],
rxdataF_comp128_1
[
i
]);
#endif
}
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
pbch_unscrambling
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int8_t
*
llr
,
uint32_t
length
,
uint8_t
frame_mod4
)
{
int
i
;
uint8_t
reset
;
uint32_t
x1
,
x2
,
s
=
0
;
reset
=
1
;
// x1 is set in first call to lte_gold_generic
x2
=
frame_parms
->
Nid_cell
;
//this is c_init in 36.211 Sec 6.6.1
// msg("pbch_unscrambling: Nid_cell = %d\n",x2);
for
(
i
=
0
;
i
<
length
;
i
++
)
{
if
(
i
%
32
==
0
)
{
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
// printf("lte_gold[%d]=%x\n",i,s);
reset
=
0
;
}
// take the quarter of the PBCH that corresponds to this frame
if
((
i
>=
(
frame_mod4
*
(
length
>>
2
)))
&&
(
i
<
((
1
+
frame_mod4
)
*
(
length
>>
2
))))
{
if
(((
s
>>
(
i
%
32
))
&
1
)
==
0
)
llr
[
i
]
=
-
llr
[
i
];
}
}
}
void
pbch_alamouti
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
uint8_t
symbol
)
{
int16_t
*
rxF0
,
*
rxF1
;
// __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b;
uint8_t
rb
,
re
,
symbol_mod
;
int
jj
;
// printf("Doing alamouti\n");
symbol_mod
=
(
symbol
>=
(
7
-
frame_parms
->
Ncp
))
?
symbol
-
(
7
-
frame_parms
->
Ncp
)
:
symbol
;
jj
=
(
symbol_mod
*
6
*
12
);
rxF0
=
(
int16_t
*
)
&
rxdataF_comp
[
0
][
jj
];
//tx antenna 0 h0*y
rxF1
=
(
int16_t
*
)
&
rxdataF_comp
[
2
][
jj
];
//tx antenna 1 h1*y
for
(
rb
=
0
;
rb
<
6
;
rb
++
)
{
for
(
re
=
0
;
re
<
12
;
re
+=
2
)
{
// Alamouti RX combining
rxF0
[
0
]
=
rxF0
[
0
]
+
rxF1
[
2
];
rxF0
[
1
]
=
rxF0
[
1
]
-
rxF1
[
3
];
rxF0
[
2
]
=
rxF0
[
2
]
-
rxF1
[
0
];
rxF0
[
3
]
=
rxF0
[
3
]
+
rxF1
[
1
];
rxF0
+=
4
;
rxF1
+=
4
;
}
}
}
void
pbch_quantize
(
int8_t
*
pbch_llr8
,
int16_t
*
pbch_llr
,
uint16_t
len
)
{
uint16_t
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
pbch_llr
[
i
]
>
7
)
pbch_llr8
[
i
]
=
7
;
else
if
(
pbch_llr
[
i
]
<-
8
)
pbch_llr8
[
i
]
=-
8
;
else
pbch_llr8
[
i
]
=
(
char
)(
pbch_llr
[
i
]);
}
}
static
unsigned
char
dummy_w_rx
[
3
*
3
*
(
16
+
PBCH_A
)];
static
int8_t
pbch_w_rx
[
3
*
3
*
(
16
+
PBCH_A
)],
pbch_d_rx
[
96
+
(
3
*
(
16
+
PBCH_A
))];
uint16_t
rx_pbch
(
LTE_UE_COMMON
*
lte_ue_common_vars
,
LTE_UE_PBCH
*
lte_ue_pbch_vars
,
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
eNB_id
,
MIMO_mode_t
mimo_mode
,
uint32_t
high_speed_flag
,
uint8_t
frame_mod4
)
{
uint8_t
log2_maxh
;
//,aatx,aarx;
int
max_h
=
0
;
int
symbol
,
i
;
uint32_t
nsymb
=
(
frame_parms
->
Ncp
==
0
)
?
14
:
12
;
uint16_t
pbch_E
;
uint8_t
pbch_a
[
8
];
uint8_t
RCC
;
int8_t
*
pbch_e_rx
;
uint8_t
*
decoded_output
=
lte_ue_pbch_vars
->
decoded_output
;
uint16_t
crc
;
// pbch_D = 16+PBCH_A;
pbch_E
=
(
frame_parms
->
Ncp
==
0
)
?
1920
:
1728
;
//RE/RB * #RB * bits/RB (QPSK)
pbch_e_rx
=
&
lte_ue_pbch_vars
->
llr
[
frame_mod4
*
(
pbch_E
>>
2
)];
#ifdef DEBUG_PBCH
LOG_D
(
PHY
,
"[PBCH] starting symbol loop (Ncp %d, frame_mod4 %d,mimo_mode %d
\n
"
,
frame_parms
->
Ncp
,
frame_mod4
,
mimo_mode
);
#endif
// clear LLR buffer
memset
(
lte_ue_pbch_vars
->
llr
,
0
,
pbch_E
);
for
(
symbol
=
(
nsymb
>>
1
);
symbol
<
(
nsymb
>>
1
)
+
4
;
symbol
++
)
{
#ifdef DEBUG_PBCH
LOG_D
(
PHY
,
"[PBCH] starting extract
\n
"
);
#endif
pbch_extract
(
lte_ue_common_vars
->
common_vars_rx_data_per_thread
[
0
].
rxdataF
,
lte_ue_common_vars
->
common_vars_rx_data_per_thread
[
0
].
dl_ch_estimates
[
eNB_id
],
lte_ue_pbch_vars
->
rxdataF_ext
,
lte_ue_pbch_vars
->
dl_ch_estimates_ext
,
symbol
,
high_speed_flag
,
frame_parms
);
#ifdef DEBUG_PBCH
LOG_D
(
PHY
,
"[PHY] PBCH Symbol %d
\n
"
,
symbol
);
LOG_D
(
PHY
,
"[PHY] PBCH starting channel_level
\n
"
);
#endif
max_h
=
pbch_channel_level
(
lte_ue_pbch_vars
->
dl_ch_estimates_ext
,
frame_parms
,
symbol
);
log2_maxh
=
3
+
(
log2_approx
(
max_h
)
/
2
);
#ifdef DEBUG_PBCH
LOG_D
(
PHY
,
"[PHY] PBCH log2_maxh = %d (%d)
\n
"
,
log2_maxh
,
max_h
);
#endif
pbch_channel_compensation
(
lte_ue_pbch_vars
->
rxdataF_ext
,
lte_ue_pbch_vars
->
dl_ch_estimates_ext
,
lte_ue_pbch_vars
->
rxdataF_comp
,
frame_parms
,
symbol
,
log2_maxh
);
// log2_maxh+I0_shift
if
(
frame_parms
->
nb_antennas_rx
>
1
)
pbch_detection_mrc
(
frame_parms
,
lte_ue_pbch_vars
->
rxdataF_comp
,
symbol
);
if
(
mimo_mode
==
ALAMOUTI
)
{
pbch_alamouti
(
frame_parms
,
lte_ue_pbch_vars
->
rxdataF_comp
,
symbol
);
}
else
if
(
mimo_mode
!=
SISO
)
{
LOG_D
(
PHY
,
"[PBCH][RX] Unsupported MIMO mode
\n
"
);
return
(
-
1
);
}
if
(
symbol
>
(
nsymb
>>
1
)
+
1
)
{
pbch_quantize
(
pbch_e_rx
,
(
short
*
)
&
(
lte_ue_pbch_vars
->
rxdataF_comp
[
0
][(
symbol
%
(
nsymb
>>
1
))
*
72
]),
144
);
pbch_e_rx
+=
144
;
}
else
{
pbch_quantize
(
pbch_e_rx
,
(
short
*
)
&
(
lte_ue_pbch_vars
->
rxdataF_comp
[
0
][(
symbol
%
(
nsymb
>>
1
))
*
72
]),
96
);
pbch_e_rx
+=
96
;
}
}
pbch_e_rx
=
lte_ue_pbch_vars
->
llr
;
//un-scrambling
#ifdef DEBUG_PBCH
LOG_D
(
PHY
,
"[PBCH] doing unscrambling
\n
"
);
#endif
pbch_unscrambling
(
frame_parms
,
pbch_e_rx
,
pbch_E
,
frame_mod4
);
//un-rate matching
#ifdef DEBUG_PBCH
LOG_D
(
PHY
,
"[PBCH] doing un-rate-matching
\n
"
);
#endif
memset
(
dummy_w_rx
,
0
,
3
*
3
*
(
16
+
PBCH_A
));
RCC
=
generate_dummy_w_cc
(
16
+
PBCH_A
,
dummy_w_rx
);
lte_rate_matching_cc_rx
(
RCC
,
pbch_E
,
pbch_w_rx
,
dummy_w_rx
,
pbch_e_rx
);
sub_block_deinterleaving_cc
((
unsigned
int
)(
PBCH_A
+
16
),
&
pbch_d_rx
[
96
],
&
pbch_w_rx
[
0
]);
memset
(
pbch_a
,
0
,((
16
+
PBCH_A
)
>>
3
));
phy_viterbi_lte_sse2
(
pbch_d_rx
+
96
,
pbch_a
,
16
+
PBCH_A
);
// Fix byte endian of PBCH (bit 23 goes in first)
for
(
i
=
0
;
i
<
(
PBCH_A
>>
3
);
i
++
)
decoded_output
[(
PBCH_A
>>
3
)
-
i
-
1
]
=
pbch_a
[
i
];
#ifdef DEBUG_PBCH
for
(
i
=
0
;
i
<
(
PBCH_A
>>
3
);
i
++
)
LOG_I
(
PHY
,
"[PBCH] pbch_a[%d] = %x
\n
"
,
i
,
decoded_output
[
i
]);
#endif //DEBUG_PBCH
#ifdef DEBUG_PBCH
LOG_I
(
PHY
,
"PBCH CRC %x : %x
\n
"
,
crc16
(
pbch_a
,
PBCH_A
),
((
uint16_t
)
pbch_a
[
PBCH_A
>>
3
]
<<
8
)
+
pbch_a
[(
PBCH_A
>>
3
)
+
1
]);
#endif
crc
=
(
crc16
(
pbch_a
,
PBCH_A
)
>>
16
)
^
(((
uint16_t
)
pbch_a
[
PBCH_A
>>
3
]
<<
8
)
+
pbch_a
[(
PBCH_A
>>
3
)
+
1
]);
if
(
crc
==
0x0000
)
return
(
1
);
else
if
(
crc
==
0xffff
)
return
(
2
);
else
if
(
crc
==
0x5555
)
return
(
4
);
else
return
(
-
1
);
}
This diff is collapsed.
Click to expand it.
openair1/PHY/LTE_UE_TRANSPORT/pcfich_ue.c
0 → 100644
View file @
5619814b
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/pcfich.c
* \brief Top-level routines for generating and decoding the PCFICH/CFI physical/transport channel V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#include "PHY/defs.h"
//#define DEBUG_PCFICH
void
generate_pcfich_reg_mapping
(
LTE_DL_FRAME_PARMS
*
frame_parms
)
{
uint16_t
kbar
=
6
*
(
frame_parms
->
Nid_cell
%
(
2
*
frame_parms
->
N_RB_DL
));
uint16_t
first_reg
;
uint16_t
*
pcfich_reg
=
frame_parms
->
pcfich_reg
;
pcfich_reg
[
0
]
=
kbar
/
6
;
first_reg
=
pcfich_reg
[
0
];
frame_parms
->
pcfich_first_reg_idx
=
0
;
pcfich_reg
[
1
]
=
((
kbar
+
(
frame_parms
->
N_RB_DL
>>
1
)
*
6
)
%
(
frame_parms
->
N_RB_DL
*
12
))
/
6
;
if
(
pcfich_reg
[
1
]
<
pcfich_reg
[
0
])
{
frame_parms
->
pcfich_first_reg_idx
=
1
;
first_reg
=
pcfich_reg
[
1
];
}
pcfich_reg
[
2
]
=
((
kbar
+
(
frame_parms
->
N_RB_DL
)
*
6
)
%
(
frame_parms
->
N_RB_DL
*
12
))
/
6
;
if
(
pcfich_reg
[
2
]
<
first_reg
)
{
frame_parms
->
pcfich_first_reg_idx
=
2
;
first_reg
=
pcfich_reg
[
2
];
}
pcfich_reg
[
3
]
=
((
kbar
+
((
3
*
frame_parms
->
N_RB_DL
)
>>
1
)
*
6
)
%
(
frame_parms
->
N_RB_DL
*
12
))
/
6
;
if
(
pcfich_reg
[
3
]
<
first_reg
)
{
frame_parms
->
pcfich_first_reg_idx
=
3
;
first_reg
=
pcfich_reg
[
3
];
}
//#ifdef DEBUG_PCFICH
printf
(
"pcfich_reg : %d,%d,%d,%d
\n
"
,
pcfich_reg
[
0
],
pcfich_reg
[
1
],
pcfich_reg
[
2
],
pcfich_reg
[
3
]);
//#endif
}
void
pcfich_scrambling
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
subframe
,
uint8_t
*
b
,
uint8_t
*
bt
)
{
uint32_t
i
;
uint8_t
reset
;
uint32_t
x1
,
x2
,
s
=
0
;
reset
=
1
;
// x1 is set in lte_gold_generic
x2
=
((((
2
*
frame_parms
->
Nid_cell
)
+
1
)
*
(
1
+
subframe
))
<<
9
)
+
frame_parms
->
Nid_cell
;
//this is c_init in 36.211 Sec 6.7.1
for
(
i
=
0
;
i
<
32
;
i
++
)
{
if
((
i
&
0x1f
)
==
0
)
{
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
//printf("lte_gold[%d]=%x\n",i,s);
reset
=
0
;
}
bt
[
i
]
=
(
b
[
i
]
&
1
)
^
((
s
>>
(
i
&
0x1f
))
&
1
);
}
}
void
pcfich_unscrambling
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
subframe
,
int16_t
*
d
)
{
uint32_t
i
;
uint8_t
reset
;
uint32_t
x1
,
x2
,
s
=
0
;
reset
=
1
;
// x1 is set in lte_gold_generic
x2
=
((((
2
*
frame_parms
->
Nid_cell
)
+
1
)
*
(
1
+
subframe
))
<<
9
)
+
frame_parms
->
Nid_cell
;
//this is c_init in 36.211 Sec 6.7.1
for
(
i
=
0
;
i
<
32
;
i
++
)
{
if
((
i
&
0x1f
)
==
0
)
{
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
//printf("lte_gold[%d]=%x\n",i,s);
reset
=
0
;
}
if
(((
s
>>
(
i
&
0x1f
))
&
1
)
==
1
)
d
[
i
]
=-
d
[
i
];
}
}
uint8_t
pcfich_b
[
4
][
32
]
=
{{
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
},
{
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
},
{
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
,
0
,
1
,
1
},
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}
};
void
generate_pcfich
(
uint8_t
num_pdcch_symbols
,
int16_t
amp
,
LTE_DL_FRAME_PARMS
*
frame_parms
,
int32_t
**
txdataF
,
uint8_t
subframe
)
{
uint8_t
pcfich_bt
[
32
],
nsymb
,
pcfich_quad
;
int32_t
pcfich_d
[
2
][
16
];
uint8_t
i
;
uint32_t
symbol_offset
,
m
,
re_offset
,
reg_offset
;
int16_t
gain_lin_QPSK
;
uint16_t
*
pcfich_reg
=
frame_parms
->
pcfich_reg
;
int
nushiftmod3
=
frame_parms
->
nushift
%
3
;
#ifdef DEBUG_PCFICH
LOG_D
(
PHY
,
"Generating PCFICH in subfrmae %d for %d PDCCH symbols, AMP %d, p %d, Ncp %d
\n
"
,
subframe
,
num_pdcch_symbols
,
amp
,
frame_parms
->
nb_antenna_ports_eNB
,
frame_parms
->
Ncp
);
#endif
// scrambling
if
((
num_pdcch_symbols
>
0
)
&&
(
num_pdcch_symbols
<
4
))
pcfich_scrambling
(
frame_parms
,
subframe
,
pcfich_b
[
num_pdcch_symbols
-
1
],
pcfich_bt
);
// modulation
if
(
frame_parms
->
nb_antenna_ports_eNB
==
1
)
gain_lin_QPSK
=
(
int16_t
)((
amp
*
ONE_OVER_SQRT2_Q15
)
>>
15
);
else
gain_lin_QPSK
=
amp
/
2
;
if
(
frame_parms
->
nb_antenna_ports_eNB
==
1
)
{
// SISO
for
(
i
=
0
;
i
<
16
;
i
++
)
{
((
int16_t
*
)(
&
(
pcfich_d
[
0
][
i
])))[
0
]
=
((
pcfich_bt
[
2
*
i
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
((
int16_t
*
)(
&
(
pcfich_d
[
1
][
i
])))[
0
]
=
((
pcfich_bt
[
2
*
i
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
((
int16_t
*
)(
&
(
pcfich_d
[
0
][
i
])))[
1
]
=
((
pcfich_bt
[
2
*
i
+
1
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
((
int16_t
*
)(
&
(
pcfich_d
[
1
][
i
])))[
1
]
=
((
pcfich_bt
[
2
*
i
+
1
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
}
}
else
{
// ALAMOUTI
for
(
i
=
0
;
i
<
16
;
i
+=
2
)
{
// first antenna position n -> x0
((
int16_t
*
)(
&
(
pcfich_d
[
0
][
i
])))[
0
]
=
((
pcfich_bt
[
2
*
i
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
((
int16_t
*
)(
&
(
pcfich_d
[
0
][
i
])))[
1
]
=
((
pcfich_bt
[
2
*
i
+
1
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
// second antenna position n -> -x1*
((
int16_t
*
)(
&
(
pcfich_d
[
1
][
i
])))[
0
]
=
((
pcfich_bt
[
2
*
i
+
2
]
==
1
)
?
gain_lin_QPSK
:
-
gain_lin_QPSK
);
((
int16_t
*
)(
&
(
pcfich_d
[
1
][
i
])))[
1
]
=
((
pcfich_bt
[
2
*
i
+
3
]
==
1
)
?
-
gain_lin_QPSK
:
gain_lin_QPSK
);
// fill in the rest of the ALAMOUTI precoding
((
int16_t
*
)
&
pcfich_d
[
0
][
i
+
1
])[
0
]
=
-
((
int16_t
*
)
&
pcfich_d
[
1
][
i
])[
0
];
((
int16_t
*
)
&
pcfich_d
[
0
][
i
+
1
])[
1
]
=
((
int16_t
*
)
&
pcfich_d
[
1
][
i
])[
1
];
((
int16_t
*
)
&
pcfich_d
[
1
][
i
+
1
])[
0
]
=
((
int16_t
*
)
&
pcfich_d
[
0
][
i
])[
0
];
((
int16_t
*
)
&
pcfich_d
[
1
][
i
+
1
])[
1
]
=
-
((
int16_t
*
)
&
pcfich_d
[
0
][
i
])[
1
];
}
}
// mapping
nsymb
=
(
frame_parms
->
Ncp
==
0
)
?
14
:
12
;
symbol_offset
=
(
uint32_t
)
frame_parms
->
ofdm_symbol_size
*
(
subframe
*
nsymb
);
re_offset
=
frame_parms
->
first_carrier_offset
;
// loop over 4 quadruplets and lookup REGs
m
=
0
;
for
(
pcfich_quad
=
0
;
pcfich_quad
<
4
;
pcfich_quad
++
)
{
reg_offset
=
re_offset
+
((
uint16_t
)
pcfich_reg
[
pcfich_quad
]
*
6
);
if
(
reg_offset
>=
frame_parms
->
ofdm_symbol_size
)
reg_offset
=
1
+
reg_offset
-
frame_parms
->
ofdm_symbol_size
;
for
(
i
=
0
;
i
<
6
;
i
++
)
{
if
((
i
!=
nushiftmod3
)
&&
(
i
!=
(
nushiftmod3
+
3
)))
{
txdataF
[
0
][
symbol_offset
+
reg_offset
+
i
]
=
pcfich_d
[
0
][
m
];
if
(
frame_parms
->
nb_antenna_ports_eNB
>
1
)
txdataF
[
1
][
symbol_offset
+
reg_offset
+
i
]
=
pcfich_d
[
1
][
m
];
m
++
;
}
}
}
}
uint8_t
rx_pcfich
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
subframe
,
LTE_UE_PDCCH
*
lte_ue_pdcch_vars
,
MIMO_mode_t
mimo_mode
)
{
uint8_t
pcfich_quad
;
uint8_t
i
,
j
;
uint16_t
reg_offset
;
int32_t
**
rxdataF_comp
=
lte_ue_pdcch_vars
->
rxdataF_comp
;
int16_t
pcfich_d
[
32
],
*
pcfich_d_ptr
;
int32_t
metric
,
old_metric
=-
16384
;
uint8_t
num_pdcch_symbols
=
3
;
uint16_t
*
pcfich_reg
=
frame_parms
->
pcfich_reg
;
// demapping
// loop over 4 quadruplets and lookup REGs
// m=0;
pcfich_d_ptr
=
pcfich_d
;
for
(
pcfich_quad
=
0
;
pcfich_quad
<
4
;
pcfich_quad
++
)
{
reg_offset
=
(
pcfich_reg
[
pcfich_quad
]
*
4
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
pcfich_d_ptr
[
0
]
=
((
int16_t
*
)
&
rxdataF_comp
[
0
][
reg_offset
+
i
])[
0
];
// RE component
pcfich_d_ptr
[
1
]
=
((
int16_t
*
)
&
rxdataF_comp
[
0
][
reg_offset
+
i
])[
1
];
// IM component
#ifdef DEBUG_PCFICH
printf
(
"rx_pcfich: quad %d, i %d, offset %d => (%d,%d) => pcfich_d_ptr[0] %d
\n
"
,
pcfich_quad
,
i
,
reg_offset
+
i
,
((
int16_t
*
)
&
rxdataF_comp
[
0
][
reg_offset
+
i
])[
0
],
((
int16_t
*
)
&
rxdataF_comp
[
0
][
reg_offset
+
i
])[
1
],
pcfich_d_ptr
[
0
]);
#endif
pcfich_d_ptr
+=
2
;
}
/*
}
else { // ALAMOUTI
for (i=0;i<4;i+=2) {
pcfich_d_ptr[0] = 0;
pcfich_d_ptr[1] = 0;
pcfich_d_ptr[2] = 0;
pcfich_d_ptr[3] = 0;
for (j=0;j<frame_parms->nb_antennas_rx;j++) {
pcfich_d_ptr[0] += (((int16_t*)&rxdataF_comp[j][reg_offset+i])[0]+
((int16_t*)&rxdataF_comp[j+2][reg_offset+i+1])[0]); // RE component
pcfich_d_ptr[1] += (((int16_t*)&rxdataF_comp[j][reg_offset+i])[1] -
((int16_t*)&rxdataF_comp[j+2][reg_offset+i+1])[1]);// IM component
pcfich_d_ptr[2] += (((int16_t*)&rxdataF_comp[j][reg_offset+i+1])[0]-
((int16_t*)&rxdataF_comp[j+2][reg_offset+i])[0]); // RE component
pcfich_d_ptr[3] += (((int16_t*)&rxdataF_comp[j][reg_offset+i+1])[1] +
((int16_t*)&rxdataF_comp[j+2][reg_offset+i])[1]);// IM component
}
pcfich_d_ptr+=4;
}
*/
}
// pcfhich unscrambling
pcfich_unscrambling
(
frame_parms
,
subframe
,
pcfich_d
);
// pcfich detection
for
(
i
=
0
;
i
<
3
;
i
++
)
{
metric
=
0
;
for
(
j
=
0
;
j
<
32
;
j
++
)
{
// printf("pcfich_b[%d][%d] %d => pcfich_d[%d] %d\n",i,j,pcfich_b[i][j],j,pcfich_d[j]);
metric
+=
(
int32_t
)(((
pcfich_b
[
i
][
j
]
==
0
)
?
(
pcfich_d
[
j
])
:
(
-
pcfich_d
[
j
])));
}
#ifdef DEBUG_PCFICH
printf
(
"metric %d : %d
\n
"
,
i
,
metric
);
#endif
if
(
metric
>
old_metric
)
{
num_pdcch_symbols
=
1
+
i
;
old_metric
=
metric
;
}
}
#ifdef DEBUG_PCFICH
printf
(
"[PHY] PCFICH detected for %d PDCCH symbols
\n
"
,
num_pdcch_symbols
);
#endif
return
(
num_pdcch_symbols
);
}
This diff is collapsed.
Click to expand it.
openair1/PHY/LTE_UE_TRANSPORT/pch_ue.c
0 → 100644
View file @
5619814b
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "assertions.h"
const
unsigned
int
Ttab
[
4
]
=
{
32
,
64
,
128
,
256
};
// This function implements the initialization of paging parameters for UE (See Section 7, 36.304)
// It must be called after setting IMSImod1024 during UE startup and after receiving SIB2
int
init_ue_paging_info
(
PHY_VARS_UE
*
ue
,
long
defaultPagingCycle
,
long
nB
)
{
LTE_DL_FRAME_PARMS
*
fp
=
&
ue
->
frame_parms
;
unsigned
int
T
=
Ttab
[
defaultPagingCycle
];
unsigned
int
N
=
(
nB
<=
2
)
?
T
:
(
T
>>
(
nB
-
2
));
unsigned
int
Ns
=
(
nB
<
2
)
?
(
1
<<
(
2
-
nB
))
:
1
;
unsigned
int
UE_ID
=
ue
->
IMSImod1024
;
unsigned
int
i_s
=
(
UE_ID
/
N
)
%
Ns
;
ue
->
PF
=
(
T
/
N
)
*
(
UE_ID
%
N
);
// This implements Section 7.2 from 36.304
if
(
Ns
==
1
)
ue
->
PO
=
(
fp
->
frame_type
==
FDD
)
?
9
:
0
;
else
if
(
Ns
==
2
)
ue
->
PO
=
(
fp
->
frame_type
==
FDD
)
?
(
4
+
(
5
*
i_s
))
:
(
5
*
i_s
);
else
if
(
Ns
==
4
)
ue
->
PO
=
(
fp
->
frame_type
==
FDD
)
?
(
4
*
(
i_s
&
1
)
+
(
5
*
(
i_s
>>
1
)))
:
((
i_s
&
1
)
+
(
5
*
(
i_s
>>
1
)));
else
AssertFatal
(
1
==
0
,
"init_ue_paging_info: Ns is %d
\n
"
,
Ns
);
return
(
0
);
}
This diff is collapsed.
Click to expand it.
openair1/PHY/LTE_UE_TRANSPORT/phich_ue.c
0 → 100644
View file @
5619814b
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/phich.c
* \brief Top-level routines for generating and decoding the PHICH/HI physical/transport channel V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "defs.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.h"
#include "T.h"
//#define DEBUG_PHICH 1
//extern unsigned short pcfich_reg[4];
//extern unsigned char pcfich_first_reg_idx;
//unsigned short phich_reg[MAX_NUM_PHICH_GROUPS][3];
uint8_t
rv_table
[
4
]
=
{
0
,
2
,
3
,
1
};
uint8_t
get_mi
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
subframe
)
{
// for FDD
if
(
frame_parms
->
frame_type
==
FDD
)
return
1
;
// for TDD
switch
(
frame_parms
->
tdd_config
)
{
case
0
:
if
((
subframe
==
0
)
||
(
subframe
==
5
))
return
(
2
);
else
return
(
1
);
break
;
case
1
:
if
((
subframe
==
0
)
||
(
subframe
==
5
))
return
(
0
);
else
return
(
1
);
break
;
case
2
:
if
((
subframe
==
3
)
||
(
subframe
==
8
))
return
(
1
);
else
return
(
0
);
break
;
case
3
:
if
((
subframe
==
0
)
||
(
subframe
==
8
)
||
(
subframe
==
9
))
return
(
1
);
else
return
(
0
);
break
;
case
4
:
if
((
subframe
==
8
)
||
(
subframe
==
9
))
return
(
1
);
else
return
(
0
);
break
;
case
5
:
if
(
subframe
==
8
)
return
(
1
);
else
return
(
0
);
break
;
case
6
:
return
(
1
);
break
;
default:
return
(
0
);
}
}
unsigned
char
subframe2_ul_harq
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
unsigned
char
subframe
)
{
if
(
frame_parms
->
frame_type
==
FDD
)
return
(
subframe
&
7
);
switch
(
frame_parms
->
tdd_config
)
{
case
3
:
if
(
(
subframe
==
8
)
||
(
subframe
==
9
)
)
{
return
(
subframe
-
8
);
}
else
if
(
subframe
==
0
)
return
(
2
);
else
{
LOG_E
(
PHY
,
"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
return
(
0
);
}
break
;
case
4
:
if
(
(
subframe
==
8
)
||
(
subframe
==
9
)
)
{
return
(
subframe
-
8
);
}
else
{
LOG_E
(
PHY
,
"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
return
(
0
);
}
break
;
}
return
(
0
);
}
int
phich_frame2_pusch_frame
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
frame
,
int
subframe
)
{
int
pusch_frame
;
if
(
frame_parms
->
frame_type
==
FDD
)
{
pusch_frame
=
subframe
<
4
?
frame
+
1024
-
1
:
frame
;
}
else
{
// Note this is not true, but it doesn't matter, the frame number is irrelevant for TDD!
pusch_frame
=
(
frame
);
}
//LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, subframe, pusch_frame);
return
pusch_frame
%
1024
;
}
uint8_t
phich_subframe2_pusch_subframe
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
subframe
)
{
uint8_t
pusch_subframe
=
255
;
if
(
frame_parms
->
frame_type
==
FDD
)
return
subframe
<
4
?
subframe
+
6
:
subframe
-
4
;
switch
(
frame_parms
->
tdd_config
)
{
case
0
:
if
(
subframe
==
0
)
pusch_subframe
=
(
3
);
else
if
(
subframe
==
5
)
{
pusch_subframe
=
(
8
);
}
else
if
(
subframe
==
6
)
pusch_subframe
=
(
2
);
else
if
(
subframe
==
1
)
pusch_subframe
=
(
7
);
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
case
1
:
if
(
subframe
==
6
)
pusch_subframe
=
(
2
);
else
if
(
subframe
==
9
)
pusch_subframe
=
(
3
);
else
if
(
subframe
==
1
)
pusch_subframe
=
(
7
);
else
if
(
subframe
==
4
)
pusch_subframe
=
(
8
);
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
case
2
:
if
(
subframe
==
8
)
pusch_subframe
=
(
2
);
else
if
(
subframe
==
3
)
pusch_subframe
=
(
7
);
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
case
3
:
if
(
(
subframe
==
8
)
||
(
subframe
==
9
)
)
{
pusch_subframe
=
(
subframe
-
6
);
}
else
if
(
subframe
==
0
)
pusch_subframe
=
(
4
);
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
case
4
:
if
(
(
subframe
==
8
)
||
(
subframe
==
9
)
)
{
pusch_subframe
=
(
subframe
-
6
);
}
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
case
5
:
if
(
subframe
==
8
)
{
pusch_subframe
=
(
2
);
}
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
case
6
:
if
(
subframe
==
6
)
{
pusch_subframe
=
(
2
);
}
else
if
(
subframe
==
9
)
{
pusch_subframe
=
(
3
);
}
else
if
(
subframe
==
0
)
{
pusch_subframe
=
(
4
);
}
else
if
(
subframe
==
1
)
{
pusch_subframe
=
(
7
);
}
else
if
(
subframe
==
5
)
{
pusch_subframe
=
(
8
);
}
else
{
AssertFatal
(
1
==
0
,
"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d
\n
"
,
subframe
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
break
;
default:
AssertFatal
(
1
==
0
,
"no implementation for TDD UL/DL-config = %d!
\n
"
,
frame_parms
->
tdd_config
);
pusch_subframe
=
(
0
);
}
LOG_D
(
PHY
,
"subframe %d: PUSCH subframe = %d
\n
"
,
subframe
,
pusch_subframe
);
return
pusch_subframe
;
}
int
check_pcfich
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint16_t
reg
)
{
if
((
reg
==
frame_parms
->
pcfich_reg
[
0
])
||
(
reg
==
frame_parms
->
pcfich_reg
[
1
])
||
(
reg
==
frame_parms
->
pcfich_reg
[
2
])
||
(
reg
==
frame_parms
->
pcfich_reg
[
3
]))
return
(
1
);
return
(
0
);
}
void
generate_phich_reg_mapping
(
LTE_DL_FRAME_PARMS
*
frame_parms
)
{
unsigned
short
n0
=
(
frame_parms
->
N_RB_DL
*
2
)
-
4
;
// 2 REG per RB less the 4 used by PCFICH in first symbol
unsigned
short
n1
=
(
frame_parms
->
N_RB_DL
*
3
);
// 3 REG per RB in second and third symbol
unsigned
short
n2
=
n1
;
unsigned
short
mprime
=
0
;
unsigned
short
Ngroup_PHICH
;
// uint16_t *phich_reg = frame_parms->phich_reg;
uint16_t
*
pcfich_reg
=
frame_parms
->
pcfich_reg
;
// compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211
Ngroup_PHICH
=
(
frame_parms
->
phich_config_common
.
phich_resource
*
frame_parms
->
N_RB_DL
)
/
48
;
if
(((
frame_parms
->
phich_config_common
.
phich_resource
*
frame_parms
->
N_RB_DL
)
%
48
)
>
0
)
Ngroup_PHICH
++
;
// check if Extended prefix
if
(
frame_parms
->
Ncp
==
1
)
{
Ngroup_PHICH
<<=
1
;
}
#ifdef DEBUG_PHICH
LOG_D
(
PHY
,
"Ngroup_PHICH %d (phich_config_common.phich_resource %d,phich_config_common.phich_duration %s, NidCell %d,Ncp %d, frame_type %d), smallest pcfich REG %d, n0 %d, n1 %d (first PHICH REG %d)
\n
"
,
((
frame_parms
->
Ncp
==
NORMAL
)
?
Ngroup_PHICH
:
(
Ngroup_PHICH
>>
1
)),
frame_parms
->
phich_config_common
.
phich_resource
,
frame_parms
->
phich_config_common
.
phich_duration
==
normal
?
"normal"
:
"extended"
,
frame_parms
->
Nid_cell
,
frame_parms
->
Ncp
,
frame_parms
->
frame_type
,
pcfich_reg
[
frame_parms
->
pcfich_first_reg_idx
],
n0
,
n1
,
((
frame_parms
->
Nid_cell
))
%
n0
);
#endif
// This is the algorithm from Section 6.9.3 in 36-211, it works only for normal PHICH duration for now ...
for
(
mprime
=
0
;
mprime
<
((
frame_parms
->
Ncp
==
NORMAL
)
?
Ngroup_PHICH
:
(
Ngroup_PHICH
>>
1
));
mprime
++
)
{
if
(
frame_parms
->
phich_config_common
.
phich_duration
==
normal
)
{
// normal PHICH duration
frame_parms
->
phich_reg
[
mprime
][
0
]
=
(
frame_parms
->
Nid_cell
+
mprime
)
%
n0
;
if
(
frame_parms
->
phich_reg
[
mprime
][
0
]
>=
pcfich_reg
[
frame_parms
->
pcfich_first_reg_idx
])
frame_parms
->
phich_reg
[
mprime
][
0
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
0
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
1
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
0
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
0
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
2
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
0
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
0
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
3
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
0
]
++
;
frame_parms
->
phich_reg
[
mprime
][
1
]
=
(
frame_parms
->
Nid_cell
+
mprime
+
(
n0
/
3
))
%
n0
;
if
(
frame_parms
->
phich_reg
[
mprime
][
1
]
>=
pcfich_reg
[
frame_parms
->
pcfich_first_reg_idx
])
frame_parms
->
phich_reg
[
mprime
][
1
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
1
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
1
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
1
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
1
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
2
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
1
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
1
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
3
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
1
]
++
;
frame_parms
->
phich_reg
[
mprime
][
2
]
=
(
frame_parms
->
Nid_cell
+
mprime
+
(
2
*
n0
/
3
))
%
n0
;
if
(
frame_parms
->
phich_reg
[
mprime
][
2
]
>=
pcfich_reg
[
frame_parms
->
pcfich_first_reg_idx
])
frame_parms
->
phich_reg
[
mprime
][
2
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
2
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
1
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
2
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
2
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
2
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
2
]
++
;
if
(
frame_parms
->
phich_reg
[
mprime
][
2
]
>=
pcfich_reg
[(
frame_parms
->
pcfich_first_reg_idx
+
3
)
&
3
])
frame_parms
->
phich_reg
[
mprime
][
2
]
++
;
#ifdef DEBUG_PHICH
printf
(
"phich_reg :%d => %d,%d,%d
\n
"
,
mprime
,
frame_parms
->
phich_reg
[
mprime
][
0
],
frame_parms
->
phich_reg
[
mprime
][
1
],
frame_parms
->
phich_reg
[
mprime
][
2
]);
#endif
}
else
{
// extended PHICH duration
frame_parms
->
phich_reg
[
mprime
<<
1
][
0
]
=
(
frame_parms
->
Nid_cell
+
mprime
)
%
n0
;
frame_parms
->
phich_reg
[
1
+
(
mprime
<<
1
)][
0
]
=
(
frame_parms
->
Nid_cell
+
mprime
)
%
n0
;
frame_parms
->
phich_reg
[
mprime
<<
1
][
1
]
=
((
frame_parms
->
Nid_cell
*
n1
/
n0
)
+
mprime
+
(
n1
/
3
))
%
n1
;
frame_parms
->
phich_reg
[
mprime
<<
1
][
2
]
=
((
frame_parms
->
Nid_cell
*
n2
/
n0
)
+
mprime
+
(
2
*
n2
/
3
))
%
n2
;
frame_parms
->
phich_reg
[
1
+
(
mprime
<<
1
)][
1
]
=
((
frame_parms
->
Nid_cell
*
n1
/
n0
)
+
mprime
+
(
n1
/
3
))
%
n1
;
frame_parms
->
phich_reg
[
1
+
(
mprime
<<
1
)][
2
]
=
((
frame_parms
->
Nid_cell
*
n2
/
n0
)
+
mprime
+
(
2
*
n2
/
3
))
%
n2
;
//#ifdef DEBUG_PHICH
printf
(
"phich_reg :%d => %d,%d,%d
\n
"
,
mprime
<<
1
,
frame_parms
->
phich_reg
[
mprime
<<
1
][
0
],
frame_parms
->
phich_reg
[
mprime
][
1
],
frame_parms
->
phich_reg
[
mprime
][
2
]);
printf
(
"phich_reg :%d => %d,%d,%d
\n
"
,
1
+
(
mprime
<<
1
),
frame_parms
->
phich_reg
[
1
+
(
mprime
<<
1
)][
0
],
frame_parms
->
phich_reg
[
1
+
(
mprime
<<
1
)][
1
],
frame_parms
->
phich_reg
[
1
+
(
mprime
<<
1
)][
2
]);
//#endif
}
}
// mprime loop
}
// num_pdcch_symbols loop
void
generate_phich_emul
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
uint8_t
HI
,
uint8_t
subframe
)
{
}
int32_t
alam_bpsk_perm1
[
4
]
=
{
2
,
1
,
4
,
3
};
// -conj(x) 1 (-1-j) -> 2 (1-j), 2->1, 3 (-1+j) -> (4) 1+j, 4->3
int32_t
alam_bpsk_perm2
[
4
]
=
{
3
,
4
,
2
,
1
};
// conj(x) 1 (-1-j) -> 3 (-1+j), 3->1, 2 (1-j) -> 4 (1+j), 4->2
// This routine generates the PHICH
void
generate_phich
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int16_t
amp
,
uint8_t
nseq_PHICH
,
uint8_t
ngroup_PHICH
,
uint8_t
HI
,
uint8_t
subframe
,
int32_t
**
y
)
{
int16_t
d
[
24
],
*
dp
;
// unsigned int i,aa;
unsigned
int
re_offset
;
int16_t
y0_16
[
8
],
y1_16
[
8
];
int16_t
*
y0
,
*
y1
;
// scrambling
uint32_t
x1
,
x2
,
s
=
0
;
uint8_t
reset
=
1
;
int16_t
cs
[
12
];
uint32_t
i
,
i2
,
i3
,
m
,
j
;
int16_t
gain_lin_QPSK
;
uint32_t
subframe_offset
=
((
frame_parms
->
Ncp
==
0
)
?
14
:
12
)
*
frame_parms
->
ofdm_symbol_size
*
subframe
;
memset
(
d
,
0
,
24
*
sizeof
(
int16_t
));
if
(
frame_parms
->
nb_antenna_ports_eNB
==
1
)
gain_lin_QPSK
=
(
int16_t
)(((
int32_t
)
amp
*
ONE_OVER_SQRT2_Q15
)
>>
15
);
else
gain_lin_QPSK
=
amp
/
2
;
//printf("PHICH : gain_lin_QPSK %d\n",gain_lin_QPSK);
// BPSK modulation of HI input (to be repeated 3 times, 36-212 Section 5.3.5, p. 56 in v8.6)
if
(
HI
>
0
)
HI
=
1
;
// c = (1-(2*HI))*SSS_AMP;
// x1 is set in lte_gold_generic
x2
=
(((
subframe
+
1
)
*
((
frame_parms
->
Nid_cell
<<
1
)
+
1
))
<<
9
)
+
frame_parms
->
Nid_cell
;
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
// compute scrambling sequence
for
(
i
=
0
;
i
<
12
;
i
++
)
{
cs
[
i
]
=
(
uint8_t
)((
s
>>
(
i
&
0x1f
))
&
1
);
cs
[
i
]
=
(
cs
[
i
]
==
0
)
?
(
1
-
(
HI
<<
1
))
:
((
HI
<<
1
)
-
1
);
}
if
(
frame_parms
->
Ncp
==
0
)
{
// Normal Cyclic Prefix
// printf("Doing PHICH : Normal CP, subframe %d\n",subframe);
// 12 output symbols (Msymb)
for
(
i
=
0
,
i2
=
0
,
i3
=
0
;
i
<
3
;
i
++
,
i2
+=
4
,
i3
+=
8
)
{
switch
(
nseq_PHICH
)
{
case
0
:
// +1 +1 +1 +1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
1
:
// +1 -1 +1 -1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
break
;
case
2
:
// +1 +1 -1 -1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
break
;
case
3
:
// +1 -1 -1 +1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
4
:
// +j +j +j +j
d
[
i3
]
=
-
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
5
:
// +j -j +j -j
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
i3
]
=
-
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
6
:
// +j +j -j -j
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
i3
]
=
-
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
7
:
// +j -j -j +j
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
d
[
i3
]
=
-
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
break
;
default:
AssertFatal
(
1
==
0
,
"phich_coding.c: Illegal PHICH Number
\n
"
);
}
// nseq_PHICH
}
#ifdef DEBUG_PHICH
LOG_D
(
PHY
,
"[PUSCH 0]PHICH d = "
);
for
(
i
=
0
;
i
<
24
;
i
+=
2
)
LOG_D
(
PHY
,
"(%d,%d)"
,
d
[
i
],
d
[
i
+
1
]);
LOG_D
(
PHY
,
"
\n
"
);
#endif
// modulation here
if
(
frame_parms
->
nb_antenna_ports_eNB
!=
1
)
{
// do Alamouti precoding here
// Symbol 0
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
0
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y1
=
(
int16_t
*
)
&
y
[
1
][
re_offset
+
subframe_offset
];
// first antenna position n -> x0
y0_16
[
0
]
=
d
[
0
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
1
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
0
]
=
-
d
[
2
]
*
gain_lin_QPSK
;
y1_16
[
1
]
=
d
[
3
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
2
]
=
-
y1_16
[
0
];
y0_16
[
3
]
=
y1_16
[
1
];
y1_16
[
2
]
=
y0_16
[
0
];
y1_16
[
3
]
=
-
y0_16
[
1
];
// first antenna position n -> x0
y0_16
[
4
]
=
d
[
4
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
5
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
4
]
=
-
d
[
6
]
*
gain_lin_QPSK
;
y1_16
[
5
]
=
d
[
7
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
6
]
=
-
y1_16
[
4
];
y0_16
[
7
]
=
y1_16
[
5
];
y1_16
[
6
]
=
y0_16
[
4
];
y1_16
[
7
]
=
-
y0_16
[
5
];
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
];
y1
[
j
]
+=
y1_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
];
y1
[
j
+
1
]
+=
y1_16
[
m
++
];
}
}
// Symbol 1
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
1
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y1
=
(
int16_t
*
)
&
y
[
1
][
re_offset
+
subframe_offset
];
// first antenna position n -> x0
y0_16
[
0
]
=
d
[
8
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
9
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
0
]
=
-
d
[
10
]
*
gain_lin_QPSK
;
y1_16
[
1
]
=
d
[
11
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
2
]
=
-
y1_16
[
0
];
y0_16
[
3
]
=
y1_16
[
1
];
y1_16
[
2
]
=
y0_16
[
0
];
y1_16
[
3
]
=
-
y0_16
[
1
];
// first antenna position n -> x0
y0_16
[
4
]
=
d
[
12
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
13
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
4
]
=
-
d
[
14
]
*
gain_lin_QPSK
;
y1_16
[
5
]
=
d
[
15
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
6
]
=
-
y1_16
[
4
];
y0_16
[
7
]
=
y1_16
[
5
];
y1_16
[
6
]
=
y0_16
[
4
];
y1_16
[
7
]
=
-
y0_16
[
5
];
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
];
y1
[
j
]
+=
y1_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
];
y1
[
j
+
1
]
+=
y1_16
[
m
++
];
}
}
// Symbol 2
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
2
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y1
=
(
int16_t
*
)
&
y
[
1
][
re_offset
+
subframe_offset
];
// first antenna position n -> x0
y0_16
[
0
]
=
d
[
16
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
17
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
0
]
=
-
d
[
18
]
*
gain_lin_QPSK
;
y1_16
[
1
]
=
d
[
19
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
2
]
=
-
y1_16
[
0
];
y0_16
[
3
]
=
y1_16
[
1
];
y1_16
[
2
]
=
y0_16
[
0
];
y1_16
[
3
]
=
-
y0_16
[
1
];
// first antenna position n -> x0
y0_16
[
4
]
=
d
[
20
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
21
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
4
]
=
-
d
[
22
]
*
gain_lin_QPSK
;
y1_16
[
5
]
=
d
[
23
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
6
]
=
-
y1_16
[
4
];
y0_16
[
7
]
=
y1_16
[
5
];
y1_16
[
6
]
=
y0_16
[
4
];
y1_16
[
7
]
=
-
y0_16
[
5
];
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
];
y1
[
j
]
+=
y1_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
];
y1
[
j
+
1
]
+=
y1_16
[
m
++
];
}
}
}
// nb_antenna_ports_eNB
else
{
// Symbol 0
// printf("[PUSCH 0]PHICH REG %d\n",frame_parms->phich_reg[ngroup_PHICH][0]);
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
0
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
// printf("y0 %p\n",y0);
y0_16
[
0
]
=
d
[
0
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
1
]
*
gain_lin_QPSK
;
y0_16
[
2
]
=
d
[
2
]
*
gain_lin_QPSK
;
y0_16
[
3
]
=
d
[
3
]
*
gain_lin_QPSK
;
y0_16
[
4
]
=
d
[
4
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
5
]
*
gain_lin_QPSK
;
y0_16
[
6
]
=
d
[
6
]
*
gain_lin_QPSK
;
y0_16
[
7
]
=
d
[
7
]
*
gain_lin_QPSK
;
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
++
];
}
}
// Symbol 1
// printf("[PUSCH 0]PHICH REG %d\n",frame_parms->phich_reg[ngroup_PHICH][1]);
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
1
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y0_16
[
0
]
=
d
[
8
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
9
]
*
gain_lin_QPSK
;
y0_16
[
2
]
=
d
[
10
]
*
gain_lin_QPSK
;
y0_16
[
3
]
=
d
[
11
]
*
gain_lin_QPSK
;
y0_16
[
4
]
=
d
[
12
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
13
]
*
gain_lin_QPSK
;
y0_16
[
6
]
=
d
[
14
]
*
gain_lin_QPSK
;
y0_16
[
7
]
=
d
[
15
]
*
gain_lin_QPSK
;
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
++
];
}
}
// Symbol 2
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
2
]
*
6
);
// printf("[PUSCH 0]PHICH REG %d\n",frame_parms->phich_reg[ngroup_PHICH][2]);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y0_16
[
0
]
=
d
[
16
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
17
]
*
gain_lin_QPSK
;
y0_16
[
2
]
=
d
[
18
]
*
gain_lin_QPSK
;
y0_16
[
3
]
=
d
[
19
]
*
gain_lin_QPSK
;
y0_16
[
4
]
=
d
[
20
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
21
]
*
gain_lin_QPSK
;
y0_16
[
6
]
=
d
[
22
]
*
gain_lin_QPSK
;
y0_16
[
7
]
=
d
[
23
]
*
gain_lin_QPSK
;
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
++
];
}
}
/*
for (i=0;i<512;i++)
printf("re %d (%d): %d,%d\n",i,subframe_offset+i,((int16_t*)&y[0][subframe_offset+i])[0],((int16_t*)&y[0][subframe_offset+i])[1]);
*/
}
// nb_antenna_ports_eNB
}
else
{
// extended prefix
// 6 output symbols
if
((
ngroup_PHICH
&
1
)
==
1
)
dp
=
&
d
[
4
];
else
dp
=
d
;
switch
(
nseq_PHICH
)
{
case
0
:
// +1 +1
dp
[
0
]
=
cs
[
0
];
dp
[
2
]
=
cs
[
1
];
dp
[
8
]
=
cs
[
2
];
dp
[
10
]
=
cs
[
3
];
dp
[
16
]
=
cs
[
4
];
dp
[
18
]
=
cs
[
5
];
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
cs
[
5
];
break
;
case
1
:
// +1 -1
dp
[
0
]
=
cs
[
0
];
dp
[
2
]
=
-
cs
[
1
];
dp
[
8
]
=
cs
[
2
];
dp
[
10
]
=
-
cs
[
3
];
dp
[
16
]
=
cs
[
4
];
dp
[
18
]
=
-
cs
[
5
];
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
-
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
-
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
-
cs
[
5
];
break
;
case
2
:
// +j +j
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
cs
[
5
];
dp
[
0
]
=
-
cs
[
0
];
dp
[
2
]
=
-
cs
[
1
];
dp
[
8
]
=
-
cs
[
2
];
dp
[
10
]
=
-
cs
[
3
];
dp
[
16
]
=
-
cs
[
4
];
dp
[
18
]
=
-
cs
[
5
];
break
;
case
3
:
// +j -j
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
-
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
-
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
-
cs
[
5
];
dp
[
0
]
=
-
cs
[
0
];
dp
[
2
]
=
cs
[
1
];
dp
[
8
]
=
-
cs
[
2
];
dp
[
10
]
=
cs
[
3
];
dp
[
16
]
=
-
cs
[
4
];
dp
[
18
]
=
cs
[
5
];
break
;
default:
AssertFatal
(
1
==
0
,
"phich_coding.c: Illegal PHICH Number
\n
"
);
}
if
(
frame_parms
->
nb_antenna_ports_eNB
!=
1
)
{
// do Alamouti precoding here
// Symbol 0
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
0
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y1
=
(
int16_t
*
)
&
y
[
1
][
re_offset
+
subframe_offset
];
// first antenna position n -> x0
y0_16
[
0
]
=
d
[
0
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
1
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
0
]
=
-
d
[
2
]
*
gain_lin_QPSK
;
y1_16
[
1
]
=
d
[
3
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
2
]
=
-
y1_16
[
0
];
y0_16
[
3
]
=
y1_16
[
1
];
y1_16
[
2
]
=
y0_16
[
0
];
y1_16
[
3
]
=
-
y0_16
[
1
];
// first antenna position n -> x0
y0_16
[
4
]
=
d
[
4
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
5
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
4
]
=
-
d
[
6
]
*
gain_lin_QPSK
;
y1_16
[
5
]
=
d
[
7
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
6
]
=
-
y1_16
[
4
];
y0_16
[
7
]
=
y1_16
[
5
];
y1_16
[
6
]
=
y0_16
[
4
];
y1_16
[
7
]
=
-
y0_16
[
5
];
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
];
y1
[
j
]
+=
y1_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
];
y1
[
j
+
1
]
+=
y1_16
[
m
++
];
}
}
// Symbol 1
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
1
]
<<
2
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
re_offset
+=
(
frame_parms
->
ofdm_symbol_size
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y1
=
(
int16_t
*
)
&
y
[
1
][
re_offset
+
subframe_offset
];
// first antenna position n -> x0
y0_16
[
0
]
=
d
[
8
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
9
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
0
]
=
-
d
[
10
]
*
gain_lin_QPSK
;
y1_16
[
1
]
=
d
[
11
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
2
]
=
-
y1_16
[
0
];
y0_16
[
3
]
=
y1_16
[
1
];
y1_16
[
2
]
=
y0_16
[
0
];
y1_16
[
3
]
=
-
y0_16
[
1
];
// first antenna position n -> x0
y0_16
[
4
]
=
d
[
12
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
13
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
4
]
=
-
d
[
14
]
*
gain_lin_QPSK
;
y1_16
[
5
]
=
d
[
15
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
6
]
=
-
y1_16
[
4
];
y0_16
[
7
]
=
y1_16
[
5
];
y1_16
[
6
]
=
y0_16
[
4
];
y1_16
[
7
]
=
-
y0_16
[
5
];
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
4
;
i
++
,
j
+=
2
)
{
y0
[
j
]
+=
y0_16
[
m
];
y1
[
j
]
+=
y1_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
];
y1
[
j
+
1
]
+=
y1_16
[
m
++
];
}
// Symbol 2
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
2
]
<<
2
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
re_offset
+=
(
frame_parms
->
ofdm_symbol_size
<<
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y1
=
(
int16_t
*
)
&
y
[
1
][
re_offset
+
subframe_offset
];
// first antenna position n -> x0
y0_16
[
0
]
=
d
[
16
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
17
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
0
]
=
-
d
[
18
]
*
gain_lin_QPSK
;
y1_16
[
1
]
=
d
[
19
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
2
]
=
-
y1_16
[
0
];
y0_16
[
3
]
=
y1_16
[
1
];
y1_16
[
2
]
=
y0_16
[
0
];
y1_16
[
3
]
=
-
y0_16
[
1
];
// first antenna position n -> x0
y0_16
[
4
]
=
d
[
20
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
21
]
*
gain_lin_QPSK
;
// second antenna position n -> -x1*
y1_16
[
4
]
=
-
d
[
22
]
*
gain_lin_QPSK
;
y1_16
[
5
]
=
d
[
23
]
*
gain_lin_QPSK
;
// fill in the rest of the ALAMOUTI precoding
y0_16
[
6
]
=
-
y1_16
[
4
];
y0_16
[
7
]
=
y1_16
[
5
];
y1_16
[
6
]
=
y0_16
[
4
];
y1_16
[
7
]
=
-
y0_16
[
5
];
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
4
;
i
++
,
j
+=
2
)
{
y0
[
j
]
+=
y0_16
[
m
];
y1
[
j
]
+=
y1_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
];
y1
[
j
+
1
]
+=
y1_16
[
m
++
];
}
}
else
{
// Symbol 0
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
0
]
*
6
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y0_16
[
0
]
=
d
[
0
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
1
]
*
gain_lin_QPSK
;
y0_16
[
2
]
=
d
[
2
]
*
gain_lin_QPSK
;
y0_16
[
3
]
=
d
[
3
]
*
gain_lin_QPSK
;
y0_16
[
4
]
=
d
[
4
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
5
]
*
gain_lin_QPSK
;
y0_16
[
6
]
=
d
[
6
]
*
gain_lin_QPSK
;
y0_16
[
7
]
=
d
[
7
]
*
gain_lin_QPSK
;
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
6
;
i
++
,
j
+=
2
)
{
if
((
i
!=
(
frame_parms
->
nushift
))
&&
(
i
!=
(
frame_parms
->
nushift
+
3
)))
{
y0
[
j
]
+=
y0_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
++
];
}
}
// Symbol 1
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
1
]
<<
2
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
re_offset
+=
(
frame_parms
->
ofdm_symbol_size
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y0_16
[
0
]
=
d
[
8
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
9
]
*
gain_lin_QPSK
;
y0_16
[
2
]
=
d
[
10
]
*
gain_lin_QPSK
;
y0_16
[
3
]
=
d
[
11
]
*
gain_lin_QPSK
;
y0_16
[
4
]
=
d
[
12
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
13
]
*
gain_lin_QPSK
;
y0_16
[
6
]
=
d
[
14
]
*
gain_lin_QPSK
;
y0_16
[
7
]
=
d
[
15
]
*
gain_lin_QPSK
;
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
4
;
i
++
,
j
+=
2
)
{
y0
[
j
]
+=
y0_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
++
];
}
// Symbol 2
re_offset
=
frame_parms
->
first_carrier_offset
+
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
2
]
<<
2
);
if
(
re_offset
>
frame_parms
->
ofdm_symbol_size
)
re_offset
-=
(
frame_parms
->
ofdm_symbol_size
-
1
);
re_offset
+=
(
frame_parms
->
ofdm_symbol_size
<<
1
);
y0
=
(
int16_t
*
)
&
y
[
0
][
re_offset
+
subframe_offset
];
y0_16
[
0
]
=
d
[
16
]
*
gain_lin_QPSK
;
y0_16
[
1
]
=
d
[
17
]
*
gain_lin_QPSK
;
y0_16
[
2
]
=
d
[
18
]
*
gain_lin_QPSK
;
y0_16
[
3
]
=
d
[
19
]
*
gain_lin_QPSK
;
y0_16
[
4
]
=
d
[
20
]
*
gain_lin_QPSK
;
y0_16
[
5
]
=
d
[
21
]
*
gain_lin_QPSK
;
y0_16
[
6
]
=
d
[
22
]
*
gain_lin_QPSK
;
y0_16
[
7
]
=
d
[
23
]
*
gain_lin_QPSK
;
for
(
i
=
0
,
j
=
0
,
m
=
0
;
i
<
4
;
i
++
)
{
y0
[
j
]
+=
y0_16
[
m
++
];
y0
[
j
+
1
]
+=
y0_16
[
m
++
];
}
}
// nb_antenna_ports_eNB
}
// normal/extended prefix
}
// This routine demodulates the PHICH and updates PUSCH/ULSCH parameters
void
rx_phich
(
PHY_VARS_UE
*
ue
,
UE_rxtx_proc_t
*
proc
,
uint8_t
subframe
,
uint8_t
eNB_id
)
{
LTE_DL_FRAME_PARMS
*
frame_parms
=&
ue
->
frame_parms
;
LTE_UE_PDCCH
**
pdcch_vars
=
&
ue
->
pdcch_vars
[
ue
->
current_thread_id
[
subframe
]][
eNB_id
];
// uint8_t HI;
uint8_t
harq_pid
=
phich_subframe_to_harq_pid
(
frame_parms
,
proc
->
frame_rx
,
subframe
);
LTE_UE_ULSCH_t
*
ulsch
=
ue
->
ulsch
[
eNB_id
];
int16_t
phich_d
[
24
],
*
phich_d_ptr
,
HI16
;
// unsigned int i,aa;
int8_t
d
[
24
],
*
dp
;
uint16_t
reg_offset
;
// scrambling
uint32_t
x1
,
x2
,
s
=
0
;
uint8_t
reset
=
1
;
int16_t
cs
[
12
];
uint32_t
i
,
i2
,
i3
,
phich_quad
;
int32_t
**
rxdataF_comp
=
pdcch_vars
[
eNB_id
]
->
rxdataF_comp
;
uint8_t
Ngroup_PHICH
,
ngroup_PHICH
,
nseq_PHICH
;
uint8_t
NSF_PHICH
=
4
;
uint8_t
pusch_subframe
;
int8_t
delta_PUSCH_acc
[
4
]
=
{
-
1
,
0
,
1
,
3
};
// check if we're expecting a PHICH in this subframe
LOG_D
(
PHY
,
"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX
\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
,
subframe
);
if
(
!
ulsch
)
return
;
LOG_D
(
PHY
,
"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX Status: %d
\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
,
subframe
,
ulsch
->
harq_processes
[
harq_pid
]
->
status
);
if
(
ulsch
->
harq_processes
[
harq_pid
]
->
status
==
ACTIVE
)
{
LOG_D
(
PHY
,
"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX ACTIVE
\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
,
subframe
);
Ngroup_PHICH
=
(
frame_parms
->
phich_config_common
.
phich_resource
*
frame_parms
->
N_RB_DL
)
/
48
;
if
(((
frame_parms
->
phich_config_common
.
phich_resource
*
frame_parms
->
N_RB_DL
)
%
48
)
>
0
)
Ngroup_PHICH
++
;
if
(
frame_parms
->
Ncp
==
1
)
NSF_PHICH
=
2
;
ngroup_PHICH
=
(
ulsch
->
harq_processes
[
harq_pid
]
->
first_rb
+
ulsch
->
harq_processes
[
harq_pid
]
->
n_DMRS
)
%
Ngroup_PHICH
;
if
((
frame_parms
->
tdd_config
==
0
)
&&
(
frame_parms
->
frame_type
==
TDD
)
)
{
pusch_subframe
=
phich_subframe2_pusch_subframe
(
frame_parms
,
subframe
);
if
((
pusch_subframe
==
4
)
||
(
pusch_subframe
==
9
))
ngroup_PHICH
+=
Ngroup_PHICH
;
}
nseq_PHICH
=
((
ulsch
->
harq_processes
[
harq_pid
]
->
first_rb
/
Ngroup_PHICH
)
+
ulsch
->
harq_processes
[
harq_pid
]
->
n_DMRS
)
%
(
2
*
NSF_PHICH
);
}
else
{
LOG_D
(
PHY
,
"[UE %d][PUSCH %d] Frame %d subframe %d PHICH RX %s
\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
,
subframe
,
(
ulsch
->
harq_processes
[
harq_pid
]
->
status
==
SCH_IDLE
?
"SCH_IDLE"
:
(
ulsch
->
harq_processes
[
harq_pid
]
->
status
==
ACTIVE
?
"ACTIVE"
:
(
ulsch
->
harq_processes
[
harq_pid
]
->
status
==
CBA_ACTIVE
?
"CBA_ACTIVE"
:
(
ulsch
->
harq_processes
[
harq_pid
]
->
status
==
DISABLED
?
"DISABLED"
:
"UNKNOWN"
)))));
return
;
}
memset
(
d
,
0
,
24
*
sizeof
(
int8_t
));
phich_d_ptr
=
phich_d
;
// x1 is set in lte_gold_generic
x2
=
(((
subframe
+
1
)
*
((
frame_parms
->
Nid_cell
<<
1
)
+
1
))
<<
9
)
+
frame_parms
->
Nid_cell
;
s
=
lte_gold_generic
(
&
x1
,
&
x2
,
reset
);
// compute scrambling sequence
for
(
i
=
0
;
i
<
12
;
i
++
)
{
cs
[
i
]
=
1
-
(((
s
>>
(
i
&
0x1f
))
&
1
)
<<
1
);
}
if
(
frame_parms
->
Ncp
==
0
)
{
// Normal Cyclic Prefix
// 12 output symbols (Msymb)
for
(
i
=
0
,
i2
=
0
,
i3
=
0
;
i
<
3
;
i
++
,
i2
+=
4
,
i3
+=
8
)
{
switch
(
nseq_PHICH
)
{
case
0
:
// +1 +1 +1 +1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
1
:
// +1 -1 +1 -1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
break
;
case
2
:
// +1 +1 -1 -1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
break
;
case
3
:
// +1 -1 -1 +1
d
[
i3
]
=
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
4
:
// +j +j +j +j
d
[
i3
]
=
-
cs
[
i2
];
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
5
:
// +j -j +j -j
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
5
+
i3
]
=
cs
[
2
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
i3
]
=
-
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
6
:
// +j +j -j -j
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
3
+
i3
]
=
cs
[
1
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
7
+
i3
]
=
-
cs
[
3
+
i2
];
d
[
i3
]
=
-
cs
[
i2
];
d
[
2
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
cs
[
3
+
i2
];
break
;
case
7
:
// +j -j -j +j
d
[
1
+
i3
]
=
cs
[
i2
];
d
[
3
+
i3
]
=
-
cs
[
1
+
i2
];
d
[
5
+
i3
]
=
-
cs
[
2
+
i2
];
d
[
7
+
i3
]
=
cs
[
3
+
i2
];
d
[
i3
]
=
-
cs
[
i2
];
d
[
2
+
i3
]
=
cs
[
1
+
i2
];
d
[
4
+
i3
]
=
cs
[
2
+
i2
];
d
[
6
+
i3
]
=
-
cs
[
3
+
i2
];
break
;
default:
AssertFatal
(
1
==
0
,
"phich_coding.c: Illegal PHICH Number
\n
"
);
}
// nseq_PHICH
}
#ifdef DEBUG_PHICH
LOG_D
(
PHY
,
"PHICH =>"
);
for
(
i
=
0
;
i
<
24
;
i
++
)
{
LOG_D
(
PHY
,
"%2d,"
,
d
[
i
]);
}
LOG_D
(
PHY
,
"
\n
"
);
#endif
// demodulation here
}
else
{
// extended prefix
// 6 output symbols
if
((
ngroup_PHICH
&
1
)
==
1
)
dp
=
&
d
[
4
];
else
dp
=
d
;
switch
(
nseq_PHICH
)
{
case
0
:
// +1 +1
dp
[
0
]
=
cs
[
0
];
dp
[
2
]
=
cs
[
1
];
dp
[
8
]
=
cs
[
2
];
dp
[
10
]
=
cs
[
3
];
dp
[
16
]
=
cs
[
4
];
dp
[
18
]
=
cs
[
5
];
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
cs
[
5
];
break
;
case
1
:
// +1 -1
dp
[
0
]
=
cs
[
0
];
dp
[
2
]
=
-
cs
[
1
];
dp
[
8
]
=
cs
[
2
];
dp
[
10
]
=
-
cs
[
3
];
dp
[
16
]
=
cs
[
4
];
dp
[
18
]
=
-
cs
[
5
];
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
-
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
-
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
-
cs
[
5
];
break
;
case
2
:
// +j +j
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
cs
[
5
];
dp
[
0
]
=
-
cs
[
0
];
dp
[
2
]
=
-
cs
[
1
];
dp
[
8
]
=
-
cs
[
2
];
dp
[
10
]
=
-
cs
[
3
];
dp
[
16
]
=
-
cs
[
4
];
dp
[
18
]
=
-
cs
[
5
];
break
;
case
3
:
// +j -j
dp
[
1
]
=
cs
[
0
];
dp
[
3
]
=
-
cs
[
1
];
dp
[
9
]
=
cs
[
2
];
dp
[
11
]
=
-
cs
[
3
];
dp
[
17
]
=
cs
[
4
];
dp
[
19
]
=
-
cs
[
5
];
dp
[
0
]
=
-
cs
[
0
];
dp
[
2
]
=
cs
[
1
];
dp
[
8
]
=
-
cs
[
2
];
dp
[
10
]
=
cs
[
3
];
dp
[
16
]
=
-
cs
[
4
];
dp
[
18
]
=
cs
[
5
];
break
;
default:
AssertFatal
(
1
==
0
,
"phich_coding.c: Illegal PHICH Number
\n
"
);
}
}
HI16
=
0
;
//#ifdef DEBUG_PHICH
//#endif
/*
for (i=0;i<200;i++)
printf("re %d: %d %d\n",i,((int16_t*)&rxdataF_comp[0][i])[0],((int16_t*)&rxdataF_comp[0][i])[1]);
*/
for
(
phich_quad
=
0
;
phich_quad
<
3
;
phich_quad
++
)
{
if
(
frame_parms
->
Ncp
==
1
)
reg_offset
=
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
phich_quad
]
*
4
)
+
(
phich_quad
*
frame_parms
->
N_RB_DL
*
12
);
else
reg_offset
=
(
frame_parms
->
phich_reg
[
ngroup_PHICH
][
phich_quad
]
*
4
);
// msg("\n[PUSCH 0]PHICH (RX) quad %d (%d)=>",phich_quad,reg_offset);
dp
=
&
d
[
phich_quad
*
8
];;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
phich_d_ptr
[
i
]
=
((
int16_t
*
)
&
rxdataF_comp
[
0
][
reg_offset
])[
i
];
#ifdef DEBUG_PHICH
LOG_D
(
PHY
,
"%d,"
,((
int16_t
*
)
&
rxdataF_comp
[
0
][
reg_offset
])[
i
]);
#endif
HI16
+=
(
phich_d_ptr
[
i
]
*
dp
[
i
]);
}
}
#ifdef DEBUG_PHICH
LOG_D
(
PHY
,
"
\n
"
);
LOG_D
(
PHY
,
"HI16 %d
\n
"
,
HI16
);
#endif
if
(
HI16
>
0
)
{
//NACK
if
(
ue
->
ulsch_Msg3_active
[
eNB_id
]
==
1
)
{
LOG_D
(
PHY
,
"[UE %d][PUSCH %d][RAPROC] Frame %d subframe %d Msg3 PHICH, received NAK (%d) nseq %d, ngroup %d
\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
,
subframe
,
HI16
,
nseq_PHICH
,
ngroup_PHICH
);
ulsch
->
f_pusch
+=
delta_PUSCH_acc
[
ulsch
->
harq_processes
[
harq_pid
]
->
TPC
];
LOG_D
(
PHY
,
"[PUSCH %d] AbsSubframe %d.%d: f_pusch (ACC) %d, adjusting by %d (TPC %d)
\n
"
,
harq_pid
,
proc
->
frame_rx
,
subframe
,
ulsch
->
f_pusch
,
delta_PUSCH_acc
[
ulsch
->
harq_processes
[
harq_pid
]
->
TPC
],
ulsch
->
harq_processes
[
harq_pid
]
->
TPC
);
ulsch
->
harq_processes
[
harq_pid
]
->
subframe_scheduling_flag
=
1
;
// ulsch->harq_processes[harq_pid]->Ndi = 0;
ulsch
->
harq_processes
[
harq_pid
]
->
round
++
;
ulsch
->
harq_processes
[
harq_pid
]
->
rvidx
=
rv_table
[
ulsch
->
harq_processes
[
harq_pid
]
->
round
&
3
];
if
(
ulsch
->
harq_processes
[
harq_pid
]
->
round
>=
ue
->
frame_parms
.
maxHARQ_Msg3Tx
)
{
ulsch
->
harq_processes
[
harq_pid
]
->
subframe_scheduling_flag
=
0
;
ulsch
->
harq_processes
[
harq_pid
]
->
status
=
SCH_IDLE
;
// inform MAC that Msg3 transmission has failed
ue
->
ulsch_Msg3_active
[
eNB_id
]
=
0
;
}
}
else
{
#ifdef UE_DEBUG_TRACE
LOG_D
(
PHY
,
"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received NAK (%d) nseq %d, ngroup %d round %d (Mlimit %d)
\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
%
1024
,
subframe
,
HI16
,
nseq_PHICH
,
ngroup_PHICH
,
ulsch
->
harq_processes
[
harq_pid
]
->
round
,
ulsch
->
Mlimit
);
#endif
// ulsch->harq_processes[harq_pid]->Ndi = 0;
ulsch
->
harq_processes
[
harq_pid
]
->
round
++
;
if
(
ulsch
->
harq_processes
[
harq_pid
]
->
round
>=
(
ulsch
->
Mlimit
-
1
)
)
{
// this is last push re transmission
ulsch
->
harq_processes
[
harq_pid
]
->
rvidx
=
rv_table
[
ulsch
->
harq_processes
[
harq_pid
]
->
round
&
3
];
ulsch
->
O_RI
=
0
;
ulsch
->
O
=
0
;
ulsch
->
uci_format
=
HLC_subband_cqi_nopmi
;
// disable phich decoding since it is the last retransmission
ulsch
->
harq_processes
[
harq_pid
]
->
status
=
SCH_IDLE
;
//ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
//ulsch->harq_processes[harq_pid]->round = 0;
//LOG_I(PHY,"PUSCH MAX Retransmission acheived ==> flush harq buff (%d) \n",harq_pid);
//LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH NACK MAX RETRANS(%d) ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->Mlimit, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag, ulsch->harq_processes[harq_pid]->round);
}
else
{
// ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
ulsch
->
harq_processes
[
harq_pid
]
->
rvidx
=
rv_table
[
ulsch
->
harq_processes
[
harq_pid
]
->
round
&
3
];
ulsch
->
O_RI
=
0
;
ulsch
->
O
=
0
;
ulsch
->
uci_format
=
HLC_subband_cqi_nopmi
;
//LOG_I(PHY,"[HARQ-UL harqId: %d] PHICH NACK ==> subframe_scheduling_flag = %d round: %d\n", harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag,ulsch->harq_processes[harq_pid]->round);
}
}
#if T_TRACER
T
(
T_UE_PHY_ULSCH_UE_NACK
,
T_INT
(
eNB_id
),
T_INT
(
proc
->
frame_rx
%
1024
),
T_INT
(
subframe
),
T_INT
(
ulsch
->
rnti
),
T_INT
(
harq_pid
));
#endif
}
else
{
//ACK
if
(
ue
->
ulsch_Msg3_active
[
eNB_id
]
==
1
)
{
LOG_D
(
PHY
,
"[UE %d][PUSCH %d][RAPROC] Frame %d subframe %d Msg3 PHICH, received ACK (%d) nseq %d, ngroup %d
\n\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
,
subframe
,
HI16
,
nseq_PHICH
,
ngroup_PHICH
);
}
else
{
#ifdef UE_DEBUG_TRACE
LOG_D
(
PHY
,
"[UE %d][PUSCH %d] Frame %d subframe %d PHICH, received ACK (%d) nseq %d, ngroup %d
\n\n
"
,
ue
->
Mod_id
,
harq_pid
,
proc
->
frame_rx
%
1024
,
subframe
,
HI16
,
nseq_PHICH
,
ngroup_PHICH
);
#endif
}
// LOG_I(PHY,"[HARQ-UL harqId: %d] subframe_scheduling_flag = %d \n",harq_pid, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag);
// Incase of adaptive retransmission, PHICH is always decoded as ACK (at least with OAI-eNB)
// Workaround:
// rely only on DCI0 decoding and check if NDI has toggled
// save current harq_processes content in temporary struct
// harqId-8 corresponds to the temporary struct. In total we have 8 harq process(0 ..7) + 1 temporary harq process()
//ulsch->harq_processes[8] = ulsch->harq_processes[harq_pid];
ulsch
->
harq_processes
[
harq_pid
]
->
status
=
SCH_IDLE
;
ulsch
->
harq_processes
[
harq_pid
]
->
round
=
0
;
ulsch
->
harq_processes
[
harq_pid
]
->
subframe_scheduling_flag
=
0
;
// inform MAC?
ue
->
ulsch_Msg3_active
[
eNB_id
]
=
0
;
#if T_TRACER
T
(
T_UE_PHY_ULSCH_UE_ACK
,
T_INT
(
eNB_id
),
T_INT
(
proc
->
frame_rx
%
1024
),
T_INT
(
subframe
),
T_INT
(
ulsch
->
rnti
),
T_INT
(
harq_pid
));
#endif
}
}
void
generate_phich_top
(
PHY_VARS_eNB
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
int16_t
amp
)
{
LTE_DL_FRAME_PARMS
*
frame_parms
=&
eNB
->
frame_parms
;
int32_t
**
txdataF
=
eNB
->
common_vars
.
txdataF
;
uint8_t
harq_pid
;
uint8_t
Ngroup_PHICH
,
ngroup_PHICH
,
nseq_PHICH
;
uint8_t
NSF_PHICH
=
4
;
uint8_t
pusch_subframe
;
uint8_t
i
;
uint32_t
pusch_frame
;
int
subframe
=
proc
->
subframe_tx
;
phich_config_t
*
phich
;
// compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211
Ngroup_PHICH
=
(
frame_parms
->
phich_config_common
.
phich_resource
*
frame_parms
->
N_RB_DL
)
/
48
;
if
(((
frame_parms
->
phich_config_common
.
phich_resource
*
frame_parms
->
N_RB_DL
)
%
48
)
>
0
)
Ngroup_PHICH
++
;
if
(
frame_parms
->
Ncp
==
1
)
NSF_PHICH
=
2
;
if
(
eNB
->
phich_vars
[
subframe
&
1
].
num_hi
>
0
)
{
pusch_frame
=
phich_frame2_pusch_frame
(
frame_parms
,
proc
->
frame_tx
,
subframe
);
pusch_subframe
=
phich_subframe2_pusch_subframe
(
frame_parms
,
subframe
);
harq_pid
=
subframe2harq_pid
(
frame_parms
,
pusch_frame
,
pusch_subframe
);
}
for
(
i
=
0
;
i
<
eNB
->
phich_vars
[
subframe
&
1
].
num_hi
;
i
++
)
{
phich
=
&
eNB
->
phich_vars
[
subframe
&
1
].
config
[
i
];
ngroup_PHICH
=
(
phich
->
first_rb
+
phich
->
n_DMRS
)
%
Ngroup_PHICH
;
if
((
frame_parms
->
tdd_config
==
0
)
&&
(
frame_parms
->
frame_type
==
TDD
)
)
{
if
((
pusch_subframe
==
4
)
||
(
pusch_subframe
==
9
))
ngroup_PHICH
+=
Ngroup_PHICH
;
}
nseq_PHICH
=
((
phich
->
first_rb
/
Ngroup_PHICH
)
+
phich
->
n_DMRS
)
%
(
2
*
NSF_PHICH
);
LOG_D
(
PHY
,
"[eNB %d][PUSCH %d] Frame %d subframe %d Generating PHICH, AMP %d ngroup_PHICH %d/%d, nseq_PHICH %d : HI %d, first_rb %d)
\n
"
,
eNB
->
Mod_id
,
harq_pid
,
proc
->
frame_tx
,
subframe
,
amp
,
ngroup_PHICH
,
Ngroup_PHICH
,
nseq_PHICH
,
phich
->
hi
,
phich
->
first_rb
);
T
(
T_ENB_PHY_PHICH
,
T_INT
(
eNB
->
Mod_id
),
T_INT
(
proc
->
frame_tx
),
T_INT
(
subframe
),
T_INT
(
-
1
/* TODO: rnti */
),
T_INT
(
harq_pid
),
T_INT
(
Ngroup_PHICH
),
T_INT
(
NSF_PHICH
),
T_INT
(
ngroup_PHICH
),
T_INT
(
nseq_PHICH
),
T_INT
(
phich
->
hi
),
T_INT
(
phich
->
first_rb
),
T_INT
(
phich
->
n_DMRS
));
generate_phich
(
frame_parms
,
amp
,
//amp*2,
nseq_PHICH
,
ngroup_PHICH
,
phich
->
hi
,
subframe
,
txdataF
);
}
// for (i=0; i<eNB->phich_vars[subframe&1].num_hi; i++) {
eNB
->
phich_vars
[
subframe
&
1
].
num_hi
=
0
;
}
This diff is collapsed.
Click to expand it.
openair1/PHY/LTE_UE_TRANSPORT/pmch_ue.c
0 → 100644
View file @
5619814b
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/sse_intrin.h"
// Mask for identifying subframe for MBMS
#define MBSFN_TDD_SF3 0x80// for TDD
#define MBSFN_TDD_SF4 0x40
#define MBSFN_TDD_SF7 0x20
#define MBSFN_TDD_SF8 0x10
#define MBSFN_TDD_SF9 0x08
#include "PHY/defs.h"
#define MBSFN_FDD_SF1 0x80// for FDD
#define MBSFN_FDD_SF2 0x40
#define MBSFN_FDD_SF3 0x20
#define MBSFN_FDD_SF6 0x10
#define MBSFN_FDD_SF7 0x08
#define MBSFN_FDD_SF8 0x04
void
dump_mch
(
PHY_VARS_UE
*
ue
,
uint8_t
eNB_id
,
uint16_t
coded_bits_per_codeword
,
int
subframe
)
{
unsigned
int
nsymb_pmch
=
12
;
char
fname
[
32
],
vname
[
32
];
int
N_RB_DL
=
ue
->
frame_parms
.
N_RB_DL
;
sprintf
(
fname
,
"mch_rxF_ext0.m"
);
sprintf
(
vname
,
"pmch_rxF_ext0"
);
write_output
(
fname
,
vname
,
ue
->
pdsch_vars_MCH
[
eNB_id
]
->
rxdataF_ext
[
0
],
12
*
N_RB_DL
*
nsymb_pmch
,
1
,
1
);
sprintf
(
fname
,
"mch_ch_ext00.m"
);
sprintf
(
vname
,
"pmch_ch_ext00"
);
write_output
(
fname
,
vname
,
ue
->
pdsch_vars_MCH
[
eNB_id
]
->
dl_ch_estimates_ext
[
0
],
12
*
N_RB_DL
*
nsymb_pmch
,
1
,
1
);
/*
write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb_pmch,1,1);
write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb_pmch,1,1);
write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb_pmch,1,1);
write_output("dlsch%d_rho.m","dl_rho",pdsch_vars[eNB_id]->rho[0],12*N_RB_DL*nsymb_pmch,1,1);
*/
sprintf
(
fname
,
"mch_rxF_comp0.m"
);
sprintf
(
vname
,
"pmch_rxF_comp0"
);
write_output
(
fname
,
vname
,
ue
->
pdsch_vars_MCH
[
eNB_id
]
->
rxdataF_comp0
[
0
],
12
*
N_RB_DL
*
nsymb_pmch
,
1
,
1
);
sprintf
(
fname
,
"mch_rxF_llr.m"
);
sprintf
(
vname
,
"pmch_llr"
);
write_output
(
fname
,
vname
,
ue
->
pdsch_vars_MCH
[
eNB_id
]
->
llr
[
0
],
coded_bits_per_codeword
,
1
,
0
);
sprintf
(
fname
,
"mch_mag1.m"
);
sprintf
(
vname
,
"pmch_mag1"
);
write_output
(
fname
,
vname
,
ue
->
pdsch_vars_MCH
[
eNB_id
]
->
dl_ch_mag0
[
0
],
12
*
N_RB_DL
*
nsymb_pmch
,
1
,
1
);
sprintf
(
fname
,
"mch_mag2.m"
);
sprintf
(
vname
,
"pmch_mag2"
);
write_output
(
fname
,
vname
,
ue
->
pdsch_vars_MCH
[
eNB_id
]
->
dl_ch_magb0
[
0
],
12
*
N_RB_DL
*
nsymb_pmch
,
1
,
1
);
write_output
(
"mch00_ch0.m"
,
"pmch00_ch0"
,
&
(
ue
->
common_vars
.
common_vars_rx_data_per_thread
[
ue
->
current_thread_id
[
subframe
]].
dl_ch_estimates
[
eNB_id
][
0
][
0
]),
ue
->
frame_parms
.
ofdm_symbol_size
*
12
,
1
,
1
);
write_output
(
"rxsig_mch.m"
,
"rxs_mch"
,
&
ue
->
common_vars
.
rxdata
[
0
][
subframe
*
ue
->
frame_parms
.
samples_per_tti
],
ue
->
frame_parms
.
samples_per_tti
,
1
,
1
);
/*
if (PHY_vars_eNB_g)
write_output("txsig_mch.m","txs_mch",
&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0][subframe*ue->frame_parms.samples_per_tti],
ue->frame_parms.samples_per_tti,1,1);*/
}
int
is_pmch_subframe
(
uint32_t
frame
,
int
subframe
,
LTE_DL_FRAME_PARMS
*
frame_parms
)
{
uint32_t
period
;
uint8_t
i
;
// LOG_D(PHY,"is_pmch_subframe: frame %d, subframe %d, num_MBSFN_config %d\n",
// frame,subframe,frame_parms->num_MBSFN_config);
for
(
i
=
0
;
i
<
frame_parms
->
num_MBSFN_config
;
i
++
)
{
// we have at least one MBSFN configuration
period
=
1
<<
frame_parms
->
MBSFN_config
[
i
].
radioframeAllocationPeriod
;
if
((
frame
%
period
)
==
frame_parms
->
MBSFN_config
[
i
].
radioframeAllocationOffset
)
{
if
(
frame_parms
->
MBSFN_config
[
i
].
fourFrames_flag
==
0
)
{
if
(
frame_parms
->
frame_type
==
FDD
)
{
switch
(
subframe
)
{
case
1
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_FDD_SF1
)
>
0
)
return
(
1
);
break
;
case
2
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_FDD_SF2
)
>
0
)
return
(
1
);
break
;
case
3
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_FDD_SF3
)
>
0
)
return
(
1
);
break
;
case
6
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_FDD_SF6
)
>
0
)
return
(
1
);
break
;
case
7
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_FDD_SF7
)
>
0
)
return
(
1
);
break
;
case
8
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_FDD_SF8
)
>
0
)
return
(
1
);
break
;
}
}
else
{
switch
(
subframe
)
{
case
3
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_TDD_SF3
)
>
0
)
return
(
1
);
break
;
case
4
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_TDD_SF4
)
>
0
)
return
(
1
);
break
;
case
7
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_TDD_SF7
)
>
0
)
return
(
1
);
break
;
case
8
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_TDD_SF8
)
>
0
)
return
(
1
);
break
;
case
9
:
if
((
frame_parms
->
MBSFN_config
[
i
].
mbsfn_SubframeConfig
&
MBSFN_TDD_SF9
)
>
0
)
return
(
1
);
break
;
}
}
}
else
{
// handle 4 frames case
}
}
}
return
(
0
);
}
void
fill_eNB_dlsch_MCH
(
PHY_VARS_eNB
*
eNB
,
int
mcs
,
int
ndi
,
int
rvidx
)
{
LTE_eNB_DLSCH_t
*
dlsch
=
eNB
->
dlsch_MCH
;
LTE_DL_FRAME_PARMS
*
frame_parms
=&
eNB
->
frame_parms
;
// dlsch->rnti = M_RNTI;
dlsch
->
harq_processes
[
0
]
->
mcs
=
mcs
;
// dlsch->harq_processes[0]->Ndi = ndi;
dlsch
->
harq_processes
[
0
]
->
rvidx
=
rvidx
;
dlsch
->
harq_processes
[
0
]
->
Nl
=
1
;
dlsch
->
harq_processes
[
0
]
->
TBS
=
TBStable
[
get_I_TBS
(
dlsch
->
harq_processes
[
0
]
->
mcs
)][
frame_parms
->
N_RB_DL
-
1
];
// dlsch->harq_ids[subframe] = 0;
dlsch
->
harq_processes
[
0
]
->
nb_rb
=
frame_parms
->
N_RB_DL
;
switch
(
frame_parms
->
N_RB_DL
)
{
case
6
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
0
]
=
0x3f
;
break
;
case
25
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
0
]
=
0x1ffffff
;
break
;
case
50
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
0
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
1
]
=
0x3ffff
;
break
;
case
100
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
0
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
1
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
2
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc
[
3
]
=
0xf
;
break
;
}
if
(
eNB
->
abstraction_flag
)
{
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
cntl
.
pmch_flag
=
1
;
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
num_pmch
=
1
;
// assumption: there is always one pmch in each SF
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
num_common_dci
=
0
;
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
num_ue_spec_dci
=
0
;
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
dlsch_type
[
0
]
=
5
;
// put at the reserved position for PMCH
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
harq_pid
[
0
]
=
0
;
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
ue_id
[
0
]
=
255
;
//broadcast
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
tbs
[
0
]
=
dlsch
->
harq_processes
[
0
]
->
TBS
>>
3
;
}
}
void
fill_UE_dlsch_MCH
(
PHY_VARS_UE
*
ue
,
int
mcs
,
int
ndi
,
int
rvidx
,
int
eNB_id
)
{
LTE_UE_DLSCH_t
*
dlsch
=
ue
->
dlsch_MCH
[
eNB_id
];
LTE_DL_FRAME_PARMS
*
frame_parms
=&
ue
->
frame_parms
;
// dlsch->rnti = M_RNTI;
dlsch
->
harq_processes
[
0
]
->
mcs
=
mcs
;
dlsch
->
harq_processes
[
0
]
->
rvidx
=
rvidx
;
// dlsch->harq_processes[0]->Ndi = ndi;
dlsch
->
harq_processes
[
0
]
->
Nl
=
1
;
dlsch
->
harq_processes
[
0
]
->
TBS
=
TBStable
[
get_I_TBS
(
dlsch
->
harq_processes
[
0
]
->
mcs
)][
frame_parms
->
N_RB_DL
-
1
];
dlsch
->
current_harq_pid
=
0
;
dlsch
->
harq_processes
[
0
]
->
nb_rb
=
frame_parms
->
N_RB_DL
;
switch
(
frame_parms
->
N_RB_DL
)
{
case
6
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
0
]
=
0x3f
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
0
]
=
0x3f
;
break
;
case
25
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
0
]
=
0x1ffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
0
]
=
0x1ffffff
;
break
;
case
50
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
0
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
0
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
1
]
=
0x3ffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
1
]
=
0x3ffff
;
break
;
case
100
:
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
0
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
0
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
1
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
1
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
2
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
2
]
=
0xffffffff
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_even
[
3
]
=
0xf
;
dlsch
->
harq_processes
[
0
]
->
rb_alloc_odd
[
3
]
=
0xf
;
break
;
}
}
void
generate_mch
(
PHY_VARS_eNB
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
uint8_t
*
a
)
{
int
G
;
int
subframe
=
proc
->
subframe_tx
;
int
frame
=
proc
->
frame_tx
;
if
(
eNB
->
abstraction_flag
!=
0
)
{
if
(
eNB_transport_info_TB_index
[
eNB
->
Mod_id
][
eNB
->
CC_id
]
!=
0
)
printf
(
"[PHY][EMU] PMCH transport block position is different than zero %d
\n
"
,
eNB_transport_info_TB_index
[
eNB
->
Mod_id
][
eNB
->
CC_id
]);
memcpy
(
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
b
,
a
,
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
TBS
>>
3
);
LOG_D
(
PHY
,
"[eNB %d] dlsch_encoding_emul pmch , tbs is %d
\n
"
,
eNB
->
Mod_id
,
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
TBS
>>
3
);
memcpy
(
&
eNB_transport_info
[
eNB
->
Mod_id
][
eNB
->
CC_id
].
transport_blocks
[
eNB_transport_info_TB_index
[
eNB
->
Mod_id
][
eNB
->
CC_id
]],
a
,
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
TBS
>>
3
);
eNB_transport_info_TB_index
[
eNB
->
Mod_id
][
eNB
->
CC_id
]
+=
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
TBS
>>
3
;
//=eNB_transport_info[eNB->Mod_id].tbs[0];
}
else
{
G
=
get_G
(
&
eNB
->
frame_parms
,
eNB
->
frame_parms
.
N_RB_DL
,
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
rb_alloc
,
get_Qm
(
eNB
->
dlsch_MCH
->
harq_processes
[
0
]
->
mcs
),
1
,
2
,
proc
->
frame_tx
,
subframe
,
0
);
generate_mbsfn_pilot
(
eNB
,
proc
,
eNB
->
common_vars
.
txdataF
,
AMP
);
AssertFatal
(
dlsch_encoding
(
eNB
,
a
,
1
,
eNB
->
dlsch_MCH
,
proc
->
frame_tx
,
subframe
,
&
eNB
->
dlsch_rate_matching_stats
,
&
eNB
->
dlsch_turbo_encoding_stats
,
&
eNB
->
dlsch_interleaving_stats
)
==
0
,
"problem in dlsch_encoding"
);
dlsch_scrambling
(
&
eNB
->
frame_parms
,
1
,
eNB
->
dlsch_MCH
,
0
,
G
,
0
,
frame
,
subframe
<<
1
);
mch_modulation
(
eNB
->
common_vars
.
txdataF
,
AMP
,
subframe
,
&
eNB
->
frame_parms
,
eNB
->
dlsch_MCH
);
}
}
void
mch_extract_rbs
(
int
**
rxdataF
,
int
**
dl_ch_estimates
,
int
**
rxdataF_ext
,
int
**
dl_ch_estimates_ext
,
unsigned
char
symbol
,
unsigned
char
subframe
,
LTE_DL_FRAME_PARMS
*
frame_parms
)
{
int
pilots
=
0
,
i
,
j
,
offset
,
aarx
;
// printf("Extracting PMCH: symbol %d\n",symbol);
if
((
symbol
==
2
)
||
(
symbol
==
10
))
{
pilots
=
1
;
offset
=
1
;
}
else
if
(
symbol
==
6
)
{
pilots
=
1
;
offset
=
0
;
}
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
if
(
pilots
==
1
)
{
for
(
i
=
offset
,
j
=
0
;
i
<
frame_parms
->
N_RB_DL
*
6
;
i
+=
2
,
j
++
)
{
/* printf("MCH with pilots: i %d, j %d => %d,%d\n",i,j,
*(int16_t*)&rxdataF[aarx][i+frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)],
*(int16_t*)(1+&rxdataF[aarx][i+frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)]));
*/
rxdataF_ext
[
aarx
][
j
+
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)]
=
rxdataF
[
aarx
][
i
+
frame_parms
->
first_carrier_offset
+
(
symbol
*
frame_parms
->
ofdm_symbol_size
)];
rxdataF_ext
[
aarx
][(
frame_parms
->
N_RB_DL
*
3
)
+
j
+
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)]
=
rxdataF
[
aarx
][
i
+
1
+
(
symbol
*
frame_parms
->
ofdm_symbol_size
)];
dl_ch_estimates_ext
[
aarx
][
j
+
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)]
=
dl_ch_estimates
[
aarx
][
i
+
(
symbol
*
frame_parms
->
ofdm_symbol_size
)];
dl_ch_estimates_ext
[
aarx
][(
frame_parms
->
N_RB_DL
*
3
)
+
j
+
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)]
=
dl_ch_estimates
[
aarx
][
i
+
(
frame_parms
->
N_RB_DL
*
6
)
+
(
symbol
*
frame_parms
->
ofdm_symbol_size
)];
}
}
else
{
memcpy
((
void
*
)
&
rxdataF_ext
[
aarx
][
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)],
(
void
*
)
&
rxdataF
[
aarx
][
frame_parms
->
first_carrier_offset
+
(
symbol
*
frame_parms
->
ofdm_symbol_size
)],
frame_parms
->
N_RB_DL
*
24
);
memcpy
((
void
*
)
&
rxdataF_ext
[
aarx
][(
frame_parms
->
N_RB_DL
*
6
)
+
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)],
(
void
*
)
&
rxdataF
[
aarx
][
1
+
(
symbol
*
frame_parms
->
ofdm_symbol_size
)],
frame_parms
->
N_RB_DL
*
24
);
memcpy
((
void
*
)
&
dl_ch_estimates_ext
[
aarx
][
symbol
*
(
frame_parms
->
N_RB_DL
*
12
)],
(
void
*
)
&
dl_ch_estimates
[
aarx
][(
symbol
*
frame_parms
->
ofdm_symbol_size
)],
frame_parms
->
N_RB_DL
*
48
);
}
}
}
void
mch_channel_level
(
int
**
dl_ch_estimates_ext
,
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
*
avg
,
uint8_t
symbol
,
unsigned
short
nb_rb
)
{
int
i
,
aarx
,
nre
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
dl_ch128
,
avg128
;
#elif defined(__arm__)
int32x4_t
avg128
;
#endif
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
#if defined(__x86_64__) || defined(__i386__)
//clear average level
avg128
=
_mm_setzero_si128
();
// 5 is always a symbol with no pilots for both normal and extended prefix
dl_ch128
=
(
__m128i
*
)
&
dl_ch_estimates_ext
[
aarx
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
#elif defined(__arm__)
#endif
if
((
symbol
==
2
)
||
(
symbol
==
6
)
||
(
symbol
==
10
))
nre
=
(
frame_parms
->
N_RB_DL
*
6
);
else
nre
=
(
frame_parms
->
N_RB_DL
*
12
);
for
(
i
=
0
;
i
<
(
nre
>>
2
);
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
avg128
=
_mm_add_epi32
(
avg128
,
_mm_madd_epi16
(
dl_ch128
[
0
],
dl_ch128
[
0
]));
#elif defined(__arm__)
#endif
}
avg
[
aarx
]
=
(((
int
*
)
&
avg128
)[
0
]
+
((
int
*
)
&
avg128
)[
1
]
+
((
int
*
)
&
avg128
)[
2
]
+
((
int
*
)
&
avg128
)[
3
])
/
nre
;
// printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
mch_channel_compensation
(
int
**
rxdataF_ext
,
int
**
dl_ch_estimates_ext
,
int
**
dl_ch_mag
,
int
**
dl_ch_magb
,
int
**
rxdataF_comp
,
LTE_DL_FRAME_PARMS
*
frame_parms
,
unsigned
char
symbol
,
unsigned
char
mod_order
,
unsigned
char
output_shift
)
{
int
aarx
,
nre
,
i
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
dl_ch128
,
*
dl_ch_mag128
,
*
dl_ch_mag128b
,
*
rxdataF128
,
*
rxdataF_comp128
;
__m128i
mmtmpD0
,
mmtmpD1
,
mmtmpD2
,
mmtmpD3
,
QAM_amp128
,
QAM_amp128b
;
#elif defined(__arm__)
#endif
if
((
symbol
==
2
)
||
(
symbol
==
6
)
||
(
symbol
==
10
))
nre
=
frame_parms
->
N_RB_DL
*
6
;
else
nre
=
frame_parms
->
N_RB_DL
*
12
;
#if defined(__x86_64__) || defined(__i386__)
if
(
mod_order
==
4
)
{
QAM_amp128
=
_mm_set1_epi16
(
QAM16_n1
);
// 2/sqrt(10)
QAM_amp128b
=
_mm_setzero_si128
();
}
else
if
(
mod_order
==
6
)
{
QAM_amp128
=
_mm_set1_epi16
(
QAM64_n1
);
//
QAM_amp128b
=
_mm_set1_epi16
(
QAM64_n2
);
}
#elif defined(__arm__)
#endif
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
{
#if defined(__x86_64__) || defined(__i386__)
dl_ch128
=
(
__m128i
*
)
&
dl_ch_estimates_ext
[
aarx
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128
=
(
__m128i
*
)
&
dl_ch_mag
[
aarx
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128b
=
(
__m128i
*
)
&
dl_ch_magb
[
aarx
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
rxdataF128
=
(
__m128i
*
)
&
rxdataF_ext
[
aarx
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
rxdataF_comp128
=
(
__m128i
*
)
&
rxdataF_comp
[
aarx
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
#elif defined(__arm__)
#endif
for
(
i
=
0
;
i
<
(
nre
>>
2
);
i
+=
2
)
{
if
(
mod_order
>
2
)
{
// get channel amplitude if not QPSK
#if defined(__x86_64__) || defined(__i386__)
mmtmpD0
=
_mm_madd_epi16
(
dl_ch128
[
0
],
dl_ch128
[
0
]);
mmtmpD0
=
_mm_srai_epi32
(
mmtmpD0
,
output_shift
);
mmtmpD1
=
_mm_madd_epi16
(
dl_ch128
[
1
],
dl_ch128
[
1
]);
mmtmpD1
=
_mm_srai_epi32
(
mmtmpD1
,
output_shift
);
mmtmpD0
=
_mm_packs_epi32
(
mmtmpD0
,
mmtmpD1
);
// store channel magnitude here in a new field of dlsch
dl_ch_mag128
[
0
]
=
_mm_unpacklo_epi16
(
mmtmpD0
,
mmtmpD0
);
dl_ch_mag128b
[
0
]
=
dl_ch_mag128
[
0
];
dl_ch_mag128
[
0
]
=
_mm_mulhi_epi16
(
dl_ch_mag128
[
0
],
QAM_amp128
);
dl_ch_mag128
[
0
]
=
_mm_slli_epi16
(
dl_ch_mag128
[
0
],
1
);
dl_ch_mag128
[
1
]
=
_mm_unpackhi_epi16
(
mmtmpD0
,
mmtmpD0
);
dl_ch_mag128b
[
1
]
=
dl_ch_mag128
[
1
];
dl_ch_mag128
[
1
]
=
_mm_mulhi_epi16
(
dl_ch_mag128
[
1
],
QAM_amp128
);
dl_ch_mag128
[
1
]
=
_mm_slli_epi16
(
dl_ch_mag128
[
1
],
1
);
dl_ch_mag128b
[
0
]
=
_mm_mulhi_epi16
(
dl_ch_mag128b
[
0
],
QAM_amp128b
);
dl_ch_mag128b
[
0
]
=
_mm_slli_epi16
(
dl_ch_mag128b
[
0
],
1
);
dl_ch_mag128b
[
1
]
=
_mm_mulhi_epi16
(
dl_ch_mag128b
[
1
],
QAM_amp128b
);
dl_ch_mag128b
[
1
]
=
_mm_slli_epi16
(
dl_ch_mag128b
[
1
],
1
);
#elif defined(__arm__)
#endif
}
#if defined(__x86_64__) || defined(__i386__)
// multiply by conjugated channel
mmtmpD0
=
_mm_madd_epi16
(
dl_ch128
[
0
],
rxdataF128
[
0
]);
// print_ints("re",&mmtmpD0);
// mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
mmtmpD1
=
_mm_shufflelo_epi16
(
dl_ch128
[
0
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpD1
=
_mm_shufflehi_epi16
(
mmtmpD1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpD1
=
_mm_sign_epi16
(
mmtmpD1
,
*
(
__m128i
*
)
&
conjugate
[
0
]);
// print_ints("im",&mmtmpD1);
mmtmpD1
=
_mm_madd_epi16
(
mmtmpD1
,
rxdataF128
[
0
]);
// mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpD0
=
_mm_srai_epi32
(
mmtmpD0
,
output_shift
);
// print_ints("re(shift)",&mmtmpD0);
mmtmpD1
=
_mm_srai_epi32
(
mmtmpD1
,
output_shift
);
// print_ints("im(shift)",&mmtmpD1);
mmtmpD2
=
_mm_unpacklo_epi32
(
mmtmpD0
,
mmtmpD1
);
mmtmpD3
=
_mm_unpackhi_epi32
(
mmtmpD0
,
mmtmpD1
);
// print_ints("c0",&mmtmpD2);
// print_ints("c1",&mmtmpD3);
rxdataF_comp128
[
0
]
=
_mm_packs_epi32
(
mmtmpD2
,
mmtmpD3
);
// print_shorts("rx:",rxdataF128);
// print_shorts("ch:",dl_ch128);
// print_shorts("pack:",rxdataF_comp128);
// multiply by conjugated channel
mmtmpD0
=
_mm_madd_epi16
(
dl_ch128
[
1
],
rxdataF128
[
1
]);
// mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
mmtmpD1
=
_mm_shufflelo_epi16
(
dl_ch128
[
1
],
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpD1
=
_mm_shufflehi_epi16
(
mmtmpD1
,
_MM_SHUFFLE
(
2
,
3
,
0
,
1
));
mmtmpD1
=
_mm_sign_epi16
(
mmtmpD1
,
*
(
__m128i
*
)
conjugate
);
mmtmpD1
=
_mm_madd_epi16
(
mmtmpD1
,
rxdataF128
[
1
]);
// mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpD0
=
_mm_srai_epi32
(
mmtmpD0
,
output_shift
);
mmtmpD1
=
_mm_srai_epi32
(
mmtmpD1
,
output_shift
);
mmtmpD2
=
_mm_unpacklo_epi32
(
mmtmpD0
,
mmtmpD1
);
mmtmpD3
=
_mm_unpackhi_epi32
(
mmtmpD0
,
mmtmpD1
);
rxdataF_comp128
[
1
]
=
_mm_packs_epi32
(
mmtmpD2
,
mmtmpD3
);
// print_shorts("rx:",rxdataF128+1);
// print_shorts("ch:",dl_ch128+1);
// print_shorts("pack:",rxdataF_comp128+1);
dl_ch128
+=
2
;
dl_ch_mag128
+=
2
;
dl_ch_mag128b
+=
2
;
rxdataF128
+=
2
;
rxdataF_comp128
+=
2
;
#elif defined(__arm__)
#endif
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
void
mch_detection_mrc
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
int
**
dl_ch_mag
,
int
**
dl_ch_magb
,
unsigned
char
symbol
)
{
int
i
;
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
rxdataF_comp128_0
,
*
rxdataF_comp128_1
,
*
dl_ch_mag128_0
,
*
dl_ch_mag128_1
,
*
dl_ch_mag128_0b
,
*
dl_ch_mag128_1b
;
#elif defined(__arm__)
int16x8_t
*
rxdataF_comp128_0
,
*
rxdataF_comp128_1
,
*
dl_ch_mag128_0
,
*
dl_ch_mag128_1
,
*
dl_ch_mag128_0b
,
*
dl_ch_mag128_1b
;
#endif
if
(
frame_parms
->
nb_antennas_rx
>
1
)
{
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0
=
(
__m128i
*
)
&
rxdataF_comp
[
0
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
rxdataF_comp128_1
=
(
__m128i
*
)
&
rxdataF_comp
[
1
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_0
=
(
__m128i
*
)
&
dl_ch_mag
[
0
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_1
=
(
__m128i
*
)
&
dl_ch_mag
[
1
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_0b
=
(
__m128i
*
)
&
dl_ch_magb
[
0
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_1b
=
(
__m128i
*
)
&
dl_ch_magb
[
1
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
#elif defined(__arm__)
rxdataF_comp128_0
=
(
int16x8_t
*
)
&
rxdataF_comp
[
0
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
rxdataF_comp128_1
=
(
int16x8_t
*
)
&
rxdataF_comp
[
1
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_0
=
(
int16x8_t
*
)
&
dl_ch_mag
[
0
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_1
=
(
int16x8_t
*
)
&
dl_ch_mag
[
1
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_0b
=
(
int16x8_t
*
)
&
dl_ch_magb
[
0
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
dl_ch_mag128_1b
=
(
int16x8_t
*
)
&
dl_ch_magb
[
1
][
symbol
*
frame_parms
->
N_RB_DL
*
12
];
#endif
// MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
for
(
i
=
0
;
i
<
frame_parms
->
N_RB_DL
*
3
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0
[
i
]
=
_mm_adds_epi16
(
_mm_srai_epi16
(
rxdataF_comp128_0
[
i
],
1
),
_mm_srai_epi16
(
rxdataF_comp128_1
[
i
],
1
));
dl_ch_mag128_0
[
i
]
=
_mm_adds_epi16
(
_mm_srai_epi16
(
dl_ch_mag128_0
[
i
],
1
),
_mm_srai_epi16
(
dl_ch_mag128_1
[
i
],
1
));
dl_ch_mag128_0b
[
i
]
=
_mm_adds_epi16
(
_mm_srai_epi16
(
dl_ch_mag128_0b
[
i
],
1
),
_mm_srai_epi16
(
dl_ch_mag128_1b
[
i
],
1
));
#elif defined(__arm__)
rxdataF_comp128_0
[
i
]
=
vhaddq_s16
(
rxdataF_comp128_0
[
i
],
rxdataF_comp128_1
[
i
]);
dl_ch_mag128_0
[
i
]
=
vhaddq_s16
(
dl_ch_mag128_0
[
i
],
dl_ch_mag128_1
[
i
]);
dl_ch_mag128_0b
[
i
]
=
vhaddq_s16
(
dl_ch_mag128_0b
[
i
],
dl_ch_mag128_1b
[
i
]);
#endif
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
int
mch_qpsk_llr
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
short
*
dlsch_llr
,
unsigned
char
symbol
,
short
**
llr32p
)
{
uint32_t
*
rxF
=
(
uint32_t
*
)
&
rxdataF_comp
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
uint32_t
*
llr32
;
int
i
,
len
;
if
(
symbol
==
2
)
{
llr32
=
(
uint32_t
*
)
dlsch_llr
;
}
else
{
llr32
=
(
uint32_t
*
)(
*
llr32p
);
}
AssertFatal
(
llr32
!=
NULL
,
"dlsch_qpsk_llr: llr is null, symbol %d, llr32=%p
\n
"
,
symbol
,
llr32
);
if
((
symbol
==
2
)
||
(
symbol
==
6
)
||
(
symbol
==
10
))
{
len
=
frame_parms
->
N_RB_DL
*
6
;
}
else
{
len
=
frame_parms
->
N_RB_DL
*
12
;
}
// printf("dlsch_qpsk_llr: symbol %d,len %d,pbch_pss_sss_adjust %d\n",symbol,len,pbch_pss_sss_adjust);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
*
llr32
=
*
rxF
;
rxF
++
;
llr32
++
;
}
*
llr32p
=
(
short
*
)
llr32
;
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
return
(
0
);
}
//----------------------------------------------------------------------------------------------
// 16-QAM
//----------------------------------------------------------------------------------------------
void
mch_16qam_llr
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
short
*
dlsch_llr
,
int
**
dl_ch_mag
,
unsigned
char
symbol
,
int16_t
**
llr32p
)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i
*
rxF
=
(
__m128i
*
)
&
rxdataF_comp
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
__m128i
*
ch_mag
;
__m128i
llr128
[
2
],
xmm0
;
uint32_t
*
llr32
;
#elif defined(__arm__)
int16x8_t
*
rxF
=
(
int16x8_t
*
)
&
rxdataF_comp
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
int16x8_t
*
ch_mag
;
int16x8_t
llr128
[
2
],
xmm0
;
int16_t
*
llr16
;
#endif
int
i
,
len
;
unsigned
char
len_mod4
=
0
;
#if defined(__x86_64__) || defined(__i386__)
if
(
symbol
==
2
)
{
llr32
=
(
uint32_t
*
)
dlsch_llr
;
}
else
{
llr32
=
(
uint32_t
*
)
*
llr32p
;
}
#elif defined(__arm__)
if
(
symbol
==
2
)
{
llr16
=
(
int16_t
*
)
dlsch_llr
;
}
else
{
llr16
=
(
int16_t
*
)
*
llr32p
;
}
#endif
#if defined(__x86_64__) || defined(__i386__)
ch_mag
=
(
__m128i
*
)
&
dl_ch_mag
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
#elif defined(__arm__)
ch_mag
=
(
int16x8_t
*
)
&
dl_ch_mag
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
#endif
if
((
symbol
==
2
)
||
(
symbol
==
6
)
||
(
symbol
==
10
))
{
len
=
frame_parms
->
N_RB_DL
*
6
;
}
else
{
len
=
frame_parms
->
N_RB_DL
*
12
;
}
// update output pointer according to number of REs in this symbol (<<2 because 4 bits per RE)
if
(
symbol
==
2
)
*
llr32p
=
dlsch_llr
+
(
len
<<
2
);
else
*
llr32p
+=
(
len
<<
2
);
len_mod4
=
len
&
3
;
len
>>=
2
;
// length in quad words (4 REs)
len
+=
(
len_mod4
==
0
?
0
:
1
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
xmm0
=
_mm_abs_epi16
(
rxF
[
i
]);
xmm0
=
_mm_subs_epi16
(
ch_mag
[
i
],
xmm0
);
// lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2
llr128
[
0
]
=
_mm_unpacklo_epi32
(
rxF
[
i
],
xmm0
);
llr128
[
1
]
=
_mm_unpackhi_epi32
(
rxF
[
i
],
xmm0
);
llr32
[
0
]
=
((
uint32_t
*
)
&
llr128
[
0
])[
0
];
llr32
[
1
]
=
((
uint32_t
*
)
&
llr128
[
0
])[
1
];
llr32
[
2
]
=
((
uint32_t
*
)
&
llr128
[
0
])[
2
];
llr32
[
3
]
=
((
uint32_t
*
)
&
llr128
[
0
])[
3
];
llr32
[
4
]
=
((
uint32_t
*
)
&
llr128
[
1
])[
0
];
llr32
[
5
]
=
((
uint32_t
*
)
&
llr128
[
1
])[
1
];
llr32
[
6
]
=
((
uint32_t
*
)
&
llr128
[
1
])[
2
];
llr32
[
7
]
=
((
uint32_t
*
)
&
llr128
[
1
])[
3
];
llr32
+=
8
;
#elif defined(__arm__)
xmm0
=
vabsq_s16
(
rxF
[
i
]);
xmm0
=
vsubq_s16
(
ch_mag
[
i
],
xmm0
);
// lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2
llr16
[
0
]
=
vgetq_lane_s16
(
rxF
[
i
],
0
);
llr16
[
1
]
=
vgetq_lane_s16
(
xmm0
,
0
);
llr16
[
2
]
=
vgetq_lane_s16
(
rxF
[
i
],
1
);
llr16
[
3
]
=
vgetq_lane_s16
(
xmm0
,
1
);
llr16
[
4
]
=
vgetq_lane_s16
(
rxF
[
i
],
2
);
llr16
[
5
]
=
vgetq_lane_s16
(
xmm0
,
2
);
llr16
[
6
]
=
vgetq_lane_s16
(
rxF
[
i
],
2
);
llr16
[
7
]
=
vgetq_lane_s16
(
xmm0
,
3
);
llr16
[
8
]
=
vgetq_lane_s16
(
rxF
[
i
],
4
);
llr16
[
9
]
=
vgetq_lane_s16
(
xmm0
,
4
);
llr16
[
10
]
=
vgetq_lane_s16
(
rxF
[
i
],
5
);
llr16
[
11
]
=
vgetq_lane_s16
(
xmm0
,
5
);
llr16
[
12
]
=
vgetq_lane_s16
(
rxF
[
i
],
6
);
llr16
[
13
]
=
vgetq_lane_s16
(
xmm0
,
6
);
llr16
[
14
]
=
vgetq_lane_s16
(
rxF
[
i
],
7
);
llr16
[
15
]
=
vgetq_lane_s16
(
xmm0
,
7
);
llr16
+=
16
;
#endif
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
//----------------------------------------------------------------------------------------------
// 64-QAM
//----------------------------------------------------------------------------------------------
void
mch_64qam_llr
(
LTE_DL_FRAME_PARMS
*
frame_parms
,
int
**
rxdataF_comp
,
short
*
dlsch_llr
,
int
**
dl_ch_mag
,
int
**
dl_ch_magb
,
unsigned
char
symbol
,
short
**
llr_save
)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i
xmm1
,
xmm2
,
*
ch_mag
,
*
ch_magb
;
__m128i
*
rxF
=
(
__m128i
*
)
&
rxdataF_comp
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
#elif defined(__arm__)
int16x8_t
xmm1
,
xmm2
,
*
ch_mag
,
*
ch_magb
;
int16x8_t
*
rxF
=
(
int16x8_t
*
)
&
rxdataF_comp
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
#endif
int
i
,
len
,
len2
;
// int j=0;
unsigned
char
len_mod4
;
short
*
llr
;
int16_t
*
llr2
;
if
(
symbol
==
2
)
llr
=
dlsch_llr
;
else
llr
=
*
llr_save
;
#if defined(__x86_64__) || defined(__i386__)
ch_mag
=
(
__m128i
*
)
&
dl_ch_mag
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
ch_magb
=
(
__m128i
*
)
&
dl_ch_magb
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
#elif defined(__arm__)
ch_mag
=
(
int16x8_t
*
)
&
dl_ch_mag
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
ch_magb
=
(
int16x8_t
*
)
&
dl_ch_magb
[
0
][(
symbol
*
frame_parms
->
N_RB_DL
*
12
)];
#endif
if
((
symbol
==
2
)
||
(
symbol
==
6
)
||
(
symbol
==
10
))
{
len
=
frame_parms
->
N_RB_DL
*
6
;
}
else
{
len
=
frame_parms
->
N_RB_DL
*
12
;
}
llr2
=
llr
;
llr
+=
(
len
*
6
);
len_mod4
=
len
&
3
;
len2
=
len
>>
2
;
// length in quad words (4 REs)
len2
+=
(
len_mod4
?
0
:
1
);
for
(
i
=
0
;
i
<
len2
;
i
++
)
{
#if defined(__x86_64__) || defined(__i386__)
xmm1
=
_mm_abs_epi16
(
rxF
[
i
]);
xmm1
=
_mm_subs_epi16
(
ch_mag
[
i
],
xmm1
);
xmm2
=
_mm_abs_epi16
(
xmm1
);
xmm2
=
_mm_subs_epi16
(
ch_magb
[
i
],
xmm2
);
#elif defined(__arm__)
xmm1
=
vabsq_s16
(
rxF
[
i
]);
xmm1
=
vsubq_s16
(
ch_mag
[
i
],
xmm1
);
xmm2
=
vabsq_s16
(
xmm1
);
xmm2
=
vsubq_s16
(
ch_magb
[
i
],
xmm2
);
#endif
/*
printf("pmch i: %d => mag (%d,%d) (%d,%d)\n",i,((short *)&ch_mag[i])[0],((short *)&ch_magb[i])[0],
((short *)&rxF[i])[0],((short *)&rxF[i])[1]);
*/
// loop over all LLRs in quad word (24 coded bits)
/*
for (j=0;j<8;j+=2) {
llr2[0] = ((short *)&rxF[i])[j];
llr2[1] = ((short *)&rxF[i])[j+1];
llr2[2] = _mm_extract_epi16(xmm1,j);
llr2[3] = _mm_extract_epi16(xmm1,j+1);//((short *)&xmm1)[j+1];
llr2[4] = _mm_extract_epi16(xmm2,j);//((short *)&xmm2)[j];
llr2[5] = _mm_extract_epi16(xmm2,j+1);//((short *)&xmm2)[j+1];
llr2+=6;
}
*/
llr2
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
0
];
llr2
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
1
];
#if defined(__x86_64__) || defined(__i386__)
llr2
[
2
]
=
_mm_extract_epi16
(
xmm1
,
0
);
llr2
[
3
]
=
_mm_extract_epi16
(
xmm1
,
1
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
_mm_extract_epi16
(
xmm2
,
0
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
_mm_extract_epi16
(
xmm2
,
1
);
//((short *)&xmm2)[j+1];
#elif defined(__arm__)
llr2
[
2
]
=
vgetq_lane_s16
(
xmm1
,
0
);
llr2
[
3
]
=
vgetq_lane_s16
(
xmm1
,
1
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
vgetq_lane_s16
(
xmm2
,
0
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
vgetq_lane_s16
(
xmm2
,
1
);
//((short *)&xmm2)[j+1];
#endif
llr2
+=
6
;
llr2
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
2
];
llr2
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
3
];
#if defined(__x86_64__) || defined(__i386__)
llr2
[
2
]
=
_mm_extract_epi16
(
xmm1
,
2
);
llr2
[
3
]
=
_mm_extract_epi16
(
xmm1
,
3
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
_mm_extract_epi16
(
xmm2
,
2
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
_mm_extract_epi16
(
xmm2
,
3
);
//((short *)&xmm2)[j+1];
#elif defined(__arm__)
llr2
[
2
]
=
vgetq_lane_s16
(
xmm1
,
2
);
llr2
[
3
]
=
vgetq_lane_s16
(
xmm1
,
3
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
vgetq_lane_s16
(
xmm2
,
2
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
vgetq_lane_s16
(
xmm2
,
3
);
//((short *)&xmm2)[j+1];
#endif
llr2
+=
6
;
llr2
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
4
];
llr2
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
5
];
#if defined(__x86_64__) || defined(__i386__)
llr2
[
2
]
=
_mm_extract_epi16
(
xmm1
,
4
);
llr2
[
3
]
=
_mm_extract_epi16
(
xmm1
,
5
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
_mm_extract_epi16
(
xmm2
,
4
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
_mm_extract_epi16
(
xmm2
,
5
);
//((short *)&xmm2)[j+1];
#elif defined(__arm__)
llr2
[
2
]
=
vgetq_lane_s16
(
xmm1
,
4
);
llr2
[
3
]
=
vgetq_lane_s16
(
xmm1
,
5
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
vgetq_lane_s16
(
xmm2
,
4
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
vgetq_lane_s16
(
xmm2
,
5
);
//((short *)&xmm2)[j+1];
#endif
llr2
+=
6
;
llr2
[
0
]
=
((
short
*
)
&
rxF
[
i
])[
6
];
llr2
[
1
]
=
((
short
*
)
&
rxF
[
i
])[
7
];
#if defined(__x86_64__) || defined(__i386__)
llr2
[
2
]
=
_mm_extract_epi16
(
xmm1
,
6
);
llr2
[
3
]
=
_mm_extract_epi16
(
xmm1
,
7
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
_mm_extract_epi16
(
xmm2
,
6
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
_mm_extract_epi16
(
xmm2
,
7
);
//((short *)&xmm2)[j+1];
#elif defined(__arm__)
llr2
[
2
]
=
vgetq_lane_s16
(
xmm1
,
6
);
llr2
[
3
]
=
vgetq_lane_s16
(
xmm1
,
7
);
//((short *)&xmm1)[j+1];
llr2
[
4
]
=
vgetq_lane_s16
(
xmm2
,
6
);
//((short *)&xmm2)[j];
llr2
[
5
]
=
vgetq_lane_s16
(
xmm2
,
7
);
//((short *)&xmm2)[j+1];
#endif
llr2
+=
6
;
}
*
llr_save
=
llr
;
#if defined(__x86_64__) || defined(__i386__)
_mm_empty
();
_m_empty
();
#endif
}
int
avg_pmch
[
4
];
int
rx_pmch
(
PHY_VARS_UE
*
ue
,
unsigned
char
eNB_id
,
uint8_t
subframe
,
unsigned
char
symbol
)
{
LTE_UE_COMMON
*
common_vars
=
&
ue
->
common_vars
;
LTE_UE_PDSCH
**
pdsch_vars
=
&
ue
->
pdsch_vars_MCH
[
eNB_id
];
LTE_DL_FRAME_PARMS
*
frame_parms
=
&
ue
->
frame_parms
;
LTE_UE_DLSCH_t
**
dlsch
=
&
ue
->
dlsch_MCH
[
eNB_id
];
int
avgs
,
aarx
;
//printf("*********************mch: symbol %d\n",symbol);
mch_extract_rbs
(
common_vars
->
common_vars_rx_data_per_thread
[
ue
->
current_thread_id
[
subframe
]].
rxdataF
,
common_vars
->
common_vars_rx_data_per_thread
[
ue
->
current_thread_id
[
subframe
]].
dl_ch_estimates
[
eNB_id
],
pdsch_vars
[
eNB_id
]
->
rxdataF_ext
,
pdsch_vars
[
eNB_id
]
->
dl_ch_estimates_ext
,
symbol
,
subframe
,
frame_parms
);
if
(
symbol
==
2
)
{
mch_channel_level
(
pdsch_vars
[
eNB_id
]
->
dl_ch_estimates_ext
,
frame_parms
,
avg_pmch
,
symbol
,
frame_parms
->
N_RB_DL
);
}
avgs
=
0
;
for
(
aarx
=
0
;
aarx
<
frame_parms
->
nb_antennas_rx
;
aarx
++
)
avgs
=
cmax
(
avgs
,
avg_pmch
[
aarx
]);
if
(
get_Qm
(
dlsch
[
0
]
->
harq_processes
[
0
]
->
mcs
)
==
2
)
pdsch_vars
[
eNB_id
]
->
log2_maxh
=
(
log2_approx
(
avgs
)
/
2
)
;
// + 2
else
pdsch_vars
[
eNB_id
]
->
log2_maxh
=
(
log2_approx
(
avgs
)
/
2
);
// + 5;// + 2
mch_channel_compensation
(
pdsch_vars
[
eNB_id
]
->
rxdataF_ext
,
pdsch_vars
[
eNB_id
]
->
dl_ch_estimates_ext
,
pdsch_vars
[
eNB_id
]
->
dl_ch_mag0
,
pdsch_vars
[
eNB_id
]
->
dl_ch_magb0
,
pdsch_vars
[
eNB_id
]
->
rxdataF_comp0
,
frame_parms
,
symbol
,
get_Qm
(
dlsch
[
0
]
->
harq_processes
[
0
]
->
mcs
),
pdsch_vars
[
eNB_id
]
->
log2_maxh
);
if
(
frame_parms
->
nb_antennas_rx
>
1
)
mch_detection_mrc
(
frame_parms
,
pdsch_vars
[
eNB_id
]
->
rxdataF_comp0
,
pdsch_vars
[
eNB_id
]
->
dl_ch_mag0
,
pdsch_vars
[
eNB_id
]
->
dl_ch_magb0
,
symbol
);
switch
(
get_Qm
(
dlsch
[
0
]
->
harq_processes
[
0
]
->
mcs
))
{
case
2
:
mch_qpsk_llr
(
frame_parms
,
pdsch_vars
[
eNB_id
]
->
rxdataF_comp0
,
pdsch_vars
[
eNB_id
]
->
llr
[
0
],
symbol
,
pdsch_vars
[
eNB_id
]
->
llr128
);
break
;
case
4
:
mch_16qam_llr
(
frame_parms
,
pdsch_vars
[
eNB_id
]
->
rxdataF_comp0
,
pdsch_vars
[
eNB_id
]
->
llr
[
0
],
pdsch_vars
[
eNB_id
]
->
dl_ch_mag0
,
symbol
,
pdsch_vars
[
eNB_id
]
->
llr128
);
break
;
case
6
:
mch_64qam_llr
(
frame_parms
,
pdsch_vars
[
eNB_id
]
->
rxdataF_comp0
,
pdsch_vars
[
eNB_id
]
->
llr
[
0
],
pdsch_vars
[
eNB_id
]
->
dl_ch_mag0
,
pdsch_vars
[
eNB_id
]
->
dl_ch_magb0
,
symbol
,
pdsch_vars
[
eNB_id
]
->
llr128
);
break
;
}
return
(
0
);
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment