Commit 18919576 authored by Laurent THOMAS's avatar Laurent THOMAS

rework PUCCH codec with c16_t type, rewrite large parts of functions to make...

rework PUCCH codec with c16_t type, rewrite large parts of functions to make readable code. Not fixed parts that are using SIMD. No change, the code is still same block by block (variable visibility narrowed, declaration can be shifted)
parent c37974ca
......@@ -8,144 +8,152 @@
configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char *argv[])
{
time_stats_t timeEncoder,timeDecoder;
opp_enabled=1;
reset_meas(&timeEncoder);
reset_meas(&timeDecoder);
randominit(0);
int arguments, iterations = 1000, messageLength = 11;
//int matlabDebug = 0;
uint32_t testInput, encoderOutput, codingDifference, nBitError=0, blockErrorState = 0, blockErrorCumulative=0, bitErrorCumulative=0;
uint16_t estimatedOutput;
double SNRstart = -20.0, SNRstop = 5.0, SNRinc= 0.5; //dB
double SNR, SNR_lin, sigma;
double modulatedInput[NR_SMALL_BLOCK_CODED_BITS], channelOutput[NR_SMALL_BLOCK_CODED_BITS];
//int16_t channelOutput_int16[NR_SMALL_BLOCK_CODED_BITS];
int8_t channelOutput_int8[NR_SMALL_BLOCK_CODED_BITS];
unsigned char qbits=8;
while ((arguments = getopt (argc, argv, "s:d:f:l:i:mhg")) != -1)
switch (arguments)
{
case 's':
SNRstart = atof(optarg);
break;
case 'd':
SNRinc = atof(optarg);
break;
case 'f':
SNRstop = atof(optarg);
break;
case 'l':
messageLength = atoi(optarg);
break;
case 'i':
iterations = atoi(optarg);
break;
/*case 'm':
matlabDebug = 1;
//#define DEBUG_POLAR_MATLAB
break;*/
case 'g':
iterations = 1;
SNRstart = -6.0;
SNRstop = -6.0;
messageLength = 11;
break;
case 'h':
//printf("./smallblocktest -s SNRstart -d SNRinc -f SNRstop -l messageLength -i iterations -m Matlab Debug\n");
printf("./smallblocktest -s SNRstart -d SNRinc -f SNRstop -l messageLength -i iterations\n");
exit(-1);
default:
perror("[smallblocktest.c] Problem at argument parsing with getopt");
exit(-1);
}
uint16_t mask = 0x07ff >> (11-messageLength);
for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) {
printf("SNR %f\n",SNR);
SNR_lin = pow(10, SNR/10.0);
sigma = 1.0/sqrt(SNR_lin);
for (int itr = 1; itr <= iterations; itr++) {
//Generate random test input of length "messageLength"
testInput = 0;
for (int i = 1; i < messageLength; i++) {
testInput |= ( ((uint32_t) (rand()%2)) &1);
testInput<<=1;
}
testInput |= ( ((uint32_t) (rand()%2)) &1);
//Encoding
start_meas(&timeEncoder);
encoderOutput = encodeSmallBlock((uint16_t*)&testInput, (uint8_t)messageLength);
stop_meas(&timeEncoder);
for (int i=0; i<NR_SMALL_BLOCK_CODED_BITS; i++) {
//BPSK modulation
if ((encoderOutput>>i) & 1 ) {
modulatedInput[i]=-1;
} else {
modulatedInput[i]=1;
}
//AWGN
channelOutput[i] = modulatedInput[i] + ( gaussdouble(0.0,1.0) * ( 1/sqrt(SNR_lin) ) );
//Quantization
channelOutput_int8[i] = quantize(sigma/16.0, channelOutput[i], qbits);
}
//Decoding
start_meas(&timeDecoder);
estimatedOutput = decodeSmallBlock(channelOutput_int8, (uint8_t)messageLength);
stop_meas(&timeDecoder);
time_stats_t timeEncoder, timeDecoder;
opp_enabled = 1;
reset_meas(&timeEncoder);
reset_meas(&timeDecoder);
randominit(0);
int arguments, iterations = 1000, messageLength = 11;
// int matlabDebug = 0;
uint32_t testInput, encoderOutput, codingDifference, nBitError = 0, blockErrorState = 0, blockErrorCumulative = 0,
bitErrorCumulative = 0;
uint16_t estimatedOutput;
double SNRstart = -20.0, SNRstop = 5.0, SNRinc = 0.5; // dB
double SNR, SNR_lin, sigma;
double modulatedInput[NR_SMALL_BLOCK_CODED_BITS], channelOutput[NR_SMALL_BLOCK_CODED_BITS];
// int16_t channelOutput_int16[NR_SMALL_BLOCK_CODED_BITS];
int8_t channelOutput_int8[NR_SMALL_BLOCK_CODED_BITS];
unsigned char qbits = 8;
while ((arguments = getopt(argc, argv, "s:d:f:l:i:mhg")) != -1)
switch (arguments) {
case 's':
SNRstart = atof(optarg);
break;
case 'd':
SNRinc = atof(optarg);
break;
case 'f':
SNRstop = atof(optarg);
break;
case 'l':
messageLength = atoi(optarg);
break;
case 'i':
iterations = atoi(optarg);
break;
/*case 'm':
matlabDebug = 1;
//#define DEBUG_POLAR_MATLAB
break;*/
case 'g':
iterations = 1;
SNRstart = -6.0;
SNRstop = -6.0;
messageLength = 11;
break;
case 'h':
// printf("./smallblocktest -s SNRstart -d SNRinc -f SNRstop -l messageLength -i iterations -m Matlab Debug\n");
printf("./smallblocktest -s SNRstart -d SNRinc -f SNRstop -l messageLength -i iterations\n");
exit(-1);
default:
perror("[smallblocktest.c] Problem at argument parsing with getopt");
exit(-1);
}
uint16_t mask = 0x07ff >> (11 - messageLength);
for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) {
printf("SNR %f\n", SNR);
SNR_lin = pow(10, SNR / 10.0);
sigma = 1.0 / sqrt(SNR_lin);
for (int itr = 1; itr <= iterations; itr++) {
// Generate random test input of length "messageLength"
testInput = 0;
for (int i = 1; i < messageLength; i++) {
testInput |= (((uint32_t)(rand() % 2)) & 1);
testInput <<= 1;
}
testInput |= (((uint32_t)(rand() % 2)) & 1);
// Encoding
start_meas(&timeEncoder);
encoderOutput = encodeSmallBlock(testInput, messageLength);
stop_meas(&timeEncoder);
for (int i = 0; i < NR_SMALL_BLOCK_CODED_BITS; i++) {
// BPSK modulation
if ((encoderOutput >> i) & 1) {
modulatedInput[i] = -1;
} else {
modulatedInput[i] = 1;
}
// AWGN
channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0, 1.0) * (1 / sqrt(SNR_lin)));
// Quantization
channelOutput_int8[i] = quantize(sigma / 16.0, channelOutput[i], qbits);
}
// Decoding
start_meas(&timeDecoder);
estimatedOutput = decodeSmallBlock(channelOutput_int8, (uint8_t)messageLength);
stop_meas(&timeDecoder);
#ifdef DEBUG_SMALLBLOCKTEST
printf("[smallblocktest] Input = 0x%x, Output = 0x%x, DecoderOutput = 0x%x\n", testInput, encoderOutput, estimatedOutput);
for (int i=0;i<32;i++)
printf("[smallblocktest] Input[%d] = %d, Output[%d] = %d, codingDifference[%d]=%d, Mask[%d] = %d\n", i, (testInput>>i)&1, i, (estimatedOutput>>i)&1, i, (codingDifference>>i)&1, i, (mask>>i)&1);
printf("[smallblocktest] Input = 0x%x, Output = 0x%x, DecoderOutput = 0x%x\n", testInput, encoderOutput, estimatedOutput);
for (int i = 0; i < 32; i++)
printf("[smallblocktest] Input[%d] = %d, Output[%d] = %d, codingDifference[%d]=%d, Mask[%d] = %d\n",
i,
(testInput >> i) & 1,
i,
(estimatedOutput >> i) & 1,
i,
(codingDifference >> i) & 1,
i,
(mask >> i) & 1);
#endif
//Error Calculation
estimatedOutput &= mask;
codingDifference = ((uint32_t)estimatedOutput) ^ testInput; // Count the # of 1's in codingDifference by Brian Kernighan’s algorithm.
// Error Calculation
estimatedOutput &= mask;
codingDifference =
((uint32_t)estimatedOutput) ^ testInput; // Count the # of 1's in codingDifference by Brian Kernighan’s algorithm.
for (nBitError = 0; codingDifference; nBitError++)
codingDifference &= codingDifference - 1;
for (nBitError = 0; codingDifference; nBitError++)
codingDifference &= codingDifference - 1;
blockErrorState = (nBitError > 0) ? 1 : 0;
blockErrorState = (nBitError > 0) ? 1 : 0;
blockErrorCumulative+=blockErrorState;
bitErrorCumulative+=nBitError;
blockErrorCumulative += blockErrorState;
bitErrorCumulative += nBitError;
nBitError = 0; blockErrorState = 0;
}
nBitError = 0;
blockErrorState = 0;
}
//Error statistics for the SNR; iteration times are in nanoseconds and microseconds, respectively.
printf("[smallblocktest] SNR=%+7.3f, BER=%9.6f, BLER=%9.6f, t_Encoder=%9.3fns, t_Decoder=%7.3fus\n",
SNR,
((double)bitErrorCumulative / (iterations*messageLength)),
((double)blockErrorCumulative/iterations),
((double)timeEncoder.diff/timeEncoder.trials)/(get_cpu_freq_GHz()),
((double)timeDecoder.diff/timeDecoder.trials)/(get_cpu_freq_GHz()*1000.0));
// Error statistics for the SNR; iteration times are in nanoseconds and microseconds, respectively.
printf("[smallblocktest] SNR=%+7.3f, BER=%9.6f, BLER=%9.6f, t_Encoder=%9.3fns, t_Decoder=%7.3fus\n",
SNR,
((double)bitErrorCumulative / (iterations * messageLength)),
((double)blockErrorCumulative / iterations),
((double)timeEncoder.diff / timeEncoder.trials) / (get_cpu_freq_GHz()),
((double)timeDecoder.diff / timeDecoder.trials) / (get_cpu_freq_GHz() * 1000.0));
blockErrorCumulative=0;
bitErrorCumulative=0;
}
blockErrorCumulative = 0;
bitErrorCumulative = 0;
}
print_meas(&timeEncoder, "smallblock_encoder", NULL, NULL);
print_meas(&timeDecoder, "smallblock_decoder", NULL, NULL);
print_meas(&timeEncoder, "smallblock_encoder", NULL, NULL);
print_meas(&timeDecoder, "smallblock_decoder", NULL, NULL);
return (0);
return (0);
}
......@@ -34,11 +34,12 @@
//input = [0 ... 0 c_K-1 ... c_2 c_1 c_0]
//output = [d_31 d_30 ... d_2 d_1 d_0]
uint32_t encodeSmallBlock(uint16_t *in, uint8_t len){
uint32_t out = 0;
for (uint16_t i=0; i<len; i++)
if ((*in & (1<<i)) > 0)
out^=nrSmallBlockBasis[i];
uint32_t encodeSmallBlock(int in, int len)
{
uint32_t out = 0;
for (int i = 0; i < len; i++)
if ((in & (1 << i)) > 0)
out ^= nrSmallBlockBasis[i];
return out;
return out;
}
......@@ -43,7 +43,7 @@
#define L1d_CLS 64
uint32_t encodeSmallBlock(uint16_t *in, uint8_t len);
uint32_t encodeSmallBlock(int in, int len);
uint16_t decodeSmallBlock(int8_t *in, uint8_t len);
......
......@@ -42,7 +42,7 @@
void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
uint8_t n_hop,
int n_hop,
int nr_slot_tx,
uint8_t *u,
uint8_t *v);
......
......@@ -32,12 +32,13 @@
#include "nr_dci.h"
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
uint8_t n_hop,
int nr_slot_tx,
uint8_t *u,
uint8_t *v) {
void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id,
int n_hop,
int nr_slot_tx,
uint8_t *u,
uint8_t *v)
{
/*
* Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping
* The following variables are set by higher layers:
......
......@@ -158,8 +158,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
AssertFatal(pucch_pdu->bit_len_harq > 0 || pucch_pdu->sr_flag > 0,
"Either bit_len_harq (%d) or sr_flag (%d) must be > 0\n",
pucch_pdu->bit_len_harq,pucch_pdu->sr_flag);
"Either bit_len_harq (%d) or sr_flag (%d) must be > 0\n",
pucch_pdu->bit_len_harq,
pucch_pdu->sr_flag);
NR_gNB_PHY_STATS_t *phy_stats = get_phy_stats(gNB, pucch_pdu->rnti);
AssertFatal(phy_stats != NULL, "phy_stats shouldn't be NULL\n");
......@@ -188,43 +189,19 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
int cs_ind = get_pucch0_cs_lut_index(gNB,pucch_pdu);
/*
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
*
*/
/*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
*/
// alpha is cyclic shift
//double alpha;
// lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
//uint8_t lnormal;
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
//uint8_t lprime;
/*
* in TS 38.213 Subclause 9.2.1 it is said that:
* for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
* is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift
*/
/*
* Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to:
* x(l*12+n) = r_u_v_alpha_delta(n)
*/
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
uint8_t u[2]={0},v[2]={0};
// x_n contains the sequence r_u_v_alpha_delta(n)
int n,i;
int prb_offset[2] = {pucch_pdu->bwp_start+pucch_pdu->prb_start, pucch_pdu->bwp_start+pucch_pdu->prb_start};
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1);
nr_group_sequence_hopping(pucch_GroupHopping,
pucch_pdu->hopping_id,
0,
slot,
&u[0],
&v[0]); // calculating u and v value first hop
// the value of u,v (delta always 0 for PUCCH) has to be calculated according
// to TS 38.211 Subclause 6.3.2.2.1
uint8_t u[2] = {0}, v[2] = {0};
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 0, slot, u,
v); // calculating u and v value first hop
LOG_D(PHY,"pucch0: u %d, v %d\n",u[0],v[0]);
if (pucch_pdu->freq_hop_flag == 1) {
......@@ -253,10 +230,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uint8_t index=0;
int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1
int32_t rp[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][nb_re_pucch];
memset(rp, 0, sizeof(rp));
int32_t *tmp_rp = NULL;
int signal_energy = 0;
int signal_energy = 0, signal_energy_ant0 = 0;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
uint8_t l2 = l + pucch_pdu->start_symbol_index;
......@@ -266,39 +240,38 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
re_offset[l]-=frame_parms->ofdm_symbol_size;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
tmp_rp = (int32_t *)&rxdataF[aa][soffset + l2*frame_parms->ofdm_symbol_size];
c16_t rp[nb_re_pucch];
memset(rp, 0, sizeof(rp));
c16_t *tmp_rp = &rxdataF[aa][soffset + l2 * frame_parms->ofdm_symbol_size];
if(re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) {
int neg_length = frame_parms->ofdm_symbol_size-re_offset[l];
int pos_length = nb_re_pucch-neg_length;
memcpy((void*)rp[aa][l],(void*)&tmp_rp[re_offset[l]],neg_length*sizeof(int32_t));
memcpy((void*)&rp[aa][l][neg_length],(void*)tmp_rp,pos_length*sizeof(int32_t));
memcpy(rp, &tmp_rp[re_offset[l]], neg_length * sizeof(*tmp_rp));
memcpy(&rp[neg_length], tmp_rp, pos_length * sizeof(*tmp_rp));
}
else
memcpy((void*)rp[aa][l],(void*)&tmp_rp[re_offset[l]],nb_re_pucch*sizeof(int32_t));
c16_t *r = (c16_t*)&rp[aa][l];
memcpy(rp, &tmp_rp[re_offset[l]], nb_re_pucch * sizeof(*tmp_rp));
for (n=0;n<nb_re_pucch;n++) {
xr[aa][l][n].r = (int32_t)x_re[l][n] * r[n].r + (int32_t)x_im[l][n] * r[n].i;
xr[aa][l][n].i = (int32_t)x_re[l][n] * r[n].i - (int32_t)x_im[l][n] * r[n].r;
for (int n = 0; n < nb_re_pucch; n++) {
xr[aa][l][n].r = (int32_t)x_re[l][n] * rp[n].r + (int32_t)x_im[l][n] * rp[n].i;
xr[aa][l][n].i = (int32_t)x_re[l][n] * rp[n].i - (int32_t)x_im[l][n] * rp[n].r;
#ifdef DEBUG_NR_PUCCH_RX
printf("x (%d,%d), r%d.%d (%d,%d), xr (%lld,%lld)\n",
x_re[l][n],x_im[l][n],l2,re_offset[l],r[n].r,r[n].i,xr[aa][l][n].r,xr[aa][l][n].i);
printf("x (%d,%d), xr (%ld,%ld)\n", x_re[l][n], x_im[l][n], xr[aa][l][n].r, xr[aa][l][n].i);
#endif
}
signal_energy += signal_energy_nodc((int32_t *)r, nb_re_pucch);
int energ = signal_energy_nodc((int32_t *)rp, nb_re_pucch);
signal_energy += energ;
if (aa == 0)
signal_energy_ant0 += energ;
}
}
signal_energy /= (pucch_pdu->nr_of_symbols * frame_parms->nb_antennas_rx);
int pucch_power_dBtimes10 = 10 * dB_fixed(signal_energy);
//int32_t no_corr = 0;
int seq_index = 0;
int64_t temp;
for(i=0;i<nr_sequences;i++){
for (int i = 0; i < nr_sequences; i++) {
c64_t corr[frame_parms->nb_antennas_rx][2];
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
for (int l=0;l<pucch_pdu->nr_of_symbols;l++) {
......@@ -309,7 +282,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
printf("PUCCH symbol %d seq %d, seq_index %d, mcs %d\n",l,i,seq_index,mcs[i]);
#endif
corr[aa][l]=(c64_t){0};
for (n = 0; n < 12; n++) {
for (int n = 0; n < 12; n++) {
corr[aa][l].r += xr[aa][l][n].r * idft12_re[seq_index][n] + xr[aa][l][n].i * idft12_im[seq_index][n];
corr[aa][l].i += xr[aa][l][n].r * idft12_im[seq_index][n] - xr[aa][l][n].i * idft12_re[seq_index][n];
}
......@@ -321,30 +294,32 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
mcs[i],seq_index,corr[0][0].r,corr[0][0].i,
10*log10((double)squaredMod(corr[0][0])));
if (pucch_pdu->nr_of_symbols==2)
LOG_D(PHY,"PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n",
mcs[i],seq_index,corr[0][1].r,corr[0][1].i,
10*log10((double)squaredMod(corr[0][1])));
LOG_D(PHY,
"PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n",
mcs[i],
seq_index,
corr[0][1].r,
corr[0][1].i,
10 * log10((double)squaredMod(corr[0][1])));
int64_t temp = 0;
if (pucch_pdu->freq_hop_flag == 0) {
if (pucch_pdu->nr_of_symbols==1) {// non-coherent correlation
temp=0;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++)
temp+=squaredMod(corr[aa][0]);
} else {
temp=0;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
c64_t corr2;
csum(corr2, corr[aa][0], corr[aa][1]);
// coherent combining of 2 symbols and then complex modulus for single-frequency case
temp+=corr2.r*corr2.r + corr2.i*corr2.i;
}
if (pucch_pdu->nr_of_symbols == 1) { // non-coherent correlation
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++)
temp += squaredMod(corr[aa][0]);
} else {
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
c64_t corr2;
csum(corr2, corr[aa][0], corr[aa][1]);
// coherent combining of 2 symbols and then complex modulus for
// single-frequency case
temp += corr2.r * corr2.r + corr2.i * corr2.i;
}
} else if (pucch_pdu->freq_hop_flag == 1) {
}
} else {
// full non-coherent combining of 2 symbols for frequency-hopping case
temp=0;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++)
for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++)
temp += squaredMod(corr[aa][0]) + squaredMod(corr[aa][1]);
}
else AssertFatal(1==0,"shouldn't happen\n");
if (temp>xrtmag) {
xrtmag_next = xrtmag;
......@@ -356,11 +331,11 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
temp2 += squaredMod(corr[aa][0]);
if (pucch_pdu->nr_of_symbols==2)
temp3 += squaredMod(corr[aa][1]);
temp3 += squaredMod(corr[aa][1]);
}
uci_stats->current_pucch0_stat0= dB_fixed64(temp2);
if ( pucch_pdu->nr_of_symbols==2)
uci_stats->current_pucch0_stat1= dB_fixed64(temp3);
uci_stats->current_pucch0_stat1 = dB_fixed64(temp3);
}
else if (temp>xrtmag_next)
xrtmag_next = temp;
......@@ -377,28 +352,30 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_stats->pucch0_n01 = gNB->measurements.n0_subband_power_tot_dB[prb_offset[1]];
LOG_D(PHY,"n00[%d] = %d, n01[%d] = %d\n",prb_offset[0],uci_stats->pucch0_n00,prb_offset[1],uci_stats->pucch0_n01);
// estimate CQI for MAC (from antenna port 0 only)
int max_n0 = max(gNB->measurements.n0_subband_power_tot_dB[prb_offset[0]],
gNB->measurements.n0_subband_power_tot_dB[prb_offset[1]]);
int SNRtimes10,sigenergy=0;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++)
sigenergy += signal_energy_nodc(rp[aa][0],12);
SNRtimes10 = pucch_power_dBtimes10 - (10 * max_n0);
int max_n0 =
max(gNB->measurements.n0_subband_power_tot_dB[prb_offset[0]], gNB->measurements.n0_subband_power_tot_dB[prb_offset[1]]);
const int SNRtimes10 = pucch_power_dBtimes10 - (10 * max_n0);
int cqi;
if (SNRtimes10 < -640) cqi=0;
else if (SNRtimes10 > 635) cqi=255;
else cqi=(640+SNRtimes10)/5;
if (SNRtimes10 < -640)
cqi = 0;
else if (SNRtimes10 > 635)
cqi = 255;
else
cqi = (640 + SNRtimes10) / 5;
uci_stats->pucch0_thres = gNB->pucch0_thres; /* + (10*max_n0);*/
bool no_conf=false;
if (nr_sequences>1) {
if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 < gNB->pucch0_thres) {
no_conf=true;
LOG_D(PHY,"%d.%d PUCCH bad confidence: %d threshold, %d, %d, %d\n",
frame, slot,
uci_stats->pucch0_thres,
SNRtimes10,
xrtmag_dBtimes10,
xrtmag_next_dBtimes10);
LOG_D(PHY,
"%d.%d PUCCH bad confidence: %d threshold, %d, %d, %d\n",
frame,
slot,
uci_stats->pucch0_thres,
SNRtimes10,
xrtmag_dBtimes10,
xrtmag_next_dBtimes10);
}
}
gNB->bad_pucch += no_conf;
......@@ -408,7 +385,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_pdu->rnti = pucch_pdu->rnti;
uci_pdu->ul_cqi = cqi;
uci_pdu->timing_advance = 0xffff; // currently not valid
uci_pdu->rssi = 1280 - (10*dB_fixed(32767*32767))-dB_fixed_times10(sigenergy);
uci_pdu->rssi = 1280 - (10 * dB_fixed(32767 * 32767)) - dB_fixed_times10(signal_energy_ant0);
if (pucch_pdu->bit_len_harq==0) {
uci_pdu->sr.sr_confidence_level = SNRtimes10 < uci_stats->pucch0_thres;
......@@ -426,7 +403,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_pdu->harq.harq_confidence_level = no_conf;
uci_pdu->harq.harq_list[0].harq_value = !(index&0x01);
LOG_D(PHY,
"[DLSCH/PDSCH/PUCCH] %d.%d HARQ %s with confidence level %s xrt_mag %d xrt_mag_next %d pucch_power_dBtimes10 %d n0 %d (%d,%d) pucch0_thres %d, "
"[DLSCH/PDSCH/PUCCH] %d.%d HARQ %s with confidence level %s xrt_mag "
"%d xrt_mag_next %d pucch_power_dBtimes10 %d n0 %d "
"(%d,%d) pucch0_thres %d, "
"cqi %d, SNRtimes10 %d, energy %f\n",
frame,
slot,
......@@ -441,7 +420,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_stats->pucch0_thres,
cqi,
SNRtimes10,
10 * log10((double)sigenergy));
10 * log10((double)signal_energy_ant0));
if (pucch_pdu->sr_flag == 1) {
uci_pdu->sr.sr_indication = (index>1);
......@@ -488,10 +467,10 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
}
//*****************************************************************//
void nr_decode_pucch1(c16_t **rxdataF,
pucch_GroupHopping_t pucch_GroupHopping,
uint32_t n_id, // hoppingID higher layer parameter
pucch_GroupHopping_t pucch_GroupHopping,
uint32_t n_id, // hoppingID higher layer parameter
uint64_t *payload,
NR_DL_FRAME_PARMS *frame_parms,
NR_DL_FRAME_PARMS *frame_parms,
int16_t amp,
int nr_tti_tx,
uint8_t m0,
......@@ -503,33 +482,33 @@ void nr_decode_pucch1(c16_t **rxdataF,
uint8_t nr_bit)
{
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%lp m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n",
nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit);
printf(
"\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d "
"payload=%lux m0=%d nrofSymbols=%d startingSymbolIndex=%d "
"startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d "
"nr_bit=%d\n",
nr_tti_tx,
*payload,
m0,
nrofSymbols,
startingSymbolIndex,
startingPRB,
startingPRB_intraSlotHopping,
timeDomainOCC,
nr_bit);
#endif
/*
* Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation
*
*/
int soffset = (nr_tti_tx&3)*frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
// complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
int16_t d_re=0, d_im=0,d1_re=0,d1_im=0;
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] sequence modulation: payload=%lp \tde_re=%d \tde_im=%d\n",payload,d_re,d_im);
#endif
/*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
*/
// alpha is cyclic shift
double alpha;
// lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
//uint8_t lnormal = 0 ;
const int soffset = (nr_tti_tx & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
uint8_t lprime = startingSymbolIndex;
const int lprime = startingSymbolIndex;
// mcs = 0 except for PUCCH format 0
uint8_t mcs=0;
const uint8_t mcs = 0;
// r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence y(n) for the PUCCH, when they are multiplied by d(0)
// r_u_v_alpha_delta_dmrs_re and r_u_v_alpha_delta_dmrs_im tables containing the sequence for the DM-RS.
int16_t r_u_v_alpha_delta_re[12],r_u_v_alpha_delta_im[12],r_u_v_alpha_delta_dmrs_re[12],r_u_v_alpha_delta_dmrs_im[12];
c16_t r_u_v_alpha_delta[12], r_u_v_alpha_delta_dmrs[12];
/*
* in TS 38.213 Subclause 9.2.1 it is said that:
* for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
......@@ -540,21 +519,12 @@ void nr_decode_pucch1(c16_t **rxdataF,
*/
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
uint8_t u=0,v=0;//,delta=0;
// if frequency hopping is disabled, intraSlotFrequencyHopping is not provided
// n_hop = 0
// if frequency hopping is enabled, intraSlotFrequencyHopping is provided
// n_hop = 0 for first hop
// n_hop = 1 for second hop
uint8_t n_hop = 0;
// Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided,
// regardless of whether the frequency-hop distance is zero or not,
// otherwise no intra-slot frequency hopping shall be assumed
//uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers
uint8_t intraSlotFrequencyHopping = 0;
if (startingPRB != startingPRB_intraSlotHopping) {
intraSlotFrequencyHopping=1;
}
const bool intraSlotFrequencyHopping = startingPRB != startingPRB_intraSlotHopping;
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping);
......@@ -562,119 +532,110 @@ void nr_decode_pucch1(c16_t **rxdataF,
/*
* Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources
*/
//int32_t *txptr;
uint32_t re_offset=0;
int i=0;
#define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n
int16_t z_re_rx[MAX_SIZE_Z],z_im_rx[MAX_SIZE_Z],z_re_temp,z_im_temp;
int16_t z_dmrs_re_rx[MAX_SIZE_Z],z_dmrs_im_rx[MAX_SIZE_Z],z_dmrs_re_temp,z_dmrs_im_temp;
memset(z_re_rx,0,MAX_SIZE_Z*sizeof(int16_t));
memset(z_im_rx,0,MAX_SIZE_Z*sizeof(int16_t));
memset(z_dmrs_re_rx,0,MAX_SIZE_Z*sizeof(int16_t));
memset(z_dmrs_im_rx,0,MAX_SIZE_Z*sizeof(int16_t));
int l=0;
for(l=0;l<nrofSymbols;l++){ //extracting data and dmrs from rxdataF
if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB
c16_t z_rx[MAX_SIZE_Z] = {0};
c16_t z_dmrs_rx[MAX_SIZE_Z] = {0};
const int half_nb_rb_dl = frame_parms->N_RB_DL >> 1;
const bool nb_rb_is_even = (frame_parms->N_RB_DL & 1) == 0;
for (int l = 0; l < nrofSymbols; l++) { // extracting data and dmrs from rxdataF
if (intraSlotFrequencyHopping && (l < floor(nrofSymbols / 2))) { // intra-slot hopping enabled, we need
// to calculate new offset PRB
startingPRB = startingPRB + startingPRB_intraSlotHopping;
}
if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1)));
}
if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
}
if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
}
if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size;
if (nb_rb_is_even) {
if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is even and
// current PRB is lower band
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
else // if number RBs in bandwidth is even and current PRB is upper band
re_offset += 12 * (startingPRB - half_nb_rb_dl);
} else {
if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is odd and
// current PRB is lower band
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
else if (startingPRB > half_nb_rb_dl) // if number RBs in bandwidth is odd
// and current PRB is upper band
re_offset += 12 * (startingPRB - half_nb_rb_dl) + 6;
else // if number RBs in bandwidth is odd and current PRB contains DC
re_offset += 12 * startingPRB + frame_parms->first_carrier_offset;
}
for (int n=0; n<12; n++) {
if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
const int current_subcarrier = l * 12 + n;
if (n == 6 && startingPRB == half_nb_rb_dl && !nb_rb_is_even) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
}
if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1
z_re_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[0];
z_im_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[1];
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset,
l,n,((int16_t *)&rxdataF[0][soffset+re_offset])[0],((int16_t *)&rxdataF[0][soffset+re_offset])[1]);
#endif
}
if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1
z_dmrs_re_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[0];
z_dmrs_im_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[1];
// printf("%d\t%d\t%d\n",l,z_dmrs_re_rx[i+n],z_dmrs_im_rx[i+n]);
if (l % 2 == 1) // mapping PUCCH or DM-RS according to TS38.211 subclause 6.4.1.3.1
z_rx[current_subcarrier] = rxdataF[0][soffset + re_offset];
else
z_dmrs_rx[current_subcarrier] = rxdataF[0][soffset + re_offset];
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset,
l,n,((int16_t *)&rxdataF[0][soffset+re_offset])[0],((int16_t *)&rxdataF[0][soffset+re_offset])[1]);
printf(
"\t [nr_generate_pucch1] mapping %s to RE \t amp=%d "
"\tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d "
"\tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
l % 2 ? "PUCCH" : "DM-RS",
amp,
frame_parms->ofdm_symbol_size,
frame_parms->N_RB_DL,
frame_parms->first_carrier_offset,
current_subcarrier,
re_offset,
l,
n,
rxdataF[0][soffset + re_offset].r,
rxdataF[0][soffset + re_offset].i);
#endif
// printf("l=%d\ti=%d\tre_offset=%d\treceived dmrs re=%d\tim=%d\n",l,i,re_offset,z_dmrs_re_rx[i+n],z_dmrs_im_rx[i+n]);
}
re_offset++;
}
if (l%2 == 1) i+=12;
}
int16_t y_n_re[12],y_n_im[12],y1_n_re[12],y1_n_im[12];
memset(y_n_re,0,12*sizeof(int16_t));
memset(y_n_im,0,12*sizeof(int16_t));
memset(y1_n_re,0,12*sizeof(int16_t));
memset(y1_n_im,0,12*sizeof(int16_t));
cd_t y_n[12] = {0}, y1_n[12] = {0};
//generating transmitted sequence and dmrs
for (l=0; l<nrofSymbols; l++) {
for (int l = 0; l < nrofSymbols; l++) {
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n",
l,lprime);
#endif
// y_n contains the complex value d multiplied by the sequence r_u_v
if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop
// if frequency hopping is disabled, intraSlotFrequencyHopping is not
// provided
// n_hop = 0
// if frequency hopping is enabled, intraSlotFrequencyHopping is provided
// n_hop = 0 for first hop
// n_hop = 1 for second hop
const int n_hop = intraSlotFrequencyHopping && l >= nrofSymbols / 2 ? 1 : 0;
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n",
n_hop,nr_tti_tx);
#endif
nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value
alpha = nr_cyclic_shift_hopping(n_id,m0,mcs,l,lprime,nr_tti_tx);
// Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
double alpha = nr_cyclic_shift_hopping(n_id, m0, mcs, l, lprime, nr_tti_tx);
for (int n=0; n<12; n++) { // generating low papr sequences
if(l%2==1){
r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
- (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha
r_u_v_alpha_delta_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha
}
else{
r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
- (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of DMRS base sequence shifted by alpha
r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha
r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_re[n]))>>15);
r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_im[n]))>>15);
}
// printf("symbol=%d\tr_u_rx_re=%d\tr_u_rx_im=%d\n",l,r_u_v_alpha_delta_dmrs_re[n], r_u_v_alpha_delta_dmrs_im[n]);
// PUCCH sequence = DM-RS sequence multiplied by d(0)
/* y_n_re[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15)
- (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n)
y_n_im[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15)
+ (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) */
const c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * n))};
const c16_t table = {table_5_2_2_2_2_Re[u][n], table_5_2_2_2_2_Im[u][n]};
if (l % 2 == 1)
r_u_v_alpha_delta[n] = c16mulShift(angle, table, 15);
else
r_u_v_alpha_delta_dmrs[n] = c16mulRealShift(c16mulShift(angle, table, 15), amp, 15);
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n",
u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]);
printf(
"\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d "
"\talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) "
"\ty_n[n=%d]=(%f,%f)\n",
u,
v,
alpha,
n,
r_u_v_alpha_delta[n].r,
r_u_v_alpha_delta[n].i,
n,
y_n[n].r,
y_n[n].i);
#endif
}
/*
......@@ -691,298 +652,208 @@ void nr_decode_pucch1(c16_t **rxdataF,
// the index of the orthogonal cover code is from a set determined as described in [4, TS 38.211]
// and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC
// In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field
uint8_t w_index = timeDomainOCC;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime_PUCCH_1;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime_PUCCH_DMRS_1;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime0_PUCCH_1;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime0_PUCCH_DMRS_1;
// mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping
uint8_t mprime = 0;
if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled
const int w_index = timeDomainOCC;
if (intraSlotFrequencyHopping == false) { // intra-slot hopping disabled
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n",
intraSlotFrequencyHopping);
#endif
N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (PUCCH)
N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (DM-RS)
N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH)
N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS)
// mprime is 0 in this not hopping case
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
// (depending on number of PUCCH symbols nrofSymbols, mprime and
// intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains
// N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH
// symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
// (depending on number of PUCCH symbols nrofSymbols, mprime=0 and
// intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains
// N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH
// symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
// mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot
// hopping
int N_SF_mprime_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (PUCCH)
int N_SF_mprime_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (DM-RS)
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
#endif
if(l%2==1){
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)){
for (int n=0; n<12 ; n++) {
z_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]=z_re_temp;
z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]=z_im_temp;
// printf("symbol=%d\tz_re_rx=%d\tz_im_rx=%d\t",l,(int)z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
// multiplying with conjugate of low papr sequence
z_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
+ (((int32_t)(r_u_v_alpha_delta_im[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
- (((int32_t)(r_u_v_alpha_delta_im[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp;
z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_im_temp;
/* if(z_re_temp<0){
printf("\nBug detection %d\t%d\t%d\t%d\n",r_u_v_alpha_delta_re[n],z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(((int32_t)(r_u_v_alpha_delta_re[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15),(((int32_t)(r_u_v_alpha_delta_im[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15));
}
printf("z1_re_rx=%d\tz1_im_rx=%d\n",(int)z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); */
}
}
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
if (l / 2 == m) {
for (int n = 0; n < 12; n++) {
c16_t *zPtr = z_rx + m * 12 + n;
*zPtr = c16MulConjShift(table, *zPtr, 15);
// multiplying with conjugate of low papr sequence
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
}
}
}
}
else{
} else {
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)){
for (int n=0; n<12 ; n++) {
z_dmrs_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp;
z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp;
// printf("symbol=%d\tz_dmrs_re_rx=%d\tz_dmrs_im_rx=%d\t",l,(int)z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
//finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and z_dmrs_im_rx arrays
z_dmrs_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
+ (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
- (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
/* if(z_dmrs_re_temp<0){
printf("\nBug detection %d\t%d\t%d\t%d\n",r_u_v_alpha_delta_dmrs_re[n],z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15),(((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15));
}*/
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp;
z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp;
// printf("z1_dmrs_re_rx=%d\tz1_dmrs_im_rx=%d\n",(int)z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
/* z_dmrs_re_rx[(int)(l/2)*12+n]=z_dmrs_re_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_re[n];
z_dmrs_im_rx[(int)(l/2)*12+n]=z_dmrs_im_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_im[n]; */
}
}
const c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]};
if (l / 2 == m) {
for (int n = 0; n < 12; n++) {
c16_t *zDmrsPtr = z_dmrs_rx + m * 12 + n;
*zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
// finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
// z_dmrs_im_rx arrays
*zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
}
}
}
}
}
if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled
if (intraSlotFrequencyHopping == true) { // intra-slot hopping enabled
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n",
intraSlotFrequencyHopping);
#endif
N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
// (depending on number of PUCCH symbols nrofSymbols, mprime and
// intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains
// N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH
// symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
// (depending on number of PUCCH symbols nrofSymbols, mprime=0 and
// intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains
// N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH
// symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
// mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot
// hopping
int N_SF_mprime_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
int N_SF_mprime_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
int N_SF_mprime0_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
int N_SF_mprime0_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
#endif
for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1}
if(l%2==1){
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)){
for (int n=0; n<12 ; n++) {
z_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp;
z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_im_temp;
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
z_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
+ (((int32_t)(r_u_v_alpha_delta_im[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)
- (((int32_t)(r_u_v_alpha_delta_im[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1);
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp;
z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_im_temp;
}
}
}
for (int mprime = 0; mprime < 2; mprime++) { // mprime can get values {0,1}
if (l % 2 == 1) {
for (int m = 0; m < N_SF_mprime_PUCCH_1; m++) {
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12)) {
for (int n = 0; n < 12; n++) {
c16_t *zPtr = z_rx + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n;
*zPtr = c16MulConjShift(table, *zPtr, 15);
*zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
}
}
}
}
else{
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)){
for (int n=0; n<12 ; n++) {
z_dmrs_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp;
z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp;
#ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
//finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and z_dmrs_im_rx arrays
z_dmrs_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
+ (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15)
- (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1);
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp;
z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp;
/* z_dmrs_re_rx[(int)(l/2)*12+n]=z_dmrs_re_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_re[n];
z_dmrs_im_rx[(int)(l/2)*12+n]=z_dmrs_im_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_im[n]; */
}
}
}
else {
for (int m = 0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12)) {
for (int n = 0; n < 12; n++) {
c16_t *zDmrsPtr = z_dmrs_rx + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12) + n;
*zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
// finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
// z_dmrs_im_rx arrays
*zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
}
}
}
}
N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH)
N_SF_mprime_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH)
N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS)
}
}
}
int16_t H_re[12],H_im[12],H1_re[12],H1_im[12];
memset(H_re,0,12*sizeof(int16_t));
memset(H_im,0,12*sizeof(int16_t));
memset(H1_re,0,12*sizeof(int16_t));
memset(H1_im,0,12*sizeof(int16_t));
//averaging channel coefficients
for(l=0;l<=ceil(nrofSymbols/2);l++){
if(intraSlotFrequencyHopping==0){
for(int n=0;n<12;n++){
H_re[n]=round(z_dmrs_re_rx[l*12+n]/ceil(nrofSymbols/2))+H_re[n];
H_im[n]=round(z_dmrs_im_rx[l*12+n]/ceil(nrofSymbols/2))+H_im[n];
}
}
else{
if(l<round(nrofSymbols/4)){
for(int n=0;n<12;n++){
H_re[n]=round(z_dmrs_re_rx[l*12+n]/round(nrofSymbols/4))+H_re[n];
H_im[n]=round(z_dmrs_im_rx[l*12+n]/round(nrofSymbols/4))+H_im[n];
}
}
else{
for(int n=0;n<12;n++){
H1_re[n]=round(z_dmrs_re_rx[l*12+n]/(ceil(nrofSymbols/2)-round(nrofSymbols/4)))+H1_re[n];
H1_im[n]=round(z_dmrs_im_rx[l*12+n]/(ceil(nrofSymbols/2))-round(nrofSymbols/4))+H1_im[n];
}
cd_t H[12] = {0}, H1[12] = {0};
const double half_nb_symbols = nrofSymbols / 2.0;
const double quarter_nb_symbols = nrofSymbols / 4.0;
for (int l = 0; l <= half_nb_symbols; l++) {
if (intraSlotFrequencyHopping == false) {
for (int n = 0; n < 12; n++) {
H[n].r += z_dmrs_rx[l * 12 + n].r / half_nb_symbols;
H[n].i += z_dmrs_rx[l * 12 + n].i / half_nb_symbols;
y_n[n].r += z_rx[l * 12 + n].r / half_nb_symbols;
y_n[n].i += z_rx[l * 12 + n].i / half_nb_symbols;
}
}
}
//averaging information sequences
for(l=0;l<floor(nrofSymbols/2);l++){
if(intraSlotFrequencyHopping==0){
for(int n=0;n<12;n++){
y_n_re[n]=round(z_re_rx[l*12+n]/floor(nrofSymbols/2))+y_n_re[n];
y_n_im[n]=round(z_im_rx[l*12+n]/floor(nrofSymbols/2))+y_n_im[n];
}
}
else{
if(l<floor(nrofSymbols/4)){
for(int n=0;n<12;n++){
y_n_re[n]=round(z_re_rx[l*12+n]/floor(nrofSymbols/4))+y_n_re[n];
y_n_im[n]=round(z_im_rx[l*12+n]/floor(nrofSymbols/4))+y_n_im[n];
}
}
else{
for(int n=0;n<12;n++){
y1_n_re[n]=round(z_re_rx[l*12+n]/round(nrofSymbols/4))+y1_n_re[n];
y1_n_im[n]=round(z_im_rx[l*12+n]/round(nrofSymbols/4))+y1_n_im[n];
} else {
if (l < nrofSymbols / 4) {
for (int n = 0; n < 12; n++) {
H[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols;
H[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols;
y_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols;
y_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols;
}
}
} else {
for (int n = 0; n < 12; n++) {
H1[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols;
H1[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols;
y1_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols;
y1_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols;
}
}
}
}
// mrc combining to obtain z_re and z_im
if(intraSlotFrequencyHopping==0){
for(int n=0;n<12;n++){
d_re = round(((int16_t)(((((int32_t)(H_re[n])*y_n_re[n])>>15) + (((int32_t)(H_im[n])*y_n_im[n])>>15))>>1))/12)+d_re;
d_im = round(((int16_t)(((((int32_t)(H_re[n])*y_n_im[n])>>15) - (((int32_t)(H_im[n])*y_n_re[n])>>15))>>1))/12)+d_im;
cd_t d = {0};
if (intraSlotFrequencyHopping == false) {
// complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
for (int n = 0; n < 12; n++) {
d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i;
d.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r;
}
}
else{
for(int n=0;n<12;n++){
d_re = round(((int16_t)(((((int32_t)(H_re[n])*y_n_re[n])>>15) + (((int32_t)(H_im[n])*y_n_im[n])>>15))>>1))/12)+d_re;
d_im = round(((int16_t)(((((int32_t)(H_re[n])*y_n_im[n])>>15) - (((int32_t)(H_im[n])*y_n_re[n])>>15))>>1))/12)+d_im;
d1_re = round(((int16_t)(((((int32_t)(H1_re[n])*y1_n_re[n])>>15) + (((int32_t)(H1_im[n])*y1_n_im[n])>>15))>>1))/12)+d1_re;
d1_im = round(((int16_t)(((((int32_t)(H1_re[n])*y1_n_im[n])>>15) - (((int32_t)(H1_im[n])*y1_n_re[n])>>15))>>1))/12)+d1_im;
} else {
for (int n = 0; n < 12; n++) {
d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i;
d.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r;
d.r += H[n].r * y1_n[n].r + H[n].i * y1_n[n].i;
d.i += H[n].r * y1_n[n].i - H[n].i * y1_n[n].r;
}
d_re=round(d_re/2);
d_im=round(d_im/2);
d1_re=round(d1_re/2);
d1_im=round(d1_im/2);
d_re=d_re+d1_re;
d_im=d_im+d1_im;
}
//Decoding QPSK or BPSK symbols to obtain payload bits
if(nr_bit==1){
if((d_re+d_im)>0){
*payload=0;
}
else{
*payload=1;
}
}
else if(nr_bit==2){
if((d_re>0)&&(d_im>0)){
*payload=0;
}
else if((d_re<0)&&(d_im>0)){
*payload=1;
}
else if((d_re>0)&&(d_im<0)){
*payload=2;
if (nr_bit == 1) {
if ((d.r + d.i) > 0) {
*payload = 0;
} else {
*payload = 1;
}
else{
*payload=3;
} else if (nr_bit == 2) {
if ((d.r > 0) && (d.i > 0)) {
*payload = 0;
} else if ((d.r < 0) && (d.i > 0)) {
*payload = 1;
} else if ((d.r > 0) && (d.i < 0)) {
*payload = 2;
} else {
*payload = 3;
}
}
}
simde__m256i pucch2_3bit[8*2];
simde__m256i pucch2_4bit[16*2];
simde__m256i pucch2_5bit[32*2];
simde__m256i pucch2_6bit[64*2];
simde__m256i pucch2_7bit[128*2];
simde__m256i pucch2_8bit[256*2];
simde__m256i pucch2_9bit[512*2];
simde__m256i pucch2_10bit[1024*2];
simde__m256i pucch2_11bit[2048*2];
static simde__m256i *pucch2_lut[9]={pucch2_3bit,
pucch2_4bit,
pucch2_5bit,
pucch2_6bit,
pucch2_7bit,
pucch2_8bit,
pucch2_9bit,
pucch2_10bit,
pucch2_11bit};
static simde__m256i pucch2_3bit[8 * 2];
static simde__m256i pucch2_4bit[16 * 2];
static simde__m256i pucch2_5bit[32 * 2];
static simde__m256i pucch2_6bit[64 * 2];
static simde__m256i pucch2_7bit[128 * 2];
static simde__m256i pucch2_8bit[256 * 2];
static simde__m256i pucch2_9bit[512 * 2];
static simde__m256i pucch2_10bit[1024 * 2];
static simde__m256i pucch2_11bit[2048 * 2];
static simde__m256i *pucch2_lut[9] =
{pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit};
simde__m64 pucch2_polar_4bit[16];
simde__m128i pucch2_polar_llr_num_lut[256],pucch2_polar_llr_den_lut[256];
......@@ -993,8 +864,8 @@ void init_pucch2_luts() {
int8_t bit;
for (int b=3;b<12;b++) {
for (uint16_t i=0;i<(1<<b);i++) {
out=encodeSmallBlock(&i,b);
for (int i = 0; i < (1 << b); i++) {
out = encodeSmallBlock(i, b);
#ifdef DEBUG_NR_PUCCH_RX
if (b==3) printf("in %d, out %x\n",i,out);
#endif
......@@ -1066,7 +937,7 @@ void init_pucch2_luts() {
*lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,15);
}
}
for (uint16_t i=0;i<16;i++) {
for (int i = 0; i < 16; i++) {
simde__m64 *lut_i=&pucch2_polar_4bit[i];
bit = (i&0x1) > 0 ? -1 : 1;
......@@ -1082,47 +953,48 @@ void init_pucch2_luts() {
simde__m128i *lut_num_i=&pucch2_polar_llr_num_lut[i];
simde__m128i *lut_den_i=&pucch2_polar_llr_den_lut[i];
bit = (i&0x1) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,0);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,0);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 0);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 0);
bit = (i&0x10) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,1);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,1);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 1);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 1);
bit = (i&0x2) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,2);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,2);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 2);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 2);
bit = (i&0x20) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,3);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,3);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 3);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 3);
bit = (i&0x4) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,4);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,4);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 4);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 4);
bit = (i&0x40) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,5);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,5);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 5);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 5);
bit = (i&0x8) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,6);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,6);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 6);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 6);
bit = (i&0x80) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,bit,7);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i,1-bit,7);
*lut_num_i = simde_mm_insert_epi16(*lut_num_i, bit, 7);
*lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 7);
#ifdef DEBUG_NR_PUCCH_RX
printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",i,
((int16_t *)lut_num_i)[0],
((int16_t *)lut_num_i)[1],
((int16_t *)lut_num_i)[2],
((int16_t *)lut_num_i)[3],
((int16_t *)lut_num_i)[4],
((int16_t *)lut_num_i)[5],
((int16_t *)lut_num_i)[6],
((int16_t *)lut_num_i)[7]);
printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
i,
((int16_t *)lut_num_i)[0],
((int16_t *)lut_num_i)[1],
((int16_t *)lut_num_i)[2],
((int16_t *)lut_num_i)[3],
((int16_t *)lut_num_i)[4],
((int16_t *)lut_num_i)[5],
((int16_t *)lut_num_i)[6],
((int16_t *)lut_num_i)[7]);
#endif
}
}
......@@ -1138,8 +1010,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
//pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
AssertFatal(pucch_pdu->nr_of_symbols==1 || pucch_pdu->nr_of_symbols==2,
"Illegal number of symbols for PUCCH 2 %d\n",pucch_pdu->nr_of_symbols);
AssertFatal(pucch_pdu->nr_of_symbols == 1 || pucch_pdu->nr_of_symbols == 2,
"Illegal number of symbols for PUCCH 2 %d\n",
pucch_pdu->nr_of_symbols);
AssertFatal((pucch_pdu->prb_start-((pucch_pdu->prb_start>>2)<<2))==0,
"Current pucch2 receiver implementation requires a PRB offset multiple of 4. The one selected is %d",
......@@ -1147,21 +1020,26 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
//extract pucch and dmrs first
int l2=pucch_pdu->start_symbol_index;
int re_offset[2];
re_offset[0] = 12*(pucch_pdu->prb_start+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset;
int soffset=(slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
int l2 = pucch_pdu->start_symbol_index;
int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
int re_offset[2];
re_offset[0] =
(12 * (pucch_pdu->prb_start + pucch_pdu->bwp_start) + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
if (re_offset[0]>= frame_parms->ofdm_symbol_size)
re_offset[0]-=frame_parms->ofdm_symbol_size;
if (pucch_pdu->freq_hop_flag == 0) re_offset[1] = re_offset[0];
if (pucch_pdu->freq_hop_flag == 0)
re_offset[1] = re_offset[0];
else {
re_offset[1] = 12*(pucch_pdu->second_hop_prb+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset;
if (re_offset[1]>= frame_parms->ofdm_symbol_size)
re_offset[1]-=frame_parms->ofdm_symbol_size;
}
AssertFatal(pucch_pdu->prb_size*pucch_pdu->nr_of_symbols > 1,"number of PRB*SYMB (%d,%d)< 2",
pucch_pdu->prb_size,pucch_pdu->nr_of_symbols);
AssertFatal(pucch_pdu->prb_size * pucch_pdu->nr_of_symbols > 1,
"number of PRB*SYMB (%d,%d)< 2",
pucch_pdu->prb_size,
pucch_pdu->nr_of_symbols);
int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value;
// AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of2\n",pucch_pdu->prb_size);
......@@ -1216,7 +1094,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// if the number of PRBs is odd
// we fill the unsed part of the arrays
for (int aa = 0; aa < Prx; aa++) {
for (int symb=0; symb<pucch_pdu->nr_of_symbols;symb++) {
for (int symb = 0; symb < pucch_pdu->nr_of_symbols; symb++) {
const int sz = pucch_pdu->prb_size;
memset(r_re_ext[aa][symb] + 8 * sz, 0, 8 * sizeof(int16_t));
memset(r_im_ext[aa][symb] + 8 * sz, 0, 8 * sizeof(int16_t));
......@@ -1228,7 +1106,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int symb=0; symb<pucch_pdu->nr_of_symbols;symb++) {
// 24 REs contains 48x16-bit, so 6x8x16-bit
for (int aa=0;aa<Prx;aa++) {
for (int aa = 0; aa < Prx; aa++) {
for (int prb = 0; prb < pucch_pdu->prb_size; prb++) {
int16_t *r_re_ext_p = &r_re_ext[aa][symb][8 * prb];
int16_t *r_im_ext_p = &r_im_ext[aa][symb][8 * prb];
......@@ -1272,7 +1150,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
reset = 0;
}
for (int group=0;group<ngroup;group++) {
for (int group = 0; group < ngroup; group++) {
// each group has 8*nc_group_size elements, compute 1 complex correlation with DMRS per group
// non-coherent combining across groups
simde__m64 dmrs_re = byte2m64_re[sGold8[(group & 1) << 1]];
......@@ -1280,9 +1158,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
simde__m64 dmrs_im = byte2m64_im[sGold8[(group & 1) << 1]];
int16_t *dmrs_im16 = (int16_t *)&dmrs_im;
#ifdef DEBUG_NR_PUCCH_RX
printf("Group %d: s %x x2 %x ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n",
printf("Group %d: x2 %x ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n",
group,
((uint16_t *)&s)[0],
x2,
dmrs_re16[0],
dmrs_im16[0],
......@@ -1308,7 +1185,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int z = 0; z < 4; z++) {
corr32_re[symb][group][aa] += rd_re_ext_p[z] * dmrs_re16[z] + rd_im_ext_p[z] * dmrs_im16[z];
corr32_im[symb][group][aa] += -rd_re_ext_p[z] * dmrs_im16[z] + rd_im_ext_p[z] * dmrs_re16[z];
}
}
}
dmrs_re = byte2m64_re[sGold8[1 + ((group & 1) << 1)]];
dmrs_im = byte2m64_im[sGold8[1 + ((group & 1) << 1)]];
......@@ -1340,7 +1217,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
corr32_re[symb][group][aa] += rd_re_ext_p[z + 4] * dmrs_re16[z] + rd_im_ext_p[z + 4] * dmrs_im16[z];
corr32_im[symb][group][aa] += -rd_re_ext_p[z + 4] * dmrs_im16[z] + rd_im_ext_p[z + 4] * dmrs_re16[z];
}
/* corr32_re[group][aa]>>=5;
/* corr32_re[group][aa]>>=5;
corr32_im[group][aa]>>=5;*/
#ifdef DEBUG_NR_PUCCH_RX
printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[symb][group][aa],corr32_im[symb][group][aa]);
......@@ -1358,7 +1235,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
sGold = lte_gold_generic(&x1, &x2, 1);
uint8_t *sGold8 = (uint8_t *)&sGold;
#ifdef DEBUG_NR_PUCCH_RX
printf("x2 %x, s %x\n",x2,s);
printf("x2 %x\n", x2);
#endif
for (int symb=0;symb<pucch_pdu->nr_of_symbols;symb++) {
simde__m64 c_re[4], c_im[4];
......@@ -1477,9 +1354,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
#ifdef DEBUG_NR_PUCCH_RX
printf("cw %d:",cw);
for (int i=0;i<32;i+=2) {
printf("%d,%d,",
((int16_t*)&pucch2_lut[nb_bit-3][cw<<1])[i>>1],
((int16_t*)&pucch2_lut[nb_bit-3][cw<<1])[1+(i>>1)]);
printf("%d,%d,",
((int16_t *)&pucch2_lut[nb_bit - 3][cw << 1])[i >> 1],
((int16_t *)&pucch2_lut[nb_bit - 3][cw << 1])[1 + (i >> 1)]);
}
printf("\n");
#endif
......@@ -1489,10 +1366,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int group=0;group<ngroup;group++) {
// do complex correlation
for (int aa=0;aa<Prx;aa++) {
prod_re[aa] = /*simde_mm256_srai_epi16(*/simde_mm256_adds_epi16(simde_mm256_mullo_epi16(pucch2_lut[nb_bit-3][cw<<1],rp_re[aa][symb][group]),
simde_mm256_mullo_epi16(pucch2_lut[nb_bit-3][(cw<<1)+1],rp_im[aa][symb][group]))/*,5)*/;
prod_im[aa] = /*simde_mm256_srai_epi16(*/simde_mm256_subs_epi16(simde_mm256_mullo_epi16(pucch2_lut[nb_bit-3][cw<<1],rp2_im[aa][symb][group]),
simde_mm256_mullo_epi16(pucch2_lut[nb_bit-3][(cw<<1)+1],rp2_re[aa][symb][group]))/*,5)*/;
prod_re[aa] = /*simde_mm256_srai_epi16(*/ simde_mm256_adds_epi16(
simde_mm256_mullo_epi16(pucch2_lut[nb_bit - 3][cw << 1], rp_re[aa][symb][group]),
simde_mm256_mullo_epi16(pucch2_lut[nb_bit - 3][(cw << 1) + 1], rp_im[aa][symb][group])) /*,5)*/;
prod_im[aa] = /*simde_mm256_srai_epi16(*/ simde_mm256_subs_epi16(
simde_mm256_mullo_epi16(pucch2_lut[nb_bit - 3][cw << 1], rp2_im[aa][symb][group]),
simde_mm256_mullo_epi16(pucch2_lut[nb_bit - 3][(cw << 1) + 1], rp2_re[aa][symb][group])) /*,5)*/;
#ifdef DEBUG_NR_PUCCH_RX
printf("prod_re[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",aa,
((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3],
......@@ -1513,7 +1392,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
#endif
#endif
prod_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
prod_re[aa] = simde_mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3
#ifdef DEBUG_NR_PUCCH_RX
......@@ -1522,7 +1401,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
#endif
#endif
prod_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
prod_re[aa] = simde_mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7
#ifdef DEBUG_NR_PUCCH_RX
......@@ -1531,7 +1410,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7],
((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11],
((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]);
#endif
#endif
prod_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
}
int64_t corr_re=0,corr_im=0;
......@@ -1542,12 +1421,16 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
corr_re = ( corr32_re[symb][group][aa]+((int16_t*)(&prod_re[aa]))[0]+((int16_t*)(&prod_re[aa]))[8]);
corr_im = ( corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]+((int16_t*)(&prod_im[aa]))[8]);
#ifdef DEBUG_NR_PUCCH_RX
printf("pucch2 cw %d group %d aa %d: (%d,%d)+(%d,%d) = (%ld,%ld)\n",cw,group,aa,
corr32_re[symb][group][aa],corr32_im[symb][group][aa],
((int16_t*)(&prod_re[aa]))[0]+((int16_t*)(&prod_re[aa]))[8],
((int16_t*)(&prod_im[aa]))[0]+((int16_t*)(&prod_im[aa]))[8],
corr_re,corr_im
);
printf("pucch2 cw %d group %d aa %d: (%d,%d)+(%d,%d) = (%ld,%ld)\n",
cw,
group,
aa,
corr32_re[symb][group][aa],
corr32_im[symb][group][aa],
((int16_t *)(&prod_re[aa]))[0] + ((int16_t *)(&prod_re[aa]))[8],
((int16_t *)(&prod_im[aa]))[0] + ((int16_t *)(&prod_im[aa]))[8],
corr_re,
corr_im);
#endif
......@@ -1556,10 +1439,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
}// group loop
} // symb loop
if (corr_tmp > corr) {
corr = corr_tmp;
cw_ML=cw;
corr = corr_tmp;
cw_ML = cw;
#ifdef DEBUG_NR_PUCCH_RX
printf("slot %d PUCCH2 cw_ML %d, corr %lu\n",slot,cw_ML,corr);
printf("slot %d PUCCH2 cw_ML %d, corr %lu\n", slot, cw_ML, corr);
#endif
}
} // cw loop
......@@ -1592,8 +1475,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
printf("cw %d:",cw);
for (int i=0;i<4;i++) {
printf("%d,",
((int16_t*)&pucch2_polar_4bit[cw])[i>>1]);
printf("%d,", ((int16_t *)&pucch2_polar_4bit[cw])[i >> 1]);
}
printf("\n");
}
......@@ -1609,10 +1491,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int cw=0;cw<256;cw++) {
corr_tmp=0;
for (int aa=0;aa<Prx;aa++) {
prod_re[aa] = simde_mm_srai_pi16(simde_mm_adds_pi16(simde_mm_mullo_pi16(pucch2_polar_4bit[cw&15],rp_re[aa][symb][half_prb]),
simde_mm_mullo_pi16(pucch2_polar_4bit[cw>>4],rp_im[aa][symb][half_prb])),5);
prod_im[aa] = simde_mm_srai_pi16(simde_mm_subs_pi16(simde_mm_mullo_pi16(pucch2_polar_4bit[cw&15],rp2_im[aa][symb][half_prb]),
simde_mm_mullo_pi16(pucch2_polar_4bit[cw>>4],rp2_re[aa][symb][half_prb])),5);
prod_re[aa] =
simde_mm_srai_pi16(simde_mm_adds_pi16(simde_mm_mullo_pi16(pucch2_polar_4bit[cw & 15], rp_re[aa][symb][half_prb]),
simde_mm_mullo_pi16(pucch2_polar_4bit[cw >> 4], rp_im[aa][symb][half_prb])),
5);
prod_im[aa] =
simde_mm_srai_pi16(simde_mm_subs_pi16(simde_mm_mullo_pi16(pucch2_polar_4bit[cw & 15], rp2_im[aa][symb][half_prb]),
simde_mm_mullo_pi16(pucch2_polar_4bit[cw >> 4], rp2_re[aa][symb][half_prb])),
5);
prod_re[aa] = simde_mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1
prod_im[aa] = simde_mm_hadds_pi16(prod_im[aa],prod_im[aa]);
prod_re[aa] = simde_mm_hadds_pi16(prod_re[aa],prod_re[aa]);// 0+1+2+3
......@@ -1626,63 +1512,65 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
corr_re = ( corr32_re[symb][half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_re[aa]))[0]);
corr_im = ( corr32_im[symb][half_prb>>2][aa]/(2*nc_group_size*4/2)+((int16_t*)(&prod_im[aa]))[0]);
corr_tmp += corr_re*corr_re + corr_im*corr_im;
/*
LOG_D(PHY,"pucch2 half_prb %d cw %d (%d,%d) aa %d: (%d,%d,%d,%d,%d,%d,%d,%d)x(%d,%d,%d,%d,%d,%d,%d,%d) (%d,%d)+(%d,%d) = (%d,%d) => %d\n",
half_prb,cw,cw&15,cw>>4,aa,
/*
LOG_D(PHY,"pucch2 half_prb %d cw %d (%d,%d) aa %d: (%d,%d,%d,%d,%d,%d,%d,%d)x(%d,%d,%d,%d,%d,%d,%d,%d) (%d,%d)+(%d,%d)
= (%d,%d) => %d\n", half_prb,cw,cw&15,cw>>4,aa,
((int16_t*)&pucch2_polar_4bit[cw&15])[0],((int16_t*)&pucch2_polar_4bit[cw>>4])[0],
((int16_t*)&pucch2_polar_4bit[cw&15])[1],((int16_t*)&pucch2_polar_4bit[cw>>4])[1],
((int16_t*)&pucch2_polar_4bit[cw&15])[2],((int16_t*)&pucch2_polar_4bit[cw>>4])[2],
((int16_t*)&pucch2_polar_4bit[cw&15])[3],((int16_t*)&pucch2_polar_4bit[cw>>4])[3],
((int16_t*)&rp_re[aa][half_prb])[0],((int16_t*)&rp_im[aa][half_prb])[0],
((int16_t*)&rp_re[aa][half_prb])[1],((int16_t*)&rp_im[aa][half_prb])[1],
((int16_t*)&rp_re[aa][half_prb])[2],((int16_t*)&rp_im[aa][half_prb])[2],
((int16_t*)&rp_re[aa][half_prb])[3],((int16_t*)&rp_im[aa][half_prb])[3],
corr32_re[half_prb>>2][aa]/(2*nc_group_size*4/2),corr32_im[half_prb>>2][aa]/(2*nc_group_size*4/2),
((int16_t*)(&prod_re[aa]))[0],
((int16_t*)(&prod_im[aa]))[0],
corr_re,
corr_im,
corr_tmp);
*/
}
corr16 = simde_mm_set1_epi16((int16_t)(corr_tmp>>8));
LOG_D(PHY,"half_prb %d cw %d corr16 %d\n",half_prb,cw,corr_tmp>>8);
llr_num = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16,pucch2_polar_llr_num_lut[cw]),llr_num);
llr_den = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16,pucch2_polar_llr_den_lut[cw]),llr_den);
LOG_D(PHY,"lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t*)&pucch2_polar_llr_num_lut[cw])[0],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[1],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[2],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[3],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[4],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[5],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[6],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[7]);
LOG_D(PHY,"llr_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t*)&llr_num)[0],
((int16_t*)&llr_num)[1],
((int16_t*)&llr_num)[2],
((int16_t*)&llr_num)[3],
((int16_t*)&llr_num)[4],
((int16_t*)&llr_num)[5],
((int16_t*)&llr_num)[6],
((int16_t*)&llr_num)[7]);
LOG_D(PHY,"llr_den (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t*)&llr_den)[0],
((int16_t*)&llr_den)[1],
((int16_t*)&llr_den)[2],
((int16_t*)&llr_den)[3],
((int16_t*)&llr_den)[4],
((int16_t*)&llr_den)[5],
((int16_t*)&llr_den)[6],
((int16_t*)&llr_den)[7]);
}
// compute llrs
((int16_t*)&pucch2_polar_4bit[cw&15])[3],((int16_t*)&pucch2_polar_4bit[cw>>4])[3],
((int16_t*)&rp_re[aa][half_prb])[0],((int16_t*)&rp_im[aa][half_prb])[0],
((int16_t*)&rp_re[aa][half_prb])[1],((int16_t*)&rp_im[aa][half_prb])[1],
((int16_t*)&rp_re[aa][half_prb])[2],((int16_t*)&rp_im[aa][half_prb])[2],
((int16_t*)&rp_re[aa][half_prb])[3],((int16_t*)&rp_im[aa][half_prb])[3],
corr32_re[half_prb>>2][aa]/(2*nc_group_size*4/2),corr32_im[half_prb>>2][aa]/(2*nc_group_size*4/2),
((int16_t*)(&prod_re[aa]))[0],
((int16_t*)(&prod_im[aa]))[0],
corr_re,
corr_im,
corr_tmp);
*/
}
corr16 = simde_mm_set1_epi16((int16_t)(corr_tmp >> 8));
LOG_D(PHY, "half_prb %d cw %d corr16 %d\n", half_prb, cw, corr_tmp >> 8);
llr_num = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16, pucch2_polar_llr_num_lut[cw]), llr_num);
llr_den = simde_mm_max_epi16(simde_mm_mullo_epi16(corr16, pucch2_polar_llr_den_lut[cw]), llr_den);
LOG_D(PHY,
"lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t *)&pucch2_polar_llr_num_lut[cw])[0],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[1],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[2],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[3],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[4],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[5],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[6],
((int16_t *)&pucch2_polar_llr_num_lut[cw])[7]);
LOG_D(PHY,
"llr_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t *)&llr_num)[0],
((int16_t *)&llr_num)[1],
((int16_t *)&llr_num)[2],
((int16_t *)&llr_num)[3],
((int16_t *)&llr_num)[4],
((int16_t *)&llr_num)[5],
((int16_t *)&llr_num)[6],
((int16_t *)&llr_num)[7]);
LOG_D(PHY,
"llr_den (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t *)&llr_den)[0],
((int16_t *)&llr_den)[1],
((int16_t *)&llr_den)[2],
((int16_t *)&llr_den)[3],
((int16_t *)&llr_den)[4],
((int16_t *)&llr_den)[5],
((int16_t *)&llr_den)[6],
((int16_t *)&llr_den)[7]);
}
// compute llrs
llrs[half_prb + (symb*2*pucch_pdu->prb_size)] = simde_mm_subs_epi16(llr_num,llr_den);
LOG_D(PHY,"llrs[%d] : (%d,%d,%d,%d,%d,%d,%d,%d)\n",
half_prb,
......@@ -1712,9 +1600,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// estimate CQI for MAC (from antenna port 0 only)
// TODO this computation is wrong -> to be ignored at MAC for now
int SNRtimes10 = dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset+(l2*frame_parms->ofdm_symbol_size)+re_offset[0]],
12*pucch_pdu->prb_size)) -
(10*gNB->measurements.n0_power_tot_dB);
int SNRtimes10 =
dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset + (l2 * frame_parms->ofdm_symbol_size) + re_offset[0]],
12 * pucch_pdu->prb_size))
- (10 * gNB->measurements.n0_power_tot_dB);
int cqi,bit_left;
if (SNRtimes10 < -640) cqi=0;
else if (SNRtimes10 > 635) cqi=255;
......@@ -1739,14 +1628,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int i=0;
for (;i<harq_bytes-1;i++) {
uci_pdu->harq.harq_payload[i] = decodedPayload[0] & 255;
LOG_D(PHY,"[DLSCH/PDSCH/PUCCH2] %d.%d HARQ paylod (%d) = %d\n",
frame,slot,i,uci_pdu->harq.harq_payload[i]);
LOG_D(PHY, "[DLSCH/PDSCH/PUCCH2] %d.%d HARQ payload (%d) = %d\n", frame, slot, i, uci_pdu->harq.harq_payload[i]);
decodedPayload[0]>>=8;
}
bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3);
uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<bit_left)-1);
LOG_D(PHY,"[DLSCH/PDSCH/PUCCH2] %d.%d HARQ paylod (%d) = %d\n",
frame,slot,i,uci_pdu->harq.harq_payload[i]);
LOG_D(PHY, "[DLSCH/PDSCH/PUCCH2] %d.%d HARQ payload (%d) = %d\n", frame, slot, i, uci_pdu->harq.harq_payload[i]);
decodedPayload[0] >>= pucch_pdu->bit_len_harq;
}
......
......@@ -54,7 +54,7 @@
void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int16_t amp16,
const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
......@@ -72,13 +72,14 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
*/
// alpha is cyclic shift
double alpha;
// lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
//uint8_t lnormal;
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
//uint8_t lprime;
// lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH
// transmission
// uint8_t lnormal;
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the
// slot given by [5, TS 38.213]
// uint8_t lprime;
// mcs is provided by TC 38.213 subclauses 9.2.3, 9.2.4, 9.2.5 FIXME!
//uint8_t mcs;
// uint8_t mcs;
/*
* in TS 38.213 Subclause 9.2.1 it is said that:
* for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
......@@ -89,7 +90,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
* x(l*12+n) = r_u_v_alpha_delta(n)
*/
// the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
uint8_t u[2]={0,0},v[2]={0,0};
uint8_t u[2] = {0}, v[2] = {0};
LOG_D(PHY,"pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d, group_hop_flag %d, sequence_hop_flag %d, mcs %d\n",
nr_slot_tx,pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->mcs);
......@@ -97,70 +98,55 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
#endif
// x_n contains the sequence r_u_v_alpha_delta(n)
int16_t x_n_re[2][24],x_n_im[2][24];
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
int startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
// we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
int prb_offset[2]={startingPRB,startingPRB};
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 0, nr_slot_tx, u, v); // calculating u and v value
if (pucch_pdu->freq_hop_flag == 1) {
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value
nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 1, nr_slot_tx, u + 1, v + 1); // calculating u and v value
prb_offset[1] = pucch_pdu->second_hop_prb + pucch_pdu->bwp_start;
}
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,
pucch_pdu->initial_cyclic_shift,
pucch_pdu->mcs,l,
pucch_pdu->start_symbol_index,
nr_slot_tx);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u[l],v[l],alpha,l);
#endif
for (int n=0; n<12; n++) {
x_n_re[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15)
- (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15))); // Re part of base sequence shifted by alpha
x_n_im[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15))); // Im part of base sequence shifted by alpha
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n",
u[l],v[l],alpha,l,n,x_n_re[l][n],x_n_im[l][n]);
#endif
}
}
/*
* Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources FIXME!
*/
//int32_t *txptr;
uint32_t re_offset=0;
uint8_t l2;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
l2=l+pucch_pdu->start_symbol_index;
re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset;
const double alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,
pucch_pdu->initial_cyclic_shift,
pucch_pdu->mcs,
l,
pucch_pdu->start_symbol_index,
nr_slot_tx);
int l2 = l + pucch_pdu->start_symbol_index;
int re_offset = (12 * prb_offset[l]) + frame_parms->first_carrier_offset;
if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size;
//txptr = &txdataF[0][re_offset];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n",l,prb_offset[l],re_offset);
#endif
#endif
c16_t *txdataFptr = txdataF[0] + l2 * frame_parms->ofdm_symbol_size;
const int32_t amp = amp16;
for (int n=0; n<12; n++) {
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r = (int16_t)(((int32_t)(amp) * x_n_re[l][n])>>15);
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i = (int16_t)(((int32_t)(amp) * x_n_im[l][n])>>15);
//((int16_t *)txptr[0][re_offset])[0] = (int16_t)((int32_t)amp * x_n_re[(12*l)+n])>>15;
//((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15;
//txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n];
const c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * n))};
const c16_t table = {table_5_2_2_2_2_Re[u[l]][n], table_5_2_2_2_2_Im[u[l]][n]};
txdataFptr[re_offset] = c16mulRealShift(c16mulShift(angle, table, 15), amp, 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, (l2 * frame_parms->ofdm_symbol_size) + re_offset,
l2, n, txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r,
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i);
printf(
"\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d "
"\ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp,
frame_parms->ofdm_symbol_size,
frame_parms->N_RB_DL,
frame_parms->first_carrier_offset,
(l2 * frame_parms->ofdm_symbol_size) + re_offset,
l2,
n,
txdataFptr[re_offset].r,
txdataFptr[re_offset].i);
#endif
re_offset++;
if (re_offset>= frame_parms->ofdm_symbol_size)
......@@ -172,7 +158,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int16_t amp16,
const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
......@@ -192,37 +178,20 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
*
*/
// complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
int16_t d_re = 0, d_im = 0;
c16_t d = {0};
const int32_t amp = amp16;
const int16_t baseVal = (amp * ONE_OVER_SQRT2) >> 15;
const c16_t qpskSymbols[4] = {{baseVal, baseVal}, {baseVal, -baseVal}, {-baseVal, baseVal}, {-baseVal, -baseVal}};
if (pucch_pdu->n_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2
d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d = (payload & 1) == 0 ? qpskSymbols[0] : qpskSymbols[3];
}
if (pucch_pdu->n_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2
if (((payload&1)==0) && (((payload>>1)&1)==0)) {
d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((payload&1)==0) && (((payload>>1)&1)==1)) {
d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((payload&1)==1) && (((payload>>1)&1)==0)) {
d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((payload&1)==1) && (((payload>>1)&1)==1)) {
d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
int tmp = ((payload & 1) << 1) + ((payload >> 1) & 1);
d = qpskSymbols[tmp];
}
// printf("d_re=%d\td_im=%d\n",(int)d_re,(int)d_im);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] sequence modulation: payload=%lx \tde_re=%d \tde_im=%d\n",payload,d_re,d_im);
printf("\t [nr_generate_pucch1] sequence modulation: payload=%lx \tde_re=%d \tde_im=%d\n", payload, d.r, d.i);
#endif
/*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
......@@ -265,11 +234,11 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
uint32_t re_offset=0;
int i=0;
#define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n
int16_t z_re[MAX_SIZE_Z],z_im[MAX_SIZE_Z];
int16_t z_dmrs_re[MAX_SIZE_Z],z_dmrs_im[MAX_SIZE_Z];
c16_t z[MAX_SIZE_Z];
c16_t z_dmrs[MAX_SIZE_Z];
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
uint8_t lprime = startingSymbolIndex;
int lprime = startingSymbolIndex;
for (int l = 0; l < nrofSymbols; l++) {
#ifdef DEBUG_NR_PUCCH_TX
......@@ -277,7 +246,7 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
l,lprime);
#endif
// y_n contains the complex value d multiplied by the sequence r_u_v
int16_t y_n_re[12],y_n_im[12];
c16_t y_n[12];
if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols / 2)))
n_hop = 1; // n_hop = 1 for second hop
......@@ -294,28 +263,27 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
// r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence y(n) for the PUCCH, when they are multiplied by d(0)
// r_u_v_alpha_delta_dmrs_re and r_u_v_alpha_delta_dmrs_im tables containing the sequence for the DM-RS.
int16_t r_u_v_alpha_delta_re[12], r_u_v_alpha_delta_im[12], r_u_v_alpha_delta_dmrs_re[12], r_u_v_alpha_delta_dmrs_im[12];
c16_t r_u_v_alpha_delta[12], r_u_v_alpha_delta_dmrs[12];
for (int n = 0; n < 12; n++) {
r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
- (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha
r_u_v_alpha_delta_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha
r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
- (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of DMRS base sequence shifted by alpha
r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
+ (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha
r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_re[n]))>>15);
r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_im[n]))>>15);
// printf("symbol=%d\tr_u_v_re=%d\tr_u_v_im=%d\n",l,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n]);
c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * n))};
c16_t table = {table_5_2_2_2_2_Re[u][n], table_5_2_2_2_2_Im[u][n]};
r_u_v_alpha_delta[n] = c16mulShift(angle, table, 15);
r_u_v_alpha_delta_dmrs[n] = c16mulRealShift(r_u_v_alpha_delta[n], amp, 15);
// PUCCH sequence = DM-RS sequence multiplied by d(0)
y_n_re[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15)
- (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n)
y_n_im[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15)
+ (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n)
// printf("symbol=%d\tr_u_v_dmrs_re=%d\tr_u_v_dmrs_im=%d\n",l,r_u_v_alpha_delta_dmrs_re[n],r_u_v_alpha_delta_dmrs_im[n]);
y_n[n] = c16mulShift(r_u_v_alpha_delta[n], d, 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n",
u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]);
printf(
"\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) "
"\ty_n[n=%d]=(%d,%d)\n",
u,
v,
alpha,
n,
r_u_v_alpha_delta[n].r,
r_u_v_alpha_delta[n].i,
n,
y_n[n].r,
y_n[n].i);
#endif
}
......@@ -333,16 +301,13 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
// the index of the orthogonal cover code is from a set determined as described in [4, TS 38.211]
// and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC
// In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field
uint8_t w_index = timeDomainOCC;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime_PUCCH_1;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime_PUCCH_DMRS_1;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime0_PUCCH_1;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
uint8_t N_SF_mprime0_PUCCH_DMRS_1;
// mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping
const uint8_t w_index = timeDomainOCC;
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime
// and intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on
// number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains N_SF_mprime
// from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
// N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0
// and intra-slot hopping enabled/disabled) mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping
uint8_t mprime = 0;
if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled
......@@ -350,46 +315,74 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n",
intraSlotFrequencyHopping);
#endif
N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (PUCCH)
N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (DM-RS)
N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH)
N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS)
int N_SF_mprime_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (PUCCH)
int N_SF_mprime_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled (DM-RS)
int N_SF_mprime0_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols - 1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH)
int N_SF_mprime0_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols
- 1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS)
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
#endif
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
c16_t *zPtr = z + mprime * 12 * N_SF_mprime0_PUCCH_1 + m * 12;
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
for (int n=0; n<12 ; n++) {
z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15));
zPtr[n] = c16mulShift(table, y_n[n], 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],
z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
printf(
"\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d "
"+ %d * %d)) = (%d,%d)\n",
mprime,
m,
n,
(mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n,
table.r,
y_n[n].r,
table.i,
y_n[n].i,
table.r,
y_n[n].i,
table.i,
y_n[n].r,
zPtr[n].r,
zPtr[n].i);
#endif
}
}
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
c16_t *zDmrsPtr = z_dmrs + mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1 + m * 12;
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]};
for (int n=0; n<12 ; n++) {
z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15));
z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15));
zDmrsPtr[n] = c16mulShift(table, r_u_v_alpha_delta_dmrs[n], 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],
z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
printf(
"\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d "
"+ %d * %d)) = (%d,%d)\n",
mprime,
m,
n,
(mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n,
table.r,
r_u_v_alpha_delta_dmrs[n].r,
table.i,
r_u_v_alpha_delta_dmrs[n].i,
table.r,
r_u_v_alpha_delta_dmrs[n].i,
table.i,
r_u_v_alpha_delta_dmrs[n].r,
zDmrsPtr[n].r,
zDmrsPtr[n].i);
#endif
// printf("gNB entering l=%d\tdmrs_re=%d\tdmrs_im=%d\n",l,z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n],z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n]);
}
}
}
}
......@@ -398,10 +391,14 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n",
intraSlotFrequencyHopping);
#endif
N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
int N_SF_mprime_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
int N_SF_mprime_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
int N_SF_mprime0_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
int N_SF_mprime0_PUCCH_DMRS_1 =
table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
......@@ -409,38 +406,23 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1}
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
for (int n=0; n<12 ; n++) {
z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15));
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],
z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
}
c16_t *zPtr = z + mprime * 12 * N_SF_mprime0_PUCCH_1 + m * 12;
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
for (int n = 0; n < 12; n++)
zPtr[n] = c16mulShift(table, y_n[n], 15);
}
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
for (int n=0; n<12 ; n++) {
z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15));
z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)
+ (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15));
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],
table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],
z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
}
c16_t *zDmrsPtr = z_dmrs + mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1 + m * 12;
c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m],
table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]};
for (int n = 0; n < 12; n++)
zDmrsPtr[n] = c16mulShift(table, r_u_v_alpha_delta_dmrs[n], 15);
}
N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH)
N_SF_mprime_PUCCH_1 =
table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols - 1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH)
N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS)
}
}
......@@ -476,8 +458,7 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
}
if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1
txdataF[0][re_offset].r = z_re[i+n];
txdataF[0][re_offset].i = z_im[i+n];
txdataF[0][re_offset] = z[i + n];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i + n, re_offset,
......@@ -486,8 +467,7 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
}
if (l % 2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1
txdataF[0][re_offset].r = z_dmrs_re[i+n];
txdataF[0][re_offset].i = z_dmrs_im[i+n];
txdataF[0][re_offset] = z_dmrs[i + n];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i+n, re_offset,
......@@ -504,7 +484,6 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
}
}
static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) __attribute__((always_inline));
static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) {
uint32_t x1 = 0, x2 = 0, s = 0;
int i;
......@@ -632,7 +611,7 @@ static void nr_uci_encoding(uint64_t payload,
if (A<=11) {
// procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2)
// CRC bits are not attached, and coding small block lengths (subclause 5.3.3)
uint64_t b0= encodeSmallBlock((uint16_t*)&payload,A);
uint64_t b0 = encodeSmallBlock(payload, A);
// repetition for rate-matching up to 16 PRB
b[0] = b0 | (b0<<32);
b[1] = b[0];
......@@ -658,7 +637,7 @@ static void nr_uci_encoding(uint64_t payload,
void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int16_t amp16,
const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
......@@ -687,8 +666,8 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
* n_id = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured
* n_id = N_ID_cell if higher layer parameter not configured
*/
uint8_t *btilde = calloc(M_bit, sizeof(uint8_t));
uint8_t btilde[M_bit];
memset(btilde, 0, sizeof(btilde));
// rnti is given by the C-RNTI
uint16_t rnti=pucch_pdu->rnti;
#ifdef DEBUG_NR_PUCCH_TX
......@@ -717,41 +696,31 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
*/
//#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
// complex-valued symbol d(0)
int16_t *d_re = calloc(M_bit, sizeof(int16_t));
int16_t *d_im = calloc(M_bit, sizeof(int16_t));
c16_t d[M_bit];
memset(d, 0, sizeof(d));
uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1;
const int32_t amp = amp16;
const int16_t baseVal = (amp * ONE_OVER_SQRT2) >> 15;
c16_t qpskSymbols[4] = {{baseVal, baseVal}, {baseVal, -baseVal}, {-baseVal, baseVal}, {-baseVal, -baseVal}};
for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3
if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) {
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) {
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) {
d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) {
d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
int tmp = (btilde[2 * i] & 1) * 2 + (btilde[(2 * i) + 1] & 1);
d[i] = qpskSymbols[tmp];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]);
printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",
(btilde[2 * i] & 1),
(btilde[(2 * i) + 1] & 1),
m_symbol,
i,
d[i].r,
d[i].i);
#endif
}
/*
* Implementing TS 38.211 Subclause 6.3.2.5.3 Mapping to physical resources
*/
//int32_t *txptr;
uint32_t re_offset=0;
// int32_t *txptr;
uint32_t x1 = 0, x2 = 0, s = 0;
int i=0;
int m=0;
......@@ -773,24 +742,22 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
m = 0;
for (int rb=0; rb<pucch_pdu->prb_size; rb++) {
//startingPRB = startingPRB + rb;
if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
}
if (((rb+startingPRB) >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1)));
}
if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
}
if (((rb+startingPRB) > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6;
}
if (((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
const int halfRBs = frame_parms->N_RB_DL / 2;
const int baseRB = rb + startingPRB;
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size + 12 * baseRB;
if (nb_rb_is_even) {
if (baseRB < halfRBs) // if number RBs in bandwidth is even and current PRB is lower band
re_offset += frame_parms->first_carrier_offset;
else
re_offset -= halfRBs;
} else {
if (baseRB < halfRBs) // if number RBs in bandwidth is odd and current PRB is lower band
re_offset += frame_parms->first_carrier_offset;
else if (baseRB > halfRBs) // if number RBs in bandwidth is odd and current PRB is upper band
re_offset += -halfRBs + 6;
else
re_offset += frame_parms->first_carrier_offset;
}
//txptr = &txdataF[0][re_offset];
......@@ -800,14 +767,13 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
#endif
for (int n=0; n<12; n++) {
if ((n==6) && ((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
if (n == 6 && baseRB == halfRBs && !nb_rb_is_even) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
}
if (n%3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
((int16_t *)&txdataF[0][re_offset])[0] = d_re[i+k];
((int16_t *)&txdataF[0][re_offset])[1] = d_im[i+k];
txdataF[0][re_offset] = d[i + k];
#ifdef DEBUG_NR_PUCCH_TX
printf(
"\t [nr_generate_pucch2] (n=%d,i=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
......@@ -822,15 +788,15 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
re_offset,
l,
n,
((int16_t *)&txdataF[0][re_offset])[0],
((int16_t *)&txdataF[0][re_offset])[1]);
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
#endif
k++;
}
if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>(2*m))&1)))))>>15);
((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>((2*m)+1))&1)))))>>15);
txdataF[0][re_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((s >> (2 * m)) & 1)))));
txdataF[0][re_offset].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((s >> (2 * m + 1)) & 1)))));
m++;
#ifdef DEBUG_NR_PUCCH_TX
printf(
......@@ -846,8 +812,8 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
re_offset,
l,
n,
((int16_t *)&txdataF[0][re_offset])[0],
((int16_t *)&txdataF[0][re_offset])[1]);
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
kk++;
#endif
}
......@@ -863,15 +829,12 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
}
}
}
free(d_re);
free(d_im);
free(btilde);
}
//#if 0
void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp,
const int16_t amp16,
const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
......@@ -902,7 +865,7 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping);
#endif
}
const int32_t amp = amp16;
uint8_t nrofSymbols = pucch_pdu->nr_of_symbols;
uint16_t nrofPRB = pucch_pdu->prb_size;
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
......@@ -912,11 +875,13 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
pucch_pdu->n_bit,
pucch_pdu->format_type,
is_pi_over_2_bpsk_enabled,
nrofSymbols,nrofPRB,
nrofSymbols,
nrofPRB,
n_SF_PUCCH_s,
intraSlotFrequencyHopping,
add_dmrs,
&b[0],&M_bit);
b,
&M_bit);
/*
* Implementing TS 38.211
* Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4)
......@@ -929,7 +894,7 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
* n_id = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured
* n_id = N_ID_cell if higher layer parameter not configured
*/
uint8_t *btilde = malloc(sizeof(int8_t)*M_bit);
uint8_t btilde[M_bit];
// rnti is given by the C-RNTI
uint16_t rnti=pucch_pdu->rnti, n_id=0;
#ifdef DEBUG_NR_PUCCH_TX
......@@ -946,35 +911,24 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
* Subclause 5.1.3 QPSK
*/
// complex-valued symbol d(0)
int16_t *d_re = malloc(sizeof(int16_t)*M_bit);
int16_t *d_im = malloc(sizeof(int16_t)*M_bit);
c16_t d[M_bit];
uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1;
const int16_t baseVal = (amp * ONE_OVER_SQRT2) >> 15;
if (is_pi_over_2_bpsk_enabled == 0) {
// using QPSK if PUCCH format 3,4 and pi/2-BPSK is not configured, according to subclause 6.3.2.6.2
c16_t qpskSymbols[4] = {{baseVal, baseVal}, {-baseVal, baseVal}, {-baseVal, baseVal}, {-baseVal, -baseVal}};
for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3
if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) {
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) {
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) {
d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) {
d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
int tmp = (btilde[2 * i] & 1) * 2 + (btilde[(2 * i) + 1] & 1);
d[i] = qpskSymbols[tmp];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] modulation QPSK of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]);
printf("\t [nr_generate_pucch3_4] modulation QPSK of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",
(btilde[2 * i] & 1),
(btilde[(2 * i) + 1] & 1),
m_symbol,
i,
d[i].r,
d[i].i);
#endif
}
}
......@@ -982,30 +936,17 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
if (is_pi_over_2_bpsk_enabled == 1) {
// using PI/2-BPSK if PUCCH format 3,4 and pi/2-BPSK is configured, according to subclause 6.3.2.6.2
m_symbol = M_bit;
c16_t qpskSymbols[4] = {{baseVal, baseVal}, {-baseVal, baseVal}, {-baseVal, -baseVal}, {baseVal, -baseVal}};
for (int i=0; i<m_symbol; i++) { // PI/2-BPSK modulation subclause 5.1.1
if (((btilde[i]&1)==0) && (i%2 == 0)) {
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[i]&1)==0) && (i%2 == 1)) {
d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[i]&1)==1) && (i%2 == 0)) {
d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
if (((btilde[i]&1)==1) && (i%2 == 1)) {
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
}
int tmp = (btilde[i] & 1) * 2 + (i & 1);
d[i] = qpskSymbols[tmp];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] modulation PI/2-BPSK of bit btilde(%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[i]&1),m_symbol,i,d_re[i],d_im[i]);
printf("\t [nr_generate_pucch3_4] modulation PI/2-BPSK of bit btilde(%d), m_symbol=%d, d(%d)=(%d,%d)\n",
(btilde[i] & 1),
m_symbol,
i,
d[i].r,
d[i].i);
#endif
}
}
......@@ -1020,33 +961,27 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
// number of symbols, provided by higher layers parameters PUCCH-F0-F2-number-of-symbols or PUCCH-F1-F3-F4-number-of-symbols
// uint8_t nrofSymbols;
// complex-valued symbol d(0)
int16_t *y_n_re = malloc(sizeof(int16_t)*4*M_bit); // 4 is the maximum number n_SF_PUCCH_s, so is the maximunm size of y_n
int16_t *y_n_im = malloc(sizeof(int16_t)*4*M_bit);
c16_t y_n[4 * M_bit]; // 4 is the maximum number n_SF_PUCCH_s, so is the maximunm size of y_n
// Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1)
// k={0,..11} n={0,1,2,3}
// parameter PUCCH-F4-preDFT-OCC-index set of {0,1,2,3} -> n
uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1}
};
const uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1}};
// Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1)
// k={0,..11} n={0,1}
uint16_t table_6_3_2_6_3_1_Wn_Im[2][12] = {{0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0}
};
const uint16_t table_6_3_2_6_3_1_Wn_Im[2][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
// Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2)
// k={0,..11} n={0,1,2.3}
uint16_t table_6_3_2_6_3_2_Wn_Re[4][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0},
{1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1},
{1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}
};
const uint16_t table_6_3_2_6_3_2_Wn_Re[4][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 0, 0, 0, -1, -1, -1, 0, 0, 0},
{1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1},
{1, 1, 1, 0, 0, 0, -1, -1, -1, 0, 0, 0}};
// Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2)
// k={0,..11} n={0,1,2,3}
uint16_t table_6_3_2_6_3_2_Wn_Im[4][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0,-1,-1,-1, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1}
};
const uint16_t table_6_3_2_6_3_2_Wn_Im[4][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, -1, -1, -1, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 0, 0, 0, -1, -1, -1}};
uint8_t occ_Index = pucch_pdu->pre_dft_occ_idx; // higher layer parameter occ-Index
......@@ -1054,12 +989,17 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
if (pucch_pdu->format_type == 3) { // no block-wise spreading for format 3
for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++) {
for (int k=0; k < (12*nrofPRB); k++) {
y_n_re[l*(12*nrofPRB)+k] = d_re[l*(12*nrofPRB)+k];
y_n_im[l*(12*nrofPRB)+k] = d_im[l*(12*nrofPRB)+k];
for (int k = l * 12 * nrofPRB; k < (l + 1) * 12 * nrofPRB; k++) {
y_n[k] = d[k];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n",
l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]);
printf(
"\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d) = "
"\t(d_re=%d, d_im=%d)\n",
l,
k,
k,
d[k].r,
d[k].i);
#endif
}
}
......@@ -1070,29 +1010,37 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) {
for (int k=0; k < (12*nrofPRB); k++) {
c16_t dVal = d[l * (12 * nrofPRB / n_SF_PUCCH_s) + k % (12 * nrofPRB / n_SF_PUCCH_s)];
c16_t *yPtr = y_n + l * 12 * nrofPRB + k;
if (n_SF_PUCCH_s == 2) {
y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k])
- ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k]));
y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k])
+ ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k]));
c16_t table = {table_6_3_2_6_3_1_Wn_Re[occ_Index][k], table_6_3_2_6_3_1_Wn_Im[occ_Index][k]};
*yPtr = c16mulShift(table, dVal, 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n",
occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]);
// printf("\t\t d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]);
// printf("\t\t d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]);
// printf("\t\t table_6_3_2_6_3_1_Wn_Re[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Re[occ_Index][k]);
// printf("\t\t table_6_3_2_6_3_1_Wn_Im[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Im[occ_Index][k]);
printf(
"\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) "
" = \t(d_re=%d, d_im=%d)\n",
occ_Index,
l,
k,
l * (12 * nrofPRB) + k,
yPtr->r,
yPtr->i);
#endif
}
if (n_SF_PUCCH_s == 4) {
y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k])
- ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k]));
y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k])
+ ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k]));
c16_t table = {table_6_3_2_6_3_2_Wn_Re[occ_Index][k], table_6_3_2_6_3_2_Wn_Im[occ_Index][k]};
*yPtr = c16mulShift(table, dVal, 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n",
occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]);
printf(
"\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) "
" = \t(d_re=%d, d_im=%d)\n",
occ_Index,
l,
k,
l * 12 * nrofPRB + k,
yPtr->r,
yPtr->i);
#endif
}
}
......@@ -1102,41 +1050,28 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
/*
* Implementing Transform pre-coding subclause 6.3.2.6.4
*/
int16_t *z_re = malloc(sizeof(int16_t)*4*M_bit); // 4 is the maximum number n_SF_PUCCH_s
int16_t *z_im = malloc(sizeof(int16_t)*4*M_bit);
c16_t z[4 * M_bit]; // 4 is the maximum number n_SF_PUCCH_s
#define M_PI 3.14159265358979323846 // pi
//int16_t inv_sqrt_nrofPRBs = (int16_t)round(32767/sqrt(12*nrofPRB));
const int64_t base = round(32767 / sqrt(12 * nrofPRB));
for (int l=0; l<floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) {
for (int k=0; k<(12*nrofPRB); k++) {
z_re[l*(12*nrofPRB)+k] = 0;
z_im[l*(12*nrofPRB)+k] = 0;
// int16_t z_re_tmp[240] = {0};
// int16_t z_im_tmp[240] = {0};
for (int m=0; m<(12*nrofPRB); m++) {
//z_re[l*(12*nrofPRB)+k] = y_n_re[l*(12*nrofPRB)+m] * (int16_t)(round(32767*cos((2*M_PI*m*k)/(12*nrofPRB))));
// z_re_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
// + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
// z_im_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
// - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
z_re[l*(12*nrofPRB)+k] = z_re[l*(12*nrofPRB)+k]
+ (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
+ (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
z_im[l*(12*nrofPRB)+k] = z_im[l*(12*nrofPRB)+k]
+ (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
- (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
#ifdef DEBUG_NR_PUCCH_TX
// printf("\t\t z_re_tmp[%d] = %d\n",m,z_re_tmp[m]);
// printf("\t\t z_im_tmp[%d] = %d\n",m,z_im_tmp[m]);
// printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k,m)=(%d,%d,%d)\tz(%d) = \t(%d, %d)\n",
// l,k,m,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]);
#endif
c16_t *yPtr = y_n + l * 12 * nrofPRB;
c16_t *zPtr = z + l * 12 * nrofPRB + k;
*zPtr = (c16_t){0};
for (int m = l * 12 * nrofPRB; m < (l + 1) * 12 * nrofPRB; m++) {
const c16_t angle = {lround(32767 * cos(2 * M_PI * m * k / (12 * nrofPRB))),
lround(32767 * sin(2 * M_PI * m * k / (12 * nrofPRB)))};
c16_t tmp = c16mulShift(yPtr[m], angle, 15);
csum(*zPtr, *zPtr, c16mulRealShift(tmp, base, 15));
}
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k)=(%d,%d)\tz(%d) = \t(%d, %d)\n",
l,k,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]);
l,
k,
l * (12 * nrofPRB) + k,
zPtr->r,
zPtr->i);
#endif
}
}
......@@ -1157,10 +1092,11 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
//uint8_t lprime = startingSymbolIndex;
// m0 is the cyclic shift index calculated depending on the Orthogonal sequence index n, according to table 6.4.1.3.3.1-1 from TS 38.211 subclause 6.4.1.3.3.1
uint8_t m0;
uint8_t m0 = 0;
uint8_t mcs=0;
if (pucch_pdu->format_type == 3) m0 = 0;
if (pucch_pdu->format_type == 3)
m0 = 0;
if (pucch_pdu->format_type == 4) {
if (n_SF_PUCCH_s == 2) {
......@@ -1173,17 +1109,9 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
}
double alpha;
uint8_t N_ZC = 12*nrofPRB;
int16_t *r_u_v_base_re = malloc(sizeof(int16_t)*12*nrofPRB);
int16_t *r_u_v_base_im = malloc(sizeof(int16_t)*12*nrofPRB);
//int16_t *r_u_v_alpha_delta_re = malloc(sizeof(int16_t)*12*nrofPRB);
//int16_t *r_u_v_alpha_delta_im = malloc(sizeof(int16_t)*12*nrofPRB);
// Next we proceed to mapping to physical resources according to TS 38.211, subclause 6.3.2.6.5 dor PUCCH formats 3 and 4 and subclause 6.4.1.3.3.2 for DM-RS
//int32_t *txptr;
uint32_t re_offset=0;
//uint32_t x1, x2, s=0;
// intraSlotFrequencyHopping
// uint8_t intraSlotFrequencyHopping = 0;
int N_ZC = 12 * nrofPRB;
c16_t r_u_v_base[N_ZC];
uint32_t re_offset = 0;
uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = {
{(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4
{1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5
......@@ -1197,10 +1125,11 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13
{0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14
};
uint16_t k=0;
int k = 0;
for (int l=0; l<nrofSymbols; l++) {
if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop
if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols / 2)))
n_hop = 1; // n_hop = 1 for second hop
pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value
......@@ -1217,33 +1146,43 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
q = ((uint8_t)floor(2*q_base)%2 == 0 ? q+v : q-v);
for (int n=0; n<(12*nrofPRB); n++) {
r_u_v_base_re[n] = (int16_t)(((int32_t)amp*(int16_t)(32767*cos(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15);
r_u_v_base_im[n] = -(int16_t)(((int32_t)amp*(int16_t)(32767*sin(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15);
const double tmp = M_PI * q * (n % N_ZC) * ((n % N_ZC) + 1) / N_ZC;
r_u_v_base[n].r = lround(amp * 32767 * cos(tmp)) >> 15;
r_u_v_base[n].i = -lround(amp * 32767 * sin(tmp)) >> 15;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d >= 3: r_u_v_base[n=%d]=(%d,%d)\n",
nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]);
nrofPRB,
n,
r_u_v_base[n].r,
r_u_v_base[n].i);
#endif
}
}
if (nrofPRB == 2) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-4) applies
for (int n=0; n<(12*nrofPRB); n++) {
r_u_v_base_re[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Re[u][n])>>15);
r_u_v_base_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Im[u][n])>>15);
for (int n = 0; n < 12 * nrofPRB; n++) {
c16_t table = {table_5_2_2_2_4_Re[u][n], table_5_2_2_2_4_Im[u][n]};
r_u_v_base[n] = c16mulRealShift(table, amp, 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 2: r_u_v_base[n=%d]=(%d,%d)\n",
nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]);
nrofPRB,
n,
r_u_v_base[n].r,
r_u_v_base[n].i);
#endif
}
}
if (nrofPRB == 1) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-2) applies
for (int n=0; n<(12*nrofPRB); n++) {
r_u_v_base_re[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Re[u][n])>>15);
r_u_v_base_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Im[u][n])>>15);
for (int n = 0; n < 12 * nrofPRB; n++) {
c16_t table = {table_5_2_2_2_2_Re[u][n], table_5_2_2_2_2_Im[u][n]};
r_u_v_base[n] = c16mulRealShift(table, amp, 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 1: r_u_v_base[n=%d]=(%d,%d)\n",
nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]);
nrofPRB,
n,
r_u_v_base[n].r,
r_u_v_base[n].i);
#endif
}
}
......@@ -1253,76 +1192,102 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,startingSymbolIndex,nr_slot_tx);
for (int rb=0; rb<nrofPRB; rb++) {
const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
const int halfRBs = frame_parms->N_RB_DL / 2;
const int baseRB = rb + startingPRB;
if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB
startingPRB = startingPRB + pucch_pdu->second_hop_prb;
}
re_offset = ((l + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
//startingPRB = startingPRB + rb;
if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
if (nb_rb_is_even) {
if (baseRB < halfRBs) { // if number RBs in bandwidth is even and current PRB is lower band
re_offset += 12 * baseRB + frame_parms->first_carrier_offset;
#ifdef DEBUG_NR_PUCCH_TX
printf("1 ");
#endif
}
}
if (((rb+startingPRB) >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1)));
else { // if number RBs in bandwidth is even and current PRB is upper band
re_offset += 12 * (baseRB - halfRBs);
#ifdef DEBUG_NR_PUCCH_TX
printf("2 ");
#endif
}
if (((rb+startingPRB) < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
}
} else {
if (baseRB < halfRBs) { // if number RBs in bandwidth is odd and current PRB is lower band
re_offset += 12 * baseRB + frame_parms->first_carrier_offset;
#ifdef DEBUG_NR_PUCCH_TX
printf("3 ");
#endif
}
if (((rb+startingPRB) > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6;
} else if (baseRB > halfRBs) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset += 12 * (baseRB - halfRBs) + 6;
#ifdef DEBUG_NR_PUCCH_TX
printf("4 ");
#endif
}
if (((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
} else { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset += 12 * baseRB + frame_parms->first_carrier_offset;
#ifdef DEBUG_NR_PUCCH_TX
printf("5 ");
#endif
}
}
#ifdef DEBUG_NR_PUCCH_TX
printf("re_offset=%u,(rb+startingPRB)=%d\n",re_offset,(rb+startingPRB));
printf("re_offset=%u,baseRB=%d\n", re_offset, baseRB);
#endif
//txptr = &txdataF[0][re_offset];
for (int n=0; n<12; n++) {
if ((n==6) && ((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
if ((n == 6) && baseRB == halfRBs && !nb_rb_is_even) {
// if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second
// half PRB)
re_offset = ((l + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
}
if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
((int16_t *)&txdataF[0][re_offset])[0] = z_re[n+k];
((int16_t *)&txdataF[0][re_offset])[1] = z_im[n+k];
txdataF[0][re_offset] = z[n + k];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(z(l=%d,n=%d)=(%d,%d))\n",
l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset,
l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
printf(
"\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
"\tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(z(l=%d,n=%d)=(%d,%d))\n",
l,
rb,
n,
k,
amp,
frame_parms->ofdm_symbol_size,
frame_parms->N_RB_DL,
frame_parms->first_carrier_offset,
n + k,
re_offset,
l,
n,
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
#endif
}
if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15)
- (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15));
((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)
+ (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15));
const c16_t angle = {lround(32767 * cos(alpha * ((n + j) % N_ZC))), lround(32767 * sin(alpha * ((n + j) % N_ZC)))};
txdataF[0][re_offset] = c16mulShift(angle, r_u_v_base[n + j], 15);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(r_u_v(l=%d,n=%d)=(%d,%d))\n",
l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset,
l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
printf(
"\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
"\tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(r_u_v(l=%d,n=%d)=(%d,%d))\n",
l,
rb,
n,
j,
amp,
frame_parms->ofdm_symbol_size,
frame_parms->N_RB_DL,
frame_parms->first_carrier_offset,
n + j,
re_offset,
l,
n,
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
#endif
}
......@@ -1334,7 +1299,4 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) j+=12;
}
}
free(z_re);
free(z_im);
free(btilde);
}
......@@ -215,7 +215,8 @@ extern "C" {
{
return (c16_t){.r = (int16_t)((a.r * b) >> Shift), .i = (int16_t)((a.i * b) >> Shift)};
}
__attribute__((always_inline)) inline c16_t c16divShift(const c16_t a, const c16_t b, const int Shift) {
__attribute__((always_inline)) inline c16_t c16MulConjShift(const c16_t a, const c16_t b, const int Shift)
{
return (c16_t) {
.r = (int16_t)((a.r * b.r + a.i * b.i) >> Shift),
.i = (int16_t)((a.r * b.i - a.i * b.r) >> Shift)
......
......@@ -83,64 +83,7 @@ binary_search_float_nr(
return first;
}
/*
void nr_generate_pucch0(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
int16_t amp,
int nr_slot_tx,
uint8_t mcs,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint16_t startingPRB);
void nr_generate_pucch1(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint64_t payload,
int16_t amp,
int nr_slot_tx,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint16_t startingPRB,
uint16_t startingPRB_intraSlotHopping,
uint8_t timeDomainOCC,
uint8_t nr_bit);
void nr_generate_pucch2(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint64_t payload,
int16_t amp,
int nr_slot_tx,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint8_t nrofPRB,
uint16_t startingPRB,
uint8_t nr_bit);
void nr_generate_pucch3_4(int32_t **txdataF,
NR_DL_FRAME_PARMS *frame_parms,
pucch_format_nr_t fmt,
PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
uint64_t payload,
int16_t amp,
int nr_slot_tx,
uint8_t nrofSymbols,
uint8_t startingSymbolIndex,
uint8_t nrofPRB,
uint16_t startingPRB,
uint8_t nr_bit,
uint8_t occ_length_format4,
uint8_t occ_index_format4);
*/
/**************** variables **************************************/
/**************** functions **************************************/
//extern uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id);
//extern uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id);
/*******************************************************************
*
* NAME : pucch_procedures_ue_nr
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment