Skip to content

Commit

Permalink
Merge pull request #3674 from pavelmachek/m_42_spacer
Browse files Browse the repository at this point in the history
spacer: Compare GPS with Baido and Glonass
  • Loading branch information
bobrippling authored Dec 20, 2024
2 parents 6e11c56 + 97911d7 commit bc5fb81
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 0 deletions.
1 change: 1 addition & 0 deletions apps/spacer/ChangeLog
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.01: attempt to import
8 changes: 8 additions & 0 deletions apps/spacer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Space Race

Compare GPS with Baido and Glonass

This turns GNSS receiver into mode with all three systems enabled, and
displays debug info from all of them. Click into top left corner to
switch navigation systems.

2 changes: 2 additions & 0 deletions apps/spacer/app-icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require("heatshrink").decompress(atob("mEwgIQNgQFEj/gAof+jgECgeAAIIFBgwCBuACBhgCEjAOEAoQ6CmAhCDwItDoEB4AFCsEBFgUEkEDG4XEJYcL8gFCgUP+gxCAoP8DIIFBhfsiEIAoMJAogCBAoYlBiBMBAoUwrA0B////ALECI0QAocgAolgApVADolAHYnAAomAAoqdBAoKVBMoRvCOIQDCRIIFBYwKVBAoKqC4AFBVQVggTRDn0CYgQcBN4LpDV4T7IAooAJA="))

Binary file added apps/spacer/app.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions apps/spacer/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{ "id": "spacer",
"name": "Space Race",
"version": "0.01",
"description": "Compare GPS with Baido and Glonass",
"icon": "app.png",
"readme": "README.md",
"supports" : ["BANGLEJS2"],
"tags": "tool",
"storage": [
{"name":"spacer.app.js","url":"spacer.app.js"},
{"name":"spacer.img","url":"app-icon.js","evaluate":true}
]
}
333 changes: 333 additions & 0 deletions apps/spacer/spacer.app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
/* Space race */

/*
Performance Assessment of GNSS Signals in
terms of Time to First Fix for
Cold, Warm and Hot Start
Matteo Paonni, Marco Anghileri, Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller
Institute of Geodesy and Navigation, University FAF Munich, Germany
=> 22 to 26 dB -- long time / no fix / ...
=> 26db + -- basically strength no longer matters
apps/assistedgps/custom.html
https://github.com/espruino/EspruinoDocs/blob/master/info/Bangle.js2%20Technical.md#gps
gsa mi rika 2d/3d fix, a taky pdop/vdop/hdop
CFG-NAVX z CASIC_en -- umoznuje nastavit chodec / auto / letadlo
MON-VER -- vrati version stringy
CFG-PMS z gpssetup to zda se neumi?
2.11.5 CFG-RATE (0x06 0x04)
*/

/* ui library 0.1.4 */
let ui = {
display: 0,
numScreens: 2,
drawMsg: function(msg) {
g.reset().setFont("Vector", 35)
.setColor(1, 1, 1)
.fillRect(0, this.wi, this.w, this.y2)
.setColor(0, 0, 0)
.drawString(msg, 5, 30)
.flip();
},
drawBusy: function() {
this.drawMsg("\n.oO busy");
},
nextScreen: function() {
print("nextS");
this.display = this.display + 1;
if (this.display == this.numScreens)
this.display = 0;
this.drawBusy();
},
prevScreen: function() {
print("prevS");
this.display = this.display - 1;
if (this.display < 0)
this.display = this.numScreens - 1;
this.drawBusy();
},
onSwipe: function(dir) {
this.nextScreen();
},
wi: 24,
y2: 176,
h: 152,
w: 176,
last_b: 0,
topLeft: function() { this.drawMsg("Unimpl"); },
topRight: function() { this.drawMsg("Unimpl"); },
touchHandler: function(d) {
let x = Math.floor(d.x);
let y = Math.floor(d.y);

if (d.b != 1 || this.last_b != 0) {
this.last_b = d.b;
return;
}

print("touch", x, y, this.h, this.w);

if ((x<this.w/2) && (y<this.y2/2))
this.topLeft();
if ((x>this.w/2) && (y<this.y2/2))
this.topRight();
if ((x<this.w/2) && (y>this.y2/2)) {
print("prev");
this.prevScreen();
}
if ((x>this.w/2) && (y>this.y2/2)) {
print("next");
this.nextScreen();
}
},
init: function() {
this.h = this.y2 - this.wi;
this.drawBusy();
},
/* radial angle -- convert 0..1 to 0..2pi */
radA: function(p) { return p*(Math.PI*2); },
/* radial distance -- convert 0..1 to something that fits on screen */
radD: function(d) { return d*(ui.h/2); },

/* given angle/distance, get X coordinate */
radX: function(p, d) {
let a = this.radA(p);
return this.w/2 + Math.sin(a)*this.radD(d);
},
/* given angle/distance, get Y coordinate */
radY: function(p, d) {
let a = this.radA(p);
return this.h/2 - Math.cos(a)*this.radD(d) + this.wi;
},
radLine: function(a1, d1, a2, d2) {
g.drawLine(this.radX(a1, d1), this.radY(a1, d1), this.radX(a2, d2), this.radY(a2, d2));
},
radCircle: function(d) {
g.drawCircle(this.radX(0, 0), this.radY(0, 0), this.radD(d));
if (1)
return;
let step = 0.05;
for (let i = 0; i < 1; i += 0.05) {
this.radLine(i - step, d, i, d);
}
},
};

let fix = {}; /* Global for sky library */

/* sky library v0.1.0 */
let sky = {
sats: [],
snum: 0,
sats_used: 0,
sky_start: -1,
this_usable: 0,

drawGrid: function() {
g.setColor(0,0,0);
ui.radLine(0, 1, 0.5, 1);
ui.radLine(0.25, 1, 0.75, 1);
ui.radCircle(0.5);
ui.radCircle(1.0);
},

snrLim: 28,
drawSat: function(s) {
let a = s.azi / 360;
let e = ((90 - s.ele) / 90);
let x = ui.radX(a, e);
let y = ui.radY(a, e);

if (s.snr == 0)
g.setColor(1, 0.25, 0.25);
else if (s.snr < this.snrLim)
g.setColor(0.25, 0.5, 0.25);
else
g.setColor(0, 0, 0);
g.drawString(s.id, x, y);
},

// Should correspond to view from below.
// https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1
decorate: function() {},
drawSats: function(sats) {
if (ui.display != 0)
return;
g.reset()
.setColor(1, 1, 1)
.fillRect(0, ui.wi, ui.w, ui.y2)
.setFont("Vector", 20)
.setFontAlign(0, 0);
this.drawGrid();
sats.forEach(s => this.drawSat(s));

if (fix && fix.fix && fix.lat) {
g.setColor(0, 0, 0)
.setFontAlign(-1, 1);
g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2);
}
this.decorate();
},

parseSats: function(s) {
let view = 1 * s[3];
let k = Math.min(4, view - this.snum);
for (let i = 4, j = 0; j < k; j++) {
let sat = { id: s[i++], ele: 1 * s[i++], azi: 1 * s[i++], snr: s[i++] };
if (sat.snr === "")
sat.snr = 0;
if (sat.snr >= this.snrLim) {
this.sats_used++;
print(sat.id, sat.snr);
}
this.sats[this.snum++] = sat;
}
},

old_msg: {},
msg: {},
tof: function(v) { let i = (1*v); return i.toFixed(0); },
fmtSys: function(sys) {
if (sys && sys.sent !== undefined && sys.d23 !== undefined)
return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n";
else
return "(no data)\n";
},
display: function() {
if (ui.display != 1)
return;
let m = this.old_msg;
let msg = "" + this.tof(m.time) + "\n" +
"q" + m.quality + " " + m.in_view + " " + m.hdop + "\n" +
"gp"+ this.fmtSys(m.gp) +
"bd" + this.fmtSys(m.bd) +
"gl" + this.fmtSys(m.gl);
if (this.msg.finished != 1)
msg += "!";
g.reset().clear().setFont("Vector", 30)
.setColor(0, 0, 0)
.setFontAlign(-1, -1)
.drawString(msg, 0, 0);
},
parseRaw: function(msg, lost) {
if (lost) print("## data lost");
let s = msg.split(",");
let cmd = s[0].slice(3);
//print("cmd", cmd);
if (cmd === "GGA") {
this.old_msg = this.msg;
this.msg = {};
this.msg.time = s[1];
this.msg.quality = s[6];
this.msg.in_view = s[7];
this.msg.hdop = s[8];
this.msg.gp = {};
this.msg.bd = {};
this.msg.gl = {};
print("-----------------------------------------------");
print("GGA Time", s[1], "fix quality", s[4], "sats in view ", s[5]);
this.drawSats(this.sats);
if (this.sats_used < 5)
this.sky_start = getTime();
this.snum = 0;
this.sats = [];
this.sats_used = 0;
return;
}
if (cmd === "GLL") return; /* Position lat/lon */
if (cmd === "GSA") {
/*
$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04
0 1 2 15 16 17 18
*/
/* Satelites used, fix type! INTERESTING */
let sys = s[18];
let add = {};
add.d23 = s[2];
add.pdop = s[15];
add.hdop = s[16];
add.vdop = s[17];
/* FIXME -- should really add to the sentence */
if (sys == 1) { this.msg.gp = add; }
else if (sys == 2) { this.msg.gl = add; }
else if (sys == 4) { this.msg.bd = add; }
else print("GSA Unknown system\n");

print(msg);
return;
}
if (s[0] === "$GPGSV") {
print("Have gps sentences", s[1], "/", s[2]);
this.parseSats(s);
this.msg.gp.sent = ""+s[2];
return;
}
if (s[0] === "$BDGSV") {
print("Have baidu sentences", s[1], "/", s[2]);
this.parseSats(s);
this.msg.bd.sent = ""+s[2];
return;
}
if (s[0] === "$GLGSV") {
print("Have glonass sentences", s[1], "/", s[2]);
this.parseSats(s);
this.msg.gl.sent = ""+s[2];
return;
}
if (cmd === "RMC") return; /* Repeat of position/speed/course */
if (cmd === "VTG") return; /* Speeds in knots/kph */
if (cmd === "ZDA") return; /* Time + timezone */
if (cmd === "TXT") {
this.msg.finished = 1;
return; /* Misc text? antena open */
}

print(msg);
},
casic_cmd: function (cmd) {
var cs = 0;
for (var i=1;i<cmd.length;i++)
cs = cs ^ cmd.charCodeAt(i);
Serial1.println(cmd+"*"+cs.toString(16).toUpperCase().padStart(2, '0'));
},
sys: 3,
selectSpace: function () {
this.sys += 1;
if (this.sys == 4)
this.sys = 0;
let val = 7;
if (this.sys)
val = 1 << (this.sys - 1);
this.casic_cmd("$PCAS04,"+val);
ui.drawMsg("Sys "+val);
}
};

function start() {
Bangle.setGPSPower(1);
Bangle.on('GPS-raw', function(a, b) { sky.parseRaw(a, b); });
setTimeout(function() {
Bangle.removeAllListeners('GPS-raw');
}, 1000000);
setInterval(function() { sky.display(); }, 1000);
}

// CASIC_CMD("$PCAS06,0"); /* Query product information */
setTimeout(() => sky.casic_cmd("$PCAS04,7"), 1000); /* Enable gps + beidou + glonass */
setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1000); /* Enable gps + beidou + glonass */

//setTimeout(() => sky.casic_cmd("$PCAS10,2"), 1200); /* 2: cold start, 1 warm start, 0: hot start */

ui.init();
ui.topLeft = () => sky.selectSpace();
Bangle.on("drag", (b) => ui.touchHandler(b));
start();

0 comments on commit bc5fb81

Please sign in to comment.