Commit 27a311ab authored by Florian Kaltenberger's avatar Florian Kaltenberger

vcd: added some more traces for PHY

pdcp_thread: bugfix in init 
lte-softmodem: changed thread priority for emos and xforms, changed gains for external rf, changed compile options to O2 (now possible with dlsch_demodulation fix)
new firmware version (see changelog openair0)
dlsch_demodulation: using sse4 extract for llrs
pmi_feedback now stored independend of harq_process_id
dlsim: fixed memory leak, improved csv output, changed compile option to O2 (now possible with dlsch_demodulation fix)
removed unused files


git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4174 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent bae7fb2a
......@@ -2058,7 +2058,8 @@ int generate_ue_dlsch_params_from_dci(uint8_t subframe,
case 5:
dlsch0->harq_processes[harq_pid]->mimo_mode = PUSCH_PRECODING0;
// pmi stored from ulsch allocation routine
//msg("using PMI %x\n",pmi2hex_2Ar1(dlsch0->harq_processes[harq_pid]->pmi_alloc));
dlsch0->harq_processes[harq_pid]->pmi_alloc = dlsch0->pmi_alloc;
//LOG_I(PHY,"XXX using PMI %x\n",pmi2hex_2Ar1(dlsch0->harq_processes[harq_pid]->pmi_alloc));
break;
case 6:
dlsch0->harq_processes[harq_pid]->mimo_mode = PUSCH_PRECODING1;
......@@ -2214,7 +2215,9 @@ int generate_ue_dlsch_params_from_dci(uint8_t subframe,
case 5:
dlsch0->harq_processes[harq_pid]->mimo_mode = PUSCH_PRECODING0;
// pmi stored from ulsch allocation routine
break;
dlsch0->harq_processes[harq_pid]->pmi_alloc = dlsch0->pmi_alloc;
//LOG_I(PHY,"XXX using PMI %x\n",pmi2hex_2Ar1(dlsch0->harq_processes[harq_pid]->pmi_alloc));
break;
case 6:
dlsch0->harq_processes[harq_pid]->mimo_mode = PUSCH_PRECODING1;
LOG_E(PHY,"Unsupported TPMI\n");
......
......@@ -614,6 +614,8 @@ typedef struct {
uint32_t cqi_alloc1;
/// Current subband CQI2 allocation
uint32_t cqi_alloc2;
/// saved subband PMI allocation from last PUSCH/PUCCH report
uint16_t pmi_alloc;
/// HARQ-ACKs
harq_status_t harq_ack[10];
/// Pointers to up to 8 HARQ processes
......
......@@ -45,6 +45,7 @@
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/LTE_TRANSPORT/defs.h"
#include "defs.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
//#define DEBUG_DLSCH_CODING
//#define DEBUG_DLSCH_FREE 1
......@@ -223,6 +224,8 @@ int dlsch_encoding(unsigned char *a,
unsigned int Kr=0,Kr_bytes,r,r_offset=0;
unsigned short m=dlsch->harq_processes[harq_pid]->mcs;
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);
A = dlsch->harq_processes[harq_pid]->TBS; //6228
// printf("Encoder: A: %d\n",A);
mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);
......@@ -353,6 +356,8 @@ int dlsch_encoding(unsigned char *a,
write_output("enc_output.m","enc",dlsch->e,r_offset,1,4);
#endif
}
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return(0);
}
......
......@@ -152,7 +152,7 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue,
if (frame_parms->nb_antennas_tx_eNB>1) {
#ifdef DEBUG_DLSCH_MOD
msg("dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc),dlsch_ue[0],dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc[0]);
LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc),dlsch_ue[0],dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc[0]);
#endif
nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF,
lte_ue_common_vars->dl_ch_estimates[eNB_id],
......@@ -261,7 +261,7 @@ int rx_pdsch(PHY_VARS_UE *phy_vars_ue,
// avgs = cmax(avgs,avg[(aarx<<1)+aatx]);
lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2);// + 2
lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2);
// + log2_approx(frame_parms->nb_antennas_tx_eNB-1) //-1 because log2_approx counts the number of bits
// + log2_approx(frame_parms->nb_antennas_rx-1);
......
......@@ -46,6 +46,9 @@
#include <pmmintrin.h>
#include <tmmintrin.h>
#endif
#ifdef __SSE4_1__
#include <smmintrin.h>
#endif
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
......@@ -757,14 +760,14 @@ void dlsch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
// lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2
llr128[0] = _mm_unpacklo_epi32(rxF[i],xmm0);
llr128[1] = _mm_unpackhi_epi32(rxF[i],xmm0);
llr32[0] = ((u32 *)&llr128[0])[0];
llr32[1] = ((u32 *)&llr128[0])[1];
llr32[2] = ((u32 *)&llr128[0])[2];
llr32[3] = ((u32 *)&llr128[0])[3];
llr32[4] = ((u32 *)&llr128[1])[0];
llr32[5] = ((u32 *)&llr128[1])[1];
llr32[6] = ((u32 *)&llr128[1])[2];
llr32[7] = ((u32 *)&llr128[1])[3];
llr32[0] = _mm_extract_epi32(llr128[0],0); //((u32 *)&llr128[0])[0];
llr32[1] = _mm_extract_epi32(llr128[0],1); //((u32 *)&llr128[0])[1];
llr32[2] = _mm_extract_epi32(llr128[0],2); //((u32 *)&llr128[0])[2];
llr32[3] = _mm_extract_epi32(llr128[0],3); //((u32 *)&llr128[0])[3];
llr32[4] = _mm_extract_epi32(llr128[1],0); //((u32 *)&llr128[1])[0];
llr32[5] = _mm_extract_epi32(llr128[1],1); //((u32 *)&llr128[1])[1];
llr32[6] = _mm_extract_epi32(llr128[1],2); //((u32 *)&llr128[1])[2];
llr32[7] = _mm_extract_epi32(llr128[1],3); //((u32 *)&llr128[1])[3];
llr32+=8;
}
_mm_empty();
......@@ -788,7 +791,7 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
__m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
__m128i *ch_mag,*ch_magb;
int j=0,i,len,len2;
int i,len,len2;
unsigned char symbol_mod,len_mod4;
short *llr;
s16 *llr2;
......@@ -828,6 +831,7 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
xmm2 = _mm_subs_epi16(ch_magb[i],xmm2);
// loop over all LLRs in quad word (24 coded bits)
/*
for (j=0;j<8;j+=2) {
llr2[0] = ((short *)&rxF[i])[j];
llr2[1] = ((short *)&rxF[i])[j+1];
......@@ -838,6 +842,40 @@ void dlsch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
llr2+=6;
}
*/
llr2[0] = ((short *)&rxF[i])[0];
llr2[1] = ((short *)&rxF[i])[1];
llr2[2] = _mm_extract_epi16(xmm1,0);
llr2[3] = _mm_extract_epi16(xmm1,1);//((short *)&xmm1)[j+1];
llr2[4] = _mm_extract_epi16(xmm2,0);//((short *)&xmm2)[j];
llr2[5] = _mm_extract_epi16(xmm2,1);//((short *)&xmm2)[j+1];
llr2+=6;
llr2[0] = ((short *)&rxF[i])[2];
llr2[1] = ((short *)&rxF[i])[3];
llr2[2] = _mm_extract_epi16(xmm1,2);
llr2[3] = _mm_extract_epi16(xmm1,3);//((short *)&xmm1)[j+1];
llr2[4] = _mm_extract_epi16(xmm2,2);//((short *)&xmm2)[j];
llr2[5] = _mm_extract_epi16(xmm2,3);//((short *)&xmm2)[j+1];
llr2+=6;
llr2[0] = ((short *)&rxF[i])[4];
llr2[1] = ((short *)&rxF[i])[5];
llr2[2] = _mm_extract_epi16(xmm1,4);
llr2[3] = _mm_extract_epi16(xmm1,5);//((short *)&xmm1)[j+1];
llr2[4] = _mm_extract_epi16(xmm2,4);//((short *)&xmm2)[j];
llr2[5] = _mm_extract_epi16(xmm2,5);//((short *)&xmm2)[j+1];
llr2+=6;
llr2[0] = ((short *)&rxF[i])[6];
llr2[1] = ((short *)&rxF[i])[7];
llr2[2] = _mm_extract_epi16(xmm1,6);
llr2[3] = _mm_extract_epi16(xmm1,7);//((short *)&xmm1)[j+1];
llr2[4] = _mm_extract_epi16(xmm2,6);//((short *)&xmm2)[j];
llr2[5] = _mm_extract_epi16(xmm2,7);//((short *)&xmm2)[j+1];
llr2+=6;
}
*llr_save = llr;
_mm_empty();
......
......@@ -44,6 +44,7 @@
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/LTE_TRANSPORT/defs.h"
#include "defs.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
//#define DEBUG_DLSCH_MODULATION
......@@ -768,6 +769,8 @@ int dlsch_modulation(mod_sym_t **txdataF,
int16_t qam16_table_a[4],qam64_table_a[8],qam16_table_b[4],qam64_table_b[8];
int16_t *qam_table_s;
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_IN);
nsymb = (frame_parms->Ncp==0) ? 14:12;
amp_rho_a = (int16_t)(((int32_t)amp*dlsch->sqrt_rho_a)>>13);
......@@ -995,6 +998,8 @@ int dlsch_modulation(mod_sym_t **txdataF,
msg("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->nb_rb,dlsch->rb_alloc,mod_order,2,0,subframe_offset));
#endif
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
return (re_allocated);
}
......
......@@ -46,6 +46,8 @@
#include "defs.h"
#include "extern.h"
#include "PHY/extern.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
int mbsfn_flag,
LTE_eNB_DLSCH_t *dlsch,
......@@ -58,6 +60,8 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
u32 x1, x2, s=0;
u8 *e=dlsch->e;
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_IN);
// reset = 1;
// x1 is set in lte_gold_generic
if (mbsfn_flag == 0) {
......@@ -84,6 +88,8 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
s = lte_gold_generic(&x1, &x2, 0);
}
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_OUT);
}
......
......@@ -200,7 +200,7 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t
if (phy_vars_ue->transmission_mode[eNB] == 6)
len += sprintf(&buffer[len], "[UE PROC] Mode 6 Wideband CQI eNB %d : %d dB\n",eNB,phy_vars_ue->PHY_measurements.precoded_cqi_dB[eNB][0]);
if (phy_vars_ue->dlsch_ue[0] && phy_vars_ue->dlsch_ue[0][0] && phy_vars_ue->dlsch_ue[0][1]) {
len += sprintf(&buffer[len], "[UE PROC] Saved PMI for DLSCH eNB %d : %x (%p)\n",eNB,pmi2hex_2Ar1(phy_vars_ue->dlsch_ue[0][0]->harq_processes[0]->pmi_alloc),phy_vars_ue->dlsch_ue[0][0]);
len += sprintf(&buffer[len], "[UE PROC] Saved PMI for DLSCH eNB %d : %x (%p)\n",eNB,pmi2hex_2Ar1(phy_vars_ue->dlsch_ue[0][0]->pmi_alloc),phy_vars_ue->dlsch_ue[0][0]);
len += sprintf(&buffer[len], "[UE PROC] eNB %d: dl_power_off = %d\n",eNB,phy_vars_ue->dlsch_ue[0][0]->harq_processes[0]->dl_power_off);
......@@ -222,6 +222,7 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t
#endif
len += sprintf(&buffer[len], "[UE PROC] DLSCH Bitrate %dkbps\n",(phy_vars_ue->bitrate[0]/1000));
len += sprintf(&buffer[len], "[UE PROC] Total Received Bits %dkbits\n",(phy_vars_ue->total_received_bits[0]/1000));
len += sprintf(&buffer[len], "[UE PROC] IA receiver %d\n",openair_daq_vars.use_ia_receiver);
}
......
......@@ -297,43 +297,43 @@ void print_CQI(void *o,UCI_format_t uci_format,unsigned char eNB_id) {
switch(uci_format){
case wideband_cqi_rank1_2A:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] wideband_cqi rank 1: eNB %d, cqi %d\n",eNB_id,((wideband_cqi_rank1_2A_5MHz *)o)->cqi1);
LOG_D(PHY,"[PRINT CQI] wideband_cqi rank 1: eNB %d, pmi (%x) %8x\n",eNB_id,((wideband_cqi_rank1_2A_5MHz *)o)->pmi,pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)o)->pmi));
LOG_I(PHY,"[PRINT CQI] wideband_cqi rank 1: eNB %d, cqi %d\n",eNB_id,((wideband_cqi_rank1_2A_5MHz *)o)->cqi1);
LOG_I(PHY,"[PRINT CQI] wideband_cqi rank 1: eNB %d, pmi (%x) %8x\n",eNB_id,((wideband_cqi_rank1_2A_5MHz *)o)->pmi,pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)o)->pmi));
#endif //DEBUG_UCI
break;
case wideband_cqi_rank2_2A:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] wideband_cqi rank 2: eNB %d, cqi1 %d\n",eNB_id,((wideband_cqi_rank2_2A_5MHz *)o)->cqi1);
LOG_D(PHY,"[PRINT CQI] wideband_cqi rank 2: eNB %d, cqi2 %d\n",eNB_id,((wideband_cqi_rank2_2A_5MHz *)o)->cqi2);
LOG_D(PHY,"[PRINT CQI] wideband_cqi rank 2: eNB %d, pmi %8x\n",eNB_id,pmi2hex_2Ar2(((wideband_cqi_rank2_2A_5MHz *)o)->pmi));
LOG_I(PHY,"[PRINT CQI] wideband_cqi rank 2: eNB %d, cqi1 %d\n",eNB_id,((wideband_cqi_rank2_2A_5MHz *)o)->cqi1);
LOG_I(PHY,"[PRINT CQI] wideband_cqi rank 2: eNB %d, cqi2 %d\n",eNB_id,((wideband_cqi_rank2_2A_5MHz *)o)->cqi2);
LOG_I(PHY,"[PRINT CQI] wideband_cqi rank 2: eNB %d, pmi %8x\n",eNB_id,pmi2hex_2Ar2(((wideband_cqi_rank2_2A_5MHz *)o)->pmi));
#endif //DEBUG_UCI
break;
case HLC_subband_cqi_nopmi:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] hlc_cqi (no pmi) : eNB %d, cqi1 %d\n",eNB_id,((HLC_subband_cqi_rank1_2A_5MHz *)o)->cqi1);
LOG_D(PHY,"[PRINT CQI] hlc_cqi (no pmi) : eNB %d, diffcqi1 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank1_2A_5MHz *)o)->diffcqi1));
LOG_I(PHY,"[PRINT CQI] hlc_cqi (no pmi) : eNB %d, cqi1 %d\n",eNB_id,((HLC_subband_cqi_rank1_2A_5MHz *)o)->cqi1);
LOG_I(PHY,"[PRINT CQI] hlc_cqi (no pmi) : eNB %d, diffcqi1 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank1_2A_5MHz *)o)->diffcqi1));
#endif //DEBUG_UCI
break;
case HLC_subband_cqi_rank1_2A:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 1: eNB %d, cqi1 %d\n",eNB_id,((HLC_subband_cqi_rank1_2A_5MHz *)o)->cqi1);
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 1: eNB %d, diffcqi1 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank1_2A_5MHz *)o)->diffcqi1));
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 1: eNB %d, pmi %d\n",eNB_id,((HLC_subband_cqi_rank1_2A_5MHz *)o)->pmi);
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 1: eNB %d, cqi1 %d\n",eNB_id,((HLC_subband_cqi_rank1_2A_5MHz *)o)->cqi1);
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 1: eNB %d, diffcqi1 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank1_2A_5MHz *)o)->diffcqi1));
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 1: eNB %d, pmi %d\n",eNB_id,((HLC_subband_cqi_rank1_2A_5MHz *)o)->pmi);
#endif //DEBUG_UCI
break;
case HLC_subband_cqi_rank2_2A:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, cqi1 %d\n",eNB_id,((HLC_subband_cqi_rank2_2A_5MHz *)o)->cqi1);
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, cqi2 %d\n",eNB_id,((HLC_subband_cqi_rank2_2A_5MHz *)o)->cqi2);
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, diffcqi1 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank2_2A_5MHz *)o)->diffcqi1));
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, diffcqi2 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank2_2A_5MHz *)o)->diffcqi2));
LOG_D(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, pmi %d\n",eNB_id,((HLC_subband_cqi_rank2_2A_5MHz *)o)->pmi);
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, cqi1 %d\n",eNB_id,((HLC_subband_cqi_rank2_2A_5MHz *)o)->cqi1);
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, cqi2 %d\n",eNB_id,((HLC_subband_cqi_rank2_2A_5MHz *)o)->cqi2);
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, diffcqi1 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank2_2A_5MHz *)o)->diffcqi1));
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, diffcqi2 %8x\n",eNB_id,cqi2hex(((HLC_subband_cqi_rank2_2A_5MHz *)o)->diffcqi2));
LOG_I(PHY,"[PRINT CQI] hlc_cqi rank 2: eNB %d, pmi %d\n",eNB_id,((HLC_subband_cqi_rank2_2A_5MHz *)o)->pmi);
#endif //DEBUG_UCI
break;
case HLC_subband_cqi_mcs_CBA:
#ifdef DEBUG_UCI
LOG_D(PHY,"[PRINT CQI] hlc_cqi_mcs_CBA : eNB %d, mcs %d\n",eNB_id,((HLC_subband_cqi_mcs_CBA_5MHz *)o)->mcs);
LOG_D(PHY,"[PRINT CQI] hlc_cqi_mcs_CBA : eNB %d, rnti %x\n",eNB_id,((HLC_subband_cqi_mcs_CBA_5MHz *)o)->crnti);
LOG_I(PHY,"[PRINT CQI] hlc_cqi_mcs_CBA : eNB %d, mcs %d\n",eNB_id,((HLC_subband_cqi_mcs_CBA_5MHz *)o)->mcs);
LOG_I(PHY,"[PRINT CQI] hlc_cqi_mcs_CBA : eNB %d, rnti %x\n",eNB_id,((HLC_subband_cqi_mcs_CBA_5MHz *)o)->crnti);
#endif //DEBUG_UCI
break;
case ue_selected:
......
......@@ -248,9 +248,10 @@ u32 ulsch_encoding(u8 *a,
print_CQI(ulsch->o,ulsch->uci_format,0);
// save PUSCH pmi for later (transmission modes 4,5,6)
// msg("ulsch: saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi));
if (dlsch[0])
dlsch[0]->harq_processes[harq_pid]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi;
if (dlsch[0]) {
//LOG_I(PHY,"XXX saving pmi for DL %x\n",pmi2hex_2Ar1(((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi));
dlsch[0]->pmi_alloc = ((wideband_cqi_rank1_2A_5MHz *)ulsch->o)->pmi;
}
}
if (ulsch->O<=32) {
......
......@@ -10,8 +10,8 @@ int write_output(const char *fname,const char *vname,void *data,int length,int d
int i;
// printf("Writing %d elements of type %d to %s\n",length,format,fname);
// printf("Writing %d elements of type %d to %s\n",length,format,fname);
printf("Writing %d elements of type %d to %s\n",length,format,fname);
printf("Writing %d elements of type %d to %s\n",length,format,fname);
if (format == 10 || format ==11 || format == 12 )
......
......@@ -374,7 +374,7 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) {
// Generic UE Button
fdui->button_0 = fl_add_button( FL_PUSH_BUTTON, 540, 720, 240, 40, "" );
fl_set_object_lalign(fdui->button_0, FL_ALIGN_CENTER );
openair_daq_vars.use_ia_receiver = 0;
//openair_daq_vars.use_ia_receiver = 0;
fl_set_button(fdui->button_0,0);
fl_set_object_label(fdui->button_0, "IA Receiver OFF");
fl_set_object_color(fdui->button_0, FL_RED, FL_RED);
......
......@@ -488,7 +488,7 @@ void phy_procedures_emos_eNB_RX(unsigned char last_slot,PHY_VARS_eNB *phy_vars_e
}
else {
if (phy_vars_eNB->frame%100==0) {
LOG_D(PHY,"[eNB %d] Frame %d (%d), slot %d, Writing %d bytes EMOS data to FIFO\n",
LOG_I(PHY,"[eNB %d] Frame %d (%d), slot %d, Writing %d bytes EMOS data to FIFO\n",
phy_vars_eNB->Mod_id,phy_vars_eNB->frame, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, last_slot, bytes);
}
}
......@@ -517,7 +517,6 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
DCI_pdu->Num_ue_spec_dci=0;
switch (subframe) {
/*
case 5:
DCI_pdu->Num_common_dci = 1;
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_5MHz_TDD_1_6_t;
......@@ -536,7 +535,6 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
BCCH_alloc_pdu.TPC = 1; // set to 3 PRB
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],&BCCH_alloc_pdu,sizeof(DCI1A_5MHz_TDD_1_6_t));
break;
*/
case 6:
/*
DCI_pdu->Num_ue_spec_dci = 1;
......@@ -558,8 +556,8 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&DLSCH_alloc_pdu1,sizeof(DCI2_5MHz_2A_M10PRB_TDD_t));
*/
break;
case 5:
DCI_pdu->Num_ue_spec_dci = 1;
case 7:
DCI_pdu->Num_ue_spec_dci = 1;
if (transmission_mode<3) {
//user 1
......@@ -606,7 +604,7 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
DLSCH_alloc_pdu1E.tpmi = 5; //5=use feedback
DLSCH_alloc_pdu1E.rv = 0;
DLSCH_alloc_pdu1E.ndi = 1;
DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu1E.mcs = cqi_to_mcs[phy_vars_eNB->eNB_UE_stats->DL_cqi[0]];//openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu1E.harq_pid = 0;
DLSCH_alloc_pdu1E.dai = 0;
DLSCH_alloc_pdu1E.TPC = 0;
......@@ -621,6 +619,7 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
DCI_pdu->dci_alloc[1].rnti = 0x1236;
DCI_pdu->dci_alloc[1].format = format1E_2A_M10PRB;
DCI_pdu->dci_alloc[1].ra_flag = 0;
//DLSCH_alloc_pdu1E.mcs = openair_daq_vars.target_ue_dl_mcs;
DLSCH_alloc_pdu1E.mcs = (unsigned char) (taus()%28);
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&DLSCH_alloc_pdu1E,sizeof(DCI1E_5MHz_2A_M10PRB_TDD_t));
......@@ -651,7 +650,7 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
break;
*/
case 9:
DCI_pdu->Num_ue_spec_dci = 1;
DCI_pdu->Num_ue_spec_dci = 2;
//user 1
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ;
......@@ -668,10 +667,9 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
UL_alloc_pdu.TPC = 0;
UL_alloc_pdu.cshift = 0;
UL_alloc_pdu.dai = 0;
UL_alloc_pdu.cqi_req = 0;
UL_alloc_pdu.cqi_req = 1;
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD_1_6_t));
//user 2
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI0_5MHz_TDD_1_6_t ;
DCI_pdu->dci_alloc[1].L = 2;
DCI_pdu->dci_alloc[1].rnti = 0x1236;
......@@ -692,7 +690,7 @@ void fill_dci(DCI_PDU *DCI_pdu, u8 subframe, PHY_VARS_eNB *phy_vars_eNB) {
else
UL_alloc_pdu.cshift = 1;
UL_alloc_pdu.dai = 0;
UL_alloc_pdu.cqi_req = 0;
UL_alloc_pdu.cqi_req = 1;
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&UL_alloc_pdu,sizeof(DCI0_5MHz_TDD_1_6_t));
break;
......@@ -1253,12 +1251,16 @@ void phy_procedures_eNB_TX(unsigned char next_slot,PHY_VARS_eNB *phy_vars_eNB,u8
next_slot>>1);
#else
DCI_pdu = &DCI_pdu_tmp;
/*
if ((phy_vars_eNB->frame%1000 == 0) && (phy_vars_eNB->frame>=500) && (next_slot == 0) && (openair_daq_vars.target_ue_dl_mcs<28)) {
#ifdef EMOS
if ((phy_vars_eNB->frame%1000 == 0) && (phy_vars_eNB->frame>1000) && (next_slot == 0) && (openair_daq_vars.target_ue_dl_mcs<28)) {
openair_daq_vars.target_ue_dl_mcs++;
msg("[MYEMOS] frame %d, increasing MCS to %d\n",phy_vars_eNB->frame,openair_daq_vars.target_ue_dl_mcs);
}
*/
if (phy_vars_eNB->frame > 28000) {
LOG_E(PHY,"More that 28000 frames reached! Exiting!\n");
mac_xface->macphy_exit("");
}
#endif
#ifdef EMOS_CHANNEL
fill_dci_emos(DCI_pdu,next_slot>>1,phy_vars_eNB);
#else
......
......@@ -1521,8 +1521,8 @@ void phy_procedures_emos_UE_RX(PHY_VARS_UE *phy_vars_ue,u8 last_slot,u8 eNB_id)
emos_dump_UE.total_TBS_last = phy_vars_ue->total_TBS_last[eNB_id];
emos_dump_UE.bitrate = phy_vars_ue->bitrate[eNB_id];
emos_dump_UE.total_received_bits = phy_vars_ue->total_received_bits[eNB_id];
emos_dump_UE.pmi_saved = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[1]->pmi_alloc;
emos_dump_UE.mcs = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[1]->mcs;
emos_dump_UE.pmi_saved = phy_vars_ue->dlsch_ue[eNB_id][0]->pmi_alloc;
emos_dump_UE.mcs = phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->mcs;
emos_dump_UE.use_ia_receiver = openair_daq_vars.use_ia_receiver;
bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_UE, sizeof(fifo_dump_emos_UE));
......@@ -1749,8 +1749,12 @@ void lte_ue_pbch_procedures(u8 eNB_id,u8 last_slot, PHY_VARS_UE *phy_vars_ue,u8
phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors++;
#ifdef OPENAIR2
mac_xface->out_of_sync_ind(phy_vars_ue->Mod_id,phy_vars_ue->frame,eNB_id);
#else
if (phy_vars_ue->lte_ue_pbch_vars[eNB_id]->pdu_errors_conseq>=100) {
LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n");
mac_xface->macphy_exit("");
}
#endif
//mac_xface->macphy_exit("");
}
if (phy_vars_ue->frame % 100 == 0) {
......@@ -2200,6 +2204,12 @@ int lte_ue_pdcch_procedures(u8 eNB_id,u8 last_slot, PHY_VARS_UE *phy_vars_ue,u8
(r_type == multicast_relay) ? "RN/UE" : "UE",
phy_vars_ue->Mod_id,phy_vars_ue->frame, last_slot>>1, last_slot);
#endif
#ifdef EMOS
if ((phy_vars_ue->frame%500 == 0) && (phy_vars_ue->frame>=500) && (last_slot == 0)) {
openair_daq_vars.use_ia_receiver = !openair_daq_vars.use_ia_receiver;
LOG_I(PHY,"[MYEMOS] frame %d, IA receiver %d, MCS %d, bitrate %d\n",phy_vars_ue->frame,openair_daq_vars.use_ia_receiver, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs,phy_vars_ue->bitrate[eNB_id]);
}
#endif
if (phy_vars_ue->lte_frame_parms.Ncp == 0) { // normal prefix
pilot1 = 4;
......
/*
// \author R. Knopp
// \date 02.06.2004 (initial WIDENS version)
// updated 04.04.2006 (migration to 2.6.x kernels)
// updated 01.06.2006 (updates by M. Guillaud for MIMO sounder, new HW tracking mechanism)
// updated 01.08.2006 (integration of PLATON hardware support)
// updated 15.01.2007 (RX/TX FIFO debug support, RK)
// updated 21.05.2007 (structural changes,GET Frame fifo support, RK)
* @{
*/
/*
* @addtogroup _physical_layer_ref_implementation_
\section _process_scheduling_ Process Scheduling
This section deals with real-time process scheduling for PHY and synchronization with certain hardware targets (PLATON,CBMIMO1).
*/
#ifndef USER_MODE
#define __NO_VERSION__
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
#ifdef RTAI_ISNT_POSIX
#include "rt_compat.h"
#endif /* RTAI_ISNT_POSIX */
#include "MAC_INTERFACE/extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h"
#endif // CBMIMO1
#ifdef RTAI_ENABLED
#include <rtai.h>
#include <rtai_posix.h>
#include <rtai_fifos.h>
#endif //
#else
#include <stdio.h>
#include <stdlib.h>
#endif // /* USER_MODE */
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/TRANSPORT/defs.h"
#include "extern.h"
//#include "dummy_driver.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/from_grlib_softregs.h"
#endif //CBMIMO1
#ifdef SERIAL_IO
#include "rtai_serial.h"
#endif
#ifdef EMOS
#include "phy_procedures_emos.h"
#endif
/// Mutex for instance count on MACPHY scheduling
pthread_mutex_t openair_mutex;
/// Condition variable for MACPHY thread
pthread_cond_t openair_cond;
/// Threads
pthread_t threads[openair_SCHED_NB_THREADS]={NULL,NULL,NULL};
/// Thread Attributes
pthread_attr_t attr_threads[openair_SCHED_NB_THREADS];
/// RX Signal FIFO for Testing without hardware
#define RX_SIG_FIFO_NUMBER 59
int rx_sig_fifo = RX_SIG_FIFO_NUMBER;
/// RX Control FIFO for testing without hardware
#define RF_CNTL_FIFO_NUMBER 60
int rf_cntl_fifo = RF_CNTL_FIFO_NUMBER;
#ifdef NOCARD_TEST
/// RX Signal FIFO Mutex
pthread_mutex_t openair_rx_fifo_mutex;
/// RX Signal FIFO Condition variable
pthread_cond_t openair_rx_fifo_cond;
/// Packet for RX Signal Control
RF_CNTL_PACKET rf_cntl_packet;
#endif //NOCARD_TEST
/// Global exit variable (exit on error or manual stop via IOCTL)
int exit_openair = 0;
#define NO_SYNC_TEST 1
#ifdef CBMIMO1
#define NUMBER_OF_CHUNKS_PER_SLOT NUMBER_OF_OFDM_SYMBOLS_PER_SLOT
#define NUMBER_OF_CHUNKS_PER_FRAME (NUMBER_OF_CHUNKS_PER_SLOT * SLOTS_PER_FRAME)
#ifdef CLOCK768
#define NS_PER_CHUNK 41667 // (7.68 msps, 320 samples per OFDM symbol/CHUNK) //44308 // (6.5 msps, 288 samples per OFDM symbol)
#else
#define NS_PER_CHUNK 49231 // (6.5 msps, 320 samples per OFDM symbol/CHUNK)
#endif
#define SYNCH_WAIT_TIME 4096 // number of symbols between SYNCH retries
#define SYNCH_WAIT_TIME_RUNNING 128 // number of symbols between SYNCH retries
#define DRIFT_OFFSET 300
#define NS_PER_SLOT (NS_PER_CHUNK * NUMBER_OF_CHUNKS_PER_SLOT)
#define US_PER_SLOT (NS_PER_SLOT * 0.001)
#define MAX_DRIFT_COMP 3000
#endif // CBMIMO1
#ifdef PLATON
#define NUMBER_OF_CHUNKS_PER_SLOT 10
#define NUMBER_OF_CHUNKS_PER_FRAME (NUMBER_OF_CHUNKS_PER_SLOT * SLOTS_PER_FRAME)
#define NS_PER_CHUNK 66667 // (7.68 msps, 512 samples per chunk
#define SYNCH_WAIT_TIME 2048
#define SYNCH_WAIT_TIME_RUNNING 128 // number of symbols between SYNCH retries
//#define SLOTS_PER_FRAME 15
#define DRIFT_OFFSET 300
#define MAX_DRIFT_COMP 10000
#endif // PLATON
#define MAX_SCHED_CNT 50000000
unsigned char first_sync_call;
//-----------------------------------------------------------------------------
/** MACPHY Thread */
static void * openair_thread(void *param) {
//-----------------------------------------------------------------------------
//------------------------------
#ifndef USER_MODE
struct sched_param p;
#endif // /* USER_MODE */
u8 next_slot, last_slot,i;
unsigned int time_in,time_out;
#ifdef SERIAL_IO
msg("[SCHED][OPENAIR THREAD] Opening RT serial port interface\n");
rt_spopen(COM1,38400,8,1,RT_SP_PARITY_NONE,RT_SP_NO_HAND_SHAKE,RT_SP_FIFO_SIZE_14);
rt_msg("[SCHED][OPENAIR THREAD] Opened RT Serial Port Interface\n");
#endif
p.sched_priority = OPENAIR_THREAD_PRIORITY;
pthread_attr_setschedparam (&attr_threads[OPENAIR_THREAD_INDEX], &p);
#ifndef RTAI_ISNT_POSIX
pthread_attr_setschedpolicy (&attr_threads[OPENAIR_THREAD_INDEX], SCHED_FIFO);
#endif
msg("[openair][SCHED][openair_thread] openair_thread started with id %x, fpu_flag = %x\n",(unsigned int)pthread_self(),pthread_self()->uses_fpu);
if (mac_xface->is_primary_cluster_head == 1)
msg("[openair][SCHED][openair_thread] Configuring openair_thread for primary clusterhead\n");
else if (mac_xface->is_secondary_cluster_head == 1)
msg("[openair][SCHED][openair_thread] Configuring openair_thread for secondary clusterhead\n");
else
msg("[openair][SCHED][INFO] Configuring OPENAIR THREAD for regular node\n");
exit_openair = 0;
PHY_vars->rx_vars[0].rx_total_gain_dB = MIN_RF_GAIN;//138;
#ifdef CBMIMO1
openair_set_rx_gain_cal_openair(PHY_vars->rx_vars[0].rx_total_gain_dB);
// turn on AGC by default
openair_daq_vars.rx_gain_mode = DAQ_AGC_ON;
#endif
openair_daq_vars.synch_source = 1; //by default we sync to CH1
for (i=0;i<PHY_config->total_no_chsch;i++){
#ifdef DEBUG_PHY
msg("[OPENAIR][SCHED] Initializing CHSCH %d\n",i);
#endif //DEBUG_PHY
phy_chsch_init_rt_part(i);
}
for (i=0;i<PHY_config->total_no_sch;i++){
#ifdef DEBUG_PHY
msg("[OPENAIR][SCHED] Initializing SCH %d\n",i);
#endif //DEBUG_PHY
phy_sch_init_rt_part(i);
}
// Inner thread endless loop
// exits on error or normally
sach_error_cnt = 0;
openair_daq_vars.sched_cnt = 0;
openair_daq_vars.instance_cnt = -1;
#ifdef PLATON
for (i=0;i<NB_ANTENNAS_RX;i++)
Zero_Buffer(&PHY_vars->tx_vars[i].TX_DMA_BUFFER[0],
4*SLOT_LENGTH_BYTES_NO_PREFIX);
#else
Zero_Buffer(&PHY_vars->tx_vars[0].TX_DMA_BUFFER[0],
4*SLOT_LENGTH_BYTES_NO_PREFIX);
#endif
// fk 20090324: This code is in phy_procedures_emos.c
/*
#ifdef EMOS
// Initialization of the TX signal for EMOS Part I: Pilot symbols
if (mac_xface->is_primary_cluster_head) {
for (i = 12; i < 21; i++)
{
#ifdef CBMIMO1
// cbmimo1 already removes the cyclic prefix
phy_generate_sch (0, 1, i, 0xFFFF, 0, NB_ANTENNAS_TX);
#else // User-space simulation or PLATON
phy_generate_sch (0, 1, i, 0xFFFF, 1, NB_ANTENNAS_TX);
#endif
}
}
else if (mac_xface->is_secondary_cluster_head) {
for (i = 22; i < 31; i++)
{
#ifdef CBMIMO1
// cbmimo1 already removes the cyclic prefix
phy_generate_sch (0, 2, i, 0xFFFF, 0, NB_ANTENNAS_TX);
#else // User-space simulation or PLATON
phy_generate_sch (0, 2, i, 0xFFFF, 1, NB_ANTENNAS_TX);
#endif
}
}
#endif //EMOS
*/
while (exit_openair == 0){
pthread_mutex_lock(&openair_mutex);
while (openair_daq_vars.instance_cnt < 0) {
pthread_cond_wait(&openair_cond,&openair_mutex);
}
openair_daq_vars.instance_cnt--;
pthread_mutex_unlock(&openair_mutex);
next_slot = (openair_daq_vars.slot_count + 1 ) % SLOTS_PER_FRAME;
last_slot = (openair_daq_vars.slot_count - 1 ) % SLOTS_PER_FRAME;
// msg("[SCHED][Thread] In, Synched ? %d, %d\n",openair_daq_vars.mode,SYNCHED);
if ((openair_daq_vars.mode != openair_NOT_SYNCHED) && (openair_daq_vars.node_running == 1)) {
time_in = openair_get_mbox();
#ifndef EMOS
mac_xface->macphy_scheduler(last_slot);
#endif
// phy_procedures(last_slot);
if (last_slot== 2)
mac_xface->frame++;
time_out = openair_get_mbox();
#ifdef CBMIMO1
switch (last_slot) {
case 0:
if (time_in>22) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
// exit_openair = 1;
openair1_restart();
}
break;
case 1:
if (time_in>38) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
// exit_openair = 1;
openair1_restart();
}
break;
case 2:
if (time_in>54) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
// exit_openair = 1;
openair1_restart();
}
break;
case 3:
if (time_in>6) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, NUMBER_OF_SYMBOLS_PER_FRAME = %d\n",mac_xface->frame, last_slot, pci_interface->ofdm_symbols_per_frame);
openair1_restart();
// exit_openair = 1;
}
break;
}
// }
#endif //CBMIMO1
if ((mac_xface->is_primary_cluster_head == 0) && (last_slot == 0)) {
#ifdef CBMIMO1 // Note this code cannot run on PLATON!!!
if (openair_daq_vars.first_sync_call == 1)
openair_daq_vars.first_sync_call = 0;
#endif // CBMIMO1
}
} // daq_mode != NOT_SYNCHED
} // end while (1)
// report what happened
msg ("[SCHED][OPENAIR_THREAD] Exited : openair_daq_vars.slot_count = %d, MODE = %d\n", openair_daq_vars.slot_count, openair_daq_vars.mode);
// rt_task_delete(rt_whoami);
/* pthread_exit(NULL); */
#ifdef SERIAL_IO
rt_spclose(COM1);
#endif
return(0);
}
#ifdef CBMIMO1
static unsigned char dummy_mac_pdu[256] __attribute__((aligned(16)));
static unsigned char dummy_mac_pdu2[256] __attribute__((aligned(16)));
#define NUMBER_OF_CHSCH_SYNCH_RETRIES 8
#define NUMBER_OF_SCH_SYNCH_RETRIES 8
unsigned int find_chbch(void) {
unsigned int target_SCH_index;
unsigned char chbch_status=0;
int ret[2];
unsigned char chsch_indices[2] = {1, 2};
unsigned char *chbch_pdu_rx[2];
int rssi1_max,rssi2_max;
chbch_pdu_rx[0] = dummy_mac_pdu;
chbch_pdu_rx[1] = dummy_mac_pdu2;
for (target_SCH_index = 1;
target_SCH_index < 4;
target_SCH_index++) {
phy_channel_estimation_top(PHY_vars->rx_vars[0].offset,
SYMBOL_OFFSET_CHSCH+target_SCH_index,
0,
target_SCH_index,
NB_ANTENNAS_RX,
CHSCH);
}
// get maximum rssi for first two CHSCH
rssi1_max = max(PHY_vars->PHY_measurements.rx_rssi_dBm[1][0],PHY_vars->PHY_measurements.rx_rssi_dBm[1][1]); rssi2_max = max(PHY_vars->PHY_measurements.rx_rssi_dBm[2][0],PHY_vars->PHY_measurements.rx_rssi_dBm[2][1]);
// try to decode both streams
phy_decode_chbch_2streams_ml(chsch_indices,
ML,
NB_ANTENNAS_RX,
NB_ANTENNAS_TX,
chbch_pdu_rx,
ret,
CHBCH_PDU_SIZE);
if (ret[0] == 0) { // first CHBCH is decoded correctly
PHY_vars->PHY_measurements.chbch_detection_count[1]++;
openair_daq_vars.synch_source = 1;
chbch_status = 1;
}
if (ret[1] == 0) { // second CHBCH is decoded correctly
PHY_vars->PHY_measurements.chbch_detection_count[2]++;
if ( (chbch_status == 0) || (rssi2_max>rssi1_max) ) // first is not decoded or second has higher rssi
openair_daq_vars.synch_source = 2;
chbch_status += 2;
}
// msg("Find CHBCH: chbch_status = %d (%d,%d), rssi1 %d dBm, rssi2 %d dBm\n",chbch_status,ret[0],ret[1],rssi1_max,rssi2_max);
return(chbch_status);
}
unsigned int find_mrbch(void) {
unsigned int target_SCH_index = MRSCH_INDEX;
unsigned char mrbch_status = 0;
phy_channel_estimation_top(PHY_vars->rx_vars[0].offset,
SYMBOL_OFFSET_MRSCH,
0,
target_SCH_index,
NB_ANTENNAS_RX,
SCH);
if (phy_decode_mrbch(target_SCH_index,
#ifdef BIT8_RXDEMUX
1,
#endif
NB_ANTENNAS_RX,
NB_ANTENNAS_TXRX,
(unsigned char*)&dummy_mac_pdu,
#ifdef OPENAIR2
sizeof(MRBCH_PDU)) == 0)
#else
MRBCH_PDU_SIZE) == 0)
#endif
{
PHY_vars->PHY_measurements.mrbch_detection_count++;
#ifdef DEBUG_PHY
msg("[openair][SCHED][SYNCH] MRBCH %d detected successfully, RSSI Rx1 %d, RSSI Rx2 %d\n",
target_SCH_index,PHY_vars->PHY_measurements.rx_rssi_dBm[0][0],
target_SCH_index,PHY_vars->PHY_measurements.rx_rssi_dBm[0][1]);
#endif
mrbch_status = 1;
}
return(mrbch_status);
}
void openair1_restart(void) {
openair_dma(FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
openair_daq_vars.tx_test=0;
openair_daq_vars.sync_state = 0;
mac_xface->frame = 0;
if ((mac_xface->is_cluster_head) && (mac_xface->is_primary_cluster_head)) {
openair_daq_vars.mode = openair_SYNCHED_TO_MRSCH;
}
else {
openair_daq_vars.mode = openair_NOT_SYNCHED;
}
#ifndef EMOS
#ifdef OPENAIR2
// msg("[openair][SCHED][SYNCH] Clearing MAC Interface\n");
//mac_resynch();
#endif //OPENAIR2
#endif //EMOS
}
void openair_sync(void) {
// mode looking_for_CH, looking_for_MR
// synch_source SCH index
int i;
//int size,j;
int status;
int length;
int ret;
static unsigned char clear = 1;
static unsigned char clear_mesh = 1;
static SCH_t searching_mode = CHSCH;
unsigned char target_SCH_index = 0;
static unsigned char SCH_retries = 0;
static unsigned char CHSCH_retries = 0;
unsigned char chbch_status,mrbch_status;
RTIME time;
openair_daq_vars.mode = openair_NOT_SYNCHED;
//openair_set_lo_freq_openair(openair_daq_vars.freq,openair_daq_vars.freq);
ret = setup_regs();
#ifndef NOCARD_TEST
openair_get_frame();
#else ///NOCARD_TEST
rf_cntl_packet.frame = mac_xface->frame;
rf_cntl_packet.rx_offset = 0;
rtf_put(rf_cntl_fifo,&rf_cntl_packet,sizeof(RF_CNTL_PACKET));
pthread_cond_wait(&openair_rx_fifo_cond,&openair_rx_fifo_mutex);
#endif //NOCARD_TEST
// sleep during acquisition of frame
time = rt_get_cpu_time_ns();
for (i=0;i<2*NUMBER_OF_CHUNKS_PER_FRAME;i++) {
#ifdef RTAI_ENABLED
rt_sleep(nano2count(NS_PER_CHUNK));
#endif //
}
time = rt_get_cpu_time_ns();
if (openair_daq_vars.one_shot_get_frame == 1) { // we're in a non real-time mode so just grab a frame and write to fifo
status=rtf_reset(rx_sig_fifo);
for (i=0;i<NB_ANTENNAS_RX;i++) {
length=rtf_put(rx_sig_fifo,PHY_vars->rx_vars[i].RX_DMA_BUFFER,FRAME_LENGTH_BYTES);
if (length < FRAME_LENGTH_BYTES)
msg("[openair][sched][rx_sig_fifo_handler] Didn't put %d bytes for antenna %d (put %d)\n",FRAME_LENGTH_BYTES,i,length);
}
// signal that acquisition is done in control fifo
rtf_put(rf_cntl_fifo,&openair_daq_vars.sched_cnt,sizeof(int));
openair_daq_vars.one_shot_get_frame = 0;
}
if (openair_daq_vars.one_shot_get_frame == 0) { // we're in a real-time mode so do basic decoding
memcpy((void *)&PHY_vars->rx_vars[0].RX_DMA_BUFFER[FRAME_LENGTH_COMPLEX_SAMPLES],(void*)PHY_vars->rx_vars[0].RX_DMA_BUFFER,OFDM_SYMBOL_SIZE_BYTES);
memcpy((void *)&PHY_vars->rx_vars[1].RX_DMA_BUFFER[FRAME_LENGTH_COMPLEX_SAMPLES],(void*)PHY_vars->rx_vars[1].RX_DMA_BUFFER,OFDM_SYMBOL_SIZE_BYTES);
#ifdef DEBUG_PHY
msg("[openair][openair SYNC] freq %d:%d, RX_DMA ADR 0 %x, RX_DMA ADR 1 %x, OFDM_SPF %d, RX_GAIN_VAL %x, TX_RX_SW %d, TCXO %d, NODE_ID %d\n",
(pci_interface->freq_info>>1)&3,
(pci_interface->freq_info>>3)&3,
pci_interface->adc_head[0],
pci_interface->adc_head[1],
pci_interface->ofdm_symbols_per_frame,
pci_interface->rx_gain_val,
pci_interface->tx_rx_switch_point,
pci_interface->tcxo_dac,
pci_interface->node_id);
#endif
// For debugging we overrule the searching_mode
if (openair_daq_vars.node_running == 1) {
if ((mac_xface->is_cluster_head == 1) && (mac_xface->is_secondary_cluster_head == 1)) {
searching_mode = SCH;
target_SCH_index = MRSCH_INDEX; //this is needed for the initial synch of the 2nd CH.
// msg("[openair][openair SYNC] Synching to MRSCH %d\n",target_SCH_index);
}
else if (mac_xface->is_cluster_head == 0) {
// msg("[openair][openair SYNC] Synching to CHSCH %d\n",target_SCH_index);
searching_mode = CHSCH;
target_SCH_index = 0;
}
else { //This should not happen
msg("[openair][openair SYNC] searching_mode for primary clusterhead undefined (mode %d)!\n");
exit_openair=1;
}
}
/*
//SENSING
openair_daq_vars.channel_vacant[openair_daq_vars.freq] =
openair_daq_vars.channel_vacant[openair_daq_vars.freq] + model_based_detection();
msg("[OPENAIR][SCHED] Sensing results = [%d %d %d %d]\n",openair_daq_vars.channel_vacant[0],openair_daq_vars.channel_vacant[1],openair_daq_vars.channel_vacant[2],openair_daq_vars.channel_vacant[3]);
*/
// Do initial timing acquisition
phy_synch_time((short*)PHY_vars->rx_vars[0].RX_DMA_BUFFER,
&sync_pos,
FRAME_LENGTH_COMPLEX_SAMPLES-768,
768,
searching_mode,
target_SCH_index);
//msg("[openair][openair SYNC] sync_pos = %d\n",sync_pos);
PHY_vars->rx_vars[0].offset = sync_pos;
#ifndef NOCARD_TEST
pci_interface->frame_offset = sync_pos;
#endif //NOCARD_TEST
openair_daq_vars.mode = openair_NOT_SYNCHED;
// Try to decode CHBCH
if (searching_mode == CHSCH) {
chbch_status = 0;
PHY_vars->PHY_measurements.chbch_search_count++;
chbch_status = find_chbch();
if ((chbch_status >0 ) && (openair_daq_vars.node_running == 1)) {
openair_daq_vars.mode = openair_SYNCHED_TO_CHSCH;
PHY_vars->chbch_data[0].pdu_errors = 0;
PHY_vars->chbch_data[0].pdu_errors_last = 0;
PHY_vars->chbch_data[0].pdu_errors_conseq = 0;
PHY_vars->chbch_data[1].pdu_errors = 0;
PHY_vars->chbch_data[1].pdu_errors_last = 0;
PHY_vars->chbch_data[1].pdu_errors_conseq = 0;
PHY_vars->chbch_data[2].pdu_errors = 0;
PHY_vars->chbch_data[2].pdu_errors_last = 0;
PHY_vars->chbch_data[2].pdu_errors_conseq = 0;
PHY_vars->chbch_data[3].pdu_errors = 0;
PHY_vars->chbch_data[3].pdu_errors_last = 0;
PHY_vars->chbch_data[3].pdu_errors_conseq = 0;
mac_xface->frame = 0;
#ifndef EMOS
#ifdef OPENAIR2
// msg("[openair][SCHED][SYNCH] Clearing MAC Interface\n");
mac_resynch();
#endif //OPENAIR2
#endif //EMOS
openair_daq_vars.scheduler_interval_ns=NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK; // initial guess
openair_daq_vars.last_adac_cnt=-1;
// msg("[openair][SCHED][SYNCH] Resynching hardware\n");
// phy_adjust_synch(1,openair_daq_vars.synch_source,16384,CHSCH);
phy_adjust_synch_multi_CH(1,16384,CHSCH);
openair_daq_vars.tx_rx_switch_point = TX_RX_SWITCH_SYMBOL;
pci_interface->tx_rx_switch_point = openair_daq_vars.tx_rx_switch_point;
}
else {
if (chbch_status == 0)
#ifdef DEBUG_PHY
msg("[openair][SCHED][SYNCH] No CHBCH detected successfully, retrying (%d/%d)... \n",
CHSCH_retries,NUMBER_OF_CHSCH_SYNCH_RETRIES);
#endif
openair_daq_vars.mode = openair_NOT_SYNCHED;
}
//AGC mesh
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
// msg("[openair][SCHED][AGC] Running mesh AGC on CHSCHes\n" );
phy_adjust_gain_mesh (clear_mesh, 16384);
if (clear_mesh == 1)
clear_mesh = 0;
}
CHSCH_retries++;
if (CHSCH_retries == NUMBER_OF_CHSCH_SYNCH_RETRIES){
CHSCH_retries = 0;
searching_mode = SCH;
/*
if (!mac_xface->is_cluster_head) {
openair_daq_vars.freq = (openair_daq_vars.freq+1) % 4;
openair_daq_vars.freq_info = 1 + (openair_daq_vars.freq<<1) + (openair_daq_vars.freq<<4);
clear_mesh=1;
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
PHY_vars->rx_vars[0].rx_total_gain_dB = MIN_RF_GAIN;//138;
#ifdef CBMIMO1
openair_set_rx_gain_cal_openair(PHY_vars->rx_vars[0].rx_total_gain_dB);
#endif //CBMIMO1
}
}
*/
}
} // end of search for CHSCH
else { // Search for MRSCH
target_SCH_index = MRSCH_INDEX;
PHY_vars->PHY_measurements.mrbch_search_count++;
mrbch_status = find_mrbch();
if (mrbch_status == 1) {
if (openair_daq_vars.node_running == 1) {
msg("[openair][SCHED] Found MRBCH, gain = %d, offset =%d\n",PHY_vars->rx_vars[0].rx_total_gain_dB,PHY_vars->rx_vars[0].offset);
msg("[OPENAIR][SCHED] Frame %d:, mrbch_pdu = ");
for (i=0; i<MRBCH_PDU_SIZE; i++)
msg("%d, ",dummy_mac_pdu[i]);
msg("\n");
openair_daq_vars.mode = openair_SYNCHED_TO_MRSCH;
PHY_vars->mrbch_data[0].pdu_errors = 0;
PHY_vars->mrbch_data[0].pdu_errors_last = 0;
PHY_vars->mrbch_data[0].pdu_errors_conseq = 0;
mac_xface->frame = 0;
#ifndef EMOS
#ifdef OPENAIR2
// msg("[openair][SCHED][SYNCH] Clearing MAC Interface\n");
mac_resynch();
#endif //OPENAIR2
#endif //EMOS
openair_daq_vars.scheduler_interval_ns=NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK; // initial guess
openair_daq_vars.last_adac_cnt=-1;
phy_adjust_synch(1,MRSCH_INDEX,16384,SCH);
openair_daq_vars.tx_rx_switch_point = TX_RX_SWITCH_SYMBOL;
pci_interface->tx_rx_switch_point = openair_daq_vars.tx_rx_switch_point;
}
}
else {
#ifdef DEBUG_PHY
msg("[openair][SCHED][SYNCH] MRBCH %d not detected successfully, retrying (%d/%d)... \n",
target_SCH_index,SCH_retries,NUMBER_OF_SCH_SYNCH_RETRIES);
#endif
}
// run AGC
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
// msg("[openair][SCHED][AGC] Running AGC on MRSCH %d\n", target_SCH_index);
phy_adjust_gain (clear, 16384, target_SCH_index);
if (clear == 1)
clear = 0;
}
SCH_retries++;
if (SCH_retries == NUMBER_OF_SCH_SYNCH_RETRIES){
SCH_retries = 0;
searching_mode = CHSCH;
/*
if (mac_xface->is_cluster_head) {
openair_daq_vars.freq = (openair_daq_vars.freq+1) % 4;
openair_daq_vars.freq_info = 1 + (openair_daq_vars.freq<<1) + (openair_daq_vars.freq<<4);
clear_mesh=1;
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
PHY_vars->rx_vars[0].rx_total_gain_dB = MIN_RF_GAIN;//138;
#ifdef CBMIMO1
openair_set_rx_gain_cal_openair(PHY_vars->rx_vars[0].rx_total_gain_dB);
#endif //CBMIMO1
}
}
*/
}
} // search for mrbch
}
else { // store frame to RX fifo and clear one shot flag
openair_daq_vars.one_shot_get_frame=0;
// msg("[openair][SCHED] Putting RF_CNTL_FIFO info\n");
rtf_put(rf_cntl_fifo,&openair_daq_vars.sched_cnt,sizeof(int));
}
// msg("[openair][SCHED][SYNCH] Returning\n");
}
void openair_sensing(void) {
int i;
int ret;
static unsigned char clear = 1;
static unsigned char clear_mesh = 1;
static unsigned int sensing_counter = 0;
int sensing_result;
RTIME time;
//msg("[OPENAIR][SENSING] freq=%d, freq_info=%d\n",openair_daq_vars.freq,openair_daq_vars.freq_info);
ret = setup_regs();
#ifndef NOCARD_TEST
openair_get_frame();
#else ///NOCARD_TEST
rf_cntl_packet.frame = mac_xface->frame;
rf_cntl_packet.rx_offset = 0;
rtf_put(rf_cntl_fifo,&rf_cntl_packet,sizeof(RF_CNTL_PACKET));
pthread_cond_wait(&openair_rx_fifo_cond,&openair_rx_fifo_mutex);
#endif //NOCARD_TEST
// msg("[openair][openair SYNC] openair_get_frame done\n");
// sleep during acquisition of frame
time = rt_get_cpu_time_ns();
// msg("Sleeping at %d ns... \n",(unsigned int)time);
for (i=0;i<2*NUMBER_OF_CHUNKS_PER_FRAME;i++) {
#ifdef RTAI_ENABLED
rt_sleep(nano2count(NS_PER_CHUNK));
#endif //
}
time = rt_get_cpu_time_ns();
// msg("Awakening at %d ns... \n",(unsigned int)time);
if (openair_daq_vars.one_shot_get_frame == 0) { // we're in a real-time mode so do basic decoding
memcpy((void *)&PHY_vars->rx_vars[0].RX_DMA_BUFFER[FRAME_LENGTH_COMPLEX_SAMPLES],(void*)PHY_vars->rx_vars[0].RX_DMA_BUFFER,OFDM_SYMBOL_SIZE_BYTES);
memcpy((void *)&PHY_vars->rx_vars[1].RX_DMA_BUFFER[FRAME_LENGTH_COMPLEX_SAMPLES],(void*)PHY_vars->rx_vars[1].RX_DMA_BUFFER,OFDM_SYMBOL_SIZE_BYTES);
//AGC mesh
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
// msg("[openair][SCHED][AGC] Running mesh AGC on CHSCHes\n" );
phy_adjust_gain_mesh (clear_mesh, 16384);
if (clear_mesh == 1)
clear_mesh = 0;
}
sensing_counter++;
openair_daq_vars.channel_vacant[openair_daq_vars.freq] = 0;
if (sensing_counter >= 12){
sensing_result = model_based_detection();
msg("[OPENAIR][SENSING] sensing_counter=%d, freq=%d, sensing_result=%d\n",sensing_counter,openair_daq_vars.freq,sensing_result);
if (sensing_result==1) {
openair_daq_vars.freq = (openair_daq_vars.freq+1) % 4;
openair_daq_vars.freq_info = 1 + (openair_daq_vars.freq<<1) + (openair_daq_vars.freq<<4);
sensing_counter = 0;
clear_mesh=1;
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
PHY_vars->rx_vars[0].rx_total_gain_dB = MIN_RF_GAIN;//138;
#ifdef CBMIMO1
openair_set_rx_gain_cal_openair(PHY_vars->rx_vars[0].rx_total_gain_dB);
#endif //CBMIMO1
}
}
else {
openair_daq_vars.channel_vacant[openair_daq_vars.freq] = 1;
}
}
}
}
#endif // //CBMIMO1
//-----------------------------------------------------------------------------
static void * top_level_scheduler(void *param) {
#ifdef CBMIMO1
unsigned int adac_cnt;
#endif // CBMIMO1
#ifdef PLATON
unsigned int adac_cnt,chunk_count,chunk_offset,slot_count_new;
#endif // PLATON
int adac_offset;
int first_increment = 0;
int i;
int ret=0;
msg("[openair][SCHED][top_level_scheduler] top_level_scheduler started with id %x, MODE %d\n",(unsigned int)pthread_self(),openair_daq_vars.mode);
openair_daq_vars.sched_cnt = 0;
msg("[openair][SCHED][top_level_scheduler] SLOTS_PER_FRAME=%d, NUMBER_OF_CHUNKS_PER_SLOT=%d, PHY_vars->mbox %p\n",SLOTS_PER_FRAME,NUMBER_OF_CHUNKS_PER_SLOT,(void*)mbox);
//***************************************************************************************
#ifdef PLATON
for (i = 0; i < hardware_configuration.number_of_DAQ_cards; i++) {
setup_regs (i);
*rx_mbox[i] = 0;
*tx_mbox[i] = 0;
}
// Arm slave DMA engines
for (i = 0; i <NB_ANTENNAS_RX; i++) {
if (i != hardware_configuration.master_id) {
msg ("[openair][sched][top_level_scheduler] Arming card %d\n", i);
daq_writel (DMA_ADC_ON + DMA_DAC_ON, m_device[i].data_base + PCI_START_STOP_DMA);
}
}
daq_writel (DMA_DAC_ON + CNT_DAC_ON + DMA_ADC_ON + CNT_ADC_ON, m_device[hardware_configuration.master_id].data_base + PCI_START_STOP_DMA);
//***************************************************************************************
#endif // PLATON
#ifdef RTAI_ENABLED
// msg("[OPENAIR][SCHED] Sleeping ... MODE = %d\n",openair_daq_vars.mode);
rt_sleep(nano2count(2*NUMBER_OF_CHUNKS_PER_SLOT * NS_PER_CHUNK));
// msg("[OPENAIR][SCHED] Awakening ... MODE = %d\n",openair_daq_vars.mode);
#endif //
openair_daq_vars.sync_state=0;
for (i=0;i<4;i++) {
PHY_vars->PHY_measurements.chbch_detection_count[i]= 0;
}
PHY_vars->PHY_measurements.mrbch_detection_count= 0;
PHY_vars->PHY_measurements.chbch_search_count= 0;
PHY_vars->PHY_measurements.mrbch_search_count= 0;
while (exit_openair == 0) {
#ifdef PLATON
adac_cnt = (*PHY_vars->mbox>>1)%NUMBER_OF_CHUNKS_PER_FRAME; /* counts from 0 to NUMBER_OF_CHUNKS_PER_FRAME-1 */
#endif //
#ifdef CBMIMO1
adac_cnt = (*(unsigned int *)mbox)%NUMBER_OF_CHUNKS_PER_FRAME; /* counts from 0 to NUMBER_OF_CHUNKS_PER_FRAME-1 */
#endif //
openair_daq_vars.sched_cnt++;
if ((openair_daq_vars.mode == openair_NOT_SYNCHED) && (openair_daq_vars.node_id != PRIMARY_CH)) {
// DO Nothing
if (openair_daq_vars.synch_wait_cnt <= 0) {
rt_sleep(nano2count(NUMBER_OF_CHUNKS_PER_SLOT * NS_PER_CHUNK));
#ifdef CBMIMO1 // Note this code cannot run on PLATON!!!
if (openair_daq_vars.tx_test == 0)
openair_sync();
#endif // CBMIMO1
if ( (openair_daq_vars.mode != openair_NOT_SYNCHED) &&
(openair_daq_vars.node_running == 1) ){
#ifdef CBMIMO1
openair_dma(FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_START_RT_ACQUISITION);
#endif //CBMIMO1
openair_daq_vars.sync_state = 1;
for (i=0;i<NB_ANTENNAS_RX;i++){
bzero((void *)PHY_vars->rx_vars[i].RX_DMA_BUFFER,FRAME_LENGTH_BYTES);
}
rt_sleep(nano2count(NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK*SLOTS_PER_FRAME));
}
#ifdef DEBUG_PHY
else {
if (((openair_daq_vars.sched_cnt - 1) % (SYNCH_WAIT_TIME<<2) ) == 0)
msg("[openair][SCHED][SYNCH] Return MODE : NOT SYNCHED, sched_cnt = %d\n",openair_daq_vars.sched_cnt);
}
#endif //DEBUG_PHY
if (openair_daq_vars.node_running == 0){
openair_daq_vars.synch_wait_cnt = SYNCH_WAIT_TIME;
}
else {
openair_daq_vars.synch_wait_cnt = SYNCH_WAIT_TIME_RUNNING;
}
}
openair_daq_vars.synch_wait_cnt--;
rt_sleep(nano2count(NUMBER_OF_CHUNKS_PER_SLOT * NS_PER_CHUNK));
}
/*
else if ((openair_daq_vars.mode == openair_NOT_SYNCHED) && (openair_daq_vars.node_id == PRIMARY_CH)) { //this is for cognitive operation
openair_sensing(); // this also does the sensing
if (openair_daq_vars.channel_vacant[openair_daq_vars.freq]==1) { //check if the current frequency band is vacant
ret = setup_regs();
if (ret == 0) {
msg("[OPENAIR][SCHED] Starting CH on frequency %d\n",openair_daq_vars.freq);
openair_daq_vars.mode = openair_SYNCHED_TO_MRSCH;
openair_daq_vars.node_running = 1;
openair_daq_vars.sync_state = 0;
}
else {
msg("[OPENAIR][SCHED] Starting CH in cognitive mode failed\n");
}
}
}
*/
else { // We're in synch with the CH or are a 1ary clusterhead
#ifndef NOCARD_TEST
if (openair_daq_vars.sync_state == 0) { // This means we're a CH, so start RT acquisition!!
openair_daq_vars.rach_detection_count=0;
openair_daq_vars.sync_state = 1;
//openair_daq_vars.tx_rx_switch_point = TX_RX_SWITCH_SYMBOL;
//PHY_vars->rx_vars[0].rx_total_gain_dB = 115;
//openair_set_rx_gain_cal_openair(PHY_vars->rx_vars[0].rx_total_gain_dB);
msg("OFDM_Symbols_per_frame %d, log2_symbol_size %d\n",NUMBER_OF_SYMBOLS_PER_FRAME, LOG2_NUMBER_OF_OFDM_CARRIERS);
#ifdef CBMIMO1
openair_dma(FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_START_RT_ACQUISITION);
pci_interface->tx_rx_switch_point = openair_daq_vars.tx_rx_switch_point;
#endif //CBMIMO1
mac_xface->frame = 0;
openair_daq_vars.scheduler_interval_ns=NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK; // initial guess
openair_daq_vars.last_adac_cnt=-1;
}
if (openair_daq_vars.sync_state==1) // waiting for first wrap-around of frame
{
if (adac_cnt==0)
{
//msg("[openair][SCHED][top_level_scheduler] got adac_cnt=0, starting acquisition\n");
openair_daq_vars.sync_state=2;
openair_daq_vars.last_adac_cnt=0;
openair_daq_vars.slot_count=0;
openair_daq_vars.sched_cnt = 0;
first_increment = 0;
rt_sleep(nano2count(openair_daq_vars.scheduler_interval_ns)); /* sleep for one slot */
}
else
{
//msg("[openair][SCHED][top_level_scheduler] sync startup, current time=%llu, waiting for adac_cnt=0 (current adac_cnt=%d)\n",rt_get_time_ns(),adac_cnt);
rt_sleep(nano2count(NS_PER_CHUNK/2)); /* sleep for half a SYMBOL */
}
}
else if (openair_daq_vars.sync_state==2) /* acquisition running, track hardware.... */
{
// if (mac_xface->frame % 100 == 0)
// msg("[openair][SCHED] frame %d: scheduler interval %d\n",mac_xface->frame,openair_daq_vars.scheduler_interval_ns);
adac_offset=((int)adac_cnt-((int)openair_daq_vars.slot_count*NUMBER_OF_CHUNKS_PER_SLOT));
if (adac_offset > NUMBER_OF_CHUNKS_PER_FRAME)
adac_offset -= NUMBER_OF_CHUNKS_PER_FRAME;
else if (adac_offset < 0)
adac_offset += NUMBER_OF_CHUNKS_PER_FRAME;
//if (mac_xface->frame % 100 == 0)
// msg("[openair][SCHED] frame %d: adac_offset %d\n",mac_xface->frame,adac_offset);
#ifdef CBMIMO1
if (adac_offset > 20) {
msg("[openair][sched][top_level_scheduler] Frame %d : Scheduling too late (adac_offset %d), exiting ...\n",mac_xface->frame,adac_offset);
// exit_openair = 1;
// restart CBMIMO1
openair1_restart();
}
#endif //CBMIMO1
if (adac_offset>=NUMBER_OF_CHUNKS_PER_SLOT)
{
if (adac_offset>NUMBER_OF_CHUNKS_PER_SLOT) /* adjust openair_daq_vars.scheduler_interval_ns to track the ADAC counter */
{
openair_daq_vars.scheduler_interval_ns-= DRIFT_OFFSET;
if (openair_daq_vars.scheduler_interval_ns < NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK - MAX_DRIFT_COMP)
openair_daq_vars.scheduler_interval_ns = NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK - MAX_DRIFT_COMP;
/* msg("adac_offset=%d, openair_daq_vars.scheduler_interval_ns=%d\n",adac_offset,openair_daq_vars.scheduler_interval_ns); */
}
if (pthread_mutex_lock (&openair_mutex) != 0) // Signal MAC_PHY Scheduler
msg("[openair][SCHED][SCHED] ERROR pthread_mutex_lock\n");// lock before accessing shared resource
openair_daq_vars.instance_cnt++;
pthread_mutex_unlock (&openair_mutex);
// msg("[openair][SCHED][SCHED] Signaling MACPHY scheduler\n");
if (openair_daq_vars.instance_cnt == 0) // PHY must have finished by now
if (pthread_cond_signal(&openair_cond) != 0)
msg("[openair][SCHED][SCHED] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
openair_daq_vars.slot_count=(openair_daq_vars.slot_count+1) % SLOTS_PER_FRAME;
openair_daq_vars.last_adac_cnt=adac_cnt;
rt_sleep(nano2count(openair_daq_vars.scheduler_interval_ns));
first_increment = 0;
}
else if (adac_offset<NUMBER_OF_CHUNKS_PER_SLOT)
{
if (first_increment == 0) {
openair_daq_vars.scheduler_interval_ns+=DRIFT_OFFSET;
first_increment = 1;
}
if (openair_daq_vars.scheduler_interval_ns > NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK + MAX_DRIFT_COMP)
openair_daq_vars.scheduler_interval_ns = NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK + MAX_DRIFT_COMP;
// msg("adac_offset=%d, openair_daq_vars.scheduler_interval_ns=%d, sleeping for 2us\n",adac_offset,openair_daq_vars.scheduler_interval_ns);
rt_sleep(nano2count(2000));
}
} // tracking mode
#else //NOCARD_TEST
if ((openair_daq_vars.slot_count % SLOTS_PER_FRAME) == 0) {
msg("[openair][SCHED][top_level_thread] Waiting for frame signal in fifo (instance cnt %d)\n",
openair_daq_vars.instance_cnt);
rf_cntl_packet.frame = mac_xface->frame;
rf_cntl_packet.rx_offset = PHY_vars->rx_vars[0].offset;
rtf_put(rf_cntl_fifo,&rf_cntl_packet,sizeof(RF_CNTL_PACKET));
pthread_cond_wait(&openair_rx_fifo_cond,&openair_rx_fifo_mutex);
}
// here, wait for data in the test fifo
if (pthread_mutex_lock (&openair_mutex) != 0) // Signal MAC_PHY Scheduler
msg("[openair][SCHED][SCHED] ERROR pthread_mutex_lock\n");// lock before accessing shared resource
openair_daq_vars.instance_cnt++;
pthread_mutex_unlock (&openair_mutex);
if (openair_daq_vars.instance_cnt == 0) // PHY must have finished by now
if (pthread_cond_signal(&openair_cond) != 0)
msg("[openair][SCHED][SCHED] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
openair_daq_vars.slot_count=(openair_daq_vars.slot_count+1) % SLOTS_PER_FRAME;
rt_sleep(nano2count(10000000)); /* sleep for one slot */
#endif //NOCARD_TEST
} // in synch
} // exit_openair = 0
msg("[openair][SCHED][top_level_thread] Exiting ... openair_daq_vars.sched_cnt = %d\n",openair_daq_vars.sched_cnt);
openair_daq_vars.mode = openair_SCHED_EXIT;
// schedule openair_thread to exit
msg("[openair][SCHED][top_level_thread] Scheduling openair_thread to exit ... \n");
if (pthread_mutex_lock (&openair_mutex) != 0)
msg("[openair][SCHED][top_level_thread] ERROR pthread_mutex_lock\n");// lock before accessing shared resource
openair_daq_vars.instance_cnt = 10;
pthread_mutex_unlock (&openair_mutex);
if (pthread_cond_signal(&openair_cond) != 0)
msg("[openair][SCHED][top_level_thread] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
openair_daq_vars.node_running = 0;
// rt_task_delete(rt_whoami);
/* pthread_exit(NULL); */
msg("[openair][SCHED][top_level_thread] Exiting top_level_scheduler ... \n");
return(0);
}
#ifdef NOCARD_TEST
int rx_sig_fifo_handler(unsigned int fifo, int rw) {
int status,i;
int length;
if (rw=='w') {
for (i=0;i<NB_ANTENNAS_RX;i++) {
length=rtf_get(fifo,PHY_vars->rx_vars[i].RX_DMA_BUFFER,FRAME_LENGTH_BYTES);
if (length < FRAME_LENGTH_BYTES)
msg("[openair][sched][rx_sig_fifo_handler] Didn't get %d bytes for antenna %d (got %d)\n",FRAME_LENGTH_BYTES,i,length);
}
status=rtf_reset(fifo);
msg("[openair][sched][rx_sig_fifo_handler] fifo reset status=%d\n",status);
pthread_cond_signal(&openair_rx_fifo_cond);
return(0);
}
else
return(0);
}
#endif //NOCARD_TEST
int openair_sched_init(void) {
int error_code;
mac_xface->frame = 0;
openair_daq_vars.scheduler_interval_ns=NUMBER_OF_CHUNKS_PER_SLOT*NS_PER_CHUNK; // initial guess
openair_daq_vars.last_adac_cnt=-1;
pthread_mutex_init(&openair_mutex,NULL);
pthread_cond_init(&openair_cond,NULL);
if (mac_xface->is_primary_cluster_head == 1) {
printk("[openair][SCHED][init] Configuring primary clusterhead\n");
}
else if (mac_xface->is_secondary_cluster_head == 1) {
printk("[openair][SCHED][init] Configuring secondary clusterhead\n");
}
else {
printk("[openair][SCHED][init] Configuring regular node\n");
}
openair_daq_vars.mode = openair_NOT_SYNCHED;
error_code = rtf_create(rx_sig_fifo, NB_ANTENNAS_RX*FRAME_LENGTH_BYTES);
printk("[openair][SCHED][INIT] Created rx_sig_fifo (%d bytes), error_code %d\n",
NB_ANTENNAS_RX*FRAME_LENGTH_BYTES,
error_code);
error_code = rtf_create(rf_cntl_fifo, 256);
printk("[openair][SCHED][INIT] Created rx_cntl_fifo, error_code %d\n",error_code);
#ifdef EMOS
error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE);
printk("[OPENAIR][SCHED][INIT] Created EMOS FIFO, error code %d\n",error_code);
#endif
#ifdef NOCARD_TEST
/*RX Signal FIFOS HANDLER*/
pthread_mutex_init(&openair_rx_fifo_mutex,NULL);
pthread_cond_init(&openair_rx_fifo_cond,NULL);
#endif //NOCARD_TEST
pthread_attr_init (&attr_threads[OPENAIR_THREAD_INDEX]);
pthread_attr_setstacksize(&attr_threads[OPENAIR_THREAD_INDEX],OPENAIR_THREAD_STACK_SIZE);
attr_threads[OPENAIR_THREAD_INDEX].priority = 1;
openair_daq_vars.instance_cnt = -1;
// Create openair_thread
error_code = pthread_create(&threads[OPENAIR_THREAD_INDEX],
&attr_threads[OPENAIR_THREAD_INDEX],
openair_thread,
(void *)0);
if (error_code!= 0) {
printk("[SCHED][OPENAIR_THREAD][INIT] Could not allocate openair_thread, error %d\n",error_code);
return(error_code);
}
else {
printk("[SCHED][OPENAIR_THREAD][INIT] Allocate openair_thread successful\n");
}
pthread_attr_init (&attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX]);
pthread_attr_setstacksize(&attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],OPENAIR_THREAD_STACK_SIZE);
attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX].priority = 0;
// Create top_level_scheduler
error_code = pthread_create(&threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],
&attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX], //default attributes
top_level_scheduler,
(void *)0);
// rt_change_prio(threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],0);
if (error_code!= 0) {
printk("[openair][SCHED][INIT] Could not allocate top_level_scheduler, error %d\n",error_code);
return(error_code);
}
else {
printk("[openair][SCHED][INIT] Allocate top_level_scheduler successfull\n");
}
// Done by pthread_create in rtai_posix.h
// rt_task_use_fpu(threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],1);
#ifdef NOCARD_TEST
/*RX Signal FIFOS HANDLER*/
pthread_mutex_init(&openair_rx_fifo_mutex,NULL);
pthread_cond_init(&openair_rx_fifo_cond,NULL);
error_code = rtf_create(rx_sig_fifo, NB_ANTENNAS_RX*FRAME_LENGTH_BYTES);
printk("[openair][SCHED][INIT] Created rx_sig_fifo, error_code %d\n",error_code);
error_code = rtf_create_handler(rx_sig_fifo, X_FIFO_HANDLER(rx_sig_fifo_handler));
printk("[openair][SCHED][INIT] Created rx_sig_fifo handler, error_code %d\n",error_code);
#endif //NOCARD_TEST
return(0);
}
void openair_sched_cleanup() {
int error_code;
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
pthread_exit(&threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX]);//H.A
#ifdef NOCARD_TEST
pthread_cond_destroy(&openair_rx_fifo_cond);
#endif //NOCARD_TEST
pthread_mutex_destroy(&openair_mutex);
pthread_cond_destroy(&openair_cond);
error_code = rtf_destroy(rx_sig_fifo);
printk("[OPENAIR][SCHED][CLEANUP] rx_sig_fifo closed, error_code %d\n", error_code);
error_code = rtf_destroy(rf_cntl_fifo);
printk("[OPENAIR][SCHED][CLEANUP] rf_cntl_fifo closed, error_code %d\n", error_code);
#ifdef EMOS
error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
printk("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
#endif
printk("[openair][SCHED][CLEANUP] Done!\n");
}
void openair_sched_exit(char *str) {
// msg("%s\n",str);
// msg("[OPENAIR][SCHED] TTI %d: openair_sched_exit() called, preparing to exit ...\n",mac_xface->frame);
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
}
/*@}*/
/*
// \author R. Knopp
// \date 02.06.2004 (initial WIDENS version)
// updated 04.04.2006 (migration to 2.6.x kernels)
// updated 01.06.2006 (updates by M. Guillaud for MIMO sounder, new HW tracking mechanism)
// updated 15.01.2007 (RX/TX FIFO debug support, RK)
// updated 21.05.2007 (structural changes,GET Frame fifo support, RK)
// Created LTE version 02.10.2009
* @{
*/
/*
* @addtogroup _physical_layer_ref_implementation_
\section _process_scheduling_ Process Scheduling
This section deals with real-time process scheduling for PHY and synchronization with certain hardware targets (CBMIMO1).
*/
#ifndef USER_MODE
#define __NO_VERSION__
/*
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
*/
#ifdef RTAI_ISNT_POSIX
#include "rt_compat.h"
#endif /* RTAI_ISNT_POSIX */
#include "MAC_INTERFACE/extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h"
#endif // CBMIMO1
#ifdef RTAI_ENABLED
#include <rtai.h>
#include <rtai_posix.h>
#include <rtai_fifos.h>
#endif //
#else
#include <stdio.h>
#include <stdlib.h>
#endif // /* USER_MODE */
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
#include "extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/from_grlib_softregs.h"
#endif //CBMIMO1
#ifdef SERIAL_IO
#include "rtai_serial.h"
#endif
#ifdef EMOS
#include "phy_procedures_emos.h"
extern fifo_dump_emos_UE emos_dump_UE;
#endif
/// Mutex for instance count on MACPHY scheduling
pthread_mutex_t openair_mutex;
/// Condition variable for MACPHY thread
pthread_cond_t openair_cond;
/// Threads
pthread_t threads[openair_SCHED_NB_THREADS]={NULL,NULL,NULL};
/// Thread Attributes
pthread_attr_t attr_threads[openair_SCHED_NB_THREADS];
/// RX Signal FIFO for Testing without hardware
#define RX_SIG_FIFO_NUMBER 59
int rx_sig_fifo = RX_SIG_FIFO_NUMBER;
/// RX Control FIFO for testing without hardware
#define RF_CNTL_FIFO_NUMBER 60
int rf_cntl_fifo = RF_CNTL_FIFO_NUMBER;
#ifdef NOCARD_TEST
/// RX Signal FIFO Mutex
pthread_mutex_t openair_rx_fifo_mutex;
/// RX Signal FIFO Condition variable
pthread_cond_t openair_rx_fifo_cond;
/// Packet for RX Signal Control
RF_CNTL_PACKET rf_cntl_packet;
#endif //NOCARD_TEST
/// Global exit variable (exit on error or manual stop via IOCTL)
int exit_openair = 0;
extern int init_dlsch_threads(void);
extern void cleanup_dlsch_threads(void);
extern int dlsch_instance_cnt[8];
extern pthread_mutex_t dlsch_mutex[8];
extern pthread_cond_t dlsch_cond[8];
#define NO_SYNC_TEST 1
#ifdef CBMIMO1
#define NUMBER_OF_CHUNKS_PER_SLOT NUMBER_OF_OFDM_SYMBOLS_PER_SLOT
#define NUMBER_OF_CHUNKS_PER_FRAME (NUMBER_OF_CHUNKS_PER_SLOT * SLOTS_PER_FRAME)
#define SYNCH_WAIT_TIME 4000 // number of symbols between SYNCH retries
#define SYNCH_WAIT_TIME_RUNNING 100 // number of symbols between SYNCH retries
#define DRIFT_OFFSET 300
#define NS_PER_SLOT 500000
#define MAX_DRIFT_COMP 3000
#endif // CBMIMO1
#define MAX_SCHED_CNT 50000000
unsigned char first_sync_call;
rtheap_t rt_heap;
void openair1_restart(void) {
int i;
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
// openair_daq_vars.tx_test=0;
openair_daq_vars.sync_state = 0;
mac_xface->frame = 0;
/*
if ((mac_xface->is_cluster_head) && (mac_xface->is_primary_cluster_head)) {
openair_daq_vars.mode = openair_SYNCHED_TO_MRSCH;
}
else {
openair_daq_vars.mode = openair_NOT_SYNCHED;
}
*/
#ifdef OPENAIR2
msg("[openair][SCHED][SYNCH] Clearing MAC Interface\n");
//mac_resynch();
#endif //OPENAIR2
}
//-----------------------------------------------------------------------------
/** MACPHY Thread */
static void * openair_thread(void *param) {
//-----------------------------------------------------------------------------ddd
//------------------------------
#ifndef USER_MODE
struct sched_param p;
#endif // USER_MODE
u8 next_slot, last_slot;
unsigned int time_in,time_out,i;
int diff;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
// run on CPU 1, which should be reserved only for this (by adding isolcpus=1 noirqbalance to the kernel options). Also use IsolCpusMaks=0x2 when loading rtai_hal
rt_set_runnable_on_cpuid(pthread_self(),0);
rt_sleep(nano2count(NS_PER_SLOT));
#ifdef SERIAL_IO
msg("[SCHED][OPENAIR THREAD] Opening RT serial port interface\n");
rt_spopen(COM1,38400,8,1,RT_SP_PARITY_NONE,RT_SP_NO_HAND_SHAKE,RT_SP_FIFO_SIZE_14);
rt_msg("[SCHED][OPENAIR THREAD] Opened RT Serial Port Interface\n");
#endif
p.sched_priority = OPENAIR_THREAD_PRIORITY;
pthread_attr_setschedparam (&attr_threads[OPENAIR_THREAD_INDEX], &p);
#ifndef RTAI_ISNT_POSIX
pthread_attr_setschedpolicy (&attr_threads[OPENAIR_THREAD_INDEX], SCHED_FIFO);
#endif
printk("[openair][SCHED][openair_thread] openair_thread started with id %x, fpu_flag = %x, cpuid = %d\n",(unsigned int)pthread_self(),pthread_self()->uses_fpu,rtai_cpuid());
if (mac_xface->is_primary_cluster_head == 1) {
msg("[openair][SCHED][openair_thread] Configuring openair_thread for primary eNodeB/clusterhead\n");
}
else if (mac_xface->is_secondary_cluster_head == 1) {
msg("[openair][SCHED][openair_thread] Configuring openair_thread for secondary eNodeB/clusterhead\n");
}
else {
msg("[openair][SCHED][openair_thread] Configuring OPENAIR THREAD for regular UE/node\n");
}
exit_openair = 0;
// Inner thread endless loop
// exits on error or normally
openair_daq_vars.sched_cnt = 0;
openair_daq_vars.instance_cnt = -1;
for (i=0;i<number_of_cards;i++)
Zero_Buffer((void*)TX_DMA_BUFFER[i][0],
4*SLOT_LENGTH_BYTES_NO_PREFIX);
while (exit_openair == 0)
{
pthread_mutex_lock(&openair_mutex);
while (openair_daq_vars.instance_cnt < 0) {
pthread_cond_wait(&openair_cond,&openair_mutex);
}
openair_daq_vars.instance_cnt--;
pthread_mutex_unlock(&openair_mutex);
next_slot = (openair_daq_vars.slot_count + 1 ) % SLOTS_PER_FRAME;
if (openair_daq_vars.slot_count==0)
last_slot = SLOTS_PER_FRAME-1;
else
last_slot = (openair_daq_vars.slot_count - 1 ) % SLOTS_PER_FRAME;
//msg("[SCHED][Thread] Mode = %d (openair_NOT_SYNCHED=%d), slot_count = %d, instance_cnt = %d\n",openair_daq_vars.mode,openair_NOT_SYNCHED,openair_daq_vars.slot_count,openair_daq_vars.instance_cnt);
if ((openair_daq_vars.mode != openair_NOT_SYNCHED) && (openair_daq_vars.node_running == 1)) {
time_in = openair_get_mbox();
#ifdef DEBUG_PHY
if (mac_xface->frame % 100 == 0) {
msg("[SCHED][OPENAIR_THREAD] frame = %d, slot_count %d, last %d, next %d\n", mac_xface->frame, openair_daq_vars.slot_count, last_slot, next_slot);
}
#endif
#ifdef OPENAIR_LTE
if (mac_xface->is_cluster_head) {
if (PHY_vars_eNB_g && PHY_vars_eNB_g[0])
phy_procedures_eNB_lte(last_slot,next_slot,PHY_vars_eNB_g[0],0);
}
else {
if (PHY_vars_UE_g && PHY_vars_UE_g[0])
phy_procedures_UE_lte(last_slot,next_slot,PHY_vars_UE_g[0],0,0);
}
#else
#ifdef EMOS
phy_procedures_emos(last_slot);
#else
phy_procedures(last_slot);
#endif
#endif
if (last_slot==SLOTS_PER_FRAME-2)
mac_xface->frame++;
time_out = openair_get_mbox();
diff = ((int) time_out - (int) time_in) % ((int) (NUMBER_OF_SYMBOLS_PER_FRAME));
if (diff > (NUMBER_OF_OFDM_SYMBOLS_PER_SLOT+4)) { // we scheduled too late
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d, time_out %d, diff %d, scheduler_interval_ns %d\n",
mac_xface->frame, last_slot,
time_in,time_out,
diff,
openair_daq_vars.scheduler_interval_ns);
//openair1_restart();
//exit_openair = 1;
}
/*
#ifdef CBMIMO1
switch (last_slot) {
case 0:
if (time_in>22) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
// exit_openair = 1;
openair1_restart();
}
break;
case 1:
if (time_in>38) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
// exit_openair = 1;
openair1_restart();
}
break;
case 2:
if (time_in>54) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
// exit_openair = 1;
openair1_restart();
}
break;
case 3:
if (time_in>6) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d,time_out %d, scheduler_interval_ns %d\n", mac_xface->frame, last_slot,
time_in,time_out,openair_daq_vars.scheduler_interval_ns);
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, NUMBER_OF_SYMBOLS_PER_FRAME = %d\n",mac_xface->frame, last_slot, pci_interface[0]->ofdm_symbols_per_frame);
openair1_restart();
// exit_openair = 1;
}
break;
}
#endif //CBMIMO1
*/
#ifdef CBMIMO1 // Note this code cannot run on PLATON!!!
if ((mac_xface->is_primary_cluster_head == 0) && (last_slot == 0)) {
if (openair_daq_vars.first_sync_call == 1)
openair_daq_vars.first_sync_call = 0;
}
#endif // CBMIMO1
} // daq_mode != NOT_SYNCHED
} // end while (1)
// report what happened
msg ("[SCHED][OPENAIR_THREAD] Exited : openair_daq_vars.slot_count = %d, MODE = %d\n", openair_daq_vars.slot_count, openair_daq_vars.mode);
// rt_task_delete(rt_whoami);
/* pthread_exit(NULL); */
#ifdef SERIAL_IO
rt_spclose(COM1);
#endif
return(0);
}
void openair_sync(void) {
int i;
//int size,j;
int status;
int length;
int ret;
static unsigned char clear=1, clear2=1;
int Nsymb, sync_pos, sync_pos_slot;
int Ns;
int l;
int rx_power;
unsigned int adac_cnt;
int pbch_decoded = 0;
int frame_mod4,pbch_tx_ant;
u8 dummy;
RTIME time;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
openair_daq_vars.mode = openair_NOT_SYNCHED;
//openair_set_lo_freq_openair(openair_daq_vars.freq,openair_daq_vars.freq);
for (i=0;i<number_of_cards;i++) {
ret = setup_regs(i,frame_parms);
openair_get_frame(i); //received frame is stored in PHY_vars->RX_DMA_BUFFER
}
// sleep during acquisition of frame
time = rt_get_cpu_time_ns();
for (i=0;i<3*NUMBER_OF_CHUNKS_PER_FRAME;i++) {
rt_sleep(nano2count(NS_PER_SLOT/NUMBER_OF_OFDM_SYMBOLS_PER_SLOT));
}
time = rt_get_cpu_time_ns();
if (openair_daq_vars.one_shot_get_frame == 1) { // we're in a non real-time mode so just grab a frame and write to fifo
status=rtf_reset(rx_sig_fifo);
for (i=0;i<NB_ANTENNAS_RX;i++) {
length=rtf_put(rx_sig_fifo,(unsigned char*)RX_DMA_BUFFER[0][i],FRAME_LENGTH_BYTES);
if (length < FRAME_LENGTH_BYTES) {
msg("[openair][sched][rx_sig_fifo_handler] Didn't put %d bytes for antenna %d (put %d)\n",FRAME_LENGTH_BYTES,i,length);
}
else {
msg("[openair][sched][rx_sig_fifo_handler] Worte %d bytes for antenna %d to fifo (put %d)\n",FRAME_LENGTH_BYTES,i,length);
}
}
// signal that acquisition is done in control fifo
rtf_put(rf_cntl_fifo,&openair_daq_vars.sched_cnt,sizeof(int));
openair_daq_vars.one_shot_get_frame = 0;
}
if (openair_daq_vars.one_shot_get_frame == 0) { // we're in a real-time mode so do basic decoding
memcpy((void *)(RX_DMA_BUFFER[0][0]+FRAME_LENGTH_COMPLEX_SAMPLES),(void*)RX_DMA_BUFFER[0][0],OFDM_SYMBOL_SIZE_BYTES);
memcpy((void *)(RX_DMA_BUFFER[0][1]+FRAME_LENGTH_COMPLEX_SAMPLES),(void*)RX_DMA_BUFFER[0][1],OFDM_SYMBOL_SIZE_BYTES);
#ifdef DEBUG_PHY
for (i=0;i<number_of_cards;i++)
msg("[openair][SCHED][SYNC] card %d freq %d:%d, RX_DMA ADR 0 %x, RX_DMA ADR 1 %x, OFDM_SPF %d, RX_GAIN_VAL %x, TCXO %d, NODE_ID %d\n",
(pci_interface[i]->freq_info>>1)&3,
(pci_interface[i]->freq_info>>3)&3,
pci_interface[i]->adc_head[0],
pci_interface[i]->adc_head[1],
pci_interface[i]->ofdm_symbols_per_frame,
pci_interface[i]->rx_gain_val,
pci_interface[i]->tcxo_dac,
pci_interface[i]->node_id);
#endif
if (openair_daq_vars.node_configured == 3) { // the node has been cofigured as a UE
msg("[openair][SCHED][SYNCH] starting sync\n");
if (initial_sync(PHY_vars_UE_g[0]) == 0) {
if (openair_daq_vars.node_running == 1) {
pci_interface[0]->frame_offset = PHY_vars_UE_g[0]->rx_offset;
openair_daq_vars.mode = openair_SYNCHED;
openair_daq_vars.scheduler_interval_ns=NS_PER_SLOT; // initial guess
openair_daq_vars.last_adac_cnt=-1;
msg("[openair][SCHED][SYNCH] openair synched \n");
}
}
}
/*
// Measurements
rx_power = 0;
for (i=0;i<NB_ANTENNAS_RX; i++) {
// energy[i] = signal_energy(lte_eNB_common_vars->rxdata[i], FRAME_LENGTH_COMPLEX_SAMPLES);
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi[0][i] = signal_energy((int*)RX_DMA_BUFFER[0][i],FRAME_LENGTH_COMPLEX_SAMPLES);
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi_dB[0][i] = dB_fixed(PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi[0][i]);
rx_power += PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi[0][i];
}
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi_tot[0] = dB_fixed(rx_power);
if (openair_daq_vars.rx_rf_mode == 0)
PHY_vars_UE_g[0]->PHY_measurements.rx_rssi_dBm[0] = PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi_tot[0] - PHY_vars_UE_g[0]->rx_total_gain_dB + 25;
else
PHY_vars_UE_g[0]->PHY_measurements.rx_rssi_dBm[0] = PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi_tot[0] - PHY_vars_UE_g[0]->rx_total_gain_dB;
msg("[openair][SCHED] RX RSSI %d dBm, digital (%d, %d) dB, linear (%d, %d), RX gain %d dB, TDD %d, Dual_tx %d\n",
PHY_vars_UE_g[0]->PHY_measurements.rx_rssi_dBm[0],
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi_dB[0][0],
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi_dB[0][1],
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi[0][0],
PHY_vars_UE_g[0]->PHY_measurements.wideband_cqi[0][1],
PHY_vars_UE_g[0]->rx_total_gain_dB,
pci_interface[0]->tdd,
pci_interface[0]->dual_tx);
*/
#ifdef EMOS
memcpy(&emos_dump_UE.PHY_measurements[0], &PHY_vars_UE_g[0]->PHY_measurements, sizeof(PHY_MEASUREMENTS));
emos_dump_UE.timestamp = rt_get_time_ns();
emos_dump_UE.UE_mode = UE_mode;
emos_dump_UE.rx_total_gain_dB = PHY_vars_UE_g[0]->rx_total_gain_dB;
debug_msg("[SCHED_LTE] Writing EMOS data to FIFO\n");
if (rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_UE, sizeof(fifo_dump_emos_UE))!=sizeof(fifo_dump_emos_UE)) {
msg("[SCHED_LTE] Problem writing EMOS data to FIFO\n");
}
#endif
/*
// Do AGC
if (openair_daq_vars.node_configured==3 && openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
phy_adjust_gain(PHY_vars_UE_g[0], 0);
if (clear == 1)
clear = 0;
}
if (openair_daq_vars.node_configured==3) {
lte_adjust_synch(&PHY_vars_UE_g[0]->lte_frame_parms,
PHY_vars_UE_g[0],
0,
clear2,
16384);
if (clear2 == 1)
clear2 = 0;
}
*/
}
msg("[openair][SCHED] leaving openair_sync()\n");
}
static void * top_level_scheduler(void *param) {
#ifdef CBMIMO1
unsigned int adac_cnt;
#endif // CBMIMO1
int adac_offset;
int first_increment = 0;
int i;
int ret=0;
LTE_DL_FRAME_PARMS *frame_parms=lte_frame_parms_g;
msg("[openair][SCHED][top_level_scheduler] top_level_scheduler started with id %x, MODE %d, cpuid = %d, fpu_flag = %d\n",(unsigned int)pthread_self(),openair_daq_vars.mode,rtai_cpuid(),pthread_self()->uses_fpu);
openair_daq_vars.sched_cnt = 0;
msg("[openair][SCHED][top_level_scheduler] SLOTS_PER_FRAME=%d, NUMBER_OF_CHUNKS_PER_SLOT=%d, NUMBER_OF_CHUNKS_PER_FRAME=%d, PHY_vars->mbox %p\n",
SLOTS_PER_FRAME,NUMBER_OF_CHUNKS_PER_SLOT, NUMBER_OF_CHUNKS_PER_FRAME, (void*)mbox);
// Do initialization routines that use SSE here. They should not be run from the main kernel module because they might screw up the floating point unit when interrupted.
lte_sync_time_init(frame_parms);
/*
// Init the heap
if (rtheap_init(&rt_heap, NULL, 4096, 4096) == 0) {
msg("[OPENAIR][SCHED] Heap initialized successfully\n");
}
else {
openair_sched_exit("[OPENAIR][SCHED] Cannot initialized heap\n");
}
*/
#ifdef RTAI_ENABLED
msg("[OPENAIR][SCHED] Sleeping %d ns (MODE = %d)\n",2*NS_PER_SLOT,openair_daq_vars.mode);
rt_sleep(nano2count(2*NS_PER_SLOT));
//rt_sleep(2*NS_PER_SLOT);
msg("[OPENAIR][SCHED] Awakening (MODE = %d)\n",openair_daq_vars.mode);
#endif //
openair_daq_vars.sync_state=0;
while (exit_openair == 0) {
#ifdef CBMIMO1
adac_cnt = (*(unsigned int *)mbox)%NUMBER_OF_CHUNKS_PER_FRAME; // counts from 0 to NUMBER_OF_CHUNKS_PER_FRAME-1
#endif //
openair_daq_vars.sched_cnt++;
if ((openair_daq_vars.mode == openair_NOT_SYNCHED) && (openair_daq_vars.node_id != PRIMARY_CH)) {
// DO Nothing
if (openair_daq_vars.synch_wait_cnt <= 0) {
rt_sleep(nano2count(NS_PER_SLOT));
//rt_sleep(NS_PER_SLOT);
#ifdef CBMIMO1 // Note this code cannot run on PLATON!!!
if (openair_daq_vars.tx_test == 0)
openair_sync();
#endif // CBMIMO1
if ( (openair_daq_vars.mode != openair_NOT_SYNCHED) &&
(openair_daq_vars.node_running == 1) ){
msg("[openair][SCHED] staring RT acquisition, adac_cnt = %d\n",adac_cnt);
#ifdef CBMIMO1
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_START_RT_ACQUISITION);
#endif //CBMIMO1
openair_daq_vars.sync_state = 1;
openair_daq_vars.sched_cnt = 0;
/*
for (i=0;i<NB_ANTENNAS_RX;i++){
bzero((void *)RX_DMA_BUFFER[0][0],FRAME_LENGTH_BYTES);
}
*/
for (i=0;i<NUMBER_OF_CHUNKS_PER_FRAME;i++) {
rt_sleep(nano2count(NS_PER_SLOT/NUMBER_OF_OFDM_SYMBOLS_PER_SLOT));
}
//rt_sleep(nano2count(NS_PER_SLOT*SLOTS_PER_FRAME));
//rt_sleep(NS_PER_SLOT*SLOTS_PER_FRAME);
}
#ifdef DEBUG_PHY
else {
if (((openair_daq_vars.sched_cnt - 1) % (SYNCH_WAIT_TIME<<2) ) == 0)
msg("[openair][SCHED][SYNCH] Return MODE : NOT SYNCHED, sched_cnt = %d\n",openair_daq_vars.sched_cnt);
}
#endif //DEBUG_PHY
if (openair_daq_vars.node_running == 0){
openair_daq_vars.synch_wait_cnt = SYNCH_WAIT_TIME;
}
else {
openair_daq_vars.synch_wait_cnt = SYNCH_WAIT_TIME_RUNNING;
}
}
openair_daq_vars.synch_wait_cnt--;
rt_sleep(nano2count(NS_PER_SLOT));
//rt_sleep(NS_PER_SLOT));
}
else { // We're in synch with the CH or are a 1ary clusterhead
#ifndef NOCARD_TEST
if (openair_daq_vars.sync_state == 0) { // This means we're a CH, so start RT acquisition!!
openair_daq_vars.rach_detection_count=0;
openair_daq_vars.sync_state = 1;
openair_daq_vars.sched_cnt = 0;
msg("[openair][sched][top_level_scheduler] Starting RT acquisition, ofdm_symbols_per_frame %d, log2_symbol_size %d\n",
NUMBER_OF_SYMBOLS_PER_FRAME, LOG2_NUMBER_OF_OFDM_CARRIERS);
#ifdef CBMIMO1
for (i=0;i<number_of_cards;i++) {
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_START_RT_ACQUISITION);
}
#endif //CBMIMO1
#ifdef OPENAIR2
if (openair_daq_vars.node_id == PRIMARY_CH) {
msg("[openair][SCHED][SYNCH] Calling mrbch_phy_sync_failure\n");
mac_xface->mrbch_phy_sync_failure(0,0);
mac_xface->frame = 0;
}
#endif
openair_daq_vars.scheduler_interval_ns=NS_PER_SLOT; // initial guess
openair_daq_vars.last_adac_cnt=-1;
}
if (openair_daq_vars.sync_state==1) // waiting for first wrap-around of frame
{
if (adac_cnt==0)
{
msg("[openair][SCHED][top_level_scheduler] got adac_cnt=0, starting acquisition\n");
openair_daq_vars.sync_state=2;
openair_daq_vars.last_adac_cnt=0;
openair_daq_vars.slot_count=0;
openair_daq_vars.sched_cnt = 0;
first_increment = 0;
rt_sleep(nano2count(openair_daq_vars.scheduler_interval_ns)); /* sleep for one slot */
//rt_sleep(openair_daq_vars.scheduler_interval_ns); /* sleep for one slot */
}
else
{
//msg("[openair][SCHED][top_level_scheduler] sync startup, current time=%llu, waitig for adac_cnt=0 (current adac_cnt=%d)\n",rt_get_time_ns(),adac_cnt);
//msg("[openair][SCHED][top_level_scheduler] waiting for adac_cnt=0 (current adac_cnt=%d)\n",adac_cnt);
rt_sleep(nano2count(NS_PER_SLOT/NUMBER_OF_OFDM_SYMBOLS_PER_SLOT/2)); /* sleep for half a SYMBOL */
//rt_sleep(NS_PER_SLOT/NUMBER_OF_OFDM_SYMBOLS_PER_SLOT/2); /* sleep for half a SYMBOL */
if (openair_daq_vars.sched_cnt > 3*NUMBER_OF_SYMBOLS_PER_FRAME) {
msg("[openair][SCHED][top_level_scheduler] got sched_cnt =%d, stopping\n",openair_daq_vars.sched_cnt);
openair_daq_vars.mode = openair_NOT_SYNCHED;
openair_daq_vars.sync_state=0;
openair1_restart();
//openair_sched_exit("exit");
}
}
}
else if (openair_daq_vars.sync_state==2) /* acquisition running, track hardware.... */
{
// if (mac_xface->frame % 100 == 0)
// msg("[openair][SCHED] frame %d: scheduler interval %d\n",mac_xface->frame,openair_daq_vars.scheduler_interval_ns);
adac_offset=((int)adac_cnt-((int)openair_daq_vars.slot_count*NUMBER_OF_CHUNKS_PER_SLOT));
if (adac_offset > NUMBER_OF_CHUNKS_PER_FRAME)
adac_offset -= NUMBER_OF_CHUNKS_PER_FRAME;
else if (adac_offset < 0)
adac_offset += NUMBER_OF_CHUNKS_PER_FRAME;
// if (mac_xface->frame % 100 == 0)
// msg("[openair][SCHED] frame %d: adac_offset %d\n",mac_xface->frame,adac_offset);
if (adac_offset > 20) {
msg("[openair][sched][top_level_scheduler] Frame %d : Scheduling too late (adac_offset %d, adac_cnt %d, slot_count %d, tx_test = %d), restarting ...\n",
mac_xface->frame, adac_offset, adac_cnt, openair_daq_vars.slot_count,openair_daq_vars.tx_test);
openair1_restart();
}
if (adac_offset>=NUMBER_OF_CHUNKS_PER_SLOT)
{
if (adac_offset>NUMBER_OF_CHUNKS_PER_SLOT) /* adjust openair_daq_vars.scheduler_interval_ns to track the ADAC counter */
{
openair_daq_vars.scheduler_interval_ns-= DRIFT_OFFSET;
if (openair_daq_vars.scheduler_interval_ns < NS_PER_SLOT - MAX_DRIFT_COMP)
openair_daq_vars.scheduler_interval_ns = NS_PER_SLOT - MAX_DRIFT_COMP;
/* msg("adac_offset=%d, openair_daq_vars.scheduler_interval_ns=%d\n",adac_offset,openair_daq_vars.scheduler_interval_ns); */
}
if (pthread_mutex_lock (&openair_mutex) != 0) // Signal MAC_PHY Scheduler
msg("[openair][SCHED][SCHED] ERROR pthread_mutex_lock\n");// lock before accessing shared resource
openair_daq_vars.instance_cnt++;
pthread_mutex_unlock (&openair_mutex);
// msg("[openair][SCHED][SCHED] Signaling MACPHY scheduler\n");
if (openair_daq_vars.instance_cnt == 0) // PHY must have finished by now
if (pthread_cond_signal(&openair_cond) != 0)
msg("[openair][SCHED][SCHED] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
openair_daq_vars.slot_count=(openair_daq_vars.slot_count+1) % SLOTS_PER_FRAME;
openair_daq_vars.last_adac_cnt=adac_cnt;
rt_sleep(nano2count(openair_daq_vars.scheduler_interval_ns));
//rt_sleep(openair_daq_vars.scheduler_interval_ns);
first_increment = 0;
}
else if (adac_offset<NUMBER_OF_CHUNKS_PER_SLOT)
{
if (first_increment == 0) {
openair_daq_vars.scheduler_interval_ns+=DRIFT_OFFSET;
first_increment = 1;
}
if (openair_daq_vars.scheduler_interval_ns > NS_PER_SLOT + MAX_DRIFT_COMP)
openair_daq_vars.scheduler_interval_ns = NS_PER_SLOT + MAX_DRIFT_COMP;
// msg("adac_offset=%d, openair_daq_vars.scheduler_interval_ns=%d, sleeping for 2us\n",adac_offset,openair_daq_vars.scheduler_interval_ns);
rt_sleep(nano2count(2000));
//rt_sleep(2000);
}
} // tracking mode
#else //NOCARD_TEST
if ((openair_daq_vars.slot_count % SLOTS_PER_FRAME) == 0) {
msg("[openair][SCHED][top_level_thread] Waiting for frame signal in fifo (instance cnt %d)\n",
openair_daq_vars.instance_cnt);
rf_cntl_packet.frame = mac_xface->frame;
rf_cntl_packet.rx_offset = PHY_vars->rx_offset;
rtf_put(rf_cntl_fifo,&rf_cntl_packet,sizeof(RF_CNTL_PACKET));
pthread_cond_wait(&openair_rx_fifo_cond,&openair_rx_fifo_mutex);
}
// here, wait for data in the test fifo
if (pthread_mutex_lock (&openair_mutex) != 0) // Signal MAC_PHY Scheduler
msg("[openair][SCHED][SCHED] ERROR pthread_mutex_lock\n");// lock before accessing shared resource
openair_daq_vars.instance_cnt++;
pthread_mutex_unlock (&openair_mutex);
if (openair_daq_vars.instance_cnt == 0) // PHY must have finished by now
if (pthread_cond_signal(&openair_cond) != 0)
msg("[openair][SCHED][SCHED] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
openair_daq_vars.slot_count=(openair_daq_vars.slot_count+1) % SLOTS_PER_FRAME;
rt_sleep(nano2count(openair_daq_vars.scheduler_interval_ns)); /* sleep for one slot */
//rt_sleep(openair_daq_vars.scheduler_interval_ns); /* sleep for one slot */
msg("[openair][SCHED][top_level_thread] slot_count =%d, scheduler_interval_ns = %d\n",openair_daq_vars.slot_count, openair_daq_vars.scheduler_interval_ns);
#endif //NOCARD_TEST
} // in synch
} // exit_openair = 0
msg("[openair][SCHED][top_level_thread] Frame %d: Exiting ... openair_daq_vars.sched_cnt = %d\n",mac_xface->frame, openair_daq_vars.sched_cnt);
openair_daq_vars.mode = openair_SCHED_EXIT;
// schedule openair_thread to exit
msg("[openair][SCHED][top_level_thread] Scheduling openair_thread to exit ... \n");
if (pthread_mutex_lock (&openair_mutex) != 0)
msg("[openair][SCHED][top_level_thread] ERROR pthread_mutex_lock\n");// lock before accessing shared resource
openair_daq_vars.instance_cnt = 10;
pthread_mutex_unlock (&openair_mutex);
if (pthread_cond_signal(&openair_cond) != 0)
msg("[openair][SCHED][top_level_thread] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
openair_daq_vars.node_running = 0;
// rt_task_delete(rt_whoami);
/* pthread_exit(NULL); */
msg("[openair][SCHED][top_level_thread] Exiting top_level_scheduler ... \n");
return(0);
}
#ifdef NOCARD_TEST
int rx_sig_fifo_handler(unsigned int fifo, int rw) {
int status,i;
int length;
if (rw=='w') {
for (i=0;i<NB_ANTENNAS_RX;i++) {
length=rtf_get(fifo,(unsigned char*)RX_DMA_BUFFER[0][0],FRAME_LENGTH_BYTES);
if (length < FRAME_LENGTH_BYTES)
msg("[openair][sched][rx_sig_fifo_handler] Didn't get %d bytes for antenna %d (got %d)\n",FRAME_LENGTH_BYTES,i,length);
}
status=rtf_reset(fifo);
msg("[openair][sched][rx_sig_fifo_handler] fifo reset status=%d\n",status);
pthread_cond_signal(&openair_rx_fifo_cond);
return(0);
}
else
return(0);
}
#endif //NOCARD_TEST
s32 openair_sched_init(void) {
int error_code;
int* tmp;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
mac_xface->frame = 0;
openair_daq_vars.scheduler_interval_ns=NS_PER_SLOT; // initial guess
openair_daq_vars.last_adac_cnt=-1;
pthread_mutex_init(&openair_mutex,NULL);
pthread_cond_init(&openair_cond,NULL);
if (mac_xface->is_primary_cluster_head == 1) {
printk("[openair][SCHED][init] Configuring primary eNodeB/clusterhead\n");
}
else if (mac_xface->is_secondary_cluster_head == 1) {
printk("[openair][SCHED][init] Configuring secondary eNodeB/clusterhead\n");
}
else {
printk("[openair][SCHED][init] Configuring regular UE/node\n");
}
openair_daq_vars.mode = openair_NOT_SYNCHED;
error_code = rtf_create(rx_sig_fifo, NB_ANTENNAS_RX*FRAME_LENGTH_BYTES);
printk("[openair][SCHED][INIT] Created rx_sig_fifo (%d bytes), error_code %d\n",
NB_ANTENNAS_RX*FRAME_LENGTH_BYTES,
error_code);
error_code = rtf_create(rf_cntl_fifo, 256);
printk("[openair][SCHED][INIT] Created rx_cntl_fifo, error_code %d\n",error_code);
#ifdef EMOS
error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE);
printk("[OPENAIR][SCHED][INIT] Created EMOS FIFO, error code %d\n",error_code);
#endif
#ifdef NOCARD_TEST
/*RX Signal FIFOS HANDLER*/
pthread_mutex_init(&openair_rx_fifo_mutex,NULL);
pthread_cond_init(&openair_rx_fifo_cond,NULL);
#endif //NOCARD_TEST
pthread_attr_init (&attr_threads[OPENAIR_THREAD_INDEX]);
pthread_attr_setstacksize(&attr_threads[OPENAIR_THREAD_INDEX],OPENAIR_THREAD_STACK_SIZE);
attr_threads[OPENAIR_THREAD_INDEX].priority = 1;
openair_daq_vars.instance_cnt = -1;
// Create openair_thread
error_code = pthread_create(&threads[OPENAIR_THREAD_INDEX],
&attr_threads[OPENAIR_THREAD_INDEX],
openair_thread,
(void *)0);
if (error_code!= 0) {
printk("[OPENAIR][SCHED][INIT] Could not allocate openair_thread, error %d\n",error_code);
return(error_code);
}
else {
printk("[OPENAIR][SCHED][INIT] Allocate openair_thread successful\n");
}
pthread_attr_init (&attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX]);
pthread_attr_setstacksize(&attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],OPENAIR_THREAD_STACK_SIZE);
attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX].priority = 0;
// Create top_level_scheduler
error_code = pthread_create(&threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],
&attr_threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX], //default attributes
top_level_scheduler,
(void *)0);
// rt_change_prio(threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],0);
if (error_code!= 0) {
printk("[openair][SCHED][INIT] Could not allocate top_level_scheduler, error %d\n",error_code);
return(error_code);
}
else {
printk("[openair][SCHED][INIT] Allocate top_level_scheduler successfull\n");
}
// Done by pthread_create in rtai_posix.h
// rt_task_use_fpu(threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX],1);
#ifdef NOCARD_TEST
/*RX Signal FIFOS HANDLER*/
pthread_mutex_init(&openair_rx_fifo_mutex,NULL);
pthread_cond_init(&openair_rx_fifo_cond,NULL);
error_code = rtf_create(rx_sig_fifo, NB_ANTENNAS_RX*FRAME_LENGTH_BYTES);
printk("[openair][SCHED][INIT] Created rx_sig_fifo, error_code %d\n",error_code);
error_code = rtf_create_handler(rx_sig_fifo, X_FIFO_HANDLER(rx_sig_fifo_handler));
printk("[openair][SCHED][INIT] Created rx_sig_fifo handler, error_code %d\n",error_code);
#endif //NOCARD_TEST
tmp = rt_malloc(sizeof(int));
printk("[openair][SCHED][INIT] tmp= %p\n",tmp);
rt_free(tmp);
return(error_code);
}
void openair_sched_cleanup(void) {
int error_code;
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
//pthread_exit(&threads[TOP_LEVEL_SCHEDULER_THREAD_INDEX]);//H.A
//pthread_exit(&threads[OPENAIR_THREAD_INDEX]);//F.K
#ifdef NOCARD_TEST
pthread_cond_destroy(&openair_rx_fifo_cond);
#endif //NOCARD_TEST
pthread_mutex_destroy(&openair_mutex);
pthread_cond_destroy(&openair_cond);
error_code = rtf_destroy(rx_sig_fifo);
printk("[OPENAIR][SCHED][CLEANUP] rx_sig_fifo closed, error_code %d\n", error_code);
error_code = rtf_destroy(rf_cntl_fifo);
printk("[OPENAIR][SCHED][CLEANUP] rf_cntl_fifo closed, error_code %d\n", error_code);
#ifdef EMOS
error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
printk("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
#endif
//rtheap_destroy(rt_heap);
printk("[openair][SCHED][CLEANUP] Done!\n");
}
void openair_sched_exit(char *str) {
u8 i;
msg("%s\n",str);
msg("[OPENAIR][SCHED] Frame %d: openair_sched_exit() called, preparing to exit ...\n",mac_xface->frame);
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
}
/*@}*/
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file sched_lte_fw2011.c
* \brief RTAI scheduler for LTE UE/eNB procedures (CBMIMO1 2011 FPGA firmware)
* \author R. Knopp, M. Guillaud, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
/*
* @{
*/
/*
* @addtogroup _physical_layer_ref_implementation_
\section _process_scheduling_ Process Scheduling
This section deals with real-time process scheduling for PHY and synchronization with certain hardware targets (CBMIMO1).
*/
#ifndef USER_MODE
#define __NO_VERSION__
/*
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
*/
#ifdef RTAI_ISNT_POSIX
#include "rt_compat.h"
#endif /* RTAI_ISNT_POSIX */
#include "MAC_INTERFACE/extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h"
#endif // CBMIMO1
#ifdef RTAI_ENABLED
#include <rtai.h>
#include <rtai_posix.h>
#include <rtai_fifos.h>
#endif //
#include <linux/pci.h>
#else
#include <stdio.h>
#include <stdlib.h>
#endif // /* USER_MODE */
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
#include "extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/from_grlib_softregs.h"
#endif //CBMIMO1
#ifdef SERIAL_IO
#include "rtai_serial.h"
#endif
#ifdef EMOS
#include "phy_procedures_emos.h"
extern fifo_dump_emos_UE emos_dump_UE;
#endif
/// Mutex for instance count on MACPHY scheduling
pthread_mutex_t openair_mutex;
/// Condition variable for MACPHY thread
pthread_cond_t openair_cond;
/// Threads
pthread_t threads[openair_SCHED_NB_THREADS]={NULL,NULL,NULL};
/// Thread Attributes
pthread_attr_t attr_threads[openair_SCHED_NB_THREADS];
/// RX Signal FIFO for Testing without hardware
#define RX_SIG_FIFO_NUMBER 59
int rx_sig_fifo = RX_SIG_FIFO_NUMBER;
/// RX Control FIFO for testing without hardware
#define RF_CNTL_FIFO_NUMBER 60
int rf_cntl_fifo = RF_CNTL_FIFO_NUMBER;
#ifdef NOCARD_TEST
/// RX Signal FIFO Mutex
pthread_mutex_t openair_rx_fifo_mutex;
/// RX Signal FIFO Condition variable
pthread_cond_t openair_rx_fifo_cond;
/// Packet for RX Signal Control
RF_CNTL_PACKET rf_cntl_packet;
#endif //NOCARD_TEST
/// Global exit variable (exit on error or manual stop via IOCTL)
int exit_openair = 0;
extern int init_dlsch_threads(void);
extern void cleanup_dlsch_threads(void);
extern int dlsch_instance_cnt[8];
extern pthread_mutex_t dlsch_mutex[8];
extern pthread_cond_t dlsch_cond[8];
#define NO_SYNC_TEST 1
#ifdef CBMIMO1
#define NUMBER_OF_CHUNKS_PER_SLOT NUMBER_OF_OFDM_SYMBOLS_PER_SLOT
#define NUMBER_OF_CHUNKS_PER_FRAME (NUMBER_OF_CHUNKS_PER_SLOT * LTE_SLOTS_PER_FRAME)
#define SYNCH_WAIT_TIME 4000 // number of symbols between SYNCH retries
#define SYNCH_WAIT_TIME_RUNNING 100 // number of symbols between SYNCH retries
#define DRIFT_OFFSET 300
#define NS_PER_SLOT 500000
#define MAX_DRIFT_COMP 3000
#endif // CBMIMO1
#define MAX_SCHED_CNT 50000000
rtheap_t rt_heap;
unsigned int sync_slot_cnt=0;
unsigned int sync_getting_frame = 0;
//static int hw_frame = 0;
static int intr_cnt = 0;
int intr_cnt2 = 0;
int intr_in = 0;
void openair1_restart(void) {
int i;
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
// openair_daq_vars.tx_test=0;
openair_daq_vars.sync_state = 0;
if (openair_daq_vars.is_eNB==0)
PHY_vars_eNB_g[0]->frame = 0;
else
PHY_vars_UE_g[0]->frame = 0;
/*
if ((mac_xface->is_cluster_head) && (mac_xface->is_primary_cluster_head)) {
openair_daq_vars.mode = openair_SYNCHED_TO_MRSCH;
}
else {
openair_daq_vars.mode = openair_NOT_SYNCHED;
}
*/
#ifdef OPENAIR2
msg("[openair][SCHED][SYNCH] Clearing MAC Interface\n");
//mac_resynch();
#endif //OPENAIR2
}
void openair_sync(void) {
int i;
//int size,j;
int status;
int length;
int ret;
// static unsigned char clear=1, clear2=1;
// int Nsymb, sync_pos, sync_pos_slot;
// int Ns;
// int l;
// int rx_power;
// unsigned int adac_cnt;
// int pbch_decoded = 0;
// int frame_mod4,pbch_tx_ant;
// u8 dummy;
// RTIME time;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
openair_daq_vars.mode = openair_NOT_SYNCHED;
//openair_set_lo_freq_openair(openair_daq_vars.freq,openair_daq_vars.freq);
// sleep during acquisition of frame
/*
time = rt_get_cpu_time_ns();
for (i=0;i<3*NUMBER_OF_CHUNKS_PER_FRAME;i++) {
rt_sleep(nano2count(NS_PER_SLOT/NUMBER_OF_OFDM_SYMBOLS_PER_SLOT));
}
time = rt_get_cpu_time_ns();
*/
if (openair_daq_vars.one_shot_get_frame == 1) { // we're in a non real-time mode so just grab a frame and write to fifo
if (sync_getting_frame == 0) {
for (i=0;i<number_of_cards;i++) {
ret = setup_regs(i,frame_parms);
openair_get_frame(i); //received frame is stored in PHY_vars->RX_DMA_BUFFER
}
sync_getting_frame = 1;
sync_slot_cnt = 0;
}
if (sync_slot_cnt == 40) { // wait 2 frames worth of samples
msg("[PHY][SYNC] Getting frame, slot %d, adac %d\n",sync_slot_cnt,openair_get_mbox());
status=rtf_reset(rx_sig_fifo);
for (i=0;i<NB_ANTENNAS_RX;i++) {
length=rtf_put(rx_sig_fifo,(unsigned char*)RX_DMA_BUFFER[0][i],FRAME_LENGTH_BYTES);
if (length < FRAME_LENGTH_BYTES) {
msg("[openair][sched][rx_sig_fifo_handler] Didn't put %d bytes for antenna %d (put %d)\n",FRAME_LENGTH_BYTES,i,length);
}
else {
msg("[openair][sched][rx_sig_fifo_handler] Worte %d bytes for antenna %d to fifo (put %d)\n",FRAME_LENGTH_BYTES,i,length);
}
}
// signal that acquisition is done in control fifo
rtf_put(rf_cntl_fifo,&openair_daq_vars.sched_cnt,sizeof(int));
openair_daq_vars.one_shot_get_frame = 0;
sync_getting_frame = 0;
sync_slot_cnt = 0;
}
sync_slot_cnt++;
} //(openair_daq_vars.one_shot_get_frame == 0)
#ifdef OPENAIR1
if ((openair_daq_vars.do_synch==1) && (openair_daq_vars.node_configured == 3)) {// the node has been cofigured as a UE and we do sync
if (sync_getting_frame == 0) {
ret = setup_regs(0,frame_parms);
openair_get_frame(0); //received frame is stored in PHY_vars->RX_DMA_BUFFER
sync_getting_frame = 1;
sync_slot_cnt = 0;
}
if (sync_slot_cnt == 40) { // wait 2 frames worth of samples
//memcpy((void *)(RX_DMA_BUFFER[0][0]+FRAME_LENGTH_COMPLEX_SAMPLES),(void*)RX_DMA_BUFFER[0][0],OFDM_SYMBOL_SIZE_BYTES);
//memcpy((void *)(RX_DMA_BUFFER[0][1]+FRAME_LENGTH_COMPLEX_SAMPLES),(void*)RX_DMA_BUFFER[0][1],OFDM_SYMBOL_SIZE_BYTES);
#ifdef DEBUG_PHY
for (i=0;i<number_of_cards;i++)
msg("[openair][SCHED][SYNC] card %d freq %d:%d, RX_DMA ADR 0 %x, RX_DMA ADR 1 %x, RX_GAIN_VAL %x, TDD_CONFIG %d, TCXO %d, NODE_ID %d\n",
(pci_interface[i]->freq_info>>1)&3,
(pci_interface[i]->freq_info>>3)&3,
pci_interface[i]->adc_head[0],
pci_interface[i]->adc_head[1],
//pci_interface[i]->ofdm_symbols_per_frame,
pci_interface[i]->rx_gain_val,
pci_interface[i]->tdd_config,
pci_interface[i]->tcxo_dac,
pci_interface[i]->node_id);
#endif
msg("[openair][SCHED][SYNCH] starting sync\n");
if (initial_sync(PHY_vars_UE_g[0]) == 0) {
if (openair_daq_vars.node_running == 1) {
for (i=0;i<number_of_cards;i++)
pci_interface[i]->frame_offset = PHY_vars_UE_g[0]->rx_offset;
openair_daq_vars.mode = openair_SYNCHED;
/*
lte_adjust_synch(&PHY_vars_UE_g[0]->lte_frame_parms,
PHY_vars_UE_g[0],
0,
clear2,
16384);
if (clear2 == 1)
clear2 = 0;
*/
msg("[openair][SCHED][SYNCH] Starting RT aquisition\n");
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_START_RT_ACQUISITION);
}
}
else {
msg("[openair][SCHED][SYNCH] PBCH not decoded!\n");
}
/*
// Do AGC
if (openair_daq_vars.rx_gain_mode == DAQ_AGC_ON) {
phy_adjust_gain(clear, 512, 0, PHY_vars_UE_g[0]);
if (clear == 1)
clear = 0;
}
*/
openair_daq_vars.do_synch=0;
sync_getting_frame = 0;
sync_slot_cnt = 0;
}
sync_slot_cnt++;
}
#endif
}
//-----------------------------------------------------------------------------
/** MACPHY Thread */
static void * openair_thread(void *param) {
//-----------------------------------------------------------------------------ddd
//------------------------------
#ifndef USER_MODE
struct sched_param p;
#endif // USER_MODE
u8 next_slot, last_slot;
unsigned int time_in,time_out,i;
unsigned int aa,slot_offset, slot_offset_F;
int diff;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
RTIME rt_time_in, rt_time_out, rt_diff;
int rc;
RTIME tv;
struct timespec ts;
// run on CPU 1, which should be reserved only for this (by adding isolcpus=1 noirqbalance to the kernel options). Also use IsolCpusMaks=0x2 when loading rtai_hal
// rt_set_runnable_on_cpuid(pthread_self(),1);
rt_sleep(nano2count(NS_PER_SLOT));
p.sched_priority = OPENAIR_THREAD_PRIORITY;
pthread_attr_setschedparam (&attr_threads[OPENAIR_THREAD_INDEX], &p);
#ifndef RTAI_ISNT_POSIX
pthread_attr_setschedpolicy (&attr_threads[OPENAIR_THREAD_INDEX], SCHED_FIFO);
#endif
printk("[openair][SCHED][openair_thread] openair_thread started with id %x, fpu_flag = %x, cpuid = %d\n",(unsigned int)pthread_self(),pthread_self()->uses_fpu,rtai_cpuid());
if (openair_daq_vars.is_eNB == 1) {
msg("[openair][SCHED][openair_thread] Configuring openair_thread for primary clusterhead\n");
}
else {
msg("[openair][SCHED][openair_thread] Configuring OPENAIR THREAD for regular node\n");
}
#ifdef OPENAIR1
lte_sync_time_init(frame_parms);
#endif
openair_daq_vars.sync_state=0;
exit_openair = 0;
sync_slot_cnt = 0;
sync_getting_frame = 0;
// Inner thread endless loop
// exits on error or normally
openair_daq_vars.sched_cnt = 0;
openair_daq_vars.instance_cnt = -1;
for (i=0;i<number_of_cards;i++)
Zero_Buffer((void*)TX_DMA_BUFFER[i][0],
4*SLOT_LENGTH_BYTES_NO_PREFIX);
while (exit_openair == 0) {
tv = rt_get_time();
count2timespec(tv, &ts);
ts.tv_nsec += 100000;
rc = pthread_mutex_timedlock(&openair_mutex,&ts);
if (rc==ETIMEDOUT)
msg("[SCHED][openair_thread] pthread_mutex_timedlock timed out, exiting\n");
else if (rc != 0)
msg("[SCHED][openair_thread] ERROR pthread_mutex_lock\n");
else {
//msg("[SCHED][openair_thread] Starting PHY processing for slot %d, frame %d\n",last_slot,mac_xface->frame);
//msg("[SCHED][openair_thread] Locked openair_mutex, instance_cnt=%d\n",openair_daq_vars.instance_cnt);
while (openair_daq_vars.instance_cnt < 0) {
// wait for the irq handler to signal
// this also unlocks the mutex
// when signal is received, mutex is automatically locked again
pthread_cond_wait(&openair_cond,&openair_mutex);
}
/*
if (exit_openair==1) {
msg("Exiting openair_thread ... \n");
break;
}
*/
//msg("[SCHED][openair_thread] unlocking openair_mutex, instance_cnt=%d\n",openair_daq_vars.instance_cnt);
if (pthread_mutex_unlock(&openair_mutex) !=0)
msg("[SCHED][openair_thread] ERROR unlocking openair_mutex\n");
}
next_slot = (openair_daq_vars.slot_count + 1 ) % LTE_SLOTS_PER_FRAME;
if (openair_daq_vars.slot_count==0)
last_slot = LTE_SLOTS_PER_FRAME-1;
else
last_slot = (openair_daq_vars.slot_count - 1 ) % LTE_SLOTS_PER_FRAME;
//msg("[SCHED][Thread] Mode = %d (openair_NOT_SYNCHED=%d), slot_count = %d, instance_cnt = %d\n",openair_daq_vars.mode,openair_NOT_SYNCHED,openair_daq_vars.slot_count,openair_daq_vars.instance_cnt);
if ((openair_daq_vars.mode != openair_NOT_SYNCHED) && (openair_daq_vars.node_running == 1)) {
time_in = openair_get_mbox();
rt_time_in = rt_get_time_ns();
#ifdef DEBUG_PHY
//debug_msg("[SCHED][OPENAIR_THREAD] frame = %d, slot_count %d, last %d, next %d\n", mac_xface->frame, openair_daq_vars.slot_count, last_slot, next_slot);
#endif
#ifdef OPENAIR1
if (openair_daq_vars.is_eNB==1) {
if (PHY_vars_eNB_g && PHY_vars_eNB_g[0]) {
PHY_vars_eNB_g[0]->frame = openair_daq_vars.hw_frame;
phy_procedures_eNB_lte(last_slot,next_slot,PHY_vars_eNB_g[0],0);
#ifndef IFFT_FPGA
slot_offset_F = (next_slot)*
(PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)*
((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
slot_offset = (next_slot)*
(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1);
for (aa=0; aa<PHY_vars_eNB_g[0]->lte_frame_parms.nb_antennas_tx; aa++) {
if (PHY_vars_eNB_g[0]->lte_frame_parms.Ncp == 1) {
/*
if ((openair_daq_vars.hw_frame%100) == 0)
msg("[SCHED][OPENAIR_THREAD] frame = %d, slot_offset_F %d, slot_offset %d, input %p, output %p, samples_per_tti %d\n",
openair_daq_vars.hw_frame,
slot_offset_F,
slot_offset,
&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F],
&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset>>1],
PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti);
*/
/*
for (i=0;i<6;i++) {
memset(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+i*PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size],0,PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size*sizeof(int));
((short*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa]))[(slot_offset_F+i*512+75)*2]=1024;
}
*/
/*
for (i=0;i<PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size;i++)
((short*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa]))[(slot_offset_F+i)*2]=i;
*/
/*
for (i=0;i<PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1;i++)
((char*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa]))[(slot_offset+i)*2] = (char) 0; //(i/30);
*/
PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], // input
#ifdef BIT8_TX
&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset>>1], // output
#else
&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset], // output
#endif
PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size, // log2_fft_size
(PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7, // number of symbols
PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples, // number of prefix samples
PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft, // IFFT twiddle factors
PHY_vars_eNB_g[0]->lte_frame_parms.rev, // bit-reversal permutation
CYCLIC_PREFIX);
if (((openair_daq_vars.hw_frame%1000)==0) && (next_slot==0) && (aa==0)) {
/*
for (i=0;i<511;i++) {
msg("twiddle_ifft(%d) = (%d, %d)\n", i,
PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft[4*i],
PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft[4*i+1]);
}
*/
for (i=0;i<512;i++)
msg("X(%d)=(%d,%d), ",i,((short*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa]))[(slot_offset_F+i)*2],
((short*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa]))[(slot_offset_F+i)*2+1]);
msg("\n");
for (i=0;i<640;i++)
msg("x(%d)=(%d,%d), ",i,((char*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa]))[(slot_offset+i)*2],
((char*)(PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa]))[(slot_offset+i)*2+1]);
msg("\n");
//exit_openair=1;
}
}
else {
msg("[SCHED][OPENAIR_THREAD] Normal prefix not implemented yet!!!\n");
}
}
#endif //IFFT_FPGA
}
}
else {
if (PHY_vars_UE_g && PHY_vars_UE_g[0])
phy_procedures_UE_lte(last_slot,next_slot,PHY_vars_UE_g[0],0,0);
#ifndef IFFT_FPGA
slot_offset_F = (next_slot)*
(PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size)*
((PHY_vars_UE_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
slot_offset = (next_slot)*
(PHY_vars_UE_g[0]->lte_frame_parms.ofdm_symbol_size + PHY_vars_UE_g[0]->lte_frame_parms.nb_prefix_samples)*
((PHY_vars_UE_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7);
for (aa=0; aa<PHY_vars_UE_g[0]->lte_frame_parms.nb_antennas_tx; aa++) {
if (PHY_vars_UE_g[0]->lte_frame_parms.Ncp == 1) {
/*
debug_msg("[SCHED][OPENAIR_THREAD] frame = %d, slot_offset_F %d, slot_offset %d, input %p, output %p\n",
mac_xface->frame,
slot_offset_F,
slot_offset,
&PHY_vars_UE_g[0]->lte_ue_common_vars.txdataF[aa][slot_offset_F],
&PHY_vars_UE_g[0]->lte_ue_common_vars.txdata[aa][slot_offset>>1]);
*/
PHY_ofdm_mod(&PHY_vars_UE_g[0]->lte_ue_common_vars.txdataF[aa][slot_offset_F], // input
#ifdef BIT8_TX
&PHY_vars_UE_g[0]->lte_ue_common_vars.txdata[aa][slot_offset>>1], // output
#else
&PHY_vars_UE_g[0]->lte_ue_common_vars.txdata[aa][slot_offset], // output
#endif
PHY_vars_UE_g[0]->lte_frame_parms.log2_symbol_size, // log2_fft_size
(PHY_vars_UE_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7, // number of symbols
PHY_vars_UE_g[0]->lte_frame_parms.nb_prefix_samples, // number of prefix samples
PHY_vars_UE_g[0]->lte_frame_parms.twiddle_ifft, // IFFT twiddle factors
PHY_vars_UE_g[0]->lte_frame_parms.rev, // bit-reversal permutation
CYCLIC_PREFIX);
}
else {
msg("[SCHED][OPENAIR_THREAD] Normal prefix not implemented yet!!!\n");
}
}
#endif //IFFT_FPGA
}
#endif //OPENAIR1
time_out = openair_get_mbox();
rt_time_out = rt_get_time_ns();
diff = (((int) time_out) - ((int) time_in)) % ((int) 160);
rt_diff = rt_time_out-rt_time_in;
/*
debug_msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d, macphy_scheduler time_in %d, time_out %d, diff %d, time_in %llu, time_out %llu, diff %llu\n",
mac_xface->frame, last_slot,
time_in,time_out,diff,
rt_time_in,rt_time_out,rt_diff);
*/
if (rt_diff > 500000)
msg("[SCHED][OPENAIR_THREAD] last_slot %d, macphy_scheduler time_in %d, time_out %d, diff %d, time_in %llu, time_out %llu, diff %llu\n",
last_slot,
time_in,time_out,diff,
rt_time_in,rt_time_out,rt_diff);
/*
if ((mac_xface->is_primary_cluster_head == 0) && (last_slot == 0)) {
if (openair_daq_vars.first_sync_call == 1)
openair_daq_vars.first_sync_call = 0;
}
*/
} // daq_mode != NOT_SYNCHED
else { // synchronization and get frame
if ((openair_daq_vars.hw_frame%100==0)
&& (openair_daq_vars.slot_count==0)
&& (openair_daq_vars.mode != openair_SYNCHED)) {
msg("[SCHED][OPENAIR_THREAD] Frame %d: last_slot %d: calling openair_sync\n",
openair_daq_vars.hw_frame,openair_daq_vars.slot_count);
openair_daq_vars.do_synch=1;
}
openair_sync();
}
// signal that PHY has finished by decreasing instance count
// don't forget to protect access with mutex
tv = rt_get_time();
count2timespec(tv, &ts);
ts.tv_nsec += 100000;
rc = pthread_mutex_timedlock(&openair_mutex,&ts);
if (rc==ETIMEDOUT)
msg("[SCHED][openair_thread] pthread_mutex_timedlock timed out, exiting\n");
else if (rc != 0)
msg("[SCHED][openair_thread] ERROR pthread_mutex_lock\n");
else {
openair_daq_vars.instance_cnt--;
//msg("[SCHED][openair_thread] Finished PHY processing for slot %d, frame %d\n",last_slot,mac_xface->frame);
// msg("[SCHED][openair_thread] unlocking openair_mutex, instance_cnt=%d\n",openair_daq_vars.instance_cnt);
if (pthread_mutex_unlock(&openair_mutex) !=0)
msg("[SCHED][openair_thread] ERROR unlocking openair_mutex\n");
}
} // end while (1)
// report what happened
msg ("[SCHED][OPENAIR_THREAD] Exited : openair_daq_vars.slot_count = %d, MODE = %d\n", openair_daq_vars.slot_count, openair_daq_vars.mode);
// rt_task_delete(rt_whoami);
/* pthread_exit(NULL); */
#ifdef SERIAL_IO
rt_spclose(COM1);
#endif
pthread_mutex_destroy(&openair_mutex);
pthread_cond_destroy(&openair_cond);
return(0);
}
int slot_irq_handler(int irq, void *cookie) {
unsigned int adac_cnt;
unsigned short irqval;
LTE_DL_FRAME_PARMS *frame_parms=lte_frame_parms_g;
int rc;
RTIME tv;
struct timespec ts;
u32 irqcmd;
static int busy=0;
intr_in = 1;
intr_cnt++;
if (oai_semaphore && inst_cnt_ptr && lxrt_task) {
rt_sem_wait(oai_semaphore);
//if ((intr_cnt2%2000)<10) rt_printk("intr_cnt %d, inst_cnt_ptr %p, inst_cnt %d\n",intr_cnt,inst_cnt_ptr,*inst_cnt_ptr);
if (*inst_cnt_ptr==0) {
rt_sem_signal(oai_semaphore); //now the mutex should have vaule 1
if (busy==0) {
rt_printk("intr_cnt %d, worker thread busy!\n", intr_cnt);
busy = 1;
} //else no need to repeat this message
}
else {
(*inst_cnt_ptr)++;
//rt_printk("*inst_cnt_ptr %d\n",*inst_cnt_ptr);
rt_sem_signal(oai_semaphore); //now the mutex should have vaule 1
rt_send_if(lxrt_task,intr_cnt);
if (busy==1) {
rt_printk("intr_cnt %d, resuming worker thread!\n", intr_cnt);
busy = 0;
} //else no need to repeat this message
}
intr_cnt2++;
}
if (vid != XILINX_VENDOR) { //CBMIMO1
// check interrupt status register
pci_read_config_word(pdev[0],6 , &irqval);
if ((irqval&8) != 0) {
//msg("got interrupt for CBMIMO1, intr_cnt=%d, node_configured=%d\n",intr_cnt,openair_daq_vars.node_configured);
// RESET PCI IRQ
openair_writel(pdev[0], FROM_GRLIB_CFG_GRPCI_EUR_CTRL_OFFSET, FROM_GRLIB_BOOT_HOK|FROM_GRLIB_PCI_IRQ_ACK);
openair_writel(pdev[0], FROM_GRLIB_CFG_GRPCI_EUR_CTRL_OFFSET, FROM_GRLIB_BOOT_HOK);
if (openair_daq_vars.node_configured > 0) {
adac_cnt = (*(unsigned int *)mbox);
openair_daq_vars.slot_count=intr_cnt % LTE_SLOTS_PER_FRAME;
//openair_daq_vars.slot_count=adac_cnt>>3;
//if ((adac_cnt>>3) == 0)
//if (((int) adac_cnt - (int) openair_daq_vars.last_adac_cnt)<0) // This is a new frame
if (openair_daq_vars.slot_count==0)
openair_daq_vars.hw_frame++;
if (((openair_daq_vars.hw_frame %100) == 0) && (openair_daq_vars.hw_frame>0)) {
tv = rt_get_time_ns();
msg("[SCHED][slot_irq_handler] time %llu, interrupt count %d, adac %d, last %d, HW Frame %d, slot %d\n",
tv,intr_cnt,adac_cnt,openair_daq_vars.last_adac_cnt,openair_daq_vars.hw_frame,openair_daq_vars.slot_count);
}
openair_daq_vars.last_adac_cnt=adac_cnt;
/*
if ((openair_daq_vars.hw_frame %100) == 0)
printk("[SCHED][slot_irq_handler] Current HW Frame %d, interrupt cnt %d\n",openair_daq_vars.hw_frame,intr_cnt);
*/
tv = rt_get_time();
count2timespec(tv, &ts);
ts.tv_nsec += 100000;
if (exit_openair==0) {
// Schedule openair_thread
//first lock the mutex that protects the counter that indicates if PHY is still busy
//rc = pthread_mutex_lock (&openair_mutex); // lock before accessing shared resource
rc = pthread_mutex_timedlock (&openair_mutex,&ts); // lock before accessing shared resource
if (rc==ETIMEDOUT) {
msg("[SCHED][slot_irq_handler] pthread_mutex_timedlock timed out, exiting\n");
//exit_openair = 1;
}
else if (rc != 0) {
msg("[SCHED][slot_irq_handler] ERROR pthread_mutex_lock, exiting\n");
//exit_openair = 1;
}
else {
// we locked the mutex successfully, so now we can check its value
//msg("[SCHED][slot_irq_handler] Locked openair_mutex, instance_cnt=%d\n",openair_daq_vars.instance_cnt);
if (openair_daq_vars.instance_cnt == 0) {// PHY is still busy
msg("[SCHED][slot_irq_handler] ERROR slot interrupt while processing, instance_cnt=%d\n",
openair_daq_vars.instance_cnt);
// unlock the mutex
if (pthread_mutex_unlock (&openair_mutex) != 0) {
msg("[SCHED][slot_irq_handler] ERROR pthread_mutex_unlock\n");
//exit_openair=1;
}
}
else { // schedule L2/L1H TX thread
openair_daq_vars.instance_cnt++; //now it should be 0
// Signal MAC_PHY Scheduler
/*
if ((openair_daq_vars.is_eNB==1) &&
(PHY_vars_eNB_g[0]->frame<100))
msg("[SCHED][slot_irq_handler] Signaling eNB MACPHY scheduler for slot %d\n",openair_daq_vars.slot_count);
else if ((openair_daq_vars.is_eNB==0) &&
(PHY_vars_UE_g[0]->frame<100))
msg("[SCHED][slot_irq_handler] Signaling UE MACPHY scheduler for slot %d\n",openair_daq_vars.slot_count);
*/
// unlock the mutex
if (pthread_mutex_unlock (&openair_mutex) != 0) {
msg("[SCHED][slot_irq_handler] ERROR pthread_mutex_unlock\n");
//exit_openair=1;
}
if (pthread_cond_signal(&openair_cond) != 0) {
msg("[SCHED][slot_irq_handler] ERROR pthread_cond_signal\n");// schedule L2/L1H TX thread
//exit_openair = 1;
}
}
}
}
} // node_configured > 0
rt_ack_irq(irq);
rt_unmask_irq(irq);
rt_enable_irq(irq);
intr_in = 0;
return IRQ_HANDLED;
}
else { // CBMIMO is not source of interrupt
rt_pend_linux_irq(irq);
intr_in = 0;
return IRQ_NONE;
}
// CBMIMO1 is not activated yet (no interrupts!)
rt_pend_linux_irq(irq);
intr_in = 0;
return IRQ_NONE;
}
else { //EXPRESS MIMO
// msg("Got Exmimo PCIe interrupt ...\n");
irqval = ioread32(bar[0]);
if ((irqval&0x80) != 0) {
// clear PCIE interrupt bit (bit 7 of register 0x0)
iowrite32(irqval&0xffffff7f,bar[0]);
irqcmd = ioread32(bar[0]+0x4);
if (irqcmd == SLOT_INTERRUPT) {
// process_slot_interrupt();
}
else if (irqcmd == PCI_PRINTK) {
// msg("Got PCIe interrupt for printk ...\n");
pci_fifo_printk();
}
else if (irqcmd == GET_FRAME_DONE) {
msg("Got PCIe interrupt for GET_FRAME_DONE ...\n");
openair_daq_vars.get_frame_done=1;
}
rt_ack_irq(irq);
rt_unmask_irq(irq);
rt_enable_irq(irq);
intr_in = 0;
return IRQ_HANDLED;
}
else {
// RESET PCI IRQ
rt_pend_linux_irq(irq);
intr_in = 0;
return IRQ_NONE;
}
}
}
s32 openair_sched_init(void) {
int error_code;
int* tmp;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
openair_daq_vars.scheduler_interval_ns=NS_PER_SLOT; // initial guess
openair_daq_vars.last_adac_cnt=-1;
exit_openair=0;
pthread_mutex_init(&openair_mutex,NULL);
pthread_cond_init(&openair_cond,NULL);
/*
if (openair_daq_vars.is_eNB==1){
printk("[openair][SCHED][init] Configuring primary clusterhead\n");
PHY_vars_eNB_g[0]->frame=0;
}
else {
PHY_vars_UE_g[0]->frame=0;
printk("[openair][SCHED][init] Configuring regular node\n");
}
*/
openair_daq_vars.mode = openair_NOT_SYNCHED;
#ifdef EMOS
error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE);
printk("[OPENAIR][SCHED][INIT] Created EMOS FIFO, error code %d\n",error_code);
#endif
pthread_attr_init (&attr_threads[OPENAIR_THREAD_INDEX]);
pthread_attr_setstacksize(&attr_threads[OPENAIR_THREAD_INDEX],OPENAIR_THREAD_STACK_SIZE);
attr_threads[OPENAIR_THREAD_INDEX].priority = 1;
openair_daq_vars.instance_cnt = -1;
// Create openair_thread
error_code = pthread_create(&threads[OPENAIR_THREAD_INDEX],
&attr_threads[OPENAIR_THREAD_INDEX],
openair_thread,
(void *)0);
if (error_code!= 0) {
printk("[OPENAIR][SCHED][INIT] Could not allocate openair_thread, error %d\n",error_code);
return(error_code);
}
else {
printk("[OPENAIR][SCHED][INIT] Allocate openair_thread successful\n");
}
// Create interrupt service routine for PCI
error_code = rtf_create(rx_sig_fifo, NB_ANTENNAS_RX*FRAME_LENGTH_BYTES);
printk("[openair][SCHED][INIT] Created rx_sig_fifo (%d bytes), error_code %d\n",
NB_ANTENNAS_RX*FRAME_LENGTH_BYTES,
error_code);
//if (mac_xface->is_cluster_head == 0)
//FK mac_xface->is_cluster_head not initialized at this stage
// error_code = init_dlsch_threads();
tmp = rt_malloc(sizeof(int));
printk("[openair][SCHED][INIT] tmp= %p\n",tmp);
rt_free(tmp);
return(error_code);
}
void openair_sched_cleanup() {
#ifdef EMOS
int error_code;
#endif
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
#ifdef EMOS
error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
printk("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
#endif
//if (mac_xface->is_cluster_head == 0)
//FK: mac_xface->is_cluster_head not initialized at this stage
// cleanup_dlsch_threads();
if (openair_irq_enabled==1) {
rt_disable_irq(pdev[0]->irq);
rt_release_irq(pdev[0]->irq);
}
printk("[openair][SCHED][CLEANUP] Done!\n");
}
void openair_sched_exit(char *str) {
u8 i;
msg("%s\n",str);
msg("[OPENAIR][SCHED] openair_sched_exit() called, preparing to exit ...\n");
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
}
/*@}*/
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file sched_lte_fw2011.c
* \brief RTAI scheduler for LTE UE/eNB procedures (CBMIMO1 2011 FPGA firmware)
* \author R. Knopp, M. Guillaud, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
/*
* @{
*/
/*
* @addtogroup _physical_layer_ref_implementation_
\section _process_scheduling_ Process Scheduling
This section deals with real-time process scheduling for PHY and synchronization with certain hardware targets (CBMIMO1).
*/
#ifndef USER_MODE
#define __NO_VERSION__
/*
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
*/
#ifdef RTAI_ISNT_POSIX
#include "rt_compat.h"
#endif /* RTAI_ISNT_POSIX */
#include "MAC_INTERFACE/extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#include "ARCH/CBMIMO1/DEVICE_DRIVER/defs.h"
#endif // CBMIMO1
#ifdef RTAI_ENABLED
#include <rtai.h>
#include <rtai_posix.h>
#include <rtai_fifos.h>
#endif //
#include <linux/pci.h>
#else
#include <stdio.h>
#include <stdlib.h>
#endif // /* USER_MODE */
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
#include "extern.h"
#ifdef CBMIMO1
#include "ARCH/CBMIMO1/DEVICE_DRIVER/from_grlib_softregs.h"
#endif //CBMIMO1
#ifdef SERIAL_IO
#include "rtai_serial.h"
#endif
#ifdef EMOS
#include "phy_procedures_emos.h"
extern fifo_dump_emos_UE emos_dump_UE;
#endif
/// Mutex for instance count on MACPHY scheduling
pthread_mutex_t openair_mutex;
/// Condition variable for MACPHY thread
pthread_cond_t openair_cond;
/// Threads
pthread_t threads[openair_SCHED_NB_THREADS]={NULL,NULL,NULL};
/// Thread Attributes
pthread_attr_t attr_threads[openair_SCHED_NB_THREADS];
/// RX Signal FIFO for Testing without hardware
#define RX_SIG_FIFO_NUMBER 59
int rx_sig_fifo = RX_SIG_FIFO_NUMBER;
/// RX Control FIFO for testing without hardware
#define RF_CNTL_FIFO_NUMBER 60
int rf_cntl_fifo = RF_CNTL_FIFO_NUMBER;
#ifdef NOCARD_TEST
/// RX Signal FIFO Mutex
pthread_mutex_t openair_rx_fifo_mutex;
/// RX Signal FIFO Condition variable
pthread_cond_t openair_rx_fifo_cond;
/// Packet for RX Signal Control
RF_CNTL_PACKET rf_cntl_packet;
#endif //NOCARD_TEST
/// Global exit variable (exit on error or manual stop via IOCTL)
int exit_openair = 0;
extern int init_dlsch_threads(void);
extern void cleanup_dlsch_threads(void);
extern int dlsch_instance_cnt[8];
extern pthread_mutex_t dlsch_mutex[8];
extern pthread_cond_t dlsch_cond[8];
#define NO_SYNC_TEST 1
#ifdef CBMIMO1
#define NUMBER_OF_CHUNKS_PER_SLOT NUMBER_OF_OFDM_SYMBOLS_PER_SLOT
#define NUMBER_OF_CHUNKS_PER_FRAME (NUMBER_OF_CHUNKS_PER_SLOT * LTE_SLOTS_PER_FRAME)
#define SYNCH_WAIT_TIME 4000 // number of symbols between SYNCH retries
#define SYNCH_WAIT_TIME_RUNNING 100 // number of symbols between SYNCH retries
#define DRIFT_OFFSET 300
#define NS_PER_SLOT 500000
#define MAX_DRIFT_COMP 3000
#endif // CBMIMO1
#define MAX_SCHED_CNT 50000000
rtheap_t rt_heap;
unsigned int sync_slot_cnt=0;
unsigned int sync_getting_frame = 0;
//static int hw_frame = 0;
static int intr_cnt = 0;
int intr_cnt2 = 0;
int intr_in = 0;
void openair1_restart(void) {
int i;
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
// openair_daq_vars.tx_test=0;
openair_daq_vars.sync_state = 0;
if (openair_daq_vars.is_eNB==0)
PHY_vars_eNB_g[0]->frame = 0;
else
PHY_vars_UE_g[0]->frame = 0;
/*
if ((mac_xface->is_cluster_head) && (mac_xface->is_primary_cluster_head)) {
openair_daq_vars.mode = openair_SYNCHED_TO_MRSCH;
}
else {
openair_daq_vars.mode = openair_NOT_SYNCHED;
}
*/
#ifdef OPENAIR2
msg("[openair][SCHED][SYNCH] Clearing MAC Interface\n");
//mac_resynch();
#endif //OPENAIR2
}
int slot_irq_handler(int irq, void *cookie) {
unsigned int adac_cnt;
unsigned short irqval;
LTE_DL_FRAME_PARMS *frame_parms=lte_frame_parms_g;
int rc;
RTIME tv;
struct timespec ts;
u32 irqcmd;
static int busy=0;
unsigned int slot_interrupt = 0;
intr_in = 1;
// intr_cnt++;
if (vid != XILINX_VENDOR) { //CBMIMO1
// check interrupt status register
pci_read_config_word(pdev[0],6 , &irqval);
if ((irqval&8) != 0) {
intr_cnt++;
slot_interrupt = 1;
//msg("got interrupt for CBMIMO1, intr_cnt=%d, node_configured=%d\n",intr_cnt,openair_daq_vars.node_configured);
// RESET PCI IRQ
openair_writel(pdev[0], FROM_GRLIB_CFG_GRPCI_EUR_CTRL_OFFSET, FROM_GRLIB_BOOT_HOK|FROM_GRLIB_PCI_IRQ_ACK);
openair_writel(pdev[0], FROM_GRLIB_CFG_GRPCI_EUR_CTRL_OFFSET, FROM_GRLIB_BOOT_HOK);
rt_ack_irq(irq);
rt_unmask_irq(irq);
rt_enable_irq(irq);
intr_in = 0;
}
else { // CBMIMO is not source of interrupt
rt_pend_linux_irq(irq);
intr_in = 0;
return IRQ_NONE;
}
if (oai_semaphore && inst_cnt_ptr && lxrt_task && (slot_interrupt == 1)) {
rt_sem_wait(oai_semaphore);
if ((intr_cnt2%2000)==0) rt_printk("***intr_cnt %d, intr_cnt2 %d, inst_cnt_ptr %p, inst_cnt %d\n",intr_cnt,intr_cnt2,inst_cnt_ptr,*inst_cnt_ptr);
if (*inst_cnt_ptr==0) {
rt_sem_signal(oai_semaphore); //now the mutex should have vaule 1
if (busy==0) {
rt_printk("intr_cnt %d, worker thread busy!\n", intr_cnt);
busy = 1;
} //else no need to repeat this message
}
else {
(*inst_cnt_ptr)++;
//rt_printk("*inst_cnt_ptr %d\n",*inst_cnt_ptr);
rt_sem_signal(oai_semaphore); //now the mutex should have vaule 1
rt_send_if(lxrt_task,intr_cnt);
if (busy==1) {
rt_printk("intr_cnt %d, resuming worker thread!\n", intr_cnt);
busy = 0;
} //else no need to repeat this message
}
intr_cnt2++;
}
}
else { //EXPRESS MIMO
// msg("Got Exmimo PCIe interrupt ...\n");
irqval = ioread32(bar[0]);
if ((irqval&0x80) != 0) {
// clear PCIE interrupt bit (bit 7 of register 0x0)
iowrite32(irqval&0xffffff7f,bar[0]);
irqcmd = ioread32(bar[0]+0x4);
if (irqcmd == SLOT_INTERRUPT) {
// process_slot_interrupt();
intr_cnt++;
slot_interrupt = 1;
rt_ack_irq(irq);
rt_unmask_irq(irq);
rt_enable_irq(irq);
intr_in = 0;
if ((intr_cnt%2000)==0) rt_printk("intr_cnt %d\n",intr_cnt);
}
else if (irqcmd == PCI_PRINTK) {
// msg("Got PCIe interrupt for printk ...\n");
pci_fifo_printk();
rt_ack_irq(irq);
rt_unmask_irq(irq);
rt_enable_irq(irq);
intr_in = 0;
return IRQ_HANDLED;
}
else if (irqcmd == GET_FRAME_DONE) {
msg("Got PCIe interrupt for GET_FRAME_DONE ...\n");
openair_daq_vars.get_frame_done=1;
rt_ack_irq(irq);
rt_unmask_irq(irq);
rt_enable_irq(irq);
intr_in = 0;
return IRQ_HANDLED;
}
}
else {
// RESET PCI IRQ
rt_printk("EXMIMO: got %x from control register (intr_cnt %d)\n",irqval,intr_cnt);
irqval = ioread32(bar[0]);
rt_printk("EXMIMO: retry got %x from control register (intr_cnt %d)\n",irqval,intr_cnt);
rt_pend_linux_irq(irq);
intr_in = 0;
return IRQ_NONE;
}
}
// clear PCIE interrupt bit (bit 7 of register 0x0)
return IRQ_HANDLED;
}
s32 openair_sched_init(void) {
int error_code;
int* tmp;
LTE_DL_FRAME_PARMS *frame_parms = lte_frame_parms_g;
openair_daq_vars.scheduler_interval_ns=NS_PER_SLOT; // initial guess
openair_daq_vars.last_adac_cnt=-1;
exit_openair=0;
//pthread_mutex_init(&openair_mutex,NULL);
//pthread_cond_init(&openair_cond,NULL);
/*
if (openair_daq_vars.is_eNB==1){
printk("[openair][SCHED][init] Configuring primary clusterhead\n");
PHY_vars_eNB_g[0]->frame=0;
}
else {
PHY_vars_UE_g[0]->frame=0;
printk("[openair][SCHED][init] Configuring regular node\n");
}
*/
openair_daq_vars.mode = openair_NOT_SYNCHED;
#ifdef EMOS
error_code = rtf_create(CHANSOUNDER_FIFO_MINOR,CHANSOUNDER_FIFO_SIZE);
printk("[OPENAIR][SCHED][INIT] Created EMOS FIFO, error code %d\n",error_code);
#endif
openair_daq_vars.instance_cnt = -1;
error_code = rtf_create(rx_sig_fifo, NB_ANTENNAS_RX*FRAME_LENGTH_BYTES);
printk("[openair][SCHED][INIT] Created rx_sig_fifo (%d bytes), error_code %d\n",
NB_ANTENNAS_RX*FRAME_LENGTH_BYTES,
error_code);
tmp = rt_malloc(sizeof(int));
printk("[openair][SCHED][INIT] tmp= %p\n",tmp);
rt_free(tmp);
return(error_code);
}
void openair_sched_cleanup() {
#ifdef EMOS
int error_code;
#endif
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
#ifdef EMOS
error_code = rtf_destroy(CHANSOUNDER_FIFO_MINOR);
printk("[OPENAIR][SCHED][CLEANUP] EMOS FIFO closed, error_code %d\n", error_code);
#endif
//if (mac_xface->is_cluster_head == 0)
//FK: mac_xface->is_cluster_head not initialized at this stage
// cleanup_dlsch_threads();
if (openair_irq_enabled==1) {
rt_disable_irq(pdev[0]->irq);
rt_release_irq(pdev[0]->irq);
}
printk("[openair][SCHED][CLEANUP] Done!\n");
}
void openair_sched_exit(char *str) {
u8 i;
msg("%s\n",str);
msg("[OPENAIR][SCHED] openair_sched_exit() called, preparing to exit ...\n");
exit_openair = 1;
openair_daq_vars.mode = openair_SCHED_EXIT;
for (i=0;i<number_of_cards;i++)
openair_dma(i,FROM_GRLIB_IRQ_FROM_PCI_IS_ACQ_DMA_STOP);
}
/*@}*/
......@@ -9,7 +9,7 @@ OPENAIR1_TOP = $(OPENAIR1_DIR)
OPENAIR2_TOP = $(OPENAIR2_DIR)
OPENAIR3 = $(OPENAIR3_DIR)
CFLAGS = -g -O -Wno-strict-aliasing -rdynamic -Wall -DPHYSIM -DNODE_RG -DUSER_MODE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DPHY_CONTEXT=1 $(CPUFLAGS) -DMALLOC_CHECK_=1 # -Wno-packed-bitfield-compat
CFLAGS = -g -O2 -Wno-strict-aliasing -rdynamic -Wall -DPHYSIM -DNODE_RG -DUSER_MODE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DPHY_CONTEXT=1 $(CPUFLAGS) -DMALLOC_CHECK_=1 # -Wno-packed-bitfield-compat
# DCI Debug
......@@ -189,7 +189,7 @@ clean :
rm -f *.o
cleanall : clean
rm -f dlsim pbchsim pdcchsim ulsim pucchsim
rm -f dlsim pbchsim pdcchsim ulsim pucchsim mbmssim prachsim
rm -f *.exe*
showflags :
......
......@@ -196,7 +196,7 @@ int main(int argc, char **argv) {
u16 Nid_cell=0;
int eNB_id = 0, eNB_id_i = 1;
unsigned char mcs=0,mcs_i=mcs,dual_stream_UE = 0,awgn_flag=0,round,dci_flag=0;
unsigned char mcs=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0,round,dci_flag=0;
unsigned char i_mod = 2;
unsigned short NB_RB;
unsigned char Ns,l,m;
......@@ -288,6 +288,7 @@ int main(int argc, char **argv) {
printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz);
signal(SIGSEGV, handler);
signal(SIGABRT, handler);
logInit();
......@@ -301,6 +302,7 @@ int main(int argc, char **argv) {
{
case 'a':
awgn_flag = 1;
channel_model = AWGN;
break;
case 'b':
tdd_config=atoi(optarg);
......@@ -467,7 +469,7 @@ int main(int argc, char **argv) {
openair_daq_vars.use_ia_receiver = 0;
}
if ((n_tx!=2) || (transmission_mode!=5)) {
msg("Unsupported nb of decoded users: %d user(s), %d user(s) to decode\n", n_tx, dual_stream_UE);
msg("IA receiver only supported for TM5!");
exit(-1);
}
break;
......@@ -597,13 +599,10 @@ int main(int argc, char **argv) {
printf("SCM-A=%d, SCM-B=%d, SCM-C=%d, SCM-D=%d, EPA=%d, EVA=%d, ETU=%d, Rayleigh8=%d, Rayleigh1=%d, Rayleigh1_corr=%d, Rayleigh1_anticorr=%d, Rice1=%d, Rice8=%d\n",
SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr, Rayleigh1_anticorr, Rice1, Rice8);
if(awgn_flag==0)
sprintf(bler_fname,"second_bler_tx%d_mcs%d_chan%d.csv",transmission_mode,mcs,channel_model);
else
if(transmission_mode==5)
sprintf(bler_fname,"awgn_bler_tx%d_mcs%d_u%d.csv",transmission_mode,mcs,dual_stream_UE);
else
sprintf(bler_fname,"awgn_bler_tx%d_mcs%d.csv",transmission_mode,mcs);
if(transmission_mode==5)
sprintf(bler_fname,"bler_tx%d_chan%d_nrx%d_mcs%d_mcsi%d_u%d_imod%d.csv",transmission_mode,channel_model,n_rx,mcs,mcs_i,dual_stream_UE,i_mod);
else
sprintf(bler_fname,"bler_tx%d_chan%d_nrx%d_mcs%d.csv",transmission_mode,channel_model,n_rx,mcs);
bler_fd = fopen(bler_fname,"w");
fprintf(bler_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n");
......@@ -616,6 +615,7 @@ int main(int argc, char **argv) {
fprintf(csv_fd,"data_all%d=[",mcs);
}
/*
//sprintf(tikz_fname, "second_bler_tx%d_u2=%d_mcs%d_chan%d_nsimus%d.tex",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames);
sprintf(tikz_fname, "second_bler_tx%d_u2%d_mcs%d_chan%d_nsimus%d",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames);
tikz_fd = fopen(tikz_fname,"w");
......@@ -710,6 +710,8 @@ int main(int argc, char **argv) {
fprintf(tikz_fd,"\\addplot[color=yellow, mark=+] plot coordinates {");
break;
}
*/
for (i=0;i<2;i++) {
s_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
......@@ -951,7 +953,7 @@ int main(int argc, char **argv) {
dci_alloc[num_dci].rnti = n_rnti+k;
dci_alloc[num_dci].format = format1;
dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]);
for(k=0;k<n_users;k++) {
printf("Generating dlsch params for user %d\n",k);
generate_eNB_dlsch_params_from_dci(0,
&DLSCH_alloc_pdu_1[0],
......@@ -964,7 +966,6 @@ int main(int argc, char **argv) {
0,
P_RNTI,
PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single);
}
num_dci++;
num_ue_spec_dci++;
......@@ -1086,7 +1087,7 @@ int main(int argc, char **argv) {
dci_alloc[num_dci].format = format1A;
dci_alloc[num_dci].nCCE = 0;
dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]);
for(k=0;k<n_users;k++) {
printf("Generating dlsch params for user %d\n",k);
generate_eNB_dlsch_params_from_dci(0,
&DLSCH_alloc_pdu_1[0],
......@@ -1099,7 +1100,6 @@ int main(int argc, char **argv) {
0,
P_RNTI,
PHY_vars_eNB->eNB_UE_stats[0].DL_pmi_single);
}
num_common_dci++;
num_dci++;
......@@ -1114,7 +1114,6 @@ int main(int argc, char **argv) {
dci_alloc[num_dci].rnti = n_rnti+k;
dci_alloc[num_dci].format = format1E_2A_M10PRB;
dci_alloc[num_dci].nCCE = 4*k;
for(k=0;k<n_users;k++) {
printf("Generating dlsch params for user %d\n",k);
generate_eNB_dlsch_params_from_dci(0,
&DLSCH_alloc_pdu2_1E[k],
......@@ -1127,7 +1126,6 @@ int main(int argc, char **argv) {
0,
P_RNTI,
PHY_vars_eNB->eNB_UE_stats[k].DL_pmi_single);
}
dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]);
num_ue_spec_dci++;
......@@ -1173,7 +1171,7 @@ int main(int argc, char **argv) {
input_buffer_length = PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->TBS/8;
input_buffer[k] = (unsigned char *)malloc(input_buffer_length+4);
memset(input_buffer[k],0,input_buffer_length+4);
if (input_trch_file==0) {
for (i=0;i<input_buffer_length;i++) {
input_buffer[k][i]= (unsigned char)(taus()&0xff);
......@@ -1196,12 +1194,23 @@ int main(int argc, char **argv) {
}
}
}
// this is for user 0 only
coded_bits_per_codeword = get_G(&PHY_vars_eNB->lte_frame_parms,
PHY_vars_eNB->dlsch_eNB[0][0]->nb_rb,
PHY_vars_eNB->dlsch_eNB[0][0]->rb_alloc,
get_Qm(PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->mcs),
num_pdcch_symbols,
0,subframe);
uncoded_ber_bit = (short*) malloc(sizeof(short)*coded_bits_per_codeword);
snr_step = input_snr_step;
for (ch_realization=0;ch_realization<n_ch_rlz;ch_realization++){
if(abstx){
printf("**********************Channel Realization Index = %d **************************\n", ch_realization);
saving_bler=1;
}
for (SNR=snr0;SNR<snr1;SNR+=snr_step) {
......@@ -1446,46 +1455,34 @@ int main(int argc, char **argv) {
}
for (k=0;k<n_users;k++) {
coded_bits_per_codeword = get_G(&PHY_vars_eNB->lte_frame_parms,
PHY_vars_eNB->dlsch_eNB[k][0]->nb_rb,
PHY_vars_eNB->dlsch_eNB[k][0]->rb_alloc,
get_Qm(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs),
num_pdcch_symbols,
0,subframe);
#ifdef TBS_FIX // This is for MESH operation!!!
tbs = (double)3*TBStable[get_I_TBS(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs)][PHY_vars_eNB->dlsch_eNB[k][0]->nb_rb-1]/4;
#else
tbs = PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->TBS;
#endif
rate = (double)tbs/(double)coded_bits_per_codeword;
uncoded_ber_bit = (short*) malloc(2*coded_bits_per_codeword);
if ((trials==0) && (round==0))
printf("Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n",
rate,rate*get_Qm(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs),
if ((SNR==snr0) && (trials==0) && (round==0))
printf("User %d: Rate = %f (%f bits/dim) (G %d, TBS %d, mod %d, pdcch_sym %d, ndi %d)\n",
k,rate,rate*get_Qm(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs),
coded_bits_per_codeword,
tbs,
get_Qm(PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->mcs),
num_pdcch_symbols,
PHY_vars_eNB->dlsch_eNB[0][0]->harq_processes[0]->Ndi);
/*
// generate channel here
random_channel(eNB2UE);
// generate frequency response
freq_channel(eNB2UE,NB_RB);
// generate PMI from channel
*/
// use the PMI from previous trial
if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) {
PHY_vars_eNB->dlsch_eNB[0][0]->pmi_alloc = quantize_subband_pmi(&PHY_vars_UE->PHY_measurements,0);
PHY_vars_UE->dlsch_ue[0][0]->harq_processes[0]->pmi_alloc = quantize_subband_pmi(&PHY_vars_UE->PHY_measurements,0);
PHY_vars_UE->dlsch_ue[0][0]->pmi_alloc = quantize_subband_pmi(&PHY_vars_UE->PHY_measurements,0);
if (n_users>1)
PHY_vars_eNB->dlsch_eNB[1][0]->pmi_alloc = (PHY_vars_eNB->dlsch_eNB[0][0]->pmi_alloc ^ 0x1555);
/*
......@@ -1496,6 +1493,8 @@ int main(int argc, char **argv) {
}
*/
}
start_meas(&PHY_vars_eNB->dlsch_encoding_stats);
if (dlsch_encoding(input_buffer[k],
&PHY_vars_eNB->lte_frame_parms,
......@@ -1508,7 +1507,7 @@ int main(int argc, char **argv) {
)<0)
exit(-1);
stop_meas(&PHY_vars_eNB->dlsch_encoding_stats);
// printf("Did not Crash here 1\n");
PHY_vars_eNB->dlsch_eNB[k][0]->rnti = (common_flag==0) ? n_rnti+k : SI_RNTI;
start_meas(&sts);
dlsch_scrambling(&PHY_vars_eNB->lte_frame_parms,
......@@ -1531,10 +1530,7 @@ int main(int argc, char **argv) {
printf("%d : (%x)\n",i,PHY_vars_eNB->dlsch_eNB[k][0]->harq_processes[0]->c[s][i]);
}
}
// printf("Did not Crash here 2\n");
// if (k==1)
// printf("AMP: %d\n",AMP);
start_meas(&PHY_vars_eNB->dlsch_modulation_stats);
re_allocated = dlsch_modulation(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id],
AMP,
......@@ -1543,10 +1539,10 @@ int main(int argc, char **argv) {
num_pdcch_symbols,
PHY_vars_eNB->dlsch_eNB[k][0]);
stop_meas(&PHY_vars_eNB->dlsch_modulation_stats);
// printf("Did not Crash here 3\n");
/*
if (trials==0 && round==0)
printf("RE count %d\n",re_allocated);
*/
if (num_layers>1)
re_allocated = dlsch_modulation(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id],
1024,
......@@ -2129,7 +2125,7 @@ int main(int argc, char **argv) {
}
}
//saving PMI incase of Transmission Mode > 5
//saving PMI in case of Transmission Mode > 5
if(abstx){
if(saving_bler==0)
......@@ -2155,7 +2151,8 @@ int main(int argc, char **argv) {
uncoded_ber/=coded_bits_per_codeword;
avg_ber += uncoded_ber;
write_output("uncoded_ber_bit.m","uncoded_ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0);
if (n_frames==1)
write_output("uncoded_ber_bit.m","uncoded_ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0);
/*
printf("precoded CQI %d dB, opposite precoded CQI %d dB\n",
......@@ -2281,8 +2278,6 @@ int main(int argc, char **argv) {
printf("DLSCH in error in round %d\n",round);
}
//free(uncoded_ber_bit);
//uncoded_ber_bit = NULL;
#ifdef XFORMS
phy_scope_UE(form_ue,
PHY_vars_UE,
......@@ -2438,8 +2433,8 @@ int main(int argc, char **argv) {
fclose(bler_fd);
fprintf(tikz_fd,"};\n");
fclose(tikz_fd);
//fprintf(tikz_fd,"};\n");
//fclose(tikz_fd);
if (input_trch_file==1)
fclose(input_trch_fd);
......@@ -2449,8 +2444,13 @@ int main(int argc, char **argv) {
fprintf(csv_fd,"];");
fclose(csv_fd);
}
free(uncoded_ber_bit);
uncoded_ber_bit = NULL;
for (k=0;k<n_users;k++) {
free(input_buffer[k]);
input_buffer[k]=NULL;
}
printf("Freeing dlsch structures\n");
for (i=0;i<2;i++) {
printf("eNB %d\n",i);
......
synctest:lxrt+sem+mbx+msg:!./synctest ;sleep 1;popall:control_c
condtest:lxrt+sem+mbx+msg:!sudo ./condtest;sleep 1;popall:control_c
msg_test:lxrt+sem+mbx+msg:!sudo ./msg_test;sleep 1;popall:control_c
msg_many:lxrt+sem+mbx+msg:!sudo ./msg_test;sleep 1;popall:control_c
eNB:lxrt+sem+mbx+msg:!sudo ./synctest;sleep 1;popall:control_c
synctest:lxrt+sem+mbx+msg+fifos:!./synctest ;sleep 1;popall:control_c
condtest:lxrt+sem+mbx+msg+fifos:!sudo ./condtest;sleep 1;popall:control_c
msg_test:lxrt+sem+mbx+msg+fifos:!sudo ./msg_test;sleep 1;popall:control_c
msg_many:lxrt+sem+mbx+msg+fifos:!sudo ./msg_test;sleep 1;popall:control_c
eNB:lxrt+sem+mbx+msg+fifos:!sudo ./synctest;sleep 1;popall:control_c
eNB_test:lxrt+sem+mbx+msg+smi:!sudo ./lte-softmodem -S -F enb2tx;sleep 1;popall:control_c
UE:lxrt+sem+mbx+msg:!sudo ./synctest -U -d -T 108;sleep 1;popall:control_c
UE0:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907602944 -V;sleep 1;popall:control_c
UE0_smbv:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907598252 -V;sleep 1;popall:control_c
UE850:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 859498000 -F ex2_850;sleep 1;popall:control_c
eNB850:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -d -C 859500000 -F ex2_850;sleep 1;popall:control_c
UE0noL2:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907593460 -F ex2_2 --no-L2-connect;sleep 1;popall:control_c
UE0calib:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1912600000 --calib-ue-rx -70 ;sleep 1;popall:control_c
UE0calibmed:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1912600000 --calib-ue-rx-med -70 ;sleep 1;popall:control_c
UE0calibbyp:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1912600000 --calib-ue-rx-byp -70 ;sleep 1;popall:control_c
UE0prach:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1912606900 -F ue1 --debug-ue-prach;sleep 1;popall:control_c
UE1:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue1 ;sleep 1;popall:control_c
UE1prach:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue1 --debug-ue-prach;sleep 1;popall:control_c
UE1noL2:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue1 --no-L2-connect;sleep 1;popall:control_c
UE2:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue2;sleep 1;popall:control_c
UE2prach:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue2 --debug-ue-prach;sleep 1;popall:control_c
UE2noL2:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue2 --no-L2-connect;sleep 1;popall:control_c
eNB0:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -C 1907600000 -d -V;sleep 1;popall:control_c
#eNB0:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -C 1907598252 -d -V;sleep 1;popall:control_c
eNB1:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -C 1907600000 -F ex2_2 -d;sleep 1;popall:control_c
eNB2:lxrt+sem+mbx+msg:!sudo ./lte-softmodem -C 1907600000 -F ue2 -d;sleep 1;popall:control_c
dot11:lxrt+sem+mbx+msg:!sudo ./dot11 -C 1907600000 -d;sleep 1;popall:control_c
dot11_tx_test: lxrt+sem+mbx+msg:!sudo ./dot11 -C 1907600000 -d -t;sleep 1;popall:control_c
eNB2_750:lxrt+sem+mbx+msg:!sudo ./synctest_eNB -C 746000000 -F enb1tx_750 -d;sleep 1;popall:control_c
eNB2_1900:lxrt+sem+mbx+msg:!sudo ./synctest_eNB -C 19076000000 -F enb1tx_1900 -d;sleep 1;popall:control_c
UE:lxrt+sem+mbx+msg+fifos:!sudo ./synctest -U -d -T 108;sleep 1;popall:control_c
#UE0:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907602944 -V;sleep 1;popall:control_c
#EXMIMO2 card 1
#UE0:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600480 -V;sleep 1;popall:control_c
#EXMIMO2 card 5
UE0:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907597440 -V;sleep 1;popall:control_c
UE0_smbv:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907598252 -V;sleep 1;popall:control_c
UE850:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 859498000 -F ex2_850;sleep 1;popall:control_c
eNB850:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -d -C 859500000 -F ex2_850;sleep 1;popall:control_c
UE0noL2:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600480 --no-L2-connect;sleep 1;popall:control_c
UE0calib:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1912600000 --calib-ue-rx -70 ;sleep 1;popall:control_c
UE0calibmed:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1912600000 --calib-ue-rx-med -70 ;sleep 1;popall:control_c
UE0calibbyp:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1912600000 --calib-ue-rx-byp -70 ;sleep 1;popall:control_c
UE0prach:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1912606900 -F ue1 --debug-ue-prach;sleep 1;popall:control_c
UE1:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue1 ;sleep 1;popall:control_c
UE1prach:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue1 --debug-ue-prach;sleep 1;popall:control_c
UE1noL2:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue1 --no-L2-connect;sleep 1;popall:control_c
UE2:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue2;sleep 1;popall:control_c
UE2prach:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue2 --debug-ue-prach;sleep 1;popall:control_c
UE2noL2:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -U -d -C 1907600000 -F ue2 --no-L2-connect;sleep 1;popall:control_c
eNB0:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -C 1907600000 -d -V;sleep 1;popall:control_c
#eNB0:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -C 1907598252 -d -V;sleep 1;popall:control_c
eNB1:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -C 1907600000 -F ex2_2 -d;sleep 1;popall:control_c
eNB2:lxrt+sem+mbx+msg+fifos:!sudo ./lte-softmodem -C 1907600000 -F ue2 -d;sleep 1;popall:control_c
dot11:lxrt+sem+mbx+msg+fifos:!sudo ./dot11 -C 1907600000 -d;sleep 1;popall:control_c
dot11_tx_test: lxrt+sem+mbx+msg+fifos:!sudo ./dot11 -C 1907600000 -d -t;sleep 1;popall:control_c
eNB2_750:lxrt+sem+mbx+msg+fifos:!sudo ./synctest_eNB -C 746000000 -F enb1tx_750 -d;sleep 1;popall:control_c
eNB2_1900:lxrt+sem+mbx+msg+fifos:!sudo ./synctest_eNB -C 19076000000 -F enb1tx_1900 -d;sleep 1;popall:control_c
......@@ -9,7 +9,7 @@ ifeq "$(GCCVERSION)" "4.6.1"
CFLAGS += -Wno-packed-bitfield-compat
endif
CFLAGS += -O
CFLAGS += -O2
CFLAGS += -DDRIVER2013 -I$(OPENAIR_TARGETS)/ARCH/EXMIMO/USERSPACE/LIB/ -I$(OPENAIR_TARGETS)/ARCH/EXMIMO/DEFS -DENABLE_VCD_FIFO
SRC = synctest.c condtest.c lte-softmodem.c
......@@ -101,7 +101,7 @@ endif
#CPUFLAGS = -mmmx -msse -msse2 -m32 -mssse3 -msse4.1
CPUFLAGS = -mmmx -msse -msse2 -mssse3 -msse4.1
#CFLAGS += -fno-common -mpreferred-stack-boundary=4
CFLAGS += -Wall -fno-strict-aliasing -DPHYSIM -DUSER_MODE -DPC_TARGET -DPC_DSP -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DPHY_CONTEXT=1 -g -ggdb -rdynamic $(CPUFLAGS) # -Wno-packed-bitfield-compat
CFLAGS += -Wall -fno-strict-aliasing -DPHYSIM -DUSER_MODE -DPC_TARGET -DPC_DSP -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DPHY_CONTEXT=1 -rdynamic $(CPUFLAGS) # -Wno-packed-bitfield-compat
CFLAGS += -DOPENAIR_LTE -DENABLE_FXP -DOPENAIR1 -DDLSCH_THREAD #-DULSCH_THREAD
#only for CBMIMO1
......@@ -119,7 +119,7 @@ CFLAGS += -DHARD_RT
endif
ifeq ($(EMOS),1)
CFLAGS += -DEMOS -DEMOS_CHANNEL
CFLAGS += -DEMOS #-DEMOS_CHANNEL
LDFLAGS += -lgps
endif
......@@ -247,7 +247,8 @@ run_eNB2:
rtai-load eNB2 --verbose
clean:
rm -rf $(OBJ) $(RTAI_OBJ)
rm -rf $(OBJ) $(RTAI_OBJ)
rm -f $(ASN1_MSG_INC)/asn1_msg.o
cleanasn1:
rm -f $(ASN1_MSG_OBJS1)
......@@ -265,6 +266,11 @@ cleancell:
rm -f $(OPENAIR2_DIR)/NAS/SIMU_CELLULAR/*.o
rm -f $(OPENAIR2_DIR)/NAS/SIMU_CELLULAR/*.d
cleanalmostall: clean
rm -f $(ASN1_MSG_OBJS1)
rm -rf condtest synctest lte-softmodem
rm -rf synctest_eNB synctest_UE
cleanall: clean cleanasn1
rm -rf condtest synctest lte-softmodem
rm -rf synctest_eNB synctest_UE
......
......@@ -122,8 +122,9 @@ pthread_attr_t attr_dlsch_threads;
struct sched_param sched_param_dlsch;
#endif
pthread_t thread2;
pthread_t thread3;
pthread_t thread2; //xforms
pthread_t thread3; //emos
/*
static int instance_cnt=-1; //0 means worker is busy, -1 means its free
int instance_cnt_ptr_kern,*instance_cnt_ptr_user;
......@@ -231,6 +232,12 @@ void *scope_thread(void *arg) {
char stats_buffer[16384];
//FILE *UE_stats, *eNB_stats;
int len=0;
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
sched_setscheduler(0, SCHED_FIFO,&sched_param);
printf("Scope thread has priority %d\n",sched_param.sched_priority);
/*
if (UE_flag==1)
......@@ -298,6 +305,13 @@ void *emos_thread (void *arg)
struct gps_data_t *gps_data = NULL;
struct gps_fix_t dummy_gps_data;
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
sched_setscheduler(0, SCHED_FIFO,&sched_param);
printf("EMOS thread has priority %d\n",sched_param.sched_priority);
timer = time(NULL);
now = localtime(&timer);
......@@ -320,6 +334,8 @@ void *emos_thread (void *arg)
printf("[EMOS] Error sending command to GPS\n");
//exit(-1);
}
else
printf("[EMOS] Opened GPS, gps_data=%p\n");
if (UE_flag==0)
channel_buffer_size = sizeof(fifo_dump_emos_eNB);
......@@ -365,7 +381,7 @@ void *emos_thread (void *arg)
continue;
/*
if (eNB_flag==1)
if (UE_flag==0)
printf("eNB: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_eNB*)fifo2file_ptr)->frame_tx,bytes);
else
printf("UE: count %d, frame %d, read: %d bytes from the fifo\n",counter, ((fifo_dump_emos_UE*)fifo2file_ptr)->frame_rx,bytes);
......@@ -479,16 +495,17 @@ static void *eNB_thread(void *arg)
else
diff = mbox_target - mbox_current;
if (diff < (-6)) {
LOG_D(HW,"eNB Frame %d, time %llu: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, diff);
slot++;
if (frame>0)
oai_exit=1;
if (slot==20){
slot=0;
frame++;
}
continue;
if (((slot%2==0) && (diff < (-14))) || ((slot%2==1) && (diff < (-7)))) {
// at the eNB, even slots have double as much time since most of the processing is done here and almost nothing in odd slots
LOG_D(HW,"eNB Frame %d, time %llu: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, diff);
slot++;
if (frame>0)
oai_exit=1;
if (slot==20){
slot=0;
frame++;
}
continue;
}
if (diff>8)
LOG_D(HW,"eNB Frame %d, time %llu: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, mbox_current, mbox_target, diff);
......@@ -713,7 +730,7 @@ static void *UE_thread(void *arg)
else
diff2 = mbox_target - mbox_current;
if (diff2 <(-5)) {
if (diff2 <(-7)) {
LOG_D(HW,"UE Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff2);
if (frame>0)
oai_exit=1;
......@@ -846,11 +863,13 @@ static void *UE_thread(void *arg)
else {
LOG_I(PHY,"[initial_sync] trying carrier off %d Hz\n",openair_daq_vars.freq_offset);
for (i=0; i<4; i++) {
p_exmimo_config->rf.rf_freq_rx[i] = carrier_freq[i]+openair_daq_vars.freq_offset;
p_exmimo_config->rf.rf_freq_tx[i] = carrier_freq[i]+openair_daq_vars.freq_offset;
if (p_exmimo_config->rf.rf_freq_rx[i])
p_exmimo_config->rf.rf_freq_rx[i] = carrier_freq[i]+openair_daq_vars.freq_offset;
if (p_exmimo_config->rf.rf_freq_tx[i])
p_exmimo_config->rf.rf_freq_tx[i] = carrier_freq[i]+openair_daq_vars.freq_offset;
}
openair0_dump_config(card);
rt_sleep_ns(FRAME_PERIOD);
}
}
}
......@@ -907,7 +926,7 @@ int main(int argc, char **argv) {
u32 rf_vcocal_850[4] = {2015, 2015, 2015, 2015};
u32 rf_rxdc[4] = {32896,32896,32896,32896};
u32 rxgain[4] = {20,20,20,20};
u32 txgain[4] = {25,25,25,25};
u32 txgain[4] = {20,20,20,20};
u16 Nid_cell = 0;
u8 cooperation_flag=0, transmission_mode=1, abstraction_flag=0;
......@@ -1106,7 +1125,7 @@ int main(int argc, char **argv) {
case 5:
case 6:
frame_parms->nb_antennas_tx = 2;
frame_parms->nb_antennas_rx = 1;
frame_parms->nb_antennas_rx = 2;
break;
default:
printf("Unsupported transmission mode %d\n",transmission_mode);
......@@ -1194,17 +1213,13 @@ int main(int argc, char **argv) {
openair_daq_vars.manual_timing_advance = 0;
//openair_daq_vars.timing_advance = TIMING_ADVANCE_HW;
openair_daq_vars.rx_gain_mode = DAQ_AGC_OFF;
openair_daq_vars.rx_gain_mode = DAQ_AGC_ON;
openair_daq_vars.auto_freq_correction = 0;
openair_daq_vars.use_ia_receiver = 1;
openair_daq_vars.use_ia_receiver = 0;
// if AGC is off, the following values will be used
// for (i=0;i<4;i++)
// rxgain[i] = 20;
rxgain[0] = 20;
rxgain[1] = 20;
rxgain[2] = 20;
rxgain[3] = 20;
for (i=0;i<4;i++)
rxgain[i] = 0;
for (i=0;i<4;i++) {
PHY_vars_UE_g[0]->rx_gain_max[i] = rxg_max[i];
......@@ -1286,18 +1301,13 @@ int main(int argc, char **argv) {
NB_INST=1;
openair_daq_vars.ue_dl_rb_alloc=0x1fff;
openair_daq_vars.target_ue_dl_mcs=20;
openair_daq_vars.target_ue_dl_mcs=0;
openair_daq_vars.ue_ul_nb_rb=6;
openair_daq_vars.target_ue_ul_mcs=12;
openair_daq_vars.target_ue_ul_mcs=6;
// if AGC is off, the following values will be used
// for (i=0;i<4;i++)
// rxgain[i]=30;
rxgain[0] = 20;
rxgain[1] = 20;
rxgain[2] = 20;
rxgain[3] = 20;
for (i=0;i<4;i++)
rxgain[i]=10;
// set eNB to max gain
PHY_vars_eNB_g[0]->rx_total_gain_eNB_dB = rxg_max[0] + rxgain[0] - 30; //was measured at rxgain=30;
......@@ -1332,6 +1342,7 @@ int main(int argc, char **argv) {
p_exmimo_config->framing.eNB_flag = 0;
else
p_exmimo_config->framing.eNB_flag = !UE_flag;
p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD + TXRXSWITCH_LSB;
p_exmimo_config->framing.resampling_factor = 2;
......@@ -1360,14 +1371,18 @@ int main(int argc, char **argv) {
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal_850[ant];
p_exmimo_config->rf.rffe_band_mode[ant] = DD_TDD;
}
else {
else if ((carrier_freq[ant] >= 1900000000) && (carrier_freq[ant] <= 2000000000)) {
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant];
p_exmimo_config->rf.rffe_band_mode[ant] = B19G_TDD;
}
else {
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal[ant];
p_exmimo_config->rf.rffe_band_mode[ant] = 0;
}
p_exmimo_config->rf.rffe_gain_txlow[ant] = 63;
p_exmimo_config->rf.rffe_gain_txhigh[ant] = 63;
p_exmimo_config->rf.rffe_gain_rxfinal[ant] = 63;
p_exmimo_config->rf.rffe_gain_txlow[ant] = 31;
p_exmimo_config->rf.rffe_gain_txhigh[ant] = 31;
p_exmimo_config->rf.rffe_gain_rxfinal[ant] = 31;
p_exmimo_config->rf.rffe_gain_rxlow[ant] = 63;
}
......@@ -1407,7 +1422,7 @@ int main(int argc, char **argv) {
#endif
#ifdef OPENAIR2
init_pdcp_thread(!UE_flag);
init_pdcp_thread();
#endif
number_of_cards = openair0_num_detected_cards;
......
......@@ -168,18 +168,6 @@ static void * rx_pdsch_thread(void *param) {
phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols,
phy_vars_ue->frame,subframe);
/*
// msg("[MYEMOS] frame %d, las_slot %d, IA %d\n",phy_vars_ue->frame,last_slot,openair_daq_vars.use_ia_receiver);
if ((phy_vars_ue->frame%500 == 0) && (phy_vars_ue->frame>=500) && (last_slot%2 == 0) && (openair_daq_vars.use_ia_receiver == 0)) {
msg("[MYEMOS] frame %d, IA receiver ON, MCS %d, bitrate %d\n",phy_vars_ue->frame,phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs,phy_vars_ue->bitrate[eNB_id]);
openair_daq_vars.use_ia_receiver = 1;
}
if ((phy_vars_ue->frame%1000 == 0) && (phy_vars_ue->frame>=500) && (last_slot%2 == 0) && (openair_daq_vars.use_ia_receiver == 1)) {
msg("[MYEMOS] frame %d, IA receiver OFF, MCS %d, bitrate %d\n",phy_vars_ue->frame,phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs,phy_vars_ue->bitrate[eNB_id]);
openair_daq_vars.use_ia_receiver = 0;
}
*/
if ((phy_vars_ue->transmission_mode[eNB_id] == 5) &&
(phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) &&
(openair_daq_vars.use_ia_receiver ==1)) {
......
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