diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-08-06 09:10:42 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-08-06 09:10:42 +0200 |
commit | 7e91c6a59858325593093c046c213c6bd4e7e4f3 (patch) | |
tree | 0a5765a048fd3910caf2fc396d113ef2ef5ea753 | |
parent | 08705c0399240f984cf54294a369cb3a896e089a (diff) | |
download | dabmod-7e91c6a59858325593093c046c213c6bd4e7e4f3.tar.gz dabmod-7e91c6a59858325593093c046c213c6bd4e7e4f3.tar.bz2 dabmod-7e91c6a59858325593093c046c213c6bd4e7e4f3.zip |
Some GUI changes
-rwxr-xr-x | gui/api/__init__.py | 5 | ||||
-rw-r--r-- | gui/dpd/Capture.py | 57 | ||||
-rw-r--r-- | gui/dpd/__init__.py | 24 | ||||
-rw-r--r-- | gui/static/js/odr-modulator.js | 6 | ||||
-rw-r--r-- | gui/static/js/odr-predistortion.js | 22 | ||||
-rw-r--r-- | gui/templates/modulator.html | 8 | ||||
-rw-r--r-- | gui/templates/predistortion.html | 5 |
7 files changed, 96 insertions, 31 deletions
diff --git a/gui/api/__init__.py b/gui/api/__init__.py index 959dedc..6c04a64 100755 --- a/gui/api/__init__.py +++ b/gui/api/__init__.py @@ -71,3 +71,8 @@ class API: cherrypy.response.headers["Content-Type"] = "text/plain" cherrypy.response.status = 400 return "POST only" + + @cherrypy.expose + def dpd_status(self, **kwargs): + cherrypy.response.headers["Content-Type"] = "application/json" + return json.dumps(self.dpd.status()).encode() diff --git a/gui/dpd/Capture.py b/gui/dpd/Capture.py index d6d0307..31fa78d 100644 --- a/gui/dpd/Capture.py +++ b/gui/dpd/Capture.py @@ -77,8 +77,12 @@ class Capture: self.binning_n_bins = 64 # Number of bins between binning_start and binning_end self.binning_n_per_bin = 128 # Number of measurements pre bin + self.target_median = 0.01 + self.median_max = self.target_median * 1.4 + self.median_min = self.target_median / 1.4 + # axis 1: 0=tx, 1=rx - self.accumulated_samples = np.zeros((0, 2), dtype=np.complex64) + self.accumulated_bins = [np.zeros((0, 2), dtype=np.complex64) for i in range(self.binning_n_bins)] def _recv_exact(self, sock, num_bytes): """Receive an exact number of bytes from a socket. This is @@ -156,42 +160,45 @@ class Capture: txframe, tx_ts, rxframe, rx_ts = self.receive_tcp() # Normalize received signal with sent signal - rx_median = np.median(np.abs(rxframe)) tx_median = np.median(np.abs(txframe)) - rxframe = rxframe / rx_median * tx_median - txframe_aligned, rxframe_aligned = align_samples(txframe, rxframe) + if self.median_max < tx_median: + raise ValueError("Median {} too high, decrease digital_gain!".format(tx_median)) + elif tx_median < self.median_min: + raise ValueError("Median {} too low, increase digital_gain!".format(tx_median)) + else: + rx_median = np.median(np.abs(rxframe)) + rxframe = rxframe / rx_median * tx_median + + txframe_aligned, rxframe_aligned = align_samples(txframe, rxframe) - self._bin_and_accumulate(txframe_aligned, rxframe_aligned) + self._bin_and_accumulate(txframe_aligned, rxframe_aligned) - return txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median + return txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median - def num_accumulated(self): - return self.accumulated_samples.shape[0] + def bin_histogram(self): + return [b.shape[0] for b in self.accumulated_bins] def _bin_and_accumulate(self, txframe, rxframe): """Bin the samples and extend the accumulated samples""" bin_edges = np.linspace(self.binning_start, self.binning_end, self.binning_n_bins) - binned_sample_pairs = {} - minsize = self.num_samples_to_request for i, (tx_start, tx_end) in enumerate(zip(bin_edges, bin_edges[1:])): - indices = np.bitwise_and(tx_start < txframe, txframe <= tx_end) - binned_sample_pairs[i] = (txframe[indices], rxframe[indices]) - len_bin = len(txframe[indices]) - - #TODO this doesn't work, the min is always 0 - if len_bin < minsize: - minsize = len_bin - - # axis 0: bins, axis 1: sample index, axis 2: tx(0) and rx(1) - samples = np.zeros((self.binning_n_bins, len_bin, 2), dtype=np.complex64) - - for i in binned_sample_pairs: - tx, rx = binned_sample_pairs[i] - new_samples = np.array((tx[:minsize], rx[:minsize]), dtype=np.complex64) - self.accumulated_samples = np.concatenate((self.accumulated_samples, new_samples.T)) + txframe_abs = np.abs(txframe) + indices = np.bitwise_and(tx_start < txframe_abs, txframe_abs <= tx_end) + txsamples = np.asmatrix(txframe[indices]) + rxsamples = np.asmatrix(rxframe[indices]) + binned_sample_pairs = np.concatenate((txsamples, rxsamples)).T + + missing_in_bin = self.binning_n_per_bin - self.accumulated_bins[i].shape[0] + num_to_append = min(missing_in_bin, binned_sample_pairs.shape[0]) + print("Handling bin {} {}-{}, {} available, {} missing".format(i, tx_start, tx_end, binned_sample_pairs.shape[0], missing_in_bin)) + if num_to_append: + print("Appending {} to bin {} with shape {}".format(num_to_append, i, self.accumulated_bins[i].shape)) + + self.accumulated_bins[i] = np.concatenate((self.accumulated_bins[i], binned_sample_pairs[:num_to_append,...])) + print("{} now has shape {}".format(i, self.accumulated_bins[i].shape)) diff --git a/gui/dpd/__init__.py b/gui/dpd/__init__.py index c0c76cc..d006c1c 100644 --- a/gui/dpd/__init__.py +++ b/gui/dpd/__init__.py @@ -35,19 +35,31 @@ class DPD: self.T_U = oversample * 2048 # Inverse of carrier spacing self.T_C = oversample * 504 # Duration of cyclic prefix + self.last_capture_info = {} + port = 50055 samples_to_capture = 81920 self.capture = Capture.Capture(self.samplerate, port, samples_to_capture) + def status(self): + r = {} + r['histogram'] = self.capture.bin_histogram() + r['capture'] = self.last_capture_info + return r + def capture_samples(self): """Captures samples and store them in the accumulated samples, returns a string with some info""" - txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median = self.capture.get_samples() - - num_acc = self.capture.num_accumulated() - - return "Captured {} with median {}/{}, accumulated {} samples".format( - len(txframe_aligned), tx_median, rx_median, num_acc) + try: + txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median = self.capture.get_samples() + self.last_capture_info['length'] = len(txframe_aligned) + self.last_capture_info['tx_median'] = tx_median + self.last_capture_info['rx_median'] = rx_median + self.last_capture_info['tx_ts'] = tx_ts + self.last_capture_info['rx_ts'] = rx_ts + return "Captured {} samples, tx median {}, rx median {}".format(len(txframe_aligned, tx_median, rx_median)) + except ValueError as e: + return "Error: {}".format(e) # tx, rx, phase_diff, n_per_bin = extStat.extract(txframe_aligned, rxframe_aligned) # off = SA.calc_offset(txframe_aligned) diff --git a/gui/static/js/odr-modulator.js b/gui/static/js/odr-modulator.js index 9671fb3..273d9f7 100644 --- a/gui/static/js/odr-modulator.js +++ b/gui/static/js/odr-modulator.js @@ -64,6 +64,7 @@ function getRc(callback) { function requestAllParams(callback) { getRc(function(data) { $('#windowlength').val(data.guardinterval.windowlen.value); + $('#digitalgain').val(data.gain.digital.value); $('#cfrenable').prop("checked", data.ofdm.cfr.value == 1); $('#cfrclip').val(data.ofdm.clip.value); $('#cfrerrorclip').val(data.ofdm.errorclip.value); @@ -84,6 +85,11 @@ var updateTimer = setInterval(requestStats, 2000); $(function(){ requestAllParams(); + $('#setdigitalgain').click(function() { + set_rc("gain", "digital", $('#digitalgain').val(), + requestAllParams); + }); + $('#setwindowlength').click(function() { set_rc("guardinterval", "windowlen", $('#windowlength').val(), requestAllParams); diff --git a/gui/static/js/odr-predistortion.js b/gui/static/js/odr-predistortion.js index d385f6c..dce3922 100644 --- a/gui/static/js/odr-predistortion.js +++ b/gui/static/js/odr-predistortion.js @@ -40,6 +40,28 @@ $(function(){ }, }); }); + + $('#dpdstatusbutton').click(function() { + $.ajax({ + type: "GET", + url: "/api/dpd_status", + contentType: 'application/json', + dataType: '', + data: '', + + error: function(data) { + $.gritter.add({ + title: 'DPD Status Update', + text: "ERROR", + image: '/fonts/warning.png', + sticky: true, + }); + }, + success: function(data) { + $('#dpdstatus').val(data); + }, + }); + }); }); diff --git a/gui/templates/modulator.html b/gui/templates/modulator.html index 2cd5765..07e7a82 100644 --- a/gui/templates/modulator.html +++ b/gui/templates/modulator.html @@ -30,6 +30,14 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. <div class="panel-group"> <div class="panel panel-default"> <div class="panel-body"> + <h3>Gain</h3> + <div class="form-group"> + <label for="digitalgain">Digital Gain:</label> + <input type="text" class="form-control" id="digitalgain"> + <button type="button" class="btn btn-sm btn-info" id="setdigitalgain">Set</button> + </div> + </div> + <div class="panel-body"> <h3>OFDM Windowing</h3> <div class="form-group"> <label for="windowlength">Window length:</label> diff --git a/gui/templates/predistortion.html b/gui/templates/predistortion.html index 6828f14..ef20a16 100644 --- a/gui/templates/predistortion.html +++ b/gui/templates/predistortion.html @@ -37,6 +37,11 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. <button type="button" class="btn btn-sm btn-info" id="capturebutton">Capture</button> </div> </div> + <div class="panel-body"> + <h3>Status</h3> + <button type="button" class="btn btn-sm btn-info" id="dpdstatusbutton">Update</button> + <div id="dpdstatus"></div> + </div> </div> </div> </div> |