Skip to content
Snippets Groups Projects
Commit 7e4e63ae authored by Raymond.Knopp's avatar Raymond.Knopp
Browse files

Merge remote-tracking branch 'origin/develop' into enhancement-10-harmony

Conflicts:
	targets/RT/USER/lte-enb.c
	targets/RT/USER/lte-softmodem.c
parents 108cf6bf 9a0f32aa
Branches
Tags
No related merge requests found
Showing
with 3128 additions and 541 deletions
...@@ -38,3 +38,4 @@ v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for ...@@ -38,3 +38,4 @@ v0.2 -> Merge of enhancement-10-harmony to include NGFI RRH + New Interface for
v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License v0.3 -> Last stable commit on develop branch before the merge of feature-131-new-license. This is the last commit with GPL License
v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0 v0.4 -> Merge of feature-131-new-license. It closes issue#131 and changes the license to OAI Public License V1.0
v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support v0.5 -> Merge of enhancement-10-harmony-lts. It includes fixes for Ubuntu 16.04 support
v0.5.1 -> Merge of bugfix-137-uplink-fixes. It includes stablity fixes for eNB
...@@ -218,7 +218,7 @@ Obj.# Case# Test# Description ...@@ -218,7 +218,7 @@ Obj.# Case# Test# Description
01 70 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 70 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
01 75 00 lte-softmodem + RRH tests with B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 75 00 lte-softmodem + RRU (NGFI IF4P5, RAW) tests with B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX
01 75 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 75 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
01 75 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 75 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
01 75 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX 01 75 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
...@@ -226,7 +226,7 @@ Obj.# Case# Test# Description ...@@ -226,7 +226,7 @@ Obj.# Case# Test# Description
01 75 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 75 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
01 75 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 75 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
01 80 00 lte-softmodem + RRH tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 80 00 lte-softmodem + RRU (NGFI) tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX
01 80 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 80 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
01 80 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 80 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
01 80 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX 01 80 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
...@@ -234,7 +234,7 @@ Obj.# Case# Test# Description ...@@ -234,7 +234,7 @@ Obj.# Case# Test# Description
01 80 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 80 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
01 80 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 80 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
01 85 00 lte-softmodem + RRH tests with USRP X310 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX 01 85 00 lte-softmodem + RRU (NGFI) tests with USRP X310 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX
01 85 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX 01 85 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
01 85 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX 01 85 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
01 85 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX 01 85 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
...@@ -268,6 +268,15 @@ Obj.# Case# Test# Description ...@@ -268,6 +268,15 @@ Obj.# Case# Test# Description
02 55 22 Band 7 FDD 10MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) 02 55 22 Band 7 FDD 10MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2)
02 55 23 Band 7 FDD 20MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2) 02 55 23 Band 7 FDD 20MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2)
02 57 lte-softmodem tests with USRP B210 RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ OAI UE
02 57 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
02 57 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
02 57 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
02 57 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX
02 57 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
02 57 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
01 64 lte-softmodem-noS1 tests 01 64 lte-softmodem-noS1 tests
02 Functional test case 02 Functional test case
......
This diff is collapsed.
Source diff could not be displayed: it is too large. Options to address this: view the blob.
#! /usr/bin/python
#******************************************************************************
#
# \file autotest_analyser.py
#
# \par Informations
# - \b Project : UED Autotest Framework
# - \b Software :
#
# \date 16 september 2016
#
# \version 0.1
#
# \brief helper to test lib_autotest_analyser.py
#
# \author Benoit ROBERT (benoit.robert@syrtem.com)
#
# \par Statement of Ownership
# COPYRIGHT (c) 2016 BY SYRTEM S.A.R.L
# This software is furnished under license and may be used and copied
# only in accordance with the terms of such license and with the inclusion
# of the above COPYRIGHT notice. This SOFTWARE or any other copies thereof
# may not be provided or otherwise made available to any other person.
# No title to and ownership of the SOFTWARE is hereby transferred.
#
# The information in this SOFTWARE is subject to change without notice
# and should not be constructed as a commitment by SYRTEM.
# SYRTEM assumes no responsibility for the use or reliability of its
# SOFTWARE on equipment or platform not explicitly validated by SYRTEM.
#
# *******************************************************************************
import os
import getopt
import sys
from subprocess import call
#test_cases = ('030001', '030901', '031001', '031601', '031701', '031801', '031901', '032001', '032101', '032201', '032301', '032501', '032601', '032801')
test_cases = ('030030' , '030030' )
nb_run = 3
def error_opt(msg):
print("Option error: " + msg)
def main(args):
try:
analyser = __import__("lib_autotest_analyser")
except ImportError as err:
print('Import error: ' + str(err))
exit(0)
log_path = 'log_save_2016-08-14/log/'
metric = {}
metric['id'] = 'UE_DLSCH_BITRATE'
metric['description'] = 'UE downlink physical throughput'
metric['regex'] = '(UE_DLSCH_BITRATE) =\s+(\d+\.\d+) kbps.+frame = (\d+)\)'
metric['unit_of_meas'] = 'kbps'
metric['min_limit'] = 14668.8
#report_path = log_path+'/report/'
#os.system(' mkdir -p ' + report_path)
#analyser.create_report_html(report_path)
#return(0)
for test_case in test_cases:
# print test_case
if test_case == '030001':
metric['min_limit'] = 500.0
if test_case == '030901':
metric['min_limit'] = 640.0
if test_case == '031001':
metric['min_limit'] = 3200.0
if test_case == '031601':
metric['min_limit'] = 5920.0
if test_case == '031701':
metric['min_limit'] = 6000.0
if test_case == '031801':
metric['min_limit'] = 6200.0
if test_case == '031901':
metric['min_limit'] = 7000.0
if test_case == '032001':
metric['min_limit'] = 7800.0
if test_case == '032101':
metric['min_limit'] = 8000.0
if test_case == '032201':
metric['min_limit'] = 9000.0
if test_case == '032301':
metric['min_limit'] = 10000.0
if test_case == '032501':
metric['min_limit'] = 11000.0
if test_case == '032601':
metric['min_limit'] = 12000.0
if test_case == '032801':
metric['min_limit'] = 12500.0
if test_case == '035201':
metric['min_limit'] = 14668.8
if test_case == '036001':
metric['min_limit'] = 25363.2
for i in range(0, nb_run):
fname = 'log//'+test_case+'/run_'+str(i)+'/UE_exec_'+str(i)+'_.log'
args = {'metric' : metric,
'file' : fname }
cell_synch_status = analyser.check_cell_synchro(fname)
if cell_synch_status == 'CELL_SYNCH':
print '!!!!!!!!!!!!!! Cell synchronized !!!!!!!!!!!'
metric_checks_flag = 0
else :
print '!!!!!!!!!!!!!! Cell NOT NOT synchronized !!!!!!!!!!!'
# metric_extracted = analyser.do_extract_metrics(args)
# print "min = "+ str( metric_extracted['metric_min'] )
# print "min_index = "+ str( metric_extracted['metric_min_index'] )
# print "max = "+ str( metric_extracted['metric_max'] )
# print "max_index = "+ str( metric_extracted['metric_max_index'] )
# print "mean = "+ str( metric_extracted['metric_mean'] )
# print "median = "+ str( metric_extracted['metric_median'] )
# verdict = analyser.do_check_verdict(metric, metric_extracted)
# print verdict
# fname= 'report/2016-9-8_toto/'+test_case+'/UE_metric_UE_DLSCH_BITRATE_'+str(i)+'_.png'
# fname= 'report/UE_metric_UE_DLSCH_BITRATE_'+test_case+'_'+str(i)+'.png'
# print fname
# analyser.do_img_metrics(metric, metric_extracted, fname)
# fname = 'log//'+test_case+'/run_'+str(i)+'/UE_traffic_'+str(i)+'_.log'
# args = {'file' : fname }
# traffic_metrics = analyser.do_extract_traffic_metrics(args)
# fname= 'report/iperf_'+test_case+'_'+str(i)+'.png'
# print fname
# analyser.do_img_traffic(traffic_metrics, fname)
if __name__ == "__main__":
main(sys.argv)
#******************************************************************************
#
# \file lib_autotest_analyser.py
#
# \par Informations
# - \b Project : UED Autotest Framework
# - \b Software :
#
# \date 16 september 2016
#
# \version 0.1
#
# \brief library to extract metrics from autotest logs and assign a verdict
#
# \author Benoit ROBERT (benoit.robert@syrtem.com)
#
# \par Statement of Ownership
# COPYRIGHT (c) 2016 BY SYRTEM S.A.R.L
# This software is furnished under license and may be used and copied
# only in accordance with the terms of such license and with the inclusion
# of the above COPYRIGHT notice. This SOFTWARE or any other copies thereof
# may not be provided or otherwise made available to any other person.
# No title to and ownership of the SOFTWARE is hereby transferred.
#
# The information in this SOFTWARE is subject to change without notice
# and should not be constructed as a commitment by SYRTEM.
# SYRTEM assumes no responsibility for the use or reliability of its
# SOFTWARE on equipment or platform not explicitly validated by SYRTEM.
#
# *******************************************************************************
import re
from pylab import *
from matplotlib.font_manager import FontProperties
import os
from jinja2 import Environment, FileSystemLoader
PATH = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_ENVIRONMENT = Environment(
autoescape=False,
loader=FileSystemLoader(os.path.join(PATH, 'templates')),
trim_blocks=False)
def render_template(template_filename, context):
return TEMPLATE_ENVIRONMENT.get_template(template_filename).render(context)
def init(args = None):
return
#
#
#
def do_extract_metrics(args):
# print ""
# print "do_extract_metrics ... "
fname = args['file']
metric = args['metric']
# print(fname)
# print 'metric id = ' + metric['id']
# print 'metric regex = ' + metric['regex']
count = 0
mmin = 0
mmin_index = 0
mmax = 0
mmax_index = 0
mean = 0
median = 0
output = np.fromregex(fname,metric['regex'], [('id', 'S20'), ('metric', np.float), ('frame', np.int)] )
# print 'T0T0 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
# print output
count = output['metric'].size
# print count
if count > 0:
mmin = np.amin(output['metric']);
mmin_index = np.argmin(output['metric']);
mmax = np.amax(output['metric']);
mmax_index = np.argmax(output['metric']);
mean = np.mean(output['metric']);
median = np.median(output['metric']);
# print ( ( (metric['min_limit'] > output['metric']).sum() / float(output['metric'].size) ) * 100 )
ret = { 'metric_count' : count,
'metric_buf' : output,
'metric_min' : mmin,
'metric_min_index' : mmin_index,
'metric_max' : mmax,
'metric_max_index' : mmax_index,
'metric_mean' : mean,
'metric_median' : median,
}
return(ret)
#
#
#
def do_check_verdict(metric_def, metric_data):
verdict = 'INCON'
pass_fail_stat = metric_def['pass_fail_stat']
if pass_fail_stat == 'max_value':
metric_stat = metric_data['metric_max']
elif pass_fail_stat == 'min_value':
metric_stat = metric_data['metric_min']
elif pass_fail_stat == 'mean_value':
metric_stat = metric_data['metric_mean']
elif pass_fail_stat == 'median_value':
metric_stat = metric_data['metric_median']
else :
print "do_check_verdict -> undef metric stat (pass_fail_stat in xml file)"
return verdict
if 'max_limit' in metric_def:
if metric_stat > metric_def['max_limit']:
verdict = 'FAIL'
else:
verdict = 'PASS'
if 'min_limit' in metric_def:
if metric_stat < metric_def['min_limit']:
verdict = 'FAIL'
else:
verdict = 'PASS'
return verdict
def do_print_metrics(metric_def, metric_data):
if metric_data['metric_count'] > 0 :
# output = np.array( metric_data['metric_buf'] , [('id', 'S20'), ('metric', np.float), ('frame', np.int)])
output = metric_data['metric_buf']
# print output
fontP = FontProperties()
fontP.set_size('small')
plt.scatter(output['frame'], output['metric'], color='b', alpha=0.33, s = 1 )
plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2) # Red straight line
plt.title('Physical throughput ')
plt.xlabel('frame')
plt.ylabel(metric_def['id'])
plt.legend(prop=fontP)
mng = plt.get_current_fig_manager()
plt.show()
def do_img_metrics(metric_def, metric_data, fname):
if metric_data['metric_count'] > 0 :
# output = np.array( metric_data['metric_buf'] , [('id', 'S20'), ('metric', np.float), ('frame', np.int)])
output = metric_data['metric_buf']
# print 'TITI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
# print output
# print metric_def['min_limit']
# print metric_data['metric_count']
# print output['frame'][metric_data['metric_count']-1]
fontP = FontProperties()
fontP.set_size('small')
plt.figure()
# print output['frame'].size
# print output['metric'].size
plt.scatter(output['frame'], output['metric'], color='b', alpha=0.33, s = 1 , label=metric_def['id'])
plt.plot([0, output['frame'][metric_data['metric_count']-1]],[ metric_def['min_limit'],metric_def['min_limit']], 'r-', lw=2, label='min limit') # Red straight line
plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
plt.xlabel('frame')
plt.ylabel(metric_def['id'])
# Set graphic minimum Y axis
# -------------------------
if metric_data['metric_min'] == 0 :
plt.ylim(ymin=-metric_def['min_limit']/10)
else :
plt.ylim(ymin=0)
y_axis_max = 0
if metric_data['metric_max'] > metric_def['min_limit']:
y_axis_max =metric_data['metric_max']+metric_data['metric_max']/10
else:
y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
plt.ylim(ymax=y_axis_max)
lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
mng = plt.get_current_fig_manager()
plt.savefig(fname, bbox_extra_artists=(lgd,), bbox_inches='tight')
plt.close()
# with open(fname, 'r') as f:
# for line in f:
# m = re.search(metric['regex'], line)
# if m :
# print m.group(1) + " -> "+m.group(2)
def do_extract_traffic_metrics(args):
print ""
print "do_extract_traffic_metrics ... "
fname = args['file']
# print(fname)
# print 'metric id = ' + metric['id']
#[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
#[ 3] 0.0- 1.0 sec 238 KBytes 1.95 Mbits/sec 0.980 ms 2/ 174 (1.1%)
# [ 3] 0.0- 1.0 sec 63.2 KBytes 517 Kbits/sec 0.146 ms 1/ 45 (2.2%)
# iperf_regex = '[\s*(\d+)]\s+\d+\.\d+-\s*(\d+\.\d+)\s+sec\s+(\d+).+(\d+\.\d+).+(\d+\.\d+).+(\d+)\/\s*(\d+)\s+\((\d+\.\d+)\%\)'
# ID 0.0 1.0 63.2 KByte 517 Kbits/s 0.146
iperf_regex = '\[\s*(\d+)\]\s+(\d+\.*\d*)-\s*(\d+\.*\d*)\s+sec\s+(\d+\.*\d*)\s+(\D+)\s+(\d+\.*\d*)\s+(\D+)\s+(\d+\.*\d*)\s+ms\s+(\d+)\/\s*(\d+)\s+\((\d+\.*\d*)\%\)'
# print 'iperf regex = ' + iperf_regex
count = 0
bw_min = 0
bw_max = 0
bw_mean = 0
bw_median = 0
jitter_min = 0
jitter_max = 0
jitter_mean = 0
jitter_median = 0
rl_min = 0
rl_max = 0
rl_mean = 0
rl_median = 0
interval_stop_max = 0
output = np.fromregex(fname,iperf_regex, [('id', np.int) , ('interval_start', np.float), ('interval_stop', np.float), ('transfer', np.float), ('transfer_uom', 'S20') ,('bandwidth', np.float), ('bandwidth_uom', 'S20') ,('jitter', np.float), ('lost', np.int) , ('total', np.int), ('rate_lost', np.float) ] )
count = output['id'].size -1
# remove last line that is an iperf result resume
if count > 0:
output= np.delete(output, (count), axis=0 )
# print output
bw_min = np.amin(output['bandwidth']);
bw_max = np.amax(output['bandwidth']);
bw_mean = np.mean(output['bandwidth']);
bw_median = np.median(output['bandwidth']);
jitter_min = np.amin(output['jitter']);
jitter_max = np.amax(output['jitter']);
jitter_mean = np.mean(output['jitter']);
jitter_median = np.median(output['jitter']);
rl_min = np.amin(output['rate_lost']);
rl_max = np.amax(output['rate_lost']);
rl_mean = np.mean(output['rate_lost']);
rl_median = np.median(output['rate_lost']);
interval_stop_max = np.amax(output['interval_stop']);
else :
count = 0
ret = { 'traffic_count' : count,
'traffic_buf' : output,
'bw_min' : bw_min,
'bw_max' : bw_max,
'bw_mean' : bw_mean,
'bw_median' : bw_median,
'jitter_min' : jitter_min,
'jitter_max' : jitter_max,
'jitter_mean' : jitter_mean,
'jitter_median' : jitter_median,
'rl_min' : rl_min,
'rl_max' : rl_max,
'rl_mean' : rl_mean,
'rl_median' : rl_median,
'interval_stop_max' : interval_stop_max
}
return(ret)
def do_img_traffic(traffic_data, fname):
if traffic_data['traffic_count'] > 0 :
output = traffic_data['traffic_buf']
fontP = FontProperties()
fontP.set_size('small')
fig = plt.figure(1)
ax1= plt.subplot(311)
plt.plot(output['interval_stop'], output['bandwidth'], color='b' )
ax1.set_title('Bandwidth (Mbits/s)')
ax1.set_ylim(ymin=-1)
ax1.set_xlim(xmax=np.amax(output['interval_stop']))
text='min: '+str(traffic_data['bw_min'])+'\nmax: '+str(traffic_data['bw_max'])+'\nmean: '+str(traffic_data['bw_mean'])+'\nmedian: '+str(traffic_data['bw_median'])
ax1.text( np.amax(output['interval_stop'])+10,0,text)
ax2=plt.subplot(312)
plt.plot(output['interval_stop'], output['jitter'], color='b' )
ax2.set_title('Jitter (ms)')
ax2.set_xlim(xmax=np.amax(output['interval_stop']))
ax2.set_ylim(ymin=-1)
text='min: '+str(traffic_data['jitter_min'])+'\nmax: '+str(traffic_data['jitter_max'])+'\nmean: '+str(traffic_data['jitter_mean'])+'\nmedian: '+str(traffic_data['jitter_median'])
ax2.text( np.amax(output['interval_stop'])+10,0,text)
ax3=plt.subplot(313)
plt.plot(output['interval_stop'], output['rate_lost'], color='b')
ax3.set_title('Loss rate %')
ax3.set_xlim(xmax=np.amax(output['interval_stop']))
ax3.set_ylim(ymin=-1)
text='min: '+str(traffic_data['rl_min'])+'\nmax: '+str(traffic_data['rl_max'])+'\nmean: '+str(traffic_data['rl_mean'])+'\nmedian: '+str(traffic_data['rl_median'])
ax3.text( np.amax(output['interval_stop'])+10,0,text)
# plt.title('Physical throughput ('+metric_def['unit_of_meas']+')')
plt.xlabel('time (s)')
# plt.ylabel(metric_def['id'])
# Set graphic minimum Y axis
# -------------------------
# if traffic_data['bw_min'] == 0 :
# plt.ylim(ymin=-metric_def['min_limit']/10)
# else :
# plt.ylim(ymin=0)
# y_axis_max = 0
# if traffic_data['metric_max'] > metric_def['min_limit']:
# y_axis_max =traffic_data['metric_max']+traffic_data['metric_max']/10
# else:
# y_axis_max =metric_def['min_limit']+metric_def['min_limit']/10
#
# plt.ylim(ymax=y_axis_max)
plt.tight_layout()
lgd = plt.legend(prop=fontP, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
mng = plt.get_current_fig_manager()
plt.savefig(fname, bbox_inches='tight')
plt.close()
def create_report_html(context):
fname = context['report_path']+"/index.html"
#
with open(fname, 'w') as f:
html = render_template('index.html', context)
f.write(html)
def create_test_report_detailed_html(context, fname ):
with open(fname, 'w') as f:
html = render_template('testcase_report.html', context)
f.write(html)
def check_cell_synchro(fname):
with open(fname, 'r') as f:
for line in f:
m = re.search('AUTOTEST Cell Sync \:', line)
if m :
print line
return 'CELL_SYNCH'
return 'CELL_NOT_SYNCH'
def check_exec_seg_fault(fname):
with open(fname, 'r') as f:
for line in f:
m = re.search('Segmentation fault', line)
if m :
print line
return 'SEG_FAULT'
return 'NO_SEG_FAULT'
...@@ -226,10 +226,12 @@ check_install_additional_tools (){ ...@@ -226,10 +226,12 @@ check_install_additional_tools (){
sshpass \ sshpass \
nscd \ nscd \
bc \ bc \
ntp ntp \
python-scipy \
python-matplotlib
$SUDO pip install paramiko $SUDO pip install paramiko
$SUDO pip install pyroute2 $SUDO pip install pyroute2 colorama
$SUDO rm -fr /opt/ssh $SUDO rm -fr /opt/ssh
$SUDO GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/ssh.git /opt/ssh $SUDO GIT_SSL_NO_VERIFY=true git clone https://gitlab.eurecom.fr/oai/ssh.git /opt/ssh
......
...@@ -16,7 +16,7 @@ ID = ENB_PHY_DL_TICK ...@@ -16,7 +16,7 @@ ID = ENB_PHY_DL_TICK
ID = ENB_PHY_DLSCH_UE_DCI ID = ENB_PHY_DLSCH_UE_DCI
DESC = eNodeB downlink UE specific DCI as sent by the PHY layer DESC = eNodeB downlink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
ID = ENB_PHY_DLSCH_UE_ACK ID = ENB_PHY_DLSCH_UE_ACK
DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback
GROUP = ALL:PHY:GRAPHIC:ENB GROUP = ALL:PHY:GRAPHIC:ENB
...@@ -28,7 +28,7 @@ ID = ENB_PHY_DLSCH_UE_NACK ...@@ -28,7 +28,7 @@ ID = ENB_PHY_DLSCH_UE_NACK
ID = ENB_PHY_ULSCH_UE_DCI ID = ENB_PHY_ULSCH_UE_DCI
DESC = eNodeB uplink UE specific DCI as sent by the PHY layer DESC = eNodeB uplink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS
ID = ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION ID = ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION
DESC = eNodeB uplink UE retransmission due to PHICH NACK (see generate_phich_top) DESC = eNodeB uplink UE retransmission due to PHICH NACK (see generate_phich_top)
GROUP = ALL:PHY:GRAPHIC:ENB GROUP = ALL:PHY:GRAPHIC:ENB
...@@ -61,6 +61,18 @@ ID = ENB_PHY_PUCCH_1_ENERGY ...@@ -61,6 +61,18 @@ ID = ENB_PHY_PUCCH_1_ENERGY
DESC = eNodeB PUCCH 1 energy and threshold DESC = eNodeB PUCCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,energy : int,threshold FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,energy : int,threshold
ID = ENB_PHY_PHICH
DESC = eNodeB PHICH
GROUP = ALL:PHY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,NGROUP : int,NSF : int,ngroup : int,nseq : int,ACK : int,first_rb : int,n_DMRS
ID = ENB_PHY_MSG3_ALLOCATION
DESC = eNodeB Msg3 allocation/reallocation
GROUP = ALL:PHY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,first_transmission : int,Msg3_frame : int,Msg3_subframe
ID = ENB_PHY_INITIATE_RA_PROCEDURE
DESC = eNodeB initiates a random access procedure after detecting enough energy for one of the preambles
GROUP = ALL:PHY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,preamble : int,energy : int,delay
#MAC logs #MAC logs
ID = ENB_MAC_UE_DL_SDU ID = ENB_MAC_UE_DL_SDU
...@@ -70,7 +82,7 @@ ID = ENB_MAC_UE_DL_SDU ...@@ -70,7 +82,7 @@ ID = ENB_MAC_UE_DL_SDU
ID = ENB_MAC_UE_UL_SCHEDULE ID = ENB_MAC_UE_UL_SCHEDULE
DESC = MAC uplink UE scheduling decision DESC = MAC uplink UE scheduling decision
GROUP = ALL:MAC:ENB GROUP = ALL:MAC:ENB
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : int,mcs : int,first_rb : int,nb_rb : int,TBS FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : int,mcs : int,first_rb : int,nb_rb : int,TBS : int,ndi
ID = ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION ID = ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION
DESC = MAC uplink UE scheduling retransmission decision DESC = MAC uplink UE scheduling retransmission decision
GROUP = ALL:MAC:ENB GROUP = ALL:MAC:ENB
......
...@@ -24,6 +24,30 @@ typedef struct { ...@@ -24,6 +24,30 @@ typedef struct {
view *pdcpview; view *pdcpview;
view *rrcview; view *rrcview;
view *legacy; view *legacy;
widget *current_ue_label;
widget *prev_ue_button;
widget *next_ue_button;
widget *pusch_iq_ue_xy_plot;
widget *ul_estimate_ue_xy_plot;
widget *pucch1_energy_ue_xy_plot;
widget *pucch_iq_ue_xy_plot;
widget *dl_ul_harq_ue_label;
widget *dl_mcs_xy_plot;
widget *ul_mcs_xy_plot;
logger *pusch_iq_ue_logger;
logger *ul_estimate_ue_logger;
logger *pucch1_energy_ue_threshold_logger;
logger *pucch1_energy_ue_energy_logger;
logger *pucch_iq_ue_logger;
logger *dl_dci_logger[8];
logger *dl_ack_logger[8];
logger *dl_nack_logger[8];
logger *ul_dci_logger[8];
logger *ul_dci_retransmission_logger[8];
logger *ul_ack_logger[8];
logger *ul_nack_logger[8];
logger *dl_mcs_logger;
logger *ul_mcs_logger;
} enb_gui; } enb_gui;
typedef struct { typedef struct {
...@@ -31,6 +55,9 @@ typedef struct { ...@@ -31,6 +55,9 @@ typedef struct {
int *is_on; int *is_on;
int nevents; int nevents;
pthread_mutex_t lock; pthread_mutex_t lock;
enb_gui *e;
int ue; /* what UE is displayed in the UE specific views */
void *database;
} enb_data; } enb_data;
void is_on_changed(void *_d) void is_on_changed(void *_d)
...@@ -86,18 +113,109 @@ static void *gui_thread(void *_g) ...@@ -86,18 +113,109 @@ static void *gui_thread(void *_g)
return NULL; return NULL;
} }
static filter *ticktime_filter(void *database, char *event, int i) static filter *ticktime_filter(void *database, char *event, int i, int ue)
{ {
/* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */ /* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */
return return
filter_and( filter_and(
filter_eq(filter_evarg(database, event, "harq_pid"), filter_int(i)), filter_eq(filter_evarg(database, event, "harq_pid"), filter_int(i)),
filter_and( filter_and(
filter_eq(filter_evarg(database, event, "UE_id"), filter_int(0)), filter_eq(filter_evarg(database, event, "UE_id"), filter_int(ue)),
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0)))); filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0))));
} }
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) static void set_current_ue(gui *g, enb_data *e, int ue)
{
int i;
char s[256];
sprintf(s, "[UE %d] ", ue);
label_set_text(g, e->e->current_ue_label, s);
sprintf(s, "PUSCH IQ [UE %d]", ue);
xy_plot_set_title(g, e->e->pusch_iq_ue_xy_plot, s);
sprintf(s, "UL estimated channel [UE %d]", ue);
xy_plot_set_title(g, e->e->ul_estimate_ue_xy_plot, s);
sprintf(s, "PUCCH1 energy (SR) [UE %d]", ue);
xy_plot_set_title(g, e->e->pucch1_energy_ue_xy_plot, s);
sprintf(s, "PUCCH IQ [UE %d]", ue);
xy_plot_set_title(g, e->e->pucch_iq_ue_xy_plot, s);
sprintf(s, "DL/UL HARQ (x8) [UE %d]", ue);
label_set_text(g, e->e->dl_ul_harq_ue_label, s);
sprintf(s, "DL MCS [UE %d]", ue);
xy_plot_set_title(g, e->e->dl_mcs_xy_plot, s);
sprintf(s, "UL MCS [UE %d]", ue);
xy_plot_set_title(g, e->e->ul_mcs_xy_plot, s);
logger_set_filter(e->e->pusch_iq_ue_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUSCH_IQ", "UE_ID"),
filter_int(ue)));
logger_set_filter(e->e->ul_estimate_ue_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "UE_ID"),
filter_int(ue)));
logger_set_filter(e->e->pucch1_energy_ue_threshold_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_int(ue)));
logger_set_filter(e->e->pucch1_energy_ue_energy_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_int(ue)));
logger_set_filter(e->e->pucch_iq_ue_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUCCH_1AB_IQ", "UE_ID"),
filter_int(ue)));
for (i = 0; i < 8; i++) {
logger_set_filter(e->e->dl_dci_logger[i],
ticktime_filter(e->database, "ENB_PHY_DLSCH_UE_DCI", i, ue));
logger_set_filter(e->e->dl_ack_logger[i],
ticktime_filter(e->database, "ENB_PHY_DLSCH_UE_ACK", i, ue));
logger_set_filter(e->e->dl_nack_logger[i],
ticktime_filter(e->database, "ENB_PHY_DLSCH_UE_NACK", i, ue));
logger_set_filter(e->e->ul_dci_logger[i],
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_DCI", i, ue));
logger_set_filter(e->e->ul_dci_retransmission_logger[i],
ticktime_filter(e->database,
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i, ue));
logger_set_filter(e->e->ul_ack_logger[i],
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_ACK", i, ue));
logger_set_filter(e->e->ul_nack_logger[i],
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_NACK", i, ue));
}
logger_set_filter(e->e->dl_mcs_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "UE_id"),
filter_int(ue)));
logger_set_filter(e->e->ul_mcs_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_ULSCH_UE_DCI", "UE_id"),
filter_int(ue)));
}
static void click(void *private, gui *g,
char *notification, widget *w, void *notification_data)
{
int *d = notification_data;
int button = d[0];
enb_data *ed = private;
enb_gui *e = ed->e;
int ue = ed->ue;
if (button != 1) return;
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
if (w == e->next_ue_button) ue++;
if (pthread_mutex_lock(&ed->lock)) abort();
if (ue != ed->ue) {
set_current_ue(g, ed, ue);
ed->ue = ue;
}
if (pthread_mutex_unlock(&ed->lock)) abort();
}
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
enb_data *ed)
{ {
widget *main_window; widget *main_window;
widget *top_container; widget *top_container;
...@@ -113,7 +231,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -113,7 +231,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
widget *text; widget *text;
view *textview; view *textview;
int i; int i;
widget *w; widget *w, *w2;
view *v; view *v;
logger *l; logger *l;
...@@ -124,7 +242,26 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -124,7 +242,26 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
line = new_container(g, HORIZONTAL); line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1); widget_add_child(g, top_container, line, -1);
logo = new_image(g, openair_logo_png, openair_logo_png_len); logo = new_image(g, openair_logo_png, openair_logo_png_len);
widget_add_child(g, line, logo, -1);
/* logo + prev/next UE buttons */
col = new_container(g, VERTICAL);
widget_add_child(g, col, logo, -1);
w = new_container(g, HORIZONTAL);
widget_add_child(g, col, w, -1);
w2 = new_label(g, "");
widget_add_child(g, w, w2, -1);
e->current_ue_label = w2;
/* TODO: use button widget, not label widget */
w2 = new_label(g, " [prev UE] ");
widget_add_child(g, w, w2, -1);
label_set_clickable(g, w2, 1);
e->prev_ue_button = w2;
w2 = new_label(g, " [next UE] ");
widget_add_child(g, w, w2, -1);
label_set_clickable(g, w2, 1);
e->next_ue_button = w2;
widget_add_child(g, line, col, -1);
input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20); input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20);
widget_add_child(g, line, input_signal_plot, -1); widget_add_child(g, line, input_signal_plot, -1);
xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70); xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70);
...@@ -138,21 +275,20 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -138,21 +275,20 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
g, input_signal_plot, new_color(g, "#0c0c72"), XY_LOOP_MODE); g, input_signal_plot, new_color(g, "#0c0c72"), XY_LOOP_MODE);
logger_add_view(input_signal_log, input_signal_view); logger_add_view(input_signal_log, input_signal_view);
/* UE 0 PUSCH IQ data */ /* UE x PUSCH IQ data */
w = new_xy_plot(g, 55, 55, "PUSCH IQ [UE 0]", 50); w = new_xy_plot(g, 55, 55, "", 50);
e->pusch_iq_ue_xy_plot = w;
widget_add_child(g, line, w, -1); widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, -1000, 1000, -1000, 1000); xy_plot_set_range(g, w, -1000, 1000, -1000, 1000);
l = new_iqlog(h, database, "ENB_PHY_PUSCH_IQ", "nb_rb", l = new_iqlog(h, database, "ENB_PHY_PUSCH_IQ", "nb_rb",
"N_RB_UL", "symbols_per_tti", "pusch_comp"); "N_RB_UL", "symbols_per_tti", "pusch_comp");
v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE); v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
logger_add_view(l, v); logger_add_view(l, v);
logger_set_filter(l, e->pusch_iq_ue_logger = l;
filter_eq(
filter_evarg(database, "ENB_PHY_PUSCH_IQ", "UE_ID"),
filter_int(0)));
/* UE 0 estimated UL channel */ /* UE x estimated UL channel */
w = new_xy_plot(g, 280, 55, "UL estimated channel [UE 0]", 50); w = new_xy_plot(g, 280, 55, "", 50);
e->ul_estimate_ue_xy_plot = w;
widget_add_child(g, line, w, -1); widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, 0, 512*10, -10, 80); xy_plot_set_range(g, w, 0, 512*10, -10, 80);
l = new_framelog(h, database, l = new_framelog(h, database,
...@@ -161,43 +297,57 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -161,43 +297,57 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
framelog_set_update_only_at_sf9(l, 0); framelog_set_update_only_at_sf9(l, 0);
v = new_view_xy(512*10, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE); v = new_view_xy(512*10, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE);
logger_add_view(l, v); logger_add_view(l, v);
logger_set_filter(l, e->ul_estimate_ue_logger = l;
filter_eq(
filter_evarg(database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "UE_ID"),
filter_int(0)));
/* UE 0 PUCCH energy */ /* UE x PUCCH energy */
w = new_xy_plot(g, 128, 55, "PUCCH1 energy (SR) [UE 0]", 50); w = new_xy_plot(g, 128, 55, "", 50);
e->pucch1_energy_ue_xy_plot = w;
widget_add_child(g, line, w, -1); widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, 0, 1024*10, -10, 80); xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
l = new_ttilog(h, database, l = new_ttilog(h, database,
"ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "threshold", 0); "ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "threshold", 0);
v = new_view_tti(10, g, w, new_color(g, "#ff0000")); v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
logger_add_view(l, v); logger_add_view(l, v);
logger_set_filter(l, e->pucch1_energy_ue_threshold_logger = l;
filter_eq(
filter_evarg(database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_int(0)));
l = new_ttilog(h, database, l = new_ttilog(h, database,
"ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "energy", 1); "ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "energy", 1);
v = new_view_tti(10, g, w, new_color(g, "#0c0c72")); v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
logger_add_view(l, v); logger_add_view(l, v);
logger_set_filter(l, e->pucch1_energy_ue_energy_logger = l;
filter_eq(
filter_evarg(database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_int(0)));
/* UE 0 PUCCH IQ data */ /* UE x PUCCH IQ data */
w = new_xy_plot(g, 55, 55, "PUCCH IQ [UE 0]", 50); w = new_xy_plot(g, 55, 55, "", 50);
e->pucch_iq_ue_xy_plot = w;
widget_add_child(g, line, w, -1); widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, -100, 100, -100, 100); xy_plot_set_range(g, w, -2000, 2000, -2000, 2000);
l = new_iqdotlog(h, database, "ENB_PHY_PUCCH_1AB_IQ", "I", "Q"); l = new_iqdotlog(h, database, "ENB_PHY_PUCCH_1AB_IQ", "I", "Q");
v = new_view_xy(500, 10, g, w, new_color(g,"#000"), XY_LOOP_MODE); v = new_view_xy(500, 10, g, w, new_color(g,"#000"), XY_LOOP_MODE);
logger_add_view(l, v); logger_add_view(l, v);
logger_set_filter(l, e->pucch_iq_ue_logger = l;
filter_eq(
filter_evarg(database, "ENB_PHY_PUCCH_1AB_IQ", "UE_ID"), /* UE x DL mcs */
filter_int(0))); line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1);
w = new_xy_plot(g, 128, 55, "", 20);
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
e->dl_mcs_xy_plot = w;
widget_add_child(g, line, w, -1);
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
"ENB_PHY_DLSCH_UE_DCI", "mcs", 0, -1);
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
logger_add_view(l, v);
e->dl_mcs_logger = l;
/* UE x UL mcs */
w = new_xy_plot(g, 128, 55, "", 20);
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
e->ul_mcs_xy_plot = w;
widget_add_child(g, line, w, -1);
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
"ENB_PHY_ULSCH_UE_DCI", "mcs", 0, -1);
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
logger_add_view(l, v);
e->ul_mcs_logger = l;
/* downlink/uplink UE DCIs */ /* downlink/uplink UE DCIs */
widget_add_child(g, top_container, widget_add_child(g, top_container,
...@@ -250,8 +400,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -250,8 +400,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
/* harq processes' ticktime view */ /* harq processes' ticktime view */
widget_add_child(g, top_container, e->dl_ul_harq_ue_label = new_label(g, "");
new_label(g,"DL/UL HARQ (x8) [UE 0]"), -1); widget_add_child(g, top_container, e->dl_ul_harq_ue_label, -1);
line = new_container(g, HORIZONTAL); line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1); widget_add_child(g, top_container, line, -1);
timeline_plot = new_timeline(g, 512, 2*8+2, 3); timeline_plot = new_timeline(g, 512, 2*8+2, 3);
...@@ -271,15 +421,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -271,15 +421,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
/* tick on UL view */ /* tick on UL view */
subview = new_subview_ticktime(timeview, 9, new_color(g,"#bbb"), 3600*1000); subview = new_subview_ticktime(timeview, 9, new_color(g,"#bbb"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
/* DL harq pids */ /* DL DCI */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
timelog = new_ticklog(h, database, "ENB_PHY_DLSCH_UE_DCI", timelog = new_ticklog(h, database, "ENB_PHY_DLSCH_UE_DCI",
"frame", "subframe"); "frame", "subframe");
subview = new_subview_ticktime(timeview, i+1, subview = new_subview_ticktime(timeview, i+1,
new_color(g,"#55f"), 3600*1000); new_color(g,"#55f"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->dl_dci_logger[i] = timelog;
ticktime_filter(database, "ENB_PHY_DLSCH_UE_DCI", i));
} }
/* DL ACK */ /* DL ACK */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
...@@ -288,8 +437,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -288,8 +437,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+1, subview = new_subview_ticktime(timeview, i+1,
new_color(g,"#282"), 3600*1000); new_color(g,"#282"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->dl_ack_logger[i] = timelog;
ticktime_filter(database, "ENB_PHY_DLSCH_UE_ACK", i));
} }
/* DL NACK */ /* DL NACK */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
...@@ -298,10 +446,9 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -298,10 +446,9 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+1, subview = new_subview_ticktime(timeview, i+1,
new_color(g,"#f22"), 3600*1000); new_color(g,"#f22"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->dl_nack_logger[i] = timelog;
ticktime_filter(database, "ENB_PHY_DLSCH_UE_NACK", i));
} }
/* UL harq pids */ /* UL DCI/retransmission without DCI */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
/* first transmission */ /* first transmission */
timelog = new_ticklog(h, database, "ENB_PHY_ULSCH_UE_DCI", timelog = new_ticklog(h, database, "ENB_PHY_ULSCH_UE_DCI",
...@@ -309,17 +456,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -309,17 +456,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+9+1, subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#55f"), 3600*1000); new_color(g,"#55f"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->ul_dci_logger[i] = timelog;
ticktime_filter(database, "ENB_PHY_ULSCH_UE_DCI", i));
/* retransmission */ /* retransmission */
timelog = new_ticklog(h, database, timelog = new_ticklog(h, database,
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", "frame", "subframe"); "ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", "frame", "subframe");
subview = new_subview_ticktime(timeview, i+9+1, subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#99f"), 3600*1000); new_color(g,"#99f"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->ul_dci_retransmission_logger[i] = timelog;
ticktime_filter(database,
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i));
} }
/* UL ACK */ /* UL ACK */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
...@@ -328,8 +472,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -328,8 +472,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+9+1, subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#282"), 3600*1000); new_color(g,"#282"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->ul_ack_logger[i] = timelog;
ticktime_filter(database, "ENB_PHY_ULSCH_UE_ACK", i));
} }
/* UL NACK */ /* UL NACK */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
...@@ -338,8 +481,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -338,8 +481,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+9+1, subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#f22"), 3600*1000); new_color(g,"#f22"), 3600*1000);
logger_add_view(timelog, subview); logger_add_view(timelog, subview);
logger_set_filter(timelog, e->ul_nack_logger[i] = timelog;
ticktime_filter(database, "ENB_PHY_ULSCH_UE_NACK", i));
} }
/* phy/mac/rlc/pdcp/rrc textlog */ /* phy/mac/rlc/pdcp/rrc textlog */
...@@ -416,6 +558,10 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database) ...@@ -416,6 +558,10 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
widget_add_child(g, top_container, text, -1); widget_add_child(g, top_container, text, -1);
container_set_child_growable(g, top_container, text, 1); container_set_child_growable(g, top_container, text, 1);
e->legacy = new_view_textlist(10000, 10, g, text); e->legacy = new_view_textlist(10000, 10, g, text);
set_current_ue(g, ed, 0);
register_notifier(g, "click", e->prev_ue_button, click, ed);
register_notifier(g, "click", e->next_ue_button, click, ed);
} }
void view_add_log(view *v, char *log, event_handler *h, void *database, void view_add_log(view *v, char *log, event_handler *h, void *database,
...@@ -495,7 +641,11 @@ int main(int n, char **v) ...@@ -495,7 +641,11 @@ int main(int n, char **v)
g = gui_init(); g = gui_init();
new_thread(gui_thread, g); new_thread(gui_thread, g);
enb_main_gui(&eg, g, h, database); enb_data.ue = 0;
enb_data.e = &eg;
enb_data.database = database;
enb_main_gui(&eg, g, h, database, &enb_data);
for (i = 0; i < number_of_events; i++) { for (i = 0; i < number_of_events; i++) {
logger *textlog; logger *textlog;
...@@ -525,9 +675,9 @@ int main(int n, char **v) ...@@ -525,9 +675,9 @@ int main(int n, char **v)
on_off(database, "ENB_PHY_PUCCH_1_ENERGY", is_on, 1); on_off(database, "ENB_PHY_PUCCH_1_ENERGY", is_on, 1);
on_off(database, "ENB_PHY_PUCCH_1AB_IQ", is_on, 1); on_off(database, "ENB_PHY_PUCCH_1AB_IQ", is_on, 1);
on_off(database, "LEGACY_RRC_INFO", is_on, 1); on_off(database, "LEGACY_GROUP_INFO", is_on, 1);
on_off(database, "LEGACY_RRC_ERROR", is_on, 1); on_off(database, "LEGACY_GROUP_ERROR", is_on, 1);
on_off(database, "LEGACY_RRC_WARNING", is_on, 1); on_off(database, "LEGACY_GROUP_WARNING", is_on, 1);
view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_DCI", h, database, is_on); view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_DCI", h, database, is_on);
view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_ACK", h, database, is_on); view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_ACK", h, database, is_on);
...@@ -639,7 +789,9 @@ restart: ...@@ -639,7 +789,9 @@ restart:
event e; event e;
e = get_event(enb_data.socket, v, database); e = get_event(enb_data.socket, v, database);
if (e.type == -1) goto restart; if (e.type == -1) goto restart;
if (pthread_mutex_lock(&enb_data.lock)) abort();
handle_event(h, e); handle_event(h, e);
if (pthread_mutex_unlock(&enb_data.lock)) abort();
} }
return 0; return 0;
......
...@@ -13,6 +13,7 @@ struct filter { ...@@ -13,6 +13,7 @@ struct filter {
} v; } v;
int (*eval)(struct filter *this, event e); int (*eval)(struct filter *this, event e);
void (*free)(struct filter *this);
}; };
/****************************************************************************/ /****************************************************************************/
...@@ -52,7 +53,23 @@ int eval_evarg(struct filter *f, event e) ...@@ -52,7 +53,23 @@ int eval_evarg(struct filter *f, event e)
} }
/****************************************************************************/ /****************************************************************************/
/* filter construction functions */ /* free memory functions */
/****************************************************************************/
void free_op2(struct filter *f)
{
free_filter(f->v.op2.a);
free_filter(f->v.op2.b);
free(f);
}
void free_noop(struct filter *f)
{
free(f);
}
/****************************************************************************/
/* filter construction/destruction functions */
/****************************************************************************/ /****************************************************************************/
filter *filter_and(filter *a, filter *b) filter *filter_and(filter *a, filter *b)
...@@ -60,6 +77,7 @@ filter *filter_and(filter *a, filter *b) ...@@ -60,6 +77,7 @@ filter *filter_and(filter *a, filter *b)
struct filter *ret = calloc(1, sizeof(struct filter)); struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort(); if (ret == NULL) abort();
ret->eval = eval_and; ret->eval = eval_and;
ret->free = free_op2;
ret->v.op2.a = a; ret->v.op2.a = a;
ret->v.op2.b = b; ret->v.op2.b = b;
return ret; return ret;
...@@ -70,6 +88,7 @@ filter *filter_eq(filter *a, filter *b) ...@@ -70,6 +88,7 @@ filter *filter_eq(filter *a, filter *b)
struct filter *ret = calloc(1, sizeof(struct filter)); struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort(); if (ret == NULL) abort();
ret->eval = eval_eq; ret->eval = eval_eq;
ret->free = free_op2;
ret->v.op2.a = a; ret->v.op2.a = a;
ret->v.op2.b = b; ret->v.op2.b = b;
return ret; return ret;
...@@ -80,6 +99,7 @@ filter *filter_int(int v) ...@@ -80,6 +99,7 @@ filter *filter_int(int v)
struct filter *ret = calloc(1, sizeof(struct filter)); struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort(); if (ret == NULL) abort();
ret->eval = eval_int; ret->eval = eval_int;
ret->free = free_noop;
ret->v.v = v; ret->v.v = v;
return ret; return ret;
} }
...@@ -97,6 +117,7 @@ filter *filter_evarg(void *database, char *event_name, char *varname) ...@@ -97,6 +117,7 @@ filter *filter_evarg(void *database, char *event_name, char *varname)
f = get_format(database, event_id); f = get_format(database, event_id);
ret->eval = eval_evarg; ret->eval = eval_evarg;
ret->free = free_noop;
ret->v.evarg.event_type = event_id; ret->v.evarg.event_type = event_id;
ret->v.evarg.arg_index = -1; ret->v.evarg.arg_index = -1;
...@@ -114,6 +135,14 @@ filter *filter_evarg(void *database, char *event_name, char *varname) ...@@ -114,6 +135,14 @@ filter *filter_evarg(void *database, char *event_name, char *varname)
return ret; return ret;
} }
void free_filter(filter *_f)
{
struct filter *f;
if (_f == NULL) return;
f = _f;
f->free(f);
}
/****************************************************************************/ /****************************************************************************/
/* eval function */ /* eval function */
/****************************************************************************/ /****************************************************************************/
......
...@@ -12,4 +12,6 @@ filter *filter_evarg(void *database, char *event_name, char *varname); ...@@ -12,4 +12,6 @@ filter *filter_evarg(void *database, char *event_name, char *varname);
int filter_eval(filter *f, event e); int filter_eval(filter *f, event e);
void free_filter(filter *f);
#endif /* _FILTER_H_ */ #endif /* _FILTER_H_ */
...@@ -2,8 +2,8 @@ CC=gcc ...@@ -2,8 +2,8 @@ CC=gcc
CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2 CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \ OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \ gui.o label.o textarea.o event.o xy_plot.o textlist.o notify.o \
timeline.o space.o image.o positioner.o timeline.o space.o image.o
gui.a: $(OBJS) gui.a: $(OBJS)
ar cr gui.a $(OBJS) ar cr gui.a $(OBJS)
......
...@@ -14,6 +14,10 @@ typedef void widget; ...@@ -14,6 +14,10 @@ typedef void widget;
#define DEFAULT_FONT 0 #define DEFAULT_FONT 0
/* tic type for XY plot */
#define XY_PLOT_DEFAULT_TICK 0
#define XY_PLOT_SCROLL_TICK 1
/* key modifiers */ /* key modifiers */
#define KEY_SHIFT (1<<0) #define KEY_SHIFT (1<<0)
#define KEY_CONTROL (1<<1) #define KEY_CONTROL (1<<1)
...@@ -30,6 +34,7 @@ widget *new_toplevel_window(gui *gui, int width, int height, char *title); ...@@ -30,6 +34,7 @@ widget *new_toplevel_window(gui *gui, int width, int height, char *title);
widget *new_container(gui *gui, int vertical); widget *new_container(gui *gui, int vertical);
widget *new_positioner(gui *gui); widget *new_positioner(gui *gui);
widget *new_label(gui *gui, const char *text); widget *new_label(gui *gui, const char *text);
widget *new_textarea(gui *gui, int width, int height, int maxsize);
widget *new_xy_plot(gui *gui, int width, int height, char *label, widget *new_xy_plot(gui *gui, int width, int height, char *label,
int vruler_width); int vruler_width);
widget *new_textlist(gui *gui, int width, int nlines, int background_color); widget *new_textlist(gui *gui, int width, int nlines, int background_color);
...@@ -39,6 +44,9 @@ widget *new_space(gui *gui, int width, int height); ...@@ -39,6 +44,9 @@ widget *new_space(gui *gui, int width, int height);
widget *new_image(gui *gui, unsigned char *data, int length); widget *new_image(gui *gui, unsigned char *data, int length);
void label_set_clickable(gui *gui, widget *label, int clickable); void label_set_clickable(gui *gui, widget *label, int clickable);
void label_set_text(gui *gui, widget *label, char *text);
void textarea_set_text(gui *gui, widget *textarea, char *text);
void container_set_child_growable(gui *_gui, widget *_this, void container_set_child_growable(gui *_gui, widget *_this,
widget *child, int growable); widget *child, int growable);
...@@ -49,6 +57,8 @@ void xy_plot_set_range(gui *gui, widget *this, ...@@ -49,6 +57,8 @@ void xy_plot_set_range(gui *gui, widget *this,
void xy_plot_set_points(gui *gui, widget *this, void xy_plot_set_points(gui *gui, widget *this,
int plot, int npoints, float *x, float *y); int plot, int npoints, float *x, float *y);
void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height); void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height);
void xy_plot_set_title(gui *gui, widget *this, char *label);
void xy_plot_set_tick_type(gui *gui, widget *this, int type);
void textlist_add(gui *gui, widget *this, const char *text, int position, void textlist_add(gui *gui, widget *this, const char *text, int position,
int color); int color);
......
...@@ -31,7 +31,7 @@ extern int volatile gui_logd; ...@@ -31,7 +31,7 @@ extern int volatile gui_logd;
enum widget_type { enum widget_type {
TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL, TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
TIMELINE, SPACE, IMAGE TEXTAREA, TIMELINE, SPACE, IMAGE
}; };
struct widget_list; struct widget_list;
...@@ -117,6 +117,7 @@ struct xy_plot_widget { ...@@ -117,6 +117,7 @@ struct xy_plot_widget {
int wanted_height; int wanted_height;
struct xy_plot_plot *plots; struct xy_plot_plot *plots;
int nplots; int nplots;
int tick_type;
}; };
struct timeline_subline { struct timeline_subline {
...@@ -141,13 +142,24 @@ struct button_widget { ...@@ -141,13 +142,24 @@ struct button_widget {
struct label_widget { struct label_widget {
struct widget common; struct widget common;
const char *t; char *t;
int color; int color;
int width; /* as given by the graphic's backend */ int width; /* as given by the graphic's backend */
int height; /* as given by the graphic's backend */ int height; /* as given by the graphic's backend */
int baseline; /* as given by the graphic's backend */ int baseline; /* as given by the graphic's backend */
}; };
struct textarea_widget {
struct widget common;
char *t;
int tmaxsize;
int color;
int wanted_width;
int wanted_height;
int baseline; /* as given by the graphic's backend */
int text_width; /* as given by the graphic's backend */
};
struct space_widget { struct space_widget {
struct widget common; struct widget common;
int wanted_width; int wanted_width;
......
...@@ -81,3 +81,21 @@ void label_set_clickable(gui *_g, widget *_this, int clickable) ...@@ -81,3 +81,21 @@ void label_set_clickable(gui *_g, widget *_this, int clickable)
gunlock(g); gunlock(g);
} }
void label_set_text(gui *_g, widget *_this, char *text)
{
struct gui *g = _g;
struct label_widget *this = _this;
glock(g);
free(this->t);
this->t = strdup(text); if (this->t == NULL) OOM;
x_text_get_dimensions(g->x, DEFAULT_FONT, text,
&this->width, &this->height, &this->baseline);
send_event(g, REPACK, this->common.id);
gunlock(g);
}
#include "gui.h"
#include "gui_defs.h"
#include "x.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void paint(gui *_gui, widget *_w)
{
struct gui *g = _gui;
struct textarea_widget *t = _w;
LOGD("PAINT textarea '%s'\n", t->t);
x_fill_rectangle(g->x, g->xwin, BACKGROUND_COLOR,
t->common.x, t->common.y,
t->common.width, t->common.height);
x_draw_clipped_string(g->x, g->xwin, DEFAULT_FONT, t->color,
t->common.x + t->common.width - t->text_width,
t->common.y + t->baseline, t->t,
t->common.x, t->common.y,
t->common.width, t->common.height);
}
static void hints(gui *_gui, widget *_w, int *width, int *height)
{
struct textarea_widget *t = _w;
LOGD("HINTS textarea '%s'\n", t->t);
*width = t->wanted_width;
*height = t->wanted_height;
}
widget *new_textarea(gui *_gui, int width, int height, int maxsize)
{
struct gui *g = _gui;
struct textarea_widget *w;
int _;
glock(g);
w = new_widget(g, TEXTAREA, sizeof(struct textarea_widget));
w->t = calloc(maxsize, 1);
if (w->t == NULL) OOM;
w->tmaxsize = maxsize;
w->wanted_width = width;
w->wanted_height = height;
w->color = FOREGROUND_COLOR;
w->text_width = 0;
x_text_get_dimensions(g->x, DEFAULT_FONT, "jlM",
&_, &_, &w->baseline);
w->common.paint = paint;
w->common.hints = hints;
gunlock(g);
return w;
}
/*************************************************************************/
/* public functions */
/*************************************************************************/
void textarea_set_text(gui *_g, widget *_this, char *text)
{
struct gui *g = _g;
struct textarea_widget *this = _this;
int _;
int len = strlen(text);
if (len >= this->tmaxsize) {
fprintf(stderr, "ERROR: string '%s' too big for textarea\n", text);
return;
}
glock(g);
strcpy(this->t, text);
x_text_get_dimensions(g->x, DEFAULT_FONT, text,
&this->text_width, &_, &this->baseline);
send_event(g, DIRTY, this->common.id);
gunlock(g);
}
...@@ -265,7 +265,7 @@ void widget_dirty(gui *_gui, widget *_this) ...@@ -265,7 +265,7 @@ void widget_dirty(gui *_gui, widget *_this)
static const char *names[] = { static const char *names[] = {
"TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST", "TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
"XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE", "IMAGE" "XY_PLOT", "BUTTON", "LABEL", "TEXTAREA", "TIMELINE", "SPACE", "IMAGE"
}; };
const char *widget_name(enum widget_type type) const char *widget_name(enum widget_type type)
{ {
...@@ -277,6 +277,7 @@ const char *widget_name(enum widget_type type) ...@@ -277,6 +277,7 @@ const char *widget_name(enum widget_type type)
case XY_PLOT: case XY_PLOT:
case BUTTON: case BUTTON:
case LABEL: case LABEL:
case TEXTAREA:
case TIMELINE: case TIMELINE:
case SPACE: case SPACE:
case IMAGE: case IMAGE:
......
#include "gui.h" #include "gui.h"
#include "gui_defs.h" #include "gui_defs.h"
#include "x.h" #include "x.h"
#include "../utils.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#if 0
/* this version behaves differently when you resize the XY plot. Say
* you increase the size. The old (smaller) view is put at the center
* of the new view. Everything inside keeps the same size/aspect ratio.
* The other version below resizes the old view so that it fully occupies
* the new view. It may introduce aspect ratio changes, but usage seems
* to suggest it's a better behaviour.
*/
static void paint(gui *_gui, widget *_this) static void paint(gui *_gui, widget *_this)
{ {
struct gui *g = _gui; struct gui *g = _gui;
...@@ -70,7 +79,7 @@ static void paint(gui *_gui, widget *_this) ...@@ -70,7 +79,7 @@ static void paint(gui *_gui, widget *_this)
*/ */
char v[64]; char v[64];
int vwidth, dummy; int vwidth, dummy;
float x = (k * ticstep - allocated_xmin) / int x = (k * ticstep - allocated_xmin) /
(allocated_xmax - allocated_xmin) * (allocated_xmax - allocated_xmin) *
(allocated_plot_width - 1); (allocated_plot_width - 1);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR, x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
...@@ -85,7 +94,7 @@ static void paint(gui *_gui, widget *_this) ...@@ -85,7 +94,7 @@ static void paint(gui *_gui, widget *_this)
this->common.y + this->common.height - this->label_height * 2 + this->common.y + this->common.height - this->label_height * 2 +
this->label_baseline, this->label_baseline,
v); v);
LOGD("tic k %d val %g x %g\n", k, k * ticstep, x); LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
} }
/* vertical tics */ /* vertical tics */
...@@ -112,7 +121,165 @@ static void paint(gui *_gui, widget *_this) ...@@ -112,7 +121,165 @@ static void paint(gui *_gui, widget *_this)
for (k = kmin; k <= kmax; k++) { for (k = kmin; k <= kmax; k++) {
char v[64]; char v[64];
int vwidth, dummy; int vwidth, dummy;
float y = (k * ticstep - allocated_ymin) / int y = (k * ticstep - allocated_ymin) /
(allocated_ymax - allocated_ymin) *
(allocated_plot_height - 1);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width,
this->common.y + FLIP(y),
this->common.x + this->vrule_width + 5,
this->common.y + FLIP(y));
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + this->vrule_width - vwidth - 2,
this->common.y + FLIP(y) - this->label_height/2+this->label_baseline,
v);
}
/* label at bottom, in the middle */
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + (this->common.width - this->label_width) / 2,
this->common.y + this->common.height - this->label_height
+ this->label_baseline,
this->label);
for (n = 0; n < this->nplots; n++) {
/* points */
float ax, bx, ay, by;
ax = (allocated_plot_width-1) / (allocated_xmax - allocated_xmin);
bx = -ax * allocated_xmin;
ay = (allocated_plot_height-1) / (allocated_ymax - allocated_ymin);
by = -ay * allocated_ymin;
for (i = 0; i < this->plots[n].npoints; i++) {
int x, y;
x = ax * this->plots[n].x[i] + bx;
y = ay * this->plots[n].y[i] + by;
if (x >= 0 && x < allocated_plot_width &&
y >= 0 && y < allocated_plot_height)
x_add_point(g->x,
this->common.x + this->vrule_width + x,
this->common.y + FLIP(y));
}
x_plot_points(g->x, g->xwin, this->plots[n].color);
}
}
#endif
static void paint(gui *_gui, widget *_this)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
int allocated_plot_width;
int allocated_plot_height;
float pxsize;
float ticdist;
float tic;
float ticstep;
int k, kmin, kmax;
float allocated_xmin, allocated_xmax;
float allocated_ymin, allocated_ymax;
int i;
int n;
char v[64];
int vwidth, dummy;
# define FLIP(v) (-(v) + allocated_plot_height-1)
LOGD("PAINT xy plot xywh %d %d %d %d\n", this->common.x, this->common.y, this->common.width, this->common.height);
//x_draw_rectangle(g->x, g->xwin, 1, this->common.x, this->common.y, this->common.width, this->common.height);
allocated_plot_width = this->common.width - this->vrule_width;
allocated_plot_height = this->common.height - this->label_height * 2;
if (allocated_plot_width <= 1 || allocated_plot_height <= 1) {
WARN("PAINT xy plot: width (%d) or height (%d) is wrong, not painting\n",
this->common.width, this->common.height);
return;
}
/* plot zone */
/* TODO: refine height - height of hrule text may be != from label */
x_draw_rectangle(g->x, g->xwin, 1,
this->common.x + this->vrule_width,
this->common.y,
this->common.width - this->vrule_width -1, /* -1 to see right border */
this->common.height - this->label_height * 2);
/* horizontal tics */
pxsize = (this->xmax - this->xmin) / allocated_plot_width;
ticdist = 100;
tic = floor(log10(ticdist * pxsize));
ticstep = powf(10, tic);
allocated_xmin = this->xmin;
allocated_xmax = this->xmax;
/* adjust tic if too tight */
LOGD("pre x ticstep %g\n", ticstep);
while (1) {
if (ticstep / (allocated_xmax - allocated_xmin)
* (allocated_plot_width - 1) > 40) break;
ticstep *= 2;
}
LOGD("post x ticstep %g\n", ticstep);
LOGD("xmin/max %g %g width allocated %d alloc xmin/max %g %g ticstep %g\n", this->xmin, this->xmax, allocated_plot_width, allocated_xmin, allocated_xmax, ticstep);
kmin = ceil(allocated_xmin / ticstep);
kmax = floor(allocated_xmax / ticstep);
for (k = kmin; k <= kmax; k++) {
/*
(k * ticstep - allocated_xmin) / (allocated_max - allocated_xmin) =
(x - 0) / (allocated_plot_width-1 - 0)
*/
int x = (k * ticstep - allocated_xmin) /
(allocated_xmax - allocated_xmin) *
(allocated_plot_width - 1);
int px;
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2 - 5);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
/* do not draw after the widget ('width-1' for if we use 'width'
* it is still off by 1 pixel for whatever reason) */
px = this->vrule_width + x - vwidth/2;
if (px + vwidth > this->common.width-1)
px = this->common.width-1 - vwidth;
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + px,
this->common.y + this->common.height - this->label_height * 2 +
this->label_baseline,
v);
LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
}
/* vertical tics */
allocated_ymin = this->ymin;
allocated_ymax = this->ymax;
switch (this->tick_type) {
case XY_PLOT_DEFAULT_TICK:
pxsize = (this->ymax - this->ymin) / allocated_plot_height;
ticdist = 30;
tic = floor(log10(ticdist * pxsize));
ticstep = powf(10, tic);
/* adjust tic if too tight */
LOGD("pre y ticstep %g\n", ticstep);
while (1) {
if (ticstep / (allocated_ymax - allocated_ymin)
* (allocated_plot_height - 1) > 20) break;
ticstep *= 2;
}
LOGD("post y ticstep %g\n", ticstep);
LOGD("ymin/max %g %g height allocated %d alloc "
"ymin/max %g %g ticstep %g\n", this->ymin, this->ymax,
allocated_plot_height, allocated_ymin, allocated_ymax, ticstep);
kmin = ceil(allocated_ymin / ticstep);
kmax = floor(allocated_ymax / ticstep);
for (k = kmin; k <= kmax; k++) {
int y = (k * ticstep - allocated_ymin) /
(allocated_ymax - allocated_ymin) * (allocated_ymax - allocated_ymin) *
(allocated_plot_height - 1); (allocated_plot_height - 1);
sprintf(v, "%g", k * ticstep); sprintf(v, "%g", k * ticstep);
...@@ -127,6 +294,26 @@ static void paint(gui *_gui, widget *_this) ...@@ -127,6 +294,26 @@ static void paint(gui *_gui, widget *_this)
this->common.y + FLIP(y)-this->label_height/2+this->label_baseline, this->common.y + FLIP(y)-this->label_height/2+this->label_baseline,
v); v);
} }
break;
case XY_PLOT_SCROLL_TICK:
/* print only max value, formatted using 'bps' for readability */
bps(v, this->ymax, "");
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + this->vrule_width - vwidth - 2,
this->common.y + +this->label_baseline,
v);
/* vertically divide into 5 */
for (k = 1; k < 5; k++) {
int y = round((k * (allocated_plot_height - 1)) / 5.);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width,
this->common.y + y,
this->common.x + this->vrule_width + 5,
this->common.y + y);
}
break;
} /* swich (this->tick_type) */
/* label at bottom, in the middle */ /* label at bottom, in the middle */
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR, x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
...@@ -191,6 +378,7 @@ widget *new_xy_plot(gui *_gui, int width, int height, char *label, ...@@ -191,6 +378,7 @@ widget *new_xy_plot(gui *_gui, int width, int height, char *label,
w->ymax = 1; w->ymax = 1;
w->plots = NULL; w->plots = NULL;
w->nplots = 0; w->nplots = 0;
w->tick_type = XY_PLOT_DEFAULT_TICK;
w->common.paint = paint; w->common.paint = paint;
w->common.hints = hints; w->common.hints = hints;
...@@ -290,3 +478,36 @@ void xy_plot_get_dimensions(gui *_gui, widget *_this, int *width, int *height) ...@@ -290,3 +478,36 @@ void xy_plot_get_dimensions(gui *_gui, widget *_this, int *width, int *height)
gunlock(g); gunlock(g);
} }
void xy_plot_set_title(gui *_gui, widget *_this, char *label)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
glock(g);
free(this->label);
this->label = strdup(label); if (this->label == NULL) OOM;
/* TODO: be sure calling X there is valid wrt "global model" (we are
* not in the "gui thread") */
x_text_get_dimensions(g->x, DEFAULT_FONT, label,
&this->label_width, &this->label_height, &this->label_baseline);
send_event(g, REPACK, this->common.id);
gunlock(g);
}
void xy_plot_set_tick_type(gui *_gui, widget *_this, int type)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
glock(g);
this->tick_type = type;
send_event(g, DIRTY, this->common.id);
gunlock(g);
}
...@@ -2,7 +2,7 @@ CC=gcc ...@@ -2,7 +2,7 @@ CC=gcc
CFLAGS=-Wall -g -pthread -I.. CFLAGS=-Wall -g -pthread -I..
OBJS=logger.o textlog.o framelog.o ttilog.o timelog.o ticklog.o iqlog.o \ OBJS=logger.o textlog.o framelog.o ttilog.o timelog.o ticklog.o iqlog.o \
iqdotlog.o iqdotlog.o ticked_ttilog.o throughputlog.o
logger.a: $(OBJS) logger.a: $(OBJS)
ar cr logger.a $(OBJS) ar cr logger.a $(OBJS)
......
#include "logger.h" #include "logger.h"
#include "logger_defs.h" #include "logger_defs.h"
#include "filter/filter.h"
#include <stdlib.h> #include <stdlib.h>
void logger_add_view(logger *_l, view *v) void logger_add_view(logger *_l, view *v)
...@@ -13,5 +14,6 @@ void logger_add_view(logger *_l, view *v) ...@@ -13,5 +14,6 @@ void logger_add_view(logger *_l, view *v)
void logger_set_filter(logger *_l, void *filter) void logger_set_filter(logger *_l, void *filter)
{ {
struct logger *l = _l; struct logger *l = _l;
free_filter(l->filter);
l->filter = filter; l->filter = filter;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment