
Enabled console commands via normal terminal emulator Added menu for calibration of filters
1789 lines
54 KiB
HTML
1789 lines
54 KiB
HTML
<!--
|
|
This application is loosly based on the code found here:
|
|
|
|
Repository: https://github.com/krzychb/EspScopeA0
|
|
Version: Delta
|
|
Flie: index.htm
|
|
Revision: 0.1.0
|
|
Date: 10-Jul-2016
|
|
Author: krzychb at gazeta.pl
|
|
|
|
Copyright (c) 2016 Krzysztof Budzynski. All rights reserved.
|
|
|
|
This modified version takes the samples from the TinySA
|
|
spectrum analyser and displays in a web page.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
-->
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
|
|
<head>
|
|
<title>simpleSA</title>
|
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
|
<!-- get file below from http://canvasjs.com/ -->
|
|
<script type="text/javascript" src="canvasjs.min.js"></script>
|
|
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
|
|
<script type="text/javascript" src="support.js"></script>
|
|
</head>
|
|
|
|
<body style="min-width:100vw">
|
|
<div class='norm' id="top">
|
|
|
|
<button id="homeButton" onclick="window.location.href='index.html';">Home</button>
|
|
<!-- <button id="settingsButton" onclick="window.location.href='settings.html';">Settings</button>
|
|
<button id="backupRestoreButton" onclick="window.location.href='backupRestore.html';">Backup/Restore</button>
|
|
// <button id="helpButton" onclick="window.location.href='help.html';">Help</button> -->
|
|
<button id="aboutButton" onclick="window.location.href='about.html';">About</button>
|
|
</div>
|
|
<div class ="Grid">
|
|
<div class = "Grid-cell" id="chartSA" style="display:block">
|
|
<!-- container for chart -->
|
|
</div>
|
|
|
|
<div class = "Grid-cell" id="sigGen" style="display:none">
|
|
<!-- container for sig gen controls -->
|
|
<br />
|
|
<div class="sigTitle">Signal Generator</div>
|
|
<br />
|
|
<div class="sigFreq">
|
|
<button class = "inc-button" id="incButton">+</button>
|
|
<br />
|
|
<label for="setSigGenFreq8" class="sigFreqLabel">Frequency:</label>
|
|
<input class="sigFreqInput" id="setSigGenFreq8" name="setSigGenFreq8" type="number" min=-1 max=10 value=0>
|
|
<input class="sigFreqInput" id="setSigGenFreq7" name="setSigGenFreq7" type="number" min=-1 max=10 value=0>
|
|
<input class="sigFreqInput" id="setSigGenFreq6" name="setSigGenFreq6" type="number" min=-1 max=10 value=0>
|
|
<span class="sigFreqText">,</span>
|
|
<input class="sigFreqInput" id="setSigGenFreq5" name="setSigGenFreq5" type="number" min=-1 max=10 value=0>
|
|
<input class="sigFreqInput" id="setSigGenFreq4" name="setSigGenFreq4" type="number" min=-1 max=10 value=0>
|
|
<input class="sigFreqInput" id="setSigGenFreq3" name="setSigGenFreq3" type="number" min=-1 max=10 value=0>
|
|
<span class="sigFreqText">,</span>
|
|
<input class="sigFreqInput" id="setSigGenFreq2" name="setSigGenFreq2" type="number" min=-1 max=10 value=0>
|
|
<input class="sigFreqInput" id="setSigGenFreq1" name="setSigGenFreq1" type="number" min=-1 max=10 value=0>
|
|
<input class="sigFreqInput" id="setSigGenFreq0" name="setSigGenFreq0" type="number" min=0 max=10 value=0>
|
|
<span class="sigFreqText">Hz </span>
|
|
<button class = "on-button" id="sigOnButton">On/Off</button>
|
|
<br />
|
|
<button class = "inc-button" id="decButton">-</button>
|
|
|
|
|
|
</div>
|
|
<br /><br />
|
|
<label for="setSigGenPower" class = "sigLevelLabel">Level:</label>
|
|
<input class="sigLevelInput" id="setSigGenPower" name="setSigGenPower" type="number" min=-70 max=20 value=0>
|
|
dBm
|
|
<br /><br />
|
|
<div class="slidecontainer">
|
|
<input type="range" min=-70 max=20 value=0 class="slider" id="sigLevelSlider">
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<br />
|
|
|
|
<div class = "Grid-cell-side" id="postSweepSettings" >
|
|
<!--<form style="width: 90vw; margin-left: 80px" action="doSetSweep" method="get"> -->
|
|
<div class="setting" >
|
|
<select class="Sweep-select" id="setMode" name="setMode">
|
|
<option class="sweep-option" value="0">Sweep Low</option>
|
|
<!-- <option class="sweep-option" value="1">Sweep High</option> -->
|
|
<option class="sweep-option" value="2">Sig Gen</option>
|
|
<!-- <option class="sweep-option" value="3">Sig Gen High</option> -->
|
|
<option class="sweep-option" value="4">SAW Test</option>
|
|
<!-- <option class="sweep-option" value="5">Zero Span</option> -->
|
|
<!-- <option class="sweep-option" value="6">Zero Span High</option> -->
|
|
<option class="sweep-option" value="7">Bandscope</option>
|
|
<option class="sweep-option" value="8">RBW Test</option>
|
|
<option class="sweep-option" value="9">OTA Update</option>
|
|
</select>
|
|
<img src="refresh.png" id="refresh" name = "refresh" height = "18">
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setStart" class="setting-label">Start:</label>
|
|
<input class="value-input" name='setStart' type="number" id="setStart" maxlength="9" min="0" max="350" required>
|
|
MHz
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setStop" class="setting-label">Stop:</label>
|
|
<input class="value-input" name='setStop' type="number" id ="setStop" maxlength="9" min="0" max="350" required>
|
|
MHz
|
|
</div>
|
|
<br />
|
|
<div class="setting" >
|
|
<label for="setCenter" class="setting-label">Centre:</label>
|
|
<input class="value-input" name='setCenter' type="number" id ="setCenter" maxlength="9" min="0" max="350" required>
|
|
MHz
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setSpan" class="setting-label">Span:</label>
|
|
<!--<select class="select-input" id="setSpan" name="setSpan">
|
|
<option class="select-option" value="250">250</option>
|
|
<option class="select-option" value="100">100</option>
|
|
<option class="select-option" value="50">50</option>
|
|
<option class="select-option" value="20">20</option>
|
|
<option class="select-option" value="10">10</option>
|
|
<option class="select-option" value="4">4</option>
|
|
<option class="select-option" value="2">2</option>
|
|
<option class="select-option" value="1">1</option>
|
|
<option class="select-option" value="0.5">0.5</option>
|
|
</select> -->
|
|
<input class="value-input" name='setSpan' type="number" id ="setSpan" maxlength="9" min="0" max="350" step="0.1" required>
|
|
MHz
|
|
</div>
|
|
<!--
|
|
<label class="setting-label">Width:</label>
|
|
<input class="value-input" name='setWidth' type="text" id ="setWidth" placeholder="width" maxlength="9" min="0" max="250" required>
|
|
MHz
|
|
</div> -->
|
|
<br />
|
|
<!-- <div style="width:180px; display: inline-block">Ext gain:<input style = "width:100px" name='setExtGain' type="text" placeholder="extGain" maxlength="9" min="-100" max="40" required></div> -->
|
|
<div id="signal_info">
|
|
<div class="setting" >
|
|
<label class="setting-label">RBW:</label>
|
|
<input class="value-display" type="text" disabled="1" id="actRBW" size="1" value="300" />
|
|
kHz
|
|
</div>
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setRBW" class="setting-label">RBW:</label>
|
|
<select class="select-input" id="setRBW" name="setRBW"></select>
|
|
kHz
|
|
</div>
|
|
<!-- <div style="width:150px; display: inline-block">
|
|
<button type="submit">Update</button>
|
|
</div> -->
|
|
<br />
|
|
<div class="setting" >
|
|
<label for="setAtten" class="setting-label">Atten:</label>
|
|
<input class="value-input" name='setAtten' type="number" step="1" id ="setAtten" maxlength=3 min=0 max=31 required>
|
|
dB
|
|
<label for="setExtern" class="setting-label">External:</label>
|
|
<input class="value-input" name='setExtern' type="number" step="1" id ="setExtern" maxlength=3 min=-60 max=60 required>
|
|
<!--<select class="select-input" id="setAtten" name="setAtten"></select> -->
|
|
dB
|
|
</div>
|
|
<br />
|
|
<div class="setting" >
|
|
<label for="setRefOut" class="setting-label">Reference:</label>
|
|
<select class="select-input" id="setRefOut" name="setRefOut">
|
|
<option class="select-option" value="-1">Off</option>
|
|
<option class="select-option" value="0">30</option>
|
|
<option class="select-option" value="1">15</option>
|
|
<option class="select-option" value="2">10</option>
|
|
<option class="select-option" value="3">4</option>
|
|
<option class="select-option" value="4">3</option>
|
|
<option class="select-option" value="5">2</option>
|
|
<option class="select-option" value="6">1</option>
|
|
</select>
|
|
MHz
|
|
</div>
|
|
<br />
|
|
<div id="spur">
|
|
<div class="setting" >
|
|
<label class="setting-widelabel">Spur Reduce:</label>
|
|
<input class="checkbox-input" type="checkbox" id="spurReduction" size="1" value="0" />
|
|
</div>
|
|
</div>
|
|
<div id="tracking">
|
|
<div class="setting" >
|
|
<label class="setting-label">TrackGen:</label>
|
|
<select class="select-input" id="trackGen" name="trackGen">
|
|
<option class="select-option" value=0>Off</option>
|
|
<option class="select-option" value=1>Track</option>
|
|
<option class="select-option" value=2>Generate</option>
|
|
</select>
|
|
<br />
|
|
<label class="setting-label">Level:</label>
|
|
<input class="value-input" type="number" id="setTrackGenPower" placeholder="setTrackGenPower" maxlength = "6" min="-60" max="10" value="0" />
|
|
dBm
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setTGFreq" class="setting-label">TG Freq:</label>
|
|
<input class="value-input" name='setTGFreq' type="number" id="setTGFreq" maxlength="9" min=0 max=350 required>
|
|
MHz
|
|
</div>
|
|
|
|
</div>
|
|
<br />
|
|
<div id="signal_info">
|
|
<div class="setting" >
|
|
<input class="sweep-display" type="text" disabled="1" id="sweepPoints" size="1" value="65000" />
|
|
pts
|
|
<input class="sweep-display" type="text" disabled="1" id="sweepTime" size="1" value="290" />
|
|
ms
|
|
</div>
|
|
</div>
|
|
<div id="store">
|
|
<div class = "setting" >
|
|
<label class="setting-label">Store:</label>
|
|
<input class="checkbox-input" type="checkbox" id="store1" size="1" value="0" />
|
|
<input class="checkbox-input" type="checkbox" id="store2" size="1" value="0" />
|
|
<input class="checkbox-input" type="checkbox" id="store3" size="1" value="0" />
|
|
<input class="checkbox-input" type="checkbox" id="store4" size="1" value="0" />
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- form for device settings -->
|
|
<hr />
|
|
<h1>Settings</h1>
|
|
<div class="setting" >
|
|
<label for="levelOffset" class="setting-label">Offset:</label>
|
|
<input class="value-display" type="text" disabled="1" id="levelOffset" size="1" value="10" />
|
|
dB
|
|
<label for="filterCal" class="setting-label">RBW Cal:</label>
|
|
<input class="value-display" type="text" disabled="1" id="filterCal" size="1" value="0" />
|
|
dB
|
|
</div>
|
|
<div class="setting" >
|
|
<button id="setActPower">Set Actual</button>
|
|
<input class="value-input" type="number" id="setPowerValue" placeholder="setPowerValue" maxlength = "9" min="-60" max="20" value="0" />
|
|
dBm
|
|
</div>
|
|
<br />
|
|
<div class="setting" >
|
|
<label for="setLODrive" class="setting-label">LO Drive:</label>
|
|
<select class="select-input" id="setLODrive" name="setLODrive">
|
|
<option class="select-option" value="0">-1</option>
|
|
<option class="select-option" value="1">2</option>
|
|
<option class="select-option" value="2">5</option>
|
|
<option class="select-option" value="3">8</option>
|
|
<option class="select-option" value="4">11</option>
|
|
<option class="select-option" value="5">14</option>
|
|
<option class="select-option" value="6">17</option>
|
|
<option class="select-option" value="7">20</option>
|
|
</select>
|
|
dBm
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setPreAmp" class="setting-label">Pre-amp:</label>
|
|
<select class="select-input" id="setPreAmp" name="setPreAmp">
|
|
<option value="96">Auto</option> <!--0x60 Auto -->
|
|
<option value="0">5</option> <!--0x00 LNA Min 5dB-->
|
|
<option value="1">8</option> <!--0x01 -->
|
|
<option value="2">11</option> <!--0x02 -->
|
|
<option value="3">14</option> <!--0x03 -->
|
|
<option value="4">17</option> <!--0x04 -->
|
|
<option value="5">20</option> <!--0x05 -->
|
|
<option value="6">23</option> <!--0x06 -->
|
|
<option value="7">27</option> <!--0x07 -->
|
|
<option value="8">30</option> <!--0x08 -->
|
|
<option value="16">25</option> <!--0x10 LNA Max 25dB-->
|
|
<option value="17">28</option> <!--0x11 -->
|
|
<option value="18">31</option> <!--0x12 -->
|
|
<option value="19">34</option> <!--0x13 -->
|
|
<option value="20">37</option> <!--0x14 -->
|
|
<option value="21">40</option> <!--0x15 -->
|
|
<option value="22">43</option> <!--0x16 -->
|
|
<option value="23">46</option> <!--0x17 -->
|
|
<option value="24">49</option> <!--0x18 -->
|
|
</select>
|
|
dB
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="setIF" class="setting-label">IF:</label>
|
|
<input class="value-input" type="number" id="setIF" size="1" value="433.92" min="433" max=435 step=0.01 />
|
|
MHz
|
|
</div>
|
|
<div class="setting" >
|
|
<label for="Average" class="setting-label">Average:</label>
|
|
<input class="value-input" type="number" id="Average" size="1" value="10" min="2" max=100 step=1 />
|
|
</div>
|
|
|
|
</div>
|
|
<!--</form> -->
|
|
</div>
|
|
|
|
|
|
<!-- Below chart (hopefully!) -->
|
|
|
|
|
|
<div class = "Grid">
|
|
<div class = "Grid-cell-connection" id="status" >
|
|
<hr />
|
|
<div id="connection-status">
|
|
<form onsubmit="return false;">
|
|
<div style="width: 400px; display: inline-block">Host:
|
|
<input type="text" id="hostName" value="ws://hostName:81" style="width:160px;"/>
|
|
<input type="button" value="Connect" onclick="connect(hostName.value)" />
|
|
<input type="button" value="Disconnect" onclick="disconnect()" />
|
|
</div>
|
|
<div style="width: 250px; display: inline-block">Status:
|
|
<input type="text" id="connectionStatus" value="Idle" style="border: 0" />
|
|
</div>
|
|
<div style="width: 100px; display: inline-block">Pings:
|
|
<input type="text" id="connectionPings" size="3" value="-" style="border: 0" />
|
|
</div>
|
|
<div style="width: 160px; display: inline-block">Refresh:
|
|
<input class="value-input" type="number" id="refreshInterval" size="3" min="100" max="3000" value="500" />
|
|
ms
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<!-- <input class="message-display" type="text" disabled="1" id="message" size="1" value="json message" /> -->
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
|
|
var frequency = 0;
|
|
var freqStep = 1000000;
|
|
|
|
var chartDiv = document.getElementById('chartSA');
|
|
var sigDiv = document.getElementById('sigGen');
|
|
|
|
var refreshInterval = document.getElementById('refreshInterval');
|
|
|
|
var refresh = document.getElementById('refresh');
|
|
var setMode = document.getElementById('setMode');
|
|
var sweepStart = document.getElementById('sweepStart');
|
|
var sweepStop = document.getElementById('sweepStop');
|
|
var setStart = document.getElementById('setStart');
|
|
var setStop = document.getElementById('setStop');
|
|
var setCenter = document.getElementById('setCenter');
|
|
var setSpan = document.getElementById('setSpan');
|
|
var setAtten = document.getElementById('setAtten');
|
|
var setExtern = document.getElementById('setExtern');
|
|
var setActPower = document.getElementById('setActPower');
|
|
var levelOffset = document.getElementById('levelOffset');
|
|
var filterCal = document.getElementById('filterCal');
|
|
var setRefOut = document.getElementById('setRefOut');
|
|
var sweepPoints = document.getElementById('sweepPoints');
|
|
var sweepTime = document.getElementById('sweepTime');
|
|
var setSpur = document.getElementById('spurReduction');
|
|
var actRBW = document.getElementById('actRBW');
|
|
var setRBW = document.getElementById('setRBW');
|
|
var setDrive = document.getElementById('setLODrive');
|
|
var setIF = document.getElementById('setIF');
|
|
var setPreAmp = document.getElementById('setPreAmp');
|
|
var setAverage = document.getElementById('Average');
|
|
var setTrackGen = document.getElementById('trackGen');
|
|
var setTrackGenPower = document.getElementById('setTrackGenPower');
|
|
var setTGFreq = document.getElementById('setTGFreq');
|
|
var store1 = document.getElementById('store1');
|
|
var store2 = document.getElementById('store2');
|
|
var store3 = document.getElementById('store3');
|
|
var store4 = document.getElementById('store4');
|
|
//var messageWindow = document.getElementById('message');
|
|
|
|
var sigLevelSlider = document.getElementById('sigLevelSlider');
|
|
var setSigGenPower = document.getElementById('setSigGenPower');
|
|
var setSigGenFreq = document.getElementById('setSigGenFreq');
|
|
var sigOnButton = document.getElementById('sigOnButton');
|
|
|
|
var setSigGenFreq0 = document.getElementById('setSigGenFreq0');
|
|
var setSigGenFreq1 = document.getElementById('setSigGenFreq1');
|
|
var setSigGenFreq2 = document.getElementById('setSigGenFreq2');
|
|
var setSigGenFreq3 = document.getElementById('setSigGenFreq3');
|
|
var setSigGenFreq4 = document.getElementById('setSigGenFreq4');
|
|
var setSigGenFreq5 = document.getElementById('setSigGenFreq5');
|
|
var setSigGenFreq6 = document.getElementById('setSigGenFreq6');
|
|
var setSigGenFreq7 = document.getElementById('setSigGenFreq7');
|
|
var setSigGenFreq8 = document.getElementById('setSigGenFreq8');
|
|
|
|
var tempCenter;
|
|
|
|
// initialise these to silly values to force an update first time round
|
|
var oldSweepStart = -1;
|
|
var oldSweepStop = -1;
|
|
var oldSweepCenter = -1;
|
|
var oldSetRefOut = -2;
|
|
var oldSetRBW = -10;
|
|
var oldLevelOffset = 1000;
|
|
var oldFilterCal = 1000;
|
|
var oldAttenuation = 1000;
|
|
var oldExternalGain = 1000;
|
|
var oldDrive = -1;
|
|
var oldIF = 0;
|
|
var oldPreAmp = 0;
|
|
var oldSweepPoints = 0;
|
|
var oldSpur = 2;
|
|
var oldTrackGen = 2;
|
|
var oldTrackGenPower = 1000;
|
|
var oldTGFreq = -1;
|
|
var oldSigGen = -1;
|
|
var oldSigGenPower = 1000;
|
|
var oldSigGenFreq = -1;
|
|
var oldSigGenMod = -1;
|
|
var oldSigGenModFreq = -1;
|
|
var oldSigOnButton = -1;
|
|
|
|
// Chart configuration - Scope
|
|
var RSSISamples = [
|
|
{y:10},
|
|
{y:11},
|
|
{y:12},
|
|
{y:13},
|
|
{y:14},
|
|
{y:15},
|
|
{y:16},
|
|
{y:17},
|
|
{y:18},
|
|
]; // dummy for test
|
|
|
|
var dBSamples = [
|
|
{y:-10},
|
|
{y:-20},
|
|
{y:-23},
|
|
{y:-90},
|
|
{y:-120},
|
|
{y:-100},
|
|
{y:-80},
|
|
{y:-30},
|
|
{y:-40},
|
|
]; // dummy for test
|
|
|
|
var gainSamples = [
|
|
{x:0, y:42},
|
|
{x:10, y:43},
|
|
{x:20, y:44},
|
|
{x:30, y:45},
|
|
{x:40, y:46},
|
|
{x:50, y:47},
|
|
{x:80, y:48},
|
|
{x:90, y:49},
|
|
{x:100, y:40},
|
|
]; // dummy for test
|
|
|
|
var store1Samples = [
|
|
{x:0, y:42},
|
|
{x:10, y:43},
|
|
{x:20, y:44},
|
|
{x:30, y:45},
|
|
{x:40, y:46},
|
|
{x:50, y:47},
|
|
{x:80, y:48},
|
|
{x:90, y:49},
|
|
{x:100, y:40},
|
|
];
|
|
|
|
var store2Samples = [
|
|
{x:0, y:42},
|
|
{x:10, y:43},
|
|
{x:20, y:44},
|
|
{x:30, y:45},
|
|
{x:40, y:46},
|
|
{x:50, y:47},
|
|
{x:80, y:48},
|
|
{x:90, y:49},
|
|
{x:100, y:40},
|
|
];
|
|
|
|
var store3Samples = [
|
|
{x:0, y:42},
|
|
{x:10, y:43},
|
|
{x:20, y:44},
|
|
{x:30, y:45},
|
|
{x:40, y:46},
|
|
{x:50, y:47},
|
|
{x:80, y:48},
|
|
{x:90, y:49},
|
|
{x:100, y:40},
|
|
];
|
|
|
|
var store4Samples = [
|
|
{x:0, y:42},
|
|
{x:10, y:43},
|
|
{x:20, y:44},
|
|
{x:30, y:45},
|
|
{x:40, y:46},
|
|
{x:50, y:47},
|
|
{x:80, y:48},
|
|
{x:90, y:49},
|
|
{x:100, y:40},
|
|
];
|
|
|
|
|
|
var chartSA = new CanvasJS.Chart("chartSA",
|
|
{
|
|
animationEnabled: false,
|
|
zoomEnabled: true,
|
|
zoomType: "xy",
|
|
//height:800,
|
|
title: {
|
|
text: "simpleSA",
|
|
fontSize: 28
|
|
},
|
|
axisX: {
|
|
title: "Frequency (MHz)",
|
|
titleFontSize: 24,
|
|
gridThickness: 1,
|
|
gridColor: "WhiteSmoke",
|
|
stripLines:[
|
|
{
|
|
startValue:50,
|
|
thickness:1,
|
|
color:"#d8d8d8",
|
|
}
|
|
]
|
|
},
|
|
axisY:
|
|
{
|
|
title: "dBm",
|
|
titleFontSize: 24,
|
|
gridThickness: 1,
|
|
gridColor: "WhiteSmoke",
|
|
minimum: -120
|
|
},
|
|
axisY2: [
|
|
{
|
|
// title: "RSSI",
|
|
title:"",
|
|
tickLength: 0,
|
|
lineThickness:0,
|
|
margin:0,
|
|
titleFontSize: 24,
|
|
valueFormatString: " ",
|
|
minimum: 0,
|
|
maximum: 255
|
|
},
|
|
{
|
|
// title: "Gain",
|
|
title:"",
|
|
tickLength: 0,
|
|
lineThickness:0,
|
|
margin:0,
|
|
titleFontSize: 24,
|
|
valueFormatString: " ",
|
|
minimum: 0,
|
|
maximum: 50
|
|
}],
|
|
exportEnabled: true,
|
|
legend: {
|
|
cursor: "pointer",
|
|
fontSize: 16,
|
|
itemclick: function (e) {
|
|
//console.log("legend click: " + e.dataPointIndex);
|
|
//console.log(e);
|
|
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
|
|
e.dataSeries.visible = false;
|
|
|
|
if (e.dataSeries.name == "RSSI") { // turn off the RSSI axis and ticks
|
|
chartSA.axisY2[0].options.title ="";
|
|
chartSA.axisY2[0].options.tickLength = 0;
|
|
chartSA.axisY2[0].options.lineThickness = 0;
|
|
chartSA.axisY2[0].options.margin = 0;
|
|
chartSA.axisY2[0].options.valueFormatString = " ";
|
|
// chartSA.axisY2[0].labelFormatter = function(e) { return ""; }
|
|
}
|
|
if (e.dataSeries.name == "gain") { // turn off the gain axis and ticks
|
|
chartSA.axisY2[1].options.title ="";
|
|
chartSA.axisY2[1].options.tickLength = 0;
|
|
chartSA.axisY2[1].options.lineThickness = 0;
|
|
chartSA.axisY2[1].options.margin = 0;
|
|
chartSA.axisY2[1].options.valueFormatString = " ";
|
|
// chartSA.axisY2[1].labelFormatter = function(e) { return ""; }
|
|
}
|
|
|
|
} else {
|
|
e.dataSeries.visible = true;
|
|
|
|
if (e.dataSeries.name == "RSSI") { // turn on the RSSI axis and ticks
|
|
|
|
chartSA.axisY2[0].options.title ="RSSI";
|
|
chartSA.axisY2[0].options.tickLength = 5;
|
|
chartSA.axisY2[0].options.lineThickness = 2;
|
|
chartSA.axisY2[0].options.margin = 2;
|
|
chartSA.axisY2[0].options.valueFormatString = "###";
|
|
// chartSA.axisY2[0].labelFormatter = function(e)
|
|
// {
|
|
// return CanvasJS.formatNumber(e.value);
|
|
// }
|
|
}
|
|
if (e.dataSeries.name == "gain") { // turn on the gain axis and ticks
|
|
|
|
chartSA.axisY2[1].options.title ="gain";
|
|
chartSA.axisY2[1].options.tickLength = 5;
|
|
chartSA.axisY2[1].options.lineThickness = 2;
|
|
chartSA.axisY2[1].options.margin = 2;
|
|
chartSA.axisY2[1].options.valueFormatString = "##";
|
|
// chartSA.axisY2[1].labelFormatter = function(e)
|
|
// {
|
|
// return CanvasJS.formatNumber(e.value);
|
|
// }
|
|
}
|
|
|
|
}
|
|
|
|
chartSA.render();
|
|
}
|
|
},
|
|
data: [
|
|
{
|
|
type: "line",
|
|
name: "dB",
|
|
dataPoints : dBSamples,
|
|
showInLegend : true
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "RSSI",
|
|
axisYType: "secondary",
|
|
dataPoints : RSSISamples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "gain",
|
|
axisYType: "secondary",
|
|
axisYIndex: 1,
|
|
dataPoints : gainSamples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "average",
|
|
dataPoints : dBSamples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "min",
|
|
dataPoints : dBSamples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "store1",
|
|
dataPoints : store1Samples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "store2",
|
|
dataPoints : store2Samples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "store3",
|
|
dataPoints : store3Samples,
|
|
showInLegend : true,
|
|
visible : false
|
|
},
|
|
{
|
|
type: "line",
|
|
name: "store4",
|
|
dataPoints : store4Samples,
|
|
showInLegend : true,
|
|
visible : false
|
|
}
|
|
]
|
|
});
|
|
|
|
|
|
renderChart();
|
|
|
|
|
|
// Add handlers for the change events in the input fields
|
|
|
|
refresh.addEventListener('click', (event) => {
|
|
sendValue("r", 0);
|
|
});
|
|
|
|
setMode.addEventListener('change', (event) => {
|
|
sendValue("m", setMode.value);
|
|
});
|
|
|
|
setStart.addEventListener('change', (event) => {
|
|
sendValue("a", setStart.value);
|
|
});
|
|
|
|
setStop.addEventListener('change', (event) => {
|
|
sendValue("b", setStop.value);
|
|
});
|
|
|
|
setCenter.addEventListener('change', (event) => {
|
|
sendValue("c", setCenter.value);
|
|
});
|
|
|
|
setLODrive.addEventListener('change', (event) => {
|
|
if ((setLODrive.value >=0) && (setLODrive.value <= 7))
|
|
sendValue("d", setLODrive.value);
|
|
});
|
|
|
|
setIF.addEventListener('change', (event) => {
|
|
sendValue("i", setIF.value);
|
|
});
|
|
|
|
setRefOut.addEventListener('change', (event) => {
|
|
sendValue("o", setRefOut.value);
|
|
});
|
|
|
|
setActPower.addEventListener('click', (event) => {
|
|
sendValue("p", setPowerValue.value);
|
|
});
|
|
|
|
setSpan.addEventListener('change', (event) => {
|
|
sendValue("s", setSpan.value);
|
|
});
|
|
|
|
setAtten.addEventListener('change', (event) => {
|
|
sendValue("A", setAtten.value);
|
|
});
|
|
|
|
setExtern.addEventListener('change', (event) => {
|
|
sendValue("E", setExtern.value);
|
|
});
|
|
|
|
setRBW.addEventListener('change', (event) => {
|
|
sendValue("R", setRBW.value);
|
|
});
|
|
|
|
setPreAmp.addEventListener('change', (event) => {
|
|
if (setPreAmp.value == "96") {
|
|
sendValue("g", setPreAmp.value);
|
|
} else {
|
|
sendValue("g", setPreAmp.selectedOptions[0].text);
|
|
}
|
|
});
|
|
|
|
setSpur.addEventListener('change', (event) => {
|
|
if (setSpur.checked) {
|
|
sendValue("S", 1);
|
|
} else {
|
|
sendValue("S", 0);
|
|
}
|
|
});
|
|
|
|
setTrackGen.addEventListener('change', (event) => {
|
|
sendValue("t", setTrackGen.value);
|
|
});
|
|
|
|
setTrackGenPower.addEventListener('change', (event) => {
|
|
sendValue("T", setTrackGenPower.value);
|
|
});
|
|
|
|
|
|
setTGFreq.addEventListener('change', (event) => {
|
|
sendValue("f", setTGFreq.value * 1000000);
|
|
});
|
|
|
|
store1.addEventListener('change', (event) => {
|
|
if (store1.checked) {
|
|
var b = parseFloat(levelOffset.value) + parseFloat(setAtten.value) - 120 - parseFloat(setExtern.value);
|
|
chartSA.options.data[5].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
|
let rObj = {}
|
|
rObj.x = obj.x
|
|
rObj.y = obj.y/2+b
|
|
return rObj
|
|
})
|
|
} else {
|
|
chartSA.options.data[5].dataPoints.length = 2; // reset
|
|
}
|
|
});
|
|
|
|
store2.addEventListener('change', (event) => {
|
|
if (store2.checked) {
|
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
|
|
chartSA.options.data[6].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
|
let rObj = {}
|
|
rObj.x = obj.x
|
|
rObj.y = obj.y/2+b
|
|
return rObj
|
|
})
|
|
} else {
|
|
chartSA.options.data[6].dataPoints.length = 2; // reset
|
|
}
|
|
});
|
|
|
|
store3.addEventListener('change', (event) => {
|
|
if (store3.checked) {
|
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
|
|
chartSA.options.data[7].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
|
let rObj = {}
|
|
rObj.x = obj.x
|
|
rObj.y = obj.y/2+b
|
|
return rObj
|
|
})
|
|
} else {
|
|
chartSA.options.data[7].dataPoints.length = 2; // reset
|
|
}
|
|
});
|
|
|
|
store4.addEventListener('change', (event) => {
|
|
if (store4.checked) {
|
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
|
|
chartSA.options.data[8].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
|
|
let rObj = {}
|
|
rObj.x = obj.x
|
|
rObj.y = obj.y/2+b
|
|
return rObj
|
|
})
|
|
} else {
|
|
chartSA.options.data[8].dataPoints.length = 2; // reset
|
|
}
|
|
});
|
|
|
|
|
|
|
|
function changeStep(newStep) {
|
|
freqStep = newStep;
|
|
setSigGenFreq0.style.color = "black";
|
|
setSigGenFreq1.style.color = "black";
|
|
setSigGenFreq2.style.color = "black";
|
|
setSigGenFreq3.style.color = "black";
|
|
setSigGenFreq4.style.color = "black";
|
|
setSigGenFreq5.style.color = "black";
|
|
setSigGenFreq6.style.color = "black";
|
|
setSigGenFreq7.style.color = "black";
|
|
setSigGenFreq8.style.color = "black";
|
|
|
|
switch(freqStep) {
|
|
case 1:
|
|
setSigGenFreq0.style.color = "red";
|
|
break;
|
|
case 10:
|
|
setSigGenFreq1.style.color = "red";
|
|
break;
|
|
case 100:
|
|
setSigGenFreq2.style.color = "red";
|
|
break;
|
|
case 1000:
|
|
setSigGenFreq3.style.color = "red";
|
|
break;
|
|
case 10000:
|
|
setSigGenFreq4.style.color = "red";
|
|
break;
|
|
case 100000:
|
|
setSigGenFreq5.style.color = "red";
|
|
break;
|
|
case 1000000:
|
|
setSigGenFreq6.style.color = "red";
|
|
break;
|
|
case 10000000:
|
|
setSigGenFreq7.style.color = "red";
|
|
break;
|
|
case 100000000:
|
|
setSigGenFreq8.style.color = "red";
|
|
break;
|
|
}
|
|
};
|
|
|
|
changeStep(freqStep); // initial pass
|
|
|
|
function incdec(direction, factor) {
|
|
if (direction > 0) {
|
|
if ( (frequency + factor) <= 250000000)
|
|
frequency += factor;
|
|
} else {
|
|
if (frequency >= factor)
|
|
frequency -= factor;
|
|
}
|
|
if (frequency > 250000000)
|
|
frequency = 250000000;
|
|
if (frequency < 0)
|
|
frequency = 0;
|
|
console.log("incdec:", frequency);
|
|
var tempFreq = frequency;
|
|
setSigGenFreq0.value = frequency%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq1.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq2.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq3.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq4.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq5.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq6.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq7.value = tempFreq%10;
|
|
tempFreq = parseInt(tempFreq/10);
|
|
setSigGenFreq8.value = tempFreq%10;
|
|
|
|
if (factor != 0)
|
|
sendValue("F", frequency);
|
|
}
|
|
|
|
incButton.onclick = function() {incdec(1, freqStep)};
|
|
decButton.onclick = function() {incdec(-1, freqStep)};
|
|
|
|
setSigGenFreq0.onfocus = function() {changeStep(1)};
|
|
setSigGenFreq1.onfocus = function() {changeStep(10)};
|
|
setSigGenFreq2.onfocus = function() {changeStep(100)};
|
|
setSigGenFreq3.onfocus = function() {changeStep(1000)};
|
|
setSigGenFreq4.onfocus = function() {changeStep(10000)};
|
|
setSigGenFreq5.onfocus = function() {changeStep(100000)};
|
|
setSigGenFreq6.onfocus = function() {changeStep(1000000)};
|
|
setSigGenFreq7.onfocus = function() {changeStep(10000000)};
|
|
setSigGenFreq8.onfocus = function() {changeStep(100000000)};
|
|
|
|
|
|
setSigGenFreq0.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(1);
|
|
incdec(-event.deltaY,1);
|
|
});
|
|
|
|
|
|
setSigGenFreq1.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(10);
|
|
incdec(-event.deltaY,10);
|
|
});
|
|
|
|
setSigGenFreq2.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(100);
|
|
incdec(-event.deltaY,100);
|
|
});
|
|
|
|
setSigGenFreq3.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(1000);
|
|
incdec(-event.deltaY,1000);
|
|
});
|
|
|
|
setSigGenFreq4.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(10000);
|
|
incdec(-event.deltaY,10000);
|
|
});
|
|
|
|
setSigGenFreq5.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(100000);
|
|
incdec(-event.deltaY,100000);
|
|
});
|
|
|
|
setSigGenFreq6.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(1000000);
|
|
incdec(-event.deltaY,1000000);
|
|
});
|
|
|
|
setSigGenFreq7.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(10000000);
|
|
incdec(-event.deltaY,10000000);
|
|
});
|
|
|
|
setSigGenFreq8.addEventListener('wheel', (event) => {
|
|
event.preventDefault();
|
|
changeStep(100000000);
|
|
incdec(-event.deltaY,100000000);
|
|
});
|
|
|
|
|
|
setSigGenPower.onchange = function() {
|
|
sendValue("L", setSigGenPower.value);
|
|
sigLevelSlider.value = this.value;
|
|
};
|
|
|
|
// Update the current level value (each time you drag the slider handle)
|
|
sigLevelSlider.oninput = function() {
|
|
setSigGenPower.value = this.value;
|
|
setSigGenPower.onchange();
|
|
}
|
|
|
|
function styleSigGenButton ( val ) {
|
|
if (sigOnButton.value == 1) {
|
|
sigOnButton.style="background-color:green";
|
|
} else {
|
|
sigOnButton.style="background-color:lightgrey";
|
|
}
|
|
}
|
|
|
|
sigOnButton.onclick = function() {
|
|
if (sigOnButton.value == 1) {
|
|
sigOnButton.value = 0;
|
|
} else {
|
|
sigOnButton.value = 1;
|
|
}
|
|
styleSigGenButton (sigOnButton.value);
|
|
sendValue("G", sigOnButton.value);
|
|
}
|
|
|
|
//var roundtripTime = document.getElementById('roundtripTime');
|
|
//var messageCount = document.getElementById('messageCount');
|
|
//var missedReplies = document.getElementById('missedReplies');
|
|
var messageCounter = 0;
|
|
var missedMessageCounter = 0;
|
|
var messageSendMilis;
|
|
|
|
var connection;
|
|
var connectionStatus = document.getElementById('connectionStatus');
|
|
var hostName = document.getElementById('hostName');
|
|
|
|
var pingCounter = 0;
|
|
var sendPingVar;
|
|
var dateObject;
|
|
|
|
|
|
|
|
/*
|
|
* Timed update of chart render to reduce load on slow smartphones or tablets
|
|
*/
|
|
function renderChart()
|
|
{
|
|
chartSA.render();
|
|
//setTimeout(renderChart, refreshInterval.value);
|
|
setTimeout(function(){renderChart()}, refreshInterval.value);
|
|
}
|
|
|
|
|
|
|
|
//messageCount.value = messageCounter;
|
|
//missedReplies.value = missedMessageCounter;
|
|
hostName.value = "ws://" + location.host + ":81";
|
|
|
|
// connect to simpleSA server
|
|
connect(hostName.value);
|
|
|
|
// At this point the page is running
|
|
|
|
$(document).ready(function () {
|
|
|
|
// update();
|
|
sendValue("r", 0); // get settings
|
|
var chartUpdateVar;
|
|
// chartUpdateVar = setInterval(renderChart, 500);
|
|
});
|
|
|
|
var initDone = false;
|
|
var indexUpdateMilliSeconds = 1 * 1000;
|
|
|
|
|
|
function handleSettings (settings)
|
|
{
|
|
setMode.value = settings.mode;
|
|
if (setMode.value == 8) { // RX Sweep (RBW test)
|
|
setStart.max = settings.IF;
|
|
setStop.max = 600;
|
|
setStart.min = 350;
|
|
setStart.disabled = false;
|
|
setStop.min = settings.IF;
|
|
setStop.disabled = false;
|
|
setCenter.disabled = true;
|
|
setSpan.disabled = true;
|
|
setRBW.disabled = false;
|
|
setRefOut.disabled = false;
|
|
setSpur.disabled = true;
|
|
setTrackGen.disabled = true;
|
|
setTGFreq.disabled = true;
|
|
setTrackGenPower.disabled = true;
|
|
setActPower.disabled = true;
|
|
sigDiv.style.display = "none";
|
|
chartDiv.style.display = "block";
|
|
} else if (settings.mode == 4 ) { // IF Sweep (SAW test)
|
|
setStart.max = settings.IF;
|
|
setStop.max = 460;
|
|
setStart.min = 400;
|
|
setStop.min = settings.IF;
|
|
setStart.disabled = false;
|
|
setStop.disabled = false;
|
|
setCenter.disabled = true;
|
|
setSpan.disabled = true;
|
|
setRBW.disabled = true;
|
|
setRefOut.disabled = false;
|
|
setSpur.disabled = true;
|
|
setTrackGen.disabled = true;
|
|
setTGFreq.disabled = true;
|
|
setTrackGenPower.disabled = true;
|
|
setActPower.disabled = true;
|
|
sigDiv.style.display = "none";
|
|
chartDiv.style.display = "block";
|
|
} else if (settings.mode == 7 ) { // BANDSCOPE
|
|
setStart.max = 350;
|
|
setStop.max = 350;
|
|
setStart.min = 0;
|
|
setStop.min = 0;
|
|
setStart.disabled = false;
|
|
setStop.disabled = true;
|
|
setCenter.disabled = true;
|
|
setSpan.disabled = false;
|
|
setRBW.disabled = false;
|
|
setRefOut.disabled = true;
|
|
setSpur.disabled = true;
|
|
setTrackGen.disabled = true;
|
|
setTrackGenPower.disabled = true;
|
|
setActPower.disabled = true;
|
|
sigDiv.style.display = "none";
|
|
chartDiv.style.display = "block";
|
|
} else if (settings.mode == 2 ) { // Signal Generator
|
|
setStart.max = 350;
|
|
setStop.max = 350;
|
|
setStart.min = 0;
|
|
setStop.min = 0;
|
|
setStart.disabled = true;
|
|
setStop.disabled = true;
|
|
setCenter.disabled = true;
|
|
setSpan.disabled = true;
|
|
setRBW.disabled = true;
|
|
setRefOut.disabled = true;
|
|
setSpur.disabled = true;
|
|
setTrackGen.disabled = true;
|
|
setTGFreq.disabled = true;
|
|
setTrackGenPower.disabled = true;
|
|
setActPower.disabled = true;
|
|
sigDiv.style.display = "block";
|
|
chartDiv.style.display = "none";
|
|
} else {
|
|
setStart.max = 350;
|
|
setStop.max = 350;
|
|
setStart.min = 0;
|
|
setStop.min = 0;
|
|
setStart.disabled = false;
|
|
setStop.disabled = false;
|
|
setCenter.disabled = false;
|
|
setSpan.disabled = false;
|
|
setRBW.disabled = false;
|
|
setRefOut.disabled = false;
|
|
setSpur.disabled = false;
|
|
setTrackGen.disabled = false;
|
|
setTGFreq.disabled = false;
|
|
setTrackGenPower.disabled = false;
|
|
setActPower.disabled = false;
|
|
sigDiv.style.display = "none";
|
|
chartDiv.style.display = "block";
|
|
}
|
|
|
|
|
|
|
|
actRBW.value = settings.bandwidth;
|
|
|
|
|
|
levelOffset.value = settings.levelOffset;
|
|
filterCal.value = settings.filterCal;
|
|
// console.log("levelOffset=" + settings.levelOffset);
|
|
|
|
if (settings.start/1000 != oldSweepStart) {
|
|
//console.log("Start:" + settings.start + " Stop:" + settings.stop + " oldStart:" + oldSweepStart);
|
|
//sweepStart.value = settings.start/1000;
|
|
setStart.value = settings.start/1000; // change default if changed
|
|
oldSweepStart = setStart.value;
|
|
setSpan.value = (settings.stop - settings.start)/1000;
|
|
}
|
|
|
|
if (settings.stop/1000 != oldSweepStop) {
|
|
//sweepStop.value = settings.stop/1000;
|
|
setStop.value = settings.stop/1000; // change default if changed
|
|
oldSweepStop = setStop.value;
|
|
setSpan.value = (settings.stop - settings.start)/1000;
|
|
}
|
|
|
|
tempCenter = ( (parseFloat(settings.stop) - parseFloat(settings.start) )/2 + parseFloat(settings.start) ) / 1000; // calculate center
|
|
if (tempCenter != oldSweepCenter) {
|
|
setCenter.value = tempCenter;
|
|
oldSweepCenter = tempCenter;
|
|
}
|
|
|
|
if (settings.attenuation != oldAttenuation) {
|
|
setAtten.value = settings.attenuation;
|
|
oldAttenuation = settings.attenuation;
|
|
}
|
|
|
|
if (settings.extGain != oldExternalGain) {
|
|
setExtern.value = settings.extGain;
|
|
oldExternalGain = settings.extGain;
|
|
}
|
|
|
|
if (settings.setRBW != oldSetRBW) {
|
|
setRBW.value = settings.setRBW;
|
|
oldSetRBW = settings.setRBW;
|
|
}
|
|
|
|
if (settings.RefOut != oldSetRefOut) {
|
|
setRefOut.value = settings.RefOut; // reference output dropdown
|
|
oldSetRefOut = settings.RefOut;
|
|
}
|
|
|
|
if (settings.Drive != oldDrive) {
|
|
setLODrive.value = settings.Drive; // LO Drive dropdown
|
|
oldDrive = settings.Drive;
|
|
}
|
|
|
|
if (settings.IF != oldIF) {
|
|
setIF.value = settings.IF; // IF value
|
|
oldIF = settings.IF;
|
|
}
|
|
|
|
if (settings.PreAmp != oldPreAmp) {
|
|
setPreAmp.value = settings.PreAmp; // PreAmp Gain value
|
|
oldPreAmp = settings.PreAmp;
|
|
}
|
|
|
|
if (settings.spur != oldSpur) {
|
|
if (settings.spur) {
|
|
spurReduction.checked = true; // Spur reduction checkbox
|
|
} else {
|
|
spurReduction.checked = false; // Spur reduction checkbox
|
|
}
|
|
oldSpur = settings.spur;
|
|
}
|
|
|
|
if (settings.sg != oldSigGen) { // Sig gen on/off
|
|
sigOnButton.value = settings.sg;
|
|
oldSigGen = settings.sg;
|
|
styleSigGenButton (sigOnButton.value);
|
|
}
|
|
|
|
if (settings.sgFreq != oldSigGenFreq) { // sig gen frequency
|
|
frequency = settings.sgFreq;
|
|
oldSigGenFreq = settings.sgFreq;
|
|
incdec(0,0);
|
|
console.log("sigGenFreq=" + settings.sgFreq);
|
|
}
|
|
|
|
sigLevelSlider.max = settings.sgCal; // Limits for sig gen power
|
|
sigLevelSlider.min = settings.sgCal - settings.sgRange;
|
|
setSigGenPower.max = settings.sgCal;
|
|
setSigGenPower.min = settings.sgCal - settings.sgRange;
|
|
|
|
if (settings.sgPower != oldSigGenPower) {
|
|
setSigGenPower.value = settings.sgPower;
|
|
sigLevelSlider.value = settings.sgPower;
|
|
oldSigGenPower = settings.sgPower;
|
|
}
|
|
|
|
|
|
if (settings.tg != oldTrackGen) { // tracking generator state
|
|
setTrackGen.value = settings.tg;
|
|
oldTrackGen = settings.tg;
|
|
}
|
|
|
|
if (settings.tgFreq != oldTGFreq) { // tracking generator frequency for sig gen mode
|
|
setTGFreq.value = settings.tgFreq/1000000;
|
|
oldTGFreq = settings.tgFreq;
|
|
}
|
|
|
|
|
|
if (settings.tgPower != oldTrackGenPower) { // tracking generator output power
|
|
setTrackGenPower.value = settings.tgPower;
|
|
oldTrackGenPower = settings.tgPower;
|
|
}
|
|
|
|
|
|
chartSA.options.axisX.minimum = setStart.value;
|
|
chartSA.options.axisX.maximum = setStop.value;
|
|
|
|
initDone = false;
|
|
|
|
}
|
|
|
|
function handleData (data) // rarely used! see handleChunkData for most sweeps
|
|
{
|
|
|
|
if (data.sweepPoints != sweepPoints.value) {
|
|
// reset chart data
|
|
chartSA.options.data[0].dataPoints.length = 2;
|
|
chartSA.options.data[1].dataPoints.length = 2;
|
|
chartSA.options.data[3].dataPoints.length = 2;
|
|
sweepPoints.value = data.sweepPoints;
|
|
}
|
|
|
|
|
|
var b = parseFloat(levelOffset.value) + parseFloat(setAtten.value) - 120 - parseFloat(setExtern.value);
|
|
//chartSA.options.data[0].dataPoints = data.Points; // First series dB
|
|
chartSA.options.data[0].dataPoints = data.Points.map(obj => {
|
|
let rObj = {}
|
|
rObj.x = obj.x
|
|
rObj.y = obj.y/2+b
|
|
return rObj
|
|
})
|
|
|
|
chartSA.options.data[1].dataPoints = data.Points; // RSSI trace
|
|
chartSA.options.data[1].axisYType = "secondary";
|
|
|
|
if ((initDone == 0) || (oldSweepPoints != data.sweepPoints) || (oldDataPointCount != data.Points.length)) {
|
|
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints // first run
|
|
initDone = 1;
|
|
oldSweepPoints = data.Points.length;
|
|
oldDataPointCount = data.Points.length;
|
|
}
|
|
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
|
|
let rObj = {}
|
|
rObj.x = obj.x
|
|
rObj.y = chartSA.options.data[3].dataPoints[index].y*(1-1/setAverage) + obj.y*1/setAverage;
|
|
return rObj
|
|
})
|
|
|
|
chartSA.options.axisX.minimum = setStart.value;
|
|
chartSA.options.axisX.maximum = setStop.value;
|
|
// chartSA.options.axisY.minimum = -120;
|
|
// chartSA.options.axisY.maximum = 0;
|
|
chartSA.options.axisY2.minimum = 0;
|
|
chartSA.options.axisY2.maximum = 255;
|
|
// RSSISamples.from(data.Points); // moves data
|
|
//console.log(RSSISamples[10].y);
|
|
// update the chart
|
|
chartSA.render();
|
|
}
|
|
|
|
|
|
function handleChunkData (data)
|
|
{
|
|
var init = false;
|
|
var n = data.sweepPoints;
|
|
|
|
if (n != oldSweepPoints) {
|
|
// reset chart data
|
|
chartSA.options.data[0].dataPoints.length = 0;
|
|
chartSA.options.data[1].dataPoints.length = 0;
|
|
chartSA.options.data[2].dataPoints.length = 0;
|
|
chartSA.options.data[3].dataPoints.length = 0;
|
|
chartSA.options.data[4].dataPoints.length = 0;
|
|
|
|
|
|
// add dummy data points
|
|
var i;
|
|
for (i=0; i<n; i++) {
|
|
var p = {x:250, y:-120};
|
|
var q = {x:250, y:0};
|
|
var r = {x:250, y:49};
|
|
var s = {x:250, y:-120};
|
|
var m = {x:250, y:10};
|
|
chartSA.options.data[0].dataPoints.push(p); // dB
|
|
chartSA.options.data[1].dataPoints.push(q); // RSSI
|
|
chartSA.options.data[2].dataPoints.push(r); // gain
|
|
chartSA.options.data[3].dataPoints.push(s); // average
|
|
chartSA.options.data[4].dataPoints.push(m); // min - initialise to high value
|
|
}
|
|
|
|
//chartSA.options.data[0].dataPoints.length = n; // reduces size if > no of data points
|
|
//chartSA.options.data[1].dataPoints.length = n;
|
|
//chartSA.options.data[2].dataPoints.length = n;
|
|
//chartSA.options.data[3].dataPoints.length = n;
|
|
|
|
sweepPoints.value = data.sweepPoints;
|
|
init = true;
|
|
initDone = false;
|
|
oldSweepPoints = n;
|
|
//chartSA.render();
|
|
}
|
|
|
|
var dataStart = data.StartIndex;
|
|
|
|
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120 - parseFloat(setExtern.value);
|
|
// If RX Sweep (test of rbw filters) then don't add the correction from calibration
|
|
if (setMode.value != 8) b = b + parseFloat(filterCal.value);
|
|
|
|
var a = 1/setAverage.value;
|
|
|
|
data.Points.forEach (function (point, index) { // copy data into the chart data series
|
|
var p = {};
|
|
p = point.y; // create a copy not a reference ??
|
|
var f = {};
|
|
f = point.x;
|
|
var g = {};
|
|
g = point.g;
|
|
|
|
chartSA.options.data[1].dataPoints[dataStart + index].x = f * 1; // RSSI
|
|
chartSA.options.data[1].dataPoints[dataStart + index].y = p * 1;
|
|
|
|
chartSA.options.data[0].dataPoints[dataStart + index].x = f * 1; // dBm
|
|
var dB = p/2+b;
|
|
chartSA.options.data[0].dataPoints[dataStart + index].y = dB * 1;
|
|
|
|
chartSA.options.data[2].dataPoints[dataStart + index].x = f * 1; // gain
|
|
chartSA.options.data[2].dataPoints[dataStart + index].y = g * 1;
|
|
|
|
|
|
//chartSA.options.data[3].dataPoints[dataStart + index] = point;
|
|
//try {
|
|
//chartSA.options.data[3].dataPoints[dataStart + index].x = f * 1;
|
|
// if (initDone) {
|
|
// var av = chartSA.options.data[3].dataPoints[dataStart + index].y*(1-a) + dB*a;
|
|
// chartSA.options.data[3].dataPoints[dataStart + index].y = av * 1;
|
|
// } else {
|
|
// chartSA.options.data[3].dataPoints[dataStart + index].y = dB * 1;
|
|
// }
|
|
//}
|
|
//catch {
|
|
// chartSA.options.data[3].dataPoints[dataStart + index].y = point.y/2+b;
|
|
//}
|
|
|
|
})
|
|
|
|
|
|
// If end of sweep update the average and min data sets
|
|
if (dataStart + data.Points.length >= data.sweepPoints) {
|
|
if (!initDone) { // If first time then set the values to current dB series
|
|
initDone = true;
|
|
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
|
|
let rObj = {}
|
|
rObj.x = obj.x;
|
|
rObj.y = obj.y*1;
|
|
return rObj
|
|
})
|
|
chartSA.options.data[4].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
|
|
let rObj = {}
|
|
rObj.x = obj.x;
|
|
rObj.y = obj.y*1;
|
|
return rObj
|
|
})
|
|
} else {
|
|
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
|
|
let rObj = {}
|
|
rObj.x = obj.x;
|
|
rObj.y = chartSA.options.data[3].dataPoints[index].y*(1-a) + obj.y*a;
|
|
return rObj
|
|
})
|
|
chartSA.options.data[4].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
|
|
let rObj = {}
|
|
rObj.x = obj.x;
|
|
rObj.y = Math.min(chartSA.options.data[4].dataPoints[index].y, obj.y);
|
|
return rObj
|
|
})
|
|
}
|
|
|
|
// if (chartSA.options.data[2].visible) {
|
|
// $.getJSON( "getGainSweep") // proper line
|
|
// $.getJSON( "getGainSweep.json") // for local test
|
|
// .done(function (data) {
|
|
// We have the data, process it.
|
|
// chartSA.options.data[2].dataPoints = data.gainPoints; // Gain trace
|
|
// });
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
//chartSA.render();
|
|
|
|
// dataPoints.value = chartSA.options.data[0].dataPoints.length;
|
|
sweepTime.value = data.sweepTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function update()
|
|
{
|
|
// Get the settings
|
|
|
|
$.getJSON( "getSettings")
|
|
.done(function (settings) {
|
|
handleSettings(settings);
|
|
})
|
|
|
|
.fail(function(jqxhr, textStatus, error) {
|
|
var err = textStatus +", " + error;
|
|
console.log("Settings Request Failed: " + err);
|
|
});
|
|
|
|
|
|
// Get the sweep data
|
|
|
|
$.getJSON( "getSweep") // proper line
|
|
// $.getJSON( "getSweep.json") // for local test
|
|
.done(function (data) {
|
|
// We have the data, process it.
|
|
handleData(data);
|
|
//setTimeout(update, indexUpdateMilliSeconds);
|
|
|
|
})
|
|
|
|
.fail(function(jqxhr, textStatus, error) {
|
|
var err = textStatus +", " + error;
|
|
console.log("Sweep Request Failed: " + err);
|
|
});
|
|
|
|
|
|
if (chartSA.options.data[2].visible) {
|
|
$.getJSON( "getGainSweep") // proper line
|
|
// $.getJSON( "getGainSweep.json") // for local test
|
|
.done(function (data) {
|
|
// We have the data, process it.
|
|
chartSA.options.data[2].dataPoints = data.gainPoints; // Gain trace
|
|
});
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
// This method is called to add all necessary options to a
|
|
// select representing the available resolution bandwidths(RBW).
|
|
// default is auto
|
|
*/
|
|
function buildRBWSelect()
|
|
{
|
|
let dropdown = $('#setRBW');
|
|
|
|
dropdown.empty();
|
|
|
|
// Populate dropdown with list of RBW
|
|
$.getJSON("getRbwList", function (data) {
|
|
dropdown.append($('<option class="select-option" ></option>').attr('value', 0).text("Auto"));
|
|
|
|
$.each(data, function (key, bpf) {
|
|
dropdown.append($('<option class="select-option" ></option>').attr('value', bpf.bw10).text(bpf.bw));
|
|
})
|
|
|
|
});
|
|
|
|
//dropdown.prop('selectedIndex', 0);
|
|
}
|
|
|
|
buildRBWSelect();
|
|
|
|
|
|
/*
|
|
// This method is called to add all necessary options to a
|
|
// select representing the available attenuations.
|
|
// default is auto
|
|
*/
|
|
function buildAttenSelect()
|
|
{
|
|
let dropdown = $('#setAtten');
|
|
|
|
dropdown.empty();
|
|
|
|
// Populate dropdown with list of RBW
|
|
$.getJSON("getAttenList", function (data) {
|
|
$.each(data, function (key, att) {
|
|
dropdown.append($('<option class="select-option" ></option>').attr('value', att.dB).text(att.dB));
|
|
})
|
|
|
|
});
|
|
|
|
//dropdown.prop('selectedIndex', 0);
|
|
}
|
|
|
|
//buildAttenSelect();
|
|
|
|
|
|
|
|
function connect(host)
|
|
{
|
|
if(connection)
|
|
{
|
|
//connection.close(); // restart
|
|
return; // already connected
|
|
}
|
|
|
|
connectionStatus.value = "Connecting...";
|
|
connection = new WebSocket(host, ['arduino']);
|
|
|
|
connection.onopen = function()
|
|
{
|
|
connectionStatus.value = "Connected";
|
|
connectionStatus.style = "background-color:lightgreen";
|
|
connection.send('Hello from Browser :-) ' + new Date());
|
|
sendMessage();
|
|
sendPingVar = setInterval(function(){ sendPing() }, 30000);
|
|
|
|
sendValue("r",0); // request settings
|
|
|
|
// Get the settings to make sure current
|
|
//$.getJSON( "getSettings")
|
|
// .done(function (settings) {
|
|
// handleSettings(settings);
|
|
// })
|
|
//
|
|
// .fail(function(jqxhr, textStatus, error) {
|
|
// var err = textStatus +", " + error;
|
|
// console.log("Settings Request Failed: " + err);
|
|
// });
|
|
|
|
var items = document.querySelectorAll(".value-input");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = false;
|
|
}
|
|
|
|
var items = document.querySelectorAll(".select-input");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = false;
|
|
}
|
|
|
|
var items = document.querySelectorAll(".select-button");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = false;
|
|
}
|
|
|
|
var items = document.querySelectorAll(".checkbox-input");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = false;
|
|
}
|
|
|
|
};
|
|
|
|
connection.onclose = function(event)
|
|
{
|
|
clearInterval(sendPingVar);
|
|
connectionStatus.value = "Disconnected";
|
|
connectionStatus.style = "background-color:red";
|
|
//connection.removeEventListeners();
|
|
connection = null;
|
|
// Disable user input
|
|
var items = document.querySelectorAll(".value-input");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = true;
|
|
}
|
|
|
|
var items = document.querySelectorAll(".select-input");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = true;
|
|
}
|
|
|
|
var items = document.querySelectorAll(".select-button");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = true;
|
|
}
|
|
|
|
var items = document.querySelectorAll(".checkbox-input");
|
|
var i;
|
|
for (i = 0; i< items.length; i++) {
|
|
items[i].disabled = true;
|
|
}
|
|
|
|
};
|
|
|
|
connection.onerror = function(error)
|
|
{
|
|
console.log("WebSocket Error ", error);
|
|
};
|
|
|
|
connection.onmessage = function(message) // to be used later when we send data at each sweep
|
|
{
|
|
//console.log("Websocket message received");
|
|
|
|
// show message
|
|
//messageWindow.value = message.data;
|
|
//messageSize.value = message.data.length;
|
|
|
|
// check only messages begining with '{'
|
|
if(message.data[0] == "{")
|
|
{
|
|
// //console.log("Parsing message");
|
|
myObject = JSON.parse(message.data);
|
|
//console.log("message type " + myObject.mType);
|
|
if (myObject.mType == "Settings")
|
|
{
|
|
pointsCount = myObject.dispPoints;
|
|
// sweepSamples = myObject.Points;
|
|
//console.log("handle settings");
|
|
handleSettings(myObject);
|
|
}
|
|
else if (myObject.mType == "fullSweep")
|
|
{
|
|
//console.log("handle full Sweep");
|
|
handleData(myObject);
|
|
}
|
|
else if (myObject.mType == "chunkSweep")
|
|
{
|
|
//console.log("handle chunk Sweep:" + myObject.StartIndex);
|
|
handleChunkData(myObject);
|
|
}
|
|
else
|
|
{
|
|
console.log("Invalid json message type");
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
function disconnect()
|
|
{
|
|
if(connection)
|
|
{
|
|
connection.close();
|
|
}
|
|
else
|
|
{
|
|
connectionStatus.value = "Not connected yet";
|
|
}
|
|
}
|
|
|
|
function sendValue(c, val)
|
|
{
|
|
//
|
|
// Message format
|
|
// #(code) value where code is a single char. Case is important
|
|
// a start freq (MHz)
|
|
// b stop frequency
|
|
// c centre frequency
|
|
// s Span
|
|
// d Local Oscillator Drive
|
|
// g PreAmpGain/Mode
|
|
// i IF frequency
|
|
// m mode
|
|
// p set actual power to peak value
|
|
// o RefOut
|
|
// r request Settings are pushed
|
|
// A internal attenuation (PE4302)
|
|
// E external gain ( eg attenuator(-ve) or preamp(+ve) )
|
|
// R requested RBW
|
|
// S Spur reduction Off/On
|
|
// t trackGen Off/On/Fixed
|
|
// T trackGen output level
|
|
// f trackgen signal generator frequency
|
|
// F Sig Gen frequency
|
|
// L Sig Gen level (dBm)
|
|
// G Sig Gen Off/On
|
|
// P Sig Gen set max output level (dBm)
|
|
//
|
|
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
|
|
if (connectionStatus.value == "Connected") {
|
|
connection.send("#" + c + " " + val);
|
|
console.log("Command:" + c + val);
|
|
} else {
|
|
console.log("No connection - Command:" + c + val);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function sendMessage()
|
|
{
|
|
messageCounter++;
|
|
//messageCount.value = messageCounter;
|
|
dateObject = new Date();
|
|
messageSendMilis = dateObject.getTime();
|
|
//
|
|
// Message format
|
|
// # MESSAGE_NUMBER SAMPLE_THRESHOLD NUMBER_OF_SAMPLES
|
|
//
|
|
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
|
|
connection.send("# " + messageCounter + " " + sweepStart + " " + sweepStop);
|
|
}
|
|
|
|
function sendPing()
|
|
{
|
|
connection.send('ping');
|
|
pingCounter++;
|
|
connectionPings.value = pingCounter;
|
|
}
|
|
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|