This commits contains several fixes to improve a multi-UE scenario.
This is not the end of the story.
Summary of work:
================
1 - improve SR (scheduling requests):
We configured n1pucch == 3 for scheduling requests, for all
UEs. We now use 71 - UE_id/10.
For it to work, it is vital that pucch_nRB_CQI in the configuration
file is set to 0, otherwise the SR will go to an RB used for
PUSCH and uplink decoding will fail whenever an UE does SR.
Note that we will have problems with 20MHz when we use a CCE that
let the UE send the ACK/NACK using a n1pucch allocated for SR,
because when the PDCCH is of size 3, we can have 87 CCEs
and it may lead to an n1pucch colliding with one for SR.
The work done in this patch is a quick solution, seems to work
with 10MHz.
The real solution is to disable the use of those CCEs that would
lead an UE to use a n1pucch colliding with an SR n1pucch. Then
we can use whatever n1pucch we want for SR, as long as the
scheduler protects them.
Impacted files: configuration files
openair2/RRC/LITE/MESSAGES/asn1_msg.c
2 - some fixes for uplink scheduling:
- Do not use PRACH for PUSCH, that leads to too many false
PRACH detection. Plus the PUSCH receiving may fail if one
UE uses the PRACH at the same time.
- Take care of retransmissions. That was not done at all, so
we could allocate one RB to several UEs. The current design
of the code makes it hard to do it properly, so we chose a
quick and dirty solution, which is to increase "first_rb"
to skip any RB used for retransmission. In this process we
may skip a lot of free RBs. A proper solution is needed here.
- Do not allocate the last RB. This one is used for PUCCH.
It was sometimes allocated to PUSCH.
- In the pre-processor we didn't pre-allocate RBs to UEs
with an empty buffer status. We didn't check if the UE
sent an SR. For example in a three UEs scenario, we
could have the third UE never scheduled in the uplink.
- rb_table_index was not decreased properly, so we allocated
too much RBs to some UEs and thus not enough to others.
Impacted files: openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
openair2/LAYER2/MAC/pre_processor.c
openair1/SCHED/phy_procedures_lte_eNb.c
3 - some fixes for downlink scheduling:
- The check on CCE allocation was not correct. We did something
like:
if (cce allocation is possible) {
prepare
}
We should have done:
save current cce allocation
if (cce allocation is possible) {
allocate cce
prepare
}
reset current cce allocation
Basically, when we scheduled several UEs, they were checked
separately, and the totality of them was not checked.
Impacted file: openair2/LAYER2/MAC/eNB_scheduler_dlsch.c
- The retransmissions are probably not handled correctly.
Check in openair2/LAYER2/MAC/pre_processor.c, near
the comment "// control channel or retransmission",
the case "round > 0" was added. It's probably not enough,
even maybe not correct.
- Change SF05_LIMIT with SF0_LIMIT. We accept to use
central blocks in SF 5. The code was also not correct,
vrb_map was not set properly because the loop on j
was wrong for the last RBG (which can have one less
RB than the others).
This is not satisfying. The real solution is to use the
central RBs and check that the MCS used is compatible
with the numbers of resource elements allocated (we don't
want to put too more data bits than what fits).
4 - some fixes in PUCCH decoding:
See: openair1/PHY/LTE_TRANSPORT/pucch.c
Probably not enough. Some more work and analysis is
required for a proper use of the PUCCH. What we see
is that the PUCCH constellation gets wrong when there
are several UEs, meaning the received ACK/NACK is
not properly decoded (this, or something else...).
5 - several fixes/checks added here and there:
- The final allocate_CCEs in eNB_dlsch_ulsch_scheduler
is checked and we brutally exit if it fails.
- We exit in get_num_pdcch_symbols in case of failure
(this should never happen anyway, no big deal normally).
- Some logs added or changed to error/warning instead
of debug.
- In dlsch_scheduler_pre_processor an abort() was added.
The code here looks suspicious.
- In assign_max_mcs_min_rb, rb_table_index was not set
to 2, the value 0 was used. This was not correct.
What remains to be done:
========================
- Correct CCE allocation (take into account SR n1pucch,
check that all the n1pucch that will be used are "compatible").
- Take into account the PHICH when scheduling uplink. As of
today it is very possible to have two UEs use the same PHICH
group and PHICH sequence index. We can use n_DMRS in the DCI
to have uniqueness (see 36.213 table 9.1.2-2). We can drop an
allocation if there is no free PHICH group/sequence index for
a given UE.
- When there is an uplink retransmission in the PRACH, we have
to disable PRACH detection. It is possible that one UE does
PRACH at the same time, but then what to do? We could use
DCI0-based retransmission in this specific case maybe...
- Handle free RBs in uplink in a much better way in case of
a retransmission. We may have a lot of free unused RBs with
the current code.
- Check downlink retransmissions. Not much has been done there.
- Surely more stuff not clear yet. In some situations we don't
have a good behavior of the system. Hard to describe more
precisely at this point.
2558 lines
109 KiB
C
2558 lines
109 KiB
C
/*
|
|
* 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.0 (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/pucch.c
|
|
* \brief Top-level routines for generating and decoding the PUCCH physical 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 "LAYER2/MAC/extern.h"
|
|
|
|
#include "UTIL/LOG/log.h"
|
|
#include "UTIL/LOG/vcd_signal_dumper.h"
|
|
|
|
#include "T.h"
|
|
|
|
//uint8_t ncs_cell[20][7];
|
|
//#define DEBUG_PUCCH_TX
|
|
//#define DEBUG_PUCCH_RX
|
|
|
|
int16_t cfo_pucch_np[24*7] = {20787,-25330,27244,-18205,31356,-9512,32767,0,31356,9511,27244,18204,20787,25329,
|
|
27244,-18205,30272,-12540,32137,-6393,32767,0,32137,6392,30272,12539,27244,18204,
|
|
31356,-9512,32137,-6393,32609,-3212,32767,0,32609,3211,32137,6392,31356,9511,
|
|
32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,
|
|
31356,9511,32137,6392,32609,3211,32767,0,32609,-3212,32137,-6393,31356,-9512,
|
|
27244,18204,30272,12539,32137,6392,32767,0,32137,-6393,30272,-12540,27244,-18205,
|
|
20787,25329,27244,18204,31356,9511,32767,0,31356,-9512,27244,-18205,20787,-25330
|
|
};
|
|
|
|
int16_t cfo_pucch_ep[24*6] = {24278,-22005,29621,-14010,32412,-4808,32412,4807,29621,14009,24278,22004,
|
|
28897,-15447,31356,-9512,32609,-3212,32609,3211,31356,9511,28897,15446,
|
|
31785,-7962,32412,-4808,32727,-1608,32727,1607,32412,4807,31785,7961,
|
|
32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,
|
|
31785,7961,32412,4807,32727,1607,32727,-1608,32412,-4808,31785,-7962,
|
|
28897,15446,31356,9511,32609,3211,32609,-3212,31356,-9512,28897,-15447,
|
|
24278,22004,29621,14009,32412,4807,32412,-4808,29621,-14010,24278,-22005
|
|
};
|
|
|
|
|
|
void init_ncs_cell(LTE_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7])
|
|
{
|
|
|
|
uint8_t ns,l,reset=1,i,N_UL_symb;
|
|
uint32_t x1,x2,j=0,s=0;
|
|
|
|
N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6;
|
|
x2 = frame_parms->Nid_cell;
|
|
|
|
for (ns=0; ns<20; ns++) {
|
|
|
|
for (l=0; l<N_UL_symb; l++) {
|
|
ncs_cell[ns][l]=0;
|
|
|
|
for (i=0; i<8; i++) {
|
|
if ((j%32) == 0) {
|
|
s = lte_gold_generic(&x1,&x2,reset);
|
|
// printf("s %x\n",s);
|
|
reset=0;
|
|
}
|
|
|
|
if (((s>>(j%32))&1)==1)
|
|
ncs_cell[ns][l] += (1<<i);
|
|
|
|
j++;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH ncs_cell init (j %d): Ns %d, l %d => ncs_cell %d\n",j,ns,l,ncs_cell[ns][l]);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
int16_t alpha_re[12] = {32767, 28377, 16383, 0,-16384, -28378,-32768,-28378,-16384, -1, 16383, 28377};
|
|
int16_t alpha_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0,-16384,-28378,-32768,-28378,-16384};
|
|
|
|
int16_t W4[3][4] = {{32767, 32767, 32767, 32767},
|
|
{32767,-32768, 32767,-32768},
|
|
{32767,-32768,-32768, 32767}
|
|
};
|
|
int16_t W3_re[3][6] = {{32767, 32767, 32767},
|
|
{32767,-16384,-16384},
|
|
{32767,-16384,-16384}
|
|
};
|
|
|
|
int16_t W3_im[3][6] = {{0 ,0 ,0 },
|
|
{0 , 28377,-28378},
|
|
{0 ,-28378, 28377}
|
|
};
|
|
|
|
char pucch_format_string[6][20] = {"format 1\0","format 1a\0","format 1b\0","format 2\0","format 2a\0","format 2b\0"};
|
|
|
|
/* PUCCH format3 >> */
|
|
#define D_I 0
|
|
#define D_Q 1
|
|
#define D_IQDATA 2
|
|
#define D_NSLT1SF 2
|
|
#define D_NSYM1SLT 7
|
|
#define D_NSYM1SF 2*7
|
|
#define D_NSC1RB 12
|
|
#define D_NRB1PUCCH 2
|
|
#define D_NPUCCH_SF5 5
|
|
#define D_NPUCCH_SF4 4
|
|
|
|
uint8_t chcod_tbl[128][48] = { {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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
|
{1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1},
|
|
{0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0},
|
|
{0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0},
|
|
{1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1},
|
|
{1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1},
|
|
{0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0},
|
|
{0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0},
|
|
{1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1},
|
|
{1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1},
|
|
{0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0},
|
|
{0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
|
|
{1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1},
|
|
{1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1},
|
|
{0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0},
|
|
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1},
|
|
{1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0},
|
|
{1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0},
|
|
{0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1},
|
|
{0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1},
|
|
{1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0},
|
|
{1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0},
|
|
{0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1},
|
|
{0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1},
|
|
{1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0},
|
|
{1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0},
|
|
{0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1},
|
|
{0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
|
|
{1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
|
|
{1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0},
|
|
{0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1},
|
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
|
|
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
|
|
{1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0},
|
|
{0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1},
|
|
{0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1},
|
|
{1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0},
|
|
{1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0},
|
|
{0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1},
|
|
{0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1},
|
|
{1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0},
|
|
{1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0},
|
|
{0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1},
|
|
{0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1},
|
|
{1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0},
|
|
{1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0},
|
|
{0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1},
|
|
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0},
|
|
{1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
|
|
{1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1},
|
|
{0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0},
|
|
{0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0},
|
|
{1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1},
|
|
{1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1},
|
|
{0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0},
|
|
{0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0},
|
|
{1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1},
|
|
{1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1},
|
|
{0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0},
|
|
{0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
|
|
{1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1},
|
|
{1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1},
|
|
{0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0},
|
|
{0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1},
|
|
{1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0},
|
|
{1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0},
|
|
{0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1},
|
|
{0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
{1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0},
|
|
{1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0},
|
|
{0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1},
|
|
{0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1},
|
|
{1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0},
|
|
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0},
|
|
{0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1},
|
|
{0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1},
|
|
{1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0},
|
|
{1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0},
|
|
{0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1},
|
|
{0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0},
|
|
{1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1},
|
|
{1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1},
|
|
{0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0},
|
|
{0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0},
|
|
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1},
|
|
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1},
|
|
{0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0},
|
|
{0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0},
|
|
{1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1},
|
|
{1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1},
|
|
{0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0},
|
|
{0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0},
|
|
{1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1},
|
|
{1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1},
|
|
{0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0},
|
|
{0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0},
|
|
{1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1},
|
|
{1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1},
|
|
{0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0},
|
|
{0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0},
|
|
{1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1},
|
|
{1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1},
|
|
{0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0},
|
|
{0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0},
|
|
{1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1},
|
|
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1},
|
|
{0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0},
|
|
{0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0},
|
|
{1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1},
|
|
{1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1},
|
|
{0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0},
|
|
{0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1},
|
|
{1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0},
|
|
{1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0},
|
|
{0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1},
|
|
{0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
|
|
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
|
|
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0},
|
|
{0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1},
|
|
{0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
|
|
{1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0},
|
|
{1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0},
|
|
{0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1},
|
|
{0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1},
|
|
{1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0},
|
|
{1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0},
|
|
{0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1} };
|
|
|
|
// W5_TBL
|
|
int16_t W5_fmt3_re[5][5] = { {32767, 32767, 32767, 32767, 32767},
|
|
{32767, 10125, -26509, -26509, 10125},
|
|
{32767, -26509, 10125, 10125, -26509},
|
|
{32767, -26509, 10125, 10125, -26509},
|
|
{32767, 10125, -26509, -26509, 10125} };
|
|
|
|
int16_t W5_fmt3_im[5][5] = { {0, 0, 0, 0, 0},
|
|
{0, 31163, 19259, -19259, -31163},
|
|
{0, 19259, -31163, 31163, -19259},
|
|
{0, -19259, 31163, -31163, 19259},
|
|
{0, -31163, -19259, 19259, 31163} };
|
|
|
|
int16_t W4_fmt3[4][4] = { {32767, 32767, 32767, 32767},
|
|
{32767, -32767, 32767, -32767},
|
|
{32767, 32767, -32767, -32767},
|
|
{32767, -32767, -32767, 32767} };
|
|
|
|
// W2 TBL
|
|
int16_t W2[2] = {32767, 32767};
|
|
|
|
// e^j*pai*floor (ncs_cell(ns,l)/64)/2
|
|
int16_t RotTBL_re[4] = {32767, 0, -32767, 0};
|
|
int16_t RotTBL_im[4] = {0, 32767, 0, -32767};
|
|
|
|
//np4_tbl, np5_tbl
|
|
uint8_t Np5_TBL[5] = {0, 3, 6, 8, 10};
|
|
uint8_t Np4_TBL[4] = {0, 3, 6, 9};
|
|
|
|
// alpha_TBL
|
|
int16_t alphaTBL_re[12] = {32767, 28377, 16383, 0, -16383, -28377, -32767, -28377, -16383, 0, 16383, 28377};
|
|
int16_t alphaTBL_im[12] = {0, 16383, 28377, 32767, 28377, 16383, 0, -16383, -28377, -32767, -28377, -16383};
|
|
|
|
/* PUCCH format3 << */
|
|
|
|
void generate_pucch1x(int32_t **txdataF,
|
|
LTE_DL_FRAME_PARMS *frame_parms,
|
|
uint8_t ncs_cell[20][7],
|
|
PUCCH_FMT_t fmt,
|
|
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
|
|
uint16_t n1_pucch,
|
|
uint8_t shortened_format,
|
|
uint8_t *payload,
|
|
int16_t amp,
|
|
uint8_t subframe)
|
|
{
|
|
|
|
uint32_t u,v,n;
|
|
uint32_t z[12*14],*zptr;
|
|
int16_t d0;
|
|
uint8_t ns,N_UL_symb,nsymb,n_oc,n_oc0,n_oc1;
|
|
uint8_t c = (frame_parms->Ncp==0) ? 3 : 2;
|
|
uint16_t nprime,nprime0,nprime1;
|
|
uint16_t i,j,re_offset,thres,h;
|
|
uint8_t Nprime_div_deltaPUCCH_Shift,Nprime,d;
|
|
uint8_t m,l,refs;
|
|
uint8_t n_cs,S,alpha_ind,rem;
|
|
int16_t tmp_re,tmp_im,ref_re,ref_im,W_re=0,W_im=0;
|
|
int32_t *txptr;
|
|
uint32_t symbol_offset;
|
|
|
|
uint8_t deltaPUCCH_Shift = frame_parms->pucch_config_common.deltaPUCCH_Shift;
|
|
uint8_t NRB2 = frame_parms->pucch_config_common.nRB_CQI;
|
|
uint8_t Ncs1 = frame_parms->pucch_config_common.nCS_AN;
|
|
uint8_t Ncs1_div_deltaPUCCH_Shift = Ncs1/deltaPUCCH_Shift;
|
|
|
|
LOG_D(PHY,"generate_pucch Start [deltaPUCCH_Shift %d, NRB2 %d, Ncs1_div_deltaPUCCH_Shift %d, n1_pucch %d]\n", deltaPUCCH_Shift, NRB2, Ncs1_div_deltaPUCCH_Shift,n1_pucch);
|
|
|
|
|
|
uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
|
|
uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
|
|
uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
|
|
uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
|
|
|
|
if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) {
|
|
printf("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift);
|
|
return;
|
|
}
|
|
|
|
if (Ncs1_div_deltaPUCCH_Shift > 7) {
|
|
printf("[PHY] generate_pucch: Illegal Ncs1_div_deltaPUCCH_Shift %d (should be 0...7)\n",Ncs1_div_deltaPUCCH_Shift);
|
|
return;
|
|
}
|
|
|
|
zptr = z;
|
|
thres = (c*Ncs1_div_deltaPUCCH_Shift);
|
|
Nprime_div_deltaPUCCH_Shift = (n1_pucch < thres) ? Ncs1_div_deltaPUCCH_Shift : (12/deltaPUCCH_Shift);
|
|
Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift;
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch);
|
|
#endif
|
|
|
|
LOG_D(PHY,"[PHY] PUCCH: n1_pucch %d, thres %d Ncs1_div_deltaPUCCH_Shift %d (12/deltaPUCCH_Shift) %d Nprime_div_deltaPUCCH_Shift %d \n",
|
|
n1_pucch, thres, Ncs1_div_deltaPUCCH_Shift, (int)(12/deltaPUCCH_Shift), Nprime_div_deltaPUCCH_Shift);
|
|
LOG_D(PHY,"[PHY] PUCCH: deltaPUCCH_Shift %d, Nprime %d\n",deltaPUCCH_Shift,Nprime);
|
|
|
|
|
|
N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6;
|
|
|
|
if (n1_pucch < thres)
|
|
nprime0=n1_pucch;
|
|
else
|
|
nprime0 = (n1_pucch - thres)%(12*c/deltaPUCCH_Shift);
|
|
|
|
if (n1_pucch >= thres)
|
|
nprime1= ((c*(nprime0+1))%((12*c/deltaPUCCH_Shift)+1))-1;
|
|
else {
|
|
d = (frame_parms->Ncp==0) ? 2 : 0;
|
|
h= (nprime0+d)%(c*Nprime_div_deltaPUCCH_Shift);
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH: h %d, d %d\n",h,d);
|
|
#endif
|
|
nprime1 = (h/c) + (h%c)*Nprime_div_deltaPUCCH_Shift;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH: nprime0 %d nprime1 %d, %s, payload (%d,%d)\n",nprime0,nprime1,pucch_format_string[fmt],payload[0],payload[1]);
|
|
#endif
|
|
|
|
n_oc0 = nprime0/Nprime_div_deltaPUCCH_Shift;
|
|
|
|
if (frame_parms->Ncp==1)
|
|
n_oc0<<=1;
|
|
|
|
n_oc1 = nprime1/Nprime_div_deltaPUCCH_Shift;
|
|
|
|
if (frame_parms->Ncp==1) // extended CP
|
|
n_oc1<<=1;
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH: noc0 %d noc1 %d\n",n_oc0,n_oc1);
|
|
#endif
|
|
|
|
nprime=nprime0;
|
|
n_oc =n_oc0;
|
|
|
|
// loop over 2 slots
|
|
for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
|
|
|
|
if ((nprime&1) == 0)
|
|
S=0; // 1
|
|
else
|
|
S=1; // j
|
|
|
|
//loop over symbols in slot
|
|
for (l=0; l<N_UL_symb; l++) {
|
|
// Compute n_cs (36.211 p. 18)
|
|
n_cs = ncs_cell[ns][l];
|
|
|
|
if (frame_parms->Ncp==0) { // normal CP
|
|
n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc%deltaPUCCH_Shift))%Nprime)%12;
|
|
} else {
|
|
n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc>>1))%Nprime)%12;
|
|
}
|
|
|
|
|
|
refs=0;
|
|
|
|
// Comput W_noc(m) (36.211 p. 19)
|
|
if ((ns==(1+(subframe<<1))) && (shortened_format==1)) { // second slot and shortened format
|
|
|
|
if (l<2) { // data
|
|
W_re=W3_re[n_oc][l];
|
|
W_im=W3_im[n_oc][l];
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==0)) { // reference and normal CP
|
|
W_re=W3_re[n_oc][l-2];
|
|
W_im=W3_im[n_oc][l-2];
|
|
refs=1;
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==1)) { // reference and extended CP
|
|
W_re=W4[n_oc][l-2];
|
|
W_im=0;
|
|
refs=1;
|
|
} else if ((l>=N_UL_symb-2)) { // data
|
|
W_re=W3_re[n_oc][l-N_UL_symb+4];
|
|
W_im=W3_im[n_oc][l-N_UL_symb+4];
|
|
}
|
|
} else {
|
|
if (l<2) { // data
|
|
W_re=W4[n_oc][l];
|
|
W_im=0;
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==0)) { // reference and normal CP
|
|
W_re=W3_re[n_oc][l-2];
|
|
W_im=W3_im[n_oc][l-2];
|
|
refs=1;
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==1)) { // reference and extended CP
|
|
W_re=W4[n_oc][l-2];
|
|
W_im=0;
|
|
refs=1;
|
|
} else if ((l>=N_UL_symb-2)) { // data
|
|
W_re=W4[n_oc][l-N_UL_symb+4];
|
|
W_im=0;
|
|
}
|
|
}
|
|
|
|
// multiply W by S(ns) (36.211 p.17). only for data, reference symbols do not have this factor
|
|
if ((S==1)&&(refs==0)) {
|
|
tmp_re = W_re;
|
|
W_re = -W_im;
|
|
W_im = tmp_re;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs);
|
|
#endif
|
|
alpha_ind=0;
|
|
// compute output sequence
|
|
|
|
for (n=0; n<12; n++) {
|
|
|
|
// this is r_uv^alpha(n)
|
|
tmp_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
|
|
tmp_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
|
|
|
|
// this is S(ns)*w_noc(m)*r_uv^alpha(n)
|
|
ref_re = (tmp_re*W_re - tmp_im*W_im)>>15;
|
|
ref_im = (tmp_re*W_im + tmp_im*W_re)>>15;
|
|
|
|
if ((l<2)||(l>=(N_UL_symb-2))) { //these are PUCCH data symbols
|
|
switch (fmt) {
|
|
case pucch_format1: //OOK 1-bit
|
|
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re)>>15;
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im)>>15;
|
|
|
|
break;
|
|
|
|
case pucch_format1a: //BPSK 1-bit
|
|
d0 = (payload[0]&1)==0 ? amp : -amp;
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)d0*ref_re)>>15;
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)d0*ref_im)>>15;
|
|
// printf("d0 %d\n",d0);
|
|
break;
|
|
|
|
case pucch_format1b: //QPSK 2-bits (Table 5.4.1-1 from 36.211, pg. 18)
|
|
if (((payload[0]&1)==0) && ((payload[1]&1)==0)) {// 1
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re)>>15;
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im)>>15;
|
|
} else if (((payload[0]&1)==0) && ((payload[1]&1)==1)) { // -j
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_im)>>15;
|
|
((int16_t *)&zptr[n])[1] = (-(int32_t)amp*ref_re)>>15;
|
|
} else if (((payload[0]&1)==1) && ((payload[1]&1)==0)) { // j
|
|
((int16_t *)&zptr[n])[0] = (-(int32_t)amp*ref_im)>>15;
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_re)>>15;
|
|
} else { // -1
|
|
((int16_t *)&zptr[n])[0] = (-(int32_t)amp*ref_re)>>15;
|
|
((int16_t *)&zptr[n])[1] = (-(int32_t)amp*ref_im)>>15;
|
|
}
|
|
|
|
break;
|
|
|
|
case pucch_format2:
|
|
case pucch_format2a:
|
|
case pucch_format2b:
|
|
AssertFatal(1==0,"should not go here\n");
|
|
break;
|
|
|
|
case pucch_format3:
|
|
fprintf(stderr, "PUCCH format 3 not handled\n");
|
|
abort();
|
|
} // switch fmt
|
|
} else { // These are PUCCH reference symbols
|
|
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re)>>15;
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im)>>15;
|
|
// printf("ref\n");
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,((int16_t *)&zptr[n])[0],((int16_t *)&zptr[n])[1],
|
|
alpha_ind,alpha_re[alpha_ind],alpha_im[alpha_ind]);
|
|
#endif
|
|
alpha_ind = (alpha_ind + n_cs)%12;
|
|
} // n
|
|
|
|
zptr+=12;
|
|
} // l
|
|
|
|
nprime=nprime1;
|
|
n_oc =n_oc1;
|
|
} // ns
|
|
|
|
rem = ((((12*Ncs1_div_deltaPUCCH_Shift)>>3)&7)>0) ? 1 : 0;
|
|
|
|
m = (n1_pucch < thres) ? NRB2 : (((n1_pucch-thres)/(12*c/deltaPUCCH_Shift))+NRB2+((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)+rem);
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH: m %d\n",m);
|
|
#endif
|
|
nsymb = N_UL_symb<<1;
|
|
|
|
//for (j=0,l=0;l<(nsymb-1);l++) {
|
|
for (j=0,l=0; l<(nsymb); l++) {
|
|
if ((l<(nsymb>>1)) && ((m&1) == 0))
|
|
re_offset = (m*6) + frame_parms->first_carrier_offset;
|
|
else if ((l<(nsymb>>1)) && ((m&1) == 1))
|
|
re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else if ((m&1) == 0)
|
|
re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else
|
|
re_offset = ((m-1)*6) + frame_parms->first_carrier_offset;
|
|
|
|
if (re_offset > frame_parms->ofdm_symbol_size)
|
|
re_offset -= (frame_parms->ofdm_symbol_size);
|
|
|
|
symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*(l+(subframe*nsymb));
|
|
txptr = &txdataF[0][symbol_offset];
|
|
|
|
for (i=0; i<12; i++,j++) {
|
|
txptr[re_offset++] = z[j];
|
|
|
|
if (re_offset==frame_parms->ofdm_symbol_size)
|
|
re_offset = 0;
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void generate_pucch_emul(PHY_VARS_UE *ue,
|
|
UE_rxtx_proc_t *proc,
|
|
PUCCH_FMT_t format,
|
|
uint8_t ncs1,
|
|
uint8_t *pucch_payload,
|
|
uint8_t sr)
|
|
|
|
{
|
|
|
|
int subframe = proc->subframe_tx;
|
|
|
|
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_flag = format;
|
|
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_Ncs1 = ncs1;
|
|
|
|
|
|
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.sr = sr;
|
|
// the value of ue->pucch_sel[subframe] is set by get_n1_pucch
|
|
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_sel = ue->pucch_sel[subframe];
|
|
|
|
// LOG_I(PHY,"subframe %d emu tx pucch_sel is %d sr is %d \n", subframe, UE_transport_info[ue->Mod_id].cntl.pucch_sel, sr);
|
|
|
|
if (format == pucch_format1a) {
|
|
|
|
ue->pucch_payload[0] = pucch_payload[0];
|
|
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0];
|
|
} else if (format == pucch_format1b) {
|
|
ue->pucch_payload[0] = pucch_payload[0] + (pucch_payload[1]<<1);
|
|
UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0] + (pucch_payload[1]<<1);
|
|
} else if (format == pucch_format1) {
|
|
// LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,proc->frame_tx,subframe,sr);
|
|
}
|
|
|
|
ue->sr[subframe] = sr;
|
|
|
|
}
|
|
|
|
|
|
inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) __attribute__((always_inline));
|
|
inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) {
|
|
|
|
uint32_t x1, x2, s=0;
|
|
int i;
|
|
uint8_t c;
|
|
|
|
x2 = (rnti) + ((uint32_t)(1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1
|
|
s = lte_gold_generic(&x1, &x2, 1);
|
|
for (i=0;i<19;i++) {
|
|
c = (uint8_t)((s>>i)&1);
|
|
btilde[i] = (((B>>i)&1) ^ c);
|
|
}
|
|
}
|
|
|
|
inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) __attribute__((always_inline));
|
|
inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) {
|
|
|
|
int i;
|
|
|
|
for (i=0;i<20;i++)
|
|
d[i] = btilde[i] == 1 ? -amp : amp;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t pucch_code[13] = {0xFFFFF,0x5A933,0x10E5A,0x6339C,0x73CE0,
|
|
0xFFC00,0xD8E64,0x4F6B0,0x218EC,0x1B746,
|
|
0x0FFFF,0x33FFF,0x3FFFC};
|
|
|
|
|
|
void generate_pucch2x(int32_t **txdataF,
|
|
LTE_DL_FRAME_PARMS *fp,
|
|
uint8_t ncs_cell[20][7],
|
|
PUCCH_FMT_t fmt,
|
|
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
|
|
uint16_t n2_pucch,
|
|
uint8_t *payload,
|
|
int A,
|
|
int B2,
|
|
int16_t amp,
|
|
uint8_t subframe,
|
|
uint16_t rnti) {
|
|
|
|
int i,j;
|
|
uint32_t B=0;
|
|
uint8_t btilde[20];
|
|
int16_t d[22];
|
|
uint8_t deltaPUCCH_Shift = fp->pucch_config_common.deltaPUCCH_Shift;
|
|
uint8_t NRB2 = fp->pucch_config_common.nRB_CQI;
|
|
uint8_t Ncs1 = fp->pucch_config_common.nCS_AN;
|
|
|
|
uint32_t u0 = fp->pucch_config_common.grouphop[subframe<<1];
|
|
uint32_t u1 = fp->pucch_config_common.grouphop[1+(subframe<<1)];
|
|
uint32_t v0 = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
|
|
uint32_t v1 = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
|
|
|
|
uint32_t z[12*14],*zptr;
|
|
uint32_t u,v,n;
|
|
uint8_t ns,N_UL_symb,nsymb_slot0,nsymb_pertti;
|
|
uint32_t nprime,l,n_cs;
|
|
int alpha_ind,data_ind;
|
|
int16_t ref_re,ref_im;
|
|
int m,re_offset,symbol_offset;
|
|
int32_t *txptr;
|
|
|
|
if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) {
|
|
printf("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift);
|
|
return;
|
|
}
|
|
|
|
if (Ncs1 > 7) {
|
|
printf("[PHY] generate_pucch: Illegal Ncs1 %d (should be 0...7)\n",Ncs1);
|
|
return;
|
|
}
|
|
|
|
// pucch2x_encoding
|
|
for (i=0;i<A;i++)
|
|
if ((*payload & (1<<i)) > 0)
|
|
B=B^pucch_code[i];
|
|
|
|
// scrambling
|
|
pucch2x_scrambling(fp,subframe,rnti,B,btilde);
|
|
// modulation
|
|
pucch2x_modulation(btilde,d,amp);
|
|
|
|
// add extra symbol for 2a/2b
|
|
d[20]=0;
|
|
d[21]=0;
|
|
if (fmt==pucch_format2a)
|
|
d[20] = (B2 == 0) ? amp : -amp;
|
|
else if (fmt==pucch_format2b) {
|
|
switch (B2) {
|
|
case 0:
|
|
d[20] = amp;
|
|
break;
|
|
case 1:
|
|
d[21] = -amp;
|
|
break;
|
|
case 2:
|
|
d[21] = amp;
|
|
break;
|
|
case 3:
|
|
d[20] = -amp;
|
|
break;
|
|
default:
|
|
AssertFatal(1==0,"Illegal modulation symbol %d for PUCCH %s\n",B2,pucch_format_string[fmt]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
printf("[PHY] PUCCH2x: n2_pucch %d\n",n2_pucch);
|
|
#endif
|
|
|
|
N_UL_symb = (fp->Ncp==0) ? 7 : 6;
|
|
data_ind = 0;
|
|
zptr = z;
|
|
nprime = 0;
|
|
for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
|
|
|
|
if ((ns&1) == 0)
|
|
nprime = (n2_pucch < 12*NRB2) ?
|
|
n2_pucch % 12 :
|
|
(n2_pucch+Ncs1 + 1)%12;
|
|
else {
|
|
nprime = (n2_pucch < 12*NRB2) ?
|
|
((12*(nprime+1)) % 13)-1 :
|
|
(10-n2_pucch)%12;
|
|
}
|
|
//loop over symbols in slot
|
|
for (l=0; l<N_UL_symb; l++) {
|
|
// Compute n_cs (36.211 p. 18)
|
|
n_cs = (ncs_cell[ns][l]+nprime)%12;
|
|
|
|
alpha_ind = 0;
|
|
for (n=0; n<12; n++)
|
|
{
|
|
// this is r_uv^alpha(n)
|
|
ref_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
|
|
ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
|
|
|
|
if ((l!=1)&&(l!=5)) { //these are PUCCH data symbols
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15;
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15;
|
|
//LOG_I(PHY,"slot %d ofdm# %d ==> d[%d,%d] \n",ns,l,data_ind,n);
|
|
}
|
|
else {
|
|
if ((l==1) || ( (l==5) && (fmt==pucch_format2) ))
|
|
{
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re>>15);
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im>>15);
|
|
}
|
|
// l == 5 && pucch format 2a
|
|
else if (fmt==pucch_format2a)
|
|
{
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)d[20]*ref_re>>15);
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)d[21]*ref_im>>15);
|
|
}
|
|
// l == 5 && pucch format 2b
|
|
else if (fmt==pucch_format2b)
|
|
{
|
|
((int16_t *)&zptr[n])[0] = ((int32_t)d[20]*ref_re>>15);
|
|
((int16_t *)&zptr[n])[1] = ((int32_t)d[21]*ref_im>>15);
|
|
}
|
|
} // l==1 || l==5
|
|
alpha_ind = (alpha_ind + n_cs)%12;
|
|
} // n
|
|
zptr+=12;
|
|
|
|
if ((l!=1)&&(l!=5)) //these are PUCCH data symbols so increment data index
|
|
data_ind+=2;
|
|
} // l
|
|
} //ns
|
|
|
|
m = n2_pucch/12;
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
LOG_D(PHY,"[PHY] PUCCH: n2_pucch %d m %d\n",n2_pucch,m);
|
|
#endif
|
|
|
|
nsymb_slot0 = ((fp->Ncp==0) ? 7 : 6);
|
|
nsymb_pertti = nsymb_slot0 << 1;
|
|
|
|
//nsymb = nsymb_slot0<<1;
|
|
|
|
//for (j=0,l=0;l<(nsymb-1);l++) {
|
|
for (j=0,l=0; l<(nsymb_pertti); l++) {
|
|
|
|
if ((l<nsymb_slot0) && ((m&1) == 0))
|
|
re_offset = (m*6) + fp->first_carrier_offset;
|
|
else if ((l<nsymb_slot0) && ((m&1) == 1))
|
|
re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
|
|
else if ((m&1) == 0)
|
|
re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
|
|
else
|
|
re_offset = ((m-1)*6) + fp->first_carrier_offset;
|
|
|
|
if (re_offset > fp->ofdm_symbol_size)
|
|
re_offset -= (fp->ofdm_symbol_size);
|
|
|
|
|
|
|
|
symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb_pertti));
|
|
txptr = &txdataF[0][symbol_offset];
|
|
|
|
//LOG_I(PHY,"ofdmSymb %d/%d, firstCarrierOffset %d, symbolOffset[sfn %d] %d, reOffset %d, &txptr: %x \n", l, nsymb, fp->first_carrier_offset, subframe, symbol_offset, re_offset, &txptr[0]);
|
|
|
|
for (i=0; i<12; i++,j++) {
|
|
txptr[re_offset] = z[j];
|
|
|
|
re_offset++;
|
|
|
|
if (re_offset==fp->ofdm_symbol_size)
|
|
re_offset -= (fp->ofdm_symbol_size);
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
LOG_D(PHY,"[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/* PUCCH format3 >> */
|
|
/* DFT */
|
|
void pucchfmt3_Dft( int16_t *x, int16_t *y )
|
|
{
|
|
int16_t i, k;
|
|
int16_t tmp[2];
|
|
int16_t calctmp[D_NSC1RB*2]={0};
|
|
|
|
for (i=0; i<D_NSC1RB; i++) {
|
|
for(k=0; k<D_NSC1RB; k++) {
|
|
tmp[0] = alphaTBL_re[(12-((i*k)%12))%12];
|
|
tmp[1] = alphaTBL_im[(12-((i*k)%12))%12];
|
|
|
|
calctmp[2*i] += (((int32_t)x[2*k] * tmp[0] - (int32_t)x[2*k+1] * tmp[1])>>15);
|
|
calctmp[2*i+1] += (((int32_t)x[2*k+1] * tmp[0] + (int32_t)x[2*k] * tmp[1])>>15);
|
|
}
|
|
y[2*i] = (int16_t)( (double) calctmp[2*i] / sqrt(D_NSC1RB));
|
|
y[2*i+1] = (int16_t)((double) calctmp[2*i+1] / sqrt(D_NSC1RB));
|
|
}
|
|
}
|
|
|
|
void generate_pucch3x(int32_t **txdataF,
|
|
LTE_DL_FRAME_PARMS *frame_parms,
|
|
uint8_t ncs_cell[20][7],
|
|
PUCCH_FMT_t fmt,
|
|
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
|
|
uint16_t n3_pucch,
|
|
uint8_t shortened_format,
|
|
uint8_t *payload,
|
|
int16_t amp,
|
|
uint8_t subframe,
|
|
uint16_t rnti)
|
|
{
|
|
|
|
uint32_t u, v;
|
|
uint16_t i, j, re_offset;
|
|
uint32_t z[12*14], *zptr;
|
|
uint32_t y_tilda[12*14]={}, *y_tilda_ptr;
|
|
uint8_t ns, nsymb, n_oc, n_oc0, n_oc1;
|
|
uint8_t N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6;
|
|
uint8_t m, l;
|
|
uint8_t n_cs;
|
|
int16_t tmp_re, tmp_im, W_re=0, W_im=0;
|
|
int32_t *txptr;
|
|
uint32_t symbol_offset;
|
|
|
|
uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
|
|
uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
|
|
uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
|
|
uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
|
|
|
|
// variables for channel coding
|
|
uint8_t chcod_tbl_idx = 0;
|
|
//uint8_t chcod_dt[48] = {};
|
|
|
|
// variables for Scrambling
|
|
uint32_t cinit = 0;
|
|
uint32_t x1;
|
|
uint32_t s,s0,s1;
|
|
uint8_t C[48] ={};
|
|
uint8_t scr_dt[48]={};
|
|
|
|
// variables for Modulation
|
|
int16_t d_re[24]={};
|
|
int16_t d_im[24]={};
|
|
|
|
// variables for orthogonal sequence selection
|
|
uint8_t N_PUCCH_SF0 = 5;
|
|
uint8_t N_PUCCH_SF1 = (shortened_format==0)? 5:4;
|
|
uint8_t first_slot = 0;
|
|
int16_t rot_re=0;
|
|
int16_t rot_im=0;
|
|
|
|
uint8_t dt_offset;
|
|
uint8_t sym_offset;
|
|
int16_t y_re[14][12]; //={0};
|
|
int16_t y_im[14][12]; //={0};
|
|
|
|
// DMRS
|
|
uint8_t alpha_idx=0;
|
|
uint8_t m_alpha_idx=0;
|
|
|
|
// TODO
|
|
// "SR+ACK/NACK" length is only 7 bits.
|
|
// This restriction will be lifted in the future.
|
|
// "CQI/PMI/RI+ACK/NACK" will be supported in the future.
|
|
|
|
// Channel Coding
|
|
for (uint8_t i=0; i<7; i++) {
|
|
chcod_tbl_idx += (payload[i]<<i);
|
|
}
|
|
|
|
// Scrambling
|
|
cinit = (subframe + 1) * ((2 * frame_parms->Nid_cell + 1)<<16) + rnti;
|
|
s0 = lte_gold_generic(&x1,&cinit,1);
|
|
s1 = lte_gold_generic(&x1,&cinit,0);
|
|
|
|
for (i=0; i<48; i++) {
|
|
s = (i<32)? s0:s1;
|
|
j = (i<32)? i:(i-32);
|
|
C[i] = ((s>>j)&1);
|
|
}
|
|
|
|
for (i=0; i<48; i++) {
|
|
scr_dt[i] = chcod_tbl[chcod_tbl_idx][i] ^ C[i];
|
|
}
|
|
|
|
// Modulation
|
|
for (uint8_t i=0; i<48; i+=2){
|
|
if (scr_dt[i]==0 && scr_dt[i+1]==0){
|
|
d_re[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp) >>15);
|
|
d_im[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp) >>15);
|
|
} else if (scr_dt[i]==0 && scr_dt[i+1]==1) {
|
|
d_re[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp) >>15);
|
|
d_im[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp) >>15);
|
|
} else if (scr_dt[i]==1 && scr_dt[i+1]==0) {
|
|
d_re[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp)>>15);
|
|
d_im[ i>>1] = ((ONE_OVER_SQRT2_Q15 * amp)>>15);
|
|
} else if (scr_dt[i]==1 && scr_dt[i+1]==1) {
|
|
d_re[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp)>>15);
|
|
d_im[ i>>1] = -1 * ((ONE_OVER_SQRT2_Q15 * amp)>>15);
|
|
} else {
|
|
//***log Modulation Error!
|
|
}
|
|
}
|
|
|
|
// Calculate Orthogonal Sequence index
|
|
n_oc0 = n3_pucch % N_PUCCH_SF1;
|
|
if (N_PUCCH_SF1 == 5) {
|
|
n_oc1 = (3 * n_oc0) % N_PUCCH_SF1;
|
|
} else {
|
|
n_oc1 = n_oc0 % N_PUCCH_SF1;
|
|
}
|
|
|
|
y_tilda_ptr = y_tilda;
|
|
zptr = z;
|
|
|
|
// loop over 2 slots
|
|
for (ns=(subframe<<1), u=u0, v=v0; ns<(2+(subframe<<1)); ns++, u=u1, v=v1) {
|
|
first_slot = (ns==(subframe<<1))?1:0;
|
|
|
|
//loop over symbols in slot
|
|
for (l=0; l<N_UL_symb; l++) {
|
|
rot_re = RotTBL_re[(uint8_t) ncs_cell[ns][l]/64] ;
|
|
rot_im = RotTBL_im[(uint8_t) ncs_cell[ns][l]/64] ;
|
|
|
|
// Comput W_noc(m) (36.211 p. 19)
|
|
if ( first_slot == 0 && shortened_format==1) { // second slot and shortened format
|
|
n_oc = n_oc1;
|
|
|
|
if (l<1) { // data
|
|
W_re=W4_fmt3[n_oc][l];
|
|
W_im=0;
|
|
} else if (l==1) { // DMRS
|
|
W_re=W2[0];
|
|
W_im=0;
|
|
} else if (l>=2 && l<5) { // data
|
|
W_re=W4_fmt3[n_oc][l-1];
|
|
W_im=0;
|
|
} else if (l==5) { // DMRS
|
|
W_re=W2[1];
|
|
W_im=0;
|
|
} else if ((l>=N_UL_symb-2)) { // data
|
|
;
|
|
} else {
|
|
//***log W Select Error!
|
|
}
|
|
} else {
|
|
if (first_slot == 1) { // 1st slot or 2nd slot and not shortened
|
|
n_oc=n_oc0;
|
|
} else {
|
|
n_oc=n_oc1;
|
|
}
|
|
|
|
if (l<1) { // data
|
|
W_re=W5_fmt3_re[n_oc][l];
|
|
W_im=W5_fmt3_im[n_oc][l];
|
|
} else if (l==1) { // DMRS
|
|
W_re=W2[0];
|
|
W_im=0;
|
|
} else if (l>=2 && l<5) { // data
|
|
W_re=W5_fmt3_re[n_oc][l-1];
|
|
W_im=W5_fmt3_im[n_oc][l-1];
|
|
} else if (l==5) { // DMRS
|
|
W_re=W2[1];
|
|
W_im=0;
|
|
} else if ((l>=N_UL_symb-1)) { // data
|
|
W_re=W5_fmt3_re[n_oc][l-N_UL_symb+5];
|
|
W_im=W5_fmt3_im[n_oc][l-N_UL_symb+5];
|
|
} else {
|
|
//***log W Select Error!
|
|
}
|
|
} // W Selection end
|
|
|
|
// Compute n_cs (36.211 p. 18)
|
|
n_cs = ncs_cell[ns][l];
|
|
if (N_PUCCH_SF1 == 5) {
|
|
alpha_idx = (n_cs + Np5_TBL[n_oc]) % 12;
|
|
} else {
|
|
alpha_idx = (n_cs + Np4_TBL[n_oc]) % 12;
|
|
}
|
|
|
|
// generate pucch data
|
|
dt_offset = (first_slot == 1) ? 0:12;
|
|
sym_offset = (first_slot == 1) ? 0:7;
|
|
|
|
for (i=0; i<12; i++) {
|
|
// Calculate yn(i)
|
|
tmp_re = (((int32_t) (W_re*rot_re - W_im*rot_im)) >>15);
|
|
tmp_im = (((int32_t) (W_re*rot_im + W_im*rot_re)) >>15);
|
|
y_re[l+sym_offset][i] = (((int32_t) (tmp_re*d_re[i+dt_offset] - tmp_im*d_im[i+dt_offset]))>>15);
|
|
y_im[l+sym_offset][i] = (((int32_t) (tmp_re*d_im[i+dt_offset] + tmp_im*d_re[i+dt_offset]))>>15);
|
|
|
|
// cyclic shift
|
|
((int16_t *)&y_tilda_ptr[(l+sym_offset)*12+(i-(ncs_cell[ns][l]%12)+12)%12])[0] = y_re[l+sym_offset][i];
|
|
((int16_t *)&y_tilda_ptr[(l+sym_offset)*12+(i-(ncs_cell[ns][l]%12)+12)%12])[1] = y_im[l+sym_offset][i];
|
|
|
|
// DMRS
|
|
m_alpha_idx = (alpha_idx * i) % 12;
|
|
if (l==1 || l==5) {
|
|
((int16_t *)&zptr[(l+sym_offset)*12+i])[0] =(((((int32_t) alphaTBL_re[m_alpha_idx]*ul_ref_sigs[u][v][0][i<<1] - (int32_t) alphaTBL_im[m_alpha_idx] * ul_ref_sigs[u][v][0][1+(i<<1)])>>15) * (int32_t)amp)>>15);
|
|
((int16_t *)&zptr[(l+sym_offset)*12+i])[1] =(((((int32_t) alphaTBL_re[m_alpha_idx]*ul_ref_sigs[u][v][0][1+(i<<1)] + (int32_t) alphaTBL_im[m_alpha_idx] * ul_ref_sigs[u][v][0][i<<1])>>15) * (int32_t)amp)>>15);
|
|
}
|
|
}
|
|
|
|
} // l loop
|
|
} // ns
|
|
|
|
// DFT for pucch-data
|
|
for (l=0; l<14; l++) {
|
|
if (l==1 || l==5 || l==8 || l==12) {
|
|
;
|
|
} else {
|
|
pucchfmt3_Dft((int16_t*)&y_tilda_ptr[l*12],(int16_t*)&zptr[l*12]);
|
|
}
|
|
}
|
|
|
|
|
|
// Mapping
|
|
m = n3_pucch / N_PUCCH_SF0;
|
|
|
|
if (shortened_format == 1) {
|
|
nsymb = (N_UL_symb<<1) - 1;
|
|
} else {
|
|
nsymb = (N_UL_symb<<1);
|
|
}
|
|
|
|
for (j=0,l=0; l<(nsymb); l++) {
|
|
|
|
if ((l<7) && ((m&1) == 0))
|
|
re_offset = (m*6) + frame_parms->first_carrier_offset;
|
|
else if ((l<7) && ((m&1) == 1))
|
|
re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else if ((m&1) == 0)
|
|
re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else
|
|
re_offset = ((m-1)*6) + frame_parms->first_carrier_offset;
|
|
|
|
if (re_offset > frame_parms->ofdm_symbol_size)
|
|
re_offset -= (frame_parms->ofdm_symbol_size);
|
|
|
|
symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*(l+(subframe*14));
|
|
txptr = &txdataF[0][symbol_offset];
|
|
|
|
for (i=0; i<12; i++,j++) {
|
|
txptr[re_offset++] = z[j];
|
|
|
|
if (re_offset==frame_parms->ofdm_symbol_size)
|
|
re_offset = 0;
|
|
|
|
#ifdef DEBUG_PUCCH_TX
|
|
msg("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* PUCCH format3 << */
|
|
|
|
|
|
//#define Amax 13
|
|
//void init_pucch2x_rx() {};
|
|
|
|
|
|
/* PUCCH format3 >> */
|
|
/* SubCarrier Demap */
|
|
uint16_t pucchfmt3_subCarrierDeMapping( PHY_VARS_eNB *eNB,
|
|
int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2],
|
|
uint16_t n3_pucch )
|
|
{
|
|
LTE_eNB_COMMON *eNB_common_vars = &eNB->common_vars;
|
|
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
|
|
int16_t *rxptr;
|
|
uint8_t N_UL_symb = D_NSYM1SLT; // only Normal CP format
|
|
uint16_t m; // Mapping to physical resource blocks(m)
|
|
uint32_t aa;
|
|
uint16_t k, l;
|
|
uint32_t symbol_offset;
|
|
uint16_t carrier_offset;
|
|
|
|
|
|
m = n3_pucch / D_NPUCCH_SF5;
|
|
|
|
// Do detection
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
|
|
for (l=0; l<D_NSYM1SF; l++) {
|
|
|
|
if ((l<N_UL_symb) && ((m&1) == 0))
|
|
carrier_offset = (m*6) + frame_parms->first_carrier_offset;
|
|
else if ((l<N_UL_symb) && ((m&1) == 1))
|
|
carrier_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else if ((m&1) == 0)
|
|
carrier_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else
|
|
carrier_offset = (((m-1)*6) + frame_parms->first_carrier_offset);
|
|
|
|
if (carrier_offset > frame_parms->ofdm_symbol_size)
|
|
carrier_offset -= (frame_parms->ofdm_symbol_size);
|
|
|
|
symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*l;
|
|
rxptr = (int16_t *)&eNB_common_vars->rxdataF[0][aa][symbol_offset];
|
|
|
|
for (k=0; k<12; k++,carrier_offset++) {
|
|
SubCarrierDeMapData[aa][l][k][0] = (int16_t)rxptr[carrier_offset<<1]; // DeMapping Data I
|
|
SubCarrierDeMapData[aa][l][k][1] = (int16_t)rxptr[1+(carrier_offset<<1)]; // DeMapping Date Q
|
|
|
|
if (carrier_offset==frame_parms->ofdm_symbol_size)
|
|
carrier_offset = 0;
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d,%d) : (%d,%d)\n",subframe,l,k,carrier_offset,m,
|
|
SubCarrierDeMapData[aa][l][k][0],SubCarrierDeMapData[aa][l][k][1]);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* cyclic shift hopping remove */
|
|
uint16_t pucchfmt3_Baseseq_csh_remove( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2],
|
|
int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2],
|
|
LTE_DL_FRAME_PARMS *frame_parms,
|
|
uint8_t subframe,
|
|
uint8_t ncs_cell[20][7] )
|
|
{
|
|
//int16_t calctmp_baSeq[2];
|
|
int16_t calctmp_beta[2];
|
|
int16_t calctmp_alphak[2];
|
|
int16_t calctmp_SCDeMapData_alphak[2];
|
|
int32_t n_cell_cs_div64;
|
|
int32_t n_cell_cs_modNSC_RB;
|
|
|
|
//int32_t NSlot1subframe = D_NSLT1SF;
|
|
int32_t NSym1slot = D_NSYM1SLT; // Symbol per 1slot
|
|
int32_t NSym1subframe = D_NSYM1SF; // Symbol per 1subframe
|
|
int32_t aa, symNo, slotNo, sym, k;
|
|
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) { // Antenna
|
|
for (symNo=0; symNo<NSym1subframe; symNo++) { // Symbol
|
|
slotNo = symNo / NSym1slot;
|
|
sym = symNo % NSym1slot;
|
|
|
|
n_cell_cs_div64 = (int32_t)(ncs_cell[2*subframe+slotNo][sym]/64.0);
|
|
n_cell_cs_modNSC_RB = ncs_cell[2*subframe+slotNo][sym] % 12;
|
|
|
|
// for canceling e^(j*PI|_n_cs^cell(ns,l)/64_|/2).
|
|
calctmp_beta[0] = RotTBL_re[(n_cell_cs_div64)&0x3];
|
|
calctmp_beta[1] = RotTBL_im[(n_cell_cs_div64)&0x3];
|
|
|
|
for (k=0; k<12; k++) { // Sub Carrier
|
|
|
|
// for canceling being cyclically shifted"(i+n_cs^cell(ns,l))".
|
|
// e^((j*2PI(n_cs^cell(ns,l) mod N_SC)/N_SC)*k).
|
|
calctmp_alphak[0] = alphaTBL_re[((n_cell_cs_modNSC_RB)*k)%12];
|
|
calctmp_alphak[1] = alphaTBL_im[((n_cell_cs_modNSC_RB)*k)%12];
|
|
|
|
// e^(-alphar*k)*r_l,m,n,k
|
|
calctmp_SCDeMapData_alphak[0] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][0] * calctmp_alphak[0] + (int32_t)SubCarrierDeMapData[aa][symNo][k][1] * calctmp_alphak[1])>>15);
|
|
calctmp_SCDeMapData_alphak[1] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][1] * calctmp_alphak[0] - (int32_t)SubCarrierDeMapData[aa][symNo][k][0] * calctmp_alphak[1])>>15);
|
|
|
|
// (e^(-alphar*k)*r_l,m,n,k) * e^(-beta)
|
|
CshData_fmt3[aa][symNo][k][0] = (((int32_t)calctmp_SCDeMapData_alphak[0] * calctmp_beta[0] + (int32_t)calctmp_SCDeMapData_alphak[1] * calctmp_beta[1])>>15);
|
|
CshData_fmt3[aa][symNo][k][1] = (((int32_t)calctmp_SCDeMapData_alphak[1] * calctmp_beta[0] - (int32_t)calctmp_SCDeMapData_alphak[0] * calctmp_beta[1])>>15);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define MAXROW_TBL_SF5_OS_IDX (5) // Orthogonal sequence index
|
|
const int16_t TBL_3_SF5_GEN_N_DASH_NS[MAXROW_TBL_SF5_OS_IDX] = {0,3,6,8,10};
|
|
|
|
#define MAXROW_TBL_SF4_OS_IDX (4) // Orthogonal sequence index
|
|
const int16_t TBL_3_SF4_GEN_N_DASH_NS[MAXROW_TBL_SF4_OS_IDX] = {0,3,6,9};
|
|
|
|
/* Channel estimation */
|
|
uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2],
|
|
double delta_theta[NB_ANTENNAS_RX][12],
|
|
int16_t ChestValue[NB_ANTENNAS_RX][2][12][2],
|
|
int16_t *Interpw,
|
|
uint8_t subframe,
|
|
uint8_t shortened_format,
|
|
LTE_DL_FRAME_PARMS *frame_parms,
|
|
uint16_t n3_pucch,
|
|
uint16_t n3_pucch_array[NUMBER_OF_UE_MAX],
|
|
uint8_t ncs_cell[20][7] )
|
|
{
|
|
uint32_t aa, symNo, k, slotNo, sym, i, j;
|
|
int16_t np, np_n, ip_ind;
|
|
//int16_t npucch_sf;
|
|
int16_t calctmp[2];
|
|
int16_t BsCshData[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2];
|
|
//int16_t delta_theta_calctmp[NB_ANTENNAS_RX][4][D_NSC1RB][2], delta_theta_comp[NB_ANTENNAS_RX][D_NSC1RB][2];
|
|
int16_t delta_theta_comp[NB_ANTENNAS_RX][D_NSC1RB][2];
|
|
int16_t CsData_allavg[NB_ANTENNAS_RX][14][2];
|
|
int16_t CsData_temp[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2];
|
|
int32_t IP_CsData_allsfavg[NB_ANTENNAS_RX][14][4][2];
|
|
int32_t IP_allavg[D_NPUCCH_SF5];
|
|
//int16_t temp_ch[2];
|
|
int16_t m[NUMBER_OF_UE_MAX], m_self, same_m_number;
|
|
uint16_t n3_pucch_sameRB[NUMBER_OF_UE_MAX];
|
|
int16_t n_oc0[NUMBER_OF_UE_MAX];
|
|
int16_t n_oc1[NUMBER_OF_UE_MAX];
|
|
int16_t np_n_array[2][NUMBER_OF_UE_MAX]; //Cyclic shift
|
|
uint8_t N_PUCCH_SF0 = 5;
|
|
uint8_t N_PUCCH_SF1 = (shortened_format==0)? 5:4;
|
|
|
|
uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
|
|
uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
|
|
uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
|
|
uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
|
|
|
|
uint32_t u=u0;
|
|
uint32_t v=v0;
|
|
|
|
//double d_theta[32]={0.0};
|
|
//int32_t temp_theta[32][2]={0};
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (symNo=0; symNo<D_NSYM1SF; symNo++){
|
|
for(ip_ind=0; ip_ind<D_NPUCCH_SF5-1; ip_ind++) {
|
|
IP_CsData_allsfavg[aa][symNo][ip_ind][0] = 0;
|
|
IP_CsData_allsfavg[aa][symNo][ip_ind][1] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// compute m[], m_self
|
|
for(i=0; i<NUMBER_OF_UE_MAX; i++) {
|
|
m[i] = n3_pucch_array[i] / N_PUCCH_SF0; // N_PUCCH_SF0 = 5
|
|
if(n3_pucch_array[i] == n3_pucch) {
|
|
m_self = i;
|
|
}
|
|
}
|
|
|
|
for(i=0; i<NUMBER_OF_UE_MAX; i++) {
|
|
//printf("n3_pucch_array[%d]=%d, m[%d]=%d \n", i, n3_pucch_array[i], i, m[i]);
|
|
}
|
|
//printf("m_self=%d \n", m_self);
|
|
|
|
// compute n3_pucch_sameRB[] // Not 4 not be equally divided
|
|
for(i=0, same_m_number=0; i<NUMBER_OF_UE_MAX; i++) {
|
|
if(m[i] == m[m_self]) {
|
|
n3_pucch_sameRB[same_m_number] = n3_pucch_array[i];
|
|
same_m_number++;
|
|
}
|
|
}
|
|
//printf("same_m_number = %d \n", same_m_number);
|
|
for(i=0; i<same_m_number; i++) {
|
|
//printf("n3_pucch_sameRB[%d]=%d \n", i, n3_pucch_sameRB[i]);
|
|
}
|
|
|
|
// compute n_oc1[], n_oc0[]
|
|
for(i=0; i<same_m_number; i++) {
|
|
n_oc0[i] = n3_pucch_sameRB[i] % N_PUCCH_SF1; //N_PUCCH_SF1 = (shortened_format==0)? 5:4;
|
|
if (N_PUCCH_SF1 == 5) {
|
|
n_oc1[i] = (3 * n_oc0[i]) % N_PUCCH_SF1;
|
|
} else {
|
|
n_oc1[i] = n_oc0[i] % N_PUCCH_SF1;
|
|
}
|
|
}
|
|
for(i=0; i<same_m_number; i++) {
|
|
//printf("n_oc0[%d]=%d, n_oc1[%d]=%d \n", i, n_oc0[i], i, n_oc1[i]);
|
|
}
|
|
|
|
|
|
// np_n_array[][]
|
|
for(i=0; i<same_m_number; i++) {
|
|
if (N_PUCCH_SF1 == 5) {
|
|
np_n_array[0][i] = TBL_3_SF5_GEN_N_DASH_NS[n_oc0[i]]; //slot0
|
|
np_n_array[1][i] = TBL_3_SF5_GEN_N_DASH_NS[n_oc1[i]]; //slot1
|
|
} else {
|
|
np_n_array[0][i] = TBL_3_SF4_GEN_N_DASH_NS[n_oc0[i]];
|
|
np_n_array[1][i] = TBL_3_SF4_GEN_N_DASH_NS[n_oc1[i]];
|
|
}
|
|
}
|
|
for(i=0; i<same_m_number; i++) {
|
|
//printf("np_n_array[0][%d]=%d ,np_n_array[1][%d]=%d \n", i, np_n_array[0][i], i, np_n_array[1][i]);
|
|
}
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (symNo=0; symNo<D_NSYM1SF; symNo++){ // #define D_NSYM1SF 2*7
|
|
slotNo = symNo / D_NSYM1SLT;
|
|
sym = symNo % D_NSYM1SLT;
|
|
|
|
for (k=0; k<D_NSC1RB; k++) { // #define D_NSC1RB 12
|
|
|
|
// remove Base Sequence (c_r^*)*(r_l,m,m,n,k) = BsCshData
|
|
BsCshData[aa][symNo][k][0] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][0] * ul_ref_sigs[u][v][0][k<<1] + (int32_t)SubCarrierDeMapData[aa][symNo][k][1] * ul_ref_sigs[u][v][0][1+(k<<1)])>>15);
|
|
BsCshData[aa][symNo][k][1] = (((int32_t)SubCarrierDeMapData[aa][symNo][k][1] * ul_ref_sigs[u][v][0][k<<1] - (int32_t)SubCarrierDeMapData[aa][symNo][k][0] * ul_ref_sigs[u][v][0][1+(k<<1)])>>15);
|
|
|
|
if(shortened_format == 1) {
|
|
if (symNo < D_NSYM1SLT) {
|
|
np = n3_pucch % D_NPUCCH_SF4; // np = n_oc
|
|
np_n = TBL_3_SF4_GEN_N_DASH_NS[np]; //
|
|
} else {
|
|
np = n3_pucch % D_NPUCCH_SF4; //
|
|
np_n = TBL_3_SF4_GEN_N_DASH_NS[np]; //
|
|
}
|
|
//npucch_sf = D_NPUCCH_SF4;// = 4
|
|
} else {
|
|
if (symNo < D_NSYM1SLT) {
|
|
np = n3_pucch % D_NPUCCH_SF5;
|
|
np_n = TBL_3_SF5_GEN_N_DASH_NS[np];
|
|
} else {
|
|
np = (3 * n3_pucch) % D_NPUCCH_SF5;
|
|
np_n = TBL_3_SF5_GEN_N_DASH_NS[np];
|
|
}
|
|
//npucch_sf = D_NPUCCH_SF5;// = 5
|
|
}
|
|
// cyclic shift e^(-j * beta_n * k)
|
|
calctmp[0] = alphaTBL_re[(((ncs_cell[2*subframe+slotNo][sym] + np_n)%D_NSC1RB)*k)%12];
|
|
calctmp[1] = alphaTBL_im[(((ncs_cell[2*subframe+slotNo][sym] + np_n)%D_NSC1RB)*k)%12];
|
|
|
|
// Channel Estimation 1A, g'(n_cs)_l,m,n
|
|
// CsData_temp = g_l,m,n,k
|
|
// remove cyclic shift BsCshData * e^(-j * beta_n * k)
|
|
CsData_temp[aa][symNo][k][0]=((((int32_t)BsCshData[aa][symNo][k][0] * calctmp[0] + (int32_t)BsCshData[aa][symNo][k][1] * calctmp[1])/ D_NSC1RB)>>15);
|
|
CsData_temp[aa][symNo][k][1]=((((int32_t)BsCshData[aa][symNo][k][1] * calctmp[0] - (int32_t)BsCshData[aa][symNo][k][0] * calctmp[1])/ D_NSC1RB)>>15);
|
|
|
|
// Interference power for Channel Estimation 1A, No use Cyclic Shift g'(n_cs)_l,m,n
|
|
// Calculated by the cyclic shift that is not used S(ncs)_est
|
|
ip_ind = 0;
|
|
for(i=0; i<N_PUCCH_SF1; i++) {
|
|
for(j=0; j<same_m_number; j++) { //np_n_array Loop
|
|
if(shortened_format == 1) {
|
|
if(symNo < D_NSYM1SLT) { // if SF==1 slot0
|
|
if(TBL_3_SF4_GEN_N_DASH_NS[i] == np_n_array[0][j]) {
|
|
break;
|
|
}
|
|
} else { // if SF==1 slot1
|
|
if(TBL_3_SF4_GEN_N_DASH_NS[i] == np_n_array[1][j]) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if(symNo < D_NSYM1SLT) { // if SF==0 slot0
|
|
if(TBL_3_SF5_GEN_N_DASH_NS[i] == np_n_array[0][j]) {
|
|
break;
|
|
}
|
|
} else { // if SF==0 slot1
|
|
if(TBL_3_SF5_GEN_N_DASH_NS[i] == np_n_array[1][j]) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(j == same_m_number - 1) { //when even once it has not been used
|
|
if(shortened_format == 1) {
|
|
calctmp[0] = alphaTBL_re[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF4_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12]; //D_NSC1RB =12
|
|
calctmp[1] = alphaTBL_im[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF4_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12];
|
|
} else {
|
|
calctmp[0] = alphaTBL_re[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF5_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12];
|
|
calctmp[1] = alphaTBL_im[(((ncs_cell[2*subframe+slotNo][sym] + TBL_3_SF5_GEN_N_DASH_NS[i])%D_NSC1RB)*k)%12];
|
|
}
|
|
// IP_CsData_allsfavg = g'(n_cs)_l,m,n
|
|
IP_CsData_allsfavg[aa][symNo][ip_ind][0] += ((((int32_t)BsCshData[aa][symNo][k][0] * calctmp[0] + (int32_t)BsCshData[aa][symNo][k][1] * calctmp[1]))>>15);
|
|
IP_CsData_allsfavg[aa][symNo][ip_ind][1] += ((((int32_t)BsCshData[aa][symNo][k][1] * calctmp[0] - (int32_t)BsCshData[aa][symNo][k][0] * calctmp[1]))>>15);
|
|
if((symNo == 1 || symNo == 5 || symNo == 8 || symNo == 12)) {
|
|
}
|
|
ip_ind++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(symNo > D_NSYM1SLT-1) {
|
|
u=u1;
|
|
v=v1;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (symNo=0; symNo<D_NSYM1SF; symNo++){
|
|
CsData_allavg[aa][symNo][0] = 0;
|
|
CsData_allavg[aa][symNo][1] = 0;
|
|
for (k=0; k<D_NSC1RB; k++) {
|
|
CsData_allavg[aa][symNo][0] += (int16_t)((double)CsData_temp[aa][symNo][k][0]);
|
|
CsData_allavg[aa][symNo][1] += (int16_t)((double)CsData_temp[aa][symNo][k][1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Frequency deviation estimation
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (k=0; k<12; k++) {
|
|
delta_theta_comp[aa][k][0] = 0;
|
|
delta_theta_comp[aa][k][1] = 0;
|
|
|
|
delta_theta_comp[aa][k][0] += (((int32_t)CsData_temp[aa][1][k][0] * CsData_temp[aa][5][k][0] + (int32_t)((CsData_temp[aa][1][k][1])*CsData_temp[aa][5][k][1]))>>8);
|
|
delta_theta_comp[aa][k][1] += (((int32_t)CsData_temp[aa][1][k][0]*CsData_temp[aa][5][k][1] - (int32_t)((CsData_temp[aa][1][k][1])*CsData_temp[aa][5][k][0]) )>>8);
|
|
|
|
delta_theta_comp[aa][k][0] += (((int32_t)CsData_temp[aa][8][k][0] * CsData_temp[aa][12][k][0] + (int32_t)((CsData_temp[aa][8][k][1])*CsData_temp[aa][12][k][1]))>>8);
|
|
delta_theta_comp[aa][k][1] += (((int32_t)CsData_temp[aa][8][k][0]*CsData_temp[aa][12][k][1] - (int32_t)((CsData_temp[aa][8][k][1])*CsData_temp[aa][12][k][0]))>>8);
|
|
|
|
delta_theta[aa][k] = atan2((double)delta_theta_comp[aa][k][1], (double)delta_theta_comp[aa][k][0]) / 4.0;
|
|
}
|
|
}
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (k=0; k<D_NSC1RB; k++) {
|
|
ChestValue[aa][0][k][0] = (int16_t)((CsData_allavg[aa][1][0] + (int16_t)(((double)CsData_allavg[aa][5][0] * cos(delta_theta[aa][k]*4)) + ((double)CsData_allavg[aa][5][1] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ;
|
|
ChestValue[aa][0][k][1] = (int16_t)((CsData_allavg[aa][1][1] + (int16_t)(((double)CsData_allavg[aa][5][1] * cos(delta_theta[aa][k]*4)) - ((double)CsData_allavg[aa][5][0] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ;
|
|
ChestValue[aa][1][k][0] = (int16_t)((CsData_allavg[aa][8][0] + (int16_t)(((double)CsData_allavg[aa][12][0] * cos(delta_theta[aa][k]*4)) + ((double)CsData_allavg[aa][12][1] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ;
|
|
ChestValue[aa][1][k][1] = (int16_t)((CsData_allavg[aa][8][1] + (int16_t)(((double)CsData_allavg[aa][12][1] * cos(delta_theta[aa][k]*4)) - ((double)CsData_allavg[aa][12][0] * sin(delta_theta[aa][k]*4)))) /(2*D_NSC1RB)) ;
|
|
}
|
|
}
|
|
|
|
*Interpw = 0;
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
if(ip_ind == 0) {//ip_ind= The total number of cyclic shift of non-use
|
|
*Interpw = 1;
|
|
break;
|
|
}
|
|
for(i=0; i<ip_ind; i++) {
|
|
IP_allavg[i] = 0;
|
|
|
|
IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][1][i][0] * IP_CsData_allsfavg[aa][1][i][0] + (int32_t)IP_CsData_allsfavg[aa][1][i][1]*IP_CsData_allsfavg[aa][1][i][1])>>8);
|
|
IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][5][i][0] * IP_CsData_allsfavg[aa][5][i][0] + (int32_t)IP_CsData_allsfavg[aa][5][i][1]*IP_CsData_allsfavg[aa][5][i][1])>>8);
|
|
IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][8][i][0] * IP_CsData_allsfavg[aa][8][i][0] + (int32_t)IP_CsData_allsfavg[aa][8][i][1]*IP_CsData_allsfavg[aa][8][i][1])>>8);
|
|
IP_allavg[i] += (((int32_t)IP_CsData_allsfavg[aa][12][i][0] * IP_CsData_allsfavg[aa][12][i][0] + (int32_t)IP_CsData_allsfavg[aa][12][i][1]*IP_CsData_allsfavg[aa][12][i][1])>>8);
|
|
*Interpw += IP_allavg[i]/(2*D_NSLT1SF*frame_parms->nb_antennas_rx*ip_ind*12);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Channel Equalization */
|
|
uint16_t pucchfmt3_Equalization( int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2],
|
|
int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2],
|
|
int16_t ChestValue[NB_ANTENNAS_RX][2][12][2],
|
|
LTE_DL_FRAME_PARMS *frame_parms)
|
|
{
|
|
int16_t aa, sltNo, symNo, k;
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
sltNo = 0;
|
|
for (symNo=0; symNo<D_NSYM1SF; symNo++){
|
|
if(symNo >= D_NSYM1SLT) {
|
|
sltNo = 1;
|
|
}
|
|
for (k=0; k<D_NSC1RB; k++){
|
|
ChdetAfterValue_fmt3[aa][symNo][k][0] = (((int32_t)CshData_fmt3[aa][symNo][k][0] * ChestValue[aa][sltNo][k][0] + (int32_t)CshData_fmt3[aa][symNo][k][1] * ChestValue[aa][sltNo][k][1])>>8);
|
|
ChdetAfterValue_fmt3[aa][symNo][k][1] = (((int32_t)CshData_fmt3[aa][symNo][k][1] * ChestValue[aa][sltNo][k][0] - (int32_t)CshData_fmt3[aa][symNo][k][0] * ChestValue[aa][sltNo][k][1])>>8);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Frequency deviation remove AFC */
|
|
uint16_t pucchfmt3_FrqDevRemove( int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2],
|
|
double delta_theta[NB_ANTENNAS_RX][12],
|
|
int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2],
|
|
LTE_DL_FRAME_PARMS *frame_parms )
|
|
{
|
|
int16_t aa, sltNo, symNo1slt, k, n;
|
|
double calctmp[2];
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for(sltNo = 0; sltNo<D_NSLT1SF; sltNo++)
|
|
{
|
|
n=0;
|
|
for (symNo1slt=0, n=0; symNo1slt<D_NSYM1SLT; symNo1slt++){
|
|
if(!((symNo1slt==1) || (symNo1slt==5))) {
|
|
for (k=0; k<D_NSC1RB; k++) {
|
|
calctmp[0] = cos(delta_theta[aa][k] * (n-1));
|
|
calctmp[1] = sin(delta_theta[aa][k] * (n-1));
|
|
|
|
RemoveFrqDev_fmt3[aa][sltNo][n][k][0] = (int16_t)((double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][0] * calctmp[0]
|
|
+ (double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][1] * calctmp[1]);
|
|
RemoveFrqDev_fmt3[aa][sltNo][n][k][1] = (int16_t)((double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][1] * calctmp[0]
|
|
- (double)ChdetAfterValue_fmt3[aa][(sltNo*D_NSYM1SLT)+symNo1slt][k][0] * calctmp[1]);
|
|
}
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//for opt.Lev.2
|
|
#define MAXROW_TBL_SF5 5
|
|
#define MAXCLM_TBL_SF5 5
|
|
const int16_t TBL_3_SF5[MAXROW_TBL_SF5][MAXCLM_TBL_SF5][2] =
|
|
{{ {32767,0}, {32767,0}, {32767,0}, {32767,0}, {32767,0}},
|
|
{ {32767,0}, {10126, 31163}, {-26509, 19260}, {-26509, -19260}, {10126, -31163}},
|
|
{ {32767,0}, {-26509, 19260}, {10126, -31163}, {10126, 31163}, {-26509, -19260}},
|
|
{ {32767,0}, {-26509, -19260}, {10126, 31163}, {10126, -31163}, {-26509, 19260}},
|
|
{ {32767,0}, {10126, -31163}, {-26509, -19260}, {-26509, 19260}, {10126, 31163}}};
|
|
|
|
#define MAXROW_TBL_SF4_fmt3 4
|
|
#define MAXCLM_TBL_SF4 4
|
|
const int16_t TBL_3_SF4[MAXROW_TBL_SF4_fmt3][MAXCLM_TBL_SF4][2] =
|
|
{{ {32767,0}, {32767,0}, {32767,0}, {32767,0}},
|
|
{ {32767,0}, {-32767,0}, {32767,0}, {-32767,0}},
|
|
{ {32767,0}, {32767,0}, {-32767,0}, {-32767,0}},
|
|
{ {32767,0}, {-32767,0}, {-32767,0}, {32767,0}}};
|
|
|
|
/* orthogonal sequence remove */
|
|
uint16_t pucchfmt3_OrthSeqRemove( int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2],
|
|
int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2],
|
|
uint8_t shortened_format,
|
|
uint16_t n3_pucch,
|
|
LTE_DL_FRAME_PARMS *frame_parms )
|
|
{
|
|
int16_t aa, sltNo, n, k;
|
|
int16_t Npucch_sf;
|
|
int16_t noc;
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (sltNo=0; sltNo<D_NSLT1SF; sltNo++){
|
|
if(shortened_format == 1) {
|
|
if(sltNo == 0) {
|
|
noc = n3_pucch % D_NPUCCH_SF4;
|
|
Npucch_sf = D_NPUCCH_SF5;
|
|
} else {
|
|
noc = n3_pucch % D_NPUCCH_SF4;
|
|
Npucch_sf = D_NPUCCH_SF4;
|
|
}
|
|
} else {
|
|
if(sltNo == 0) {
|
|
noc = n3_pucch % D_NPUCCH_SF5;
|
|
Npucch_sf = D_NPUCCH_SF5;
|
|
} else {
|
|
noc = (3 * n3_pucch) % D_NPUCCH_SF5;
|
|
Npucch_sf = D_NPUCCH_SF5;
|
|
}
|
|
}
|
|
for (n=0; n<Npucch_sf; n++){
|
|
for (k=0; k<D_NSC1RB; k++) {
|
|
if ((sltNo == 1) && (shortened_format == 1)) {
|
|
Fmt3xDataRmvOrth[aa][sltNo][n][k][0] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF4[noc][n][0] + (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF4[noc][n][1])>>15);
|
|
Fmt3xDataRmvOrth[aa][sltNo][n][k][1] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF4[noc][n][0] - (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF4[noc][n][1])>>15);
|
|
} else {
|
|
Fmt3xDataRmvOrth[aa][sltNo][n][k][0] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF5[noc][n][0] + (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF5[noc][n][1])>>15);
|
|
Fmt3xDataRmvOrth[aa][sltNo][n][k][1] = (((int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][1] * TBL_3_SF5[noc][n][0] - (int32_t)RemoveFrqDev_fmt3[aa][sltNo][n][k][0] * TBL_3_SF5[noc][n][1])>>15);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* averaging antenna */
|
|
uint16_t pucchfmt3_AvgAnt( int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2],
|
|
int16_t Fmt3xDataAvgAnt[2][5][12][2],
|
|
uint8_t shortened_format,
|
|
LTE_DL_FRAME_PARMS *frame_parms )
|
|
{
|
|
int16_t aa, sltNo, n, k;
|
|
int16_t Npucch_sf;
|
|
|
|
for (sltNo=0; sltNo<D_NSLT1SF; sltNo++){
|
|
if((sltNo == 1) && (shortened_format == 1)) {
|
|
Npucch_sf = D_NPUCCH_SF4;
|
|
} else {
|
|
Npucch_sf = D_NPUCCH_SF5;
|
|
}
|
|
for (n=0; n<Npucch_sf; n++){
|
|
for (k=0; k<D_NSC1RB; k++) {
|
|
Fmt3xDataAvgAnt[sltNo][n][k][0] = 0;
|
|
Fmt3xDataAvgAnt[sltNo][n][k][1] = 0;
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
Fmt3xDataAvgAnt[sltNo][n][k][0] += Fmt3xDataRmvOrth[aa][sltNo][n][k][0] / frame_parms->nb_antennas_rx;
|
|
Fmt3xDataAvgAnt[sltNo][n][k][1] += Fmt3xDataRmvOrth[aa][sltNo][n][k][1] / frame_parms->nb_antennas_rx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* averaging symbol */
|
|
uint16_t pucchfmt3_AvgSym( int16_t Fmt3xDataAvgAnt[2][5][12][2],
|
|
int16_t Fmt3xDataAvgSym[2][12][2],
|
|
uint8_t shortened_format )
|
|
{
|
|
int16_t sltNo, n, k;
|
|
int16_t Npucch_sf;
|
|
|
|
for (sltNo=0; sltNo<D_NSLT1SF; sltNo++){
|
|
if((sltNo == 1) && (shortened_format == 1)) {
|
|
Npucch_sf = D_NPUCCH_SF4;
|
|
} else {
|
|
Npucch_sf = D_NPUCCH_SF5;
|
|
}
|
|
for (k=0; k<D_NSC1RB; k++) {
|
|
Fmt3xDataAvgSym[sltNo][k][0] = 0;
|
|
Fmt3xDataAvgSym[sltNo][k][1] = 0;
|
|
for (n=0; n<Npucch_sf; n++){
|
|
Fmt3xDataAvgSym[sltNo][k][0] += Fmt3xDataAvgAnt[sltNo][n][k][0] / Npucch_sf;
|
|
Fmt3xDataAvgSym[sltNo][k][1] += Fmt3xDataAvgAnt[sltNo][n][k][1] / Npucch_sf;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* iDFT */
|
|
void pucchfmt3_IDft2( int16_t *x, int16_t *y )
|
|
{
|
|
int16_t i, k;
|
|
int16_t tmp[2];
|
|
int16_t calctmp[D_NSC1RB*2]={0};
|
|
|
|
for(k=0; k<D_NSC1RB; k++) {
|
|
for (i=0; i<D_NSC1RB; i++) {
|
|
tmp[0] = alphaTBL_re[((i*k)%12)];
|
|
tmp[1] = alphaTBL_im[((i*k)%12)];
|
|
|
|
calctmp[2*k] += (((int32_t)x[2*i] * tmp[0] - (int32_t)x[2*i+1] * tmp[1])>>15);
|
|
calctmp[2*k+1] += (((int32_t)x[2*i+1] * tmp[0] + (int32_t)x[2*i] * tmp[1])>>15);
|
|
}
|
|
y[2*k] = (int16_t)( (double) calctmp[2*k] / sqrt(D_NSC1RB));
|
|
y[2*k+1] = (int16_t)((double) calctmp[2*k+1] / sqrt(D_NSC1RB));
|
|
}
|
|
}
|
|
|
|
/* descramble */
|
|
uint16_t pucchfmt3_Descramble( int16_t IFFTOutData_Fmt3[2][12][2],
|
|
int16_t b[48],
|
|
uint8_t subframe,
|
|
uint32_t Nid_cell,
|
|
uint32_t rnti
|
|
)
|
|
{
|
|
int16_t m, k, c,i,j;
|
|
uint32_t cinit = 0;
|
|
uint32_t x1;
|
|
uint32_t s,s0,s1;
|
|
cinit = (subframe + 1) * ((2 * Nid_cell + 1)<<16) + rnti;
|
|
s0 = lte_gold_generic(&x1,&cinit,1);
|
|
s1 = lte_gold_generic(&x1,&cinit,0);
|
|
i=0;
|
|
for (m=0; m<D_NSLT1SF; m++){
|
|
for(k=0; k<D_NSC1RB; k++) {
|
|
s = (i<32)? s0:s1;
|
|
j = (i<32)? i:(i-32);
|
|
c=((s>>j)&1);
|
|
b[i] = (IFFTOutData_Fmt3[m][k][0] * (1 - 2*c));
|
|
i++;
|
|
|
|
s = (i<32)? s0:s1;
|
|
j = (i<32)? i:(i-32);
|
|
c=((s>>j)&1);
|
|
b[i] = (IFFTOutData_Fmt3[m][k][1] * (1 - 2*c));
|
|
i++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int16_t pucchfmt3_Decode( int16_t b[48],
|
|
uint8_t subframe,
|
|
int16_t DTXthreshold,
|
|
int16_t Interpw,
|
|
uint8_t do_sr)
|
|
{
|
|
int16_t c, i;
|
|
int32_t Rho_tmp;
|
|
int16_t c_max;
|
|
int32_t Rho_max;
|
|
int16_t bit_pattern;
|
|
|
|
/* Is payload 6bit or 7bit? */
|
|
if( do_sr == 1 ) {
|
|
bit_pattern = 128;
|
|
} else {
|
|
bit_pattern = 64;
|
|
}
|
|
|
|
c=0;
|
|
Rho_tmp = 0;
|
|
for (i=0;i<48;i++) {
|
|
Rho_tmp += b[i] * (1-2*chcod_tbl[c][i]);
|
|
}
|
|
c_max = c;
|
|
Rho_max = Rho_tmp;
|
|
|
|
for(c=1; c<bit_pattern; c++) {
|
|
Rho_tmp = 0;
|
|
for (i=0;i<48;i++) {
|
|
Rho_tmp += b[i] * (1-2*chcod_tbl[c][i]);
|
|
}
|
|
if (Rho_tmp > Rho_max) {
|
|
c_max = c;
|
|
Rho_max = Rho_tmp;
|
|
}
|
|
}
|
|
if(Interpw<1){
|
|
Interpw=1;
|
|
}
|
|
if((Rho_max/Interpw) > DTXthreshold) {
|
|
// ***Log
|
|
return c_max;
|
|
} else {
|
|
// ***Log
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* PUCCH format3 << */
|
|
|
|
uint32_t rx_pucch(PHY_VARS_eNB *eNB,
|
|
PUCCH_FMT_t fmt,
|
|
uint8_t UE_id,
|
|
uint16_t n1_pucch,
|
|
uint16_t n2_pucch,
|
|
uint8_t shortened_format,
|
|
uint8_t *payload,
|
|
int frame,
|
|
uint8_t subframe,
|
|
uint8_t pucch1_thres)
|
|
{
|
|
|
|
|
|
static int first_call=1;
|
|
LTE_eNB_COMMON *common_vars = &eNB->common_vars;
|
|
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
|
|
// PUCCH_CONFIG_DEDICATED *pucch_config_dedicated = &eNB->pucch_config_dedicated[UE_id];
|
|
int8_t sigma2_dB = eNB->measurements[0].n0_subband_power_tot_dB[0]-10;
|
|
uint32_t *Po_PUCCH = &(eNB->UE_stats[UE_id].Po_PUCCH);
|
|
int32_t *Po_PUCCH_dBm = &(eNB->UE_stats[UE_id].Po_PUCCH_dBm);
|
|
uint32_t *Po_PUCCH1_below = &(eNB->UE_stats[UE_id].Po_PUCCH1_below);
|
|
uint32_t *Po_PUCCH1_above = &(eNB->UE_stats[UE_id].Po_PUCCH1_above);
|
|
int32_t *Po_PUCCH_update = &(eNB->UE_stats[UE_id].Po_PUCCH_update);
|
|
uint32_t u,v,n,aa;
|
|
uint32_t z[12*14];
|
|
int16_t *zptr;
|
|
int16_t rxcomp[NB_ANTENNAS_RX][2*12*14];
|
|
uint8_t ns,N_UL_symb,nsymb,n_oc,n_oc0,n_oc1;
|
|
uint8_t c = (frame_parms->Ncp==0) ? 3 : 2;
|
|
uint16_t nprime,nprime0,nprime1;
|
|
uint16_t i,j,re_offset,thres,h,off;
|
|
uint8_t Nprime_div_deltaPUCCH_Shift,Nprime,d;
|
|
uint8_t m,l,refs,phase,re,l2,phase_max=0;
|
|
uint8_t n_cs,S,alpha_ind,rem;
|
|
int16_t tmp_re,tmp_im,W_re=0,W_im=0;
|
|
int16_t *rxptr;
|
|
uint32_t symbol_offset;
|
|
int16_t stat_ref_re,stat_ref_im,*cfo,chest_re,chest_im;
|
|
int32_t stat_re=0,stat_im=0;
|
|
uint32_t stat,stat_max=0;
|
|
|
|
uint8_t deltaPUCCH_Shift = frame_parms->pucch_config_common.deltaPUCCH_Shift;
|
|
uint8_t NRB2 = frame_parms->pucch_config_common.nRB_CQI;
|
|
uint8_t Ncs1_div_deltaPUCCH_Shift = frame_parms->pucch_config_common.nCS_AN;
|
|
|
|
uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
|
|
uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
|
|
uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
|
|
uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
|
|
int chL;
|
|
|
|
/* PUCCH format3 >> */
|
|
uint16_t Ret = 0;
|
|
int16_t SubCarrierDeMapData[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex]
|
|
int16_t CshData_fmt3[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex]
|
|
double delta_theta[NB_ANTENNAS_RX][12]; //[Antenna][Subcarrier][Complex]
|
|
int16_t ChestValue[NB_ANTENNAS_RX][2][12][2]; //[Antenna][Slot][Subcarrier][Complex]
|
|
int16_t ChdetAfterValue_fmt3[NB_ANTENNAS_RX][14][12][2]; //[Antenna][Symbol][Subcarrier][Complex]
|
|
int16_t RemoveFrqDev_fmt3[NB_ANTENNAS_RX][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex]
|
|
int16_t Fmt3xDataRmvOrth[NB_ANTENNAS_RX][2][5][12][2]; //[Antenna][Slot][PUCCH_Symbol][Subcarrier][Complex]
|
|
int16_t Fmt3xDataAvgAnt[2][5][12][2]; //[Slot][PUCCH_Symbol][Subcarrier][Complex]
|
|
int16_t Fmt3xDataAvgSym[2][12][2]; //[Slot][Subcarrier][Complex]
|
|
int16_t IFFTOutData_Fmt3[2][12][2]; //[Slot][Subcarrier][Complex]
|
|
int16_t b[48]; //[bit]
|
|
//int16_t IP_CsData_allavg[NB_ANTENNAS_RX][12][4][2]; //[Antenna][Symbol][Nouse Cyclic Shift][Complex]
|
|
int16_t payload_entity = -1;
|
|
int16_t Interpw;
|
|
int16_t payload_max;
|
|
|
|
// TODO
|
|
// When using PUCCH format3, it must be an argument of rx_pucch function
|
|
uint16_t n3_pucch = 20;
|
|
uint16_t n3_pucch_array[NUMBER_OF_UE_MAX]={1};
|
|
n3_pucch_array[0]=n3_pucch;
|
|
uint8_t do_sr = 1;
|
|
uint16_t crnti=0x1234;
|
|
int16_t DTXthreshold = 10;
|
|
/* PUCCH format3 << */
|
|
|
|
if (first_call == 1) {
|
|
for (i=0;i<10;i++) {
|
|
for (j=0;j<NUMBER_OF_UE_MAX;j++) {
|
|
eNB->pucch1_stats_cnt[j][i]=0;
|
|
eNB->pucch1ab_stats_cnt[j][i]=0;
|
|
}
|
|
}
|
|
first_call=0;
|
|
}
|
|
/*
|
|
switch (frame_parms->N_RB_UL) {
|
|
|
|
case 6:
|
|
sigma2_dB -= 8;
|
|
break;
|
|
case 25:
|
|
sigma2_dB -= 14;
|
|
break;
|
|
case 50:
|
|
sigma2_dB -= 17;
|
|
break;
|
|
case 100:
|
|
sigma2_dB -= 20;
|
|
break;
|
|
default:
|
|
sigma2_dB -= 14;
|
|
}
|
|
*/
|
|
|
|
if(fmt!=pucch_format3) { /* PUCCH format3 */
|
|
|
|
// TODO
|
|
// "SR+ACK/NACK" length is only 7 bits.
|
|
// This restriction will be lifted in the future.
|
|
// "CQI/PMI/RI+ACK/NACK" will be supported in the future.
|
|
|
|
if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) {
|
|
LOG_E(PHY,"[eNB] rx_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift);
|
|
return(-1);
|
|
}
|
|
|
|
if (Ncs1_div_deltaPUCCH_Shift > 7) {
|
|
LOG_E(PHY,"[eNB] rx_pucch: Illegal Ncs1_div_deltaPUCCH_Shift %d (should be 0...7)\n",Ncs1_div_deltaPUCCH_Shift);
|
|
return(-1);
|
|
}
|
|
|
|
zptr = (int16_t *)z;
|
|
thres = (c*Ncs1_div_deltaPUCCH_Shift);
|
|
Nprime_div_deltaPUCCH_Shift = (n1_pucch < thres) ? Ncs1_div_deltaPUCCH_Shift : (12/deltaPUCCH_Shift);
|
|
Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift;
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch);
|
|
#endif
|
|
|
|
N_UL_symb = (frame_parms->Ncp==NORMAL) ? 7 : 6;
|
|
|
|
if (n1_pucch < thres)
|
|
nprime0=n1_pucch;
|
|
else
|
|
nprime0 = (n1_pucch - thres)%(12*c/deltaPUCCH_Shift);
|
|
|
|
if (n1_pucch >= thres)
|
|
nprime1= ((c*(nprime0+1))%((12*c/deltaPUCCH_Shift)+1))-1;
|
|
else {
|
|
d = (frame_parms->Ncp==0) ? 2 : 0;
|
|
h= (nprime0+d)%(c*Nprime_div_deltaPUCCH_Shift);
|
|
nprime1 = (h/c) + (h%c)*Nprime_div_deltaPUCCH_Shift;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("PUCCH: nprime0 %d nprime1 %d\n",nprime0,nprime1);
|
|
#endif
|
|
|
|
n_oc0 = nprime0/Nprime_div_deltaPUCCH_Shift;
|
|
|
|
if (frame_parms->Ncp==1)
|
|
n_oc0<<=1;
|
|
|
|
n_oc1 = nprime1/Nprime_div_deltaPUCCH_Shift;
|
|
|
|
if (frame_parms->Ncp==1) // extended CP
|
|
n_oc1<<=1;
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH: noc0 %d noc11 %d\n",n_oc0,n_oc1);
|
|
#endif
|
|
|
|
nprime=nprime0;
|
|
n_oc =n_oc0;
|
|
|
|
// loop over 2 slots
|
|
for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
|
|
|
|
if ((nprime&1) == 0)
|
|
S=0; // 1
|
|
else
|
|
S=1; // j
|
|
/*
|
|
if (fmt==pucch_format1)
|
|
LOG_I(PHY,"[eNB] subframe %d => PUCCH1: u%d %d, v%d %d : ", subframe,ns&1,u,ns&1,v);
|
|
else
|
|
LOG_I(PHY,"[eNB] subframe %d => PUCCH1a/b: u%d %d, v%d %d : ", subframe,ns&1,u,ns&1,v);
|
|
*/
|
|
|
|
//loop over symbols in slot
|
|
for (l=0; l<N_UL_symb; l++) {
|
|
// Compute n_cs (36.211 p. 18)
|
|
n_cs = eNB->ncs_cell[ns][l];
|
|
|
|
if (frame_parms->Ncp==0) { // normal CP
|
|
n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc%deltaPUCCH_Shift))%Nprime)%12;
|
|
} else {
|
|
n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc>>1))%Nprime)%12;
|
|
}
|
|
|
|
|
|
|
|
refs=0;
|
|
|
|
// Comput W_noc(m) (36.211 p. 19)
|
|
if ((ns==(1+(subframe<<1))) && (shortened_format==1)) { // second slot and shortened format
|
|
|
|
if (l<2) { // data
|
|
W_re=W3_re[n_oc][l];
|
|
W_im=W3_im[n_oc][l];
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==0)) { // reference and normal CP
|
|
W_re=W3_re[n_oc][l-2];
|
|
W_im=W3_im[n_oc][l-2];
|
|
refs=1;
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==1)) { // reference and extended CP
|
|
W_re=W4[n_oc][l-2];
|
|
W_im=0;
|
|
refs=1;
|
|
} else if ((l>=N_UL_symb-2)) { // data
|
|
W_re=W3_re[n_oc][l-N_UL_symb+4];
|
|
W_im=W3_im[n_oc][l-N_UL_symb+4];
|
|
}
|
|
} else {
|
|
if (l<2) { // data
|
|
W_re=W4[n_oc][l];
|
|
W_im=0;
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==NORMAL)) { // reference and normal CP
|
|
W_re=W3_re[n_oc][l-2];
|
|
W_im=W3_im[n_oc][l-2];
|
|
refs=1;
|
|
} else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==EXTENDED)) { // reference and extended CP
|
|
W_re=W4[n_oc][l-2];
|
|
W_im=0;
|
|
refs=1;
|
|
} else if ((l>=N_UL_symb-2)) { // data
|
|
W_re=W4[n_oc][l-N_UL_symb+4];
|
|
W_im=0;
|
|
}
|
|
}
|
|
|
|
// multiply W by S(ns) (36.211 p.17). only for data, reference symbols do not have this factor
|
|
if ((S==1)&&(refs==0)) {
|
|
tmp_re = W_re;
|
|
W_re = -W_im;
|
|
W_im = tmp_re;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs);
|
|
#endif
|
|
alpha_ind=0;
|
|
// compute output sequence
|
|
|
|
for (n=0; n<12; n++) {
|
|
|
|
// this is r_uv^alpha(n)
|
|
tmp_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
|
|
tmp_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
|
|
|
|
// this is S(ns)*w_noc(m)*r_uv^alpha(n)
|
|
zptr[n<<1] = (tmp_re*W_re - tmp_im*W_im)>>15;
|
|
zptr[1+(n<<1)] = -(tmp_re*W_im + tmp_im*W_re)>>15;
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,zptr[n<<1],zptr[(n<<1)+1],
|
|
alpha_ind,alpha_re[alpha_ind],alpha_im[alpha_ind]);
|
|
#endif
|
|
|
|
alpha_ind = (alpha_ind + n_cs)%12;
|
|
} // n
|
|
|
|
zptr+=24;
|
|
} // l
|
|
|
|
nprime=nprime1;
|
|
n_oc =n_oc1;
|
|
} // ns
|
|
|
|
rem = ((((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)&7)>0) ? 1 : 0;
|
|
|
|
m = (n1_pucch < thres) ? NRB2 : (((n1_pucch-thres)/(12*c/deltaPUCCH_Shift))+NRB2+((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)+rem);
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH: m %d\n",m);
|
|
#endif
|
|
nsymb = N_UL_symb<<1;
|
|
|
|
zptr = (int16_t*)z;
|
|
|
|
// Do detection
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
|
|
//for (j=0,l=0;l<(nsymb-1);l++) {
|
|
for (j=0,l=0; l<nsymb; l++) {
|
|
if ((l<(nsymb>>1)) && ((m&1) == 0))
|
|
re_offset = (m*6) + frame_parms->first_carrier_offset;
|
|
else if ((l<(nsymb>>1)) && ((m&1) == 1))
|
|
re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else if ((m&1) == 0)
|
|
re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
|
|
else
|
|
re_offset = ((m-1)*6) + frame_parms->first_carrier_offset;
|
|
|
|
if (re_offset > frame_parms->ofdm_symbol_size)
|
|
re_offset -= (frame_parms->ofdm_symbol_size);
|
|
|
|
symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*l;
|
|
rxptr = (int16_t *)&common_vars->rxdataF[0][aa][symbol_offset];
|
|
|
|
for (i=0; i<12; i++,j+=2,re_offset++) {
|
|
if (re_offset==frame_parms->ofdm_symbol_size)
|
|
re_offset = 0;
|
|
|
|
rxcomp[aa][j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[j])>>15) - ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[1+j])>>15);
|
|
rxcomp[aa][1+j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[1+j])>>15) + ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[j])>>15);
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d,%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,i,re_offset,m,j,
|
|
rxptr[re_offset<<1],rxptr[1+(re_offset<<1)],
|
|
zptr[j],zptr[1+j],
|
|
rxcomp[aa][j],rxcomp[aa][1+j]);
|
|
#endif
|
|
} //re
|
|
} // symbol
|
|
} // antenna
|
|
|
|
|
|
// PUCCH Format 1
|
|
// Do cfo correction and MRC across symbols
|
|
|
|
if (fmt == pucch_format1) {
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("Doing PUCCH detection for format 1\n");
|
|
#endif
|
|
|
|
stat_max = 0;
|
|
|
|
|
|
for (phase=0; phase<7; phase++) {
|
|
stat=0;
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (re=0; re<12; re++) {
|
|
stat_re=0;
|
|
stat_im=0;
|
|
off=re<<1;
|
|
cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase];
|
|
|
|
for (l=0; l<(nsymb>>1); l++) {
|
|
stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/nsymb;
|
|
stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/nsymb;
|
|
off+=2;
|
|
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l<<1],cfo[1+(l<<1)],
|
|
stat_re,stat_im,stat);
|
|
#endif
|
|
}
|
|
|
|
for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) {
|
|
stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb;
|
|
stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb;
|
|
off+=2;
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l2<<1],cfo[1+(l2<<1)],
|
|
stat_re,stat_im,stat);
|
|
#endif
|
|
|
|
|
|
}
|
|
stat += ((stat_re*stat_re) + (stat_im*stat_im));
|
|
|
|
} //re
|
|
} // aa
|
|
|
|
|
|
if (stat>stat_max) {
|
|
stat_max = stat;
|
|
phase_max = phase;
|
|
}
|
|
|
|
} //phase
|
|
|
|
// stat_max *= nsymb; // normalize to energy per symbol
|
|
// stat_max /= (frame_parms->N_RB_UL*12); //
|
|
stat_max /= (nsymb*12);
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max);
|
|
#endif
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max);
|
|
#endif
|
|
|
|
eNB->pucch1_stats[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max;
|
|
eNB->pucch1_stats_thres[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres;
|
|
eNB->pucch1_stats_cnt[UE_id][subframe] = (eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023;
|
|
|
|
T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(eNB->Mod_id), T_INT(UE_id), T_INT(frame), T_INT(subframe),
|
|
T_INT(stat_max), T_INT(sigma2_dB+pucch1_thres));
|
|
|
|
/*
|
|
if (eNB->pucch1_stats_cnt[UE_id][subframe] == 0) {
|
|
write_output("pucch_debug.m","pucch_energy",
|
|
&eNB->pucch1_stats[UE_id][(subframe<<10)],
|
|
1024,1,2);
|
|
AssertFatal(0,"Exiting for PUCCH 1 debug\n");
|
|
|
|
}
|
|
*/
|
|
|
|
// This is a moving average of the PUCCH1 statistics conditioned on being above or below the threshold
|
|
if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) {
|
|
*payload = 1;
|
|
*Po_PUCCH1_above = ((*Po_PUCCH1_above<<9) + (stat_max<<9)+1024)>>10;
|
|
//LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max);
|
|
}
|
|
else {
|
|
*payload = 0;
|
|
*Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10;
|
|
}
|
|
//printf("[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above));
|
|
*Po_PUCCH_update = 1;
|
|
if (UE_id==0) {
|
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,dB_fixed(stat_max));
|
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_THRES,sigma2_dB+pucch1_thres);
|
|
}
|
|
} else if ((fmt == pucch_format1a)||(fmt == pucch_format1b)) {
|
|
stat_max = 0;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n");
|
|
#endif
|
|
|
|
for (phase=0; phase<7; phase++) {
|
|
stat=0;
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (re=0; re<12; re++) {
|
|
stat_re=0;
|
|
stat_im=0;
|
|
stat_ref_re=0;
|
|
stat_ref_im=0;
|
|
off=re<<1;
|
|
cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase];
|
|
|
|
|
|
for (l=0; l<(nsymb>>1); l++) {
|
|
if ((l<2)||(l>(nsymb>>1) - 3)) { //data symbols
|
|
stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
} else { //reference symbols
|
|
stat_ref_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
stat_ref_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
}
|
|
|
|
off+=2;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l<<1],cfo[1+(l<<1)],
|
|
stat_re,stat_im);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) {
|
|
if ((l2<2) || ((l2>(nsymb>>1) - 3)) ) { // data symbols
|
|
stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15);
|
|
stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15);
|
|
} else { //reference_symbols
|
|
stat_ref_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
stat_ref_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
}
|
|
|
|
off+=2;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l2,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l2<<1],cfo[1+(l2<<1)],
|
|
stat_re,stat_im);
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat);
|
|
#endif
|
|
|
|
stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) +
|
|
((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im)))/nsymb);
|
|
|
|
|
|
} //re
|
|
} // aa
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
LOG_I(PHY,"Format 1A: phase %d : stat %d\n",phase,stat);
|
|
#endif
|
|
if (stat>stat_max) {
|
|
stat_max = stat;
|
|
phase_max = phase;
|
|
}
|
|
} //phase
|
|
|
|
stat_max/=(12); //normalize to energy per symbol and RE
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH fmt1a/b: stat_max : %d, phase_max : %d\n",stat_max,phase_max);
|
|
#endif
|
|
|
|
stat_re=0;
|
|
stat_im=0;
|
|
// printf("PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH);
|
|
*Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1));
|
|
*Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - eNB->rx_total_gain_dB;
|
|
*Po_PUCCH_update = 1;
|
|
/*
|
|
printf("PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n",
|
|
dB_fixed(stat_max),
|
|
pucch1_thres+sigma2_dB,
|
|
pucch1_thres,
|
|
sigma2_dB,
|
|
dB_fixed(*Po_PUCCH));
|
|
*/
|
|
// Do detection now
|
|
if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) {//
|
|
|
|
|
|
*Po_PUCCH = ((*Po_PUCCH*1023) + stat_max)>>10;
|
|
|
|
chL = (nsymb>>1)-4;
|
|
|
|
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
|
|
for (re=0; re<12; re++) {
|
|
chest_re=0;
|
|
chest_im=0;
|
|
cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase_max] : &cfo_pucch_ep[12*phase_max];
|
|
|
|
// channel estimate for first slot
|
|
for (l=2; l<(nsymb>>1)-2; l++) {
|
|
off=(re<<1) + (24*l);
|
|
chest_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/chL;
|
|
chest_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/chL;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d l %d re %d chest1 => (%d,%d)\n",subframe,l,re,
|
|
chest_re,chest_im);
|
|
#endif
|
|
|
|
for (l=0; l<2; l++) {
|
|
off=(re<<1) + (24*l);
|
|
tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4;
|
|
stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4;
|
|
off+=2;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l<<1],cfo[1+(l<<1)],
|
|
stat_re,stat_im);
|
|
#endif
|
|
}
|
|
|
|
for (l=(nsymb>>1)-2; l<(nsymb>>1); l++) {
|
|
off=(re<<1) + (24*l);
|
|
tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4;
|
|
stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4;
|
|
off+=2;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l<<1],cfo[1+(l<<1)],
|
|
stat_re,stat_im);
|
|
#endif
|
|
}
|
|
|
|
chest_re=0;
|
|
chest_im=0;
|
|
|
|
// channel estimate for second slot
|
|
for (l=2; l<(nsymb>>1)-2; l++) {
|
|
off=(re<<1) + (24*l) + (nsymb>>1)*24;
|
|
chest_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/chL;
|
|
chest_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/chL;
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[eNB] PUCCH subframe %d l %d re %d chest2 => (%d,%d)\n",subframe,l,re,
|
|
chest_re,chest_im);
|
|
#endif
|
|
|
|
for (l=0; l<2; l++) {
|
|
off=(re<<1) + (24*l) + (nsymb>>1)*24;
|
|
tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4;
|
|
stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4;
|
|
off+=2;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l<<1],cfo[1+(l<<1)],
|
|
stat_re,stat_im);
|
|
#endif
|
|
}
|
|
|
|
for (l=(nsymb>>1)-2; l<(nsymb>>1)-1; l++) {
|
|
off=(re<<1) + (24*l) + (nsymb>>1)*24;
|
|
tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
|
|
tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
|
|
stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4;
|
|
stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4;
|
|
off+=2;
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
|
|
rxcomp[aa][off],rxcomp[aa][1+off],
|
|
cfo[l<<1],cfo[1+(l<<1)],
|
|
stat_re,stat_im);
|
|
#endif
|
|
}
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
printf("aa%d re %d : stat %d,%d\n",aa,re,stat_re,stat_im);
|
|
#endif
|
|
|
|
} //re
|
|
} // aa
|
|
|
|
#ifdef DEBUG_PUCCH_RX
|
|
LOG_I(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im,
|
|
(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe]));
|
|
#endif
|
|
|
|
eNB->pucch1ab_stats[UE_id][(subframe<<11) + 2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_re);
|
|
eNB->pucch1ab_stats[UE_id][(subframe<<11) + 1+2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_im);
|
|
eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023;
|
|
|
|
/* frame not available here - set to -1 for the moment */
|
|
T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(eNB->Mod_id), T_INT(UE_id), T_INT(-1), T_INT(subframe), T_INT(stat_re), T_INT(stat_im));
|
|
|
|
|
|
*payload = (stat_re<0) ? 1 : 0;
|
|
|
|
if (fmt==pucch_format1b)
|
|
*(1+payload) = (stat_im<0) ? 1 : 0;
|
|
} else { // insufficient energy on PUCCH so NAK
|
|
*payload = 0;
|
|
((int16_t*)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re);
|
|
((int16_t*)&eNB->pucch1ab_stats[UE_id][(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im);
|
|
eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023;
|
|
|
|
if (fmt==pucch_format1b)
|
|
*(1+payload) = 0;
|
|
}
|
|
} else {
|
|
LOG_E(PHY,"[eNB] PUCCH fmt2/2a/2b not supported\n");
|
|
}
|
|
|
|
/* PUCCH format3 >> */
|
|
} else {
|
|
/* SubCarrier Demap */
|
|
Ret = pucchfmt3_subCarrierDeMapping( eNB, SubCarrierDeMapData, n3_pucch );
|
|
if(Ret != 0) {
|
|
//***log pucchfmt3_subCarrierDeMapping Error!
|
|
return(-1);
|
|
}
|
|
|
|
/* cyclic shift hopping remove */
|
|
Ret = pucchfmt3_Baseseq_csh_remove( SubCarrierDeMapData, CshData_fmt3, frame_parms, subframe, eNB->ncs_cell );
|
|
if(Ret != 0) {
|
|
//***log pucchfmt3_Baseseq_csh_remove Error!
|
|
return(-1);
|
|
}
|
|
|
|
/* Channel Estimation */
|
|
Ret = pucchfmt3_ChannelEstimation( SubCarrierDeMapData, delta_theta, ChestValue, &Interpw, subframe, shortened_format, frame_parms, n3_pucch, n3_pucch_array, eNB->ncs_cell );
|
|
if(Ret != 0) {
|
|
//***log pucchfmt3_ChannelEstimation Error!
|
|
return(-1);
|
|
}
|
|
|
|
/* Channel Equalization */
|
|
Ret = pucchfmt3_Equalization( CshData_fmt3, ChdetAfterValue_fmt3, ChestValue, frame_parms );
|
|
if(Ret != 0) {
|
|
//***log pucchfmt3_Equalization Error!
|
|
return(-1);
|
|
}
|
|
|
|
/* Frequency deviation remove AFC */
|
|
Ret = pucchfmt3_FrqDevRemove( ChdetAfterValue_fmt3, delta_theta, RemoveFrqDev_fmt3, frame_parms );
|
|
if(Ret != 0) {
|
|
//***log pucchfmt3_FrqDevRemove Error!
|
|
return(-1);
|
|
}
|
|
|
|
/* orthogonal sequence remove */
|
|
Ret = pucchfmt3_OrthSeqRemove( RemoveFrqDev_fmt3, Fmt3xDataRmvOrth, shortened_format, n3_pucch, frame_parms );
|
|
if(Ret != 0) {
|
|
//***log pucchfmt3_OrthSeqRemove Error!
|
|
return(-1);
|
|
}
|
|
|
|
/* averaging antenna */
|
|
pucchfmt3_AvgAnt( Fmt3xDataRmvOrth, Fmt3xDataAvgAnt, shortened_format, frame_parms );
|
|
|
|
/* averaging symbol */
|
|
pucchfmt3_AvgSym( Fmt3xDataAvgAnt, Fmt3xDataAvgSym, shortened_format );
|
|
|
|
/* IDFT */
|
|
pucchfmt3_IDft2( (int16_t*)Fmt3xDataAvgSym[0], (int16_t*)IFFTOutData_Fmt3[0] );
|
|
pucchfmt3_IDft2( (int16_t*)Fmt3xDataAvgSym[1], (int16_t*)IFFTOutData_Fmt3[1] );
|
|
|
|
/* descramble */
|
|
pucchfmt3_Descramble(IFFTOutData_Fmt3, b, subframe, frame_parms->Nid_cell, crnti);
|
|
|
|
/* Is payload 6bit or 7bit? */
|
|
if( do_sr == 1 ) {
|
|
payload_max = 7;
|
|
} else {
|
|
payload_max = 6;
|
|
}
|
|
|
|
/* decode */
|
|
payload_entity = pucchfmt3_Decode( b, subframe, DTXthreshold, Interpw, do_sr );
|
|
if (payload_entity == -1) {
|
|
//***log pucchfmt3_Decode Error!
|
|
return(-1);
|
|
}
|
|
|
|
for(i=0; i<payload_max; i++) {
|
|
*(payload+i) = (uint8_t)((payload_entity>>i) & 0x01);
|
|
}
|
|
}
|
|
/* PUCCH format3 << */
|
|
|
|
return((int32_t)stat_max);
|
|
|
|
}
|
|
|
|
|
|
int32_t rx_pucch_emul(PHY_VARS_eNB *eNB,
|
|
eNB_rxtx_proc_t *proc,
|
|
uint8_t UE_index,
|
|
PUCCH_FMT_t fmt,
|
|
uint8_t n1_pucch_sel,
|
|
uint8_t *payload)
|
|
|
|
{
|
|
uint8_t UE_id;
|
|
uint16_t rnti;
|
|
int subframe = proc->subframe_rx;
|
|
uint8_t CC_id = eNB->CC_id;
|
|
|
|
rnti = eNB->ulsch[UE_index]->rnti;
|
|
|
|
for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
|
|
if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[PHY_vars_UE_g[UE_id][CC_id]->current_thread_id[subframe]][0]->crnti)
|
|
break;
|
|
}
|
|
|
|
if (UE_id==NB_UE_INST) {
|
|
LOG_W(PHY,"rx_pucch_emul: Didn't find UE with rnti %x\n",rnti);
|
|
return(-1);
|
|
}
|
|
|
|
if (fmt == pucch_format1) {
|
|
payload[0] = PHY_vars_UE_g[UE_id][CC_id]->sr[subframe];
|
|
} else if (fmt == pucch_format1a) {
|
|
payload[0] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[0];
|
|
} else if (fmt == pucch_format1b) {
|
|
payload[0] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[0];
|
|
payload[1] = PHY_vars_UE_g[UE_id][CC_id]->pucch_payload[1];
|
|
} else
|
|
LOG_E(PHY,"[eNB] Frame %d: Can't handle formats 2/2a/2b\n",proc->frame_rx);
|
|
|
|
if (PHY_vars_UE_g[UE_id][CC_id]->pucch_sel[subframe] == n1_pucch_sel)
|
|
return(99);
|
|
else
|
|
return(0);
|
|
}
|