Commit f050cdf4 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/improve-pucch-codec' into integration_2024_w01

parents ad234a03 18919576
...@@ -8,144 +8,152 @@ ...@@ -8,144 +8,152 @@
configmodule_interface_t *uniqCfg = NULL; configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
time_stats_t timeEncoder,timeDecoder; time_stats_t timeEncoder, timeDecoder;
opp_enabled=1; opp_enabled = 1;
reset_meas(&timeEncoder); reset_meas(&timeEncoder);
reset_meas(&timeDecoder); reset_meas(&timeDecoder);
randominit(0); randominit(0);
int arguments, iterations = 1000, messageLength = 11; int arguments, iterations = 1000, messageLength = 11;
//int matlabDebug = 0; // int matlabDebug = 0;
uint32_t testInput, encoderOutput, codingDifference, nBitError=0, blockErrorState = 0, blockErrorCumulative=0, bitErrorCumulative=0; uint32_t testInput, encoderOutput, codingDifference, nBitError = 0, blockErrorState = 0, blockErrorCumulative = 0,
uint16_t estimatedOutput; bitErrorCumulative = 0;
double SNRstart = -20.0, SNRstop = 5.0, SNRinc= 0.5; //dB uint16_t estimatedOutput;
double SNR, SNR_lin, sigma; double SNRstart = -20.0, SNRstop = 5.0, SNRinc = 0.5; // dB
double modulatedInput[NR_SMALL_BLOCK_CODED_BITS], channelOutput[NR_SMALL_BLOCK_CODED_BITS]; double SNR, SNR_lin, sigma;
//int16_t channelOutput_int16[NR_SMALL_BLOCK_CODED_BITS]; double modulatedInput[NR_SMALL_BLOCK_CODED_BITS], channelOutput[NR_SMALL_BLOCK_CODED_BITS];
int8_t channelOutput_int8[NR_SMALL_BLOCK_CODED_BITS]; // int16_t channelOutput_int16[NR_SMALL_BLOCK_CODED_BITS];
unsigned char qbits=8; 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) while ((arguments = getopt(argc, argv, "s:d:f:l:i:mhg")) != -1)
{ switch (arguments) {
case 's': case 's':
SNRstart = atof(optarg); SNRstart = atof(optarg);
break; break;
case 'd': case 'd':
SNRinc = atof(optarg); SNRinc = atof(optarg);
break; break;
case 'f': case 'f':
SNRstop = atof(optarg); SNRstop = atof(optarg);
break; break;
case 'l': case 'l':
messageLength = atoi(optarg); messageLength = atoi(optarg);
break; break;
case 'i': case 'i':
iterations = atoi(optarg); iterations = atoi(optarg);
break; break;
/*case 'm': /*case 'm':
matlabDebug = 1; matlabDebug = 1;
//#define DEBUG_POLAR_MATLAB //#define DEBUG_POLAR_MATLAB
break;*/ break;*/
case 'g': case 'g':
iterations = 1; iterations = 1;
SNRstart = -6.0; SNRstart = -6.0;
SNRstop = -6.0; SNRstop = -6.0;
messageLength = 11; messageLength = 11;
break; break;
case 'h': 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 -m Matlab Debug\n");
printf("./smallblocktest -s SNRstart -d SNRinc -f SNRstop -l messageLength -i iterations\n"); printf("./smallblocktest -s SNRstart -d SNRinc -f SNRstop -l messageLength -i iterations\n");
exit(-1); exit(-1);
default: default:
perror("[smallblocktest.c] Problem at argument parsing with getopt"); perror("[smallblocktest.c] Problem at argument parsing with getopt");
exit(-1); exit(-1);
} }
uint16_t mask = 0x07ff >> (11 - messageLength);
uint16_t mask = 0x07ff >> (11-messageLength); for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) {
for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) { printf("SNR %f\n", SNR);
printf("SNR %f\n",SNR); SNR_lin = pow(10, SNR / 10.0);
SNR_lin = pow(10, SNR/10.0); sigma = 1.0 / sqrt(SNR_lin);
sigma = 1.0/sqrt(SNR_lin);
for (int itr = 1; itr <= iterations; itr++) {
for (int itr = 1; itr <= iterations; itr++) { // Generate random test input of length "messageLength"
testInput = 0;
//Generate random test input of length "messageLength" for (int i = 1; i < messageLength; i++) {
testInput = 0; testInput |= (((uint32_t)(rand() % 2)) & 1);
for (int i = 1; i < messageLength; i++) { testInput <<= 1;
testInput |= ( ((uint32_t) (rand()%2)) &1); }
testInput<<=1; testInput |= (((uint32_t)(rand() % 2)) & 1);
} // Encoding
testInput |= ( ((uint32_t) (rand()%2)) &1); start_meas(&timeEncoder);
//Encoding encoderOutput = encodeSmallBlock(testInput, messageLength);
start_meas(&timeEncoder); stop_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
for (int i=0; i<NR_SMALL_BLOCK_CODED_BITS; i++) { if ((encoderOutput >> i) & 1) {
//BPSK modulation modulatedInput[i] = -1;
if ((encoderOutput>>i) & 1 ) { } else {
modulatedInput[i]=-1; modulatedInput[i] = 1;
} else { }
modulatedInput[i]=1;
} // AWGN
channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0, 1.0) * (1 / sqrt(SNR_lin)));
//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);
//Quantization }
channelOutput_int8[i] = quantize(sigma/16.0, channelOutput[i], qbits);
} // Decoding
start_meas(&timeDecoder);
//Decoding estimatedOutput = decodeSmallBlock(channelOutput_int8, (uint8_t)messageLength);
start_meas(&timeDecoder); stop_meas(&timeDecoder);
estimatedOutput = decodeSmallBlock(channelOutput_int8, (uint8_t)messageLength);
stop_meas(&timeDecoder);
#ifdef DEBUG_SMALLBLOCKTEST #ifdef DEBUG_SMALLBLOCKTEST
printf("[smallblocktest] Input = 0x%x, Output = 0x%x, DecoderOutput = 0x%x\n", testInput, encoderOutput, estimatedOutput); printf("[smallblocktest] Input = 0x%x, Output = 0x%x, DecoderOutput = 0x%x\n", testInput, encoderOutput, estimatedOutput);
for (int i=0;i<32;i++) 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[%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 #endif
//Error Calculation // Error Calculation
estimatedOutput &= mask; estimatedOutput &= mask;
codingDifference = ((uint32_t)estimatedOutput) ^ testInput; // Count the # of 1's in codingDifference by Brian Kernighan’s algorithm. codingDifference =
((uint32_t)estimatedOutput) ^ testInput; // Count the # of 1's in codingDifference by Brian Kernighan’s algorithm.
for (nBitError = 0; codingDifference; nBitError++) for (nBitError = 0; codingDifference; nBitError++)
codingDifference &= codingDifference - 1; codingDifference &= codingDifference - 1;
blockErrorState = (nBitError > 0) ? 1 : 0; blockErrorState = (nBitError > 0) ? 1 : 0;
blockErrorCumulative+=blockErrorState; blockErrorCumulative += blockErrorState;
bitErrorCumulative+=nBitError; bitErrorCumulative += nBitError;
nBitError = 0; blockErrorState = 0; nBitError = 0;
} blockErrorState = 0;
}
//Error statistics for the SNR; iteration times are in nanoseconds and microseconds, respectively. // 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", printf("[smallblocktest] SNR=%+7.3f, BER=%9.6f, BLER=%9.6f, t_Encoder=%9.3fns, t_Decoder=%7.3fus\n",
SNR, SNR,
((double)bitErrorCumulative / (iterations*messageLength)), ((double)bitErrorCumulative / (iterations * messageLength)),
((double)blockErrorCumulative/iterations), ((double)blockErrorCumulative / iterations),
((double)timeEncoder.diff/timeEncoder.trials)/(get_cpu_freq_GHz()), ((double)timeEncoder.diff / timeEncoder.trials) / (get_cpu_freq_GHz()),
((double)timeDecoder.diff/timeDecoder.trials)/(get_cpu_freq_GHz()*1000.0)); ((double)timeDecoder.diff / timeDecoder.trials) / (get_cpu_freq_GHz() * 1000.0));
blockErrorCumulative=0; blockErrorCumulative = 0;
bitErrorCumulative=0; bitErrorCumulative = 0;
} }
print_meas(&timeEncoder, "smallblock_encoder", NULL, NULL); print_meas(&timeEncoder, "smallblock_encoder", NULL, NULL);
print_meas(&timeDecoder, "smallblock_decoder", NULL, NULL); print_meas(&timeDecoder, "smallblock_decoder", NULL, NULL);
return (0); return (0);
} }
...@@ -34,11 +34,12 @@ ...@@ -34,11 +34,12 @@
//input = [0 ... 0 c_K-1 ... c_2 c_1 c_0] //input = [0 ... 0 c_K-1 ... c_2 c_1 c_0]
//output = [d_31 d_30 ... d_2 d_1 d_0] //output = [d_31 d_30 ... d_2 d_1 d_0]
uint32_t encodeSmallBlock(uint16_t *in, uint8_t len){ uint32_t encodeSmallBlock(int in, int len)
uint32_t out = 0; {
for (uint16_t i=0; i<len; i++) uint32_t out = 0;
if ((*in & (1<<i)) > 0) for (int i = 0; i < len; i++)
out^=nrSmallBlockBasis[i]; if ((in & (1 << i)) > 0)
out ^= nrSmallBlockBasis[i];
return out; return out;
} }
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#define L1d_CLS 64 #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); uint16_t decodeSmallBlock(int8_t *in, uint8_t len);
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping, void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id, uint32_t n_id,
uint8_t n_hop, int n_hop,
int nr_slot_tx, int nr_slot_tx,
uint8_t *u, uint8_t *u,
uint8_t *v); uint8_t *v);
......
...@@ -32,12 +32,13 @@ ...@@ -32,12 +32,13 @@
#include "nr_dci.h" #include "nr_dci.h"
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping, void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping,
uint32_t n_id, uint32_t n_id,
uint8_t n_hop, int n_hop,
int nr_slot_tx, int nr_slot_tx,
uint8_t *u, uint8_t *u,
uint8_t *v) { uint8_t *v)
{
/* /*
* Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping
* The following variables are set by higher layers: * The following variables are set by higher layers:
......
...@@ -158,8 +158,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -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; 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, 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", "Either bit_len_harq (%d) or sr_flag (%d) must be > 0\n",
pucch_pdu->bit_len_harq,pucch_pdu->sr_flag); pucch_pdu->bit_len_harq,
pucch_pdu->sr_flag);
NR_gNB_PHY_STATS_t *phy_stats = get_phy_stats(gNB, pucch_pdu->rnti); 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"); AssertFatal(phy_stats != NULL, "phy_stats shouldn't be NULL\n");
...@@ -188,43 +189,19 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -188,43 +189,19 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
int cs_ind = get_pucch0_cs_lut_index(gNB,pucch_pdu); int cs_ind = get_pucch0_cs_lut_index(gNB,pucch_pdu);
/* /*
* Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation * 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 * 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: * 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 * 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 * 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}; 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); pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1);
nr_group_sequence_hopping(pucch_GroupHopping, // the value of u,v (delta always 0 for PUCCH) has to be calculated according
pucch_pdu->hopping_id, // to TS 38.211 Subclause 6.3.2.2.1
0, uint8_t u[2] = {0}, v[2] = {0};
slot, nr_group_sequence_hopping(pucch_GroupHopping, pucch_pdu->hopping_id, 0, slot, u,
&u[0], v); // calculating u and v value first hop
&v[0]); // calculating u and v value first hop
LOG_D(PHY,"pucch0: u %d, v %d\n",u[0],v[0]); LOG_D(PHY,"pucch0: u %d, v %d\n",u[0],v[0]);
if (pucch_pdu->freq_hop_flag == 1) { if (pucch_pdu->freq_hop_flag == 1) {
...@@ -253,10 +230,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -253,10 +230,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uint8_t index=0; uint8_t index=0;
int nb_re_pucch = 12*pucch_pdu->prb_size; // prb size is 1 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]; int signal_energy = 0, signal_energy_ant0 = 0;
memset(rp, 0, sizeof(rp));
int32_t *tmp_rp = NULL;
int signal_energy = 0;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) { for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
uint8_t l2 = l + pucch_pdu->start_symbol_index; uint8_t l2 = l + pucch_pdu->start_symbol_index;
...@@ -266,39 +240,38 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -266,39 +240,38 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
re_offset[l]-=frame_parms->ofdm_symbol_size; re_offset[l]-=frame_parms->ofdm_symbol_size;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) { 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) { if(re_offset[l] + nb_re_pucch > frame_parms->ofdm_symbol_size) {
int neg_length = frame_parms->ofdm_symbol_size-re_offset[l]; int neg_length = frame_parms->ofdm_symbol_size-re_offset[l];
int pos_length = nb_re_pucch-neg_length; 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(rp, &tmp_rp[re_offset[l]], neg_length * sizeof(*tmp_rp));
memcpy((void*)&rp[aa][l][neg_length],(void*)tmp_rp,pos_length*sizeof(int32_t)); memcpy(&rp[neg_length], tmp_rp, pos_length * sizeof(*tmp_rp));
} }
else else
memcpy((void*)rp[aa][l],(void*)&tmp_rp[re_offset[l]],nb_re_pucch*sizeof(int32_t)); memcpy(rp, &tmp_rp[re_offset[l]], nb_re_pucch * sizeof(*tmp_rp));
c16_t *r = (c16_t*)&rp[aa][l];
for (n=0;n<nb_re_pucch;n++) { for (int 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].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] * r[n].i - (int32_t)x_im[l][n] * r[n].r; 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 #ifdef DEBUG_NR_PUCCH_RX
printf("x (%d,%d), r%d.%d (%d,%d), xr (%lld,%lld)\n", 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);
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);
#endif #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); signal_energy /= (pucch_pdu->nr_of_symbols * frame_parms->nb_antennas_rx);
int pucch_power_dBtimes10 = 10 * dB_fixed(signal_energy); int pucch_power_dBtimes10 = 10 * dB_fixed(signal_energy);
//int32_t no_corr = 0; //int32_t no_corr = 0;
int seq_index = 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]; c64_t corr[frame_parms->nb_antennas_rx][2];
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) { for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
for (int l=0;l<pucch_pdu->nr_of_symbols;l++) { for (int l=0;l<pucch_pdu->nr_of_symbols;l++) {
...@@ -309,7 +282,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -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]); printf("PUCCH symbol %d seq %d, seq_index %d, mcs %d\n",l,i,seq_index,mcs[i]);
#endif #endif
corr[aa][l]=(c64_t){0}; 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].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]; 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, ...@@ -321,30 +294,32 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
mcs[i],seq_index,corr[0][0].r,corr[0][0].i, mcs[i],seq_index,corr[0][0].r,corr[0][0].i,
10*log10((double)squaredMod(corr[0][0]))); 10*log10((double)squaredMod(corr[0][0])));
if (pucch_pdu->nr_of_symbols==2) if (pucch_pdu->nr_of_symbols==2)
LOG_D(PHY,"PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n", LOG_D(PHY,
mcs[i],seq_index,corr[0][1].r,corr[0][1].i, "PUCCH 2nd symbol IDFT[%d/%d] = (%ld,%ld)=>%f\n",
10*log10((double)squaredMod(corr[0][1]))); 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->freq_hop_flag == 0) {
if (pucch_pdu->nr_of_symbols==1) {// non-coherent correlation if (pucch_pdu->nr_of_symbols == 1) { // non-coherent correlation
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]);
temp+=squaredMod(corr[aa][0]); } else {
} else { for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) {
temp=0; c64_t corr2;
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) { csum(corr2, corr[aa][0], corr[aa][1]);
c64_t corr2; // coherent combining of 2 symbols and then complex modulus for
csum(corr2, corr[aa][0], corr[aa][1]); // single-frequency case
// coherent combining of 2 symbols and then complex modulus for single-frequency case temp += corr2.r * corr2.r + corr2.i * corr2.i;
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 // 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]); temp += squaredMod(corr[aa][0]) + squaredMod(corr[aa][1]);
} }
else AssertFatal(1==0,"shouldn't happen\n");
if (temp>xrtmag) { if (temp>xrtmag) {
xrtmag_next = xrtmag; xrtmag_next = xrtmag;
...@@ -356,11 +331,11 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -356,11 +331,11 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) { for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
temp2 += squaredMod(corr[aa][0]); temp2 += squaredMod(corr[aa][0]);
if (pucch_pdu->nr_of_symbols==2) 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); uci_stats->current_pucch0_stat0= dB_fixed64(temp2);
if ( pucch_pdu->nr_of_symbols==2) 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) else if (temp>xrtmag_next)
xrtmag_next = temp; xrtmag_next = temp;
...@@ -377,28 +352,30 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -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]]; 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); 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) // estimate CQI for MAC (from antenna port 0 only)
int max_n0 = max(gNB->measurements.n0_subband_power_tot_dB[prb_offset[0]], int max_n0 =
gNB->measurements.n0_subband_power_tot_dB[prb_offset[1]]); 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; const int SNRtimes10 = pucch_power_dBtimes10 - (10 * max_n0);
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 cqi; int cqi;
if (SNRtimes10 < -640) cqi=0; if (SNRtimes10 < -640)
else if (SNRtimes10 > 635) cqi=255; cqi = 0;
else cqi=(640+SNRtimes10)/5; else if (SNRtimes10 > 635)
cqi = 255;
else
cqi = (640 + SNRtimes10) / 5;
uci_stats->pucch0_thres = gNB->pucch0_thres; /* + (10*max_n0);*/ uci_stats->pucch0_thres = gNB->pucch0_thres; /* + (10*max_n0);*/
bool no_conf=false; bool no_conf=false;
if (nr_sequences>1) { if (nr_sequences>1) {
if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 < gNB->pucch0_thres) { if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 < gNB->pucch0_thres) {
no_conf=true; no_conf=true;
LOG_D(PHY,"%d.%d PUCCH bad confidence: %d threshold, %d, %d, %d\n", LOG_D(PHY,
frame, slot, "%d.%d PUCCH bad confidence: %d threshold, %d, %d, %d\n",
uci_stats->pucch0_thres, frame,
SNRtimes10, slot,
xrtmag_dBtimes10, uci_stats->pucch0_thres,
xrtmag_next_dBtimes10); SNRtimes10,
xrtmag_dBtimes10,
xrtmag_next_dBtimes10);
} }
} }
gNB->bad_pucch += no_conf; gNB->bad_pucch += no_conf;
...@@ -408,7 +385,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -408,7 +385,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_pdu->rnti = pucch_pdu->rnti; uci_pdu->rnti = pucch_pdu->rnti;
uci_pdu->ul_cqi = cqi; uci_pdu->ul_cqi = cqi;
uci_pdu->timing_advance = 0xffff; // currently not valid 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) { if (pucch_pdu->bit_len_harq==0) {
uci_pdu->sr.sr_confidence_level = SNRtimes10 < uci_stats->pucch0_thres; uci_pdu->sr.sr_confidence_level = SNRtimes10 < uci_stats->pucch0_thres;
...@@ -426,7 +403,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -426,7 +403,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_pdu->harq.harq_confidence_level = no_conf; uci_pdu->harq.harq_confidence_level = no_conf;
uci_pdu->harq.harq_list[0].harq_value = !(index&0x01); uci_pdu->harq.harq_list[0].harq_value = !(index&0x01);
LOG_D(PHY, 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", "cqi %d, SNRtimes10 %d, energy %f\n",
frame, frame,
slot, slot,
...@@ -441,7 +420,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -441,7 +420,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_stats->pucch0_thres, uci_stats->pucch0_thres,
cqi, cqi,
SNRtimes10, SNRtimes10,
10 * log10((double)sigenergy)); 10 * log10((double)signal_energy_ant0));
if (pucch_pdu->sr_flag == 1) { if (pucch_pdu->sr_flag == 1) {
uci_pdu->sr.sr_indication = (index>1); uci_pdu->sr.sr_indication = (index>1);
...@@ -488,10 +467,10 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, ...@@ -488,10 +467,10 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
} }
//*****************************************************************// //*****************************************************************//
void nr_decode_pucch1(c16_t **rxdataF, void nr_decode_pucch1(c16_t **rxdataF,
pucch_GroupHopping_t pucch_GroupHopping, pucch_GroupHopping_t pucch_GroupHopping,
uint32_t n_id, // hoppingID higher layer parameter uint32_t n_id, // hoppingID higher layer parameter
uint64_t *payload, uint64_t *payload,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
int16_t amp, int16_t amp,
int nr_tti_tx, int nr_tti_tx,
uint8_t m0, uint8_t m0,
...@@ -503,33 +482,33 @@ void nr_decode_pucch1(c16_t **rxdataF, ...@@ -503,33 +482,33 @@ void nr_decode_pucch1(c16_t **rxdataF,
uint8_t nr_bit) uint8_t nr_bit)
{ {
#ifdef DEBUG_NR_PUCCH_RX #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", printf(
nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); "\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 #endif
/* /*
* Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation * 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; const 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 ;
// 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] // 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 // 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_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. // 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: * 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 * 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, ...@@ -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 // 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; 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, // 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, // regardless of whether the frequency-hop distance is zero or not,
// otherwise no intra-slot frequency hopping shall be assumed // otherwise no intra-slot frequency hopping shall be assumed
//uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers
uint8_t intraSlotFrequencyHopping = 0; const bool intraSlotFrequencyHopping = startingPRB != startingPRB_intraSlotHopping;
if (startingPRB != startingPRB_intraSlotHopping) {
intraSlotFrequencyHopping=1;
}
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping); printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping);
...@@ -562,119 +532,110 @@ void nr_decode_pucch1(c16_t **rxdataF, ...@@ -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 * 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 #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; c16_t z_rx[MAX_SIZE_Z] = {0};
int16_t z_dmrs_re_rx[MAX_SIZE_Z],z_dmrs_im_rx[MAX_SIZE_Z],z_dmrs_re_temp,z_dmrs_im_temp; c16_t z_dmrs_rx[MAX_SIZE_Z] = {0};
memset(z_re_rx,0,MAX_SIZE_Z*sizeof(int16_t)); const int half_nb_rb_dl = frame_parms->N_RB_DL >> 1;
memset(z_im_rx,0,MAX_SIZE_Z*sizeof(int16_t)); const bool nb_rb_is_even = (frame_parms->N_RB_DL & 1) == 0;
memset(z_dmrs_re_rx,0,MAX_SIZE_Z*sizeof(int16_t)); for (int l = 0; l < nrofSymbols; l++) { // extracting data and dmrs from rxdataF
memset(z_dmrs_im_rx,0,MAX_SIZE_Z*sizeof(int16_t)); if (intraSlotFrequencyHopping && (l < floor(nrofSymbols / 2))) { // intra-slot hopping enabled, we need
int l=0; // to calculate new offset PRB
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
startingPRB = startingPRB + startingPRB_intraSlotHopping; startingPRB = startingPRB + startingPRB_intraSlotHopping;
} }
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size;
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 (nb_rb_is_even) {
} if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is even and
// current PRB is lower band
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 += 12 * startingPRB + frame_parms->first_carrier_offset;
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))); 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 < (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 if (startingPRB < half_nb_rb_dl) // if number RBs in bandwidth is odd and
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; // 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
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 // and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6; 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;
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;
} }
for (int n=0; n<12; n++) { 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) // 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); 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 if (l % 2 == 1) // mapping PUCCH or DM-RS according to TS38.211 subclause 6.4.1.3.1
z_re_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[0]; z_rx[current_subcarrier] = rxdataF[0][soffset + re_offset];
z_im_rx[i+n] = ((int16_t *)&rxdataF[0][soffset+re_offset])[1]; else
#ifdef DEBUG_NR_PUCCH_RX z_dmrs_rx[current_subcarrier] = rxdataF[0][soffset + re_offset];
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]);
#ifdef DEBUG_NR_PUCCH_RX #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", printf(
amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, "\t [nr_generate_pucch1] mapping %s to RE \t amp=%d "
l,n,((int16_t *)&rxdataF[0][soffset+re_offset])[0],((int16_t *)&rxdataF[0][soffset+re_offset])[1]); "\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 #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++; 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]; cd_t y_n[12] = {0}, y1_n[12] = {0};
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));
//generating transmitted sequence and dmrs //generating transmitted sequence and dmrs
for (l=0; l<nrofSymbols; l++) { for (int l = 0; l < nrofSymbols; l++) {
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n", printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n",
l,lprime); l,lprime);
#endif #endif
// y_n contains the complex value d multiplied by the sequence r_u_v // 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 #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", 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); n_hop,nr_tti_tx);
#endif #endif
nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value 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 for (int n=0; n<12; n++) { // generating low papr sequences
if(l%2==1){ const c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * 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) const c16_t table = {table_5_2_2_2_2_Re[u][n], table_5_2_2_2_2_Im[u][n]};
- (((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 if (l % 2 == 1)
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) r_u_v_alpha_delta[n] = c16mulShift(angle, table, 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[n] = c16mulRealShift(c16mulShift(angle, table, 15), amp, 15);
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) */
#ifdef DEBUG_NR_PUCCH_RX #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", printf(
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]); "\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 #endif
} }
/* /*
...@@ -691,298 +652,208 @@ void nr_decode_pucch1(c16_t **rxdataF, ...@@ -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] // 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 // and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC
// In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field // In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field
uint8_t w_index = timeDomainOCC; const int 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) if (intraSlotFrequencyHopping == false) { // intra-slot hopping 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
#ifdef DEBUG_NR_PUCCH_RX #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", printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n",
intraSlotFrequencyHopping); intraSlotFrequencyHopping);
#endif #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) // mprime is 0 in this not hopping case
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_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1
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) // (depending on number of PUCCH symbols nrofSymbols, mprime and
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) // 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 #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", 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); 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 #endif
if(l%2==1){ if(l%2==1){
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { 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)){ c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
for (int n=0; n<12 ; n++) { table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
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) if (l / 2 == m) {
+ (((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); for (int n = 0; n < 12; n++) {
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) c16_t *zPtr = z_rx + m * 12 + n;
- (((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); *zPtr = c16MulConjShift(table, *zPtr, 15);
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]=z_re_temp; // multiplying with conjugate of low papr sequence
z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]=z_im_temp; *zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
// 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]); */
}
}
} }
} } else {
else{
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { 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)){ const c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m],
for (int n=0; n<12 ; n++) { table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]};
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) if (l / 2 == m) {
+ (((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); for (int n = 0; n < 12; n++) {
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) c16_t *zDmrsPtr = z_dmrs_rx + m * 12 + n;
- (((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); *zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp; // finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp; // z_dmrs_im_rx arrays
// 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]); *zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
#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]; */
}
}
} }
} }
} }
if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled if (intraSlotFrequencyHopping == true) { // intra-slot hopping enabled
#ifdef DEBUG_NR_PUCCH_RX #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", printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n",
intraSlotFrequencyHopping); intraSlotFrequencyHopping);
#endif #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_1 contains N_SF_mprime from table 6.3.2.4.1-1
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) // (depending on number of PUCCH symbols nrofSymbols, mprime and
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) // intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains
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 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 #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", 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); 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 #endif
for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1} for (int mprime = 0; mprime < 2; mprime++) { // mprime can get values {0,1}
if(l%2==1){ if (l % 2 == 1) {
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { 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)){ c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
for (int n=0; n<12 ; n++) { table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
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) if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12)) {
+ (((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); for (int n = 0; n < 12; n++) {
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) c16_t *zPtr = z_rx + (mprime * 12 * N_SF_mprime0_PUCCH_1) + (m * 12) + n;
- (((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); *zPtr = c16MulConjShift(table, *zPtr, 15);
z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp; *zPtr = c16MulConjShift(r_u_v_alpha_delta[n], *zPtr, 16);
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;
}
}
}
} }
else{ else {
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { 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)){ c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
for (int n=0; n<12 ; n++) { table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
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) if (floor(l / 2) * 12 == (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12)) {
+ (((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); for (int n = 0; n < 12; n++) {
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) c16_t *zDmrsPtr = z_dmrs_rx + (mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1) + (m * 12) + n;
- (((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); *zDmrsPtr = c16MulConjShift(table, *zDmrsPtr, 15);
z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp; // finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and
z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp; // z_dmrs_im_rx arrays
#ifdef DEBUG_NR_PUCCH_RX *zDmrsPtr = c16MulConjShift(r_u_v_alpha_delta_dmrs[n], *zDmrsPtr, 16);
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]; */
}
}
}
} }
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) 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]; cd_t H[12] = {0}, H1[12] = {0};
memset(H_re,0,12*sizeof(int16_t)); const double half_nb_symbols = nrofSymbols / 2.0;
memset(H_im,0,12*sizeof(int16_t)); const double quarter_nb_symbols = nrofSymbols / 4.0;
memset(H1_re,0,12*sizeof(int16_t)); for (int l = 0; l <= half_nb_symbols; l++) {
memset(H1_im,0,12*sizeof(int16_t)); if (intraSlotFrequencyHopping == false) {
//averaging channel coefficients for (int n = 0; n < 12; n++) {
for(l=0;l<=ceil(nrofSymbols/2);l++){ H[n].r += z_dmrs_rx[l * 12 + n].r / half_nb_symbols;
if(intraSlotFrequencyHopping==0){ H[n].i += z_dmrs_rx[l * 12 + n].i / half_nb_symbols;
for(int n=0;n<12;n++){ y_n[n].r += z_rx[l * 12 + n].r / half_nb_symbols;
H_re[n]=round(z_dmrs_re_rx[l*12+n]/ceil(nrofSymbols/2))+H_re[n]; y_n[n].i += z_rx[l * 12 + n].i / half_nb_symbols;
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];
}
} }
} } else {
} if (l < nrofSymbols / 4) {
//averaging information sequences for (int n = 0; n < 12; n++) {
for(l=0;l<floor(nrofSymbols/2);l++){ H[n].r += z_dmrs_rx[l * 12 + n].r / quarter_nb_symbols;
if(intraSlotFrequencyHopping==0){ H[n].i += z_dmrs_rx[l * 12 + n].i / quarter_nb_symbols;
for(int n=0;n<12;n++){ y_n[n].r += z_rx[l * 12 + n].r / quarter_nb_symbols;
y_n_re[n]=round(z_re_rx[l*12+n]/floor(nrofSymbols/2))+y_n_re[n]; y_n[n].i += z_rx[l * 12 + n].i / quarter_nb_symbols;
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 {
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 // mrc combining to obtain z_re and z_im
if(intraSlotFrequencyHopping==0){ cd_t d = {0};
for(int n=0;n<12;n++){ if (intraSlotFrequencyHopping == false) {
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; // complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
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; 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 {
else{ for (int n = 0; n < 12; n++) {
for(int n=0;n<12;n++){ d.r += H[n].r * y_n[n].r + H[n].i * y_n[n].i;
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.i += H[n].r * y_n[n].i - H[n].i * y_n[n].r;
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; d.r += H[n].r * y1_n[n].r + H[n].i * y1_n[n].i;
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; d.i += H[n].r * y1_n[n].i - H[n].i * y1_n[n].r;
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;
} }
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 //Decoding QPSK or BPSK symbols to obtain payload bits
if(nr_bit==1){ if (nr_bit == 1) {
if((d_re+d_im)>0){ if ((d.r + d.i) > 0) {
*payload=0; *payload = 0;
} } else {
else{ *payload = 1;
*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;
} }
else{ } else if (nr_bit == 2) {
*payload=3; 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]; static simde__m256i pucch2_3bit[8 * 2];
simde__m256i pucch2_4bit[16*2]; static simde__m256i pucch2_4bit[16 * 2];
simde__m256i pucch2_5bit[32*2]; static simde__m256i pucch2_5bit[32 * 2];
simde__m256i pucch2_6bit[64*2]; static simde__m256i pucch2_6bit[64 * 2];
simde__m256i pucch2_7bit[128*2]; static simde__m256i pucch2_7bit[128 * 2];
simde__m256i pucch2_8bit[256*2]; static simde__m256i pucch2_8bit[256 * 2];
simde__m256i pucch2_9bit[512*2]; static simde__m256i pucch2_9bit[512 * 2];
simde__m256i pucch2_10bit[1024*2]; static simde__m256i pucch2_10bit[1024 * 2];
simde__m256i pucch2_11bit[2048*2]; static simde__m256i pucch2_11bit[2048 * 2];
static simde__m256i *pucch2_lut[9]={pucch2_3bit, static simde__m256i *pucch2_lut[9] =
pucch2_4bit, {pucch2_3bit, pucch2_4bit, pucch2_5bit, pucch2_6bit, pucch2_7bit, pucch2_8bit, pucch2_9bit, pucch2_10bit, pucch2_11bit};
pucch2_5bit,
pucch2_6bit,
pucch2_7bit,
pucch2_8bit,
pucch2_9bit,
pucch2_10bit,
pucch2_11bit};
simde__m64 pucch2_polar_4bit[16]; simde__m64 pucch2_polar_4bit[16];
simde__m128i pucch2_polar_llr_num_lut[256],pucch2_polar_llr_den_lut[256]; simde__m128i pucch2_polar_llr_num_lut[256],pucch2_polar_llr_den_lut[256];
...@@ -993,8 +864,8 @@ void init_pucch2_luts() { ...@@ -993,8 +864,8 @@ void init_pucch2_luts() {
int8_t bit; int8_t bit;
for (int b=3;b<12;b++) { for (int b=3;b<12;b++) {
for (uint16_t i=0;i<(1<<b);i++) { for (int i = 0; i < (1 << b); i++) {
out=encodeSmallBlock(&i,b); out = encodeSmallBlock(i, b);
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
if (b==3) printf("in %d, out %x\n",i,out); if (b==3) printf("in %d, out %x\n",i,out);
#endif #endif
...@@ -1066,7 +937,7 @@ void init_pucch2_luts() { ...@@ -1066,7 +937,7 @@ void init_pucch2_luts() {
*lut_ip1 = simde_mm256_insert_epi16(*lut_ip1,bit,15); *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]; simde__m64 *lut_i=&pucch2_polar_4bit[i];
bit = (i&0x1) > 0 ? -1 : 1; bit = (i&0x1) > 0 ? -1 : 1;
...@@ -1082,47 +953,48 @@ void init_pucch2_luts() { ...@@ -1082,47 +953,48 @@ void init_pucch2_luts() {
simde__m128i *lut_num_i=&pucch2_polar_llr_num_lut[i]; simde__m128i *lut_num_i=&pucch2_polar_llr_num_lut[i];
simde__m128i *lut_den_i=&pucch2_polar_llr_den_lut[i]; simde__m128i *lut_den_i=&pucch2_polar_llr_den_lut[i];
bit = (i&0x1) > 0 ? 0 : 1; bit = (i&0x1) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 0);
bit = (i&0x10) > 0 ? 0 : 1; bit = (i&0x10) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 1);
bit = (i&0x2) > 0 ? 0 : 1; bit = (i&0x2) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 2);
bit = (i&0x20) > 0 ? 0 : 1; bit = (i&0x20) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 3);
bit = (i&0x4) > 0 ? 0 : 1; bit = (i&0x4) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 4);
bit = (i&0x40) > 0 ? 0 : 1; bit = (i&0x40) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 5);
bit = (i&0x8) > 0 ? 0 : 1; bit = (i&0x8) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 6);
bit = (i&0x80) > 0 ? 0 : 1; bit = (i&0x80) > 0 ? 0 : 1;
*lut_num_i = simde_mm_insert_epi16(*lut_num_i,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); *lut_den_i = simde_mm_insert_epi16(*lut_den_i, 1 - bit, 7);
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",i, printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t *)lut_num_i)[0], i,
((int16_t *)lut_num_i)[1], ((int16_t *)lut_num_i)[0],
((int16_t *)lut_num_i)[2], ((int16_t *)lut_num_i)[1],
((int16_t *)lut_num_i)[3], ((int16_t *)lut_num_i)[2],
((int16_t *)lut_num_i)[4], ((int16_t *)lut_num_i)[3],
((int16_t *)lut_num_i)[5], ((int16_t *)lut_num_i)[4],
((int16_t *)lut_num_i)[6], ((int16_t *)lut_num_i)[5],
((int16_t *)lut_num_i)[7]); ((int16_t *)lut_num_i)[6],
((int16_t *)lut_num_i)[7]);
#endif #endif
} }
} }
...@@ -1138,8 +1010,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1138,8 +1010,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; 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); //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, 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); "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, 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", "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, ...@@ -1147,21 +1020,26 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
//extract pucch and dmrs first //extract pucch and dmrs first
int l2=pucch_pdu->start_symbol_index; 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 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) if (re_offset[0]>= frame_parms->ofdm_symbol_size)
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 { else {
re_offset[1] = 12*(pucch_pdu->second_hop_prb+pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; 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) if (re_offset[1]>= frame_parms->ofdm_symbol_size)
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", AssertFatal(pucch_pdu->prb_size * pucch_pdu->nr_of_symbols > 1,
pucch_pdu->prb_size,pucch_pdu->nr_of_symbols); "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; 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); // 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, ...@@ -1216,7 +1094,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// if the number of PRBs is odd // if the number of PRBs is odd
// we fill the unsed part of the arrays // we fill the unsed part of the arrays
for (int aa = 0; aa < Prx; aa++) { 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; const int sz = pucch_pdu->prb_size;
memset(r_re_ext[aa][symb] + 8 * sz, 0, 8 * sizeof(int16_t)); 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)); 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, ...@@ -1228,7 +1106,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int symb=0; symb<pucch_pdu->nr_of_symbols;symb++) { for (int symb=0; symb<pucch_pdu->nr_of_symbols;symb++) {
// 24 REs contains 48x16-bit, so 6x8x16-bit // 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++) { 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_re_ext_p = &r_re_ext[aa][symb][8 * prb];
int16_t *r_im_ext_p = &r_im_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, ...@@ -1272,7 +1150,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
reset = 0; 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 // each group has 8*nc_group_size elements, compute 1 complex correlation with DMRS per group
// non-coherent combining across groups // non-coherent combining across groups
simde__m64 dmrs_re = byte2m64_re[sGold8[(group & 1) << 1]]; simde__m64 dmrs_re = byte2m64_re[sGold8[(group & 1) << 1]];
...@@ -1280,9 +1158,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1280,9 +1158,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
simde__m64 dmrs_im = byte2m64_im[sGold8[(group & 1) << 1]]; simde__m64 dmrs_im = byte2m64_im[sGold8[(group & 1) << 1]];
int16_t *dmrs_im16 = (int16_t *)&dmrs_im; int16_t *dmrs_im16 = (int16_t *)&dmrs_im;
#ifdef DEBUG_NR_PUCCH_RX #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, group,
((uint16_t *)&s)[0],
x2, x2,
dmrs_re16[0], dmrs_re16[0],
dmrs_im16[0], dmrs_im16[0],
...@@ -1308,7 +1185,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1308,7 +1185,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int z = 0; z < 4; z++) { 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_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]; 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_re = byte2m64_re[sGold8[1 + ((group & 1) << 1)]];
dmrs_im = byte2m64_im[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, ...@@ -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_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_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;*/ corr32_im[group][aa]>>=5;*/
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[symb][group][aa],corr32_im[symb][group][aa]); 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, ...@@ -1358,7 +1235,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
sGold = lte_gold_generic(&x1, &x2, 1); sGold = lte_gold_generic(&x1, &x2, 1);
uint8_t *sGold8 = (uint8_t *)&sGold; uint8_t *sGold8 = (uint8_t *)&sGold;
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("x2 %x, s %x\n",x2,s); printf("x2 %x\n", x2);
#endif #endif
for (int symb=0;symb<pucch_pdu->nr_of_symbols;symb++) { for (int symb=0;symb<pucch_pdu->nr_of_symbols;symb++) {
simde__m64 c_re[4], c_im[4]; simde__m64 c_re[4], c_im[4];
...@@ -1477,9 +1354,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1477,9 +1354,9 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("cw %d:",cw); printf("cw %d:",cw);
for (int i=0;i<32;i+=2) { for (int i=0;i<32;i+=2) {
printf("%d,%d,", printf("%d,%d,",
((int16_t*)&pucch2_lut[nb_bit-3][cw<<1])[i>>1], ((int16_t *)&pucch2_lut[nb_bit - 3][cw << 1])[i >> 1],
((int16_t*)&pucch2_lut[nb_bit-3][cw<<1])[1+(i>>1)]); ((int16_t *)&pucch2_lut[nb_bit - 3][cw << 1])[1 + (i >> 1)]);
} }
printf("\n"); printf("\n");
#endif #endif
...@@ -1489,10 +1366,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1489,10 +1366,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int group=0;group<ngroup;group++) { for (int group=0;group<ngroup;group++) {
// do complex correlation // do complex correlation
for (int aa=0;aa<Prx;aa++) { 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]), prod_re[aa] = /*simde_mm256_srai_epi16(*/ simde_mm256_adds_epi16(
simde_mm256_mullo_epi16(pucch2_lut[nb_bit-3][(cw<<1)+1],rp_im[aa][symb][group]))/*,5)*/; simde_mm256_mullo_epi16(pucch2_lut[nb_bit - 3][cw << 1], rp_re[aa][symb][group]),
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], rp_im[aa][symb][group])) /*,5)*/;
simde_mm256_mullo_epi16(pucch2_lut[nb_bit-3][(cw<<1)+1],rp2_re[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 #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, 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], ((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, ...@@ -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])[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])[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]); ((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_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 prod_re[aa] = simde_mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
...@@ -1522,7 +1401,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -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])[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])[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]); ((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_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 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 #ifdef DEBUG_NR_PUCCH_RX
...@@ -1531,7 +1410,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -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])[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])[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]); ((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_im[aa] = simde_mm256_hadds_epi16(prod_im[aa],prod_im[aa]);
} }
int64_t corr_re=0,corr_im=0; int64_t corr_re=0,corr_im=0;
...@@ -1542,12 +1421,16 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -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_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]); corr_im = ( corr32_im[symb][group][aa]+((int16_t*)(&prod_im[aa]))[0]+((int16_t*)(&prod_im[aa]))[8]);
#ifdef DEBUG_NR_PUCCH_RX #ifdef DEBUG_NR_PUCCH_RX
printf("pucch2 cw %d group %d aa %d: (%d,%d)+(%d,%d) = (%ld,%ld)\n",cw,group,aa, printf("pucch2 cw %d group %d aa %d: (%d,%d)+(%d,%d) = (%ld,%ld)\n",
corr32_re[symb][group][aa],corr32_im[symb][group][aa], cw,
((int16_t*)(&prod_re[aa]))[0]+((int16_t*)(&prod_re[aa]))[8], group,
((int16_t*)(&prod_im[aa]))[0]+((int16_t*)(&prod_im[aa]))[8], aa,
corr_re,corr_im 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 #endif
...@@ -1556,10 +1439,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1556,10 +1439,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
}// group loop }// group loop
} // symb loop } // symb loop
if (corr_tmp > corr) { if (corr_tmp > corr) {
corr = corr_tmp; corr = corr_tmp;
cw_ML=cw; cw_ML = cw;
#ifdef DEBUG_NR_PUCCH_RX #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 #endif
} }
} // cw loop } // cw loop
...@@ -1592,8 +1475,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1592,8 +1475,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
printf("cw %d:",cw); printf("cw %d:",cw);
for (int i=0;i<4;i++) { for (int i=0;i<4;i++) {
printf("%d,", printf("%d,", ((int16_t *)&pucch2_polar_4bit[cw])[i >> 1]);
((int16_t*)&pucch2_polar_4bit[cw])[i>>1]);
} }
printf("\n"); printf("\n");
} }
...@@ -1609,10 +1491,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1609,10 +1491,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
for (int cw=0;cw<256;cw++) { for (int cw=0;cw<256;cw++) {
corr_tmp=0; corr_tmp=0;
for (int aa=0;aa<Prx;aa++) { 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]), prod_re[aa] =
simde_mm_mullo_pi16(pucch2_polar_4bit[cw>>4],rp_im[aa][symb][half_prb])),5); simde_mm_srai_pi16(simde_mm_adds_pi16(simde_mm_mullo_pi16(pucch2_polar_4bit[cw & 15], rp_re[aa][symb][half_prb]),
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], rp_im[aa][symb][half_prb])),
simde_mm_mullo_pi16(pucch2_polar_4bit[cw>>4],rp2_re[aa][symb][half_prb])),5); 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_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_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 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, ...@@ -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_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_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; 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", 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)
half_prb,cw,cw&15,cw>>4,aa, = (%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])[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])[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])[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*)&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])[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])[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])[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], ((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), 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_re[aa]))[0],
((int16_t*)(&prod_im[aa]))[0], ((int16_t*)(&prod_im[aa]))[0],
corr_re, corr_re,
corr_im, corr_im,
corr_tmp); corr_tmp);
*/ */
} }
corr16 = simde_mm_set1_epi16((int16_t)(corr_tmp>>8)); 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); 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_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); 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", LOG_D(PHY,
((int16_t*)&pucch2_polar_llr_num_lut[cw])[0], "lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t*)&pucch2_polar_llr_num_lut[cw])[1], ((int16_t *)&pucch2_polar_llr_num_lut[cw])[0],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[2], ((int16_t *)&pucch2_polar_llr_num_lut[cw])[1],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[3], ((int16_t *)&pucch2_polar_llr_num_lut[cw])[2],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[4], ((int16_t *)&pucch2_polar_llr_num_lut[cw])[3],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[5], ((int16_t *)&pucch2_polar_llr_num_lut[cw])[4],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[6], ((int16_t *)&pucch2_polar_llr_num_lut[cw])[5],
((int16_t*)&pucch2_polar_llr_num_lut[cw])[7]); ((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], LOG_D(PHY,
((int16_t*)&llr_num)[1], "llr_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t*)&llr_num)[2], ((int16_t *)&llr_num)[0],
((int16_t*)&llr_num)[3], ((int16_t *)&llr_num)[1],
((int16_t*)&llr_num)[4], ((int16_t *)&llr_num)[2],
((int16_t*)&llr_num)[5], ((int16_t *)&llr_num)[3],
((int16_t*)&llr_num)[6], ((int16_t *)&llr_num)[4],
((int16_t*)&llr_num)[7]); ((int16_t *)&llr_num)[5],
LOG_D(PHY,"llr_den (%d,%d,%d,%d,%d,%d,%d,%d)\n", ((int16_t *)&llr_num)[6],
((int16_t*)&llr_den)[0], ((int16_t *)&llr_num)[7]);
((int16_t*)&llr_den)[1], LOG_D(PHY,
((int16_t*)&llr_den)[2], "llr_den (%d,%d,%d,%d,%d,%d,%d,%d)\n",
((int16_t*)&llr_den)[3], ((int16_t *)&llr_den)[0],
((int16_t*)&llr_den)[4], ((int16_t *)&llr_den)[1],
((int16_t*)&llr_den)[5], ((int16_t *)&llr_den)[2],
((int16_t*)&llr_den)[6], ((int16_t *)&llr_den)[3],
((int16_t*)&llr_den)[7]); ((int16_t *)&llr_den)[4],
((int16_t *)&llr_den)[5],
} ((int16_t *)&llr_den)[6],
// compute llrs ((int16_t *)&llr_den)[7]);
}
// compute llrs
llrs[half_prb + (symb*2*pucch_pdu->prb_size)] = simde_mm_subs_epi16(llr_num,llr_den); 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", LOG_D(PHY,"llrs[%d] : (%d,%d,%d,%d,%d,%d,%d,%d)\n",
half_prb, half_prb,
...@@ -1712,9 +1600,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1712,9 +1600,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
// estimate CQI for MAC (from antenna port 0 only) // estimate CQI for MAC (from antenna port 0 only)
// TODO this computation is wrong -> to be ignored at MAC for now // 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]], int SNRtimes10 =
12*pucch_pdu->prb_size)) - dB_fixed_times10(signal_energy_nodc((int32_t *)&rxdataF[0][soffset + (l2 * frame_parms->ofdm_symbol_size) + re_offset[0]],
(10*gNB->measurements.n0_power_tot_dB); 12 * pucch_pdu->prb_size))
- (10 * gNB->measurements.n0_power_tot_dB);
int cqi,bit_left; int cqi,bit_left;
if (SNRtimes10 < -640) cqi=0; if (SNRtimes10 < -640) cqi=0;
else if (SNRtimes10 > 635) cqi=255; else if (SNRtimes10 > 635) cqi=255;
...@@ -1739,14 +1628,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1739,14 +1628,12 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int i=0; int i=0;
for (;i<harq_bytes-1;i++) { for (;i<harq_bytes-1;i++) {
uci_pdu->harq.harq_payload[i] = decodedPayload[0] & 255; uci_pdu->harq.harq_payload[i] = decodedPayload[0] & 255;
LOG_D(PHY,"[DLSCH/PDSCH/PUCCH2] %d.%d HARQ paylod (%d) = %d\n", LOG_D(PHY, "[DLSCH/PDSCH/PUCCH2] %d.%d HARQ payload (%d) = %d\n", frame, slot, i, uci_pdu->harq.harq_payload[i]);
frame,slot,i,uci_pdu->harq.harq_payload[i]);
decodedPayload[0]>>=8; decodedPayload[0]>>=8;
} }
bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3); bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3);
uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<bit_left)-1); 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", LOG_D(PHY, "[DLSCH/PDSCH/PUCCH2] %d.%d HARQ payload (%d) = %d\n", frame, slot, i, uci_pdu->harq.harq_payload[i]);
frame,slot,i,uci_pdu->harq.harq_payload[i]);
decodedPayload[0] >>= pucch_pdu->bit_len_harq; decodedPayload[0] >>= pucch_pdu->bit_len_harq;
} }
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
void nr_generate_pucch0(const PHY_VARS_NR_UE *ue, void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
c16_t **txdataF, c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms, const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp, const int16_t amp16,
const int nr_slot_tx, const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu) const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{ {
...@@ -72,13 +72,14 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue, ...@@ -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 * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
*/ */
// alpha is cyclic shift // 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
// lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission // transmission
//uint8_t lnormal; // 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] // lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the
//uint8_t lprime; // 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! // 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: * 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 * 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, ...@@ -89,7 +90,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
* x(l*12+n) = r_u_v_alpha_delta(n) * 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 // 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", 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); 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, ...@@ -97,70 +98,55 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
#endif #endif
// x_n contains the sequence r_u_v_alpha_delta(n) int startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
int16_t x_n_re[2][24],x_n_im[2][24];
uint16_t 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); 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 // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
int prb_offset[2]={startingPRB,startingPRB}; 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) { 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; 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! * 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++) { for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
l2=l+pucch_pdu->start_symbol_index; const double alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,
re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset; 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) if (re_offset>= frame_parms->ofdm_symbol_size)
re_offset-=frame_parms->ofdm_symbol_size; re_offset-=frame_parms->ofdm_symbol_size;
//txptr = &txdataF[0][re_offset]; //txptr = &txdataF[0][re_offset];
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n",l,prb_offset[l],re_offset); 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++) { for (int n=0; n<12; n++) {
const c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * n))};
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r = (int16_t)(((int32_t)(amp) * x_n_re[l][n])>>15); const c16_t table = {table_5_2_2_2_2_Re[u[l]][n], table_5_2_2_2_2_Im[u[l]][n]};
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i = (int16_t)(((int32_t)(amp) * x_n_im[l][n])>>15); txdataFptr[re_offset] = c16mulRealShift(c16mulShift(angle, table, 15), amp, 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];
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, (l2 * frame_parms->ofdm_symbol_size) + re_offset, "\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d "
l2, n, txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r, "\ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i); 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 #endif
re_offset++; re_offset++;
if (re_offset>= frame_parms->ofdm_symbol_size) if (re_offset>= frame_parms->ofdm_symbol_size)
...@@ -172,7 +158,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue, ...@@ -172,7 +158,7 @@ void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
c16_t **txdataF, c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms, const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp, const int16_t amp16,
const int nr_slot_tx, const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu) const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{ {
...@@ -192,37 +178,20 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, ...@@ -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): // 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 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 = (payload & 1) == 0 ? qpskSymbols[0] : qpskSymbols[3];
d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
} }
if (pucch_pdu->n_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 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)) { int tmp = ((payload & 1) << 1) + ((payload >> 1) & 1);
d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d = qpskSymbols[tmp];
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);
}
} }
// printf("d_re=%d\td_im=%d\n",(int)d_re,(int)d_im);
#ifdef DEBUG_NR_PUCCH_TX #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 #endif
/* /*
* Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 * 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, ...@@ -265,11 +234,11 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
uint32_t re_offset=0; uint32_t re_offset=0;
int i=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 #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]; c16_t z[MAX_SIZE_Z];
int16_t z_dmrs_re[MAX_SIZE_Z],z_dmrs_im[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] // 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++) { for (int l = 0; l < nrofSymbols; l++) {
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
...@@ -277,7 +246,7 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, ...@@ -277,7 +246,7 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
l,lprime); l,lprime);
#endif #endif
// y_n contains the complex value d multiplied by the sequence r_u_v // 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))) if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols / 2)))
n_hop = 1; // n_hop = 1 for second hop n_hop = 1; // n_hop = 1 for second hop
...@@ -294,28 +263,27 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, ...@@ -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_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. // 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++) { 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) c16_t angle = {lround(32767 * cos(alpha * n)), lround(32767 * sin(alpha * n))};
- (((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 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_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) r_u_v_alpha_delta[n] = c16mulShift(angle, table, 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[n] = c16mulRealShift(r_u_v_alpha_delta[n], amp, 15);
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]);
// PUCCH sequence = DM-RS sequence multiplied by d(0) // 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) y_n[n] = c16mulShift(r_u_v_alpha_delta[n], d, 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]);
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
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]); "\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 #endif
} }
...@@ -333,16 +301,13 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, ...@@ -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] // 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 // and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC
// In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field // In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field
uint8_t w_index = timeDomainOCC; 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.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime
uint8_t N_SF_mprime_PUCCH_1; // 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
// 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) // number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled) N_SF_mprime_PUCCH_1 contains N_SF_mprime
uint8_t N_SF_mprime_PUCCH_DMRS_1; // 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.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
uint8_t N_SF_mprime0_PUCCH_1; // and intra-slot hopping enabled/disabled) mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping
// 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; uint8_t mprime = 0;
if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled
...@@ -350,46 +315,74 @@ void nr_generate_pucch1(const PHY_VARS_NR_UE *ue, ...@@ -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", printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n",
intraSlotFrequencyHopping); intraSlotFrequencyHopping);
#endif #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) int N_SF_mprime_PUCCH_1 =
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) 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_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_mprime_PUCCH_DMRS_1 =
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) 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 #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", 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); 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 #endif
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { 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++) { 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) zPtr[n] = c16mulShift(table, y_n[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 #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", printf(
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, "\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d "
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], "+ %d * %d)) = (%d,%d)\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], mprime,
z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); 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 #endif
} }
} }
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { 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++) { 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) zDmrsPtr[n] = c16mulShift(table, r_u_v_alpha_delta_dmrs[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 #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", printf(
mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, "\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d "
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], "+ %d * %d)) = (%d,%d)\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], mprime,
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]); 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 #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, ...@@ -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", printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n",
intraSlotFrequencyHopping); intraSlotFrequencyHopping);
#endif #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) int N_SF_mprime_PUCCH_1 =
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) 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_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 =
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) 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 #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", 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); 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, ...@@ -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 (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1}
for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
for (int n=0; n<12 ; n++) { c16_t *zPtr = z + mprime * 12 * N_SF_mprime0_PUCCH_1 + m * 12;
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) c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],
- (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m]};
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) for (int n = 0; n < 12; n++)
+ (((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]);
#endif
}
} }
for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
for (int n=0; n<12 ; n++) { c16_t *zDmrsPtr = z_dmrs + mprime * 12 * N_SF_mprime0_PUCCH_DMRS_1 + m * 12;
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) c16_t table = {table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m],
- (((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)); table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m]};
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) for (int n = 0; n < 12; n++)
+ (((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]);
#endif
}
} }
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) 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, ...@@ -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 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] = z[i + n];
txdataF[0][re_offset].i = z_im[i+n];
#ifdef DEBUG_NR_PUCCH_TX #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", 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, 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, ...@@ -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 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] = z_dmrs[i + n];
txdataF[0][re_offset].i = z_dmrs_im[i+n];
#ifdef DEBUG_NR_PUCCH_TX #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", 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, 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, ...@@ -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) { 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; uint32_t x1 = 0, x2 = 0, s = 0;
int i; int i;
...@@ -632,7 +611,7 @@ static void nr_uci_encoding(uint64_t payload, ...@@ -632,7 +611,7 @@ static void nr_uci_encoding(uint64_t payload,
if (A<=11) { 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) // 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) // 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 // repetition for rate-matching up to 16 PRB
b[0] = b0 | (b0<<32); b[0] = b0 | (b0<<32);
b[1] = b[0]; b[1] = b[0];
...@@ -658,7 +637,7 @@ static void nr_uci_encoding(uint64_t payload, ...@@ -658,7 +637,7 @@ static void nr_uci_encoding(uint64_t payload,
void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
c16_t **txdataF, c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms, const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp, const int16_t amp16,
const int nr_slot_tx, const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu) const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{ {
...@@ -687,8 +666,8 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, ...@@ -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 = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured
* n_id = N_ID_cell if higher layer parameter not 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 // rnti is given by the C-RNTI
uint16_t rnti=pucch_pdu->rnti; uint16_t rnti=pucch_pdu->rnti;
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
...@@ -717,41 +696,31 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, ...@@ -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) //#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
// complex-valued symbol d(0) // complex-valued symbol d(0)
int16_t *d_re = calloc(M_bit, sizeof(int16_t)); c16_t d[M_bit];
int16_t *d_im = calloc(M_bit, sizeof(int16_t)); memset(d, 0, sizeof(d));
uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1; 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 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)) { int tmp = (btilde[2 * i] & 1) * 2 + (btilde[(2 * i) + 1] & 1);
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d[i] = qpskSymbols[tmp];
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);
}
#ifdef DEBUG_NR_PUCCH_TX #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 #endif
} }
/* /*
* Implementing TS 38.211 Subclause 6.3.2.5.3 Mapping to physical resources * Implementing TS 38.211 Subclause 6.3.2.5.3 Mapping to physical resources
*/ */
//int32_t *txptr; // int32_t *txptr;
uint32_t re_offset=0;
uint32_t x1 = 0, x2 = 0, s = 0; uint32_t x1 = 0, x2 = 0, s = 0;
int i=0; int i=0;
int m=0; int m=0;
...@@ -773,24 +742,22 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, ...@@ -773,24 +742,22 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
m = 0; m = 0;
for (int rb=0; rb<pucch_pdu->prb_size; rb++) { for (int rb=0; rb<pucch_pdu->prb_size; rb++) {
//startingPRB = startingPRB + 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 const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; 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 (((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 if (nb_rb_is_even) {
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))); if (baseRB < halfRBs) // if number RBs in bandwidth is even and current PRB is lower band
} re_offset += frame_parms->first_carrier_offset;
else
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 -= halfRBs;
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 += 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 else if (baseRB > halfRBs) // 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; re_offset += -halfRBs + 6;
} else
re_offset += 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 contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
} }
//txptr = &txdataF[0][re_offset]; //txptr = &txdataF[0][re_offset];
...@@ -800,14 +767,13 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, ...@@ -800,14 +767,13 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
#endif #endif
for (int n=0; n<12; n++) { 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) // 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); 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 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]; txdataF[0][re_offset] = d[i + k];
((int16_t *)&txdataF[0][re_offset])[1] = d_im[i+k];
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf( printf(
"\t [nr_generate_pucch2] (n=%d,i=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d " "\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, ...@@ -822,15 +788,15 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
re_offset, re_offset,
l, l,
n, n,
((int16_t *)&txdataF[0][re_offset])[0], txdataF[0][re_offset].r,
((int16_t *)&txdataF[0][re_offset])[1]); txdataF[0][re_offset].i);
#endif #endif
k++; k++;
} }
if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2 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); txdataF[0][re_offset].r = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((s >> (2 * m)) & 1)))));
((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].i = (int16_t)(baseVal * (1 - (2 * ((uint8_t)((s >> (2 * m + 1)) & 1)))));
m++; m++;
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf( printf(
...@@ -846,8 +812,8 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, ...@@ -846,8 +812,8 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
re_offset, re_offset,
l, l,
n, n,
((int16_t *)&txdataF[0][re_offset])[0], txdataF[0][re_offset].r,
((int16_t *)&txdataF[0][re_offset])[1]); txdataF[0][re_offset].i);
kk++; kk++;
#endif #endif
} }
...@@ -863,15 +829,12 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue, ...@@ -863,15 +829,12 @@ void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
} }
} }
} }
free(d_re);
free(d_im);
free(btilde);
} }
//#if 0 //#if 0
void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
c16_t **txdataF, c16_t **txdataF,
const NR_DL_FRAME_PARMS *frame_parms, const NR_DL_FRAME_PARMS *frame_parms,
const int16_t amp, const int16_t amp16,
const int nr_slot_tx, const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu) const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{ {
...@@ -902,7 +865,7 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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); printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping);
#endif #endif
} }
const int32_t amp = amp16;
uint8_t nrofSymbols = pucch_pdu->nr_of_symbols; uint8_t nrofSymbols = pucch_pdu->nr_of_symbols;
uint16_t nrofPRB = pucch_pdu->prb_size; uint16_t nrofPRB = pucch_pdu->prb_size;
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start; 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, ...@@ -912,11 +875,13 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
pucch_pdu->n_bit, pucch_pdu->n_bit,
pucch_pdu->format_type, pucch_pdu->format_type,
is_pi_over_2_bpsk_enabled, is_pi_over_2_bpsk_enabled,
nrofSymbols,nrofPRB, nrofSymbols,
nrofPRB,
n_SF_PUCCH_s, n_SF_PUCCH_s,
intraSlotFrequencyHopping, intraSlotFrequencyHopping,
add_dmrs, add_dmrs,
&b[0],&M_bit); b,
&M_bit);
/* /*
* Implementing TS 38.211 * Implementing TS 38.211
* Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) * 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, ...@@ -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 = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured
* n_id = N_ID_cell if higher layer parameter not 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 // rnti is given by the C-RNTI
uint16_t rnti=pucch_pdu->rnti, n_id=0; uint16_t rnti=pucch_pdu->rnti, n_id=0;
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
...@@ -946,35 +911,24 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -946,35 +911,24 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
* Subclause 5.1.3 QPSK * Subclause 5.1.3 QPSK
*/ */
// complex-valued symbol d(0) // complex-valued symbol d(0)
int16_t *d_re = malloc(sizeof(int16_t)*M_bit); c16_t d[M_bit];
int16_t *d_im = malloc(sizeof(int16_t)*M_bit);
uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1; 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) { 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 // 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 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)) { int tmp = (btilde[2 * i] & 1) * 2 + (btilde[(2 * i) + 1] & 1);
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d[i] = qpskSymbols[tmp];
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);
}
#ifdef DEBUG_NR_PUCCH_TX #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 #endif
} }
} }
...@@ -982,30 +936,17 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -982,30 +936,17 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
if (is_pi_over_2_bpsk_enabled == 1) { 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 // 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; 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 for (int i=0; i<m_symbol; i++) { // PI/2-BPSK modulation subclause 5.1.1
if (((btilde[i]&1)==0) && (i%2 == 0)) { int tmp = (btilde[i] & 1) * 2 + (i & 1);
d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d[i] = qpskSymbols[tmp];
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);
}
#ifdef DEBUG_NR_PUCCH_TX #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 #endif
} }
} }
...@@ -1020,33 +961,27 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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 // 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; // uint8_t nrofSymbols;
// complex-valued symbol d(0) // 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 c16_t y_n[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);
// Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1) // 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} // k={0,..11} n={0,1,2,3}
// parameter PUCCH-F4-preDFT-OCC-index set of {0,1,2,3} -> n // 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}, 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} {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) // 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} // 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}, 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}};
{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) // 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} // 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}, 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, 0, 0, 0, -1, -1, -1, 0, 0, 0},
{1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1}, {1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1},
{1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0} {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) // 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} // 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}, 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, -1, -1, -1, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1} {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 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, ...@@ -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 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 l=0; l < floor(m_symbol/(12*nrofPRB)); l++) {
for (int k=0; k < (12*nrofPRB); k++) { for (int k = l * 12 * nrofPRB; k < (l + 1) * 12 * nrofPRB; k++) {
y_n_re[l*(12*nrofPRB)+k] = d_re[l*(12*nrofPRB)+k]; y_n[k] = d[k];
y_n_im[l*(12*nrofPRB)+k] = d_im[l*(12*nrofPRB)+k];
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]); "\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 #endif
} }
} }
...@@ -1070,29 +1010,37 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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 l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) {
for (int k=0; k < (12*nrofPRB); k++) { 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) { 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]) 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]};
- ((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])); *yPtr = c16mulShift(table, dVal, 15);
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]));
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); "\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) "
// 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)]); " = \t(d_re=%d, d_im=%d)\n",
// 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)]); occ_Index,
// 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]); l,
// 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]); k,
l * (12 * nrofPRB) + k,
yPtr->r,
yPtr->i);
#endif #endif
} }
if (n_SF_PUCCH_s == 4) { 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]) 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]};
- ((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])); *yPtr = c16mulShift(table, dVal, 15);
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]));
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); "\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 #endif
} }
} }
...@@ -1102,41 +1050,28 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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 * 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 c16_t z[4 * M_bit]; // 4 is the maximum number n_SF_PUCCH_s
int16_t *z_im = malloc(sizeof(int16_t)*4*M_bit);
#define M_PI 3.14159265358979323846 // pi #define M_PI 3.14159265358979323846 // pi
const int64_t base = round(32767 / sqrt(12 * nrofPRB));
//int16_t inv_sqrt_nrofPRBs = (int16_t)round(32767/sqrt(12*nrofPRB));
for (int l=0; l<floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) { for (int l=0; l<floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) {
for (int k=0; k<(12*nrofPRB); k++) { for (int k=0; k<(12*nrofPRB); k++) {
z_re[l*(12*nrofPRB)+k] = 0; c16_t *yPtr = y_n + l * 12 * nrofPRB;
z_im[l*(12*nrofPRB)+k] = 0; c16_t *zPtr = z + l * 12 * nrofPRB + k;
*zPtr = (c16_t){0};
// int16_t z_re_tmp[240] = {0}; for (int m = l * 12 * nrofPRB; m < (l + 1) * 12 * nrofPRB; m++) {
// int16_t z_im_tmp[240] = {0}; const c16_t angle = {lround(32767 * cos(2 * M_PI * m * k / (12 * nrofPRB))),
for (int m=0; m<(12*nrofPRB); m++) { lround(32767 * sin(2 * M_PI * m * k / (12 * nrofPRB)))};
//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)))); c16_t tmp = c16mulShift(yPtr[m], angle, 15);
// 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) csum(*zPtr, *zPtr, c16mulRealShift(tmp, base, 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
} }
#ifdef DEBUG_NR_PUCCH_TX #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", 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 #endif
} }
} }
...@@ -1157,10 +1092,11 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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] // 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; //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 // 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; 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 (pucch_pdu->format_type == 4) {
if (n_SF_PUCCH_s == 2) { if (n_SF_PUCCH_s == 2) {
...@@ -1173,17 +1109,9 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -1173,17 +1109,9 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
} }
double alpha; double alpha;
uint8_t N_ZC = 12*nrofPRB; int N_ZC = 12 * nrofPRB;
int16_t *r_u_v_base_re = malloc(sizeof(int16_t)*12*nrofPRB); c16_t r_u_v_base[N_ZC];
int16_t *r_u_v_base_im = malloc(sizeof(int16_t)*12*nrofPRB); uint32_t re_offset = 0;
//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;
uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = { 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 {(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 {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, ...@@ -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),(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 {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++) { 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); 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 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, ...@@ -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); q = ((uint8_t)floor(2*q_base)%2 == 0 ? q+v : q-v);
for (int n=0; n<(12*nrofPRB); n++) { 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); const double tmp = M_PI * q * (n % N_ZC) * ((n % N_ZC) + 1) / N_ZC;
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); 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 #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", 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 #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 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++) { 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); 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_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Im[u][n])>>15); r_u_v_base[n] = c16mulRealShift(table, amp, 15);
#ifdef DEBUG_NR_PUCCH_TX #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", 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 #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 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++) { 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); 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_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Im[u][n])>>15); r_u_v_base[n] = c16mulRealShift(table, amp, 15);
#ifdef DEBUG_NR_PUCCH_TX #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", 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 #endif
} }
} }
...@@ -1253,76 +1192,102 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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); alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,startingSymbolIndex,nr_slot_tx);
for (int rb=0; rb<nrofPRB; rb++) { 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 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; startingPRB = startingPRB + pucch_pdu->second_hop_prb;
} }
re_offset = ((l + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
//startingPRB = startingPRB + 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 if (nb_rb_is_even) {
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset; 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 #ifdef DEBUG_NR_PUCCH_TX
printf("1 "); printf("1 ");
#endif #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 else { // 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))); re_offset += 12 * (baseRB - halfRBs);
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf("2 "); printf("2 ");
#endif #endif
} }
} else {
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 if (baseRB < halfRBs) { // 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; re_offset += 12 * baseRB + frame_parms->first_carrier_offset;
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf("3 "); printf("3 ");
#endif #endif
} } else if (baseRB > halfRBs) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset += 12 * (baseRB - halfRBs) + 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 is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6;
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf("4 "); printf("4 ");
#endif #endif
} } else { // if number RBs in bandwidth is odd and current PRB contains DC
re_offset += 12 * baseRB + 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 contains DC
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
#ifdef DEBUG_NR_PUCCH_TX #ifdef DEBUG_NR_PUCCH_TX
printf("5 "); printf("5 ");
#endif #endif
}
} }
#ifdef DEBUG_NR_PUCCH_TX #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 #endif
//txptr = &txdataF[0][re_offset]; //txptr = &txdataF[0][re_offset];
for (int n=0; n<12; n++) { 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) // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); // 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 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]; txdataF[0][re_offset] = z[n + k];
((int16_t *)&txdataF[0][re_offset])[1] = z_im[n+k];
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset, "\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 "
l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); "\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 #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 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) const c16_t angle = {lround(32767 * cos(alpha * ((n + j) % N_ZC))), lround(32767 * sin(alpha * ((n + j) % N_ZC)))};
- (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)); txdataF[0][re_offset] = c16mulShift(angle, r_u_v_base[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));
#ifdef DEBUG_NR_PUCCH_TX #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", printf(
l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset, "\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 "
l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); "\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 #endif
} }
...@@ -1334,7 +1299,4 @@ void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue, ...@@ -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; 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" { ...@@ -215,7 +215,8 @@ extern "C" {
{ {
return (c16_t){.r = (int16_t)((a.r * b) >> Shift), .i = (int16_t)((a.i * b) >> Shift)}; 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) { return (c16_t) {
.r = (int16_t)((a.r * b.r + a.i * b.i) >> Shift), .r = (int16_t)((a.r * b.r + a.i * b.i) >> Shift),
.i = (int16_t)((a.r * b.i - a.i * b.r) >> Shift) .i = (int16_t)((a.r * b.i - a.i * b.r) >> Shift)
......
...@@ -83,64 +83,7 @@ binary_search_float_nr( ...@@ -83,64 +83,7 @@ binary_search_float_nr(
return first; 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 * 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