Commit 4bf5f598 authored by laurent's avatar laurent

begining functional split 6

parent ebd40e8d
#define MTU 65536
#define UDP_TIMEOUT 100000L // in nano second
receiveSubFrame(int sock) {
//read all subframe data from the control unit
char * buf[MTU];
int ret=recv(sock, buf, sizeof(buf), 0);
if ( ret==-1) {
if ( errno == EWOULDBLOCK || errno== EINTR ) {
finishSubframeRecv();
} else {
LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno));
return;
}
} else {
}
}
void pdsch_procedures(PHY_VARS_eNB *eNB,
L1_rxtx_proc_t *proc,
int harq_pid,
LTE_eNB_DLSCH_t *dlsch,
LTE_eNB_DLSCH_t *dlsch1,
LTE_eNB_UE_stats *ue_stats,
int ra_flag) {
int frame=proc->frame_tx;
int subframe=proc->subframe_tx;
LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
// 36-212
if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF
// Replace dlsch_encoding
// data is in
// dlsch->harq_processes[harq_pid]->e
feedDlschBuffers(eNB,
dlsch_harq->pdu,
dlsch_harq->pdsch_start,
dlsch,
frame,
subframe,
&eNB->dlsch_rate_matching_stats,
&eNB->dlsch_turbo_encoding_stats,
&eNB->dlsch_turbo_encoding_waiting_stats,
&eNB->dlsch_turbo_encoding_main_stats,
&eNB->dlsch_turbo_encoding_wakeup_stats0,
&eNB->dlsch_turbo_encoding_wakeup_stats1,
&eNB->dlsch_interleaving_stats);
// 36-211
dlsch_scrambling(fp,
0,
dlsch,
harq_pid,
get_G(fp,
dlsch_harq->nb_rb,
dlsch_harq->rb_alloc,
dlsch_harq->Qm,
dlsch_harq->Nl,
dlsch_harq->pdsch_start,
frame,subframe,
0),
0,
frame,
subframe<<1);
dlsch_modulation(eNB,
eNB->common_vars.txdataF,
AMP,
frame,
subframe,
dlsch_harq->pdsch_start,
dlsch,
dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL);
}
dlsch->active = 0;
dlsch_harq->round++;
}
phy_procedures_eNB_TX_fs6() {
receiveSubFrame();
// We got
// subframe number
//
for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) {
memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * fp->symbols_per_tti],
0,
fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t));
}
if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
if (is_pmch_subframe(frame,subframe,fp)) {
pmch_procedures(eNB,proc);
} else {
// this is not a pmch subframe, so generate PSS/SSS/PBCH
common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
}
}
if (ul_subframe < 10)if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0;
else
#endif
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
if (eNB->ulsch[i]) {
ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid];
/* Store first_rb and n_DMRS for correct PHICH generation below.
* For PHICH generation we need "old" values of last scheduling
* for this HARQ process. 'generate_eNB_dlsch_params' below will
* overwrite first_rb and n_DMRS and 'generate_phich_top', done
* after 'generate_eNB_dlsch_params', would use the "new" values
* instead of the "old" ones.
*
* This has been tested for FDD only, may be wrong for TDD.
*
* TODO: maybe we should restructure the code to be sure it
* is done correctly. The main concern is if the code
* changes and first_rb and n_DMRS are modified before
* we reach here, then the PHICH processing will be wrong,
* using wrong first_rb and n_DMRS values to compute
* ngroup_PHICH and nseq_PHICH.
*
* TODO: check if that works with TDD.
*/
ulsch_harq->previous_first_rb = ulsch_harq->first_rb;
ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS;
}
}
}
num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols;
num_dci = eNB->pdcch_vars[subframe&1].num_dci;
if (num_dci > 0)
if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
generate_dci_top(num_pdcch_symbols,
num_dci,
&eNB->pdcch_vars[subframe&1].dci_alloc[0],
0,
AMP,
fp,
eNB->common_vars.txdataF,
subframe);
num_mdci = eNB->mpdcch_vars[subframe &1].num_dci;
if (num_mdci > 0) {
generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF);
}
}
// Now scan UE specific DLSCH
LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
dlsch0 = eNB->dlsch[(uint8_t)UE_id][0];
dlsch1 = eNB->dlsch[(uint8_t)UE_id][1];
if ((dlsch0)&&(dlsch0->rnti>0)&&
(dlsch0->active == 1)
) {
// get harq_pid
harq_pid = dlsch0->harq_ids[frame%2][subframe];
AssertFatal(harq_pid>=0,"harq_pid is negative\n");
if (harq_pid>=8) {
if (dlsch0->ue_type==0)
LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x \n",
harq_pid,UE_id,frame,subframe,dlsch0->rnti);
} else {
// generate pdsch
pdsch_procedures_fs6(eNB,
proc,
harq_pid,
dlsch0,
dlsch1,
&eNB->UE_stats[(uint32_t)UE_id],
0);
}
} else if ((dlsch0)&&(dlsch0->rnti>0)&&
(dlsch0->active == 0)
) {
// clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
dlsch0->subframe_tx[subframe]=0;
}
}
generate_phich_top(eNB,
proc,
AMP);
}
DL_thread_fs6() {
receiveSubFrame();
phy_procedures_eNB_TX_fs6();
ru->feptx_prec(ru);
ru->feptx_ofdm(ru);
ru->fh_south_out(ru);
}
int createListner (port) {
int sock;
AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, "");
struct sockaddr_in addr = {
sin_family:
AF_INET,
sin_port:
htons(port),
sin_addr:
{ s_addr: INADDR_ANY }
};
AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,"");
struct timeval tv={0,UDP_TIMEOUT};
AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,"");
}
DL_thread_frequency() {
frequency_t header;
full_read(&header,
#ifndef __SPLIT_HEADERS_H
#define __SPLIT_HEADERS_H
struct frequency_s {
int frame;
int subframe;
int timestamp;
int sampleSize;
int nbAnt
int nbSamples;
} frequency_t;
#endif
......@@ -431,7 +431,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0;
else
else
#endif
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
......
......@@ -1354,7 +1354,7 @@ int main(int argc, char **argv) {
printStatIndent2(&eNB->ulsch_deinterleaving_stats,"sub-block interleaving" );
printStatIndent2(&eNB->ulsch_demultiplexing_stats,"sub-block demultiplexing" );
printStatIndent2(&eNB->ulsch_rate_unmatching_stats,"sub-block rate-matching" );
printf("|__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n",
printf(" |__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n",
eNB->ulsch[0]->harq_processes[harq_pid]->Cminus ?
eNB->ulsch[0]->harq_processes[harq_pid]->Kminus :
eNB->ulsch[0]->harq_processes[harq_pid]->Kplus,
......
......@@ -105,7 +105,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
if ( IS_SOFTMODEM_BASICSIM ) {
libname=OAI_BASICSIM_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else if ( IS_SOFTMODEM_RFSIM ) {
} else if ( IS_SOFTMODEM_RFSIM && flag == RAU_LOCAL_RADIO_HEAD) {
libname=OAI_RFSIM_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else if (flag == RAU_LOCAL_RADIO_HEAD) {
......
......@@ -102,6 +102,10 @@ typedef enum {
IRIS_DEV,
/*!\brief device is NONE*/
NONE_DEV,
/*!\brief device is ADRV9371_ZC706 */
ADRV9371_ZC706_DEV,
/*!\brief device is UEDv2 */
UEDv2_DEV,
MAX_RF_DEV_TYPE
} dev_type_t;
......@@ -214,6 +218,14 @@ typedef struct {
int iq_rxrescale;
//! Configuration file for LMS7002M
char *configFilename;
//! remote IP/MAC addr for Ethernet interface
char *remote_addr;
//! remote port number for Ethernet interface
unsigned int remote_port;
//! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
char *my_addr;
//! local port number for Ethernet interface (eNB/BBU, UE)
unsigned int my_port;
#if defined(USRP_REC_PLAY)
unsigned short sf_mode; // 1=record, 2=replay
char sf_filename[1024]; // subframes file path
......@@ -223,6 +235,13 @@ typedef struct {
unsigned int sf_write_delay; // write delay in replay mode
unsigned int eth_mtu; // ethernet MTU
#endif
//! number of samples per tti
unsigned int samples_per_tti;
//! the sample rate for receive.
double rx_sample_rate;
//! the sample rate for transmit.
double tx_sample_rate;
} openair0_config_t;
/*! \brief RF mapping */
......@@ -384,6 +403,31 @@ struct openair0_device_t {
typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg);
/* type of transport init function, implemented in shared lib */
typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record
#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record
#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record
#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record
#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record
#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record
#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record
#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record
#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
#define sample_t uint32_t // 2*16 bits complex number
typedef struct {
uint64_t magic; // Magic value (see defines above)
uint32_t size; // Number of samples per antenna to follow this header
uint32_t nbAnt; // Total number of antennas following this header
// Samples per antenna follow this header,
// i.e. nbAnt = 2 => this header+samples_antenna_0+samples_antenna_1
// data following this header in bytes is nbAnt*size*sizeof(sample_t)
uint64_t timestamp; // Timestamp value of first sample
uint32_t option_value; // Option value
uint32_t option_flag; // Option flag
} samplesBlockHeader_t;
#ifdef __cplusplus
extern "C"
......@@ -408,7 +452,7 @@ openair0_timestamp get_usrp_time(openair0_device *device);
* \returns 0 in success
*/
int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *openair0_cfg);
#define gettid() syscall(__NR_gettid)
/*@}*/
#ifdef __cplusplus
......
......@@ -24,28 +24,23 @@
#define PORT 4043 //TCP port for this simulator
#define CirSize 3072000 // 100ms is enough
#define MaxBlock 30000
#define sample_t uint32_t // 2*16 bits complex number
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
#define MAGICeNB 0xA5A5A5A5A5A5A5A5
#define MAGICUE 0x5A5A5A5A5A5A5A5A
typedef struct {
uint64_t magic;
uint32_t size;
uint32_t nbAnt;
uint64_t timestamp;
} transferHeader;
#define sample_t uint32_t // 2*16 bits complex number
typedef struct buffer_s {
int conn_sock;
bool alreadyRead;
bool readEnabled;
uint64_t lastReceivedTS;
uint64_t lastWroteTS;
bool headerMode;
transferHeader th;
samplesBlockHeader_t th;
char *transferPtr;
uint64_t remainToTransfer;
char *circularBufEnd;
int nbAnt;
sample_t *circularBuf;
} buffer_t;
......@@ -55,19 +50,22 @@ typedef struct {
uint64_t typeStamp;
uint64_t initialAhead;
char *ip;
int saveIQfile;
buffer_t buf[FD_SETSIZE];
} rfsimulator_state_t;
void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
buffer_t *ptr=&bridge->buf[sock];
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
ptr->conn_sock=sock;
ptr->headerMode=true;
ptr->transferPtr=(char *)&ptr->th;
ptr->remainToTransfer=sizeof(transferHeader);
ptr->remainToTransfer=sizeof(samplesBlockHeader_t);
int sendbuff=1000*1000*10;
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
int tcp_maxseg = 1400;
AssertFatal ( setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg,sizeof(tcp_maxseg)) == 0, "");
struct epoll_event ev= {0};
ev.events = EPOLLIN | EPOLLRDHUP;
ev.data.fd = sock;
......@@ -87,7 +85,7 @@ void socketError(rfsimulator_state_t *bridge, int sock) {
LOG_W(HW,"Lost socket \n");
removeCirBuf(bridge, sock);
if (bridge->typeStamp==MAGICUE)
if (bridge->typeStamp==UE_MAGICDL_FDD)
exit(1);
}
}
......@@ -120,6 +118,11 @@ void setblocking(int sock, enum blocking_t active) {
static bool flushInput(rfsimulator_state_t *t);
void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
if (t->saveIQfile != -1) {
if (write(t->saveIQfile, _buf, count) != count )
LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno));
}
char *buf = _buf;
int l;
setblocking(fd, notBlocking);
......@@ -145,7 +148,7 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
int server_start(openair0_device *device) {
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
t->typeStamp=MAGICeNB;
t->typeStamp=ENB_MAGICDL_FDD;
AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
int enable = 1;
AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
......@@ -168,7 +171,7 @@ sin_addr:
int start_ue(openair0_device *device) {
rfsimulator_state_t *t = device->priv;
t->typeStamp=MAGICUE;
t->typeStamp=UE_MAGICDL_FDD;
int sock;
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
struct sockaddr_in addr = {
......@@ -196,43 +199,104 @@ sin_addr:
setblocking(sock, notBlocking);
allocCirBuf(t, sock);
t->buf[sock].alreadyRead=true; // UE will start blocking on read
t->buf[sock].readEnabled=true; // UE will start blocking on read
return 0;
}
uint64_t lwrote;
int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
rfsimulator_state_t *t = device->priv;
// We do small blocks because the UE and the eNB are not aligned
// So large blocks can lead to deadlock (each side waits a incoming block completed)
int curBeg=0;
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *ptr=&t->buf[i];
do {
int sizeToSend=min(nsamps-curBeg,MaxBlock);
if (ptr->conn_sock >= 0 ) {
transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
fullwrite(ptr->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[nsamps][nbAnt];
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *ptr=&t->buf[i];
for(int a=0; a<nbAnt; a++) {
sample_t *in=(sample_t *)samplesVoid[a];
if (ptr->conn_sock >= 0 ) {
samplesBlockHeader_t header= {t->typeStamp, sizeToSend, nbAnt, timestamp+curBeg};
fullwrite(ptr->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[sizeToSend][nbAnt];
for(int s=0; s<nsamps; s++)
tmpSamples[s][a]=in[s];
}
for(int a=0; a<nbAnt; a++) {
sample_t *in=((sample_t *)samplesVoid[a]) + curBeg;
if (ptr->conn_sock >= 0 )
fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
for(int s=0; s<sizeToSend; s++)
tmpSamples[s][a]=in[s];
}
if (ptr->conn_sock >= 0 ) {
fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(sizeToSend,nbAnt), t);
ptr->lastWroteTS=timestamp+curBeg+sizeToSend;
}
}
}
}
LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
sizeToSend, timestamp+curBeg, timestamp+curBeg+sizeToSend,
signal_energy(samplesVoid[0]+curBeg, sizeToSend) );
curBeg+=sizeToSend;
} while ( curBeg < nsamps ) ;
return nsamps;
}
static void oneTransferDone(rfsimulator_state_t *t, buffer_t *b) {
// check the header and start block transfer
if ( b->headerMode==true) {
AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) ||
(t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol");
b->headerMode=false;
if ( b->lastReceivedTS != b->th.timestamp && b->readEnabled && b->lastReceivedTS ) {
int nbAnt= b->th.nbAnt;
for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ )
for (int a=0; a < nbAnt; a++)
b->circularBuf[(index*nbAnt+a)%CirSize]=0;
LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS );
}
if ( b->readEnabled && b->lastReceivedTS && b->lastWroteTS)
AssertFatal( fabs((double)b->lastReceivedTS - (double)b->lastWroteTS) < (double)CirSize,
"Difference between Rx/Tx timestamps impossible, Rx: %lu, T:%lu\n",
b->lastReceivedTS, b->lastWroteTS);
else
printf("diff: %f\n", abs((double)b->lastReceivedTS - (double)b->lastWroteTS)/1000.0);
b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
} else {
LOG_I(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
// in NB case, the UE started to write, since this event, we will wait it's data
// This is needed because the UE doesn't write in initial sync mode
// in UE case, the UE is already in this state (at connection time)
b->readEnabled=true;
b->lastReceivedTS=b->th.timestamp+b->th.size;
// First block in UE, resync with the eNB current TS
if ( t->nextTimestamp == 0 ) {
t->nextTimestamp=b->lastReceivedTS-b->th.size;
LOG_I(HW,"Ue synchro on NB timestamp: %lu\n", t->nextTimestamp);
}
b->headerMode=true;
b->transferPtr=(char *)&b->th;
b->remainToTransfer=sizeof(samplesBlockHeader_t);
b->th.magic=-1;
}
}
static bool flushInput(rfsimulator_state_t *t) {
// Process all incoming events on sockets
// store the data in lists
struct epoll_event events[FD_SETSIZE]= {0};
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200);
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 2);
if ( nfds==-1 ) {
if ( errno==EINTR || errno==EAGAIN )
......@@ -264,13 +328,14 @@ static bool flushInput(rfsimulator_state_t *t) {
}
int blockSz;
char * circularBufEnd=((char *)b->circularBuf)+sampleToByte(CirSize,1);
if ( b->headerMode)
blockSz=b->remainToTransfer;
else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
blockSz= b->transferPtr+b->remainToTransfer < circularBufEnd ?
b->remainToTransfer :
b->circularBufEnd - 1 - b->transferPtr ;
circularBufEnd - 1 - b->transferPtr ;
int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
......@@ -285,46 +350,11 @@ static bool flushInput(rfsimulator_state_t *t) {
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz;
if (b->transferPtr==b->circularBufEnd - 1)
if (b->transferPtr==circularBufEnd - 1)
b->transferPtr=(char *)b->circularBuf;
// check the header and start block transfer
if ( b->headerMode==true && b->remainToTransfer==0) {
AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) ||
(t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol");
b->headerMode=false;
b->alreadyRead=true;
if ( b->lastReceivedTS != b->th.timestamp) {
int nbAnt= b->th.nbAnt;
for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ )
for (int a=0; a < nbAnt; a++)
b->circularBuf[(index*nbAnt+a)%CirSize]=0;
LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS );
}
b->lastReceivedTS=b->th.timestamp;
b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
}
if ( b->headerMode==false ) {
b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
if ( b->remainToTransfer==0) {
LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
// First block in UE, resync with the eNB current TS
if ( t->nextTimestamp == 0 )
t->nextTimestamp=b->lastReceivedTS-b->th.size;
b->headerMode=true;
b->transferPtr=(char *)&b->th;
b->remainToTransfer=sizeof(transferHeader);
b->th.magic=-1;
}
if ( b->remainToTransfer==0) {
oneTransferDone(t,b);
}
}
}
......@@ -367,7 +397,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
for ( int sock=0; sock<FD_SETSIZE; sock++)
if ( t->buf[sock].circularBuf &&
t->buf[sock].alreadyRead && //>= t->initialAhead &&
t->buf[sock].readEnabled &&
(t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
have_to_wait=true;
break;
......@@ -390,7 +420,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
for (int sock=0; sock<FD_SETSIZE; sock++) {
buffer_t *ptr=&t->buf[sock];
if ( ptr->circularBuf && ptr->alreadyRead ) {
if ( ptr->circularBuf && ptr->readEnabled ) {
for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
......@@ -438,7 +468,7 @@ int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_c
__attribute__((__visibility__("default")))
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
//set_log(HW,OAILOG_DEBUG);
set_log(HW,OAILOG_DEBUG);
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) {
......@@ -447,10 +477,22 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
}
rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ?
MAGICeNB:
MAGICUE;
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE");
device->trx_start_func = rfsimulator->typeStamp == MAGICeNB ?
ENB_MAGICDL_FDD:
UE_MAGICDL_FDD;
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "eNB" : "UE");
char *saveF;
if ((saveF=getenv("saveIQfile")) != NULL) {
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
if ( rfsimulator->saveIQfile != -1 )
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
else
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
} else
rfsimulator->saveIQfile = -1;
device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
server_start :
start_ue;
device->trx_get_stats_func = rfsimulator_get_stats;
......
......@@ -148,7 +148,7 @@ int attach_rru(RU_t *ru) {
RRU_CONFIG_msg_t rru_config_msg;
int received_capabilities=0;
wait_eNBs();
LOG_ENTER(PHY);
// Wait for capabilities
while (received_capabilities==0) {
memset((void *)&rru_config_msg,0,sizeof(rru_config_msg));
......@@ -208,7 +208,7 @@ int connect_rau(RU_t *ru) {
RRU_capabilities_t *cap;
int i;
int len;
LOG_ENTER(PHY);
// wait for RAU_tick
while (tick_received == 0) {
msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE;
......@@ -299,7 +299,7 @@ int connect_rau(RU_t *ru) {
// southbound IF5 fronthaul for 16-bit OAI format
static inline void fh_if5_south_out(RU_t *ru) {
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
LOG_ENTER(PHY);
send_IF5(ru, ru->proc.timestamp_tx, ru->proc.subframe_tx, &ru->seqno, IF5_RRH_GW_DL);
}
......@@ -315,7 +315,7 @@ static inline void fh_if4p5_south_out(RU_t *ru) {
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.subframe_tx);
LOG_ENTER(PHY);
if (subframe_select(&ru->frame_parms,ru->proc.subframe_tx)!=SF_UL)
send_IF4p5(ru,ru->proc.frame_tx, ru->proc.subframe_tx, IF4p5_PDLFFT);
}
......@@ -327,6 +327,7 @@ static inline void fh_if4p5_south_out(RU_t *ru) {
void fh_if5_south_in(RU_t *ru,int *frame, int *subframe) {
LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
RU_proc_t *proc = &ru->proc;
LOG_ENTER(PHY);
recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL);
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
......@@ -358,14 +359,14 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {
uint16_t packet_type;
uint32_t symbol_number=0;
uint32_t symbol_mask_full;
LOG_ENTER(PHY);
if ((fp->frame_type == TDD) && (subframe_select(fp,*subframe)==SF_S))
symbol_mask_full = (1<<fp->ul_symbols_in_S_subframe)-1;
else
symbol_mask_full = (1<<fp->symbols_per_tti)-1;
AssertFatal(proc->symbol_mask[*subframe]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*subframe,proc->symbol_mask[*subframe]);
LOG_D(PHY,"start rcv IF4p5 \n");
do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
recv_IF4p5(ru, &f, &sf, &packet_type, &symbol_number);
......@@ -382,6 +383,7 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) {
LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*subframe,proc->symbol_mask[*subframe]);
} while(proc->symbol_mask[*subframe] != symbol_mask_full);
LOG_D(PHY,"Done rcv IF4p5 \n");
//caculate timestamp_rx, timestamp_tx based on frame and subframe
proc->subframe_rx = sf;
......@@ -482,6 +484,7 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) {
symbol_mask = (1<<fp->symbols_per_tti)-1;
prach_rx = 0;
LOG_D(PHY,"start rcv IF4p5 \n");
do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
......@@ -578,6 +581,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) {
uint16_t packet_type;
uint32_t symbol_number,symbol_mask,symbol_mask_full;
int subframe_tx,frame_tx;
LOG_ENTER(PHY);
LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru);
symbol_number = 0;
symbol_mask = 0;
......@@ -643,7 +647,7 @@ void fh_if4p5_north_out(RU_t *ru) {
RU_proc_t *proc=&ru->proc;
LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
const int subframe = proc->subframe_rx;
LOG_ENTER(PHY);
if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU, proc->subframe_rx );
if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {
......@@ -712,6 +716,8 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
unsigned int rxs;
int i;
openair0_timestamp ts=0,old_ts=0;
LOG_ENTER(PHY);
LOG_D(PHY,"%s:%d start rx_rf \n", __FILE__,__LINE__);
for (i=0; i<ru->nb_rx; i++)
rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
......@@ -820,6 +826,7 @@ void tx_rf(RU_t *ru) {
lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10);
lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10);
int sf_extension = 0;
LOG_D(PHY,"start tx_rf \n");
if ((SF_type == SF_DL) ||
(SF_type == SF_S)) {
......@@ -935,6 +942,7 @@ static void *ru_thread_asynch_rxtx( void *param ) {
printf( "devices ok (ru_thread_asynch_rx)\n");
while (!oai_exit) {
LOG_ENTER(PHY);
if (oai_exit) break;
if (subframe==9) {
......@@ -968,7 +976,7 @@ void wakeup_slaves(RU_proc_t *proc) {
struct timespec wait;
wait.tv_sec=0;
wait.tv_nsec=5000000L;
LOG_ENTER(PHY);
for (i=0; i<proc->num_slaves; i++) {
RU_proc_t *slave_proc = proc->slave_proc[i];
......@@ -1029,7 +1037,7 @@ static void *ru_thread_prach( void *param ) {
if (oai_exit) break;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 );
LOG_ENTER(PHY);
if (ru->eNB_list[0]) {
prach_procedures(
ru->eNB_list[0]
......@@ -1075,7 +1083,7 @@ static void *ru_thread_prach_br( void *param ) {
if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break;
if (oai_exit) break;
LOG_ENTER(PHY);
rx_prach(NULL,
ru,
NULL,
......@@ -1098,7 +1106,7 @@ int wakeup_synch(RU_t *ru) {
struct timespec wait;
wait.tv_sec=0;
wait.tv_nsec=5000000L;
LOG_ENTER(PHY);
// wake up synch thread
// lock the synch mutex and make sure the thread is ready
if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) {
......@@ -1135,7 +1143,7 @@ void do_ru_synch(RU_t *ru) {
double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0];
double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0];
LOG_ENTER(PHY);
for (i=0; i<4; i++) {
ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i];
ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
......@@ -1198,7 +1206,7 @@ void wakeup_L1s(RU_t *ru) {
int i;
PHY_VARS_eNB **eNB_list = ru->eNB_list;
LOG_D(PHY,"wakeup_L1s (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top);
LOG_ENTER(PHY);
if (ru->num_eNB==1 && ru->eNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) {
// call eNB function directly
char string[20];
......@@ -1496,7 +1504,7 @@ static void *ru_thread_tx( void *param ) {
wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx");
if (oai_exit) break;
LOG_ENTER(PHY);
// do TX front-end processing if needed (precoding and/or IDFTs)
if (ru->feptx_prec) ru->feptx_prec(ru);
......@@ -1644,7 +1652,7 @@ static void *ru_thread( void *param ) {
// This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
while (!oai_exit) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,sched_getcpu());
LOG_ENTER(PHY);
// these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
// They are set on the first rx/tx in the underly FH routines.
if (subframe==9) {
......
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