diff --git a/matlab/common/read_trace_uint.m b/matlab/common/read_trace_uint.m new file mode 100644 index 000000000..cdaeea99a --- /dev/null +++ b/matlab/common/read_trace_uint.m @@ -0,0 +1,19 @@ +function [ tti, values ] = read_trace_uint( filename, count ) + + [tidin msg]=fopen(filename,'r'); + if (tidin==-1) + fprintf('error opening %s: %s\n',filename, msg); + out=[]; + return + end + + if (nargin==1) + count=inf; + end + + x=fread(tidin,2*count,'uint'); + i=1:2:length(x); + tti=x(i); + values=x(i+1); +end + diff --git a/srsapps/common/include/srsapps/common/threads.h b/srsapps/common/include/srsapps/common/threads.h index 2cebb77f7..f8ad2c43b 100644 --- a/srsapps/common/include/srsapps/common/threads.h +++ b/srsapps/common/include/srsapps/common/threads.h @@ -26,12 +26,14 @@ */ #include +#include #ifdef __cplusplus extern "C" { #endif bool threads_new_rt(pthread_t *thread, void *(*start_routine) (void*), void *arg); - bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu); + bool threads_new_rt_prio(pthread_t *thread, void *(*start_routine) (void*), void *arg, uint32_t prio_offset); + bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu, uint32_t prio_offset); void threads_print_self(); #ifdef __cplusplus diff --git a/srsapps/common/include/srsapps/common/trace.h b/srsapps/common/include/srsapps/common/trace.h new file mode 100644 index 000000000..af0f52a9b --- /dev/null +++ b/srsapps/common/include/srsapps/common/trace.h @@ -0,0 +1,98 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 The srsLTE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the srsLTE library. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + + +#include +#include +#include + +#ifndef TRACE_H +#define TRACE_H + +namespace srslte { + +template +class trace +{ +public: + + trace(uint32_t nof_elems_) : tti(nof_elems_), data(nof_elems_) { + rpm=0; + nof_elems=nof_elems_; + wrapped = false; + }; + void push_cur_time_us(uint32_t cur_tti) { + struct timeval t; + gettimeofday(&t, NULL); + elemType us = t.tv_sec*1e6+t.tv_usec; + push(cur_tti, us); + } + void push(uint32_t value_tti, elemType value) { + tti[rpm] = value_tti; + data[rpm] = value; + rpm++; + if (rpm >= nof_elems) { + rpm = 0; + wrapped = true; + } + } + bool writeToBinary(std::string filename) { + FILE *f = fopen(filename.c_str(), "w"); + if (f != NULL) { + uint32_t st=wrapped?(rpm+1):0; + do { + writeToBinaryValue(f, st++); + if (st >= nof_elems) { + st=0; + } + } while(st tti; + std::vector data; + uint32_t rpm; + uint32_t nof_elems; + bool wrapped; + + void writeToBinaryValue(FILE *f, uint32_t idx) { + fwrite(&tti[idx], 1, sizeof(uint32_t), f); + fwrite(&data[idx], 1, sizeof(elemType), f); + } + +}; + + +} + +#endif \ No newline at end of file diff --git a/srsapps/common/src/threads.c b/srsapps/common/src/threads.c index 25b5d42f6..408595f49 100644 --- a/srsapps/common/src/threads.c +++ b/srsapps/common/src/threads.c @@ -35,15 +35,19 @@ #include "srsapps/common/threads.h" bool threads_new_rt(pthread_t *thread, void *(*start_routine) (void*), void *arg) { - return threads_new_rt_cpu(thread, start_routine, arg, -1); + return threads_new_rt_prio(thread, start_routine, arg, 0); } -bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu) { +bool threads_new_rt_prio(pthread_t *thread, void *(*start_routine) (void*), void *arg, uint32_t prio_offset) { + return threads_new_rt_cpu(thread, start_routine, arg, -1, prio_offset); +} + +bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void *arg, int cpu, uint32_t prio_offset) { bool ret = false; pthread_attr_t attr; struct sched_param param; - param.sched_priority = sched_get_priority_max(SCHED_FIFO); + param.sched_priority = sched_get_priority_max(SCHED_FIFO) - prio_offset; pthread_attr_init(&attr); if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) { diff --git a/srsapps/radio/include/srsapps/radio/radio_uhd.h b/srsapps/radio/include/srsapps/radio/radio_uhd.h index e7b33e6e3..1b560220f 100644 --- a/srsapps/radio/include/srsapps/radio/radio_uhd.h +++ b/srsapps/radio/include/srsapps/radio/radio_uhd.h @@ -30,6 +30,7 @@ #include "srsapps/radio/radio.h" #include "srslte/srslte.h" #include "srslte/cuhd/cuhd.h" +#include "srsapps/common/trace.h" #ifndef RADIO_UHD_H #define RADIO_UHD_H @@ -42,6 +43,7 @@ namespace srslte { class radio_uhd : public radio { public: + radio_uhd() : tr_local_time(1024*10), tr_usrp_time(1024*10), tr_tx_time(1024*10), tr_is_eob(1024*10) {}; bool init(); bool init(char *args); bool init_agc(); @@ -67,15 +69,19 @@ namespace srslte { float get_tx_gain(); float get_rx_gain(); - + void start_trace(); + void write_trace(std::string filename); void start_rx(); void stop_rx(); private: + + void save_trace(uint32_t is_eob, srslte_timestamp_t *usrp_time); + void *uhd; static const double lo_offset = 8e6; // LO offset (in Hz) - static const double burst_settle_time = 0.4e-3; // Start of burst settle time (off->on RF transition time) + static const double burst_settle_time = 0.3e-3; // Start of burst settle time (off->on RF transition time) const static uint32_t burst_settle_max_samples = 12288; // 30.72 MHz is maximum frequency srslte_timestamp_t end_of_burst_time; @@ -84,6 +90,13 @@ namespace srslte { double burst_settle_time_rounded; // settle time rounded to sample time cf_t zeros[burst_settle_max_samples]; double cur_tx_srate; + + trace tr_local_time; + trace tr_usrp_time; + trace tr_tx_time; + trace tr_is_eob; + bool trace_enabled; + uint32_t my_tti; }; } diff --git a/srsapps/radio/src/radio_uhd.cc b/srsapps/radio/src/radio_uhd.cc index a5a0cd17a..9be56289a 100644 --- a/srsapps/radio/src/radio_uhd.cc +++ b/srsapps/radio/src/radio_uhd.cc @@ -92,18 +92,23 @@ void radio_uhd::get_time(srslte_timestamp_t *now) { bool radio_uhd::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { if (is_start_of_burst) { + if (burst_settle_samples != 0) { srslte_timestamp_t tx_time_pad; srslte_timestamp_copy(&tx_time_pad, &tx_time); srslte_timestamp_sub(&tx_time_pad, 0, burst_settle_time_rounded); + save_trace(1, &tx_time_pad); cuhd_send_timed2(uhd, zeros, burst_settle_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, false); } is_start_of_burst = false; - srslte_timestamp_copy(&end_of_burst_time, &tx_time); - srslte_timestamp_add(&end_of_burst_time, 0, nof_samples*cur_tx_srate); } - if (cuhd_send_timed2(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs, false, false) > 0) { + // Save possible end of burst time + srslte_timestamp_copy(&end_of_burst_time, &tx_time); + srslte_timestamp_add(&end_of_burst_time, 0, (double) nof_samples/cur_tx_srate); + + save_trace(0, &tx_time); + if (cuhd_send_timed2(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs, true, false) > 0) { return true; } else { return false; @@ -112,10 +117,36 @@ bool radio_uhd::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_tim bool radio_uhd::tx_end() { + save_trace(2, &end_of_burst_time); cuhd_send_timed2(uhd, zeros, burst_settle_samples, end_of_burst_time.full_secs, end_of_burst_time.frac_secs, false, true); is_start_of_burst = true; } +void radio_uhd::start_trace() { + trace_enabled = true; + my_tti = 0; +} + +void radio_uhd::write_trace(std::string filename) +{ + tr_local_time.writeToBinary(filename + ".local"); + tr_is_eob.writeToBinary(filename + ".eob"); + tr_usrp_time.writeToBinary(filename + ".usrp"); + tr_tx_time.writeToBinary(filename + ".tx"); +} + +void radio_uhd::save_trace(uint32_t is_eob, srslte_timestamp_t *tx_time) { + if (trace_enabled) { + tr_local_time.push_cur_time_us(my_tti); + srslte_timestamp_t usrp_time; + cuhd_get_time(uhd, &usrp_time.full_secs, &usrp_time.frac_secs); + tr_usrp_time.push(my_tti, srslte_timestamp_uint32(&usrp_time)); + tr_tx_time.push(my_tti, srslte_timestamp_uint32(tx_time)); + tr_is_eob.push(my_tti, is_eob); + my_tti++; + } +} + void radio_uhd::set_rx_freq(float freq) { cuhd_set_rx_freq(uhd, freq); diff --git a/srsapps/ue/mac/include/srsapps/ue/mac/mac.h b/srsapps/ue/mac/include/srsapps/ue/mac/mac.h index 739374c81..621390bdd 100644 --- a/srsapps/ue/mac/include/srsapps/ue/mac/mac.h +++ b/srsapps/ue/mac/include/srsapps/ue/mac/mac.h @@ -45,6 +45,8 @@ #include "srsapps/ue/mac/mux.h" #include "srsapps/ue/mac/demux.h" #include "srsapps/ue/mac/sdu_handler.h" +#include "srsapps/common/trace.h" + #ifndef UEMAC_H #define UEMAC_H @@ -57,7 +59,7 @@ typedef _Complex float cf_t; class mac : public timer_callback { public: - mac() : timers_db((uint32_t) NOF_MAC_TIMERS) {} + mac() : timers_db((uint32_t) NOF_MAC_TIMERS), tr_end_time(1024*10), tr_start_time(1024*10) {started=false;} bool init(phy *phy_h, tti_sync *ttisync, log *log_h); void stop(); int get_tti(); @@ -83,6 +85,9 @@ public: void reconfiguration(); void reset(); + void start_trace(); + void write_trace(std::string filename); + void timer_expired(uint32_t timer_id); enum { @@ -110,7 +115,7 @@ private: static void* mac_thread_fnc(void*); int tti; - bool started = false; + bool started; bool is_synchronized; uint16_t last_temporal_crnti; @@ -144,6 +149,12 @@ private: void setup_timers(); void timeAlignmentTimerExpire(); + trace tr_start_time; + trace tr_end_time; + bool tr_enabled; + void tr_log_start(uint32_t tti); + void tr_log_end(uint32_t tti); + }; } diff --git a/srsapps/ue/mac/src/mac.cc b/srsapps/ue/mac/src/mac.cc index 33908642d..8f93215a2 100644 --- a/srsapps/ue/mac/src/mac.cc +++ b/srsapps/ue/mac/src/mac.cc @@ -79,6 +79,32 @@ int mac::get_tti() } } +void mac::start_trace() +{ + tr_enabled = true; +} + +void mac::write_trace(std::string filename) +{ + tr_start_time.writeToBinary(filename + ".start"); + tr_end_time.writeToBinary(filename + ".end"); +} + +void mac::tr_log_start(uint32_t tti) +{ + if (tr_enabled) { + tr_start_time.push_cur_time_us(tti); + } +} + +void mac::tr_log_end(uint32_t tti) +{ + if (tr_enabled) { + tr_end_time.push_cur_time_us(tti); + } +} + + // Implement Section 5.8 void mac::reconfiguration() { @@ -164,7 +190,9 @@ void mac::main_radio_loop() { } if (is_synchronized) { /* Warning: Here order of invocation of procedures is important!! */ + tr_log_end(tti); tti = ttisync->wait(); + tr_log_start(tti); log_h->step(tti); // Step all procedures diff --git a/srsapps/ue/mac/test/mac_test.cc b/srsapps/ue/mac/test/mac_test.cc index cb76013ed..3ee4ed96d 100644 --- a/srsapps/ue/mac/test/mac_test.cc +++ b/srsapps/ue/mac/test/mac_test.cc @@ -27,6 +27,7 @@ #include +#include #include "liblte_rrc.h" #include "srsapps/radio/radio_uhd.h" @@ -46,6 +47,7 @@ typedef struct { float uhd_rx_gain; float uhd_tx_gain; int verbose; + bool do_trace; }prog_args_t; void args_default(prog_args_t *args) { @@ -54,19 +56,21 @@ void args_default(prog_args_t *args) { args->uhd_rx_gain = -1; // set to autogain args->uhd_tx_gain = -1; args->verbose = 0; + args->do_trace = false; } void usage(prog_args_t *args, char *prog) { - printf("Usage: %s [gv] -f rx_frequency (in Hz) -F tx_frequency (in Hz)\n", prog); + printf("Usage: %s [gGtv] -f rx_frequency (in Hz) -F tx_frequency (in Hz)\n", prog); printf("\t-g UHD RX gain [Default AGC]\n"); printf("\t-G UHD TX gain [Default same as RX gain (AGC)]\n"); + printf("\t-t Enable trace [Default disabled]\n"); printf("\t-v [increase verbosity, default none]\n"); } void parse_args(prog_args_t *args, int argc, char **argv) { int opt; args_default(args); - while ((opt = getopt(argc, argv, "gGfFv")) != -1) { + while ((opt = getopt(argc, argv, "gGftFv")) != -1) { switch (opt) { case 'g': args->uhd_rx_gain = atof(argv[optind]); @@ -80,6 +84,9 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 'F': args->uhd_tx_freq = atof(argv[optind]); break; + case 't': + args->do_trace = true; + break; case 'v': args->verbose++; break; @@ -202,7 +209,6 @@ void setup_mac_phy_sib2(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, srslte::u phy->set_param(srslte::ue::phy_params::SRS_CS_BWCFG, sib2->rr_config_common_sib.srs_ul_cnfg.bw_cnfg); phy->set_param(srslte::ue::phy_params::SRS_CS_SFCFG, sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg); phy->set_param(srslte::ue::phy_params::SRS_CS_ACKNACKSIMUL, sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx); - phy->set_param(srslte::ue::phy_params::SRS_IS_CS_CONFIGURED, 1); } printf("Set SRS ConfigCommon: BW-Configuration=%d, SF-Configuration=%d, ACKNACK=%d\n", @@ -233,7 +239,6 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac phy->set_param(srslte::ue::phy_params::SRS_UE_HOP, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.srs_hopping_bandwidth); phy->set_param(srslte::ue::phy_params::SRS_UE_TXCOMB, msg->rr_cnfg.phy_cnfg_ded.srs_ul_cnfg_ded.tx_comb); phy->set_param(srslte::ue::phy_params::SRS_BETA, 10); - phy->set_param(srslte::ue::phy_params::SRS_IS_UE_CONFIGURED, 1); } } printf("Set PHY configuration: SR-n_pucch=%d, SR-ConfigIndex=%d, SRS-ConfigIndex=%d, SRS-bw=%d, SRS-Nrcc=%d, SRS-hop=%d, SRS-Ncs=%d\n", @@ -299,13 +304,23 @@ uint32_t lengths[2] = {37, 41}; uint8_t reply[2] = {0x00, 0x04}; +srslte::radio_uhd radio_uhd; +srslte::ue::phy phy; +srslte::ue::mac mac; + +void sig_int_handler(int signo) +{ + //radio_uhd.write_trace("radio"); + phy.write_trace("phy"); + mac.write_trace("mac"); + exit(0); +} + + int main(int argc, char *argv[]) { prog_args_t prog_args; srslte::ue::tti_sync_cv ttisync(10240); - srslte::radio_uhd radio_uhd; - srslte::ue::phy phy; - srslte::ue::mac mac; srslte::log_stdout mac_log("MAC"), phy_log("PHY"); parse_args(&prog_args, argc, argv); @@ -320,7 +335,15 @@ int main(int argc, char *argv[]) phy_log.set_level_debug(); break; } - + + if (prog_args.do_trace) { + // Capture SIGINT to write traces + signal(SIGINT, sig_int_handler); + //radio_uhd.start_trace(); + phy.start_trace(); + mac.start_trace(); + } + // Init Radio and PHY if (prog_args.uhd_rx_gain > 0 && prog_args.uhd_tx_gain > 0) { radio_uhd.init(); @@ -449,6 +472,8 @@ int main(int argc, char *argv[]) // Wait for ConnectionSetup n = mac.recv_dcch0_sdu(bit_msg.msg, LIBLTE_MAX_MSG_SIZE); if (n > 0) { + phy.set_param(srslte::ue::phy_params::SRS_IS_CS_CONFIGURED, 1); + phy.set_param(srslte::ue::phy_params::SRS_IS_UE_CONFIGURED, 1); printf("Received on DCCH0 %d bytes\n", n/8); printf("Send RLC ACK\n"); srslte_bit_pack_vector(reply, bit_msg.msg, 2*8); diff --git a/srsapps/ue/phy/include/srsapps/ue/phy/phy.h b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h index f93e65f64..8bfbd8e0e 100644 --- a/srsapps/ue/phy/include/srsapps/ue/phy/phy.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h @@ -38,6 +38,7 @@ #include "srsapps/ue/phy/sched_grant.h" #include "srsapps/common/queue.h" #include "srsapps/radio/radio.h" +#include "srsapps/common/trace.h" #ifndef UEPHY_H #define UEPHY_H @@ -119,6 +120,9 @@ public: ul_buffer* get_ul_buffer(uint32_t tti); dl_buffer* get_dl_buffer(uint32_t tti); + void start_trace(); + void write_trace(std::string filename); + void main_radio_loop(); private: @@ -166,6 +170,11 @@ private: bool is_first_of_burst; + trace tr_start_time; + trace tr_end_time; + bool tr_enabled; + void tr_log_start(); + void tr_log_end(); }; } diff --git a/srsapps/ue/phy/include/srsapps/ue/phy/prach.h b/srsapps/ue/phy/include/srsapps/ue/phy/prach.h index 6ece0489b..149a0966a 100644 --- a/srsapps/ue/phy/include/srsapps/ue/phy/prach.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/prach.h @@ -56,11 +56,11 @@ namespace ue { bool send(srslte::radio* radio_handler, float cfo, srslte_timestamp_t rx_time); private: static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission - phy_params *params_db = NULL; + phy_params *params_db; log *log_h; int preamble_idx; int allowed_subframe; - bool initiated = false; + bool initiated; uint32_t len; cf_t *buffer[64]; srslte_prach_t prach_obj; diff --git a/srsapps/ue/phy/src/dl_buffer.cc b/srsapps/ue/phy/src/dl_buffer.cc index d3379862f..de2aa8734 100644 --- a/srsapps/ue/phy/src/dl_buffer.cc +++ b/srsapps/ue/phy/src/dl_buffer.cc @@ -116,15 +116,16 @@ bool dl_buffer::get_ul_grant(ul_sched_grant *grant) if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) { return false; } - /* + grant->set_shortened(false); if (params_db->get_param(phy_params::SRS_IS_CS_CONFIGURED)) { - if (srslte_refsignal_srs_send_cs((uint32_t) params_db->get_param(phy_params::SRS_CS_SFCFG), tti%10) == 1) { + if (srslte_refsignal_srs_send_cs((uint32_t) params_db->get_param(phy_params::SRS_CS_SFCFG), (tti+4)%10) == 1) { grant->set_shortened(true); - printf("UL grant tti=%d is shortened. SF-CFG=%d\n", tti, (int) params_db->get_param(phy_params::SRS_CS_SFCFG)); + printf("UL grant tti=%d is shortened. SF-CFG=%d\n", tti+4, + (int) params_db->get_param(phy_params::SRS_CS_SFCFG)); } } - */ + return grant->create_from_dci(&dci_msg, cell, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET)); } } diff --git a/srsapps/ue/phy/src/phy.cc b/srsapps/ue/phy/src/phy.cc index fd6449311..ea05abfa0 100644 --- a/srsapps/ue/phy/src/phy.cc +++ b/srsapps/ue/phy/src/phy.cc @@ -43,7 +43,7 @@ namespace srslte { namespace ue { -phy::phy() +phy::phy() : tr_end_time(1024*10), tr_start_time(1024*10) { started = false; is_sfn_synched = false; @@ -59,6 +59,30 @@ bool phy::init_agc(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_ return init_(radio_handler_, ttisync_, log_h, true); } +void phy::start_trace() +{ + tr_enabled = true; +} + +void phy::write_trace(std::string filename) +{ + tr_start_time.writeToBinary(filename + ".start"); + tr_end_time.writeToBinary(filename + ".end"); +} + +void phy::tr_log_start() +{ + if (tr_enabled) { + tr_start_time.push_cur_time_us(get_current_tti()); + } +} + +void phy::tr_log_end() +{ + if (tr_enabled) { + tr_end_time.push_cur_time_us(get_current_tti()); + } +} bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h_, bool do_agc_) { @@ -314,7 +338,7 @@ bool phy::init_prach() { ul_buffer* phy::get_ul_buffer(uint32_t tti) { - if (tti + 1 < get_current_tti()) { + if ((tti + 1)%10240 < get_current_tti() && tti > 6) { Warning("Warning access to PHY UL buffer too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti()); } return (ul_buffer*) ul_buffer_queue->get(tti); @@ -524,8 +548,9 @@ void phy::run_rx_tx_state() } // Receive alligned buffer for the current tti + tr_log_end(); get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time); - + tr_log_start(); ttisync->increase(); } } diff --git a/srslte/include/srslte/common/timestamp.h b/srslte/include/srslte/common/timestamp.h index bc39f2c6a..7c4a98e45 100644 --- a/srslte/include/srslte/common/timestamp.h +++ b/srslte/include/srslte/common/timestamp.h @@ -39,6 +39,7 @@ #define TIMESTAMP_ #include +#include #include "srslte/config.h" typedef struct SRSLTE_API{ @@ -63,4 +64,6 @@ SRSLTE_API int srslte_timestamp_sub(srslte_timestamp_t *t, SRSLTE_API double srslte_timestamp_real(srslte_timestamp_t *t); +SRSLTE_API uint32_t srslte_timestamp_uint32(srslte_timestamp_t *t); + #endif // TIMESTAMP_ diff --git a/srslte/lib/common/src/timestamp.c b/srslte/lib/common/src/timestamp.c index 161f5cffa..670818979 100644 --- a/srslte/lib/common/src/timestamp.c +++ b/srslte/lib/common/src/timestamp.c @@ -80,3 +80,8 @@ int srslte_timestamp_sub(srslte_timestamp_t *t, time_t full_secs, double frac_se double srslte_timestamp_real(srslte_timestamp_t *t){ return t->frac_secs + t->full_secs; } + +uint32_t srslte_timestamp_uint32(srslte_timestamp_t *t){ + uint32_t x = t->full_secs*1e6 + (uint32_t) (t->frac_secs*1e6); + return x; +}