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:
@@ -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);
|
||||
|
||||
@@ -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*/
|
||||
|
||||
|
||||
@@ -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*)ð->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*)ð->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*)ð->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*)ð->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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user