Merge remote-tracking branch 'internal/mobipass-standalone' into develop_integration_w34
This commit is contained in:
@@ -532,6 +532,19 @@ set(TPLIB_ETHERNET_SOURCE
|
|||||||
)
|
)
|
||||||
add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} )
|
add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} )
|
||||||
|
|
||||||
|
include_directories("${OPENAIR_TARGETS}/ARCH/mobipass/")
|
||||||
|
set(TPLIB_MOBIPASS_SOURCE
|
||||||
|
${OPENAIR_TARGETS}/ARCH/mobipass/interface.c
|
||||||
|
${OPENAIR_TARGETS}/ARCH/mobipass/mobipass.c
|
||||||
|
${OPENAIR_TARGETS}/ARCH/mobipass/queues.c
|
||||||
|
)
|
||||||
|
add_library(oai_mobipass MODULE ${TPLIB_MOBIPASS_SOURCE} )
|
||||||
|
|
||||||
|
# Hide all functions/variables in the mobipass library.
|
||||||
|
# Use __attribute__((__visibility__("default")))
|
||||||
|
# in the source code to unhide a function/variable.
|
||||||
|
get_target_property(mobipas_cflags oai_mobipass COMPILE_FLAGS)
|
||||||
|
set_target_properties(oai_mobipass PROPERTIES COMPILE_FLAGS "${mobipass_cflags} -fvisibility=hidden")
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
|
|
||||||
|
|||||||
@@ -181,63 +181,114 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (packet_type == IF5_MOBIPASS) {
|
} else if (packet_type == IF5_MOBIPASS) {
|
||||||
uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES;
|
/* the only difference between mobipass standalone and the other one
|
||||||
|
* is the timestamp in trx_write_func, but let's duplicate anyway
|
||||||
__m128i *data_block=NULL, *data_block_head=NULL;
|
* (plus we don't call malloc for the standalone case)
|
||||||
|
*/
|
||||||
|
if (eNB->node_timing == synch_to_mobipass_standalone) {
|
||||||
|
uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES;
|
||||||
|
|
||||||
__m128i *txp128;
|
__m128i *data_block=NULL, *data_block_head=NULL;
|
||||||
__m128i t0, t1;
|
__m128i *txp128;
|
||||||
|
__m128i t0, t1;
|
||||||
|
|
||||||
// tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
unsigned char _tx_buffer[MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)];
|
||||||
tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
tx_buffer=(int32_t *)_tx_buffer;
|
||||||
IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES);
|
|
||||||
data_block_head = (__m128i *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t);
|
IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES);
|
||||||
|
data_block_head = (__m128i *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t);
|
||||||
header->flags = 0;
|
|
||||||
header->fifo_status = 0;
|
header->flags = 0;
|
||||||
header->seqno = *seqno;
|
header->fifo_status = 0;
|
||||||
header->ack = 0;
|
header->seqno = *seqno;
|
||||||
header->word0 = 0;
|
header->ack = 0;
|
||||||
|
header->word0 = 0;
|
||||||
txp[0] = (void*)&eNB->common_vars.txdata[0][0][subframe*eNB->frame_parms.samples_per_tti];
|
|
||||||
txp128 = (__m128i *) txp[0];
|
txp[0] = (void*)&eNB->common_vars.txdata[0][0][subframe*eNB->frame_parms.samples_per_tti];
|
||||||
|
txp128 = (__m128i *) txp[0];
|
||||||
for (packet_id=0; packet_id<fp->samples_per_tti/db_fulllength; packet_id++) {
|
|
||||||
header->time_stamp = htonl((uint32_t)(proc_timestamp + packet_id*db_fulllength));
|
for (packet_id=0; packet_id<fp->samples_per_tti/db_fulllength; packet_id++) {
|
||||||
data_block = data_block_head;
|
header->time_stamp = htonl((uint32_t)(proc_timestamp + packet_id*db_fulllength));
|
||||||
|
data_block = data_block_head;
|
||||||
for (i=0; i<db_fulllength>>2; i+=2) {
|
|
||||||
t0 = _mm_srai_epi16(*txp128++, 4);
|
for (i=0; i<db_fulllength>>2; i+=2) {
|
||||||
t1 = _mm_srai_epi16(*txp128++, 4);
|
t0 = _mm_srai_epi16(*txp128++, 4);
|
||||||
// *data_block++ = _mm_packs_epi16(t0, t1);
|
t1 = _mm_srai_epi16(*txp128++, 4);
|
||||||
_mm_storeu_si128(data_block++, _mm_packs_epi16(t0, t1));
|
_mm_storeu_si128(data_block++, _mm_packs_epi16(t0, t1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the packet to the fronthaul
|
||||||
|
if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice,
|
||||||
|
proc_timestamp + packet_id*db_fulllength,
|
||||||
|
(void**)&tx_buffer,
|
||||||
|
db_fulllength,
|
||||||
|
1,
|
||||||
|
IF5_MOBIPASS)) < 0) {
|
||||||
|
perror("ETHERNET write for IF5_MOBIPASS\n");
|
||||||
|
}
|
||||||
|
header->seqno += 1;
|
||||||
}
|
}
|
||||||
|
*seqno = header->seqno;
|
||||||
|
tx_buffer = NULL;
|
||||||
|
} else {
|
||||||
|
uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES;
|
||||||
|
|
||||||
// Write the packet to the fronthaul
|
__m128i *data_block=NULL, *data_block_head=NULL;
|
||||||
if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice,
|
|
||||||
packet_id,
|
__m128i *txp128;
|
||||||
(void**)&tx_buffer,
|
__m128i t0, t1;
|
||||||
db_fulllength,
|
|
||||||
1,
|
// tx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
||||||
IF5_MOBIPASS)) < 0) {
|
tx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
||||||
perror("ETHERNET write for IF5_MOBIPASS\n");
|
IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES);
|
||||||
}
|
data_block_head = (__m128i *)((uint8_t *)tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t);
|
||||||
|
|
||||||
|
header->flags = 0;
|
||||||
|
header->fifo_status = 0;
|
||||||
|
header->seqno = *seqno;
|
||||||
|
header->ack = 0;
|
||||||
|
header->word0 = 0;
|
||||||
|
|
||||||
|
txp[0] = (void*)&eNB->common_vars.txdata[0][0][subframe*eNB->frame_parms.samples_per_tti];
|
||||||
|
txp128 = (__m128i *) txp[0];
|
||||||
|
|
||||||
|
for (packet_id=0; packet_id<fp->samples_per_tti/db_fulllength; packet_id++) {
|
||||||
|
header->time_stamp = htonl((uint32_t)(proc_timestamp + packet_id*db_fulllength));
|
||||||
|
data_block = data_block_head;
|
||||||
|
|
||||||
|
for (i=0; i<db_fulllength>>2; i+=2) {
|
||||||
|
t0 = _mm_srai_epi16(*txp128++, 4);
|
||||||
|
t1 = _mm_srai_epi16(*txp128++, 4);
|
||||||
|
// *data_block++ = _mm_packs_epi16(t0, t1);
|
||||||
|
_mm_storeu_si128(data_block++, _mm_packs_epi16(t0, t1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the packet to the fronthaul
|
||||||
|
if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice,
|
||||||
|
packet_id,
|
||||||
|
(void**)&tx_buffer,
|
||||||
|
db_fulllength,
|
||||||
|
1,
|
||||||
|
IF5_MOBIPASS)) < 0) {
|
||||||
|
perror("ETHERNET write for IF5_MOBIPASS\n");
|
||||||
|
}
|
||||||
#ifdef DEBUG_DL_MOBIPASS
|
#ifdef DEBUG_DL_MOBIPASS
|
||||||
if ((subframe==0)&&(dummy_cnt == 100)) {
|
if ((subframe==0)&&(dummy_cnt == 100)) {
|
||||||
memcpy((void*)&dummy_buffer[packet_id*db_fulllength*2],(void*)data_block_head,db_fulllength*2);
|
memcpy((void*)&dummy_buffer[packet_id*db_fulllength*2],(void*)data_block_head,db_fulllength*2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
header->seqno += 1;
|
header->seqno += 1;
|
||||||
}
|
}
|
||||||
*seqno = header->seqno;
|
*seqno = header->seqno;
|
||||||
|
|
||||||
#ifdef DEBUG_DL_MOBIPASS
|
#ifdef DEBUG_DL_MOBIPASS
|
||||||
uint8_t txe;
|
uint8_t txe;
|
||||||
txe = dB_fixed(signal_energy(txp[0],fp->samples_per_tti));
|
txe = dB_fixed(signal_energy(txp[0],fp->samples_per_tti));
|
||||||
if (txe > 0){
|
if (txe > 0){
|
||||||
LOG_D(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, txe);
|
LOG_D(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, txe);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
AssertFatal(1==0, "send_IF5 - Unknown packet_type %x", packet_type);
|
AssertFatal(1==0, "send_IF5 - Unknown packet_type %x", packet_type);
|
||||||
}
|
}
|
||||||
@@ -391,131 +442,176 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram
|
|||||||
*proc_timestamp = timestamp[0];
|
*proc_timestamp = timestamp[0];
|
||||||
|
|
||||||
} else if (packet_type == IF5_MOBIPASS) {
|
} else if (packet_type == IF5_MOBIPASS) {
|
||||||
|
if (eNB->node_timing == synch_to_mobipass_standalone) {
|
||||||
uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES;
|
uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES;
|
||||||
openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength];
|
openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength];
|
||||||
#ifdef DEBUG_UL_MOBIPASS
|
int subframe_skip = 0;
|
||||||
int lower_offset = 0;
|
int reset_flag = 0;
|
||||||
int upper_offset = 70000;
|
int32_t *rx_buffer=NULL;
|
||||||
#endif
|
__m128i *data_block=NULL, *data_block_head=NULL;
|
||||||
int subframe_skip = 0;
|
__m128i *rxp128;
|
||||||
int reset_flag = 0;
|
__m128i r0;
|
||||||
int32_t *rx_buffer=NULL;
|
|
||||||
__m128i *data_block=NULL, *data_block_head=NULL;
|
|
||||||
__m128i *rxp128;
|
|
||||||
__m128i r0;
|
|
||||||
|
|
||||||
//rx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
unsigned char _rx_buffer[MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)];
|
||||||
rx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
rx_buffer = (int32_t *)_rx_buffer;
|
||||||
IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES);
|
IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES);
|
||||||
data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t);
|
data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t);
|
||||||
|
|
||||||
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti];
|
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti];
|
||||||
rxp128 = (__m128i *) (rxp[0]);
|
rxp128 = (__m128i *) (rxp[0]);
|
||||||
|
|
||||||
eNB_proc_t *proc = &eNB->proc;
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
|
||||||
|
packet_id=0;
|
||||||
|
while(packet_id<fp->samples_per_tti/db_fulllength) {
|
||||||
|
data_block = data_block_head;
|
||||||
|
|
||||||
|
eNB->ifdevice.trx_read_func(&eNB->ifdevice,
|
||||||
|
×tamp_mobipass[packet_id],
|
||||||
|
(void**)&rx_buffer,
|
||||||
|
db_fulllength,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
//store rxdata and increase packet_id
|
||||||
|
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength];
|
||||||
|
rxp128 = (__m128i *) (rxp[0]);
|
||||||
|
for (i=0; i<db_fulllength>>2; i+=2) {
|
||||||
|
r0 = _mm_loadu_si128(data_block++);
|
||||||
|
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4);
|
||||||
|
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4);
|
||||||
|
}
|
||||||
|
packet_id++;
|
||||||
|
}//end while
|
||||||
|
|
||||||
|
*proc_timestamp = ntohl(timestamp_mobipass[0]);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES;
|
||||||
|
openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength];
|
||||||
|
#ifdef DEBUG_UL_MOBIPASS
|
||||||
|
int lower_offset = 0;
|
||||||
|
int upper_offset = 70000;
|
||||||
|
#endif
|
||||||
|
int subframe_skip = 0;
|
||||||
|
int reset_flag = 0;
|
||||||
|
int32_t *rx_buffer=NULL;
|
||||||
|
__m128i *data_block=NULL, *data_block_head=NULL;
|
||||||
|
__m128i *rxp128;
|
||||||
|
__m128i r0;
|
||||||
|
|
||||||
|
//rx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
||||||
|
rx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t));
|
||||||
|
IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES);
|
||||||
|
data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t);
|
||||||
|
|
||||||
|
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti];
|
||||||
|
rxp128 = (__m128i *) (rxp[0]);
|
||||||
|
|
||||||
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
/*
|
/*
|
||||||
// while(packet_id<fp->samples_per_tti/db_fulllength) {
|
// while(packet_id<fp->samples_per_tti/db_fulllength) {
|
||||||
data_block = data_block_head;
|
data_block = data_block_head;
|
||||||
|
|
||||||
eNB->ifdevice.trx_read_func(&eNB->ifdevice,
|
eNB->ifdevice.trx_read_func(&eNB->ifdevice,
|
||||||
&ts0,
|
&ts0,
|
||||||
(void**)&rx_buffer,
|
(void**)&rx_buffer,
|
||||||
db_fulllength,
|
db_fulllength,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
if ((header->seqno == 1)&&(first_packet==1)) {
|
if ((header->seqno == 1)&&(first_packet==1)) {
|
||||||
first_packet = 0; //ignore the packets before synchnorization
|
first_packet = 0; //ignore the packets before synchnorization
|
||||||
packet_id = 0;
|
packet_id = 0;
|
||||||
ts_offset = ntohl(ts0);
|
ts_offset = ntohl(ts0);
|
||||||
}
|
}
|
||||||
if (first_packet==0) {
|
if (first_packet==0) {
|
||||||
packet_cnt++;
|
packet_cnt++;
|
||||||
ts = ntohl(ts0);
|
ts = ntohl(ts0);
|
||||||
packet_id = (ts-ts_offset)/db_fulllength;
|
packet_id = (ts-ts_offset)/db_fulllength;
|
||||||
packet_id = packet_id % (fp->samples_per_tti/db_fulllength);
|
packet_id = packet_id % (fp->samples_per_tti/db_fulllength);
|
||||||
|
|
||||||
printf("[IF5_tools]packet_id:%d\n", packet_id);
|
printf("[IF5_tools]packet_id:%d\n", packet_id);
|
||||||
// if (ts_stored == 0) {
|
// if (ts_stored == 0) {
|
||||||
// ts_stored = 1;
|
// ts_stored = 1;
|
||||||
*proc_timestamp = ntohl(ts - (packet_id*db_fulllength));
|
*proc_timestamp = ntohl(ts - (packet_id*db_fulllength));
|
||||||
// }
|
// }
|
||||||
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength];
|
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength];
|
||||||
rxp128 = (__m128i *) (rxp[0]);
|
rxp128 = (__m128i *) (rxp[0]);
|
||||||
|
|
||||||
for (i=0; i<db_fulllength>>2; i+=2) {
|
for (i=0; i<db_fulllength>>2; i+=2) {
|
||||||
r0 = _mm_loadu_si128(data_block++);
|
r0 = _mm_loadu_si128(data_block++);
|
||||||
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4);
|
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4);
|
||||||
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4);
|
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
// }//end while
|
||||||
// }//end while
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
packet_id=0;
|
packet_id=0;
|
||||||
while(packet_id<fp->samples_per_tti/db_fulllength) {
|
while(packet_id<fp->samples_per_tti/db_fulllength) {
|
||||||
data_block = data_block_head;
|
data_block = data_block_head;
|
||||||
|
|
||||||
eNB->ifdevice.trx_read_func(&eNB->ifdevice,
|
eNB->ifdevice.trx_read_func(&eNB->ifdevice,
|
||||||
×tamp_mobipass[packet_id],
|
×tamp_mobipass[packet_id],
|
||||||
(void**)&rx_buffer,
|
(void**)&rx_buffer,
|
||||||
db_fulllength,
|
db_fulllength,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
#ifdef DEBUG_UL_MOBIPASS
|
#ifdef DEBUG_UL_MOBIPASS
|
||||||
if (((proc->timestamp_tx + lower_offset) > ntohl(timestamp_mobipass[packet_id])) || ((proc->timestamp_tx + upper_offset) < ntohl(timestamp_mobipass[packet_id]))) {
|
if (((proc->timestamp_tx + lower_offset) > ntohl(timestamp_mobipass[packet_id])) || ((proc->timestamp_tx + upper_offset) < ntohl(timestamp_mobipass[packet_id]))) {
|
||||||
//ignore the packet
|
//ignore the packet
|
||||||
subframe_skip_extra = (subframe_skip_extra + 1)%67;
|
subframe_skip_extra = (subframe_skip_extra + 1)%67;
|
||||||
LOG_D("[Mobipass] ignored packet, id:[%d,%d], proc->timestamp_tx:%llu, proc->timestamp_rx:%llu, seqno:%d\n", packet_id,subframe_skip_extra, proc->timestamp_tx, ntohl(timestamp_mobipass[packet_id]), header->seqno);
|
LOG_D("[Mobipass] ignored packet, id:[%d,%d], proc->timestamp_tx:%llu, proc->timestamp_rx:%llu, seqno:%d\n", packet_id,subframe_skip_extra, proc->timestamp_tx, ntohl(timestamp_mobipass[packet_id]), header->seqno);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//skip SUBFRAME_SKIP_NUM_MOBIPASS additional UL packets
|
//skip SUBFRAME_SKIP_NUM_MOBIPASS additional UL packets
|
||||||
if ((start_flag == 1) && (subframe_skip < SUBFRAME_SKIP_NUM_MOBIPASS)){
|
if ((start_flag == 1) && (subframe_skip < SUBFRAME_SKIP_NUM_MOBIPASS)){
|
||||||
subframe_skip++;
|
subframe_skip++;
|
||||||
offset_cnt = header->seqno;
|
offset_cnt = header->seqno;
|
||||||
} else {
|
} else {
|
||||||
if ((offset_cnt != header->seqno) && (start_flag == 0) && (proc->first_rx > 3)){
|
if ((offset_cnt != header->seqno) && (start_flag == 0) && (proc->first_rx > 3)){
|
||||||
#ifdef DEBUG_UL_MOBIPASS
|
#ifdef DEBUG_UL_MOBIPASS
|
||||||
LOG_D(PHY,"[Mobipass] Reset sequence number, offset_cnt:%d, header->seqno:%d, packet_id:%d\n", offset_cnt, header->seqno, packet_id);
|
LOG_D(PHY,"[Mobipass] Reset sequence number, offset_cnt:%d, header->seqno:%d, packet_id:%d\n", offset_cnt, header->seqno, packet_id);
|
||||||
#endif
|
#endif
|
||||||
reset_flag=1;
|
reset_flag=1;
|
||||||
}
|
}
|
||||||
if ((reset_flag == 1) && (proc->first_rx > 3 ) && (start_flag == 0) && (packet_id == 0)) {
|
if ((reset_flag == 1) && (proc->first_rx > 3 ) && (start_flag == 0) && (packet_id == 0)) {
|
||||||
packet_id = 1;
|
packet_id = 1;
|
||||||
reset_flag = 0;
|
reset_flag = 0;
|
||||||
}
|
}
|
||||||
start_flag = 0;
|
start_flag = 0;
|
||||||
|
|
||||||
//store rxdata and increase packet_id
|
//store rxdata and increase packet_id
|
||||||
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength];
|
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength];
|
||||||
rxp128 = (__m128i *) (rxp[0]);
|
rxp128 = (__m128i *) (rxp[0]);
|
||||||
for (i=0; i<db_fulllength>>2; i+=2) {
|
for (i=0; i<db_fulllength>>2; i+=2) {
|
||||||
r0 = _mm_loadu_si128(data_block++);
|
r0 = _mm_loadu_si128(data_block++);
|
||||||
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4);
|
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4);
|
||||||
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4);
|
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4);
|
||||||
}
|
}
|
||||||
packet_id++;
|
packet_id++;
|
||||||
offset_cnt = (header->seqno+1)&255;
|
offset_cnt = (header->seqno+1)&255;
|
||||||
}
|
}
|
||||||
}//end while
|
}//end while
|
||||||
|
|
||||||
*proc_timestamp = ntohl(timestamp_mobipass[0]);
|
*proc_timestamp = ntohl(timestamp_mobipass[0]);
|
||||||
#ifdef DEBUG_UL_MOBIPASS
|
#ifdef DEBUG_UL_MOBIPASS
|
||||||
LOG_I(PHY,"[Mobipass][Recv_MOBIPASS] timestamp: %llu\n ", *proc_timestamp);
|
LOG_I(PHY,"[Mobipass][Recv_MOBIPASS] timestamp: %llu\n ", *proc_timestamp);
|
||||||
if (eNB->CC_id>0) {
|
if (eNB->CC_id>0) {
|
||||||
rxe = dB_fixed(signal_energy(rxp[0],fp->samples_per_tti));
|
rxe = dB_fixed(signal_energy(rxp[0],fp->samples_per_tti));
|
||||||
if (rxe > 0){
|
if (rxe > 0){
|
||||||
LOG_I(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (*proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, rxe);
|
LOG_I(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (*proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, rxe);
|
||||||
// write_output("rxsigmb.m","rxs",(void*)dummy_buffer_rx, fp->samples_per_tti,1, 5);
|
// write_output("rxsigmb.m","rxs",(void*)dummy_buffer_rx, fp->samples_per_tti,1, 5);
|
||||||
// exit(-1);
|
// exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type);
|
AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -165,8 +165,9 @@ typedef enum {
|
|||||||
} eNB_func_t;
|
} eNB_func_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
synch_to_ext_device=0, // synch to RF or Ethernet device
|
synch_to_ext_device=0, // synch to RF or Ethernet device
|
||||||
synch_to_other // synch to another source (timer, other CC_id)
|
synch_to_other, // synch to another source (timer, other CC_id)
|
||||||
|
synch_to_mobipass_standalone // special case for mobipass in standalone mode
|
||||||
} eNB_timing_t;
|
} eNB_timing_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -947,6 +947,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
|||||||
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_ext_device;
|
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_ext_device;
|
||||||
} else if (strcmp(cc_node_timing, "synch_to_other") == 0) {
|
} else if (strcmp(cc_node_timing, "synch_to_other") == 0) {
|
||||||
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_other;
|
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_other;
|
||||||
|
} else if (strcmp(cc_node_timing, "synch_to_mobipass_standalone") == 0) {
|
||||||
|
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_mobipass_standalone;
|
||||||
} else {
|
} else {
|
||||||
AssertError (0, parse_errors ++,
|
AssertError (0, parse_errors ++,
|
||||||
"Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for node_function choice: SYNCH_TO_DEVICE or SYNCH_TO_OTHER !\n",
|
"Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for node_function choice: SYNCH_TO_DEVICE or SYNCH_TO_OTHER !\n",
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <linux/sysctl.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
#include "common_lib.h"
|
||||||
|
#include "ethernet_lib.h"
|
||||||
|
|
||||||
|
#include "mobipass.h"
|
||||||
|
#include "queues.h"
|
||||||
|
|
||||||
|
struct mobipass_header {
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t fifo_status;
|
||||||
|
unsigned char seqno;
|
||||||
|
unsigned char ack;
|
||||||
|
uint32_t word0;
|
||||||
|
uint32_t timestamp;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
int mobipass_start(openair0_device *device) { init_mobipass(device->priv); return 0; }
|
||||||
|
int mobipass_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
|
||||||
|
int mobipass_reply(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
|
||||||
|
int mobipass_get_stats(openair0_device* device) { return 0; }
|
||||||
|
int mobipass_reset_stats(openair0_device* device) { return 0; }
|
||||||
|
void mobipass_end(openair0_device *device) {}
|
||||||
|
int mobipass_stop(openair0_device *device) { return 0; }
|
||||||
|
int mobipass_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return 0; }
|
||||||
|
int mobipass_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { return 0; }
|
||||||
|
|
||||||
|
int mobipass_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||||
|
mobipass_state_t *mobi = device->priv;
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
|
||||||
|
mobi->mobipass_write_last_timestamp += 640;
|
||||||
|
mobi->mobipass_write_last_timestamp %= mobi->samples_per_1024_frames;
|
||||||
|
mh->timestamp = htonl(ntohl(mh->timestamp) % mobi->samples_per_1024_frames);
|
||||||
|
if (mobi->mobipass_write_last_timestamp != ntohl(mh->timestamp))
|
||||||
|
{ printf("mobipass: ERROR: bad timestamp wanted %d got %d\n", mobi->mobipass_write_last_timestamp, ntohl(mh->timestamp)); exit(1); }
|
||||||
|
//printf("__write nsamps %d timestamps %ld seqno %d (packet timestamp %d)\n", nsamps, timestamp, mh->seqno, ntohl(mh->timestamp));
|
||||||
|
if (nsamps != 640) abort();
|
||||||
|
enqueue_to_mobipass(mobi->qstate, buff[0]);
|
||||||
|
return nsamps;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mobipass_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
|
||||||
|
mobipass_state_t *mobi = device->priv;
|
||||||
|
//printf("__read nsamps %d return timestamp %d\n", nsamps, ts);
|
||||||
|
*timestamp = htonl(mobi->mobipass_read_ts);
|
||||||
|
mobi->mobipass_read_ts += nsamps;
|
||||||
|
mobi->mobipass_read_ts %= mobi->samples_per_1024_frames;
|
||||||
|
if (nsamps != 640) { printf("mobipass: ERROR: bad nsamps %d, should be 640\n", nsamps); fflush(stdout); abort(); }
|
||||||
|
|
||||||
|
dequeue_from_mobipass(mobi->qstate, ntohl(*timestamp), buff[0]);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
|
||||||
|
mh->flags = 0;
|
||||||
|
mh->fifo_status = 0;
|
||||||
|
mh->seqno = mobi->mobipass_read_seqno++;
|
||||||
|
mh->ack = 0;
|
||||||
|
mh->word0 = 0;
|
||||||
|
mh->timestamp = htonl(mobi->mobipass_read_ts);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return nsamps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is the only function in the library that is visible from outside
|
||||||
|
* because in CMakeLists.txt we use -fvisibility=hidden
|
||||||
|
*/
|
||||||
|
__attribute__((__visibility__("default")))
|
||||||
|
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg,
|
||||||
|
eth_params_t * eth_params )
|
||||||
|
{
|
||||||
|
//init_mobipass();
|
||||||
|
|
||||||
|
mobipass_state_t *mobi = (mobipass_state_t*)malloc(sizeof(mobipass_state_t));
|
||||||
|
memset(mobi, 0, sizeof(mobipass_state_t));
|
||||||
|
|
||||||
|
if (eth_params->transp_preference != 4) goto err;
|
||||||
|
if (eth_params->if_compress != 0) goto err;
|
||||||
|
|
||||||
|
/* only 50 PRBs handled for the moment */
|
||||||
|
if (openair0_cfg[0].sample_rate != 15360000) {
|
||||||
|
printf("mobipass: ERROR: only 50 PRBs supported\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mobi->eth.flags = ETH_RAW_IF5_MOBIPASS;
|
||||||
|
mobi->eth.compression = NO_COMPRESS;
|
||||||
|
device->Mod_id = 0;//num_devices_eth++;
|
||||||
|
device->transp_type = ETHERNET_TP;
|
||||||
|
|
||||||
|
device->trx_start_func = mobipass_start;
|
||||||
|
device->trx_request_func = mobipass_request;
|
||||||
|
device->trx_reply_func = mobipass_reply;
|
||||||
|
device->trx_get_stats_func = mobipass_get_stats;
|
||||||
|
device->trx_reset_stats_func = mobipass_reset_stats;
|
||||||
|
device->trx_end_func = mobipass_end;
|
||||||
|
device->trx_stop_func = mobipass_stop;
|
||||||
|
device->trx_set_freq_func = mobipass_set_freq;
|
||||||
|
device->trx_set_gains_func = mobipass_set_gains;
|
||||||
|
device->trx_write_func = mobipass_write;
|
||||||
|
device->trx_read_func = mobipass_read;
|
||||||
|
|
||||||
|
device->priv = mobi;
|
||||||
|
|
||||||
|
mobi->eth.if_name = strdup(eth_params->local_if_name);
|
||||||
|
if (mobi->eth.if_name == NULL) abort();
|
||||||
|
|
||||||
|
if (sscanf(eth_params->my_addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||||
|
&mobi->eth_local[0],
|
||||||
|
&mobi->eth_local[1],
|
||||||
|
&mobi->eth_local[2],
|
||||||
|
&mobi->eth_local[3],
|
||||||
|
&mobi->eth_local[4],
|
||||||
|
&mobi->eth_local[5]) != 6) {
|
||||||
|
printf("mobipass: ERROR: bad local ethernet address '%s', check configuration file\n",
|
||||||
|
eth_params->my_addr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(eth_params->remote_addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||||
|
&mobi->eth_remote[0],
|
||||||
|
&mobi->eth_remote[1],
|
||||||
|
&mobi->eth_remote[2],
|
||||||
|
&mobi->eth_remote[3],
|
||||||
|
&mobi->eth_remote[4],
|
||||||
|
&mobi->eth_remote[5]) != 6) {
|
||||||
|
printf("mobipass: ERROR: bad remote ethernet address '%s', check configuration file\n",
|
||||||
|
eth_params->remote_addr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note: this only works for 50 PRBs */
|
||||||
|
mobi->samples_per_1024_frames = 7680*2*10*1024;
|
||||||
|
|
||||||
|
/* TX starts at subframe 4, let's pretend we are at the right position */
|
||||||
|
/* note: this only works for 50 PRBs */
|
||||||
|
mobi->mobipass_write_last_timestamp = 4*7680*2-640;
|
||||||
|
|
||||||
|
/* device specific */
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* this is useless, I think */
|
||||||
|
if (device->host_type == BBU_HOST) {
|
||||||
|
/*Note scheduling advance values valid only for case 7680000 */
|
||||||
|
switch ((int)openair0_cfg[0].sample_rate) {
|
||||||
|
case 30720000:
|
||||||
|
openair0_cfg[0].samples_per_packet = 3840;
|
||||||
|
break;
|
||||||
|
case 23040000:
|
||||||
|
openair0_cfg[0].samples_per_packet = 2880;
|
||||||
|
break;
|
||||||
|
case 15360000:
|
||||||
|
openair0_cfg[0].samples_per_packet = 1920;
|
||||||
|
break;
|
||||||
|
case 7680000:
|
||||||
|
openair0_cfg[0].samples_per_packet = 960;
|
||||||
|
break;
|
||||||
|
case 1920000:
|
||||||
|
openair0_cfg[0].samples_per_packet = 240;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("mobipass: ERROR: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
|
||||||
|
exit(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device->openair0_cfg=&openair0_cfg[0];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
printf("mobipass: ERROR: bad configuration file?\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "queues.h"
|
||||||
|
#include "mobipass.h"
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* time begin */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
static void init_time(mobipass_state_t *mobi)
|
||||||
|
{
|
||||||
|
struct timespec now;
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now)) abort();
|
||||||
|
mobi->t0 = (uint64_t)now.tv_sec * (uint64_t)1000000000 + (uint64_t)now.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called before sending data to mobipass
|
||||||
|
* waits if called too early with respect to system clock
|
||||||
|
* does not wait more than 1ms in any case
|
||||||
|
*/
|
||||||
|
static void synch_time(mobipass_state_t *mobi, uint32_t ts)
|
||||||
|
{
|
||||||
|
if (ts < mobi->synch_time_last_ts) mobi->synch_time_mega_ts++;
|
||||||
|
mobi->synch_time_last_ts = ts;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now)) abort();
|
||||||
|
|
||||||
|
uint64_t tnow;
|
||||||
|
tnow = (uint64_t)now.tv_sec * (uint64_t)1000000000 + (uint64_t)now.tv_nsec;
|
||||||
|
|
||||||
|
uint64_t cur = tnow - mobi->t0;
|
||||||
|
|
||||||
|
/* 15360000 samples/second, in nanoseconds:
|
||||||
|
* = 15360000 / 1000000000 = 1536 / 100000 = 48 / 3125*/
|
||||||
|
|
||||||
|
uint64_t ts_ns = ((uint64_t)ts + mobi->synch_time_mega_ts * (uint64_t)mobi->samples_per_1024_frames) * (uint64_t)3125 / (uint64_t)48;
|
||||||
|
|
||||||
|
/* TODO: if cur is way higher than ts_ns, we are very late, log something? */
|
||||||
|
if (cur >= ts_ns) return;
|
||||||
|
|
||||||
|
uint64_t delta = ts_ns - cur;
|
||||||
|
/* don't sleep more than 1 ms */
|
||||||
|
if (delta > 1000*1000) delta = 1000*1000;
|
||||||
|
delta = delta/1000;
|
||||||
|
if (delta) usleep(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* time end */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
struct ethernet_header {
|
||||||
|
unsigned char dst[6];
|
||||||
|
unsigned char src[6];
|
||||||
|
uint16_t packet_type;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
struct mobipass_header {
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t fifo_status;
|
||||||
|
unsigned char seqno;
|
||||||
|
unsigned char ack;
|
||||||
|
uint32_t word0;
|
||||||
|
uint32_t timestamp;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
static void do_receive(mobipass_state_t *mobi, unsigned char *b)
|
||||||
|
{
|
||||||
|
if (recv(mobi->sock, b, 14+14+1280, 0) != 14+14+1280) { perror("recv"); exit(1); }
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)(b+14);
|
||||||
|
mh->timestamp = htonl((ntohl(mh->timestamp)-45378/*40120*/) % mobi->samples_per_1024_frames);
|
||||||
|
//printf("recv timestamp %u\n", ntohl(mh->timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* receiver thread */
|
||||||
|
static void *receiver(void *_mobi)
|
||||||
|
{
|
||||||
|
mobipass_state_t *mobi = _mobi;
|
||||||
|
unsigned char receive_packet[14 + 14 + 1280];
|
||||||
|
while (1) {
|
||||||
|
do_receive(mobi, receive_packet);
|
||||||
|
enqueue_from_mobipass(mobi->qstate, receive_packet);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_send(mobipass_state_t *mobi, int seqno, uint32_t ts,
|
||||||
|
unsigned char *packet)
|
||||||
|
{
|
||||||
|
struct ethernet_header *eh = (struct ethernet_header *)packet;
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)(packet+14);
|
||||||
|
|
||||||
|
ts %= mobi->samples_per_1024_frames;
|
||||||
|
//printf("SEND seqno %d ts %d\n", seqno, ts);
|
||||||
|
|
||||||
|
memcpy(eh->dst, mobi->eth_remote, 6);
|
||||||
|
memcpy(eh->src, mobi->eth_local, 6);
|
||||||
|
|
||||||
|
eh->packet_type = htons(0xbffe);
|
||||||
|
|
||||||
|
mh->flags = 0;
|
||||||
|
mh->fifo_status = 0;
|
||||||
|
mh->seqno = seqno;
|
||||||
|
mh->ack = 0;
|
||||||
|
mh->word0 = 0;
|
||||||
|
mh->timestamp = htonl(ts);
|
||||||
|
|
||||||
|
synch_time(mobi, ts);
|
||||||
|
|
||||||
|
if (send(mobi->sock, packet, 14+14+1280, 0) != 14+14+1280) { perror("send"); exit(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sender thread */
|
||||||
|
static void *sender(void *_mobi)
|
||||||
|
{
|
||||||
|
mobipass_state_t *mobi = _mobi;
|
||||||
|
unsigned char packet[14 + 14 + 1280];
|
||||||
|
uint32_t ts = 0;
|
||||||
|
unsigned char seqno = 0;
|
||||||
|
while (1) {
|
||||||
|
dequeue_to_mobipass(mobi->qstate, ts, packet);
|
||||||
|
do_send(mobi, seqno, ts, packet);
|
||||||
|
seqno++;
|
||||||
|
ts += 640;
|
||||||
|
ts %= mobi->samples_per_1024_frames;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void new_thread(void *(*f)(void *), void *data)
|
||||||
|
{
|
||||||
|
pthread_t t;
|
||||||
|
pthread_attr_t att;
|
||||||
|
|
||||||
|
if (pthread_attr_init(&att))
|
||||||
|
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||||
|
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||||
|
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||||
|
if (pthread_attr_setstacksize(&att, 10000000))
|
||||||
|
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
|
||||||
|
if (pthread_create(&t, &att, f, data))
|
||||||
|
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||||
|
if (pthread_attr_destroy(&att))
|
||||||
|
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_mobipass(mobipass_state_t *mobi)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char data[14+14+640];
|
||||||
|
memset(data, 0, 14+14+640);
|
||||||
|
|
||||||
|
init_time(mobi);
|
||||||
|
|
||||||
|
mobi->qstate = init_queues(mobi->samples_per_1024_frames);
|
||||||
|
|
||||||
|
for (i = 0; i < 24*4; i++) {
|
||||||
|
uint32_t timestamp = i*640;
|
||||||
|
unsigned char seqno = i;
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)(data+14);
|
||||||
|
mh->seqno = seqno;
|
||||||
|
mh->timestamp = htonl(timestamp);
|
||||||
|
enqueue_to_mobipass(mobi->qstate, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
mobi->sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
|
||||||
|
if (mobi->sock == -1) { perror("socket"); exit(1); }
|
||||||
|
|
||||||
|
/* get if index */
|
||||||
|
struct ifreq if_index;
|
||||||
|
memset(&if_index, 0, sizeof(struct ifreq));
|
||||||
|
strcpy(if_index.ifr_name, mobi->eth.if_name);
|
||||||
|
if (ioctl(mobi->sock, SIOCGIFINDEX, &if_index)<0) {perror("SIOCGIFINDEX");exit(1);}
|
||||||
|
|
||||||
|
struct sockaddr_ll local_addr;
|
||||||
|
local_addr.sll_family = AF_PACKET;
|
||||||
|
local_addr.sll_ifindex = if_index.ifr_ifindex;
|
||||||
|
local_addr.sll_protocol = htons(0xbffe);
|
||||||
|
local_addr.sll_halen = ETH_ALEN;
|
||||||
|
local_addr.sll_pkttype = PACKET_OTHERHOST;
|
||||||
|
|
||||||
|
if (bind(mobi->sock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_ll))<0)
|
||||||
|
{ perror("bind"); exit(1); }
|
||||||
|
|
||||||
|
new_thread(receiver, mobi);
|
||||||
|
new_thread(sender, mobi);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef _MOBIPASS_H_
|
||||||
|
#define _MOBIPASS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ethernet_lib.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* this has to come first */
|
||||||
|
eth_state_t eth;
|
||||||
|
|
||||||
|
void *qstate;
|
||||||
|
|
||||||
|
uint8_t eth_local[6];
|
||||||
|
uint8_t eth_remote[6];
|
||||||
|
|
||||||
|
int samples_per_1024_frames;
|
||||||
|
|
||||||
|
/* variables used by the function interface.c:mobipass_read */
|
||||||
|
uint32_t mobipass_read_ts;
|
||||||
|
unsigned char mobipass_read_seqno;
|
||||||
|
|
||||||
|
/* variables used by the function interface.c:mobipass_write */
|
||||||
|
uint32_t mobipass_write_last_timestamp;
|
||||||
|
|
||||||
|
/* variables used by the function mobipass.c:[init_time|synch_time] */
|
||||||
|
uint64_t t0;
|
||||||
|
|
||||||
|
/* variables used by the function mobipass.c:synch_time */
|
||||||
|
uint32_t synch_time_last_ts;
|
||||||
|
uint64_t synch_time_mega_ts;
|
||||||
|
|
||||||
|
/* sock is used in mobipass.c */
|
||||||
|
int sock;
|
||||||
|
} mobipass_state_t;
|
||||||
|
|
||||||
|
void init_mobipass(mobipass_state_t *mobi);
|
||||||
|
|
||||||
|
#endif /* _MOBIPASS_H_ */
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
#include "queues.h"
|
||||||
|
#include "mobipass.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define QSIZE 10000
|
||||||
|
|
||||||
|
struct mobipass_header {
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t fifo_status;
|
||||||
|
unsigned char seqno;
|
||||||
|
unsigned char ack;
|
||||||
|
uint32_t word0;
|
||||||
|
uint32_t timestamp;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
struct queue {
|
||||||
|
unsigned char buf[QSIZE][14+14+640*2];
|
||||||
|
volatile int start;
|
||||||
|
volatile int len;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct queue to_mobipass;
|
||||||
|
struct queue from_mobipass;
|
||||||
|
int samples_per_1024_frames;
|
||||||
|
|
||||||
|
/* variables used by dequeue_from_mobipass */
|
||||||
|
int dequeue_from_mobipass_seqno;
|
||||||
|
|
||||||
|
/* variables used to manage logging of "missing samples"
|
||||||
|
* coming from mobipass. (Yes, this can happen, mostly
|
||||||
|
* at startup.)
|
||||||
|
* This idea is to print some logs, but not too much to
|
||||||
|
* flood stdout. (This is already a bad idea to call
|
||||||
|
* printf in a 'realtime' thread.)
|
||||||
|
*/
|
||||||
|
int no_sample_log_running;
|
||||||
|
uint32_t no_sample_log_start_sample;
|
||||||
|
uint32_t no_sample_log_next_sample;
|
||||||
|
} queue_state_t;
|
||||||
|
|
||||||
|
static void enqueue(void *data, struct queue *q)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
if (pthread_mutex_lock(&q->mutex)) abort();
|
||||||
|
if (q->len == QSIZE) {
|
||||||
|
printf("mobipass: WARNING: enqueue: full\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = (q->start + q->len) % QSIZE;
|
||||||
|
memcpy(q->buf[pos], data, 14+14+640*2);
|
||||||
|
q->len++;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (pthread_cond_signal(&q->cond)) abort();
|
||||||
|
if (pthread_mutex_unlock(&q->mutex)) abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void enqueue_to_mobipass(void *_qstate, void *data)
|
||||||
|
{
|
||||||
|
queue_state_t *qstate = _qstate;
|
||||||
|
enqueue(data, &qstate->to_mobipass);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dequeue_to_mobipass(void *_qstate, uint32_t timestamp, void *data)
|
||||||
|
{
|
||||||
|
queue_state_t *qstate = _qstate;
|
||||||
|
if (pthread_mutex_lock(&qstate->to_mobipass.mutex)) abort();
|
||||||
|
while (qstate->to_mobipass.len == 0) {
|
||||||
|
if (pthread_cond_wait(&qstate->to_mobipass.cond, &qstate->to_mobipass.mutex)) abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, qstate->to_mobipass.buf[qstate->to_mobipass.start], 14+14+640*2);
|
||||||
|
qstate->to_mobipass.len--;
|
||||||
|
qstate->to_mobipass.start = (qstate->to_mobipass.start + 1) % QSIZE;
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(&qstate->to_mobipass.mutex)) abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void enqueue_from_mobipass(void *_qstate, void *data)
|
||||||
|
{
|
||||||
|
queue_state_t *qstate = _qstate;
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)((char*)data+14);
|
||||||
|
mh->timestamp = htonl(ntohl(mh->timestamp) % qstate->samples_per_1024_frames);
|
||||||
|
//printf("from mobipass! timestamp %u seqno %d\n", ntohl(mh->timestamp), mh->seqno);
|
||||||
|
enqueue(data, &qstate->from_mobipass);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_timestamps(uint32_t a, uint32_t b, int samples_per_1024_frames)
|
||||||
|
{
|
||||||
|
if (a == b) return 0;
|
||||||
|
if (a < b) {
|
||||||
|
if (b-a > samples_per_1024_frames/2) return 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a-b > samples_per_1024_frames/2) return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* missing samples logging management begin */
|
||||||
|
/*************************************************/
|
||||||
|
|
||||||
|
static void log_flush(queue_state_t *qstate)
|
||||||
|
{
|
||||||
|
/* print now if there is something to print */
|
||||||
|
if (qstate->no_sample_log_running == 0)
|
||||||
|
return;
|
||||||
|
qstate->no_sample_log_running = 0;
|
||||||
|
printf("mobipass: WARNING: missing samples [%u-%u]\n",
|
||||||
|
qstate->no_sample_log_start_sample,
|
||||||
|
(uint32_t)(qstate->no_sample_log_next_sample-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_missed_sample(queue_state_t *qstate, uint32_t timestamp)
|
||||||
|
{
|
||||||
|
/* collect data, print if there is a discontinuity */
|
||||||
|
if (qstate->no_sample_log_running == 0 ||
|
||||||
|
timestamp != qstate->no_sample_log_next_sample) {
|
||||||
|
log_flush(qstate);
|
||||||
|
qstate->no_sample_log_start_sample = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
qstate->no_sample_log_next_sample = timestamp+1;
|
||||||
|
qstate->no_sample_log_running = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_flush_if_old(queue_state_t *qstate, uint32_t timestamp)
|
||||||
|
{
|
||||||
|
/* log every second (more or less), if we have to */
|
||||||
|
/* note that if mobipass stopped, it may take much more
|
||||||
|
* than one second to log, due to the sleeps done while
|
||||||
|
* waiting for samples (that never come)
|
||||||
|
*/
|
||||||
|
if (qstate->no_sample_log_running == 1 &&
|
||||||
|
labs(timestamp-qstate->no_sample_log_start_sample) > qstate->samples_per_1024_frames/10)
|
||||||
|
log_flush(qstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* missing samples logging management end */
|
||||||
|
/*************************************************/
|
||||||
|
|
||||||
|
/* to be called with lock on */
|
||||||
|
static void get_sample_from_mobipass(queue_state_t *qstate, char *I, char *Q, uint32_t timestamp)
|
||||||
|
{
|
||||||
|
unsigned char *b = NULL;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
struct mobipass_header *mh = NULL;
|
||||||
|
uint32_t packet_timestamp = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
uint32_t old_start = qstate->from_mobipass.start;
|
||||||
|
uint32_t old_len = qstate->from_mobipass.len;
|
||||||
|
b = qstate->from_mobipass.buf[qstate->from_mobipass.start];
|
||||||
|
mh = (struct mobipass_header *)(b+14);
|
||||||
|
uint32_t old_pts = qstate->from_mobipass.len ? ntohl(mh->timestamp) : -1;
|
||||||
|
b=NULL;
|
||||||
|
mh=NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (qstate->from_mobipass.len) {
|
||||||
|
b = qstate->from_mobipass.buf[qstate->from_mobipass.start];
|
||||||
|
mh = (struct mobipass_header *)(b+14);
|
||||||
|
data = b + 14*2;
|
||||||
|
packet_timestamp = ntohl(mh->timestamp);
|
||||||
|
if (cmp_timestamps(timestamp, packet_timestamp, qstate->samples_per_1024_frames) < 0) goto nodata;
|
||||||
|
if (cmp_timestamps(timestamp, (packet_timestamp+640) % qstate->samples_per_1024_frames, qstate->samples_per_1024_frames) < 0) break;
|
||||||
|
qstate->from_mobipass.len--;
|
||||||
|
qstate->from_mobipass.start = (qstate->from_mobipass.start+1) % QSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qstate->from_mobipass.len == 0) goto nodata;
|
||||||
|
|
||||||
|
if (timestamp == (packet_timestamp + 639) % qstate->samples_per_1024_frames) {
|
||||||
|
qstate->from_mobipass.len--;
|
||||||
|
qstate->from_mobipass.start = (qstate->from_mobipass.start+1) % QSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timestamp < packet_timestamp) timestamp += qstate->samples_per_1024_frames;
|
||||||
|
|
||||||
|
*I = data[(timestamp - packet_timestamp) * 2];
|
||||||
|
*Q = data[(timestamp - packet_timestamp) * 2 + 1];
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
nodata:
|
||||||
|
*I = 0;
|
||||||
|
*Q = 0;
|
||||||
|
|
||||||
|
log_missed_sample(qstate, timestamp);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("no sample timestamp %u pt %u start %d old_start %d old_pt %u len %d old len %d\n", timestamp, packet_timestamp, qstate->from_mobipass.start, old_start, old_pts, qstate->from_mobipass.len, old_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* doesn't work with delay more than 1s */
|
||||||
|
static void wait_for_data(pthread_cond_t *cond, pthread_mutex_t *mutex, int delay_us)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
struct timespec target;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
target.tv_sec = now.tv_sec;
|
||||||
|
target.tv_nsec = (now.tv_usec + delay_us) * 1000;
|
||||||
|
if (target.tv_nsec >= 1000 * 1000 * 1000) { target.tv_nsec -= 1000 * 1000 * 1000; target.tv_sec++; }
|
||||||
|
int err = pthread_cond_timedwait(cond, mutex, &target);
|
||||||
|
if (err != 0 && err != ETIMEDOUT) { printf("mobipass: ERROR: pthread_cond_timedwait: err (%d) %s\n", err, strerror(err)); abort(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* don't block infinitely when waiting for data
|
||||||
|
* if waiting for too long, just return some zeros
|
||||||
|
*/
|
||||||
|
void dequeue_from_mobipass(void *_qstate, uint32_t timestamp, void *data)
|
||||||
|
{
|
||||||
|
queue_state_t *qstate = _qstate;
|
||||||
|
int i;
|
||||||
|
// int ts = timestamp;
|
||||||
|
int waiting_allowed;
|
||||||
|
|
||||||
|
if (pthread_mutex_lock(&qstate->from_mobipass.mutex)) abort();
|
||||||
|
|
||||||
|
if (qstate->from_mobipass.len == 0) {
|
||||||
|
//printf("sleep 1\n");
|
||||||
|
wait_for_data(&qstate->from_mobipass.cond, &qstate->from_mobipass.mutex, 2000); //1000/3);
|
||||||
|
}
|
||||||
|
|
||||||
|
waiting_allowed = qstate->from_mobipass.len != 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 640*2; i+=2) {
|
||||||
|
if (qstate->from_mobipass.len == 0 && waiting_allowed) {
|
||||||
|
//printf("sleep 2\n");
|
||||||
|
wait_for_data(&qstate->from_mobipass.cond, &qstate->from_mobipass.mutex, 2000); //1000/3);
|
||||||
|
waiting_allowed = qstate->from_mobipass.len != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_sample_from_mobipass(qstate, (char*)data + 14*2 + i, (char*)data + 14*2 + i+1, timestamp % qstate->samples_per_1024_frames);
|
||||||
|
timestamp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_flush_if_old(qstate, timestamp);
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(&qstate->from_mobipass.mutex)) abort();
|
||||||
|
|
||||||
|
struct mobipass_header *mh = (struct mobipass_header *)(((char *)data) + 14);
|
||||||
|
mh->flags = 0;
|
||||||
|
mh->fifo_status = 0;
|
||||||
|
mh->seqno = qstate->dequeue_from_mobipass_seqno++;
|
||||||
|
mh->ack = 0;
|
||||||
|
mh->word0 = 0;
|
||||||
|
mh->timestamp = htonl(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *init_queues(int samples_per_1024_frames)
|
||||||
|
{
|
||||||
|
queue_state_t *q;
|
||||||
|
q = malloc(sizeof(queue_state_t));
|
||||||
|
if (q == NULL) abort();
|
||||||
|
memset(q, 0, sizeof(queue_state_t));
|
||||||
|
|
||||||
|
if (pthread_mutex_init(&q->to_mobipass.mutex, NULL)) abort();
|
||||||
|
if (pthread_mutex_init(&q->from_mobipass.mutex, NULL)) abort();
|
||||||
|
if (pthread_cond_init(&q->to_mobipass.cond, NULL)) abort();
|
||||||
|
if (pthread_cond_init(&q->from_mobipass.cond, NULL)) abort();
|
||||||
|
|
||||||
|
q->samples_per_1024_frames = samples_per_1024_frames;
|
||||||
|
|
||||||
|
return q;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _QUEUES_H_
|
||||||
|
#define _QUEUES_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void enqueue_to_mobipass(void *qstate, void *data);
|
||||||
|
void dequeue_to_mobipass(void *qstate, uint32_t timestamp, void *data);
|
||||||
|
|
||||||
|
void enqueue_from_mobipass(void *qstate, void *receive_packet);
|
||||||
|
void dequeue_from_mobipass(void *qstate, uint32_t timestamp, void *data);
|
||||||
|
|
||||||
|
/* returns a queue state type, as opaque data structure */
|
||||||
|
void *init_queues(int samples_per_1024_frames);
|
||||||
|
|
||||||
|
#endif /* _QUEUES_H_ */
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
Active_eNBs = ( "eNB_Eurecom_LTEBox");
|
||||||
|
# Asn1_verbosity, choice in: none, info, annoying
|
||||||
|
Asn1_verbosity = "none";
|
||||||
|
|
||||||
|
eNBs =
|
||||||
|
(
|
||||||
|
{
|
||||||
|
////////// Identification parameters:
|
||||||
|
eNB_ID = 0xe00;
|
||||||
|
|
||||||
|
cell_type = "CELL_MACRO_ENB";
|
||||||
|
|
||||||
|
eNB_name = "eNB_Eurecom_LTEBox";
|
||||||
|
|
||||||
|
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||||
|
tracking_area_code = "1";
|
||||||
|
|
||||||
|
mobile_country_code = "208";
|
||||||
|
|
||||||
|
mobile_network_code = "92";
|
||||||
|
|
||||||
|
////////// Physical parameters:
|
||||||
|
|
||||||
|
component_carriers = (
|
||||||
|
// second carrier-> for ERCOM
|
||||||
|
{
|
||||||
|
node_function = "eNodeB_3GPP_BBU" # should be verified
|
||||||
|
//node_function = "NGFI_RCC_IF5" # should be verified
|
||||||
|
node_timing = "synch_to_mobipass_standalone";
|
||||||
|
//node_timing = "synch_to_ext_device";
|
||||||
|
node_synch_ref = 0; #should
|
||||||
|
frame_type = "FDD";
|
||||||
|
tdd_config = 3;
|
||||||
|
tdd_config_s = 0;
|
||||||
|
prefix_type = "NORMAL";
|
||||||
|
eutra_band = 7;
|
||||||
|
downlink_frequency = 2660000000L;
|
||||||
|
uplink_frequency_offset = -120000000;
|
||||||
|
Nid_cell = 0;
|
||||||
|
N_RB_DL = 50;
|
||||||
|
Nid_cell_mbsfn = 0;
|
||||||
|
nb_antenna_ports = 1;
|
||||||
|
nb_antennas_tx = 1;
|
||||||
|
nb_antennas_rx = 1;
|
||||||
|
tx_gain = 90;
|
||||||
|
rx_gain = 125;
|
||||||
|
prach_root = 0;
|
||||||
|
prach_config_index = 0;
|
||||||
|
prach_high_speed = "DISABLE";
|
||||||
|
prach_zero_correlation = 3;
|
||||||
|
prach_freq_offset = 2;
|
||||||
|
pucch_delta_shift = 1;
|
||||||
|
pucch_nRB_CQI = 0;
|
||||||
|
pucch_nCS_AN = 0;
|
||||||
|
pucch_n1_AN = 32;
|
||||||
|
pdsch_referenceSignalPower = -29;
|
||||||
|
pdsch_p_b = 0;
|
||||||
|
pusch_n_SB = 1;
|
||||||
|
pusch_enable64QAM = "DISABLE";
|
||||||
|
pusch_hoppingMode = "interSubFrame";
|
||||||
|
pusch_hoppingOffset = 0;
|
||||||
|
pusch_groupHoppingEnabled = "ENABLE";
|
||||||
|
pusch_groupAssignment = 0;
|
||||||
|
pusch_sequenceHoppingEnabled = "DISABLE";
|
||||||
|
pusch_nDMRS1 = 1;
|
||||||
|
phich_duration = "NORMAL";
|
||||||
|
phich_resource = "ONESIXTH";
|
||||||
|
srs_enable = "DISABLE";
|
||||||
|
/* srs_BandwidthConfig =;
|
||||||
|
srs_SubframeConfig =;
|
||||||
|
srs_ackNackST =;
|
||||||
|
srs_MaxUpPts =;*/
|
||||||
|
|
||||||
|
pusch_p0_Nominal = -96;
|
||||||
|
pusch_alpha = "AL1";
|
||||||
|
pucch_p0_Nominal = -100;
|
||||||
|
msg3_delta_Preamble = 6;
|
||||||
|
pucch_deltaF_Format1 = "deltaF2";
|
||||||
|
pucch_deltaF_Format1b = "deltaF3";
|
||||||
|
pucch_deltaF_Format2 = "deltaF0";
|
||||||
|
pucch_deltaF_Format2a = "deltaF0";
|
||||||
|
pucch_deltaF_Format2b = "deltaF0";
|
||||||
|
|
||||||
|
rach_numberOfRA_Preambles = 64;
|
||||||
|
rach_preamblesGroupAConfig = "DISABLE";
|
||||||
|
/*
|
||||||
|
rach_sizeOfRA_PreamblesGroupA = ;
|
||||||
|
rach_messageSizeGroupA = ;
|
||||||
|
rach_messagePowerOffsetGroupB = ;
|
||||||
|
*/
|
||||||
|
rach_powerRampingStep = 4;
|
||||||
|
rach_preambleInitialReceivedTargetPower = -108;
|
||||||
|
rach_preambleTransMax = 10;
|
||||||
|
rach_raResponseWindowSize = 10;
|
||||||
|
rach_macContentionResolutionTimer = 48;
|
||||||
|
rach_maxHARQ_Msg3Tx = 4;
|
||||||
|
|
||||||
|
pcch_default_PagingCycle = 128;
|
||||||
|
pcch_nB = "oneT";
|
||||||
|
bcch_modificationPeriodCoeff = 2;
|
||||||
|
ue_TimersAndConstants_t300 = 1000;
|
||||||
|
ue_TimersAndConstants_t301 = 1000;
|
||||||
|
ue_TimersAndConstants_t310 = 1000;
|
||||||
|
ue_TimersAndConstants_t311 = 10000;
|
||||||
|
ue_TimersAndConstants_n310 = 20;
|
||||||
|
ue_TimersAndConstants_n311 = 1;
|
||||||
|
|
||||||
|
ue_TransmissionMode = 1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
srb1_parameters :
|
||||||
|
{
|
||||||
|
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
|
||||||
|
timer_poll_retransmit = 80;
|
||||||
|
|
||||||
|
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
|
||||||
|
timer_reordering = 35;
|
||||||
|
|
||||||
|
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
|
||||||
|
timer_status_prohibit = 0;
|
||||||
|
|
||||||
|
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
|
||||||
|
poll_pdu = 4;
|
||||||
|
|
||||||
|
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
|
||||||
|
poll_byte = 99999;
|
||||||
|
|
||||||
|
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
|
||||||
|
max_retx_threshold = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------- SCTP definitions
|
||||||
|
SCTP :
|
||||||
|
{
|
||||||
|
# Number of streams to use in input/output
|
||||||
|
SCTP_INSTREAMS = 2;
|
||||||
|
SCTP_OUTSTREAMS = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////// MME parameters:
|
||||||
|
mme_ip_address = ( { ipv4 = "127.0.0.3";
|
||||||
|
ipv6 = "192:168:30::17";
|
||||||
|
active = "yes";
|
||||||
|
preference = "ipv4";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
NETWORK_INTERFACES :
|
||||||
|
{
|
||||||
|
|
||||||
|
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
||||||
|
ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24";
|
||||||
|
ENB_INTERFACE_NAME_FOR_S1U = "lo";
|
||||||
|
ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24";
|
||||||
|
ENB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
rrh_gw_config = (
|
||||||
|
//second config for Ercom
|
||||||
|
{
|
||||||
|
local_if_name = "eth1.300";
|
||||||
|
remote_address = "00:21:5e:91:5c:7e"; # should be updated with ERCOM's MAC
|
||||||
|
local_address = "f0:1f:af:db:b9:c8";
|
||||||
|
local_port = 50000; #for raw option local port must be the same to remote
|
||||||
|
remote_port = 50000;
|
||||||
|
rrh_gw_active = "yes";
|
||||||
|
tr_preference = "raw_if5_mobipass";
|
||||||
|
rf_preference = "usrp_b200";
|
||||||
|
iq_txshift = 0;
|
||||||
|
tx_sample_advance = 80;
|
||||||
|
tx_scheduling_advance = 9;
|
||||||
|
if_compression = "None"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
log_config :
|
||||||
|
{
|
||||||
|
global_log_level ="info";
|
||||||
|
global_log_verbosity ="medium";
|
||||||
|
hw_log_level ="info";
|
||||||
|
hw_log_verbosity ="medium";
|
||||||
|
phy_log_level ="info";
|
||||||
|
phy_log_verbosity ="medium";
|
||||||
|
mac_log_level ="info";
|
||||||
|
mac_log_verbosity ="high";
|
||||||
|
rlc_log_level ="info";
|
||||||
|
rlc_log_verbosity ="medium";
|
||||||
|
pdcp_log_level ="info";
|
||||||
|
pdcp_log_verbosity ="medium";
|
||||||
|
rrc_log_level ="info";
|
||||||
|
rrc_log_verbosity ="medium";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -433,6 +433,14 @@ void tx_fh_if5_mobipass(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
|
|||||||
send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS);
|
send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tx_fh_if5_mobipass_standalone(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff );
|
||||||
|
if ((eNB->frame_parms.frame_type==FDD) ||
|
||||||
|
((eNB->frame_parms.frame_type==TDD) &&
|
||||||
|
(subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))
|
||||||
|
send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS);
|
||||||
|
}
|
||||||
|
|
||||||
void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
|
void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
|
||||||
if ((eNB->frame_parms.frame_type==FDD) ||
|
if ((eNB->frame_parms.frame_type==FDD) ||
|
||||||
((eNB->frame_parms.frame_type==TDD) &&
|
((eNB->frame_parms.frame_type==TDD) &&
|
||||||
@@ -1097,6 +1105,38 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rx_fh_if5_mobipass_standalone(PHY_VARS_eNB *eNB,int *frame, int *subframe)
|
||||||
|
{
|
||||||
|
LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
|
||||||
|
eNB_proc_t *proc = &eNB->proc;
|
||||||
|
|
||||||
|
recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_MOBIPASS);
|
||||||
|
//printf("in rx_fh_if5_mobipass timestamp from recv_IF5 %ld\n", proc->timestamp_rx);
|
||||||
|
|
||||||
|
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
|
||||||
|
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
|
||||||
|
// T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
|
||||||
|
|
||||||
|
if (proc->first_rx == 0) {
|
||||||
|
if (proc->subframe_rx != *subframe){
|
||||||
|
LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe);
|
||||||
|
exit_fun("Exiting");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc->frame_rx != *frame) {
|
||||||
|
LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
|
||||||
|
exit_fun("Exiting");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proc->first_rx--;
|
||||||
|
*frame = proc->frame_rx;
|
||||||
|
*subframe = proc->subframe_rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
|
||||||
|
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
|
||||||
|
}
|
||||||
|
|
||||||
void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
|
void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
|
||||||
|
|
||||||
@@ -2132,6 +2172,11 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
|
|||||||
eNB->fh_asynch = fh_if5_asynch_UL;
|
eNB->fh_asynch = fh_if5_asynch_UL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if (eNB->node_timing == synch_to_mobipass_standalone) {
|
||||||
|
eNB->tx_fh = tx_fh_if5_mobipass_standalone;
|
||||||
|
eNB->rx_fh = rx_fh_if5_mobipass_standalone;
|
||||||
|
eNB->fh_asynch = NULL;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
eNB->tx_fh = tx_fh_if5;
|
eNB->tx_fh = tx_fh_if5;
|
||||||
eNB->rx_fh = rx_fh_if5;
|
eNB->rx_fh = rx_fh_if5;
|
||||||
|
|||||||
Reference in New Issue
Block a user