diff --git a/apps/gpsmagdir/README.md b/apps/gpsmagdir/README.md new file mode 100644 index 000000000..b4c3acf0c --- /dev/null +++ b/apps/gpsmagdir/README.md @@ -0,0 +1,12 @@ +TODO: +- Add Widget +- Add Settings +- Test on BangleJS +- Document settings with defaults +- Document Widget +- Write a summary why +- Drop a note about compass north vs true north +- Note that top of Bangle must point at moving direction when compass +- Document uncompensated compass only when clock is faced up +- Note to regularly calibrate compass before use +- Note compass value not when NaN after calibration diff --git a/apps/gpsmagdir/app.png b/apps/gpsmagdir/app.png new file mode 100644 index 000000000..c7e990268 Binary files /dev/null and b/apps/gpsmagdir/app.png differ diff --git a/apps/gpsmagdir/boot.js b/apps/gpsmagdir/boot.js new file mode 100644 index 000000000..94daf88ca --- /dev/null +++ b/apps/gpsmagdir/boot.js @@ -0,0 +1,81 @@ +{ + const settings = Object.assign({ + speed: 6, // when lower then this use direction from compass + compassSrc: 1, // [off, firmware, magnav] + resetCompassOnPwr: true, // reset compass on power on + tiltCompensation: true, // tilt compensation on default compass + }, require("Storage").readJSON("gpsmagdir.json", true) || {}); + const CALIBDATA = (settings.compassSrc === 2) ? require("Storage").readJSON("magnav.json",1) || {} : undefined; + + // execute Bangle.resetCompass() after Bangle.setCompassPower(); + if (settings.resetCompassOnPwr) { + const origSetCompassPower = Bangle.setCompassPower; + Bangle.setCompassPower = function(on, id) { + const isOn = origSetCompassPower(on, id); + if (on) { + Bangle.resetCompass(); + } + return isOn; + }; + } // if (settings.resetCompassOnPwr) + + if (settings.tiltCompensation) { + const origGetCompass = Bangle.getCompass; + Bangle.getCompass = function(argObj) { + const mag = origGetCompass(); + if (!isNaN(mag.heading) && (argObj === undefined || !argObj.noTiltComp)) { + const d = require("magnav").tiltfix(mag, Bangle.getAccel()); + mag.headingOrig = mag.heading; + mag.heading = d; + } + return mag; + }; + + Bangle.on('mag', function(mag) { + if (!isNaN(mag.heading)) { + const d = require("magnav").tiltfix(mag, Bangle.getAccel()); + mag.headingOrig = mag.heading; + mag.heading = d; + } + }); + } // if (settings.tiltCompensation) + + if (settings.compassSrc > 0) { + const isFaceUp = (acc) => { + return (acc.z<-6700/8192) && (acc.z>-9000/8192) && Math.abs(acc.x)<2048/8192 && Math.abs(acc.y)<2048/8192; + }; + + const changeGpsCourse = (gps) => { + if (gps.speed < settings.speed) { + if (settings.compassSrc === 1 && (settings.tiltCompensation || isFaceUp(Bangle.getAccel()))) { // Use uncompensated firmware heading only if face is up + const heading = Bangle.getCompass().heading; + if (!isNaN(heading)) { + gps.courseOrig = gps.course; + gps.course = Bangle.getCompass().heading; + } + } else if (settings.compassSrc === 2) { // magnav tilt correction with magnav calibration + gps.courseOrig = gps.course; + gps.course = require("magnav").tiltfixread(CALIBDATA.offset,CALIBDATA.scale); + } + } + return gps; + }; + + // Modify GPS event + Bangle.on('GPS', gps => { + changeGpsCourse(gps); + }); + const origGetGPSFix = Bangle.getGPSFix; + Bangle.getGPSFix = function() { + return changeGpsCourse(origGetGPSFix()); + }; + + // Enable Compass with GPS + const origSetGPSPower = Bangle.setGPSPower; + Bangle.setGPSPower = function(on, id) { + const isGPSon = origSetGPSPower(on, id); + Bangle.setCompassPower(isGPSon, "gpsmagdir"); + return isGPSon; + }; + } // if (settings.compassSrc > 0) +} diff --git a/apps/gpsmagdir/metadata.json b/apps/gpsmagdir/metadata.json new file mode 100644 index 000000000..ebff8f7c9 --- /dev/null +++ b/apps/gpsmagdir/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "gpsmagdir", + "name": "GPS Compass heading switcher", + "shortName":"GPS/Compass direction", + "icon": "app.png", + "version":"0.01", + "description": "Replace GPS heading with compass heading when speed is slow or standing still to avoid the heading from jumping around randomly.", + "type": "bootloader", + "tags": "outdoors", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"gpsmagdir.boot.js","url":"boot.js"} + ], + "data": [{"name":"gpsmagdir.json"}] +} +