diff --git a/examples/cdc_rx_thruput.grc b/examples/cdc_rx_thruput.grc new file mode 100644 index 0000000000000000000000000000000000000000..4f640fd5ee0720b89d3b758c67123237b1929a3c --- /dev/null +++ b/examples/cdc_rx_thruput.grc @@ -0,0 +1,135 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: University of Melbourne + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: cdc_rx_thruput + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: CDC Rx Thruput Example + window_size: (1000,1000) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: reset_var + id: variable_qtgui_push_button + parameters: + comment: '' + gui_hint: '' + label: Reset Stats + pressed: 'True' + released: 'False' + type: bool + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [608, 20.0] + rotation: 0 + state: true +- name: blocks_message_strobe_0 + id: blocks_message_strobe + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + msg: pmt.intern("TEST") + period: '200' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [80, 132.0] + rotation: 0 + state: true +- name: blocks_random_pdu_0 + id: blocks_random_pdu + parameters: + affinity: '' + alias: '' + comment: '' + length_modulo: '2' + mask: '0xFF' + maxoutbuf: '0' + maxsize: '128' + minoutbuf: '0' + minsize: '128' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [336, 116.0] + rotation: 0 + state: true +- name: elen90089_rx_stats_0 + id: elen90089_rx_stats + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + period: '1' + reset: reset_var + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [624, 132.0] + rotation: 0 + state: true +- name: qtgui_edit_box_msg_0 + id: qtgui_edit_box_msg + parameters: + affinity: '' + alias: '' + comment: '' + gui_hint: '' + is_pair: 'False' + is_static: 'False' + key: '' + label: Thruput (kbps) + maxoutbuf: '0' + minoutbuf: '0' + type: double + value: '0.0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [832, 108.0] + rotation: 0 + state: true + +connections: +- [blocks_message_strobe_0, strobe, blocks_random_pdu_0, generate] +- [blocks_random_pdu_0, pdus, elen90089_rx_stats_0, pdu] +- [elen90089_rx_stats_0, tput, qtgui_edit_box_msg_0, val] + +metadata: + file_format: 1 diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 6cc623ecfbecc523cfc77528df78c1c0db044f21..5fa604dde61c7b509fdb2616369139825f17eb26 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -15,5 +15,6 @@ install(FILES elen90089_constellation_decoder_cf.block.yml elen90089_costas_loop_cc.block.yml elen90089_dsa_pu_scenario_cc.block.yml + elen90089_rx_stats.block.yml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/elen90089_rx_stats.block.yml b/grc/elen90089_rx_stats.block.yml new file mode 100644 index 0000000000000000000000000000000000000000..cbf5222b67aefb0c2c795c48c01156f3b2e205a0 --- /dev/null +++ b/grc/elen90089_rx_stats.block.yml @@ -0,0 +1,31 @@ +id: elen90089_rx_stats +label: CDC Rx Stats +category: '[elen90089]' + +templates: + imports: import elen90089 + make: elen90089.rx_stats(${period}) + callbacks: + - reset_stats(${reset}) + +parameters: +- id: period + label: Display Period (sec) + dtype: int + default: 1 +- id: reset + label: Reset Stats + dtype: raw + default: False + +inputs: +- label: pdu + domain: message + optional: True + +outputs: +- label: tput + domain: message + optional: True + +file_format: 1 diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 469d521dd6ab0ae9c91622dfaae3ecc1c3e4bcb1..174a0d209cf6bfdab3d107ae43630748a0b87324 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -23,6 +23,7 @@ GR_PYTHON_INSTALL( FILES __init__.py packet_mac_tx.py + rx_stats.py DESTINATION ${GR_PYTHON_DIR}/elen90089 ) diff --git a/python/__init__.py b/python/__init__.py index d997af05f5d3e93aeddd2bcdb23193d36d18e18f..53733ba83e97b41aee5c37d599278165eda46d17 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -21,4 +21,5 @@ except ModuleNotFoundError: # import any pure python here from .packet_mac_tx import packet_mac_tx +from .rx_stats import rx_stats # diff --git a/python/rx_stats.py b/python/rx_stats.py new file mode 100644 index 0000000000000000000000000000000000000000..8361c421afa3d4f16c53ed3bdaf30f142c4ec58c --- /dev/null +++ b/python/rx_stats.py @@ -0,0 +1,55 @@ +import pmt +import time +from threading import Lock + +import numpy as np +from gnuradio import gr + + +class rx_stats(gr.sync_block): + """Compute throughput (in kbps) of received PDUs.""" + def __init__(self, period=1.0): + gr.sync_block.__init__( + self, + name='Rx Stats', + in_sig=None, + out_sig=None) + self.period = period # output period + + # message ports + self.message_port_register_in(pmt.intern('pdu')) + self.message_port_register_out(pmt.intern('tput')) + self.set_msg_handler(pmt.intern('pdu'), self.handle_pdu) + + # stats + self.mutex = Lock() + self.is_reset = False + self.n_bytes = 0 + self.t_start = self.t_print = time.time() + + def reset_stats(self, is_reset): + if is_reset: + self.mutex.acquire() + self.is_reset = True + self.mutex.release() + + def handle_pdu(self, pdu): + # update stats + pld = pmt.to_python(pmt.cdr(pdu)) + self.n_bytes += len(pld) + now = time.time() + + # check reset + self.mutex.acquire() + is_reset, self.is_reset = self.is_reset, False + self.mutex.release() + + if is_reset: + self.n_bytes = 0 + self.t_start = self.t_print = now + + if now - self.t_print > self.period: + tput = 8*self.n_bytes / (now - self.t_start) / 1000.0 + self.message_port_pub(pmt.intern('tput'), pmt.from_double(tput)) + self.t_print = now +