Commit b7514c6f authored by Vincent Savaux's avatar Vincent Savaux

adapt NPUSCH demod to 3.75 kHz

parent 7cb7efe9
...@@ -62,6 +62,37 @@ static int16_t temp_out_ifft_1[2048*4] __attribute__((aligned(16))); ...@@ -62,6 +62,37 @@ static int16_t temp_out_ifft_1[2048*4] __attribute__((aligned(16)));
#define SCALE 0x3FFF #define SCALE 0x3FFF
void rotate_channel_single_carrier_NB_IoT(int16_t *estimated_channel,unsigned char l, uint8_t Qm)
{
int16_t pi_2_re[2] = {32767 , 0};
int16_t pi_2_im[2] = {0 , 32768};
int16_t pi_4_re[2] = {32767 , 25735};
int16_t pi_4_im[2] = {0 , 25736};
int k;
int16_t est_channel_re, est_channel_im;
for (k=0;k<12;k++){
est_channel_re = estimated_channel[k<<1];
est_channel_im = estimated_channel[(k<<1)+1];
if (Qm == 1){
estimated_channel[k<<1] = (int16_t)(((int32_t)pi_2_re[l%2] * (int32_t)est_channel_re +
(int32_t)pi_2_im[l%2] * (int32_t)est_channel_im)>>15);
estimated_channel[(k<<1)+1] = (int16_t)(((int32_t)pi_2_re[l%2] * (int32_t)est_channel_im -
(int32_t)pi_2_im[l%2] * (int32_t)est_channel_re)>>15);
}
if(Qm == 2){
estimated_channel[k<<1] = (int16_t)(((int32_t)pi_4_re[l%2] * (int32_t)est_channel_re +
(int32_t)pi_4_im[l%2] * (int32_t)est_channel_im)>>15);
estimated_channel[(k<<1)+1] = (int16_t)(((int32_t)pi_4_re[l%2] * (int32_t)est_channel_im -
(int32_t)pi_4_im[l%2] * (int32_t)est_channel_re)>>15);
}
}
}
int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
eNB_rxtx_proc_NB_IoT_t *proc, eNB_rxtx_proc_NB_IoT_t *proc,
uint8_t eNB_id, uint8_t eNB_id,
...@@ -88,8 +119,13 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -88,8 +119,13 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
uint16_t aa; //,Msc_RS,Msc_RS_idx; uint16_t aa; //,Msc_RS,Msc_RS_idx;
//uint16_t * Msc_idx_ptr; //uint16_t * Msc_idx_ptr;
// int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp; // int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp;
int pilot_pos1 = 3, pilot_pos2 = 10; // holds for npusch format 1, and 15 kHz subcarrier bandwidth int pilot_pos1_15k = 3, pilot_pos2_15k = 10; // holds for npusch format 1, and 15 kHz subcarrier bandwidth
int pilot_pos_format2[6] = {2,3,4,9,10,11}; // holds for npusch format 2, and 15 kHz subcarrier bandwidth int pilot_pos_format2_15k[6] = {2,3,4,9,10,11}; // holds for npusch format 2, and 15 kHz subcarrier bandwidth
int pilot_pos1_3_75k = 4, pilot_pos2_3_75k = 11; // holds for npusch format 1, and 3.75 kHz subcarrier bandwidth
int pilot_pos_format2_3_75k[6] = {0,1,2,7,8,9}; // holds for npusch format 2, and 3.75 kHz subcarrier bandwidth
int pilot_pos1, pilot_pos2; // holds for npusch format 1, and 15 kHz subcarrier bandwidth
int *pilot_pos_format2; // holds for npusch format 2, and 15 kHz subcarrier bandwidth
int16_t *ul_ch1=NULL, *ul_ch2=NULL, *ul_ch3=NULL, *ul_ch4=NULL, *ul_ch5=NULL, *ul_ch6=NULL; int16_t *ul_ch1=NULL, *ul_ch2=NULL, *ul_ch3=NULL, *ul_ch4=NULL, *ul_ch5=NULL, *ul_ch6=NULL;
int16_t average_channel[24]; // average channel over a RB and 2 slots int16_t average_channel[24]; // average channel over a RB and 2 slots
int32_t *p_average_channel = (int32_t *)&average_channel; int32_t *p_average_channel = (int32_t *)&average_channel;
...@@ -97,9 +133,10 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -97,9 +133,10 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
int16_t ul_ch_estimates_re,ul_ch_estimates_im; int16_t ul_ch_estimates_re,ul_ch_estimates_im;
//uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB; //uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
//uint8_t cyclic_shift; uint8_t subcarrier_spacing = frame_parms->subcarrier_spacing; // 15 kHz or 3.75 kHz
uint8_t Qm; // needed to rotate the estimated channel
//uint32_t alpha_ind; //uint32_t alpha_ind;
uint32_t u;//=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[Ns+(subframe<<1)]; uint32_t u;//=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[Ns+(subframe<<1)];
//uint32_t v=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.seqhop[Ns+(subframe<<1)]; //uint32_t v=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.seqhop[Ns+(subframe<<1)];
...@@ -181,11 +218,21 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -181,11 +218,21 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
break; break;
} }
if (subcarrier_spacing){
pilot_pos_format2 = pilot_pos_format2_15k;
pilot_pos1 = pilot_pos1_15k;
pilot_pos2 = pilot_pos2_15k;
}else{
pilot_pos_format2 = pilot_pos_format2_3_75k;
pilot_pos1 = pilot_pos1_3_75k;
pilot_pos2 = pilot_pos2_3_75k;
}
ul_sc_start = get_UL_sc_start_NB_IoT(I_sc); // NB-IoT: get the used subcarrier in RB ul_sc_start = get_UL_sc_start_NB_IoT(I_sc); // NB-IoT: get the used subcarrier in RB
u=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[n_s][index_Nsc_RU]; // Vincent: may be adapted for Nsc_RU, see 36.211, Section 10.1.4.1.3 u=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[n_s][index_Nsc_RU]; // Vincent: may be adapted for Nsc_RU, see 36.211, Section 10.1.4.1.3
switch (npusch_format){ switch (npusch_format){
case 1: case 1:
if (l == 3) { // NB-IoT: no extended CP if (l == pilot_pos1) { // NB-IoT: no extended CP
symbol_offset = frame_parms->N_RB_UL*12*(l+(7*(Ns&1))); symbol_offset = frame_parms->N_RB_UL*12*(l+(7*(Ns&1)));
...@@ -207,6 +254,12 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -207,6 +254,12 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
(int32_t)received_data[k<<1]*(int32_t)pilot_sig[(k<<1)+1])>>15); //imaginary part of estimated channel (int32_t)received_data[k<<1]*(int32_t)pilot_sig[(k<<1)+1])>>15); //imaginary part of estimated channel
} }
if (Nsc_RU == 1){ // rotate the estimated channel by pi/2 or pi/4, due to mapping b2c
Qm = get_Qm_ul_NB_IoT(eNB->ulsch[UE_id]->harq_process->mcs,Nsc_RU);
rotate_channel_single_carrier_NB_IoT(estimated_channel,l,Qm);
}
if(Nsc_RU != 1 && Nsc_RU != 12) { if(Nsc_RU != 1 && Nsc_RU != 12) {
// Compensating for the phase shift introduced at the transmitter // Compensating for the phase shift introduced at the transmitter
// In NB-IoT NPUSCH format 1, phase alpha is zero when 1 and 12 subcarriers are allocated // In NB-IoT NPUSCH format 1, phase alpha is zero when 1 and 12 subcarriers are allocated
...@@ -273,7 +326,7 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -273,7 +326,7 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
} }
break; break;
case 2: case 2:
if (l == 2 || l == 3 || l == 4){ if (l == pilot_pos_format2[0] || l == pilot_pos_format2[1] || l == pilot_pos_format2[2]){
symbol_offset = frame_parms->N_RB_UL*12*(l+(7*(Ns&1))); symbol_offset = frame_parms->N_RB_UL*12*(l+(7*(Ns&1)));
index_w = (uint8_t)l-2 + 3*(((uint8_t*)&s)[n_s&3]%3); // base index in w_format2_re and w_format2_im, see 36.211, Section 10.1.4.1.1 index_w = (uint8_t)l-2 + 3*(((uint8_t*)&s)[n_s&3]%3); // base index in w_format2_re and w_format2_im, see 36.211, Section 10.1.4.1.1
...@@ -292,6 +345,9 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -292,6 +345,9 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
(int32_t)received_data[k<<1]*(int32_t)pilot_sig[(k<<1)+1])>>15); //imaginary part of estimated channel (int32_t)received_data[k<<1]*(int32_t)pilot_sig[(k<<1)+1])>>15); //imaginary part of estimated channel
} }
// rotate the estimated channel by pi/2 or pi/4, due to mapping b2c
rotate_channel_single_carrier_NB_IoT(estimated_channel,l,1); // last input: Qm = 1 in format 2
// Compensating for the phase shift introduced at the transmitter // Compensating for the phase shift introduced at the transmitter
// In NB-IoT NPUSCH format 1, phase alpha is zero when 1 and 12 subcarriers are allocated // In NB-IoT NPUSCH format 1, phase alpha is zero when 1 and 12 subcarriers are allocated
// else (still format 1), alpha is defined in 36.211, Table 10.1.4.1.2-3 // else (still format 1), alpha is defined in 36.211, Table 10.1.4.1.2-3
...@@ -308,7 +364,7 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -308,7 +364,7 @@ int32_t ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
(int16_t) (((int32_t) (w_format2_re[index_w]) * (int32_t) (ul_ch_estimates_im) - (int16_t) (((int32_t) (w_format2_re[index_w]) * (int32_t) (ul_ch_estimates_im) -
(int32_t) (w_format2_im[index_w]) * (int32_t) (ul_ch_estimates_re))>>15); (int32_t) (w_format2_im[index_w]) * (int32_t) (ul_ch_estimates_re))>>15);
if (Ns&1 && l==4) {//we are in the second slot of the sub-frame, so do the interpolation if (Ns&1 && l==pilot_pos_format2[2]) {//we are in the second slot of the sub-frame, so do the interpolation
ul_ch1 = (int16_t *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos_format2[0]]; ul_ch1 = (int16_t *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos_format2[0]];
ul_ch2 = (int16_t *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos_format2[1]]; ul_ch2 = (int16_t *)&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos_format2[1]];
......
...@@ -1358,13 +1358,13 @@ void rotate_single_carrier_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -1358,13 +1358,13 @@ void rotate_single_carrier_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
if (Qm == 1){ if (Qm == 1){
rxdataF_comp16[0] = (int16_t)(((int32_t)pi_2_re[symbol%2] * (int32_t)rxdataF_comp16_re + rxdataF_comp16[0] = (int16_t)(((int32_t)pi_2_re[symbol%2] * (int32_t)rxdataF_comp16_re +
(int32_t)pi_2_im[symbol%2] * (int32_t)rxdataF_comp16_im)>>15); (int32_t)pi_2_im[symbol%2] * (int32_t)rxdataF_comp16_im)>>15);
rxdataF_comp16[1] = (int16_t)(((int32_t)pi_2_re[symbol%1] * (int32_t)rxdataF_comp16_im - rxdataF_comp16[1] = (int16_t)(((int32_t)pi_2_re[symbol%2] * (int32_t)rxdataF_comp16_im -
(int32_t)pi_2_im[symbol%2] * (int32_t)rxdataF_comp16_re)>>15); (int32_t)pi_2_im[symbol%2] * (int32_t)rxdataF_comp16_re)>>15);
} }
if(Qm == 2){ if(Qm == 2){
rxdataF_comp16[0] = (int16_t)(((int32_t)pi_4_re[symbol%2] * (int32_t)rxdataF_comp16_re + rxdataF_comp16[0] = (int16_t)(((int32_t)pi_4_re[symbol%2] * (int32_t)rxdataF_comp16_re +
(int32_t)pi_4_im[symbol%2] * (int32_t)rxdataF_comp16_im)>>15); (int32_t)pi_4_im[symbol%2] * (int32_t)rxdataF_comp16_im)>>15);
rxdataF_comp16[1] = (int16_t)(((int32_t)pi_4_re[symbol%1] * (int32_t)rxdataF_comp16_im - rxdataF_comp16[1] = (int16_t)(((int32_t)pi_4_re[symbol%2] * (int32_t)rxdataF_comp16_im -
(int32_t)pi_4_im[symbol%2] * (int32_t)rxdataF_comp16_re)>>15); (int32_t)pi_4_im[symbol%2] * (int32_t)rxdataF_comp16_re)>>15);
} }
...@@ -1573,10 +1573,19 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -1573,10 +1573,19 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
int subframe = proc->subframe_rx; int subframe = proc->subframe_rx;
uint8_t npusch_format = 1; // NB-IoT: format 1 (data), or 2: ack. Should be defined in higher layer uint8_t npusch_format = 1; // NB-IoT: format 1 (data), or 2: ack. Should be defined in higher layer
uint8_t Nsc_RU = eNB->ulsch[UE_id]->harq_process->N_sc_RU; // Vincent: number of sc 1,3,6,12 uint8_t Nsc_RU = eNB->ulsch[UE_id]->harq_process->N_sc_RU; // Vincent: number of sc 1,3,6,12
uint8_t subcarrier_spacing = frame_parms->subcarrier_spacing; // 15 kHz or 3.75 kHz
int pilot_pos1_15k = 3, pilot_pos2_15k = 10; // holds for npusch format 1, and 15 kHz subcarrier bandwidth
int pilot_pos_format2_15k[2] = {2,9}; // holds for npusch format 2, and 15 kHz subcarrier bandwidth
int pilot_pos1_3_75k = 4, pilot_pos2_3_75k = 11; // holds for npusch format 1, and 3.75 kHz subcarrier bandwidth
int pilot_pos_format2_3_75k[2] = {0,7}; // holds for npusch format 2, and 3.75 kHz subcarrier bandwidth
int pilot_pos1, pilot_pos2; // holds for npusch format 1, and 15 kHz subcarrier bandwidth
int *pilot_pos_format2; // holds for npusch format 2, and 15 kHz subcarrier bandwidth
harq_pid = subframe2harq_pid_NB_IoT(frame_parms,proc->frame_rx,subframe); harq_pid = subframe2harq_pid_NB_IoT(frame_parms,proc->frame_rx,subframe);
Qm = get_Qm_ul_NB_IoT(ulsch[UE_id]->harq_process->mcs,ulsch[UE_id]->harq_process->N_sc_RU); Qm = get_Qm_ul_NB_IoT(ulsch[UE_id]->harq_process->mcs,Nsc_RU);
rx_power_correction = 1; rx_power_correction = 1;
...@@ -1585,6 +1594,16 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -1585,6 +1594,16 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
return; return;
} }
if (subcarrier_spacing){
pilot_pos_format2 = pilot_pos_format2_15k;
pilot_pos1 = pilot_pos1_15k;
pilot_pos2 = pilot_pos2_15k;
}else{
pilot_pos_format2 = pilot_pos_format2_3_75k;
pilot_pos1 = pilot_pos1_3_75k;
pilot_pos2 = pilot_pos2_3_75k;
}
for (l=0; l<frame_parms->symbols_per_tti; l++) { for (l=0; l<frame_parms->symbols_per_tti; l++) {
ulsch_extract_rbs_single_NB_IoT(common_vars->rxdataF[eNB_id], ulsch_extract_rbs_single_NB_IoT(common_vars->rxdataF[eNB_id],
...@@ -1706,13 +1725,13 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -1706,13 +1725,13 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
for (l=0; l<frame_parms->symbols_per_tti; l++) { for (l=0; l<frame_parms->symbols_per_tti; l++) {
if (npusch_format == 1){ if (npusch_format == 1){
if (l==3 || l==10) // skip pilots if (l==pilot_pos1 || l==pilot_pos2) // skip pilots
{ {
l++; l++;
} }
} }
if (npusch_format == 2){ if (npusch_format == 2){
if (l == 2 || l == 9) // skip 3 pilots if (l == pilot_pos_format2[0] || l == pilot_pos_format2[1]) // skip 3 pilots
{ {
l = l + 3; l = l + 3;
} }
...@@ -1849,7 +1868,7 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -1849,7 +1868,7 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
// l++; // l++;
// } // }
if (npusch_format == 1){ if (npusch_format == 1){
if (l==3 || l==10) // skip pilots if (l==pilot_pos1 || l==pilot_pos2) // skip pilots
{ {
l++; l++;
} }
...@@ -1868,7 +1887,7 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, ...@@ -1868,7 +1887,7 @@ void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
} }
if (npusch_format == 2){ if (npusch_format == 2){
if (l == 2 || l == 9) // skip 3 pilots if (l == pilot_pos_format2[0] || l == pilot_pos_format2[1]) // skip 3 pilots
{ {
l = l + 3; l = l + 3;
} }
......
...@@ -509,6 +509,11 @@ typedef struct { ...@@ -509,6 +509,11 @@ typedef struct {
*/ */
uint16_t eutra_NumCRS_ports; uint16_t eutra_NumCRS_ports;
/* Subcarrier bandwidth
0 -> 3.75 kHz
1 -> 15 kHz
*/
uint8_t subcarrier_spacing;
} NB_IoT_DL_FRAME_PARMS; } NB_IoT_DL_FRAME_PARMS;
......
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