Commit 18cca485 authored by Raymond Knopp's avatar Raymond Knopp

full trx for PSCCH

parent 314bf57f
......@@ -218,11 +218,20 @@ void phy_adjust_gain (PHY_VARS_UE *phy_vars_ue,
uint32_t rx_power_fil_dB,
unsigned char eNB_id);
int lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB,
eNB_rxtx_proc_t *proc,
module_id_t UE_id,
uint8_t l,
uint8_t Ns);
int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **ul_ch_estimates,
int32_t **ul_ch_estimates_time,
int32_t **rxdataF_ext,
int N_rb_alloc,
int frame_rx,
int subframe_rx,
uint32_t u,
uint32_t v,
uint32_t cyclic_shift,
unsigned char l,
unsigned char Ns,
uint16_t rnti);
int16_t lte_ul_freq_offset_estimation(LTE_DL_FRAME_PARMS *frame_parms,
......
......@@ -34,24 +34,33 @@ static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32
#define SCALE 0x3FFF
int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
eNB_rxtx_proc_t *proc,
uint8_t UE_id,
int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **ul_ch_estimates,
int32_t **ul_ch_estimates_time,
int32_t **rxdataF_ext,
int N_rb_alloc,
int frame_rx,
int subframe_rx,
uint32_t u,
uint32_t v,
uint32_t cyclic_shift,
unsigned char l,
unsigned char Ns) {
unsigned char Ns,
uint16_t rnti) {
LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
LTE_eNB_PUSCH *pusch_vars = eNB->pusch_vars[UE_id];
int32_t **ul_ch_estimates=pusch_vars->drs_ch_estimates;
/* int32_t **ul_ch_estimates=pusch_vars->drs_ch_estimates;
int32_t **ul_ch_estimates_time= pusch_vars->drs_ch_estimates_time;
int32_t **rxdataF_ext= pusch_vars->rxdataF_ext;
int subframe = proc->subframe_rx;
uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe);
*/
int16_t delta_phase = 0;
int16_t *ru1 = ru_90;
int16_t *ru2 = ru_90;
int16_t current_phase1,current_phase2;
uint16_t N_rb_alloc = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
// uint16_t N_rb_alloc = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
uint16_t aa,Msc_RS,Msc_RS_idx;
uint16_t * Msc_idx_ptr;
int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp;
......@@ -60,11 +69,10 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
//uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
uint8_t cyclic_shift;
uint32_t alpha_ind;
uint32_t u=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[Ns+(subframe<<1)];
uint32_t v=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[Ns+(subframe<<1)];
// uint32_t u=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[Ns+(subframe<<1)];
// uint32_t v=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[Ns+(subframe<<1)];
int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16)));
int symbol_offset,i;
......@@ -86,10 +94,9 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
Msc_RS = N_rb_alloc*12;
/*
cyclic_shift = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
eNB->ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+Ns]) % 12;
*/
#if defined(USER_MODE)
Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
......@@ -267,50 +274,51 @@ int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
#endif
}
// Convert to time domain for visualization
memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
for(i=0; i<Msc_RS; i++)
((int32_t*)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i];
switch(frame_parms->N_RB_DL) {
case 6:
idft128((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 25:
idft512((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 50:
idft1024((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 100:
idft2048((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
}
if (ul_ch_estimates_time[aa]) {
// Convert to time domain for visualization
memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
for(i=0; i<Msc_RS; i++)
((int32_t*)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i];
switch(frame_parms->N_RB_DL) {
case 6:
idft128((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 25:
idft512((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 50:
idft1024((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
case 100:
idft2048((int16_t*) temp_in_ifft_0,
(int16_t*) ul_ch_estimates_time[aa],
1);
break;
}
#if T_TRACER
if (aa == 0)
T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(eNB->ulsch[UE_id]->rnti),
T_INT(proc->frame_rx), T_INT(subframe),
T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4));
if (aa == 0)
T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(0), T_INT(rnti),
T_INT(frame_rx), T_INT(subframe),
T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4));
#endif
}
#ifdef DEBUG_CH
if (aa==0) {
if (Ns == 0) {
write_output("rxdataF_ext.m","rxF_ext",&rxdataF_ext[aa][symbol_offset],512*2,2,1);
write_output("tmpin_ifft.m","drs_in",temp_in_ifft_0,512,1,1);
write_output("drs_est0.m","drs0",ul_ch_estimates_time[aa],512,1,1);
if (ul_ch_estimates_time[aa]) write_output("drs_est0.m","drs0",ul_ch_estimates_time[aa],512,1,1);
} else
write_output("drs_est1.m","drs1",ul_ch_estimates_time[aa],512,1,1);
if (ul_ch_estimates_time[aa]) write_output("drs_est1.m","drs1",ul_ch_estimates_time[aa],512,1,1);
}
#endif
......
......@@ -2544,7 +2544,7 @@ uint8_t generate_dci_top(uint8_t num_pdcch_symbols,
void dci_decoding(uint8_t DCI_LENGTH,
uint8_t aggregation_level,
uint16_t coded_bits,
int8_t *e,
uint8_t *decoded_output)
{
......@@ -2555,15 +2555,14 @@ void dci_decoding(uint8_t DCI_LENGTH,
uint16_t RCC;
uint16_t D=(DCI_LENGTH+16+64);
uint16_t coded_bits;
#ifdef DEBUG_DCI_DECODING
int32_t i;
#endif
AssertFatal(aggregation_level<4,
"dci_decoding FATAL, illegal aggregation_level %d\n",aggregation_level);
AssertFatal(coded_bits<8*72,
"dci_decoding FATAL, illegal codeblock size %d\n",coded_bits);
coded_bits = 72 * (1<<aggregation_level);
#ifdef DEBUG_DCI_DECODING
LOG_I(PHY," Doing DCI decoding for %d bits, DCI_LENGTH %d,coded_bits %d, e %p\n",3*(DCI_LENGTH+16),DCI_LENGTH,coded_bits,e);
......@@ -2905,9 +2904,9 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **pdcch_vars,
pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_c);
dci_decoding(sizeof_bits,
L,
&pdcch_vars[eNB_id]->e_rx[CCEind*72],
&dci_decoded_output[current_thread_id][0]);
(1<<L)*72,
&pdcch_vars[eNB_id]->e_rx[CCEind*72],
&dci_decoded_output[current_thread_id][0]);
/*
for (i=0;i<3+(sizeof_bits>>3);i++)
printf("dci_decoded_output[%d] => %x\n",i,dci_decoded_output[i]);
......
......@@ -886,6 +886,8 @@ typedef struct {
uint32_t prb_End;
/// SL-OffsetIndicator (0-10239)
uint32_t SL_OffsetIndicator;
/// SC-SC_Period
uint32_t SL_SC_Period;
/// PSCCH subframe bitmap, first 64-bits (up to 40 bits for Rel 12)
uint64_t bitmap1;
/// PSCCH subframe bitmap, 2nd 64-bits (up to 100 bits for Rel 14)
......@@ -908,7 +910,6 @@ typedef struct {
uint32_t timing_advance_indication;
/// SCI0 Group Destination ID for SLSCH
uint32_t group_destination_id;
// SLSCH Parameters
/// Number of Subbands (36.213 14.1.1.2)
uint32_t Nsb;
......
......@@ -58,25 +58,82 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
int32_t *txdataF = ue->common_vars.txdataF[ant];
uint32_t u,v,alpha_ind;
uint32_t u0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1];
uint32_t u1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)];
uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
uint32_t u0,u1,v0,v1;
int32_t ref_re,ref_im;
uint8_t harq_pid = subframe2harq_pid(frame_parms,proc->frame_tx,subframe);
cyclic_shift0 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
// printf("PUSCH.cyclicShift %d, n_DMRS2 %d, nPRS %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,ue->ulsch[eNB_id]->n_DMRS2,ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]);
cyclic_shift1 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
uint8_t harq_pid;
int lstart,linc;
AssertFatal(ue->sl_chan>=0 && ue->sl_chan<MAX_SLTYPES, "ue->sl_chan %d impossible\n",ue->sl_chan);
switch (ue->sl_chan) {
case PSCCH_12_EVEN:
cyclic_shift0=0;
cyclic_shift1=0;
u0=0;
u1=0;
v0=0;
v1=0;
lstart = (3 - frame_parms->Ncp);
linc = frame_parms->symbols_per_tti;
break;
case PSCCH_12_ODD:
cyclic_shift0=0;
cyclic_shift1=0;
u0=0;
u1=0;
v0=0;
v1=0;
lstart = (10 - (frame_parms->Ncp<<1));
linc = frame_parms->symbols_per_tti;
break;
break;
case PSCCH_34_EVEN:
AssertFatal(1==0,"SL Transmission type 3/4 not supported for now\n");
break;
case PSCCH_34_ODD:
AssertFatal(1==0,"SL Transmission type 3/4 not supported for now\n");
break;
case PSSCH_12:
/* Need to figure this out ...
u0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1];
u1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)];
v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];*/
cyclic_shift0 = (ue->slsch->n_ss_PSSCH>>1)&7;
cyclic_shift1 = cyclic_shift0;
lstart = (3 - frame_parms->Ncp);
linc = frame_parms->symbols_per_tti;
break;
case PSSCH_34:
AssertFatal(1==0,"SL Transmission type 3/4 not supported for now\n");
break;
case PSDCH_ODD:
case PSDCH_EVEN:
AssertFatal(1==0,"PSDCH Transmission not supported for now\n");
break;
case PSBCH:
AssertFatal(1==0,"PSBCH Transmission not supported for now\n");
break;
case NO_SL:
u0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1];
u1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)];
v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
harq_pid = subframe2harq_pid(frame_parms,proc->frame_tx,subframe);
lstart = (3 - frame_parms->Ncp);
linc = (7 - frame_parms->Ncp);
cyclic_shift0 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
// printf("PUSCH.cyclicShift %d, n_DMRS2 %d, nPRS %d\n",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,ue->ulsch[eNB_id]->n_DMRS2,ue->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]);
cyclic_shift1 = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+1]+
((ue->ulsch[0]->cooperation_flag==2)?10:0)+
ant*6) % 12;
}
// cyclic_shift0 = 0;
// cyclic_shift1 = 0;
Msc_RS = 12*nb_rb;
......@@ -105,9 +162,9 @@ int generate_drs_pusch(PHY_VARS_UE *ue,
#endif
for (l = (3 - frame_parms->Ncp),u=u0,v=v0,cyclic_shift=cyclic_shift0;
for (l = lstart,u=u0,v=v0,cyclic_shift=cyclic_shift0;
l<frame_parms->symbols_per_tti;
l += (7 - frame_parms->Ncp),u=u1,v=v1,cyclic_shift=cyclic_shift1) {
l += linc,u=u1,v=v1,cyclic_shift=cyclic_shift1) {
drs_offset = 0; // printf("drs_modulation: Msc_RS = %d, Msc_RS_idx = %d\n",Msc_RS, Msc_RS_idx);
......
......@@ -1523,12 +1523,12 @@ void qpsk_qpsk_TM3456(short *stream0_in,
/** \brief Attempt decoding of a particular DCI with given length and format.
@param DCI_LENGTH length of DCI in bits
@param DCI_FMT Format of DCI
@param coded_bits number of physical channel bits
@param e e-sequence (soft bits)
@param decoded_output Output of Viterbi decoder
*/
void dci_decoding(uint8_t DCI_LENGTH,
uint8_t DCI_FMT,
uint16_t coded_bits,
int8_t *e,
uint8_t *decoded_output);
......@@ -1719,6 +1719,24 @@ void ulsch_extract_rbs_single(int32_t **rxdataF,
uint8_t Ns,
LTE_DL_FRAME_PARMS *frame_parms);
void ulsch_channel_compensation(int32_t **rxdataF_ext,
int32_t **ul_ch_estimates_ext,
int32_t **ul_ch_mag,
int32_t **ul_ch_magb,
int32_t **rxdataF_comp,
LTE_DL_FRAME_PARMS *frame_parms,
uint8_t symbol,
uint8_t Qm,
uint16_t nb_rb,
uint8_t output_shift);
void ulsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
int32_t **ul_ch_mag,
int32_t **ul_ch_magb,
uint8_t symbol,
uint16_t nb_rb);
uint8_t subframe2harq_pid(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe);
uint8_t subframe2harq_pid_eNBrx(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
......@@ -1738,6 +1756,21 @@ int generate_ue_dlsch_params_from_dci(int frame,
uint8_t beamforming_mode,
uint16_t tc_rnti);
int32_t ulsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
int16_t *ulsch_llr,
uint8_t symbol,
uint16_t nb_rb,
int16_t **llrp);
void ulsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **rxdataF_comp,
int16_t *ulsch_llr,
int32_t **ul_ch_mag,
uint8_t symbol,
uint16_t nb_rb,
int16_t **llrp);
void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,
eNB_rxtx_proc_t *proc,
DCI_ALLOC_t *dci_alloc,
......
......@@ -44,13 +44,13 @@ void generate_sldch(PHY_VARS_UE *ue,SLDCH_t *sldch,int frame_tx,int subframe_tx)
AssertFatal(sldch->payload_length <=1500-sldch_header_len - sizeof(SLDCH_t) + sizeof(uint8_t*),
"SLDCH payload length > %d\n",
"SLDCH payload length > %lu\n",
1500-sldch_header_len - sizeof(SLDCH_t) + sizeof(uint8_t*));
memcpy((void*)&pdu.sldch,
(void*)sldch,
sizeof(SLDCH_t));
LOG_I(PHY,"SLDCH configuration %d bytes, TBS payload %d bytes => %d bytes\n",
LOG_I(PHY,"SLDCH configuration %lu bytes, TBS payload %d bytes => %lu bytes\n",
sizeof(SLDCH_t)-sizeof(uint8_t*),
sldch->payload_length,
sldch_header_len+sizeof(SLDCH_t)-sizeof(uint8_t*)+sldch->payload_length);
......
......@@ -33,35 +33,711 @@
#define __LTE_TRANSPORT_SLSS__C__
#include "PHY/defs.h"
int64_t sci_mapping(PHY_VARS_UE *ue) {
SLSCH_t *slsch = ue->slsch;
AssertFatal(slsch->freq_hopping_flag<2,"freq_hop %d >= 2\n",slsch->freq_hopping_flag);
int64_t freq_hopping_flag = (uint64_t)slsch->freq_hopping_flag;
int64_t RAbits = log2_approx(slsch->N_SL_RB*((slsch->N_SL_RB+1)>>1));
AssertFatal(slsch->resource_block_coding<(1<<RAbits),"slsch->resource_block_coding %x >= %x\n",slsch->resource_block_coding,(1<<RAbits));
int64_t resource_block_coding = (uint64_t)slsch->resource_block_coding;
AssertFatal(slsch->time_resource_pattern<128,"slsch->time_resource_pattern %d>=128\n",slsch->time_resource_pattern);
int64_t time_resource_pattern = (uint64_t)slsch->time_resource_pattern;
void generate_slsch(PHY_VARS_UE *ue,SLSCH_t *slsch,int frame_tx,int subframe_tx) {
AssertFatal(slsch->mcs<32,"slsch->mcs %d >= 32\n",slsch->mcs);
int64_t mcs = (uint64_t)slsch->mcs;
AssertFatal(slsch->timing_advance_indication<2048,"slsch->timing_advance_indication %d >= 2048\n",slsch->timing_advance_indication);
int64_t timing_advance_indication = (uint64_t)slsch->timing_advance_indication;
AssertFatal(slsch->group_destination_id<256,"slsch->group_destination_id %d >= 256\n",slsch->group_destination_id);
int64_t group_destination_id = (uint64_t)slsch->group_destination_id;
// map bitfields
// frequency-hopping 1-bit
return( freq_hopping_flag |
(resource_block_coding << 1) |
(time_resource_pattern<<(1+RAbits)) |
(mcs<<(1+RAbits+7)) |
(timing_advance_indication<<(1+RAbits+7+5)) |
(group_destination_id<<(1+RAbits+7+5+11))
);
}
void dft_slcch(int32_t *z,int32_t *d, uint8_t Nsymb) {
#if defined(__x86_64__) || defined(__i386__)
__m128i dft_in128[4][12],dft_out128[4][12];
#elif defined(__arm__)
int16x8_t dft_in128[4][12],dft_out128[4][12];
#endif
uint32_t *dft_in0=(uint32_t*)dft_in128[0],*dft_out0=(uint32_t*)dft_out128[0];
uint32_t *dft_in1=(uint32_t*)dft_in128[1],*dft_out1=(uint32_t*)dft_out128[1];
uint32_t *d0,*d1,*d2,*d3,*d4,*d5;
uint32_t *z0,*z1,*z2,*z3,*z4,*z5;
uint32_t i,ip;
#if defined(__x86_64__) || defined(__i386__)
__m128i norm128;
#elif defined(__arm__)
int16x8_t norm128;
#endif
d0 = (uint32_t *)d;
d1 = d0+12;
d2 = d1+12;
d3 = d2+12;
d4 = d3+12;
d5 = d4+12;
// printf("symbol 0 (d0 %p, d %p)\n",d0,d);
for (i=0,ip=0; i<12; i++,ip+=4) {
dft_in0[ip] = d0[i];
dft_in0[ip+1] = d1[i];
dft_in0[ip+2] = d2[i];
dft_in0[ip+3] = d3[i];
dft_in1[ip] = d4[i];
dft_in1[ip+1] = d5[i];
dft_in1[ip+2] = 0;
}
dft12((int16_t *)dft_in0,(int16_t *)dft_out0);
dft12((int16_t *)dft_in1,(int16_t *)dft_out1);
#if defined(__x86_64__) || defined(__i386__)
norm128 = _mm_set1_epi16(9459);
#elif defined(__arm__)
norm128 = vdupq_n_s16(9459);
#endif
for (i=0; i<12; i++) {
#if defined(__x86_64__) || defined(__i386__)
((__m128i*)dft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)dft_out0)[i],norm128),1);
((__m128i*)dft_out1)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)dft_out1)[i],norm128),1);
#elif defined(__arm__)
((int16x8_t*)dft_out0)[i] = vqdmulhq_s16(((int16x8_t*)dft_out0)[i],norm128);
((int16x8_t*)dft_out1)[i] = vqdmulhq_s16(((int16x8_t*)dft_out1)[i],norm128);
#endif
}
z0 = (uint32_t *)z;
z1 = z0+12;
z2 = z1+12;
z3 = z2+12;
z4 = z3+12;
z5 = z4+12;
// printf("symbol0 (dft)\n");
for (i=0,ip=0; i<12; i++,ip+=4) {
z0[i] = dft_out0[ip];
z1[i] = dft_out0[ip+1];
z2[i] = dft_out0[ip+2];
z3[i] = dft_out0[ip+3];
z4[i] = dft_out1[ip+0];
z5[i] = dft_out1[ip+1];
}
// printf("\n");
}
extern short conjugate2[8];
void idft_slcch(LTE_DL_FRAME_PARMS *frame_parms,int32_t *z)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i idft_in128[3][12],idft_out128[3][12];
__m128i norm128;
#elif defined(__arm__)
int16x8_t idft_in128[3][12],idft_out128[3][12];
int16x8_t norm128;
#endif
int16_t *idft_in0=(int16_t*)idft_in128[0],*idft_out0=(int16_t*)idft_out128[0];
int16_t *idft_in1=(int16_t*)idft_in128[1],*idft_out1=(int16_t*)idft_out128[1];
int32_t *z0,*z1,*z2,*z3,*z4,*z5=NULL;
int i,ip;
// printf("Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH);
if (frame_parms->Ncp == 0) { // Normal prefix
z0 = z;
z1 = z0+(frame_parms->N_RB_DL*12);
z2 = z1+(frame_parms->N_RB_DL*12);
//pilot
z3 = z2+(2*frame_parms->N_RB_DL*12);
z4 = z3+(frame_parms->N_RB_DL*12);
z5 = z4+(frame_parms->N_RB_DL*12);
} else { // extended prefix
z0 = z;
z1 = z0+(frame_parms->N_RB_DL*12);
//pilot
z2 = z1+(2*frame_parms->N_RB_DL*12);
z3 = z2+(frame_parms->N_RB_DL*12);
z4 = z3+(frame_parms->N_RB_DL*12);
}
// conjugate input
for (i=0; i<3; i++) {
#if defined(__x86_64__)||defined(__i386__)
*&(((__m128i*)z0)[i])=_mm_sign_epi16(*&(((__m128i*)z0)[i]),*(__m128i*)&conjugate2[0]);
*&(((__m128i*)z1)[i])=_mm_sign_epi16(*&(((__m128i*)z1)[i]),*(__m128i*)&conjugate2[0]);
*&(((__m128i*)z2)[i])=_mm_sign_epi16(*&(((__m128i*)z2)[i]),*(__m128i*)&conjugate2[0]);
*&(((__m128i*)z3)[i])=_mm_sign_epi16(*&(((__m128i*)z3)[i]),*(__m128i*)&conjugate2[0]);
*&(((__m128i*)z4)[i])=_mm_sign_epi16(*&(((__m128i*)z4)[i]),*(__m128i*)&conjugate2[0]);
*&(((__m128i*)z5)[i])=_mm_sign_epi16(*&(((__m128i*)z5)[i]),*(__m128i*)&conjugate2[0]);
#elif defined(__arm__)
*&(((int16x8_t*)z0)[i])=vmulq_s16(*&(((int16x8_t*)z0)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z1)[i])=vmulq_s16(*&(((int16x8_t*)z1)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z2)[i])=vmulq_s16(*&(((int16x8_t*)z2)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z3)[i])=vmulq_s16(*&(((int16x8_t*)z3)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z4)[i])=vmulq_s16(*&(((int16x8_t*)z4)[i]),*(int16x8_t*)&conjugate2[0]);
if (frame_parms->Ncp==NORMAL)
*&(((int16x8_t*)z5)[i])=vmulq_s16(*&(((int16x8_t*)z5)[i]),*(int16x8_t*)&conjugate2[0]);
#endif
}
for (i=0,ip=0; i<12; i++,ip+=4) {
((uint32_t*)idft_in0)[ip+0] = z0[i];
((uint32_t*)idft_in0)[ip+1] = z1[i];
((uint32_t*)idft_in0)[ip+2] = z2[i];
((uint32_t*)idft_in0)[ip+3] = z3[i];
((uint32_t*)idft_in1)[ip+0] = z4[i];
if (frame_parms->Ncp==0) ((uint32_t*)idft_in1)[ip+1] = z5[i];
}
dft12((int16_t *)idft_in0,(int16_t *)idft_out0);
dft12((int16_t *)idft_in1,(int16_t *)idft_out1);
#if defined(__x86_64__)||defined(__i386__)
norm128 = _mm_set1_epi16(9459);
#elif defined(__arm__)
norm128 = vdupq_n_s16(9459);
#endif
for (i=0; i<12; i++) {
#if defined(__x86_64__)||defined(__i386__)
((__m128i*)idft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out0)[i],norm128),1);
((__m128i*)idft_out1)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out1)[i],norm128),1);
#elif defined(__arm__)
((int16x8_t*)idft_out0)[i] = vqdmulhq_s16(((int16x8_t*)idft_out0)[i],norm128);
((int16x8_t*)idft_out1)[i] = vqdmulhq_s16(((int16x8_t*)idft_out1)[i],norm128);
#endif
}
for (i=0,ip=0; i<12; i++,ip+=4) {
z0[i] = ((uint32_t*)idft_out0)[ip];
/*
printf("out0 (%d,%d),(%d,%d),(%d,%d),(%d,%d)\n",
((int16_t*)&idft_out0[ip])[0],((int16_t*)&idft_out0[ip])[1],
((int16_t*)&idft_out0[ip+1])[0],((int16_t*)&idft_out0[ip+1])[1],
((int16_t*)&idft_out0[ip+2])[0],((int16_t*)&idft_out0[ip+2])[1],
((int16_t*)&idft_out0[ip+3])[0],((int16_t*)&idft_out0[ip+3])[1]);
*/
z1[i] = ((uint32_t*)idft_out0)[ip+1];
z2[i] = ((uint32_t*)idft_out0)[ip+2];
z3[i] = ((uint32_t*)idft_out0)[ip+3];
z4[i] = ((uint32_t*)idft_out1)[ip+0];
if (frame_parms->Ncp==0) z5[i] = ((uint32_t*)idft_out1)[ip+1];
}
// conjugate output
for (i=0; i<3; i++) {
#if defined(__x86_64__) || defined(__i386__)
((__m128i*)z0)[i]=_mm_sign_epi16(((__m128i*)z0)[i],*(__m128i*)&conjugate2[0]);
((__m128i*)z1)[i]=_mm_sign_epi16(((__m128i*)z1)[i],*(__m128i*)&conjugate2[0]);
((__m128i*)z2)[i]=_mm_sign_epi16(((__m128i*)z2)[i],*(__m128i*)&conjugate2[0]);
((__m128i*)z3)[i]=_mm_sign_epi16(((__m128i*)z3)[i],*(__m128i*)&conjugate2[0]);
((__m128i*)z4)[i]=_mm_sign_epi16(((__m128i*)z4)[i],*(__m128i*)&conjugate2[0]);
if (frame_parms->Ncp==NORMAL)
((__m128i*)z5)[i]=_mm_sign_epi16(((__m128i*)z5)[i],*(__m128i*)&conjugate2[0]);
#elif defined(__arm__)
*&(((int16x8_t*)z0)[i])=vmulq_s16(*&(((int16x8_t*)z0)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z1)[i])=vmulq_s16(*&(((int16x8_t*)z1)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z2)[i])=vmulq_s16(*&(((int16x8_t*)z2)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z3)[i])=vmulq_s16(*&(((int16x8_t*)z3)[i]),*(int16x8_t*)&conjugate2[0]);
*&(((int16x8_t*)z4)[i])=vmulq_s16(*&(((int16x8_t*)z4)[i]),*(int16x8_t*)&conjugate2[0]);
if (frame_parms->Ncp==NORMAL) *&(((int16x8_t*)z5)[i])=vmulq_s16(*&(((int16x8_t*)z5)[i]),*(int16x8_t*)&conjugate2[0]);
#endif
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty();
_m_empty();
#endif
}
void pscch_codingmodulation(PHY_VARS_UE *ue,int frame_tx,int subframe_tx,uint32_t a,int slot) {
LTE_UE_PSCCH_TX *pscch = ue->pscch_vars_tx;
SLSCH_t *slsch = ue->slsch;
int tx_amp;
int nprb;
uint64_t sci;
// Note this should depend on configuration of slsch/slcch
uint32_t Nsymb = 7;
uint32_t E = 12*(Nsymb-1)*2;
// coding part
if (ue->pscch_coded == 0) {
sci = sci_mapping(ue);
dci_encoding((uint8_t *)sci,
log2_approx(slsch->N_SL_RB*((slsch->N_SL_RB+1)>>1))+31,
E,
pscch->f,
0);
// interleaving
// Cmux assumes configuration 0
int Cmux = Nsymb-1;
uint8_t *fptr;
for (int i=0,j=0; i<Cmux; i++)
// 24 = 12*(Nsymb-1)*2/(Nsymb-1)
for (int r=0; r<24; r++) {
fptr=&pscch->f[((r*Cmux)+i)<<1];
pscch->h[j++] = *fptr++;
pscch->h[j++] = *fptr++;
}
// scrambling
uint32_t x1,x2=510;
uint32_t s = lte_gold_generic(&x1,&x2,1);
uint8_t c;
for (int i=0,k=0;i<(1+(E>>5));i++) {
for (int j=0;(j<32)&&(k<E);j++,k++) {
c = (uint8_t)((s>>j)&1);
pscch->b_tilde[k] = (pscch->h[k]+c)&1;
}
}
ue->pscch_coded=1;
}
// convert a to prb number and compute slot
// get index within slot (first half of the prbs in slot 0, second half in 1)
uint32_t amod = a%(slsch->N_SL_RB);
if (amod<(slsch->N_SL_RB>>1)) nprb = slsch->prb_Start + amod;
else nprb = slsch->prb_End-slsch->N_SL_RB+amod;
// Fill in power control later
// pssch_power_cntl(ue,proc,eNB_id,1, abstraction_flag);
// ue->tx_power_dBm[subframe_tx] = ue->slcch[eNB_id]->Po_PUSCH;
ue->tx_power_dBm[subframe_tx] = 0;
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
tx_amp = get_tx_amp(ue->tx_power_dBm[subframe_tx],
ue->tx_power_max_dBm,
ue->frame_parms.N_RB_UL,
1);
#else
tx_amp = AMP;
#endif
// modulation
int Msymb = E/2;
int32_t d[Msymb];
int16_t gain_lin_QPSK = (int16_t)((tx_amp*ONE_OVER_SQRT2_Q15)>>15);
for (int i=0,j=0; i<Msymb; i++,j+=2) {
((int16_t*)&d[i])[0] = (pscch->b_tilde[j] == 1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
((int16_t*)&d[i])[1] = (pscch->b_tilde[j+1] == 1)? (-gain_lin_QPSK) : gain_lin_QPSK;
}
// precoding
int32_t z[Msymb];
int re_offset,re_offset0,symbol_offset;
LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
dft_slcch(z,d,Nsymb);
// RE mapping
re_offset0 = frame_parms->first_carrier_offset + (nprb*12);
if (re_offset0>frame_parms->ofdm_symbol_size) {
re_offset0 -= frame_parms->ofdm_symbol_size;
}
AssertFatal(slot==0||slot==1,"Slot %d is illegal\n",slot);
int loffset = slot==0 ? 0 : Nsymb;
int32_t *txptr;
for (int j=0,l=0; l<(Nsymb-1); l++) {
re_offset = re_offset0;
symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(loffset+l+(subframe_tx*2*Nsymb));
txptr = &ue->common_vars.txdataF[0][symbol_offset];
if (((frame_parms->Ncp == 0) && ((l==3) || (l==10)))||
((frame_parms->Ncp == 1) && ((l==2) || (l==8)))) {
}
// Skip reference symbols
else {
for (int i=0; i<12; i++,j++) {
txptr[re_offset++] = z[j];
if (re_offset==frame_parms->ofdm_symbol_size) re_offset = 0;
}
}
}
ue->sl_chan = (slot==0) ? PSCCH_12_EVEN : PSCCH_12_ODD;
// DMRS insertion
for (int aa=0; aa<1/*frame_parms->nb_antennas_tx*/; aa++)
generate_drs_pusch(ue,
NULL, // no proc means this is SLSCH/SLCCH
0,
tx_amp,
subframe_tx,
nprb,
1,
aa);
}
void check_and_generate_pscch(PHY_VARS_UE *ue,int frame_tx,int subframe_tx) {
AssertFatal(frame_tx<1024 && frame_tx>0,"frame %d is illegal\n",frame_tx);
AssertFatal(subframe_tx<10 && subframe_tx>0,"subframe %d is illegal\n",subframe_tx);
SLSCH_t *slsch = ue->slsch;
AssertFatal(slsch!=NULL,"SLSCH is null\n");
uint32_t O = ue->slsch->SL_OffsetIndicator;
uint32_t P = ue->slsch->SL_SC_Period;
uint32_t absSF = (frame_tx*10)+subframe_tx;
uint32_t absSF_offset,absSF_modP;
if (ue->pscch_generated == 1) return;
absSF_offset = absSF-O;
if (absSF_offset < O) return;
absSF_modP = absSF_offset%P;
// This is the condition for short SCCH bitmap (40 bits), check that the current subframe is for SCCH
if (absSF_modP > 39) return;
uint64_t SFpos = ((uint64_t)1) << absSF_modP;
if ((SFpos & slsch->bitmap1) == 0) return;
// if we get here, then there is a PSCCH subframe for a potential transmission
uint32_t sf_index=40,LPSCCH=0;
for (int i=0;i<40;i++) {
if (i==absSF_modP) sf_index=LPSCCH;
if (((((uint64_t)1)<<i) & slsch->bitmap1)>0) sf_index++;
}
AssertFatal(sf_index<40,"sf_index not set, should not happen\n");
LPSCCH++;
// sf_index now contains the SF index in 0...LPSCCH-1
// LPSCCH has the number of PSCCH subframes
// 2 SLSCH/SLCCH resource block regions subframe times number of resources blocks per slot times 2 slots
uint32_t M_RB_PSCCH_RP = slsch->N_SL_RB*LPSCCH<<2;
AssertFatal(slsch->n_pscch < (M_RB_PSCCH_RP>>1)*LPSCCH,"n_pscch not in 0..%d\n",
((M_RB_PSCCH_RP>>1)*LPSCCH)-1);
// hard-coded to transmission mode one for now (Section 14.2.1.1 from 36.213 Rel14.3)
uint32_t a1=slsch->n_pscch/LPSCCH;
uint32_t a2=a1+slsch->n_pscch/LPSCCH+(M_RB_PSCCH_RP>>1);
uint32_t b1=slsch->n_pscch%LPSCCH;
uint32_t b2=(slsch->n_pscch + 1 + (a1%(LPSCCH-1)))%LPSCCH;
if (absSF_modP == b1) pscch_codingmodulation(ue,frame_tx,subframe_tx,a1,0);
else if (absSF_modP == b2) pscch_codingmodulation(ue,frame_tx,subframe_tx,a2,1);
else return;
}
void generate_slsch(PHY_VARS_UE *ue,SLSCH_t *slsch,int frame_tx,int subframe_tx) {
UE_tport_t pdu;
size_t slsch_header_len = sizeof(UE_tport_header_t);
if (slsch->rvidx==0) {
pdu.header.packet_type = SLSCH;
pdu.header.absSF = (frame_tx*10)+subframe_tx;
if (ue->sidelink_l2_emulation == 1) {
if (slsch->rvidx==0) {
pdu.header.packet_type = SLSCH;
pdu.header.absSF = (frame_tx*10)+subframe_tx;
memcpy((void*)&pdu.slsch,(void*)slsch,sizeof(SLSCH_t)-sizeof(uint8_t*));
AssertFatal(slsch->payload_length <=1500-slsch_header_len - sizeof(SLSCH_t) + sizeof(uint8_t*),
"SLSCH payload length > %lu\n",
1500-slsch_header_len - sizeof(SLSCH_t) + sizeof(uint8_t*));
memcpy((void*)&pdu.payload[0],
(void*)slsch->payload,
slsch->payload_length);
LOG_I(PHY,"SLSCH configuration %lu bytes, TBS payload %d bytes => %lu bytes\n",
sizeof(SLSCH_t)-sizeof(uint8_t*),
slsch->payload_length,
slsch_header_len+sizeof(SLSCH_t)-sizeof(uint8_t*)+slsch->payload_length);
multicast_link_write_sock(0,
&pdu,
slsch_header_len+sizeof(SLSCH_t)-sizeof(uint8_t*)+slsch->payload_length);
}
} // sidelink_emulation=1
else if (ue->sidelink_active==0){ // This is first indication of sidelink in this period
ue->sidelink_active = 1;
ue->slsch = slsch;
}
// check and flll SCI portion
check_and_generate_pscch(ue,frame_tx,subframe_tx);
// check_and_generate_pssch(ue,frame_tx,subframe_tx);
}
void pscch_decoding(PHY_VARS_UE *ue,int frame_rx,int subframe_rx,int a,int slot) {
AssertFatal(slot==0 || slot==1, "slot %d is illegal\n",slot);
int Nsymb = 7 - slot;
SLSCH_t *slsch = &ue->slsch_rx;
uint32_t amod = a%(slsch->N_SL_RB);
int32_t rxdataF_ext[2][12];
int32_t drs_ch_estimates[2][12] __attribute__ ((aligned (32)));
int32_t rxdataF_comp[2][12] __attribute__ ((aligned (32)));
int32_t ul_ch_mag[2][12] __attribute__ ((aligned (32)));
int32_t avgs;
uint8_t log2_maxh=0;
int32_t avgU[2];
int nprb;
if (amod<(slsch->N_SL_RB>>1)) nprb = slsch->prb_Start + amod;
else nprb = slsch->prb_End-slsch->N_SL_RB+amod;
// slot FEP
RU_t ru_tmp;
int rxdata_7_5kHz[2][ue->frame_parms.samples_per_tti] __attribute__ ((aligned (32)));
int rxdataF[2][ue->frame_parms.ofdm_symbol_size*ue->frame_parms.symbols_per_tti] __attribute__ ((aligned (32)));
memcpy((void*)&ru_tmp.frame_parms,(void*)&ue->frame_parms,sizeof(LTE_DL_FRAME_PARMS));
ru_tmp.common.rxdata = ue->common_vars.rxdata;
ru_tmp.common.rxdata_7_5kHz = (int32_t**)rxdata_7_5kHz;
ru_tmp.common.rxdataF = (int32_t**)rxdataF;
remove_7_5_kHz(&ru_tmp,(subframe_rx<<1)+slot);
// extract symbols from slot
for (int l=0; l<Nsymb; l++) {
slot_fep_ul(&ru_tmp,l,(subframe_rx<<1)+slot,0);
ulsch_extract_rbs_single((int32_t**)rxdataF,
(int32_t**)rxdataF_ext,
nprb,
1,
l,
(subframe_rx<<1)+slot,
&ue->frame_parms);
}
// channel estimation
lte_ul_channel_estimation(&ue->frame_parms,
(int32_t**)drs_ch_estimates,
(int32_t**)NULL,
(int32_t**)rxdataF_ext,
1,
frame_rx,
subframe_rx,
0,
0,
0,
3,
slot,
0);
avgs = 0;
for (int aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++)
avgs = cmax(avgs,avgU[aarx]);
// log2_maxh = 4+(log2_approx(avgs)/2);
log2_maxh = (log2_approx(avgs)/2)+ log2_approx(ue->frame_parms.nb_antennas_rx-1)+4;
for (int l=0; l<(ue->frame_parms.symbols_per_tti>>1)-1; l++) {
if (((ue->frame_parms.Ncp == 0) && ((l==3) || (l==10)))|| // skip pilots
((ue->frame_parms.Ncp == 1) && ((l==2) || (l==8)))) {
l++;
}
ulsch_channel_compensation((int32_t**)rxdataF_ext,
(int32_t**)drs_ch_estimates,
(int32_t**)ul_ch_mag,
NULL,
(int32_t**)rxdataF_comp,
&ue->frame_parms,
l,
2,
1,
log2_maxh); // log2_maxh+I0_shift
if (ue->frame_parms.nb_antennas_rx > 1)
ulsch_detection_mrc(&ue->frame_parms,
(int32_t**)rxdataF_comp,
(int32_t**)ul_ch_mag,
NULL,
l,
1);
memcpy((void*)&pdu.slsch,(void*)slsch,sizeof(SLSCH_t)-sizeof(uint8_t*));
AssertFatal(slsch->payload_length <=1500-slsch_header_len - sizeof(SLSCH_t) + sizeof(uint8_t*),
"SLSCH payload length > %d\n",
1500-slsch_header_len - sizeof(SLSCH_t) + sizeof(uint8_t*));
memcpy((void*)&pdu.payload[0],
(void*)slsch->payload,
slsch->payload_length);
LOG_I(PHY,"SLSCH configuration %d bytes, TBS payload %d bytes => %d bytes\n",
sizeof(SLSCH_t)-sizeof(uint8_t*),
slsch->payload_length,
slsch_header_len+sizeof(SLSCH_t)-sizeof(uint8_t*)+slsch->payload_length);
// if (23<ulsch_power[0]) {
freq_equalization(&ue->frame_parms,
(int32_t**)rxdataF_comp,
(int32_t**)ul_ch_mag,
NULL,
l,
12,
2);
multicast_link_write_sock(0,
&pdu,
slsch_header_len+sizeof(SLSCH_t)-sizeof(uint8_t*)+slsch->payload_length);
}
idft_slcch(&ue->frame_parms,
rxdataF_comp[0]);
int E=144;
int16_t llr[144];
int16_t *llrp = (int16_t*)&llr[0];
for (int l=0; l<(ue->frame_parms.symbols_per_tti>>1)-slot; l++) {
if (((ue->frame_parms.Ncp == 0) && ((l==3) || (l==10)))|| // skip pilots
((ue->frame_parms.Ncp == 1) && ((l==2) || (l==8)))) {
l++;
}
ulsch_qpsk_llr(&ue->frame_parms,
(int32_t**)rxdataF_comp,
llr,
l,
1,
&llrp);
}
// unscrambling
uint32_t x1,x2=510,k;
uint32_t s = lte_gold_generic(&x1,&x2,1);
for (int i=0,k=0;i<(1+(E>>5));i++)
for (int j=0;(j<32)&&(k<E);j++,k++)
llr[k] = (int16_t)((((s>>j)&1)<<1)-1) * llr[k];
// deinterleaving
int8_t f[144];
int Cmux = (ue->frame_parms.symbols_per_tti>>1)-1-slot;
for (int i=0,j=0;i<Cmux;i++)
// 24 = 12*(Nsymb-1)*2/(Nsymb-1)
for (int r=0;r<24;r++) {
f[((r*Cmux)+1)<<1] = (int8_t)llr[j++];
f[(((r*Cmux)+1)<<1)+1] = (int8_t)llr[j++];
}
uint16_t res;
uint64_t sci_rx;
//decoding
int length = log2_approx(slsch->N_SL_RB*((ue->slsch_rx.N_SL_RB+1)>>1))+31;
dci_decoding(length,144,f,(uint8_t*)&sci_rx);
res = (crc16((uint8_t*)&sci_rx,length)>>16) ^ extract_crc((uint8_t*)&sci_rx,length);
#ifdef DEBUG_SCI_DECODING
printf("crc res =>%x\n",res);
#endif
// unpopulate SCI bit fields
int RAbits = length-31;
if (res==0) {
ue->slsch_rx.freq_hopping_flag = sci_rx&1;
ue->slsch_rx.resource_block_coding = (sci_rx>>1)&((1<<RAbits)-1);
ue->slsch_rx.time_resource_pattern = (sci_rx>>(1+RAbits))&127;
ue->slsch_rx.mcs = (sci_rx>>(1+7+RAbits))&31;
ue->slsch_rx.timing_advance_indication = (sci_rx>>(1+7+5+RAbits))&2047;
ue->slsch_rx.group_destination_id = (sci_rx>>(1+7+5+11+RAbits))&255;
ue->slcch_received = 1;
}
}
void rx_slcch(PHY_VARS_UE *ue,int frame_rx,int subframe_rx) {
AssertFatal(frame_rx<1024 && frame_rx>0,"frame %d is illegal\n",frame_rx);
AssertFatal(subframe_rx<10 && subframe_rx>0,"subframe %d is illegal\n",subframe_rx);
SLSCH_t *slsch = &ue->slsch_rx;
AssertFatal(slsch!=NULL,"SLSCH is null\n");
uint32_t O = slsch->SL_OffsetIndicator;
uint32_t P = slsch->SL_SC_Period;
uint32_t absSF = (frame_rx*10)+subframe_rx;
uint32_t absSF_offset,absSF_modP;
if (ue->slcch_received == 1) return;
absSF_offset = absSF-O;
if (absSF_offset < O) return;
absSF_modP = absSF_offset%P;
// This is the condition for short SCCH bitmap (40 bits), check that the current subframe is for SCCH
if (absSF_modP > 39) return;
uint64_t SFpos = ((uint64_t)1) << absSF_modP;
if ((SFpos & slsch->bitmap1) == 0) return;
// if we get here, then there is a PSCCH subframe for a potential transmission
uint32_t sf_index=40,LPSCCH=0;
for (int i=0;i<40;i++) {
if (i==absSF_modP) sf_index=LPSCCH;
if (((((uint64_t)1)<<i) & slsch->bitmap1)>0) sf_index++;
}
AssertFatal(sf_index<40,"sf_index not set, should not happen\n");
LPSCCH++;
// sf_index now contains the SF index in 0...LPSCCH-1
// LPSCCH has the number of PSCCH subframes
// 2 SLSCH/SLCCH resource block regions subframe times number of resources blocks per slot times 2 slots
uint32_t M_RB_PSCCH_RP = slsch->N_SL_RB*LPSCCH<<2;
AssertFatal(slsch->n_pscch < (M_RB_PSCCH_RP>>1)*LPSCCH,"n_pscch not in 0..%d\n",
((M_RB_PSCCH_RP>>1)*LPSCCH)-1);
// hard-coded to transmission mode one for now (Section 14.2.1.1 from 36.213 Rel14.3)
uint32_t a1=slsch->n_pscch/LPSCCH;
uint32_t a2=a1+slsch->n_pscch/LPSCCH+(M_RB_PSCCH_RP>>1);
uint32_t b1=slsch->n_pscch%LPSCCH;
uint32_t b2=(slsch->n_pscch + 1 + (a1%(LPSCCH-1)))%LPSCCH;
if (absSF_modP == b1) pscch_decoding(ue,frame_rx,subframe_rx,a1,0);
else if (absSF_modP == b2) pscch_decoding(ue,frame_rx,subframe_rx,a2,1);
else return;
}
#endif
......@@ -1140,7 +1140,6 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
Qm = ulsch[UE_id]->harq_processes[harq_pid]->Qm;
#ifdef DEBUG_ULSCH
printf("rx_ulsch: harq_pid %d, nb_rb %d first_rb %d\n",harq_pid,ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,ulsch[UE_id]->harq_processes[harq_pid]->first_rb);
#endif //DEBUG_ULSCH
if (ulsch[UE_id]->harq_processes[harq_pid]->nb_rb == 0) {
......@@ -1152,10 +1151,10 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
#ifdef DEBUG_ULSCH
printf("rx_ulsch : symbol %d (first_rb %d,nb_rb %d), rxdataF %p, rxdataF_ext %p\n",l,
ulsch[UE_id]->harq_processes[harq_pid]->first_rb,
ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,
common_vars->rxdataF,
pusch_vars->rxdataF_ext);
ulsch[UE_id]->harq_processes[harq_pid]->first_rb,
ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,
common_vars->rxdataF,
pusch_vars->rxdataF_ext);
#endif //DEBUG_ULSCH
ulsch_extract_rbs_single(common_vars->rxdataF,
......@@ -1165,11 +1164,25 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
l%(frame_parms->symbols_per_tti/2),
l/(frame_parms->symbols_per_tti/2),
frame_parms);
lte_ul_channel_estimation(eNB,proc,
UE_id,
l%(frame_parms->symbols_per_tti/2),
l/(frame_parms->symbols_per_tti/2));
int Ns = l/(frame_parms->symbols_per_tti/2);
int lmod = l%(frame_parms->symbols_per_tti/2);
int cyclic_shift = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
eNB->ulsch[UE_id]->harq_processes[harq_pid]->n_DMRS2 +
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[(subframe<<1)+Ns]) % 12;
lte_ul_channel_estimation(&eNB->frame_parms,
pusch_vars->drs_ch_estimates,
pusch_vars->drs_ch_estimates_time,
pusch_vars->rxdataF_ext,
ulsch[UE_id]->harq_processes[harq_pid]->nb_rb,
proc->frame_rx,
subframe,
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[Ns+(subframe<<1)],
frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[Ns+(subframe<<1)],
cyclic_shift,
lmod,
Ns,
ulsch[UE_id]->rnti);
}
int correction_factor = 1;
......@@ -1212,7 +1225,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
avgs = 0;
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
avgs = cmax(avgs,avgU[(aarx<<1)]);
avgs = cmax(avgs,avgU[aarx]);
// log2_maxh = 4+(log2_approx(avgs)/2);
......
......@@ -1240,6 +1240,8 @@ typedef struct {
LTE_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX];
LTE_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX];
LTE_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX];
LTE_UE_PSCCH_TX *pscch_vars_tx;
LTE_UE_PSCCH_RX *pscch_vars_rx;
LTE_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][2]; // two RxTx Threads
LTE_UE_ULSCH_t *ulsch[NUMBER_OF_CONNECTED_eNB_MAX];
LTE_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX];
......@@ -1248,7 +1250,11 @@ typedef struct {
LTE_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_eNB_MAX];
// This is for SIC in the UE, to store the reencoded data
LTE_eNB_DLSCH_t *dlsch_eNB[NUMBER_OF_CONNECTED_eNB_MAX];
SL_chan_t sl_chan;
SLSCH_t *slsch;
SLSCH_t slsch_rx;
int slcch_received;
uint8_t sidelink_l2_emulation;
//Paging parameters
uint32_t IMSImod1024;
uint32_t PF;
......@@ -1323,6 +1329,9 @@ typedef struct {
int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
int current_dlsch_cqi[NUMBER_OF_CONNECTED_eNB_MAX];
unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_eNB_MAX];
uint8_t sidelink_active;
uint8_t pscch_coded;
uint8_t pscch_generated;
uint8_t generate_prach;
uint8_t prach_cnt;
uint8_t prach_PreambleIndex;
......
......@@ -344,6 +344,21 @@ typedef enum {
deltaF_PUCCH_Format2b_deltaF2 = 2
} deltaF_PUCCH_Format2b_t;
/// Enumeration of SL_channel_config
typedef enum {
NO_SL=0,
PSCCH_12_EVEN=1,
PSCCH_12_ODD=2,
PSCCH_34_EVEN=3,
PSCCH_34_ODD=4,
PSSCH_12=5,
PSSCH_34=6,
PSDCH_EVEN=7,
PSDCH_ODD=8,
PSBCH=9,
MAX_SLTYPES=10
} SL_chan_t;
/// DeltaFList-PUCCH from 36.331 RRC spec
typedef struct {
deltaF_PUCCH_Format1_t deltaF_PUCCH_Format1;
......@@ -353,6 +368,7 @@ typedef struct {
deltaF_PUCCH_Format2b_t deltaF_PUCCH_Format2b;
} deltaFList_PUCCH_t;
/// SoundingRS-UL-ConfigDedicated Information Element from 36.331 RRC spec
typedef struct {
/// This descriptor is active
......@@ -1068,6 +1084,43 @@ typedef struct {
uint32_t llr_length[14];
} LTE_UE_PDSCH;
typedef struct {
/// \brief Received frequency-domain signal after extraction.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
/// - second index: ? [0..168*N_RB_DL[
int32_t **rxdataF_ext;
/// \brief Hold the channel estimates in time domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..4*ofdm_symbol_size[
int32_t **drs_ch_estimates_time;
/// \brief Hold the channel estimates in frequency domain based on DRS.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t **drs_ch_estimates;
/// \brief Holds the compensated signal.
/// - first index: rx antenna id [0..nb_antennas_rx[
/// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
int32_t **rxdataF_comp;
/// received signal energy of PSCCH
int slcch_power;
/// \brief llr values.
/// - first index: ? [0..1179743] (hard coded)
int16_t *llr;
} LTE_UE_PSCCH_RX;
/// maximum size for N_SL_RB=100, SCI_A=1+13+7+5+11+8 = 45,
#define SCI_A 45
/// SCI_E=12 REs * 6 symbols * 2 bits/RE
#define SCI_E (12*6*2)
typedef struct {
/// Coded PSCCH bits (12 REs, 12 OFDM symbols, 2 bits/RE)
uint8_t f[SCI_E];
// interleaved PSSCH bits
uint8_t h[SCI_E];
// interleaved+scrambled PSSCH bits
uint8_t b_tilde[SCI_E];
} LTE_UE_PSCCH_TX;
typedef struct {
/// \brief Received frequency-domain signal after extraction.
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
......
......@@ -691,7 +691,7 @@ PUCCH_FMT_t get_pucch_format(lte_frame_type_t frame_type,
return pucch_format1a;
}
uint16_t get_n1_pucch(PHY_VARS_UE *ue,
UE_rxtx_proc_t *proc,
UE_rxtx_proc_t *proc,
harq_status_t *harq_ack,
uint8_t eNB_id,
uint8_t *b,
......@@ -2379,8 +2379,9 @@ void phy_procedures_UE_SL_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc) {
LOG_D(PHY,"****** start Sidelink TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, subframe_tx);
// check for SLBCH/SLSS
if ((slss = ue_get_slss(ue->Mod_id,ue->CC_id,frame_tx,subframe_tx)) != NULL) generate_slss(ue,slss,frame_tx,subframe_tx);
if ((slss = ue_get_slss(ue->Mod_id,ue->CC_id,frame_tx,subframe_tx)) != NULL ||
ue->sidelink_active == 1) generate_slss(ue,slss,frame_tx,subframe_tx);
// check for SLDCH
if ((sldch = ue_get_sldch(ue->Mod_id,ue->CC_id,frame_tx,subframe_tx)) != NULL) generate_sldch(ue,sldch,frame_tx,subframe_tx);
......
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