Merge remote-tracking branch 'origin/develop' into feature-131-new-license

Conflicts:
	openair1/PHY/INIT/lte_init.c
	openair1/PHY/LTE_TRANSPORT/dci_tools.c
	openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
	openair1/SCHED/phy_procedures_lte_eNb.c
	openair1/SCHED/phy_procedures_lte_ue.c
	openair1/SIMULATION/LTE_PHY/dlsim.c
	openair1/SIMULATION/RF/adc.c
	openair2/LAYER2/MAC/lte_transport_init.c
	targets/RT/USER/lte-softmodem.c
	targets/RT/USER/sched_dlsch.c
	targets/RT/USER/sched_rx_pdsch.c
	targets/RT/USER/sched_ulsch.c
	targets/SIMU/USER/oaisim.c
This commit is contained in:
Cedric Roux
2016-09-27 15:05:00 +02:00
200 changed files with 22970 additions and 19972 deletions
@@ -873,8 +873,8 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
memset(brf, 0, sizeof(brf_state_t));
/* device specific */
openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered
openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
//openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered
//openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
openair0_cfg->iq_txshift = 0;// shift
openair0_cfg->iq_rxrescale = 15;//rescale iqs
@@ -883,22 +883,18 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
case 30720000:
openair0_cfg->samples_per_packet = 2048;
openair0_cfg->tx_sample_advance = 0;
openair0_cfg->tx_scheduling_advance = 8*openair0_cfg->samples_per_packet;
break;
case 15360000:
openair0_cfg->samples_per_packet = 2048;
openair0_cfg->tx_sample_advance = 0;
openair0_cfg->tx_scheduling_advance = 4*openair0_cfg->samples_per_packet;
break;
case 7680000:
openair0_cfg->samples_per_packet = 1024;
openair0_cfg->tx_sample_advance = 0;
openair0_cfg->tx_scheduling_advance = 4*openair0_cfg->samples_per_packet;
break;
case 1920000:
openair0_cfg->samples_per_packet = 256;
openair0_cfg->tx_sample_advance = 50;
openair0_cfg->tx_scheduling_advance = 8*openair0_cfg->samples_per_packet;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg->sample_rate);
+27 -14
View File
@@ -23,6 +23,9 @@
#define BBU_LOCAL_RADIO_HEAD 0
#define BBU_REMOTE_RADIO_HEAD 1
#define MAX_CARDS 8
typedef int64_t openair0_timestamp;
typedef volatile int64_t openair0_vtimestamp;
@@ -31,9 +34,9 @@ typedef volatile int64_t openair0_vtimestamp;
typedef struct openair0_device_t openair0_device;
#ifndef EXMIMO
#define MAX_CARDS 1
#endif
//#define USRP_GAIN_OFFSET (56.0) // 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output
@@ -117,27 +120,27 @@ typedef struct {
unsigned int samples_per_frame;
//! the sample rate for both transmit and receive.
double sample_rate;
//! number of samples per RX/TX packet (USRP + Ethernet)
unsigned int samples_per_packet;
//! delay in sending samples (write) due to hardware access, softmodem processing and fronthaul delay if exist
int tx_scheduling_advance;
//! flag to indicate that the device is doing mmapped DMA transfers
int mmapped_dma;
//! offset in samples between TX and RX paths
int tx_sample_advance;
//! configurable tx thread lauch delay
int txlaunch_wait; /* 1 or 0 */
//! configurable tx thread lauch delay
int txlaunch_wait_slotcount;
//! samples per packet on the fronthaul interface
int samples_per_packet;
//! number of RX channels (=RX antennas)
int rx_num_channels;
//! number of TX channels (=TX antennas)
int tx_num_channels;
//! \brief RX base addresses for mmapped_dma
int32_t* rxbase[4];
//! \brief TX base addresses for mmapped_dma
int32_t* txbase[4];
//! \brief Center frequency in Hz for RX.
//! index: [0..rx_num_channels[
double rx_freq[4];
//! \brief Center frequency in Hz for TX.
//! index: [0..rx_num_channels[ !!! see lte-ue.c:427 FIXME iterates over rx_num_channels
double tx_freq[4];
//! \brief memory
//! \brief Pointer to Calibration table for RX gains
rx_gain_calib_table_t *rx_gain_calib_table;
@@ -205,10 +208,21 @@ typedef struct {
} eth_params_t;
typedef struct {
//! Tx buffer for if device
void *tx;
//! Rx buffer for if device
void *rx;
} if_buffer_t;
/*!\brief structure holds the parameters to configure USRP devices */
struct openair0_device_t {
/*!brief Module ID of this device */
int Mod_id;
/*!brief Component Carrier ID of this device */
int CC_id;
/*!brief Type of this device */
dev_type_t type;
@@ -287,9 +301,8 @@ struct openair0_device_t {
void (*trx_end_func)(openair0_device *device);
/*! \brief Stop operation of the transceiver
* \param card RF Card to use
*/
int (*trx_stop_func)(int card);
int (*trx_stop_func)(openair0_device *device);
/* Functions API related to UE*/
+176 -20
View File
@@ -30,7 +30,6 @@ struct sockaddr_ll dest_addr[MAX_INST];
struct sockaddr_ll local_addr[MAX_INST];
int addr_len[MAX_INST];
struct ifreq if_index[MAX_INST];
struct ether_header eh;
int eth_socket_init_raw(openair0_device *device) {
@@ -38,23 +37,18 @@ int eth_socket_init_raw(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
const char *local_mac, *remote_mac;
int local_port=0, remote_port=0;
int sock_dom=0;
int sock_type=0;
int sock_proto=0;
if (device->host_type == RRH_HOST ) { /* RRH doesn't know remote MAC(will be retrieved from first packet send from BBU) and remote port(don't care) */
local_mac = device->openair0_cfg->my_addr;
local_port = device->openair0_cfg->my_port;
remote_mac = malloc(ETH_ALEN);
memset(remote_mac,0,ETH_ALEN);
remote_port = 0;
memset((void*)remote_mac,0,ETH_ALEN);
printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac);
} else {
local_mac = device->openair0_cfg->my_addr;
local_port = device->openair0_cfg->my_port;
remote_mac = device->openair0_cfg->remote_addr;
remote_port = device->openair0_cfg->remote_port;
printf("[%s] local MAC addr %s remote MAC addr %s\n","BBU", local_mac,remote_mac);
}
@@ -92,11 +86,14 @@ int eth_socket_init_raw(openair0_device *device) {
}
/* Construct the Ethernet header */
ether_aton_r(local_mac, (struct ether_addr *)(&(eh.ether_shost)));
ether_aton_r(remote_mac, (struct ether_addr *)(&(eh.ether_dhost)));
eh.ether_type = htons((short)device->openair0_cfg->my_port);
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]);
ether_aton_r(local_mac, (struct ether_addr *)(&(eth->eh.ether_shost)));
ether_aton_r(remote_mac, (struct ether_addr *)(&(eth->eh.ether_dhost)));
if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
eth->eh.ether_type = htons(0xbffe);
} else {
eth->eh.ether_type = htons((short)device->openair0_cfg->my_port);
}
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5]);
return 0;
}
@@ -112,7 +109,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
//sendto_flag|=flags;
eth->tx_nsamps=nsamps;
for (i=0;i<cc;i++) {
/* buff[i] points to the position in tx buffer where the payload to be sent is
buff2 points to the position in tx buffer where the packet header will be placed */
@@ -124,7 +121,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t));
bytes_sent = 0;
memcpy(buff2,(void*)&eh,MAC_HEADER_SIZE_BYTES);
memcpy(buff2,(void*)&eth->eh,MAC_HEADER_SIZE_BYTES);
*(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t))=1+(i<<1);
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = timestamp;
@@ -152,7 +149,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
printf("------- TX ------: nu=%x an_id=%d ts%d bytes_sent=%d\n",
*(uint8_t *)(buff2+ETH_ALEN),
*(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)),
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)),
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)),
bytes_sent);
dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps), TX_FLAG);
#endif
@@ -170,6 +167,51 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
}
int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
int nblocks = nsamps;
int bytes_sent = 0;
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
ssize_t packet_size;
if (flags == IF4p5_PDLFFT) {
packet_size = RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks);
} else if (flags == IF4p5_PULFFT) {
packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks);
} else if (flags == IF5_MOBIPASS) {
packet_size = RAW_IF5_MOBIPASS_SIZE_BYTES;
} else {
packet_size = RAW_IF4p5_PRACH_SIZE_BYTES;
}
eth->tx_nsamps = nblocks;
memcpy(buff[0], (void*)&eth->eh, MAC_HEADER_SIZE_BYTES);
bytes_sent = send(eth->sockfd[Mod_id],
buff[0],
packet_size,
0);
if (bytes_sent == -1) {
eth->num_tx_errors++;
perror("ETHERNET WRITE: ");
exit(-1);
} else {
eth->tx_actual_nsamps = bytes_sent>>1;
eth->tx_count++;
}
return (bytes_sent-MAC_HEADER_SIZE_BYTES);
}
int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
int bytes_received=0;
@@ -200,7 +242,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("ETHERNET READ: ");
perror("ETHERNET IF5 READ: ");
exit(-1);
} else {
/* store the timestamp value from packet's header */
@@ -228,7 +270,60 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi
return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2;
}
int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
// Read nblocks info from packet itself
int nblocks = nsamps;
int bytes_received=0;
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t;
IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES);
bytes_received = recv(eth->sockfd[Mod_id],
buff[0],
packet_size,
MSG_PEEK);
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("ETHERNET IF4p5 READ (header): ");
exit(-1);
}
*timestamp = test_header->sub_type;
if (test_header->sub_type == IF4p5_PDLFFT) {
packet_size = RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks);
} else if (test_header->sub_type == IF4p5_PULFFT) {
packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks);
} else {
packet_size = RAW_IF4p5_PRACH_SIZE_BYTES;
}
while(bytes_received < packet_size) {
bytes_received = recv(eth->sockfd[Mod_id],
buff[0],
packet_size,
0);
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("ETHERNET IF4p5 READ (payload): ");
exit(-1);
} else {
eth->rx_actual_nsamps = bytes_received>>1;
eth->rx_count++;
}
}
eth->rx_nsamps = nsamps;
return(bytes_received);
}
int eth_set_dev_conf_raw(openair0_device *device) {
@@ -246,7 +341,39 @@ int eth_set_dev_conf_raw(openair0_device *device) {
msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t);
memcpy(msg,(void*)&eh,MAC_HEADER_SIZE_BYTES);
memcpy(msg,(void*)&eth->eh,MAC_HEADER_SIZE_BYTES);
memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)device->openair0_cfg,sizeof(openair0_config_t));
if (send(eth->sockfd[Mod_id],
msg,
msg_len,
0)==-1) {
perror("ETHERNET: ");
exit(0);
}
return 0;
}
int eth_set_dev_conf_raw_IF4p5(openair0_device *device) {
// use for cc_id info
int Mod_id = device->Mod_id;
eth_state_t *eth = (eth_state_t*)device->priv;
void *msg;
ssize_t msg_len;
/* a BBU client sends to RRH a set of configuration parameters (openair0_config_t)
so that RF front end is configured appropriately and
frame/packet size etc. can be set */
msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t));
msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t);
memcpy(msg,(void*)&eth->eh,MAC_HEADER_SIZE_BYTES);
memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)device->openair0_cfg,sizeof(openair0_config_t));
if (send(eth->sockfd[Mod_id],
@@ -265,7 +392,6 @@ int eth_get_dev_conf_raw(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
char str[INET_ADDRSTRLEN];
void *msg;
ssize_t msg_len;
@@ -282,10 +408,40 @@ int eth_get_dev_conf_raw(openair0_device *device) {
}
/* RRH stores the remote MAC address */
memcpy(eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN);
memcpy(eth->eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN);
//memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t));
device->openair0_cfg=(openair0_config_t *)(msg + MAC_HEADER_SIZE_BYTES);
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5],eh.ether_dhost[0],eh.ether_dhost[1],eh.ether_dhost[2],eh.ether_dhost[3],eh.ether_dhost[4],eh.ether_dhost[5]);
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5],eth->eh.ether_dhost[0],eth->eh.ether_dhost[1],eth->eh.ether_dhost[2],eth->eh.ether_dhost[3],eth->eh.ether_dhost[4],eth->eh.ether_dhost[5]);
return 0;
}
int eth_get_dev_conf_raw_IF4p5(openair0_device *device) {
// use for cc_id info
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
void *msg;
ssize_t msg_len;
msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t));
msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t);
/* RRH receives from BBU openair0_config_t */
if (recv(eth->sockfd[Mod_id],
msg,
msg_len,
0)==-1) {
perror("ETHERNET: ");
exit(0);
}
/* RRH stores the remote MAC address */
memcpy(eth->eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN);
//memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t));
//device->openair0_cfg=(openair0_config_t *)(msg + MAC_HEADER_SIZE_BYTES);
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eth->eh.ether_shost[0],eth->eh.ether_shost[1],eth->eh.ether_shost[2],eth->eh.ether_shost[3],eth->eh.ether_shost[4],eth->eh.ether_shost[5],eth->eh.ether_dhost[0],eth->eh.ether_dhost[1],eth->eh.ether_dhost[2],eth->eh.ether_dhost[3],eth->eh.ether_dhost[4],eth->eh.ether_dhost[5]);
return 0;
}
+102 -3
View File
@@ -35,7 +35,7 @@ uint16_t pck_seq_num = 1;
uint16_t pck_seq_num_cur=0;
uint16_t pck_seq_num_prev=0;
int eth_socket_init_udp(openair0_device *device) {
int eth_socket_init_udp(openair0_device *device) {
int i = 0;
eth_state_t *eth = (eth_state_t*)device->priv;
@@ -110,6 +110,105 @@ uint16_t pck_seq_num_prev=0;
return 0;
}
int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
// Read nblocks info from packet itself
int nblocks = nsamps;
int bytes_received=0;
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
ssize_t packet_size = sizeof_IF4p5_header_t;
IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0]);
bytes_received = recvfrom(eth->sockfd[Mod_id],
buff[0],
packet_size,
0,
(struct sockaddr *)&dest_addr[Mod_id],
(socklen_t *)&addr_len[Mod_id]);
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("ETHERNET IF4p5 READ (header): ");
exit(-1);
}
*timestamp = test_header->sub_type;
if (test_header->sub_type == IF4p5_PDLFFT) {
packet_size = UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks);
} else if (test_header->sub_type == IF4p5_PULFFT) {
packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks);
} else {
packet_size = UDP_IF4p5_PRACH_SIZE_BYTES;
}
while(bytes_received < packet_size) {
bytes_received = recvfrom(eth->sockfd[Mod_id],
buff[0],
packet_size,
0,
(struct sockaddr *)&dest_addr[Mod_id],
(socklen_t *)&addr_len[Mod_id]);
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("ETHERNET IF4p5 READ (payload): ");
exit(-1);
} else {
eth->rx_actual_nsamps = bytes_received>>1;
eth->rx_count++;
}
}
eth->rx_nsamps = nsamps;
return(bytes_received);
}
int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
int nblocks = nsamps;
int bytes_sent = 0;
eth_state_t *eth = (eth_state_t*)device->priv;
int Mod_id = device->Mod_id;
ssize_t packet_size;
if (flags == IF4p5_PDLFFT) {
packet_size = UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks);
} else if (flags == IF4p5_PULFFT) {
packet_size = UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks);
} else if (flags == IF4p5_PRACH) {
packet_size = UDP_IF4p5_PRACH_SIZE_BYTES;
} else {
printf("trx_eth_write_udp_IF4p5: unknown flags %d\n",flags);
return(-1);
}
eth->tx_nsamps = nblocks;
bytes_sent = sendto(eth->sockfd[Mod_id],
buff[0],
packet_size,
0,
(struct sockaddr*)&dest_addr[Mod_id],
addr_len[Mod_id]);
if (bytes_sent == -1) {
eth->num_tx_errors++;
perror("ETHERNET WRITE: ");
exit(-1);
} else {
eth->tx_actual_nsamps = bytes_sent>>1;
eth->tx_count++;
}
return (bytes_sent);
}
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
int bytes_sent=0;
@@ -188,7 +287,7 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi
int bytes_received=0;
eth_state_t *eth = (eth_state_t*)device->priv;
openair0_timestamp prev_timestamp = -1;
// openair0_timestamp prev_timestamp = -1;
int Mod_id = device->Mod_id;
int rcvfrom_flag =0;
int block_cnt=0;
@@ -270,7 +369,7 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi
pck_seq_num_cur = *(uint16_t *)buff2;
//printf("cur=%d prev=%d buff=%d\n",pck_seq_num_cur,pck_seq_num_prev,*(uint16_t *)(buff2));
if ( ( pck_seq_num_cur != (pck_seq_num_prev + 1) ) && !((pck_seq_num_prev==75) && (pck_seq_num_cur==1 ))){
printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev, *timestamp);
printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev,(int)*timestamp);
}
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,pck_seq_num_cur);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,pck_seq_num_prev);
@@ -24,7 +24,6 @@
#include "common_lib.h"
#include "ethernet_lib.h"
int num_devices_eth = 0;
struct sockaddr_in dest_addr[MAX_INST];
int dest_addr_len[MAX_INST];
@@ -35,7 +34,8 @@ int trx_eth_start(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
/* initialize socket */
if ((eth->flags & ETH_RAW_MODE) != 0 ) {
if (eth->flags == ETH_RAW_MODE) {
printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
/* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
if (device->host_type == BBU_HOST) {
@@ -45,6 +45,32 @@ int trx_eth_start(openair0_device *device) {
}
/* adjust MTU wrt number of samples per packet */
if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
printf("Setting ETHERNET to ETH_RAW_IF4p5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
/* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
if (device->host_type == BBU_HOST) {
if(eth_set_dev_conf_raw_IF4p5(device)!=0) return -1;
} else {
if(eth_get_dev_conf_raw_IF4p5(device)!=0) return -1;
}
/* adjust MTU wrt number of samples per packet */
if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
} else if (eth->flags == ETH_UDP_IF4p5_MODE) {
printf("Setting ETHERNET to UDP_IF4p5_MODE\n");
if (eth_socket_init_udp(device)!=0) return -1;
if (device->host_type == BBU_HOST) {
if(eth_set_dev_conf_udp(device)!=0) return -1;
} else {
if(eth_get_dev_conf_udp(device)!=0) return -1;
}
} else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
printf("Setting ETHERNET to RAW_IF5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
} else {
if (eth_socket_init_udp(device)!=0) return -1;
/* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
@@ -53,8 +79,6 @@ int trx_eth_start(openair0_device *device) {
} else {
if(eth_get_dev_conf_udp(device)!=0) return -1;
}
/* adjust MTU wrt number of samples per packet */
//if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1;
}
/* apply additional configuration */
if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1;
@@ -115,7 +139,7 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
int trx_eth_stop(int card) {
int trx_eth_stop(openair0_device *device) {
return(0);
}
@@ -143,11 +167,11 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) {
struct timeval timeout;
struct ifreq ifr;
char system_cmd[256];
char* if_name=DEFAULT_IF;
struct in_addr ia;
struct if_nameindex *ids;
// char* if_name=DEFAULT_IF;
// struct in_addr ia;
// struct if_nameindex *ids;
int ret=0;
int i=0;
// int i=0;
/****************** socket level options ************************/
switch(option) {
@@ -174,15 +198,15 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) {
break;
case RCV_TIMEOUT:
timeout.tv_sec = value/1000000000;
timeout.tv_usec = value%1000000000;//less than rt_period?
timeout.tv_sec = value/1000000;
timeout.tv_usec = value%1000000;//less than rt_period?
if (setsockopt(eth->sockfd[Mod_id],
SOL_SOCKET,
SO_RCVTIMEO,
(char *)&timeout,sizeof(timeout))) {
perror("[ETHERNET] setsockopt()");
} else {
printf( "receive timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec);
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
}
break;
@@ -195,7 +219,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) {
(char *)&timeout,sizeof(timeout))) {
perror("[ETHERNET] setsockopt()");
} else {
printf( "send timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec);
printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec);
}
break;
@@ -255,7 +279,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) {
break;
case RING_PAR:
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx %d tx %d",eth->if_name[Mod_id],value);
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s val %d",eth->if_name[Mod_id],value);
if (ret > 0) {
ret=system(system_cmd);
if (ret == -1) {
@@ -285,8 +309,17 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth
if (eth_params->transp_preference == 1) {
eth->flags = ETH_RAW_MODE;
} else {
} else if (eth_params->transp_preference == 0) {
eth->flags = ETH_UDP_MODE;
} else if (eth_params->transp_preference == 3) {
eth->flags = ETH_RAW_IF4p5_MODE;
} else if (eth_params->transp_preference == 2) {
eth->flags = ETH_UDP_IF4p5_MODE;
} else if (eth_params->transp_preference == 4) {
eth->flags = ETH_RAW_IF5_MOBIPASS;
} else {
printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference);
eth->flags = ETH_RAW_MODE;
}
printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH"));
@@ -302,20 +335,30 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth
device->trx_set_freq_func = trx_eth_set_freq;
device->trx_set_gains_func = trx_eth_set_gains;
if ((eth->flags & ETH_RAW_MODE) != 0 ) {
if (eth->flags == ETH_RAW_MODE) {
device->trx_write_func = trx_eth_write_raw;
device->trx_read_func = trx_eth_read_raw;
} else {
} else if (eth->flags == ETH_UDP_MODE) {
device->trx_write_func = trx_eth_write_udp;
device->trx_read_func = trx_eth_read_udp;
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
device->trx_write_func = trx_eth_write_raw_IF4p5;
device->trx_read_func = trx_eth_read_raw_IF4p5;
} else if (eth->flags == ETH_UDP_IF4p5_MODE) {
device->trx_write_func = trx_eth_write_udp_IF4p5;
device->trx_read_func = trx_eth_read_udp_IF4p5;
} else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
device->trx_write_func = trx_eth_write_raw_IF4p5;
device->trx_read_func = trx_eth_read_raw_IF4p5;
} else {
//device->trx_write_func = trx_eth_write_udp_IF4p5;
//device->trx_read_func = trx_eth_read_udp_IF4p5;
}
eth->if_name[device->Mod_id] = eth_params->local_if_name;
device->priv = eth;
/* device specific */
openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered
openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift
openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance;
@@ -325,26 +368,25 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth
/*Note scheduling advance values valid only for case 7680000 */
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
openair0_cfg[0].samples_per_packet = 4096;
openair0_cfg[0].samples_per_packet = 3840;
break;
case 23040000:
openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].samples_per_packet = 2880;
break;
case 15360000:
openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].samples_per_packet = 1920;
break;
case 7680000:
openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].samples_per_packet = 960;
break;
case 1920000:
openair0_cfg[0].samples_per_packet = 256;
openair0_cfg[0].samples_per_packet = 240;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
openair0_cfg[0].tx_scheduling_advance = eth_params->tx_scheduling_advance*openair0_cfg[0].samples_per_packet;
}
device->openair0_cfg=&openair0_cfg[0];
@@ -387,11 +429,9 @@ void dump_dev(openair0_device *device) {
printf(" Log level is %i :\n" ,device->openair0_cfg->log_level);
printf(" RB number: %i, sample rate: %lf \n" ,
device->openair0_cfg->num_rb_dl, device->openair0_cfg->sample_rate);
printf(" Scheduling_advance: %i, Sample_advance: %u \n" ,
device->openair0_cfg->tx_scheduling_advance, device->openair0_cfg->tx_sample_advance);
printf(" BBU configured for %i tx/%i rx channels)\n",
device->openair0_cfg->tx_num_channels,device->openair0_cfg->rx_num_channels);
printf(" Running flags: %s %s %s\n",
printf(" Running flags: %s %s (\n",
((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""),
((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":""));
printf(" Number of iqs dumped when displaying packets: %i\n\n",eth->iqdumpcnt);
@@ -401,14 +441,14 @@ void dump_dev(openair0_device *device) {
void inline dump_txcounters(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg->Mod_id);
printf(" Sent packets: %llu send errors: %i\n", eth->tx_count, eth->num_tx_errors);
printf(" Sent packets: %llu send errors: %i\n", (long long unsigned int)eth->tx_count, eth->num_tx_errors);
}
void inline dump_rxcounters(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv;
printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg->Mod_id);
printf(" Received packets: %llu missed packets errors: %i\n", eth->rx_count, eth->num_underflows);
printf(" Received packets: %llu missed packets errors: %i\n", (long long unsigned int)eth->rx_count, eth->num_underflows);
}
void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag, int nsamps) {
@@ -24,19 +24,11 @@
#define MAX_INST 4
#define DEFAULT_IF "lo"
#define ETH_RAW_MODE 1
#define ETH_UDP_MODE 0
#define TX_FLAG 1
#define RX_FLAG 0
#define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp)
#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header))
#include "if_defs.h"
#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp))
#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2)
#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
/*!\brief opaque ethernet data structure */
typedef struct {
@@ -93,6 +85,8 @@ typedef struct {
/*!\brief number of packets received */
uint64_t rx_count;
struct ether_header eh;
} eth_state_t;
@@ -154,9 +148,10 @@ typedef struct {
void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag);
unsigned short calc_csum (unsigned short *buf, int nwords);
void dump_dev(openair0_device *device);
void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps);
/*void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps);
void inline dump_rxcounters(openair0_device *device);
void inline dump_txcounters(openair0_device *device);
*/
void dump_iqs(char * buff, int iq_cnt);
@@ -184,6 +179,8 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value);
int eth_socket_init_udp(openair0_device *device);
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
//int trx_eth_write_udp_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
//int trx_eth_read_udp_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
int eth_get_dev_conf_udp(openair0_device *device);
/*! \fn static int eth_set_dev_conf_udp(openair0_device *device)
@@ -198,8 +195,13 @@ int eth_set_dev_conf_udp(openair0_device *device);
int eth_socket_init_raw(openair0_device *device);
int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
int eth_get_dev_conf_raw(openair0_device *device);
int eth_set_dev_conf_raw(openair0_device *device);
int eth_get_dev_conf_raw_IF4p5(openair0_device *device);
int eth_set_dev_conf_raw_IF4p5(openair0_device *device);
#endif
@@ -0,0 +1,45 @@
/*! \file targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h
* \brief
* \author S. Sandeep Kumar, Raymond Knopp
* \date 2016
* \version 0.1
* \company Eurecom
* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr
* \note
* \warning
*/
#include <netinet/ether.h>
#include <stdint.h>
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
// ETH transport preference modes
#define ETH_UDP_MODE 0
#define ETH_RAW_MODE 1
#define ETH_UDP_IF4p5_MODE 2
#define ETH_RAW_IF4p5_MODE 3
#define ETH_RAW_IF5_MOBIPASS 4
// Time domain RRH packet sizes
#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header))
#define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp)
#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2)
#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
// Packet sizes for IF4p5 interface format
#define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(uint16_t)*scaled_nblocks)
#define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839*2) // FIX hard coded prach size (uncompressed)
#define RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))
#define RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))
#define RAW_IF4p5_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + PRACH_BLOCK_SIZE_BYTES)
#define UDP_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))
#define UDP_IF4p5_PULFFT_SIZE_BYTES(nblocks) (sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))
#define UDP_IF4p5_PRACH_SIZE_BYTES (sizeof_IF4p5_header_t + PRACH_BLOCK_SIZE_BYTES)
// Mobipass packet sizes
#define RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES 1280
#define RAW_IF5_MOBIPASS_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES)
+33 -8
View File
@@ -150,6 +150,8 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd
int tmp;
unsigned int user_args[4];
static unsigned int update_firmware_command;
static unsigned int update_firmware_address;
static unsigned int update_firmware_length;
@@ -299,15 +301,38 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd
acknowledge with no limit */
#define MAX_IOCTL_ACK_CNT 500
update_firmware_command = *((unsigned int*)arg);
/* 'arg' is an unsigned long and is supposed to be big enough
* to hold an address - this hypothesis is okay for i386 and x86_64
* maybe not somewhere else
* this will probably fail with older kernels
* (works with 3.17 on x86_64)
*/
tmp = copy_from_user(&user_args, (void*)arg, 4*sizeof(unsigned int));
if (tmp) {
printk("[openair][IOCTL] UPDATE_FIRMWARE: error copying parameters to kernel-space (%d bytes uncopied).\n", tmp);
return -1;
}
update_firmware_command = user_args[0];
switch (update_firmware_command) {
case UPDATE_FIRMWARE_TRANSFER_BLOCK:
update_firmware_address = ((unsigned int*)arg)[1];
update_firmware_length = ((unsigned int*)arg)[2];
update_firmware_address = user_args[1];
update_firmware_length = user_args[2];
/* This is totally wrong on x86_64: a pointer is 64 bits and
* unsigned int is 32 bits. The userspace program has to ensure
* that its buffer address fits into 32 bits.
* If it proves a too strong requirement, we may change things
* in the future.
* The compiler emits a warning here. Do not remove this warning!
* This is to clearly remember this problem.
* If you require the compilation to work with zero warning,
* consider this one as an exception and find a proper workaround.
*/
update_firmware_ubuffer = user_args[3];
update_firmware_ubuffer = (unsigned int*)((unsigned int*)arg)[3];
update_firmware_kbuffer = (unsigned int*)kmalloc(update_firmware_length * 4 /* 4 because kmalloc expects bytes */,
GFP_KERNEL);
@@ -361,8 +386,8 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd
case UPDATE_FIRMWARE_CLEAR_BSS:
update_firmware_bss_address = ((unsigned int*)arg)[1];
update_firmware_bss_size = ((unsigned int*)arg)[2];
update_firmware_bss_address = user_args[1];
update_firmware_bss_size = user_args[2];
sparc_tmp_0 = update_firmware_bss_address;
sparc_tmp_1 = update_firmware_bss_size;
@@ -382,8 +407,8 @@ int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd
case UPDATE_FIRMWARE_START_EXECUTION:
update_firmware_start_address = ((unsigned int*)arg)[1];
update_firmware_stack_pointer = ((unsigned int*)arg)[2];
update_firmware_start_address = user_args[1];
update_firmware_stack_pointer = user_args[2];
sparc_tmp_0 = update_firmware_start_address;
sparc_tmp_1 = update_firmware_stack_pointer;
+551 -17
View File
@@ -7,18 +7,39 @@
* 28.01.2013: Initial version
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <syscall.h>
#include "openair0_lib.h"
#include "openair_device.h"
#include "common_lib.h"
#include <pthread.h>
#define max(a,b) ((a)>(b) ? (a) : (b))
//#define DEBUG_EXMIMO
exmimo_pci_interface_bot_virtual_t openair0_exmimo_pci[MAX_CARDS]; // contains userspace pointers for each card
char *bigshm_top[MAX_CARDS] = INIT_ZEROS;
@@ -37,6 +58,15 @@ static uint32_t rf_vcocal[4] = {910,910,910,910};
static uint32_t rf_vcocal_850[4] = {2015, 2015, 2015, 2015};
static uint32_t rf_rxdc[4] = {32896,32896,32896,32896};
extern volatile int oai_exit;
void kill_watchdog(openair0_device *);
void create_watchdog(openair0_device *);
void rt_sleep(struct timespec *,long );
unsigned int log2_int( unsigned int x )
{
unsigned int ans = 0 ;
@@ -218,16 +248,449 @@ int openair0_stop_without_reset(int card)
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
#define RF_MODE_BASE (LNA1ON + RFBBNORM)
void rt_sleep(struct timespec *ts,long tv_nsec) {
clock_gettime(CLOCK_MONOTONIC, ts);
ts->tv_nsec += tv_nsec;
if (ts->tv_nsec>=1000000000L) {
ts->tv_nsec -= 1000000000L;
ts->tv_sec++;
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts, NULL);
}
static void *watchdog_thread(void *arg) {
int policy, s, j;
struct sched_param sparam;
char cpu_affinity[1024];
cpu_set_t cpuset;
exmimo_state_t *exm=((openair0_device *)arg)->priv;
openair0_config_t *cfg=&((openair0_device *)arg)->openair0_cfg[0];
volatile unsigned int *daq_mbox = openair0_daq_cnt();
unsigned int mbox,diff;
int first_acquisition;
struct timespec sleep_time,wait;
wait.tv_sec=0;
wait.tv_nsec=50000000L;
/* Set affinity mask to include CPUs 1 to MAX_CPUS */
/* CPU 0 is reserved for UHD threads */
/* CPU 1 is reserved for all TX threads */
/* Enable CPU Affinity only if number of CPUs >2 */
CPU_ZERO(&cpuset);
#ifdef CPU_AFFINITY
if (get_nprocs() > 2)
{
for (j = 1; j < get_nprocs(); j++)
CPU_SET(j, &cpuset);
s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0)
{
perror( "pthread_setaffinity_np");
printf("Error setting processor affinity");
}
}
#endif //CPU_AFFINITY
/* Check the actual affinity mask assigned to the thread */
s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0)
{
perror( "pthread_getaffinity_np");
printf("Error getting processor affinity ");
}
memset(cpu_affinity,0,sizeof(cpu_affinity));
for (j = 0; j < CPU_SETSIZE; j++)
if (CPU_ISSET(j, &cpuset))
{
char temp[1024];
sprintf (temp, " CPU_%d", j);
strcat(cpu_affinity, temp);
}
memset(&sparam, 0 , sizeof (sparam));
sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
policy = SCHED_FIFO ;
s = pthread_setschedparam(pthread_self(), policy, &sparam);
if (s != 0)
{
perror("pthread_setschedparam : ");
printf("Error setting thread priority");
}
s = pthread_getschedparam(pthread_self(), &policy, &sparam);
if (s != 0)
{
perror("pthread_getschedparam : ");
printf("Error getting thread priority");
}
printf("EXMIMO2 Watchdog TX thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",
sched_getcpu(),
syscall(__NR_gettid),
(policy == SCHED_FIFO) ? "SCHED_FIFO" :
(policy == SCHED_RR) ? "SCHED_RR" :
(policy == SCHED_OTHER) ? "SCHED_OTHER" :
"???",
sparam.sched_priority,
cpu_affinity );
mlockall(MCL_CURRENT | MCL_FUTURE);
exm->watchdog_exit = 0;
exm->ts = 0;
exm->last_mbox = 0;
if (cfg->sample_rate==30.72e6) {
exm->samples_per_tick = 15360;
exm->samples_per_frame = 307200;
}
else if (cfg->sample_rate==23.04e6) {
exm->samples_per_tick = 11520;
exm->samples_per_frame = 230400;
}
else if (cfg->sample_rate==15.36e6) {
exm->samples_per_tick = 7680;
exm->samples_per_frame = 153600;
}
else if (cfg->sample_rate==7.68e6) {
exm->samples_per_tick = 3840;
exm->samples_per_frame = 76800;
}
else if (cfg->sample_rate==3.84e6) {
exm->samples_per_tick = 1920;
exm->samples_per_frame = 38400;
}
else if (cfg->sample_rate==1.92e6) {
exm->samples_per_tick = 960;
exm->samples_per_frame = 19200;
}
else {
printf("Unknown sampling rate %f, exiting \n",cfg->sample_rate);
exm->watchdog_exit=1;
}
first_acquisition=1;
printf("Locking watchdog for first acquisition\n");
pthread_mutex_timedlock(&exm->watchdog_mutex,&wait);
// main loop to keep up with DMA transfers from exmimo2
int cnt_diff0=0;
while ((!oai_exit) && (!exm->watchdog_exit)) {
if (exm->daq_state == running) {
// grab time from MBOX
mbox = daq_mbox[0];
if (mbox<exm->last_mbox) { // wrap-around
diff = 150 + mbox - exm->last_mbox;
}
else {
diff = mbox - exm->last_mbox;
}
exm->last_mbox = mbox;
if (first_acquisition==0)
pthread_mutex_timedlock(&exm->watchdog_mutex,&wait);
exm->ts += (diff*exm->samples_per_frame/150) ;
if ((exm->daq_state == running) &&
(diff > 16)&&
(first_acquisition==0)) {// we're too late so exit
exm->watchdog_exit = 1;
printf("exiting, too late to keep up\n");
}
first_acquisition=0;
if ((exm->daq_state == running) &&
(diff == 0)) {
cnt_diff0++;
if (cnt_diff0 == 10) {
exm->watchdog_exit = 1;
printf("exiting, HW stopped\n");
}
}
else
cnt_diff0=0;
if ((exm->daq_state == running) &&
(exm->wait_first_read==0) &&
(exm->ts - exm->last_ts_rx > exm->samples_per_frame)) {
exm->watchdog_exit = 1;
printf("RX Overflow, exiting (TS %llu, TS last read %llu)\n",
exm->ts,exm->last_ts_rx);
}
// printf("ts %lu, last_ts_rx %lu, mbox %d, diff %d\n",exm->ts, exm->last_ts_rx,mbox,diff);
pthread_mutex_unlock(&exm->watchdog_mutex);
}
else {
first_acquisition=1;
}
rt_sleep(&sleep_time,250000L);
}
oai_exit=1;
printf("Exiting watchdog\n");
return NULL;
}
void create_watchdog(openair0_device *dev) {
exmimo_state_t *priv = dev->priv;
priv->watchdog_exit=0;
#ifndef DEADLINE_SCHEDULER
priv->watchdog_sched_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_setschedparam(&priv->watchdog_attr,&priv->watchdog_sched_param);
pthread_attr_setschedpolicy(&priv->watchdog_attr,SCHED_FIFO);
pthread_create(&priv->watchdog,&priv->watchdog_attr,watchdog_thread,dev);
#else
pthread_create(&priv->watchdog,NULL,watchdog_thread,dev);
#endif
pthread_mutex_init(&priv->watchdog_mutex,NULL);
}
int trx_exmimo_start(openair0_device *device) {
exmimo_state_t *exm=device->priv;
printf("Starting ...\n");
openair0_config(device->openair0_cfg,0);
openair0_start_rt_acquisition(0);
printf("Setting state to running\n");
exm->daq_state = running;
exm->wait_first_read = 1;
return(0);
}
int trx_exmimo_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) {
return(nsamps);
}
int trx_exmimo_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
exmimo_state_t *exm=device->priv;
openair0_config_t *cfg=&device->openair0_cfg[0];
openair0_timestamp old_ts=0,ts,diff;
struct timespec sleep_time;
unsigned long tv_nsec;
int i;
int n,n1,n2,ntot,first_len;
int ret;
// struct timespec wait;
// wait.tv_sec=0;
// wait.tv_nsec=50000000L;
if (exm->watchdog_exit == 1)
return(0);
if (exm->daq_state == idle) {
tv_nsec=(unsigned long)((double)(nsamps)*1e9/cfg->sample_rate);
return(0);
}
switch (ret) {
case EINVAL:
#ifdef DEBUG_EXMIMO
printf("trx_exmimo_read: mutex_timedlock returned EINVAL\n");
#endif
return(0);
break;
case ETIMEDOUT:
#ifdef DEBUG_EXMIMO
printf("trx_exmimo_read: mutex_timedlock returned ETIMEDOUT\n");
#endif
return(0);
break;
case EAGAIN:
#ifdef DEBUG_EXMIMO
printf("trx_exmimo_read: mutex_timedlock returned EAGAIN\n");
#endif
return(0);
break;
case EDEADLK:
#ifdef DEBUG_EXMIMO
printf("trx_exmimo_read: mutex_timedlock returned EDEADLK\n");
#endif
return(0);
break;
}
ret = pthread_mutex_lock(&exm->watchdog_mutex);
ts = exm->ts;
if (exm->wait_first_read==1) {
exm->wait_first_read=0;
exm->last_ts_rx = ts;
}
pthread_mutex_unlock(&exm->watchdog_mutex);
// dump_frame_parms(frame_parms[0]);
if (nsamps > (exm->samples_per_frame>>1)) {
n1 = nsamps>>1;
n2 = nsamps-n1;
}
else {
n1=nsamps;
n2=0;
}
#ifdef DEBUG_EXMIMO
printf("Reading %d samples, ts %lu (%d), last_ts_rx %lu (%lu)\n",nsamps,ts,ts%exm->samples_per_frame,exm->last_ts_rx,exm->last_ts_rx+nsamps);
#endif
for (n=n1,ntot=0;ntot<nsamps;n=n2) {
while ((ts < exm->last_ts_rx + n) &&
(exm->watchdog_exit==0)) {
diff = exm->last_ts_rx+n - ts; // difference in samples between current timestamp and last RX received sample
// go to sleep until we should have enough samples (1024 for a bit more)
#ifdef DEBUG_EXMIMO
printf("portion %d samples, ts %lu, last_ts_rx %lu (%lu) => sleeping %u us\n",n,ts,exm->last_ts_rx,exm->last_ts_rx+n,
(unsigned int)((double)(diff+1024)*1e6/cfg->sample_rate));
#endif
tv_nsec=(unsigned long)((double)(diff+3840)*1e9/cfg->sample_rate);
// tv_nsec = 500000L;
old_ts = ts;
rt_sleep(&sleep_time,tv_nsec);
#ifdef DEBUG_EXMIMO
printf("back\n");
#endif
// get new timestamp, in case we have to sleep again
pthread_mutex_lock(&exm->watchdog_mutex);
ts = exm->ts;
pthread_mutex_unlock(&exm->watchdog_mutex);
if (old_ts == ts) {
printf("ts stopped, returning\n");
return(0);
}
}
if (cfg->mmapped_dma == 0) { // if buff is not the dma buffer, do a memcpy, otherwise do nothing
for (i=0;i<cc;i++) {
#ifdef DEBUG_EXMIMO
printf("copying to %p (%lu), from %llu\n",buff[i]+(ntot*sizeof(int)),ntot*sizeof(int),(exm->last_ts_rx % exm->samples_per_frame));
#endif
if ((n+(exm->last_ts_rx%exm->samples_per_frame))<exm->samples_per_frame) {
memcpy(buff[i]+(ntot*sizeof(int)),
(void*)(openair0_exmimo_pci[0].adc_head[i]+(exm->last_ts_rx % exm->samples_per_frame)),
n*sizeof(int));
}
else {
first_len = (exm->samples_per_frame-(exm->last_ts_rx%exm->samples_per_frame));
#ifdef DEBUG_EXMIMO
printf("split: first_len %d, remainder %d\n",first_len,n-first_len);
#endif
memcpy(buff[i]+(ntot*sizeof(int)),
(void*)(openair0_exmimo_pci[0].adc_head[i]+(exm->last_ts_rx % exm->samples_per_frame)),
first_len*sizeof(int));
memcpy(buff[i]+(ntot+first_len)*sizeof(int),
(void*)openair0_exmimo_pci[0].adc_head[i],
(n-first_len)*sizeof(int));
}
}
}
pthread_mutex_lock(&exm->watchdog_mutex);
exm->last_ts_rx += n;
pthread_mutex_unlock(&exm->watchdog_mutex);
if (n==n1) {
*ptimestamp=exm->last_ts_rx;
}
ntot+=n;
}
return(nsamps);
}
void trx_exmimo_end(openair0_device *device) {
exmimo_state_t *exm=device->priv;
exm->daq_state = idle;
openair0_stop(0);
}
int trx_exmimo_get_stats(openair0_device* device) {
return(0);
}
int trx_exmimo_reset_stats(openair0_device* device) {
return(0);
}
int trx_exmimo_stop(openair0_device* device) {
exmimo_state_t *exm=device->priv;
printf("Stopping ...\n");
exm->daq_state = idle;
openair0_stop(0);
return(0);
}
int trx_exmimo_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
openair0_set_frequencies(device,openair0_cfg,0);
return(0);
}
int trx_exmimo_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
return(0);
}
void kill_watchdog(openair0_device *device) {
exmimo_state_t *exm=(exmimo_state_t *)device->priv;
exm->watchdog_exit=1;
}
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
// Initialize card
// exmimo_config_t *p_exmimo_config;
exmimo_id_t *p_exmimo_id;
int ret;
exmimo_state_t *exm = (exmimo_state_t *)malloc(sizeof(exmimo_state_t));
int card,ant;
ret = openair0_open();
if ( ret != 0 ) {
if (ret == -1)
printf("Error opening /dev/openair0");
@@ -260,9 +723,42 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
device->type = EXMIMO_DEV;
// Add stuff that was in lte-softmodem here
//
device->trx_start_func = trx_exmimo_start;
device->trx_end_func = trx_exmimo_end;
device->trx_read_func = trx_exmimo_read;
device->trx_write_func = trx_exmimo_write;
device->trx_get_stats_func = trx_exmimo_get_stats;
device->trx_reset_stats_func = trx_exmimo_reset_stats;
device->trx_stop_func = trx_exmimo_stop;
device->trx_set_freq_func = trx_exmimo_set_freq;
device->trx_set_gains_func = trx_exmimo_set_gains;
device->openair0_cfg = openair0_cfg;
device->priv = (void *)exm;
printf("EXMIMO2: Getting addresses for memory-mapped DMA\n");
for (card=0; card<openair0_num_detected_cards; card++) {
for (ant=0; ant<4; ant++) {
openair0_cfg[card].rxbase[ant] = (int32_t*)openair0_exmimo_pci[card].adc_head[ant];
openair0_cfg[card].txbase[ant] = (int32_t*)openair0_exmimo_pci[card].dac_head[ant];
}
}
create_watchdog(device);
return(0);
}
unsigned int rxg_max[4] = {128,128,128,126};
unsigned int rxg_med[4] = {122,123,123,120};
unsigned int rxg_byp[4] = {116,117,116,116};
unsigned int nf_max[4] = {7,9,16,12};
unsigned int nf_med[4] = {12,13,22,17};
unsigned int nf_byp[4] = {15,20,29,23};
int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
{
int ret;
@@ -270,6 +766,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
int resampling_factor=2;
int rx_filter=RXLPF25, tx_filter=TXLPF25;
int ACTIVE_RF=0;
int i;
exmimo_config_t *p_exmimo_config;
exmimo_id_t *p_exmimo_id;
@@ -297,11 +794,10 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
p_exmimo_config->framing.multicard_syncmode=SYNCMODE_SLAVE;
/* device specific */
openair0_cfg[card].txlaunch_wait = 1;//manage when TX processing is triggered
openair0_cfg[card].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
openair0_cfg[card].iq_txshift = 4;//shift
openair0_cfg[card].iq_rxrescale = 15;//rescale iqs
if (openair0_cfg[card].sample_rate==30.72e6) {
resampling_factor = 0;
rx_filter = RXLPF10;
@@ -332,6 +828,10 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
#endif
for (ant=0; ant<4; ant++) {
openair0_cfg[card].rxbase[ant] = (int32_t*)openair0_exmimo_pci[card].adc_head[ant];
openair0_cfg[card].txbase[ant] = (int32_t*)openair0_exmimo_pci[card].dac_head[ant];
if (openair0_cfg[card].rx_freq[ant] || openair0_cfg[card].tx_freq[ant]) {
ACTIVE_RF += (1<<ant)<<5;
p_exmimo_config->rf.rf_mode[ant] = RF_MODE_BASE;
@@ -339,32 +839,59 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
printf("card %d, antenna %d, autocal %d\n",card,ant,openair0_cfg[card].autocal[ant]);
}
if (openair0_cfg[card].tx_freq[ant]) {
if (openair0_cfg[card].tx_freq[ant]>0) {
p_exmimo_config->rf.rf_mode[ant] += (TXEN + DMAMODE_TX + TXLPFNORM + TXLPFEN + tx_filter);
p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant];
p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant];
printf("openair0 : programming card %d TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
printf("Setting TX buffer to all-RX\n");
for (i=0;i<307200;i++) {
((uint32_t*)openair0_exmimo_pci[card].dac_head[ant])[i] = 0x00010001;
}
}
if (openair0_cfg[card].rx_freq[ant]) {
if (openair0_cfg[card].rx_freq[ant]>0) {
p_exmimo_config->rf.rf_mode[ant] += (RXEN + DMAMODE_RX + RXLPFNORM + RXLPFEN + rx_filter);
p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant];
p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant];
printf("openair0 : programming card %d RX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]);
switch (openair0_cfg[card].rxg_mode[ant]) {
default:
case max_gain:
p_exmimo_config->rf.rf_mode[ant] += LNAMax;
if (rxg_max[ant] >= (int)openair0_cfg[card].rx_gain[ant]) {
p_exmimo_config->rf.rx_gain[ant][0] = 30 - (rxg_max[ant] - (int)openair0_cfg[card].rx_gain[ant]); //was measured at rxgain=30;
}
else {
printf("openair0: RX RF gain too high, reduce by %d dB\n", (int)openair0_cfg[card].rx_gain[ant]-rxg_max[ant]);
exit(-1);
}
break;
case med_gain:
p_exmimo_config->rf.rf_mode[ant] += LNAMed;
if (rxg_med[ant] >= (int)openair0_cfg[card].rx_gain[ant]) {
p_exmimo_config->rf.rx_gain[ant][0] = 30 - (rxg_med[ant] - (int)openair0_cfg[card].rx_gain[ant]); //was measured at rxgain=30;
}
else {
printf("openair0: RX RF gain too high, reduce by %d dB\n", (int)openair0_cfg[card].rx_gain[ant]-rxg_med[ant]);
exit(-1);
}
break;
case byp_gain:
p_exmimo_config->rf.rf_mode[ant] += LNAByp;
if (rxg_byp[ant] >= (int)openair0_cfg[card].rx_gain[ant]) {
p_exmimo_config->rf.rx_gain[ant][0] = 30 - (rxg_byp[ant] - (int)openair0_cfg[card].rx_gain[ant]); //was measured at rxgain=30;
}
else {
printf("openair0: RX RF gain too high, reduce by %d dB\n", (int)openair0_cfg[card].rx_gain[ant]-rxg_byp[ant]);
exit(-1);
}
break;
}
} else {
@@ -375,7 +902,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
p_exmimo_config->rf.rf_local[ant] = rf_local[ant];
p_exmimo_config->rf.rf_rxdc[ant] = rf_rxdc[ant];
if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 850000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 865000000)) {
if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 790000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 865000000)) {
p_exmimo_config->rf.rf_vcocal[ant] = rf_vcocal_850[ant];
p_exmimo_config->rf.rffe_band_mode[ant] = DD_TDD;
} else if (( p_exmimo_config->rf.rf_freq_tx[ant] >= 1900000000) && ( p_exmimo_config->rf.rf_freq_tx[ant] <= 2000000000)) {
@@ -388,7 +915,7 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
}
if (openair0_cfg[card].duplex_mode==duplex_mode_FDD) {
p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD;
p_exmimo_config->framing.tdd_config = DUPLEXMODE_FDD;// + TXRXSWITCH_LSB + TXRXSWITCH_LSB + ACTIVE_RF+ ACTIVE_RF;
printf("!!!!!setting FDD (tdd_config=%d)\n",p_exmimo_config->framing.tdd_config);
}
else {
@@ -419,6 +946,9 @@ int openair0_reconfig(openair0_config_t *openair0_cfg)
return(-1);
}
#ifdef DEBUG_EXMIMO
printf("Reconfiguration of gains/frequencies\n");
#endif
for (card=0; card<openair0_num_detected_cards; card++) {
p_exmimo_config = openair0_exmimo_pci[card].exmimo_config_ptr;
@@ -428,14 +958,18 @@ int openair0_reconfig(openair0_config_t *openair0_cfg)
if (openair0_cfg[card].tx_freq[ant]) {
p_exmimo_config->rf.rf_freq_tx[ant] = (unsigned int)openair0_cfg[card].tx_freq[ant];
p_exmimo_config->rf.tx_gain[ant][0] = (unsigned int)openair0_cfg[card].tx_gain[ant];
//printf("openair0 : programming TX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
#ifdef DEBUG_EXMIMO
printf("openair0 - %d : programming TX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_tx[ant],p_exmimo_config->rf.tx_gain[ant][0]);
#endif
}
if (openair0_cfg[card].rx_freq[ant]) {
p_exmimo_config->rf.rf_freq_rx[ant] = (unsigned int)openair0_cfg[card].rx_freq[ant];
p_exmimo_config->rf.rx_gain[ant][0] = (unsigned int)openair0_cfg[card].rx_gain[ant];
//printf("openair0 : programming RX antenna %d (freq %u, gain %d)\n",ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]);
#ifdef DEBUG_EXMIMO
printf("openair0 - %d : programming RX antenna %d (freq %u, gain %d)\n",card,ant,p_exmimo_config->rf.rf_freq_rx[ant],p_exmimo_config->rf.rx_gain[ant][0]);
#endif
switch (openair0_cfg[card].rxg_mode[ant]) {
default:
case max_gain:
@@ -13,6 +13,30 @@
#include "pcie_interface.h"
#include "openair_device.h"
#include "common_lib.h"
#include <pthread.h>
#include <sched.h>
#include <linux/sched.h>
typedef enum {
idle=0,
waiting_for_synch,
running
} exmimo_daq_state_t;
typedef struct {
pthread_t watchdog;
pthread_attr_t watchdog_attr;
struct sched_param watchdog_sched_param;
pthread_mutex_t watchdog_mutex;
int watchdog_exit;
int wait_first_read;
exmimo_daq_state_t daq_state;
openair0_timestamp ts;
openair0_timestamp last_ts_rx;
int samples_per_tick;
int samples_per_frame;
int last_mbox;
} exmimo_state_t;
// Use this to access shared memory (configuration structures, adc/dac data buffers, ...)
// contains userspace pointers
@@ -12,6 +12,7 @@
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include "openair_device.h"
@@ -210,6 +211,18 @@ void find_and_transfer_section(char* section_name, unsigned int verboselevel) {
/* Dynamically allocate a chunk of memory to store the section into. */
section_content = (char*)malloc(elf_Shdr.sh_size);
/* Fail if the address returned by malloc does not fit in 32 bits.
* The kernel driver gets this address as 32 bits and uses it to copy
* from userspace. If the address does not fit into 32 bits the kernel
* will copy garbage or fail to copy completely.
* To be reworked if things do not work on some setups.
*/
if (sizeof(char*) > 4 && (((uintptr_t)section_content)>>32)) {
fprintf(stderr, "FATAL ERROR: an internal serious problem has been encountered.\n");
fprintf(stderr, "Contact the authors so as to solve this issue.\n");
exit(-1);
}
if (!section_content) {
fprintf(stderr, "Error: could not dynamically allocate %d bytes for section %s.\n",
elf_Shdr.sh_size, SecNameStnTable + elf_Shdr.sh_name);
@@ -252,6 +265,13 @@ void find_and_transfer_section(char* section_name, unsigned int verboselevel) {
ioctl_params[0] = UPDATE_FIRMWARE_TRANSFER_BLOCK;
ioctl_params[1] = elf_Shdr.sh_addr;
ioctl_params[2] = elf_Shdr.sh_size / 4;
/* This is wrong on x86_64 because a pointer is 64 bits and
* an unsigned int is only 32 bits.
* The compiler emits a warning, but the test
* above on the value of section_content makes it work
* (hopefully).
* To be changed if things do not work.
*/
ioctl_params[3] = (unsigned int)((unsigned int*)section_content);
//invert4(ioctl_params[1]);
//invert4(ioctl_params[2]);
@@ -0,0 +1 @@
volatile int oai_exit=0;
@@ -36,6 +36,7 @@
#include <octave/oct.h>
#include "pcie_interface.h"
#include "oarf.h"
extern "C" {
#include "openair0_lib.h"
@@ -42,6 +42,7 @@
extern "C" {
#include "openair0_lib.h"
}
#include "oarf.h"
#define FCNNAME "oarf_get_frame"
@@ -39,6 +39,7 @@
extern "C" {
#include "openair0_lib.h"
}
#include "oarf.h"
#define FCNNAME "oarf_get_num_detected_cards"
@@ -41,6 +41,7 @@
extern "C" {
#include "openair0_lib.h"
}
#include "oarf.h"
#define FCNNAME "oarf_send_frame"
@@ -40,6 +40,7 @@
extern "C" {
#include "openair0_lib.h"
}
#include "oarf.h"
#define FCNNAME "oarf_stop"
@@ -39,6 +39,7 @@
extern "C" {
#include "openair0_lib.h"
}
#include "oarf.h"
#define FCNNAME "oarf_stop_without_reset"
+2 -2
View File
@@ -1,4 +1,4 @@
fc = 1907600000;
fc = 2560000000
%fc = 1907600000;
%fc = 859.5e6;
@@ -6,7 +6,7 @@ rxgain=0;
txgain=0;
eNB_flag = 0;
card = 0;
active_rf = [1 1 1 1];
active_rf = [1 0 0 0];
autocal = [1 1 1 1];
resampling_factor = [2 2 2 2];
limeparms;
@@ -294,7 +294,7 @@ int trx_lms_start(openair0_device *device){
* \param card Index of the RF card to use
* \returns 0 on success
*/
int trx_lms_stop(int card) {
int trx_lms_stop(openair0_device *device) {
/*
LMS_DeviceClose(usbport);
LMS_DeviceClose(comport);
@@ -380,28 +380,24 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 30.72e6;
openair0_cfg[0].rx_bw = 30.72e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
case 15360000:
openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 28e6;
openair0_cfg[0].rx_bw = 10e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
case 7680000:
openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 70;
openair0_cfg[0].tx_bw = 28e6;
openair0_cfg[0].rx_bw = 5.0e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
case 1920000:
openair0_cfg[0].samples_per_packet = 256;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].rx_bw = 1.25e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
+82 -34
View File
@@ -16,7 +16,8 @@
#include <complex>
#include <fstream>
#include <cmath>
#include <time.h>
#include "UTIL/LOG/log_extern.h"
#include "common_lib.h"
#ifdef __SSE4_1__
# include <smmintrin.h>
@@ -143,23 +144,54 @@ static void trx_usrp_end(openair0_device *device)
*/
static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
{
static long long int loop=0;
static long time_min=0, time_max=0, time_avg=0;
struct timespec tp_start, tp_end;
long time_diff;
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start);
int ret=0, ret_i=0;
usrp_state_t *s = (usrp_state_t*)device->priv;
s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
if(flags)
s->tx_md.has_time_spec = true;
else
s->tx_md.has_time_spec = false;
if (cc>1) {
std::vector<void *> buff_ptrs;
for (int i=0;i<cc;i++) buff_ptrs.push_back(buff[i]);
s->tx_stream->send(buff_ptrs, nsamps, s->tx_md);
ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3);
}
else
s->tx_stream->send(buff[0], nsamps, s->tx_md);
ret = (int)s->tx_stream->send(buff[0], nsamps, s->tx_md,1e-3);
s->tx_md.start_of_burst = false;
return 0;
if (ret != nsamps) {
printf("[xmit] tx samples %d != %d\n",ret,nsamps);
}
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end);
time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec);
if (time_min==0 ||loop==1 || time_min > time_diff)
time_min=time_diff;
if (time_max==0 ||loop==1 || time_max < time_diff)
time_max=time_diff;
if (time_avg ==0 ||loop==1)
time_avg= time_diff;
else
time_avg=(time_diff+time_avg) /2.0;
/* //prints statics of uhd every 10 seconds
if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0)
LOG_I(HW,"usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg);
*/
loop++;
return ret;
}
/*! \brief Receive samples from hardware.
@@ -175,20 +207,25 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
*/
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
{
static long long int loop=0;
static long time_min=0, time_max=0, time_avg=0;
struct timespec tp_start, tp_end;
long time_diff;
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start);
usrp_state_t *s = (usrp_state_t*)device->priv;
int samples_received=0,i,j;
int nsamps2; // aligned to upper 32 or 16 byte boundary
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
__m256i buff_tmp[2][nsamps>>3];
nsamps2 = (nsamps+7)>>3;
__m256i buff_tmp[2][nsamps2];
#else
__m128i buff_tmp[2][nsamps>>2];
nsamps2 = (nsamps+3)>>2;
__m128i buff_tmp[2][nsamps2];
#endif
#elif defined(__arm__)
int16x8_t buff_tmp[2][nsamps>>2];
nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tmp[2][nsamps2];
#endif
@@ -203,7 +240,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
// receive a single channel (e.g. from connector RF A)
samples_received = s->rx_stream->recv(buff_tmp[0], nsamps, s->rx_md);
}
// bring RX data into 12 LSBs for softmodem RX
for (int i=0;i<cc;i++) {
for (int j=0; j<nsamps2; j++) {
@@ -219,7 +256,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
}
}
} else if (device->type == USRP_X300_DEV) {
if (cc>1) {
if (cc>1) {
// receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs;
@@ -255,6 +292,22 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end);
time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec);
if (time_min==0 ||loop==1 || time_min > time_diff)
time_min=time_diff;
if (time_max==0 ||loop==1 || time_max < time_diff)
time_max=time_diff;
if (time_avg ==0 ||loop==1)
time_avg= time_diff;
else
time_avg=(time_diff+time_avg) /2.0;
/*
//prints statics of uhd every 10 seconds
if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0)
LOG_I(HW,"usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg);
loop++;*/
return samples_received;
}
@@ -346,7 +399,7 @@ int trx_usrp_set_gains(openair0_device* device,
/*! \brief Stop USRP
* \param card refers to the hardware index to use
*/
int trx_usrp_stop(int card) {
int trx_usrp_stop(openair0_device* device) {
return(0);
}
@@ -462,6 +515,7 @@ extern "C" {
// Initialize USRP device
device->openair0_cfg = openair0_cfg;
std::string args = "type=b200";
@@ -485,6 +539,8 @@ extern "C" {
// workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
// args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096";
uhd::device_addrs_t device_adds = uhd::device::find(args);
if(device_adds.size() == 0)
@@ -516,32 +572,28 @@ extern "C" {
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
// from usrp_time_offset
openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
case 15360000:
openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 10e6;
openair0_cfg[0].rx_bw = 10e6;
openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet;
break;
case 7680000:
openair0_cfg[0].samples_per_packet = 1024;
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 5e6;
openair0_cfg[0].rx_bw = 5e6;
openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet;
break;
case 1920000:
openair0_cfg[0].samples_per_packet = 256;
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].rx_bw = 1.25e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
@@ -551,7 +603,7 @@ extern "C" {
} else {
printf("Found USRP B200");
args += ",num_recv_frames=256" ;
args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096" ;
s->usrp = uhd::usrp::multi_usrp::make(args);
// s->usrp->set_rx_subdev_spec(rx_subdev);
@@ -577,43 +629,38 @@ extern "C" {
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
s->usrp->set_master_clock_rate(30.72e6);
openair0_cfg[0].samples_per_packet = 4096;
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 115;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_scheduling_advance = 11*openair0_cfg[0].samples_per_packet;
break;
case 23040000:
s->usrp->set_master_clock_rate(23.04e6); //to be checked
openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 113;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
case 15360000:
s->usrp->set_master_clock_rate(30.72e06);
openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 103;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_scheduling_advance = 10240;
break;
case 7680000:
s->usrp->set_master_clock_rate(30.72e6);
openair0_cfg[0].samples_per_packet = 1024;
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet;
break;
case 1920000:
s->usrp->set_master_clock_rate(7.68e6);
openair0_cfg[0].samples_per_packet = 256;
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 40;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
@@ -623,8 +670,8 @@ extern "C" {
}
/* device specific */
openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered
openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
//openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered
//openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
@@ -734,7 +781,8 @@ extern "C" {
device->trx_stop_func = trx_usrp_stop;
device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_gains_func = trx_usrp_set_gains;
device->openair0_cfg = openair0_cfg;
s->sample_rate = openair0_cfg[0].sample_rate;
// TODO:
// init tx_forward_nsamps based usrp_time_offset ex