diff options
Diffstat (limited to 'python/gui')
-rwxr-xr-x | python/gui/api.py | 47 | ||||
-rw-r--r-- | python/gui/static/css/odr.css | 14 | ||||
-rw-r--r-- | python/gui/static/js/odr-home.js | 240 | ||||
-rw-r--r-- | python/gui/static/js/odr-predistortion.js | 129 | ||||
-rw-r--r-- | python/gui/static/js/odr-rcvalues.js | 29 | ||||
-rw-r--r-- | python/gui/templates/about.html | 42 | ||||
-rw-r--r-- | python/gui/templates/home.html | 72 | ||||
-rw-r--r-- | python/gui/templates/modulator.html | 40 | ||||
-rw-r--r-- | python/gui/templates/predistortion.html | 129 | ||||
-rw-r--r-- | python/gui/templates/rcvalues.html | 39 |
10 files changed, 586 insertions, 195 deletions
diff --git a/python/gui/api.py b/python/gui/api.py index bff224e..f9e0ad0 100755 --- a/python/gui/api.py +++ b/python/gui/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2018 +# Copyright (C) 2019 # Matthias P. Braendli, matthias.braendli@mpb.li # # http://www.opendigitalradio.org @@ -80,8 +80,18 @@ class API: return send_error(str(e)) return send_ok() else: - cherrypy.response.status = 400 - return send_error("POST only") + if all(p in kwargs for p in ('controllable', 'param')): + try: + return send_ok(self.mod_rc.get_param_value(kwargs['controllable'], kwargs['param'])) + except IOError as e: + cherrypy.response.status = 503 + return send_error(str(e)) + except ValueError as e: + cherrypy.response.status = 503 + return send_error(str(e)) + else: + cherrypy.response.status = 400 + return send_error("missing 'controllable' or 'param' GET parameters") def _wrap_dpd(self, method, data=None): try: @@ -89,12 +99,12 @@ class API: return send_ok(reply) except ValueError as e: cherrypy.response.status = 503 - return send_error("YAML-RPC call error: {}".format(e)) + return send_error("DPDCE remote procedure call error: {}".format(e)) except TimeoutError as e: cherrypy.response.status = 503 - return send_error("YAML-RPC timeout: {}".format(e)) + return send_error("DPDCE remote procedure call timed out") cherrypy.response.status = 500 - return send_error("YAML-RPC unknown error") + return send_error("Unknown DPDCE remote procedure error error") @cherrypy.expose @cherrypy.tools.json_out() @@ -107,6 +117,15 @@ class API: @cherrypy.expose @cherrypy.tools.json_out() + def dpd_adapt(self, **kwargs): + if cherrypy.request.method == 'POST': + return self._wrap_dpd("adapt") + else: + cherrypy.response.status = 400 + return send_error("POST only") + + @cherrypy.expose + @cherrypy.tools.json_out() def dpd_reset(self, **kwargs): if cherrypy.request.method == 'POST': return self._wrap_dpd("reset") @@ -116,12 +135,20 @@ class API: @cherrypy.expose @cherrypy.tools.json_out() - def dpd_settings(self, setting: str, value: str, **kwargs): + def dpd_restore_dump(self, **kwargs): if cherrypy.request.method == 'POST': - data = {'setting': setting, 'value': value} - return self._wrap_dpd("set_setting", data) + cl = cherrypy.request.headers['Content-Length'] + rawbody = cherrypy.request.body.read(int(cl)) + params = json.loads(rawbody.decode()) + if 'dump_id' in params: + data = {'dump_id': params['dump_id']} + return self._wrap_dpd("restore_dump", data) + else: + cherrypy.response.status = 400 + return send_error("Missing dump_id") else: - return self._wrap_dpd("get_settings") + cherrypy.response.status = 400 + return send_error("POST only") @cherrypy.expose @cherrypy.tools.json_out() diff --git a/python/gui/static/css/odr.css b/python/gui/static/css/odr.css new file mode 100644 index 0000000..1710464 --- /dev/null +++ b/python/gui/static/css/odr.css @@ -0,0 +1,14 @@ +.glyphicon-refresh-animate { + -animation: spin 1.8s infinite linear; + -webkit-animation: spin2 1.8s infinite linear; +} + +@-webkit-keyframes spin2 { + from { -webkit-transform: rotate(0deg);} + to { -webkit-transform: rotate(360deg);} +} + +@keyframes spin { + from { transform: scale(1) rotate(0deg);} + to { transform: scale(1) rotate(360deg);} +} diff --git a/python/gui/static/js/odr-home.js b/python/gui/static/js/odr-home.js new file mode 100644 index 0000000..b74c4c8 --- /dev/null +++ b/python/gui/static/js/odr-home.js @@ -0,0 +1,240 @@ +// Copyright (C) 2019 +// Matthias P. Braendli, matthias.braendli@mpb.li +// +// http://www.opendigitalradio.org +// +// This file is part of ODR-DabMod. +// +// ODR-DabMod is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// ODR-DabMod 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. +// + +function apiRequestChain(uri, get_data, success_callback, fail_callback) { + $.ajax({ + type: "GET", + url: uri, + data: get_data, + contentType: 'application/json', + dataType: 'json', + + error: function(data) { + console.log("GET " + JSON.stringify(get_data) + " error: " + data.responseText); + fail_callback(data.responseText); + }, + success: function(data) { + if (data.status == 'ok') { + success_callback(data.data); + } + else { + fail_callback(data.data); + } + }, + }); +} + +function mark_pending(id, comment) { + document.getElementById(id).className = "glyphicon glyphicon-refresh glyphicon-refresh-animate"; + + if (comment) { + document.getElementById(id + "_comment").innerHTML = comment; + } +} + +var failure_encountered = false; + +function mark_overall_ok() { + if (!failure_encountered) { + document.getElementById("overall_state").className = "glyphicon glyphicon-ok"; + } +} + +function mark_ok(id, comment) { + document.getElementById(id).className = "glyphicon glyphicon-ok"; + + if (comment) { + document.getElementById(id + "_comment").innerHTML = comment; + } +} + +function mark_fail(id, reason) { + failure_encountered = true; + + var el = document.getElementById(id); + el.className = "glyphicon glyphicon-remove"; + el.style.color = "#FF3333"; + + document.getElementById(id + "_comment").innerHTML = reason; + + var overall = document.getElementById("overall_state"); + overall.style.color = "#FF8833"; + overall.className = "glyphicon glyphicon-alert"; +} + +function check_rc() { + mark_pending('is_rc_ok'); + apiRequestChain("/api/parameter", + {controllable: 'sdr', param: 'freq'}, + function(data) { + mark_ok('is_rc_ok'); + check_modulating(0); + }, + function(data) { + mark_fail('is_rc_ok', JSON.parse(data)['reason']); + }); +} + +function check_modulating(last_num_frames) { + mark_pending('is_modulating'); + apiRequestChain("/api/parameter", + {controllable: 'sdr', param: 'frames'}, + function(data) { + if (data > 0) { + if (last_num_frames == 0) { + setTimeout(function() { check_modulating(data); }, 200); + } + else { + if (data == last_num_frames) { + mark_fail('is_modulating', "Frame counter not incrementing: " + data); + } + else { + mark_ok('is_modulating', "Number of frames modulated: " + data); + } + check_gpsdo_ok(); + } + } + else { + mark_fail('is_modulating', 'number of frames is 0'); + } + }, + function(data) { + mark_fail('is_modulating', data); + }); +} + +function check_gpsdo_ok() { + mark_pending('is_gpsdo_ok'); + apiRequestChain("/api/parameter", + {controllable: 'sdr', param: 'gpsdo_num_sv'}, + function(data) { + if (data > 3) { + mark_ok('is_gpsdo_ok', "Number of SVs used: " + data); + } + else { + mark_fail('is_gpsdo_ok', "Number of SVs (" + data + ") is too low"); + } + check_underrunning(0, 0); + check_late(0, 0); + }, + function(data) { + mark_fail('is_gpsdo_ok', json.parse(data)['reason']); + }); +} + + +function check_underrunning(iteration, first_underruns) { + var n_checks = 3; + + apiRequestChain("/api/parameter", + {controllable: 'sdr', param: 'underruns'}, + function(data) { + if (iteration == 0) { + mark_pending('is_underrunning', "Checking for underruns"); + setTimeout(function() { check_underrunning(iteration+1, data); }, 2000); + } + else if (iteration < n_checks) { + mark_pending('is_underrunning', "Check " + iteration + "/" + n_checks + "..."); + setTimeout(function() { check_underrunning(iteration+1, first_underruns); }, 2000); + } + else { + if (data == first_underruns) { + mark_ok('is_underrunning', "Number of underruns is not increasing: " + data); + } + else { + mark_fail('is_underrunning', "Underruns observed in last " + n_checks + " seconds: " + data); + } + check_rate_4x(); + } + }, + function(data) { + mark_fail('is_underrunning', data); + }); +} + +function check_late(iteration, first_late) { + var n_checks = 3; + + apiRequestChain("/api/parameter", + {controllable: 'sdr', param: 'latepackets'}, + function(data) { + if (iteration == 0) { + mark_pending('is_late', "Checking for late packets"); + setTimeout(function() { check_late(iteration+1, data); }, 2000); + } + else if (iteration < n_checks) { + mark_pending('is_late', "Check " + iteration + "/" + n_checks + "..."); + setTimeout(function() { check_late(iteration+1, first_late); }, 2000); + } + else { + if (data == first_late) { + mark_ok('is_late', "Number of late packets is not increasing: " + data); + } + else { + mark_fail('is_late', "Late packets observed in last " + n_checks + " seconds: " + data); + } + } + }, + function(data) { + mark_fail('is_late', data); + }); +} + +function check_rate_4x() { + mark_pending('is_rate_4x'); + apiRequestChain("/api/parameter", + {controllable: 'modulator', param: 'rate'}, + function(data) { + if (data == 8192000) { + mark_ok('is_rate_4x', "Samplerate: " + data); + } + else { + mark_fail('is_rate_4x', "Samplerate is not 8192ksps: " + data); + } + check_dpdce_running(); + }, + function(data) { + mark_fail('is_rate_4x', JSON.parse(data)['reason']); + }); +} + +function check_dpdce_running() { + mark_pending('is_dpdce_running'); + apiRequestChain("/api/dpd_results", + {}, + function(data) { + mark_ok('is_dpdce_running', "State: " + data['state']); + mark_overall_ok(); + }, + function(data) { + mark_fail('is_dpdce_running', JSON.parse(data)['reason']); + }); +} + +$(function(){ + setTimeout(check_rc, 20); +}); + + +// ToolTip init +$(function(){ + $('[data-toggle="tooltip"]').tooltip(); +}); diff --git a/python/gui/static/js/odr-predistortion.js b/python/gui/static/js/odr-predistortion.js index 04d2773..4dae068 100644 --- a/python/gui/static/js/odr-predistortion.js +++ b/python/gui/static/js/odr-predistortion.js @@ -1,4 +1,4 @@ -// Copyright (C) 2018 +// Copyright (C) 2019 // Matthias P. Braendli, matthias.braendli@mpb.li // // http://www.opendigitalradio.org @@ -18,6 +18,8 @@ // You should have received a copy of the GNU General Public License // along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. +var adapt_dumps = []; + function resultrefresh() { var jqxhr = doApiRequestGET("/api/dpd_results", function(data) { var summary = ""; @@ -29,6 +31,30 @@ function resultrefresh() { $('#dpdresults').html(summary); $('#dpdstatus').text(data['state']); + var percentage = data['stateprogress']; + if (percentage > 100) { + percentage = 100; + } + $('#dpdprogress').css('width', percentage + '%'); + $('#dpdprogresstext').text(percentage + '%'); + + if (data['statplot']) { + $('#dpdcapturestats').attr('src', data['statplot']); + } + else { + $('#dpdcapturestats').attr('src', ""); + } + + $('#dpdmodeldata').html(data['modeldata']); + + if (data['modelplot']) { + $('#dpdmodelplot').attr('src', data['modelplot']); + } + else { + $('#dpdmodelplot').attr('src', ""); + } + + adapt_dumps = data['adapt_dumps']; }); jqxhr.always(function() { @@ -36,8 +62,32 @@ function resultrefresh() { }); } +function adaptdumpsrefresh() { + $('#dpdadaptdumps').html(""); + + $.each(adapt_dumps, function(i, item) { + console.log(item); + + if (isNaN(+item)) { + $('#dpdadaptdumps').append($('<option>', { + value: item, + text : "DPD settings from " + item, + })); + } + else { + var d = new Date(0); + d.setUTCSeconds(item); + + $('#dpdadaptdumps').append($('<option>', { + value: item, + text : "DPD settings from " + d.toISOString(), + })); + } + }); +} + $(function(){ - setTimeout(resultrefresh, 2000); + setTimeout(resultrefresh, 20); $('#calibratebtn').click(function() { doApiRequestPOST("/api/dpd_calibrate", {}, function(data) { @@ -45,72 +95,39 @@ $(function(){ }); }); -}); - -/* -function calibraterefresh() { - doApiRequestGET("/api/calibrate", function(data) { - var text = "Captured TX signal and feedback." + - " TX median: " + data['tx_median'] + - " RX median: " + data['rx_median'] + - " with relative timestamp offset " + - (data['tx_ts'] - data['rx_ts']) + - " and measured offset " + data['coarse_offset'] + - ". Correlation: " + data['correlation']; - $('#calibrationresults').text(text); + $('#triggerbtn').click(function() { + doApiRequestPOST("/api/dpd_trigger_run", {}, function(data) { + console.log("run succeeded: " + JSON.stringify(data)); + }); }); -} -$(function(){ - $('#refreshframesbtn').click(function() { - var d = new Date(); - var n = d.getTime(); - $('#txframeimg').src = "dpd/txframe.png?cachebreak=" + n; - $('#rxframeimg').src = "dpd/rxframe.png?cachebreak=" + n; + $('#adaptbtn').click(function() { + doApiRequestPOST("/api/dpd_adapt", {}, function(data) { + console.log("adapt succeeded: " + JSON.stringify(data)); + }); }); - $('#capturebutton').click(function() { - doApiRequestPOST("/api/trigger_capture", {}, function(data) { - console.log("trigger_capture succeeded: " + JSON.stringify(data)); + + $('#resetbtn').click(function() { + doApiRequestPOST("/api/dpd_reset", {}, function(data) { + console.log("reset succeeded: " + JSON.stringify(data)); }); }); - $('#dpdstatusbutton').click(function() { - doApiRequestGET("/api/dpd_status", function(data) { - console.log("dpd_status succeeded: " + JSON.stringify(data)); - $('#histogram').text(data.histogram); - $('#capturestatus').text(data.capture.status); - $('#capturelength').text(data.capture.length); - $('#tx_median').text(data.capture.tx_median); - $('#rx_median').text(data.capture.rx_median); - }); + $('#adaptdumpsrefreshbtn').click(adaptdumpsrefresh); + + $('#adaptdumpsload').click(function() { + var elt = document.getElementById("dpdadaptdumps"); - $.ajax({ - type: "GET", - url: "/api/dpd_capture_pointcloud", - - error: function(data) { - if (data.status == 500) { - var errorWindow = window.open("", "_self"); - errorWindow.document.write(data.responseText); - } - else { - $.gritter.add({ title: 'API', - text: "AJAX failed: " + data.statusText, - image: '/fonts/warning.png', - sticky: true, - }); - } - }, - success: function(data) { - $('#dpd_pointcloud').value(data) + if (elt.selectedIndex != -1) { + var selectedoption = elt.options[elt.selectedIndex].value; + doApiRequestPOST("/api/dpd_restore_dump", {dump_id: selectedoption}, function(data) { + console.log("reset succeeded: " + JSON.stringify(data)); + }); } - }) }); }); -*/ - // ToolTip init $(function(){ diff --git a/python/gui/static/js/odr-rcvalues.js b/python/gui/static/js/odr-rcvalues.js index f49674c..486a8a7 100644 --- a/python/gui/static/js/odr-rcvalues.js +++ b/python/gui/static/js/odr-rcvalues.js @@ -31,22 +31,28 @@ function requestStatus() { doApiRequestGET("/api/rc_parameters", function(data) { console.log(data); - let keys = Object.keys(data); - keys.sort(); + let controllable_names = Object.keys(data); + controllable_names.sort(); var key1; - for (key1 in keys) { - let keys2 = Object.keys(data[keys[key1]]); - keys2.sort(); + for (key1 in controllable_names) { + let param_names = Object.keys(data[controllable_names[key1]]); + param_names.sort(); var key2; - for (key2 in keys2) { - var param = data[keys[key1]][keys2[key2]]; - var key = keys[key1] + "_" + keys2[key2]; + for (key2 in param_names) { + var name_controllable = controllable_names[key1]; + var name_param = param_names[key2]; + var key = name_controllable + "_" + name_param; + + var param = data[name_controllable][name_param]; var valueentry = '<input type="text" id="input'+key+'" ' + 'value="' + param['value'] + '">' + '<button type="button" class="btn btn-xs btn-warning"' + - 'id="button'+key+'" >upd</button>'; + 'id="button'+key+'" ' + + 'data-controllable="'+name_controllable+'" ' + + 'data-param="'+name_param+'" ' + + '>upd</button>'; $('#rctable > tbody:last').append( '<tr><td>'+key+'</td>'+ @@ -54,7 +60,10 @@ function requestStatus() { '<td>'+param['help']+'</td></tr>'); $('#button'+key).click(function() { - buttonSetRc("input"+key, key1, key2); + var attr_c = this.getAttribute('data-controllable'); + var attr_p = this.getAttribute('data-param'); + var k = attr_c + "_" + attr_p; + buttonSetRc("input"+k, attr_c, attr_p); }); } } diff --git a/python/gui/templates/about.html b/python/gui/templates/about.html index 3a05230..b781d54 100644 --- a/python/gui/templates/about.html +++ b/python/gui/templates/about.html @@ -1,24 +1,3 @@ -<!-- - Copyright (C) 2018 - Matthias P. Braendli, matthias.braendli@mpb.li - -This file is part of ODR-DabMod. - -ODR-DabMod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -ODR-DabMod 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. ---> - - <!DOCTYPE html> <html lang="en"> @@ -63,3 +42,24 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. </html> +<!-- + Copyright (C) 2018 + Matthias P. Braendli, matthias.braendli@mpb.li + +This file is part of ODR-DabMod. + +ODR-DabMod is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +ODR-DabMod 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. +--> + + diff --git a/python/gui/templates/home.html b/python/gui/templates/home.html index 5cb29f8..398df37 100644 --- a/python/gui/templates/home.html +++ b/python/gui/templates/home.html @@ -1,3 +1,59 @@ +<!DOCTYPE html> +<html lang="en"> + +{% include 'head.html' %} + +<body> + {% include 'body-nav.html' %} + + <div class="container-fluid"> + <div class="jumbotron"> + <h1>Opendigitalradio</h1><h2>ODR-DabMod Status Check + <span id="overall_state" class="glyphicon glyphicon-refresh glyphicon-refresh-animate"></span> + </h2> + <div class="well well-sm"> + <p>ODR-DabMod + </p> + <ul> + <li>Answering to RC: + <span id="is_rc_ok" class="glyphicon glyphicon-question-sign"></span> + <span id="is_rc_ok_comment"><span> + </li> + <li>Frame generation: + <span id="is_modulating" class="glyphicon glyphicon-question-sign"></span> + <span id="is_modulating_comment"><span> + </li> + <li>GPSDO status: + <span id="is_gpsdo_ok" class="glyphicon glyphicon-question-sign"></span> + <span id="is_gpsdo_ok_comment"><span> + </li> + <li>Underruns: + <span id="is_underrunning" class="glyphicon glyphicon-question-sign"></span> + <span id="is_underrunning_comment"><span> + </li> + <li>Late packets: + <span id="is_late" class="glyphicon glyphicon-question-sign"></span> + <span id="is_late_comment"><span> + </li> + </ul> + + <p>Checking predistortion + <ul> + <li>Sample rate at 4x native rate: + <span id="is_rate_4x" class="glyphicon glyphicon-question-sign"></span> + <span id="is_rate_4x_comment"><span> + </li> + <li>DPDCE running: + <span id="is_dpdce_running" class="glyphicon glyphicon-question-sign"></span> + <span id="is_dpdce_running_comment"><span> + </li> + </ul> + </div> + </div> + </div> +</body> +</html> + <!-- Copyright (C) 2018 Matthias P. Braendli, matthias.braendli@mpb.li @@ -17,19 +73,3 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. --> - -<!DOCTYPE html> -<html lang="en"> - -{% include 'head.html' %} - -<body> - {% include 'body-nav.html' %} - - <div class="container-fluid"> - <div class="jumbotron"> - <h1>Opendigitalradio</h1><h2>ODR-DabMod Interface</h2> - </div> - </div> -</body> -</html> diff --git a/python/gui/templates/modulator.html b/python/gui/templates/modulator.html index 6deffb1..016344a 100644 --- a/python/gui/templates/modulator.html +++ b/python/gui/templates/modulator.html @@ -1,23 +1,3 @@ -<!-- - Copyright (C) 2018 - Matthias P. Braendli, matthias.braendli@mpb.li - -This file is part of ODR-DabMod. - -ODR-DabMod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -ODR-DabMod 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. ---> - <!DOCTYPE html> <html lang="en"> @@ -71,3 +51,23 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. </div> </body> </html> + +<!-- + Copyright (C) 2018 + Matthias P. Braendli, matthias.braendli@mpb.li + +This file is part of ODR-DabMod. + +ODR-DabMod is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +ODR-DabMod 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. +--> diff --git a/python/gui/templates/predistortion.html b/python/gui/templates/predistortion.html index cc5ecb0..62e8503 100644 --- a/python/gui/templates/predistortion.html +++ b/python/gui/templates/predistortion.html @@ -1,23 +1,3 @@ -<!-- - Copyright (C) 2018 - Matthias P. Braendli, matthias.braendli@mpb.li - -This file is part of ODR-DabMod. - -ODR-DabMod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -ODR-DabMod 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. ---> - <!DOCTYPE html> <html lang="en"> @@ -31,42 +11,87 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. <div class="panel panel-default"> <div class="panel-heading">Status and calibration</div> <div class="panel-body"> - <div>Current DPDCE status: <span id="dpdstatus" style="font-weight:bold;">N/A</span> - <div class="well well-sm" id="dpdresults">N/A</div> + + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-4"> + <h2>Current DPDCE status</h2> + <div> + <div id="dpdstatus" style="font-weight:bold;">N/A</div> + <div class="progress"> + <div id="dpdprogress" class="progress-bar" role="progressbar" style="width:0%"> + <span id="dpdprogresstext"></span> + </div> + </div> + </div> + <div class="well well-sm" id="dpdresults">N/A</div> + </div> + <div class="col-sm-4"> + <h2>List of saved DPD settings</h2> + <!--TODO: 'erase' and 'clear' buttons. Show DPD settings in tooltip?--> + <p>This list contains previously used predistortion settings that you + can recall.</p> + <p> + <select id="dpdadaptdumps" size="8" style="width:70%" multiple></select> + </p> + <p> + <button type="button" class="btn btn-sm btn-info" id="adaptdumpsrefreshbtn">Refresh + </button> + <button type="button" class="btn btn-sm btn-warning" id="adaptdumpsload">Load and Apply + </button> + </p> + </div> + <div class="col-sm-4"> + <h2>Summary</h2> + <p>Calibration needs to be done once before the PA model + can be trained. Every time calibration is changed, the predistortion + parameters are invalidated!</p> + <p>Once calibration succeeded and correct RX gain is set, you + can trigger a capture and model the PA. Usually, several capture + runs are needed before the model can be trained.</p> + <p>The capture and model analysis will calculate a new set of + DPD model data, that you can apply using the Update Predistorter button.</p> + <p>The reset button allows you to reset the computation engine. It does not + modify the currently active predistorter.</p> + </div> + </div> </div> - <div>Calibration needs to be done once before the PA model - can be trained. Every time calibration is changed, the predistortion - parameters are invalidated!</div> <button type="button" class="btn btn-sm btn-warning" id="calibratebtn"> Calibrate</button> + <button type="button" class="btn btn-sm btn-warning" id="triggerbtn"> + Trigger Capture and PA Modeling</button> + <button type="button" class="btn btn-sm btn-warning" id="adaptbtn"> + Update Predistorter</button> + <button type="button" class="btn btn-sm btn-info" id="resetbtn"> + Reset Capture and Model</button> </div> </div> - <!-- + <div class="panel panel-default"> - <div class="panel-heading">Capture TX and RX frames</div> + <div class="panel-heading">Capture Statistics</div> <div class="panel-body"> - <div> - <img id="txframeimg" src="dpd/txframe.png" width="320" height="240" /> - <img id="rxframeimg" src="dpd/rxframe.png" width="320" height="240" /> - </div> - <div> - <button type="button" class="btn btn-sm btn-info" id="refreshframesbtn"> - Refresh</button> - </div> + <img id="dpdcapturestats" /> </div> </div> - <div class="panel panel-default"> - <div class="panel-heading">Capture</div> + <div class="panel-heading">AM/AM and AM/PM Model</div> <div class="panel-body"> - <div>On pressing this button, - the DPDCE will trigger a capture and a quick data - analysis, without updating any DPD models.</div> - <button type="button" class="btn btn-sm btn-info" id="capturebutton"> - Capture</button> + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-2"> + <p>Model data:</p> + </div> + <div class="col-sm-10"> + <pre id="dpdmodeldata"></pre> + </div> + </div> + </div> + <img id="dpdmodelplot" /> </div> </div> + + <!-- <div class="panel panel-default"> <div class="panel-heading">Status</div> <div class="panel-body"> @@ -87,3 +112,23 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. </div> </body> </html> + +<!-- + Copyright (C) 2019 + Matthias P. Braendli, matthias.braendli@mpb.li + +This file is part of ODR-DabMod. + +ODR-DabMod is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +ODR-DabMod 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. +--> diff --git a/python/gui/templates/rcvalues.html b/python/gui/templates/rcvalues.html index c1786bc..9e607bc 100644 --- a/python/gui/templates/rcvalues.html +++ b/python/gui/templates/rcvalues.html @@ -1,23 +1,3 @@ -<!-- - Copyright (C) 2018 - Matthias P. Braendli, matthias.braendli@mpb.li - -This file is part of ODR-DabMod. - -ODR-DabMod is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -ODR-DabMod 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. ---> - <!DOCTYPE html> <html lang="en"> @@ -46,3 +26,22 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. </div> </body> </html> +<!-- + Copyright (C) 2018 + Matthias P. Braendli, matthias.braendli@mpb.li + +This file is part of ODR-DabMod. + +ODR-DabMod is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +ODR-DabMod 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. +--> |