diff --git a/apps/skyspy/ChangeLog b/apps/skyspy/ChangeLog index a67665086..01e4d6aa0 100644 --- a/apps/skyspy/ChangeLog +++ b/apps/skyspy/ChangeLog @@ -3,3 +3,4 @@ 0.03: big rewrite, adding time-adjust and altitude-adjust functionality 0.04: more refactoring, fix lat/lon display 0.10: add screens with time to fixes and estimate of time to fix +0.11: introduce graphical gps status diff --git a/apps/skyspy/metadata.json b/apps/skyspy/metadata.json index 628ce6a32..b19518392 100644 --- a/apps/skyspy/metadata.json +++ b/apps/skyspy/metadata.json @@ -1,6 +1,6 @@ { "id": "skyspy", "name": "Sky Spy", - "version": "0.10", + "version": "0.11", "description": "Application for debugging GPS problems", "icon": "app.png", "readme": "README.md", diff --git a/apps/skyspy/skyspy.app.js b/apps/skyspy/skyspy.app.js index 81dbbe696..80ddaaa5d 100644 --- a/apps/skyspy/skyspy.app.js +++ b/apps/skyspy/skyspy.app.js @@ -200,10 +200,16 @@ let gps = { }, }; -/* ui library 0.1.5 */ +/* ui library 0.1.5, dirty, bad, revert! */ let ui = { display: 0, numScreens: 2, + clear: function() { + g.reset() + .setColor(g.theme.bg) + .fillRect(0, this.wi, this.w, this.y2) + .setColor(g.theme.fg); + }, drawMsg: function(msg) { g.reset().setFont("Vector", 35) .setColor(g.theme.bg) @@ -296,11 +302,7 @@ let ui = { }, }; -function log2(x) { - return Math.log(x) / Math.log(2); -} - -/* pie library v0.0.1 */ +/* pie library v0.0.4 */ let pie = { radians: function(a) { return a*Math.PI/180; }, @@ -310,77 +312,123 @@ let pie = { points.push(centerX, centerY); // Start at the center // Step through angles to create points on the arc - for (let angle = startAngle; angle <= endAngle; angle += 5) { - const x = centerX + Math.cos(this.radians(angle)) * radius; - const y = centerY + Math.sin(this.radians(angle)) * radius; + for (let angle = startAngle; angle <= endAngle; angle += 15) { + const x = centerX + Math.sin(this.radians(angle)) * radius; + const y = centerY - Math.cos(this.radians(angle)) * radius; points.push(x, y); } // Add the final point at the end angle - points.push(centerX + Math.cos(this.radians(endAngle)) * radius); - points.push(centerY + Math.sin(this.radians(endAngle)) * radius); + points.push(centerX + Math.sin(this.radians(endAngle)) * radius); + points.push(centerY - Math.cos(this.radians(endAngle)) * radius); g.fillPoly(points); // Draw the arc as a polygon }, // Function to draw the pie chart drawPieChart1: function(g, centerX, centerY, radius, data, colors) { - let startAngle = 0; + let startAngle = data[0]; // Loop through the data to draw each segment - for (let i = 0; i < data.length; i++) { + for (let i = 1; i < data.length; i++) { const angle = data[i]; // Get the angle for the current section - const endAngle = startAngle + angle; // Calculate the end angle + const endAngle = angle; // Calculate the end angle g.setColor(colors[i]); // Set the fill color this.fillArc(g, centerX, centerY, radius, startAngle, endAngle, colors[i]); // Draw the arc - startAngle = endAngle; // Update the start angle for the next segment + startAngle = angle; // Update the start angle for the next segment } - - g.flip(); // Update the screen }, - altDelta: function(centerX, centerY, radius, altitude, altChange) { - // Altitude range and mapping to a logarithmic scale - //const altitudeMin = -1000, altitudeMax = 1000; - const altitudeLog = log2(Math.abs(altitude) + 1) * Math.sign(altitude); // Logarithmic scaling - const altitudeAngle = E.clip((altitudeLog - log2(1)) / (log2(1001) - log2(1)), -1, 1) * 180; - - // Altitude Change (linear scale) - const altChangeMin = -30, altChangeMax = 30; - const altChangeAngle = E.clip((altChange - altChangeMin) / (altChangeMax - altChangeMin), 0, 1) * 360; - - this.twoPie(centerX, centerY, radius, altitudeAngle, altChangeAngle); - }, - - twoPie: function(centerX, centerY, radius, altitudeAngle, altChangeAngle) { - // Outer Ring (Altitude Change) - Draw a segment based on altitude change - - g.setColor(0, 0, 0.5); // Set a color for the outer ring - this.fillArc(g, - centerX, centerY, - radius, // Define the thickness of the outer ring - 0, altChangeAngle // Draw based on altitude change - ); - - // Inner Ring (Altitude) - Draw a segment based on altitude angle - const innerRadius = radius * 0.6; // Inner ring size - g.setColor(0, 0.5, 0); // Set a color for the inner ring - this.fillArc(g, - centerX, centerY, - innerRadius, // Define thickness of inner ring - 0, altitudeAngle // Draw based on altitude - ); - - // Draw the baseline circle for reference - g.setColor(0, 0, 0); // Gray for baseline - g.drawCircle(centerX, centerY, innerRadius); // Inner circle (reference) - g.drawCircle(centerX, centerY, radius); // Outer circle (reference) - - // Render the chart - g.flip(); - } }; +let gpsg = { + cx: ui.w/2, + cy: ui.wi+ui.h/2, + s: ui.h/2 - 1, + sats: 4, /* Number of sats with good enough snr */ + sats_bad: 0, /* Sattelites visible but with low snr */ + view_t: getTime(), /* When sky became visible */ + start_t: getTime(), /* When we started acquiring fix */ + dalt: 30, /* Altitude error between barometer and gps */ + fix: {}, + + init : function() { + }, + drawCorner(h, v) { + let cx = this.cx; + let cy = this.cy; + let s = this.s; + let st = 48; + let a = [cx+h*s, cy+v*s, cx+h*s - h*st, cy+v*s, cx+h*s, cy+v*s - v*st]; + g.fillPoly(a); + }, + clamp: function(low, v, high) { + if (v < low) + v = low; + if (v > high) + v = high; + return [ low, v, high ]; + }, + draw : function() { + let cx = this.cx; + let cy = this.cy; + let s = this.s; + ui.clear(); + g.fillCircle(cx, cy, s); + if (!this.fix.fix) + this.drawCorner(1, -1); + if (this.fix.hdop > 10) + this.drawCorner(1, 1); + if (this.fix.satellites < 4) + this.drawCorner(-1, 1); + if (this.sats < 4) + this.drawCorner(-1, -1); + + g.setColor(1, 1, 1); + let t = getTime(); + if (this.fix.fix) { /* Have speed */ + let data = this.clamp(210, 210 + (360*this.fix.speed) / 20, 210+360); + let colors = [ "ign", "#000", "#fff" ]; + pie.drawPieChart1(g, cx, cy, s * 1, data, colors); + } else { + let data = this.clamp(0, (360*(t - this.start_t)) / 600, 360); + let colors = [ "ign", "#888", "#000" ]; + pie.drawPieChart1(g, cx, cy, s * 1, data, colors); + } + if (this.fix.fix) { + let data = this.clamp(90, 90 + (360*this.dalt) / 200, 90+360); + let colors = [ "ign", "#000", "#fff" ]; + pie.drawPieChart1(g, cx, cy, s * 0.6, data, colors); + } else { /* Still waiting for fix */ + let data = this.clamp(0, (360*(t - this.view_t)) / 120, 360); + let colors = [ "ign", "#888", "#000" ]; + pie.drawPieChart1(g, cx, cy, s * 0.6, data, colors); + } + if (this.fix.fix) { + let slice = 360 / 8; + let sats = this.fix.satellites; + let data = this.clamp( 0, slice * sats, 360 ); + let colors = [ "ign", "#fff", "#000" ]; + pie.drawPieChart1(g, cx, cy, s * 0.3, data, colors); + } else { + let slice = 360 / 8; + let sats = this.sats; + let red = sats + this.sats_bad; + if (sats > 8) + sats = 8; + if (red > 8) + red = 8; + let data = [ 0, slice * sats, slice * red, 360 ]; + let colors = [ "ign", "#888", "#800", "#000" ]; + pie.drawPieChart1(g, cx, cy, s * 0.3, data, colors); + } + }, +}; + +function log2(x) { + return Math.log(x) / Math.log(2); +} + var debug = 0; var cur_altitude; var adj_time = 0, adj_alt = 0; @@ -500,9 +548,17 @@ let quality = { let t = getTime(); //print(t, this.fix_start); msg = "St: " + fmt.fmtTimeDiff(t-gps.gps_start) + "\n"; - msg += "Sky: " + fmt.fmtTimeDiff(t-sky.all.sky_start) + "\n"; + msg += "Sky: " + fmt.fmtTimeDiff(t-skys.sky_start) + "\n"; msg += "2D: " + fmt.fmtTimeDiff(t-quality.fix_start) + "\n"; msg += "3D: " + fmt.fmtTimeDiff(t-quality.f3d_start) + "\n"; + } else if (ui.display == 5) { + gpsg.start_t = gps.gps_start; + gpsg.view_t = skys.sky_start; + gpsg.sats = skys.sats_used; + gpsg.sats_bad = skys.sats_weak; + gpsg.fix = fix; + gpsg.dalt = Math.abs(adelta); + gpsg.draw(); } quality.step++; if (quality.step == 10) { @@ -524,12 +580,18 @@ let skys = { sats: [], snum: 0, sats_used: 0, + sats_weak: 0, sky_start: -1, + /* 18.. don't get reliable fix in 40s */ + /* 25.. seems to be good limit for clear sky. ~60 seconds. + .. maybe better 26? */ + snrLim: 25, reset: function() { this.snum = 0; this.sats = []; this.sats_used = 0; + this.sats_weak = 0; }, parseSats: function(s) { let view = 1 * s[3]; @@ -542,6 +604,9 @@ let skys = { this.sats_used++; print(sat.id, sat.snr); } + if (sat.snr > 0) { + this.sats_weak++; + } this.sats[this.snum++] = sat; } }, @@ -619,7 +684,7 @@ let skys = { }, onEnd: function () { this.trackSatelliteVisibility(); - if (this.sats_used < 5) + if (this.sats_used < 4) this.sky_start = getTime(); this.reset(); }, @@ -647,7 +712,7 @@ let sky = { this_usable: 0, debug: 0, all: skys, /* Sattelites from all systems */ - split: 1, + split: 0, init: function () { if (this.split) { @@ -665,8 +730,6 @@ let sky = { ui.radCircle(1.0); }, - /* 18.. don't get reliable fix in 40s */ - snrLim: 22, drawSat: function(s) { let a = s.azi / 360; let e = ((90 - s.ele) / 90); @@ -675,7 +738,7 @@ let sky = { if (s.snr == 0) g.setColor(1, 0.25, 0.25); - else if (s.snr < this.snrLim) + else if (s.snr < this.all.snrLim) g.setColor(0.25, 0.5, 0.25); else g.setColor(0, 0, 0); @@ -885,18 +948,20 @@ function onMessage() { ui.init(); -ui.numScreens = 5; +ui.numScreens = 6; /* 0.. sat drawing 1.. position, basic data 2.. fix quality esitmation 3.. times from ... 4.. time to fix experiment + 5.. gps graph */ gps.init(); quality.resetAlt(); fmt.init(); sky.onMessageEnd = onMessage; sky.init(); +gpsg.init(); sky.decorate = () => { let p = 15;