Frequency Fine Tuning

Merged project to add frequency fine tuning
This commit is contained in:
sm4xas 2020-01-11 21:39:57 +01:00
parent c3d89bd4bf
commit 2a2720bc5e
10 changed files with 429 additions and 156 deletions

View File

@ -3,7 +3,7 @@
This file is part of OpenWebRX, This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI. an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu> Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de> Copyright (c) 2019 by Jakob Ketterl <dd5jfk@darc.de>
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
@ -266,16 +266,14 @@ input[type=range]:focus::-ms-fill-upper
background-repeat: no-repeat; background-repeat: no-repeat;
background-color: #1e5f7f; background-color: #1e5f7f;
background-size: cover; background-size: cover;
display: flex;
flex-direction: column;
} }
#webrx-canvas-container #webrx-canvas-container
{ {
position: relative; position: relative;
overflow: visible; overflow: hidden;
cursor: crosshair; cursor: crosshair;
flex-grow: 1; height: 100%;
} }
#webrx-canvas-container canvas #webrx-canvas-container canvas
@ -288,6 +286,13 @@ input[type=range]:focus::-ms-fill-upper
height: 200px; height: 200px;
} }
#openwebrx-mathbox-container
{
flex-grow: 1;
overflow: none;
display: none;
}
#openwebrx-log-scroll #openwebrx-log-scroll
{ {
/*overflow-y:auto;*/ /*overflow-y:auto;*/
@ -345,7 +350,7 @@ input[type=range]:focus::-ms-fill-upper
padding: 0; padding: 0;
margin: 0; margin: 0;
line-height:22px; line-height:22px;
display: inline-block;
} }
#webrx-mouse-freq #webrx-mouse-freq
@ -358,6 +363,20 @@ input[type=range]:focus::-ms-fill-upper
margin-bottom: 5px; margin-bottom: 5px;
} }
/*---- begin id-control:id-step-freq */
#id-step-freq
{
cursor: pointer;
}
#id-freq-link {
display: inline-block;
float: right;
}
#openwebrx-panels-container-left, #openwebrx-panels-container-left,
#openwebrx-panels-container-right { #openwebrx-panels-container-right {
position: absolute; position: absolute;
@ -649,7 +668,8 @@ img.openwebrx-mirror-img
font-family: 'expletus-sans-medium'; font-family: 'expletus-sans-medium';
} }
.openwebrx-overlay { #openwebrx-autoplay-overlay
{
position: fixed; position: fixed;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -663,10 +683,6 @@ img.openwebrx-mirror-img
color: white; color: white;
font-weight: bold; font-weight: bold;
font-size: 20pt; font-size: 20pt;
}
#openwebrx-autoplay-overlay
{
cursor: pointer; cursor: pointer;
transition: opacity 0.3s linear; transition: opacity 0.3s linear;
} }
@ -676,7 +692,7 @@ img.openwebrx-mirror-img
width: 150px; width: 150px;
} }
.openwebrx-overlay .overlay-content { #openwebrx-autoplay-overlay .overlay-content {
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;
@ -684,12 +700,6 @@ img.openwebrx-mirror-img
text-align: center; text-align: center;
} }
#openwebrx-error-overlay .overlay-content {
background-color: #000;
padding: 50px;
border-radius: 20px;
}
#openwebrx-digimode-canvas-container #openwebrx-digimode-canvas-container
{ {
/*margin: -10px -10px 10px -10px;*/ /*margin: -10px -10px 10px -10px;*/
@ -932,15 +942,13 @@ img.openwebrx-mirror-img
} }
#openwebrx-panel-wsjt-message, #openwebrx-panel-wsjt-message,
#openwebrx-panel-packet-message, #openwebrx-panel-packet-message
#openwebrx-panel-pocsag-message
{ {
height: 180px; height: 180px;
} }
#openwebrx-panel-wsjt-message tbody, #openwebrx-panel-wsjt-message tbody,
#openwebrx-panel-packet-message tbody, #openwebrx-panel-packet-message tbody
#openwebrx-panel-pocsag-message tbody
{ {
display: block; display: block;
overflow: auto; overflow: auto;
@ -949,8 +957,7 @@ img.openwebrx-mirror-img
} }
#openwebrx-panel-wsjt-message thead tr, #openwebrx-panel-wsjt-message thead tr,
#openwebrx-panel-packet-message thead tr, #openwebrx-panel-packet-message thead tr
#openwebrx-panel-pocsag-message thead tr
{ {
display: block; display: block;
} }
@ -958,9 +965,7 @@ img.openwebrx-mirror-img
#openwebrx-panel-wsjt-message th, #openwebrx-panel-wsjt-message th,
#openwebrx-panel-wsjt-message td, #openwebrx-panel-wsjt-message td,
#openwebrx-panel-packet-message th, #openwebrx-panel-packet-message th,
#openwebrx-panel-packet-message td, #openwebrx-panel-packet-message td
#openwebrx-panel-pocsag-message th,
#openwebrx-panel-pocsag-message td
{ {
width: 50px; width: 50px;
text-align: left; text-align: left;
@ -982,7 +987,6 @@ img.openwebrx-mirror-img
#openwebrx-panel-packet-message .message { #openwebrx-panel-packet-message .message {
width: 410px; width: 410px;
max-width: 410px;
} }
#openwebrx-panel-packet-message .callsign { #openwebrx-panel-packet-message .callsign {
@ -994,16 +998,6 @@ img.openwebrx-mirror-img
text-align: center; text-align: center;
} }
#openwebrx-panel-pocsag-message .address {
width: 100px;
}
#openwebrx-panel-pocsag-message .message {
width: 486px;
max-width: 486px;
white-space: pre;
}
.aprs-symbol { .aprs-symbol {
display: inline-block; display: inline-block;
width: 15px; width: 15px;
@ -1085,14 +1079,12 @@ img.openwebrx-mirror-img
#openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-content-container, #openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-content-container, #openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-content-container, #openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel, #openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-select-channel, #openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel, #openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-select-channel, #openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-select-channel, #openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-select-channel, #openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-select-channel
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-select-channel
{ {
display: none; display: none;
} }
@ -1102,10 +1094,8 @@ img.openwebrx-mirror-img
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-canvas-container, #openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-canvas-container, #openwebrx-panel-digimodes[data-mode="jt9"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-canvas-container, #openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-canvas-container, #openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-canvas-container
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-canvas-container
{ {
height: 200px; height: 200px;
margin: -10px; margin: -10px;
} }

BIN
htdocs/icons/link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

BIN
htdocs/icons/stepdn.16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
htdocs/icons/stepdn.18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
htdocs/icons/stepdn.20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
htdocs/icons/stepup.16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
htdocs/icons/stepup.18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
htdocs/icons/stepup.20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -4,7 +4,7 @@
This file is part of OpenWebRX, This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI. an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu> Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de> Copyright (c) 2019 by Jakob Ketterl <dd5jfk@darc.de>
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
@ -23,7 +23,8 @@
<html> <html>
<head> <head>
<title>OpenWebRX | Open Source SDR Web App for Everyone!</title> <title>OpenWebRX | Open Source SDR Web App for Everyone!</title>
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" /> <script src="static/sdr.js"></script>
<script src="static/mathbox-bundle.min.js"></script>
<script src="static/openwebrx.js"></script> <script src="static/openwebrx.js"></script>
<script src="static/lib/jquery-3.2.1.min.js"></script> <script src="static/lib/jquery-3.2.1.min.js"></script>
<script src="static/lib/jquery.nanoscroller.js"></script> <script src="static/lib/jquery.nanoscroller.js"></script>
@ -44,6 +45,7 @@
<canvas id="openwebrx-scale-canvas" width="0" height="0"></canvas> <canvas id="openwebrx-scale-canvas" width="0" height="0"></canvas>
</div> </div>
</div> </div>
<div id="openwebrx-mathbox-container"> </div>
<div id="webrx-canvas-background"> <div id="webrx-canvas-background">
<div id="webrx-canvas-container"> <div id="webrx-canvas-container">
<!-- add canvas here by javascript --> <!-- add canvas here by javascript -->
@ -85,13 +87,6 @@
</tr></thead> </tr></thead>
<tbody></tbody> <tbody></tbody>
</table> </table>
<table class="openwebrx-panel" id="openwebrx-panel-pocsag-message" style="display: none; width: 619px;" data-panel-name="pocsag-message">
<thead><tr>
<th class="address">Address</th>
<th class="message">Message</th>
</tr></thead>
<tbody></tbody>
</table>
<div class="openwebrx-panel openwebrx-meta-panel" id="openwebrx-panel-metadata-ysf" style="display: none;" data-panel-name="metadata-ysf"> <div class="openwebrx-panel openwebrx-meta-panel" id="openwebrx-panel-metadata-ysf" style="display: none;" data-panel-name="metadata-ysf">
<div class="openwebrx-meta-frame"> <div class="openwebrx-meta-frame">
<div class="openwebrx-meta-slot"> <div class="openwebrx-meta-slot">
@ -125,6 +120,7 @@
<div class="openwebrx-panel-inner nano" id="openwebrx-log-scroll"> <div class="openwebrx-panel-inner nano" id="openwebrx-log-scroll">
<div class="nano-content"> <div class="nano-content">
<div id="openwebrx-client-log-title">OpenWebRX client log</div> <div id="openwebrx-client-log-title">OpenWebRX client log</div>
<div>Author contact: <a href="http://blog.sdr.hu/about" target="_blank">András Retzler, HA7ILM</a></div>
<div>Author contact: <a href="http://www.justjakob.de/" target="_blank">Jakob Ketterl, DD5JFK</a></div> <div>Author contact: <a href="http://www.justjakob.de/" target="_blank">Jakob Ketterl, DD5JFK</a></div>
<div id="openwebrx-debugdiv"></div> <div id="openwebrx-debugdiv"></div>
</div> </div>
@ -144,7 +140,18 @@
<div class="openwebrx-panel-line frequencies-container"> <div class="openwebrx-panel-line frequencies-container">
<div class="frequencies"> <div class="frequencies">
<div id="webrx-actual-freq">---.--- MHz</div> <div id="webrx-actual-freq">---.--- MHz</div>
<div id="webrx-mouse-freq">---.--- MHz</div> <div id="id-freq-link"></div>
<div id="webrx-mouse-freq">---.--- MHz</div>
<div id="id-step-freq" class="bal">
<img id="id-step-0" src="static/icons/stepdn.20.png" onclick="freqstep(0)" title="-5k">
<img id="id-step-1" src="static/icons/stepdn.18.png" onclick="freqstep(1)" style="padding-bottom:1px" title="-100">
<img id="id-step-2" src="static/icons/stepdn.16.png" onclick="freqstep(2)" style="padding-bottom:2px" title="-10">
<img id="id-step-3" src="static/icons/stepup.16.png" onclick="freqstep(3)" style="padding-bottom:2px" title="+10">
<img id="id-step-4" src="static/icons/stepup.18.png" onclick="freqstep(4)" style="padding-bottom:1px" title="+100">
<img id="id-step-5" src="static/icons/stepup.20.png" onclick="freqstep(5)" title="+5k">
</div>
</div> </div>
<div class="openwebrx-button openwebrx-square-button openwebrx-bookmark-button" style="display:none;" title="Add bookmark..."> <div class="openwebrx-button openwebrx-square-button openwebrx-bookmark-button" style="display:none;" title="Add bookmark...">
<img src="static/gfx/openwebrx-bookmark.png"> <img src="static/gfx/openwebrx-bookmark.png">
@ -191,7 +198,6 @@
<option value="jt9" data-feature="wsjt-x">JT9</option> <option value="jt9" data-feature="wsjt-x">JT9</option>
<option value="ft4" data-feature="wsjt-x">FT4</option> <option value="ft4" data-feature="wsjt-x">FT4</option>
<option value="packet" data-feature="packet">Packet</option> <option value="packet" data-feature="packet">Packet</option>
<option value="pocsag" data-feature="pocsag">Pocsag</option>
</select> </select>
</div> </div>
<div class="openwebrx-panel-line"> <div class="openwebrx-panel-line">
@ -211,6 +217,7 @@
<div class="openwebrx-button openwebrx-square-button" onclick="zoomOutOneStep();" title="Zoom out one step"> <img src="static/gfx/openwebrx-zoom-out.png" /></div> <div class="openwebrx-button openwebrx-square-button" onclick="zoomOutOneStep();" title="Zoom out one step"> <img src="static/gfx/openwebrx-zoom-out.png" /></div>
<div class="openwebrx-button openwebrx-square-button" onclick="zoomInTotal();" title="Zoom in totally"><img src="static/gfx/openwebrx-zoom-in-total.png" /></div> <div class="openwebrx-button openwebrx-square-button" onclick="zoomInTotal();" title="Zoom in totally"><img src="static/gfx/openwebrx-zoom-in-total.png" /></div>
<div class="openwebrx-button openwebrx-square-button" onclick="zoomOutTotal();" title="Zoom out totally"><img src="static/gfx/openwebrx-zoom-out-total.png" /></div> <div class="openwebrx-button openwebrx-square-button" onclick="zoomOutTotal();" title="Zoom out totally"><img src="static/gfx/openwebrx-zoom-out-total.png" /></div>
<div class="openwebrx-button openwebrx-square-button" onclick="mathbox_toggle();" title="Toggle 3D view"><img src="static/gfx/openwebrx-3d-spectrum.png" /></div>
<div id="openwebrx-smeter-db">0 dB</div> <div id="openwebrx-smeter-db">0 dB</div>
</div> </div>
<div class="openwebrx-panel-line"> <div class="openwebrx-panel-line">
@ -222,19 +229,12 @@
</div> </div>
</div> </div>
</div> </div>
<div id="openwebrx-autoplay-overlay" class="openwebrx-overlay" style="display:none;"> <div id="openwebrx-autoplay-overlay" style="display:none;">
<div class="overlay-content"> <div class="overlay-content">
<img id="openwebrx-play-button" src="static/gfx/openwebrx-play-button.png" /> <img id="openwebrx-play-button" src="static/gfx/openwebrx-play-button.png" />
<div>Start OpenWebRX</div> <div>Start OpenWebRX</div>
</div> </div>
</div> </div>
<div id="openwebrx-error-overlay" class="openwebrx-overlay" style="display:none;">
<div class="overlay-content">
<div>This receiver is currently unavailable due to technical issues.</div>
<div>Error Message:</div>
<div class="errormessage"></div>
</div>
</div>
<div id="openwebrx-dialog-bookmark" class="openwebrx-dialog" style="display:none;"> <div id="openwebrx-dialog-bookmark" class="openwebrx-dialog" style="display:none;">
<form> <form>
<div class="form-field"> <div class="form-field">

View File

@ -3,7 +3,7 @@
This file is part of OpenWebRX, This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI. an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu> Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de> Copyright (c) 2019 by Jakob Ketterl <dd5jfk@darc.de>
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
@ -21,6 +21,9 @@
""" """
*/ */
var base_url = window.location.origin;
//console.log(base_url);
var act_freq=0;
is_firefox = navigator.userAgent.indexOf("Firefox") >= 0; is_firefox = navigator.userAgent.indexOf("Firefox") >= 0;
@ -29,7 +32,7 @@ var center_freq;
var fft_size; var fft_size;
var fft_fps; var fft_fps;
var fft_compression = "none"; var fft_compression = "none";
var fft_codec; var fft_codec = new sdrjs.ImaAdpcm();
var waterfall_setup_done = 0; var waterfall_setup_done = 0;
var secondary_fft_size; var secondary_fft_size;
var rx_photo_state = 1; var rx_photo_state = 1;
@ -98,6 +101,51 @@ function updateVolume() {
audioEngine.setVolume(parseFloat(e("openwebrx-panel-volume").value) / 100); audioEngine.setVolume(parseFloat(e("openwebrx-panel-volume").value) / 100);
} }
function freqstep(sel){
stepsize = 0;
switch(sel) {
case 0:
stepsize = -5000;
break;
case 1:
stepsize = -100;
break;
case 2:
stepsize = -10;
break;
case 3:
stepsize = 10;
break;
case 4:
stepsize = 100;
break;
case 5:
stepsize = 5000;
break;
default:
stepsize = 0;
}
offset_frequency = parseInt(act_freq)-center_freq;
new_offset= offset_frequency + stepsize;
new_qrg = act_freq + stepsize;
demodulator_set_offset_frequency(0, new_offset);
e("webrx-actual-freq").innerHTML=format_frequency("{x} MHz",new_qrg,1e6,5);
updateShareLink(new_qrg);
act_freq = new_qrg;
}
function updateShareLink(freq){
//console.log(freq);
var sqlSliderValue=parseInt(e("openwebrx-panel-squelch").value);
e("id-freq-link").innerHTML='<a href="'+base_url+'/#freq='+freq+',mod='+last_analog_demodulator_subtype+',sql='+sqlSliderValue+'" target="_blank" title="Share Settings"><img src="icons/link.png"></a>';
}
function toggleMute() { function toggleMute() {
if (mute) { if (mute) {
mute = false; mute = false;
@ -143,6 +191,7 @@ function setSquelchToAuto() {
function updateSquelch() { function updateSquelch() {
var sliderValue = parseInt($("#openwebrx-panel-squelch").val()); var sliderValue = parseInt($("#openwebrx-panel-squelch").val());
ws.send(JSON.stringify({"type": "dspcontrol", "params": {"squelch_level": sliderValue}})); ws.send(JSON.stringify({"type": "dspcontrol", "params": {"squelch_level": sliderValue}}));
updateShareLink(act_freq);
} }
var waterfall_min_level; var waterfall_min_level;
@ -366,18 +415,8 @@ function Demodulator_default_analog(offset_frequency, subtype) {
this.subtype = subtype; this.subtype = subtype;
this.filter = { this.filter = {
min_passband: 100, min_passband: 100,
getLimits: function() { high_cut_limit: (audioEngine.getOutputRate() / 2) - 1,
var max_bw; low_cut_limit: (-audioEngine.getOutputRate() / 2) + 1
if (secondary_demod === 'pocsag') {
max_bw = 12500;
} else {
max_bw = (audioEngine.getOutputRate() / 2) - 1;
}
return {
high: max_bw,
low: -max_bw
};
}
}; };
//Subtypes only define some filter parameters and the mod string sent to server, //Subtypes only define some filter parameters and the mod string sent to server,
//so you may set these parameters in your custom child class. //so you may set these parameters in your custom child class.
@ -427,7 +466,8 @@ function Demodulator_default_analog(offset_frequency, subtype) {
timeout_this.wait_for_timer = false; timeout_this.wait_for_timer = false;
if (timeout_this.set_after) timeout_this.set(); if (timeout_this.set_after) timeout_this.set();
}, demodulator_response_time); }, demodulator_response_time);
} else { }
else {
this.set_after = true; this.set_after = true;
} }
}; };
@ -440,7 +480,6 @@ function Demodulator_default_analog(offset_frequency, subtype) {
}; };
if (first_time) params.mod = this.server_mod; if (first_time) params.mod = this.server_mod;
ws.send(JSON.stringify({"type": "dspcontrol", "params": params})); ws.send(JSON.stringify({"type": "dspcontrol", "params": params}));
mkenvelopes(get_visible_freq_range());
}; };
this.doset(true); //we set parameters on object creation this.doset(true); //we set parameters on object creation
@ -486,7 +525,7 @@ function Demodulator_default_analog(offset_frequency, subtype) {
//frequency. //frequency.
if (this.dragged_range === dr.beginning || this.dragged_range === dr.bfo || this.dragged_range === dr.pbs) { if (this.dragged_range === dr.beginning || this.dragged_range === dr.bfo || this.dragged_range === dr.pbs) {
//we don't let low_cut go beyond its limits //we don't let low_cut go beyond its limits
if ((new_value = this.drag_origin.low_cut + minus * freq_change) < this.parent.filter.getLimits().low) return true; if ((new_value = this.drag_origin.low_cut + minus * freq_change) < this.parent.filter.low_cut_limit) return true;
//nor the filter passband be too small //nor the filter passband be too small
if (this.parent.high_cut - new_value < this.parent.filter.min_passband) return true; if (this.parent.high_cut - new_value < this.parent.filter.min_passband) return true;
//sanity check to prevent GNU Radio "firdes check failed: fa <= fb" //sanity check to prevent GNU Radio "firdes check failed: fa <= fb"
@ -495,7 +534,7 @@ function Demodulator_default_analog(offset_frequency, subtype) {
} }
if (this.dragged_range === dr.ending || this.dragged_range === dr.bfo || this.dragged_range === dr.pbs) { if (this.dragged_range === dr.ending || this.dragged_range === dr.bfo || this.dragged_range === dr.pbs) {
//we don't let high_cut go beyond its limits //we don't let high_cut go beyond its limits
if ((new_value = this.drag_origin.high_cut + minus * freq_change) > this.parent.filter.getLimits().high) return true; if ((new_value = this.drag_origin.high_cut + minus * freq_change) > this.parent.filter.high_cut_limit) return true;
//nor the filter passband be too small //nor the filter passband be too small
if (new_value - this.parent.low_cut < this.parent.filter.min_passband) return true; if (new_value - this.parent.low_cut < this.parent.filter.min_passband) return true;
//sanity check to prevent GNU Radio "firdes check failed: fa <= fb" //sanity check to prevent GNU Radio "firdes check failed: fa <= fb"
@ -512,7 +551,10 @@ function Demodulator_default_analog(offset_frequency, subtype) {
mkenvelopes(this.visible_range); mkenvelopes(this.visible_range);
this.parent.set(); this.parent.set();
//will have to change this when changing to multi-demodulator mode: //will have to change this when changing to multi-demodulator mode:
e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", center_freq + this.parent.offset_frequency, 1e6, 4); //e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", center_freq + this.parent.offset_frequency, 1e6, 4);
e("webrx-actual-freq").innerHTML=format_frequency("{x} MHz",center_freq+this.parent.offset_frequency,1e6,5);
act_freq=center_freq+this.parent.offset_frequency;
updateShareLink(act_freq);
return true; return true;
}; };
@ -562,6 +604,7 @@ function demodulator_analog_replace(subtype, for_digital) { //this function shou
} }
demodulator_add(new Demodulator_default_analog(temp_offset, subtype)); demodulator_add(new Demodulator_default_analog(temp_offset, subtype));
demodulator_buttons_update(); demodulator_buttons_update();
updateShareLink(act_freq);
update_digitalvoice_panels("openwebrx-panel-metadata-" + subtype); update_digitalvoice_panels("openwebrx-panel-metadata-" + subtype);
} }
@ -586,17 +629,63 @@ var scale_ctx;
var scale_canvas; var scale_canvas;
function scale_setup() { function scale_setup() {
e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", canvas_get_frequency(window.innerWidth / 2), 1e6, 4); // e("webrx-actual-freq").innerHTML = format_frequency("{x} MHz", canvas_get_frequency(window.innerWidth / 2), 1e6, 4);
act_freq=center_freq;
e("webrx-actual-freq").innerHTML=format_frequency("{x} MHz",act_freq,1e6,5);
updateShareLink(act_freq);
scale_canvas = e("openwebrx-scale-canvas"); scale_canvas = e("openwebrx-scale-canvas");
scale_ctx = scale_canvas.getContext("2d"); scale_ctx = scale_canvas.getContext("2d");
scale_canvas.addEventListener("mousedown", scale_canvas_mousedown, false); scale_canvas.addEventListener("mousedown", scale_canvas_mousedown, false);
scale_canvas.addEventListener("mousemove", scale_canvas_mousemove, false); scale_canvas.addEventListener("mousemove", scale_canvas_mousemove, false);
scale_canvas.addEventListener("mouseup", scale_canvas_mouseup, false); scale_canvas.addEventListener("mouseup", scale_canvas_mouseup, false);
scale_canvas.addEventListener("wheel",scale_canvas_mousewheel, false);
resize_scale(); resize_scale();
var frequency_container = e("openwebrx-frequency-container"); var frequency_container = e("openwebrx-frequency-container");
frequency_container.addEventListener("mousemove", frequency_container_mousemove, false); frequency_container.addEventListener("mousemove", frequency_container_mousemove, false);
} }
var scale_canvas_scroll_params={
key_modifiers: {shiftKey:false, altKey: false, ctrlKey: false}
};
function scale_canvas_mousewheel(evt)
{
//if(!waterfall_setup_done) return;
var relativeX=(evt.offsetX)?evt.offsetX:evt.layerX;
var dir=(evt.deltaY/Math.abs(evt.deltaY))>0;
if (dir){ // scroll down on scale
if (evt.shiftKey){ // shift pressed
stepsize = -5000;
} else {
stepsize = -100;
}
} else { // scroll up on scale
if (evt.shiftKey){ // shift pressed
stepsize = 5000;
} else {
stepsize = 100;
}
}
//console.log(act_freq);
offset_frequency = parseInt(act_freq)-center_freq;
new_offset= offset_frequency + stepsize;
//console.log(new_offset);
if (Math.abs(new_offset) < bandwidth/2){ // don't tune out of range
new_qrg = act_freq + stepsize
demodulator_set_offset_frequency(0, new_offset);
e("webrx-actual-freq").innerHTML=format_frequency("{x} MHz",new_qrg,1e6,5);
updateShareLink(new_qrg);
act_freq = new_qrg;
}
evt.preventDefault();
}
var scale_canvas_drag_params = { var scale_canvas_drag_params = {
mouse_down: false, mouse_down: false,
drag: false, drag: false,
@ -635,7 +724,11 @@ function scale_canvas_mousemove(evt) {
for (i = 0; i < demodulators.length; i++) event_handled |= demodulators[i].envelope.drag_move(evt.pageX); for (i = 0; i < demodulators.length; i++) event_handled |= demodulators[i].envelope.drag_move(evt.pageX);
if (!event_handled) demodulator_set_offset_frequency(0, scale_offset_freq_from_px(evt.pageX)); if (!event_handled) demodulator_set_offset_frequency(0, scale_offset_freq_from_px(evt.pageX));
} }
else
{
relativeX=(evt.offsetX)?evt.offsetX:evt.layerX;
e("webrx-mouse-freq").innerHTML=format_frequency("{x} MHz",canvas_get_frequency(relativeX),1e6,4);
}
} }
function frequency_container_mousemove(evt) { function frequency_container_mousemove(evt) {
@ -649,7 +742,14 @@ function scale_canvas_end_drag(x) {
scale_canvas_drag_params.mouse_down = false; scale_canvas_drag_params.mouse_down = false;
var event_handled = false; var event_handled = false;
for (var i = 0; i < demodulators.length; i++) event_handled |= demodulators[i].envelope.drag_end(); for (var i = 0; i < demodulators.length; i++) event_handled |= demodulators[i].envelope.drag_end();
if (!event_handled) demodulator_set_offset_frequency(0, scale_offset_freq_from_px(x)); //if (!event_handled) demodulator_set_offset_frequency(0, scale_offset_freq_from_px(x));
if (!event_handled) {
demodulator_set_offset_frequency(0,scale_offset_freq_from_px(x));
new_qrg = parseInt(center_freq + scale_offset_freq_from_px(x));
e("webrx-actual-freq").innerHTML=format_frequency("{x} MHz",new_qrg,1e6,5);
updateShareLink(new_qrg);
act_freq = new_qrg;
}
} }
function scale_canvas_mouseup(evt) { function scale_canvas_mouseup(evt) {
@ -930,6 +1030,9 @@ function canvas_mouseup(evt) {
if (!canvas_drag) { if (!canvas_drag) {
demodulator_set_offset_frequency(0, canvas_get_freq_offset(relativeX)); demodulator_set_offset_frequency(0, canvas_get_freq_offset(relativeX));
e("webrx-actual-freq").innerHTML=format_frequency("{x} MHz",canvas_get_frequency(relativeX),1e6,5);
act_freq=canvas_get_frequency(relativeX);
updateShareLink(act_freq);
} }
else { else {
canvas_end_drag(); canvas_end_drag();
@ -1064,6 +1167,9 @@ function on_ws_recv(evt) {
fft_compression = config['fft_compression']; fft_compression = config['fft_compression'];
divlog("FFT stream is " + ((fft_compression === "adpcm") ? "compressed" : "uncompressed") + "."); divlog("FFT stream is " + ((fft_compression === "adpcm") ? "compressed" : "uncompressed") + ".");
clientProgressBar.setMaxClients(config['max_clients']); clientProgressBar.setMaxClients(config['max_clients']);
mathbox_waterfall_colors = config['mathbox_waterfall_colors'];
mathbox_waterfall_frequency_resolution = config['mathbox_waterfall_frequency_resolution'];
mathbox_waterfall_history_length = config['mathbox_waterfall_history_length'];
var sql = Number.isInteger(config['initial_squelch_level']) ? config['initial_squelch_level'] : -150; var sql = Number.isInteger(config['initial_squelch_level']) ? config['initial_squelch_level'] : -150;
$("#openwebrx-panel-squelch").val(sql); $("#openwebrx-panel-squelch").val(sql);
updateSquelch(); updateSquelch();
@ -1115,7 +1221,7 @@ function on_ws_recv(evt) {
var features = json['value']; var features = json['value'];
for (var feature in features) { for (var feature in features) {
if (features.hasOwnProperty(feature)) { if (features.hasOwnProperty(feature)) {
$('[data-feature="' + feature + '"]')[features[feature] ? "show" : "hide"](); $('[data-feature="' + feature + '"')[features[feature] ? "show" : "hide"]();
} }
} }
break; break;
@ -1143,27 +1249,10 @@ function on_ws_recv(evt) {
break; break;
case "sdr_error": case "sdr_error":
divlog(json['value'], true); divlog(json['value'], true);
var $overlay = $('#openwebrx-error-overlay');
$overlay.find('.errormessage').text(json['value']);
$overlay.show();
break; break;
case 'secondary_demod': case 'secondary_demod':
secondary_demod_push_data(json['value']); secondary_demod_push_data(json['value']);
break; break;
case 'log_message':
divlog(json['value'], true);
break;
case 'pocsag_data':
update_pocsag_panel(json['value']);
break;
case 'backoff':
divlog("Server is currently busy: " + json['reason'], true);
var $overlay = $('#openwebrx-error-overlay');
$overlay.find('.errormessage').text(json['reason']);
$overlay.show();
// set a higher reconnection timeout right away to avoid additional load
reconnect_timeout = 16000;
break;
default: default:
console.warn('received message of unknown type: ' + json['type']); console.warn('received message of unknown type: ' + json['type']);
} }
@ -1263,7 +1352,7 @@ function update_metadata(meta) {
mode = "Mode: " + meta['mode']; mode = "Mode: " + meta['mode'];
source = meta['source'] || ""; source = meta['source'] || "";
if (meta['lat'] && meta['lon'] && meta['source']) { if (meta['lat'] && meta['lon'] && meta['source']) {
source = "<a class=\"openwebrx-maps-pin\" href=\"map?callsign=" + meta['source'] + "\" target=\"_blank\"></a>" + source; source = "<a class=\"openwebrx-maps-pin\" href=\"/map?callsign=" + meta['source'] + "\" target=\"_blank\"></a>" + source;
} }
up = meta['up'] ? "Up: " + meta['up'] : ""; up = meta['up'] ? "Up: " + meta['up'] : "";
down = meta['down'] ? "Down: " + meta['down'] : ""; down = meta['down'] ? "Down: " + meta['down'] : "";
@ -1298,14 +1387,14 @@ function update_wsjt_panel(msg) {
if (['FT8', 'JT65', 'JT9', 'FT4'].indexOf(msg['mode']) >= 0) { if (['FT8', 'JT65', 'JT9', 'FT4'].indexOf(msg['mode']) >= 0) {
matches = linkedmsg.match(/(.*\s[A-Z0-9]+\s)([A-R]{2}[0-9]{2})$/); matches = linkedmsg.match(/(.*\s[A-Z0-9]+\s)([A-R]{2}[0-9]{2})$/);
if (matches && matches[2] !== 'RR73') { if (matches && matches[2] !== 'RR73') {
linkedmsg = html_escape(matches[1]) + '<a href="map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>'; linkedmsg = html_escape(matches[1]) + '<a href="/map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>';
} else { } else {
linkedmsg = html_escape(linkedmsg); linkedmsg = html_escape(linkedmsg);
} }
} else if (msg['mode'] === 'WSPR') { } else if (msg['mode'] === 'WSPR') {
matches = linkedmsg.match(/([A-Z0-9]*\s)([A-R]{2}[0-9]{2})(\s[0-9]+)/); matches = linkedmsg.match(/([A-Z0-9]*\s)([A-R]{2}[0-9]{2})(\s[0-9]+)/);
if (matches) { if (matches) {
linkedmsg = html_escape(matches[1]) + '<a href="map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>' + html_escape(matches[3]); linkedmsg = html_escape(matches[1]) + '<a href="/map?locator=' + matches[2] + '" target="_blank">' + matches[2] + '</a>' + html_escape(matches[3]);
} else { } else {
linkedmsg = html_escape(linkedmsg); linkedmsg = html_escape(linkedmsg);
} }
@ -1391,7 +1480,7 @@ function update_packet_panel(msg) {
'style="' + stylesToString(styles) + '"' 'style="' + stylesToString(styles) + '"'
].join(' '); ].join(' ');
if (msg.lat && msg.lon) { if (msg.lat && msg.lon) {
link = '<a ' + attrs + ' href="map?callsign=' + source + '" target="_blank">' + overlay + '</a>'; link = '<a ' + attrs + ' href="/map?callsign=' + source + '" target="_blank">' + overlay + '</a>';
} else { } else {
link = '<div ' + attrs + '>' + overlay + '</div>' link = '<div ' + attrs + '>' + overlay + '</div>'
} }
@ -1407,17 +1496,6 @@ function update_packet_panel(msg) {
$b.scrollTop($b[0].scrollHeight); $b.scrollTop($b[0].scrollHeight);
} }
function update_pocsag_panel(msg) {
var $b = $('#openwebrx-panel-pocsag-message').find('tbody');
$b.append($(
'<tr>' +
'<td class="address">' + msg.address + '</td>' +
'<td class="message">' + msg.message + '</td>' +
'</tr>'
));
$b.scrollTop($b[0].scrollHeight);
}
function update_digitalvoice_panels(showing) { function update_digitalvoice_panels(showing) {
$(".openwebrx-meta-panel").each(function (_, p) { $(".openwebrx-meta-panel").each(function (_, p) {
toggle_panel(p.id, p.id === showing); toggle_panel(p.id, p.id === showing);
@ -1442,7 +1520,6 @@ function waterfall_measure_minmax_do(what) {
} }
function on_ws_opened() { function on_ws_opened() {
$('#openwebrx-error-overlay').hide();
ws.send("SERVER DE CLIENT client=openwebrx.js type=receiver"); ws.send("SERVER DE CLIENT client=openwebrx.js type=receiver");
divlog("WebSocket opened to " + ws.url); divlog("WebSocket opened to " + ws.url);
if (!networkSpeedMeasurement) { if (!networkSpeedMeasurement) {
@ -1454,13 +1531,10 @@ function on_ws_opened() {
networkSpeedMeasurement.reset(); networkSpeedMeasurement.reset();
} }
reconnect_timeout = false; reconnect_timeout = false;
ws.send(JSON.stringify({
"type": "connectionproperties",
"params": {"output_rate": audioEngine.getOutputRate()}
}));
ws.send(JSON.stringify({ ws.send(JSON.stringify({
"type": "dspcontrol", "type": "dspcontrol",
"action": "start" "action": "start",
"params": {"output_rate": audioEngine.getOutputRate()}
})); }));
} }
@ -1559,23 +1633,19 @@ function on_ws_error() {
divlog("WebSocket error.", 1); divlog("WebSocket error.", 1);
} }
String.prototype.startswith = function (str) {
return this.indexOf(str) === 0;
}; //http://stackoverflow.com/questions/646628/how-to-check-if-a-string-startswith-another-string
var ws; var ws;
function open_websocket() { function open_websocket() {
var protocol = window.location.protocol.match(/https/) ? 'wss' : 'ws'; var protocol = 'ws';
if (window.location.toString().startsWith('https://')) {
var href = window.location.href; protocol = 'wss';
var index = href.lastIndexOf('/');
if (index > 0) {
href = href.substr(0, index + 1);
} }
href = href.split("://")[1];
href = protocol + "://" + href;
if (!href.endsWith('/')) {
href += '/';
}
var ws_url = href + "ws/";
var ws_url = protocol + "://" + (window.location.origin.split("://")[1]) + "/ws/"; //guess automatically -> now default behaviour
if (!("WebSocket" in window)) if (!("WebSocket" in window))
divlog("Your browser does not support WebSocket, which is required for WebRX to run. Please upgrade to a HTML5 compatible browser."); divlog("Your browser does not support WebSocket, which is required for WebRX to run. Please upgrade to a HTML5 compatible browser.");
ws = new WebSocket(ws_url); ws = new WebSocket(ws_url);
@ -1640,6 +1710,7 @@ function add_canvas() {
function init_canvas_container() { function init_canvas_container() {
canvas_container = e("webrx-canvas-container"); canvas_container = e("webrx-canvas-container");
mathbox_container = e("openwebrx-mathbox-container");
canvas_container.addEventListener("mouseleave", canvas_container_mouseleave, false); canvas_container.addEventListener("mouseleave", canvas_container_mouseleave, false);
canvas_container.addEventListener("mousemove", canvas_mousemove, false); canvas_container.addEventListener("mousemove", canvas_mousemove, false);
canvas_container.addEventListener("mouseup", canvas_mouseup, false); canvas_container.addEventListener("mouseup", canvas_mouseup, false);
@ -1677,6 +1748,27 @@ function waterfall_init() {
waterfall_setup_done = 1; waterfall_setup_done = 1;
} }
var mathbox_shift = function () {
if (mathbox_data_current_depth < mathbox_data_max_depth) mathbox_data_current_depth++;
if (mathbox_data_index + 1 >= mathbox_data_max_depth) mathbox_data_index = 0;
else mathbox_data_index++;
mathbox_data_global_index++;
};
var mathbox_clear_data = function () {
mathbox_data_index = 50;
mathbox_data_current_depth = 0;
};
var mathbox_get_data_line = function (x) {
return (mathbox_data_max_depth + mathbox_data_index + x - 1) % mathbox_data_max_depth;
};
var mathbox_data_index_valid = function (x) {
return x > mathbox_data_max_depth - mathbox_data_current_depth;
};
function waterfall_add(data) { function waterfall_add(data) {
if (!waterfall_setup_done) return; if (!waterfall_setup_done) return;
var w = fft_size; var w = fft_size;
@ -1688,18 +1780,26 @@ function waterfall_add(data) {
waterfallColorsAuto(); waterfallColorsAuto();
} }
//Add line to waterfall image if (mathbox_mode === MATHBOX_MODES.WATERFALL) {
var oneline_image = canvas_context.createImageData(w, 1); //Handle mathbox
for (var x = 0; x < w; x++) { for (var i = 0; i < fft_size; i++) mathbox_data[i + mathbox_data_index * fft_size] = data[i];
var color = waterfall_mkcolor(data[x]); mathbox_shift();
for (i = 0; i < 4; i++) } else {
oneline_image.data[x * 4 + i] = ((color >>> 0) >> ((3 - i) * 8)) & 0xff; //Add line to waterfall image
var oneline_image = canvas_context.createImageData(w, 1);
for (var x = 0; x < w; x++) {
var color = waterfall_mkcolor(data[x]);
for (i = 0; i < 4; i++)
oneline_image.data[x * 4 + i] = ((color >>> 0) >> ((3 - i) * 8)) & 0xff;
}
//Draw image
canvas_context.putImageData(oneline_image, 0, canvas_actual_line--);
shift_canvases();
if (canvas_actual_line < 0) add_canvas();
} }
//Draw image
canvas_context.putImageData(oneline_image, 0, canvas_actual_line--);
shift_canvases();
if (canvas_actual_line < 0) add_canvas();
} }
function check_top_bar_congestion() { function check_top_bar_congestion() {
@ -1717,6 +1817,167 @@ function check_top_bar_congestion() {
} }
var MATHBOX_MODES =
{
UNINITIALIZED: 0,
NONE: 1,
WATERFALL: 2,
CONSTELLATION: 3
};
var mathbox_mode = MATHBOX_MODES.UNINITIALIZED;
var mathbox;
var mathbox_element;
var mathbox_waterfall_colors;
var mathbox_waterfall_frequency_resolution;
var mathbox_waterfall_history_length;
var mathbox_correction_for_z;
var mathbox_data_max_depth;
var mathbox_data_current_depth;
var mathbox_data_index;
var mathbox_data;
var mathbox_data_global_index;
var mathbox_container;
function mathbox_init() {
//mathbox_waterfall_history_length is defined in the config
mathbox_data_max_depth = fft_fps * mathbox_waterfall_history_length; //how many lines can the buffer store
mathbox_data_current_depth = 0; //how many lines are in the buffer currently
mathbox_data_index = 0; //the index of the last empty line / the line to be overwritten
mathbox_data = new Float32Array(fft_size * mathbox_data_max_depth);
mathbox_data_global_index = 0;
mathbox_correction_for_z = 0;
mathbox = mathBox({
plugins: ['core', 'controls', 'cursor', 'stats'],
controls: {klass: THREE.OrbitControls}
});
var three = mathbox.three;
if (typeof three === "undefined") divlog("3D waterfall cannot be initialized because WebGL is not supported in your browser.", true);
three.renderer.setClearColor(new THREE.Color(0x808080), 1.0);
mathbox_container.appendChild((mathbox_element = three.renderer.domElement));
var view = mathbox
.set({
scale: 1080,
focus: 3
})
.camera({
proxy: true,
position: [-2, 1, 3]
})
.cartesian({
range: [[-1, 1], [0, 1], [0, 1]],
scale: [2, 2 / 3, 1]
});
view.axis({
axis: 1,
width: 3,
color: "#fff"
});
view.axis({
axis: 2,
width: 3,
color: "#fff"
//offset: [0, 0, 0],
});
view.axis({
axis: 3,
width: 3,
color: "#fff"
});
view.grid({
width: 2,
opacity: 0.5,
axes: [1, 3],
zOrder: 1,
color: "#fff"
});
var remap = function (x, z, t) {
var currentTimePos = mathbox_data_global_index / (fft_fps * 1.0);
var realZAdd = (-(t - currentTimePos) / mathbox_waterfall_history_length);
var zAdd = realZAdd - mathbox_correction_for_z;
if (zAdd < -0.2 || zAdd > 0.2) {
mathbox_correction_for_z = realZAdd;
}
var xIndex = Math.trunc(((x + 1) / 2.0) * fft_size); //x: frequency
var zIndex = Math.trunc(z * (mathbox_data_max_depth - 1)); //z: time
var realZIndex = mathbox_get_data_line(zIndex);
if (!mathbox_data_index_valid(zIndex)) return {y: undefined, dBValue: undefined, zAdd: 0};
var index = Math.trunc(xIndex + realZIndex * fft_size);
var dBValue = mathbox_data[index];
var y;
if (dBValue > waterfall_max_level) y = 1;
else if (dBValue < waterfall_min_level) y = 0;
else y = (dBValue - waterfall_min_level) / (waterfall_max_level - waterfall_min_level);
if (!y) y = 0;
return {y: y, dBValue: dBValue, zAdd: zAdd};
};
view.area({
expr: function (emit, x, z, i, j, t) {
var y;
var remapResult = remap(x, z, t);
if ((y = remapResult.y) === undefined) return;
emit(x, y, z + remapResult.zAdd);
},
width: mathbox_waterfall_frequency_resolution,
height: mathbox_data_max_depth - 1,
channels: 3,
axes: [1, 3]
});
view.area({
expr: function (emit, x, z, i, j, t) {
var dBValue;
if ((dBValue = remap(x, z, t).dBValue) === undefined) return;
var color = waterfall_mkcolor(dBValue, mathbox_waterfall_colors);
var b = (color & 0xff) / 255.0;
var g = ((color & 0xff00) >> 8) / 255.0;
var r = ((color & 0xff0000) >> 16) / 255.0;
emit(r, g, b, 1.0);
},
width: mathbox_waterfall_frequency_resolution,
height: mathbox_data_max_depth - 1,
channels: 4,
axes: [1, 3]
});
view.surface({
shaded: true,
points: '<<',
colors: '<',
color: 0xFFFFFF
});
view.surface({
fill: false,
lineX: false,
lineY: false,
points: '<<',
colors: '<',
color: 0xFFFFFF,
width: 2,
blending: 'add',
opacity: .25,
zBias: 5
});
mathbox_mode = MATHBOX_MODES.NONE;
}
function mathbox_toggle() {
if (mathbox_mode === MATHBOX_MODES.UNINITIALIZED) mathbox_init();
mathbox_mode = (mathbox_mode === MATHBOX_MODES.NONE) ? MATHBOX_MODES.WATERFALL : MATHBOX_MODES.NONE;
mathbox_container.style.display = (mathbox_mode === MATHBOX_MODES.WATERFALL) ? "block" : "none";
mathbox_clear_data();
waterfall_clear();
}
function waterfall_clear() { function waterfall_clear() {
while (canvases.length) //delete all canvases while (canvases.length) //delete all canvases
{ {
@ -1780,7 +2041,6 @@ function openwebrx_init() {
} else { } else {
audioEngine.start(onAudioStart); audioEngine.start(onAudioStart);
} }
fft_codec = new ImaAdpcmCodec();
initProgressBars(); initProgressBars();
init_rx_photo(); init_rx_photo();
open_websocket(); open_websocket();
@ -1793,6 +2053,38 @@ function openwebrx_init() {
bookmarks = new BookmarkBar(); bookmarks = new BookmarkBar();
parseHash(); parseHash();
initSliders(); initSliders();
init_key_listener();
}
function init_key_listener(zEvent){
//https://stackoverflow.com/questions/37557990/detecting-combination-keypresses-control-alt-shift
document.addEventListener ("keydown", function (zEvent) {
if (zEvent.ctrlKey && zEvent.altKey && zEvent.code === "KeyE") {
console.log(zEvent);
}
// shift and +
if ((zEvent.keyCode == "171" || zEvent.keyCode == "107") && zEvent.shiftKey){
freqstep(4);
}
//shift and -
if ((zEvent.keyCode == "109" || zEvent.keyCode == "173") && zEvent.shiftKey){
freqstep(1);
}
// - and not shift
if ((zEvent.keyCode == "109" || zEvent.keyCode == "173") &! zEvent.shiftKey){
freqstep(2);
}
// + and not shift
if ((zEvent.keyCode == "171" || zEvent.keyCode == "107") &! zEvent.shiftKey){
freqstep(3);
}
//console.log(zEvent);
} );
} }
function initSliders() { function initSliders() {
@ -2001,20 +2293,12 @@ function demodulator_digital_replace(subtype) {
secondary_demod_start(subtype); secondary_demod_start(subtype);
demodulator_analog_replace('nfm', true); demodulator_analog_replace('nfm', true);
break; break;
case "pocsag":
secondary_demod_start(subtype);
demodulator_analog_replace('nfm', true);
demodulators[0].low_cut = -6000;
demodulators[0].high_cut = 6000;
demodulators[0].set();
break;
} }
demodulator_buttons_update(); demodulator_buttons_update();
$('#openwebrx-panel-digimodes').attr('data-mode', subtype); $('#openwebrx-panel-digimodes').attr('data-mode', subtype);
toggle_panel("openwebrx-panel-digimodes", true); toggle_panel("openwebrx-panel-digimodes", true);
toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4'].indexOf(subtype) >= 0); toggle_panel("openwebrx-panel-wsjt-message", ['ft8', 'wspr', 'jt65', 'jt9', 'ft4'].indexOf(subtype) >= 0);
toggle_panel("openwebrx-panel-packet-message", subtype === "packet"); toggle_panel("openwebrx-panel-packet-message", subtype === "packet");
toggle_panel("openwebrx-panel-pocsag-message", subtype === "pocsag");
} }
function secondary_demod_create_canvas() { function secondary_demod_create_canvas() {
@ -2104,7 +2388,6 @@ function secondary_demod_close_window() {
toggle_panel("openwebrx-panel-digimodes", false); toggle_panel("openwebrx-panel-digimodes", false);
toggle_panel("openwebrx-panel-wsjt-message", false); toggle_panel("openwebrx-panel-wsjt-message", false);
toggle_panel("openwebrx-panel-packet-message", false); toggle_panel("openwebrx-panel-packet-message", false);
toggle_panel("openwebrx-panel-pocsag-message", false);
} }
function secondary_demod_waterfall_add(data) { function secondary_demod_waterfall_add(data) {