initial rfsimulator commit

This commit is contained in:
laurent
2019-02-06 10:18:20 +01:00
parent 35767511f8
commit b8ccf3f280
17 changed files with 774 additions and 211 deletions
+21 -16
View File
@@ -34,40 +34,42 @@
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "common_lib.h"
#include "common/utils/load_module_shlib.h"
#include <common/utils/LOG/log.h>
int set_device(openair0_device *device) {
switch (device->type) {
case EXMIMO_DEV:
printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case USRP_B200_DEV:
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case USRP_X300_DEV:
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
case USRP_X300_DEV:
LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case BLADERF_DEV:
printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case LMSSDR_DEV:
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case NONE_DEV:
printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_W(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case ADRV9371_ZC706_DEV:
printf("[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case UEDv2_DEV:
printf("[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
default:
printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return -1;
}
return 0;
@@ -78,15 +80,15 @@ int set_transport(openair0_device *device) {
switch (device->transp_type) {
case ETHERNET_TP:
printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_I(HW,"[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return 0;
break;
case NONE_TP:
printf("[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_W(HW,"[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return 0;
break;
default:
printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
LOG_E(HW,"[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return -1;
break;
}
@@ -100,6 +102,9 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
int ret=0;
char *libname;
if (flag == RAU_LOCAL_RADIO_HEAD) {
if (getenv("RFSIMULATOR") != NULL)
libname="rfsimulator";
else
libname=OAI_RF_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else {
@@ -108,7 +113,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
}
ret=load_module_shlib(libname,shlib_fdesc,1,NULL);
if (ret < 0) {
fprintf(stderr,"Library %s couldn't be loaded\n",libname);
LOG_E(HW,"Library %s couldn't be loaded\n",libname);
} else {
ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg);
}
@@ -124,7 +129,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf
if ( rc >= 0) {
if ( set_device(device) < 0) {
fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
LOG_E(HW,"Unsupported radio head\n");
return -1;
}
}
@@ -136,7 +141,7 @@ int openair0_transport_load(openair0_device *device, openair0_config_t *openair0
rc=load_lib(device, openair0_cfg, eth_params, RAU_REMOTE_RADIO_HEAD);
if ( rc >= 0) {
if ( set_transport(device) < 0) {
fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__);
LOG_E(HW,"Unsupported transport protocol\n");
return -1;
}
}
+39
View File
@@ -0,0 +1,39 @@
#General
This is a RF simulator that allows to test OAI without a RF board.
It replaces a actual RF board driver.
As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound)
#build
You can build it the same way, and together with actual RF driver
Example:
```bash
./build_oai --ue-nas-use-tun --UE --eNB -w SIMU
```
It is also possible to build actual RF and use choose on each run:
```bash
./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator
```
Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem)
We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver.
#usage
Setting the env variable RFSIMULATOR enables the RF board simulator
It should the set to "enb" in the eNB
For the UE, it should be set to the IP address of the eNB
example:
```bash
sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50
```
Except this, the UE and the eNB can be used as it the RF is real
If you reach 'RA not active' on UE, be careful to generate a valid SIM
```bash
$OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o .
```
#Caveacts
Still issues in power control: txgain, rxgain are not used
no S1 mode is currently broken, so we were not able to test the simulator in noS1 mode
+478
View File
@@ -0,0 +1,478 @@
/*
Author: Laurent THOMAS, Open Cells for Nokia
copyleft: OpenAirInterface Software Alliance and it's licence
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/epoll.h>
#include <string.h>
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include "common_lib.h"
#include <openair1/PHY/defs_eNB.h>
#include "openair1/PHY/defs_UE.h"
#define PORT 4043 //TCP port for this simulator
#define CirSize 3072000 // 100ms is enough
#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;
typedef struct buffer_s {
int conn_sock;
bool alreadyWrote;
uint64_t lastReceivedTS;
bool headerMode;
transferHeader th;
char *transferPtr;
uint64_t remainToTransfer;
char *circularBufEnd;
sample_t *circularBuf;
} buffer_t;
typedef struct {
int listen_sock, epollfd;
uint64_t nextTimestamp;
uint64_t typeStamp;
uint64_t initialAhead;
char *ip;
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);
int sendbuff=1000*1000*10;
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
struct epoll_event ev= {0};
ev.events = EPOLLIN | EPOLLRDHUP;
ev.data.fd = sock;
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
}
void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
close(sock);
free(bridge->buf[sock].circularBuf);
memset(&bridge->buf[sock], 0, sizeof(buffer_t));
bridge->buf[sock].conn_sock=-1;
}
#define helpTxt "\
\x1b[31m\
rfsimulator: error: you have to run one UE and one eNB\n\
For this, export RFSIMULATOR=enb (eNB case) or \n\
RFSIMULATOR=<an ip address> (UE case)\n\
\x1b[m"
int fullwrite(int fd, void *_buf, int count) {
char *buf = _buf;
int ret = 0;
int l;
while (count) {
l = write(fd, buf, count);
if (l <= 0) {
if(errno==EAGAIN || errno==EINTR)
continue;
else
return -1;
}
count -= l;
buf += l;
ret += l;
}
return ret;
}
enum blocking_t {
blocking,
notBlocking
};
void setblocking(int sock, enum blocking_t active) {
int opts;
AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,"");
if (active==blocking)
opts = opts & ~O_NONBLOCK;
else
opts = opts | O_NONBLOCK;
AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, "");
}
int server_start(openair0_device *device) {
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
t->typeStamp=MAGICeNB;
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, "");
struct sockaddr_in addr = {
sin_family: AF_INET,
sin_port: htons(PORT),
sin_addr: { s_addr: INADDR_ANY }
};
bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
AssertFatal(listen(t->listen_sock, 5) == 0, "");
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = t->listen_sock;
AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, "");
return 0;
}
int start_ue(openair0_device *device) {
rfsimulator_state_t *t = device->priv;
t->typeStamp=MAGICUE;
int sock;
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
struct sockaddr_in addr = {
sin_family: AF_INET,
sin_port: htons(PORT),
sin_addr: { s_addr: INADDR_ANY }
};
addr.sin_addr.s_addr = inet_addr(t->ip);
bool connected=false;
while(!connected) {
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, PORT);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
LOG_I(HW,"rfsimulator: connection established\n");
connected=true;
}
perror("rfsimulator");
sleep(1);
}
setblocking(sock, notBlocking);
allocCirBuf(t, sock);
t->buf[sock].alreadyWrote=true; //+=t->initialAhead; // UE is slave
return 0;
}
int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
rfsimulator_state_t *t = device->priv;
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *ptr=&t->buf[i];
if (ptr->conn_sock >= 0 ) {
setblocking(ptr->conn_sock, blocking);
transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
int n=-1;
AssertFatal( fullwrite(ptr->conn_sock,&header, sizeof(header)) == sizeof(header), "");
sample_t tmpSamples[nsamps][nbAnt];
for(int a=0; a<nbAnt; a++) {
sample_t *in=(sample_t *)samplesVoid[a];
for(int s=0; s<nsamps; s++)
tmpSamples[s][a]=in[s];
}
n = fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt));
if (n != sampleToByte(nsamps,nbAnt) ) {
LOG_E(HW,"rfsimulator: write error ret %d (wanted %ld) error %s\n", n, sampleToByte(nsamps,nbAnt), strerror(errno));
abort();
}
ptr->alreadyWrote=true; //+=nsamps;
setblocking(ptr->conn_sock, notBlocking);
}
}
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) );
return nsamps;
}
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);
if ( nfds==-1 ) {
if ( errno==EINTR || errno==EAGAIN )
return false;
else
AssertFatal(false,"error in epoll_wait\n");
}
for (int nbEv = 0; nbEv < nfds; ++nbEv) {
int fd=events[nbEv].data.fd;
if (events[nbEv].events & EPOLLIN && fd == t->listen_sock) {
int conn_sock;
AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, "");
allocCirBuf(t, conn_sock);
LOG_I(HW,"A ue connected\n");
} else {
if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) {
LOG_W(HW,"Lost socket\n");
removeCirBuf(t, fd);
if (t->typeStamp==MAGICUE)
exit(1);
continue;
}
buffer_t *b=&t->buf[fd];
if ( b->circularBuf == NULL ) {
LOG_E(HW, "received data on not connected socket %d\n", events[nbEv].data.fd);
continue;
}
int blockSz;
if ( b->headerMode)
blockSz=b->remainToTransfer;
else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
b->remainToTransfer :
b->circularBufEnd - 1 - b->transferPtr ;
int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
if ( sz < 0 ) {
if ( errno != EAGAIN ) {
LOG_E(HW,"socket failed %s\n", strerror(errno));
abort();
}
} else if ( sz == 0 )
continue;
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz;
if (b->transferPtr==b->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;
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;
}
}
}
}
return nfds>0;
}
int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
if (nbAnt != 1) { LOG_E(HW, "rfsimulator: only 1 antenna tested\n"); exit(1); }
rfsimulator_state_t *t = device->priv;
LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps);
// deliver data from received data
// check if a UE is connected
int first_sock;
for (first_sock=0; first_sock<FD_SETSIZE; first_sock++)
if (t->buf[first_sock].circularBuf != NULL )
break;
if ( first_sock == FD_SETSIZE ) {
// no connected device (we are eNB, no UE is connected)
if (!flushInput(t)) {
for (int x=0; x < nbAnt; x++)
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
t->nextTimestamp+=nsamps;
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ )
out[i]=0;
}
*ptimestamp = t->nextTimestamp-nsamps;
return nsamps;
}
} else {
bool have_to_wait;
do {
have_to_wait=false;
for ( int sock=0; sock<FD_SETSIZE; sock++)
if ( t->buf[sock].circularBuf &&
t->buf[sock].alreadyWrote && //>= t->initialAhead &&
(t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
have_to_wait=true;
break;
}
if (have_to_wait)
/*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n",
ptr->lastReceivedTS,
t->nextTimestamp+nsamps);
*/
flushInput(t);
} while (have_to_wait);
}
// Clear the output buffer
for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ )
out[i]=0;
}
// Add all input signal in the output buffer
for (int sock=0; sock<FD_SETSIZE; sock++) {
buffer_t *ptr=&t->buf[sock];
if ( ptr->circularBuf && ptr->alreadyWrote ) {
for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ )
out[i]+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1;
}
}
}
*ptimestamp = t->nextTimestamp; // return the time of the first sample
t->nextTimestamp+=nsamps;
LOG_D(HW,"Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n",
nsamps,
*ptimestamp, t->nextTimestamp,
signal_energy(samplesVoid[0], nsamps));
return nsamps;
}
int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) {
abort();
return 0;
}
int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) {
abort();
return 0;
}
int rfsimulator_get_stats(openair0_device *device) {
return 0;
}
int rfsimulator_reset_stats(openair0_device *device) {
return 0;
}
void rfsimulator_end(openair0_device *device) {}
int rfsimulator_stop(openair0_device *device) {
return 0;
}
int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
return 0;
}
int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
return 0;
}
__attribute__((__visibility__("default")))
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
set_log(HW,OAILOG_DEBUG);
set_log(PHY,OAILOG_DEBUG);
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) {
LOG_E(HW,helpTxt);
exit(1);
}
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 ?
server_start :
start_ue;
device->trx_get_stats_func = rfsimulator_get_stats;
device->trx_reset_stats_func = rfsimulator_reset_stats;
device->trx_end_func = rfsimulator_end;
device->trx_stop_func = rfsimulator_stop;
device->trx_set_freq_func = rfsimulator_set_freq;
device->trx_set_gains_func = rfsimulator_set_gains;
device->trx_write_func = rfsimulator_write;
device->trx_read_func = rfsimulator_read;
/* let's pretend to be a b2x0 */
device->type = USRP_B200_DEV;
device->openair0_cfg=&openair0_cfg[0];
device->priv = rfsimulator;
for (int i=0; i<FD_SETSIZE; i++)
rfsimulator->buf[i].conn_sock=-1;
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,"");
rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame
return 0;
}
@@ -282,7 +282,7 @@ NETWORK_CONTROLLER :
{
global_log_level ="info";
global_log_verbosity ="medium";
hw_log_level ="info";
hw_log_level ="debug";
hw_log_verbosity ="medium";
phy_log_level ="info";
phy_log_verbosity ="medium";
+92 -47
View File
@@ -630,7 +630,6 @@ static void *UE_thread_rxn_txnp4(void *arg) {
struct nr_rxtx_thread_data *rtd = arg;
UE_nr_rxtx_proc_t *proc = rtd->proc;
PHY_VARS_NR_UE *UE = rtd->UE;
int ret;
//proc->counter_decoder = 0;
proc->instance_cnt_rxtx=-1;
@@ -782,7 +781,6 @@ void *UE_thread(void *arg) {
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
// int tx_enabled = 0;
int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_subframe] __attribute__((aligned(32)));
openair0_timestamp timestamp;
void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
int start_rx_stream = 0;
@@ -834,45 +832,67 @@ void *UE_thread(void *arg) {
if (instance_cnt_synch < 0) { // we can invoke the synch
// grab 10 ms of signal and wakeup synch thread
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
if (UE->mode != loop_through_memory)
AssertFatal( UE->frame_parms.samples_per_subframe*10==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
rxp,
UE->frame_parms.samples_per_subframe*10,
UE->frame_parms.nb_antennas_rx), "error reading samples");
AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
instance_cnt_synch = ++UE->proc.instance_cnt_synch;
if (instance_cnt_synch == 0) {
AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
} else {
LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
exit_fun("nothing to add");
}
AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
} else {
#if OAISIM
(void)dummy_rx; /* avoid gcc warnings */
usleep(500);
#else
// grab 10 ms of signal into dummy buffer
if (UE->mode != loop_through_memory) {
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
rxp[i] = (void*)&dummy_rx[i][0];
for (int sf=0; sf<NR_NUMBER_OF_SUBFRAMES_PER_FRAME; sf++)
// printf("Reading dummy sf %d\n",sf);
AssertFatal(UE->frame_parms.samples_per_subframe==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
rxp,
UE->frame_parms.samples_per_subframe,
UE->frame_parms.nb_antennas_rx), "error reading samples");
}
#endif
if (UE->mode != loop_through_memory) {
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
for(int x=0; x<10; x++) {
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
rxp[i] = ((void*)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe;
AssertFatal( UE->frame_parms.samples_per_subframe ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
rxp,
UE->frame_parms.samples_per_subframe,
UE->frame_parms.nb_antennas_rx), "");
AssertFatal( UE->frame_parms.samples_per_subframe ==
UE->rfdevice.trx_write_func(&UE->rfdevice,
timestamp+(2*UE->frame_parms.samples_per_subframe) -
openair0_cfg[0].tx_sample_advance,
dummy_tx,
UE->frame_parms.samples_per_subframe,
UE->frame_parms.nb_antennas_tx,
1),"");
}
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
free(dummy_tx[i]);
}
AssertFatal( 0 == pthread_mutex_lock(&UE->proc.mutex_synch), "");
AssertFatal( 0 == ++UE->proc.instance_cnt_synch, "[SCHED][UE] UE sync thread busy!!\n" );
AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
AssertFatal( 0 == pthread_mutex_unlock(&UE->proc.mutex_synch), "");
} else {
// grab 10 ms of signal into dummy buffer to wait result of sync detection
if (UE->mode != loop_through_memory) {
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
void *dummy_rx[UE->frame_parms.nb_antennas_rx];
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
dummy_rx[i]=malloc16(UE->frame_parms.samples_per_subframe*4);
for (int sf=0; sf<NR_NUMBER_OF_SUBFRAMES_PER_FRAME; sf++) {
// printf("Reading dummy sf %d\n",sf);
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
dummy_rx,
UE->frame_parms.samples_per_subframe,
UE->frame_parms.nb_antennas_rx);
AssertFatal( UE->frame_parms.samples_per_subframe ==
UE->rfdevice.trx_write_func(&UE->rfdevice,
timestamp+(2*UE->frame_parms.samples_per_subframe) -
openair0_cfg[0].tx_sample_advance,
dummy_tx,
UE->frame_parms.samples_per_subframe,
UE->frame_parms.nb_antennas_tx,
1),"");
usleep(9000); // this sleep improves in the case of simulated RF and doesn't harm with true radio
}
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
free(dummy_tx[i]);
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
free(dummy_rx[i]);
}
}
} // UE->is_synchronized==0
@@ -882,12 +902,28 @@ void *UE_thread(void *arg) {
if (UE->mode != loop_through_memory) {
if (UE->no_timing_correction==0) {
LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
AssertFatal(UE->rx_offset ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
(void**)UE->common_vars.rxdata,
UE->rx_offset,
UE->frame_parms.nb_antennas_rx),"");
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4);
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ;
AssertFatal(unitTransfer ==
UE->rfdevice.trx_read_func(&UE->rfdevice,
&timestamp,
(void**)UE->common_vars.rxdata,
unitTransfer,
UE->frame_parms.nb_antennas_rx),"");
AssertFatal( unitTransfer ==
UE->rfdevice.trx_write_func(&UE->rfdevice,
timestamp+(2*UE->frame_parms.samples_per_subframe) -
openair0_cfg[0].tx_sample_advance,
dummy_tx,
unitTransfer,
UE->frame_parms.nb_antennas_tx,
1),"");
}
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
free(dummy_tx[i]);
}
UE->rx_offset=0;
UE->time_sync_cell=0;
@@ -962,6 +998,7 @@ void *UE_thread(void *arg) {
UE->rx_offset_diff = 1;
LOG_D(PHY,"AbsSubframe %d.%d TTI SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,subframe_nr,UE->rx_offset_diff,UE->rx_offset);
readBlockSize=UE->frame_parms.samples_per_subframe -
UE->frame_parms.ofdm_symbol_size -
UE->frame_parms.nb_prefix_samples0 -
@@ -1051,6 +1088,14 @@ void *UE_thread(void *arg) {
#ifdef SAIF_ENABLED
g_ue_rx_thread_busy++;
#endif
if ( getenv("RFSIMULATOR") != NULL ) {
do {
AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, "");
usleep(100);
AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, "");
} while ( proc->instance_cnt_rxtx >= 0);
} else
LOG_E( PHY, "[SCHED][UE %d] !! UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
if (proc->instance_cnt_rxtx > 4)
{
+3 -10
View File
@@ -984,23 +984,16 @@ int main( int argc, char **argv ) {
for (uint8_t i=0; i<RX_NB_TH_MAX; i++) {
//UE[CC_id]->pdcch_vars[i][0]->agregationLevel = agregation_Level;
//UE[CC_id]->pdcch_vars[i][0]->dciFormat = dci_Format;
}
/*compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common,
UE[CC_id]->frame_parms.frame_type,
UE[CC_id]->X_u);*/
if (UE[CC_id]->mac_enabled == 1)
{
UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234;
UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234;
}
UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1234;
else
{
UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235;
UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235;
}
UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1235;
}
UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];