From b7940598845d38e856308221bbcecca5fd33d12f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 11 Feb 2021 11:24:44 +0000 Subject: [PATCH] 0.02: Created gppsetup module --- apps.json | 3 +- apps/gpssetup/ChangeLog | 1 + apps/gpssetup/README.md | 42 +++++++-- apps/gpssetup/app.js | 190 ++++---------------------------------- apps/gpssetup/gpssetup.js | 179 +++++++++++++++++++++++++++++++++++ 5 files changed, 235 insertions(+), 180 deletions(-) create mode 100644 apps/gpssetup/gpssetup.js diff --git a/apps.json b/apps.json index 5d095ef39..89428e841 100644 --- a/apps.json +++ b/apps.json @@ -2771,11 +2771,12 @@ "name": "GPS Setup", "shortName":"GPS Setup", "icon": "gpssetup.png", - "version":"0.01", + "version":"0.02", "description": "Configure the GPS power options and store them in the GPS nvram", "tags": "gps, tools, outdoors", "readme": "README.md", "storage": [ + {"name":"gpssetup","url":"gpssetup.js"}, {"name":"gpssetup.settings.js","url":"settings.js"}, {"name":"gpssetup.settings.json","url":"settings.json"}, {"name":"gpssetup.app.js","url":"app.js"}, diff --git a/apps/gpssetup/ChangeLog b/apps/gpssetup/ChangeLog index 0099beb29..e57d53d8e 100644 --- a/apps/gpssetup/ChangeLog +++ b/apps/gpssetup/ChangeLog @@ -1 +1,2 @@ 0.01: First version of GPS Setup app +0.02: Created gppsetup module diff --git a/apps/gpssetup/README.md b/apps/gpssetup/README.md index a8f0ce5b7..4d3922f50 100644 --- a/apps/gpssetup/README.md +++ b/apps/gpssetup/README.md @@ -1,6 +1,6 @@ # GPS Setup -An App to enable the GPS to be configured into low power mode. +An App and module to enable the GPS to be configured into low power mode. ## Goals @@ -15,14 +15,14 @@ Example power consumption of the GPS while powered on: * Using the GPS with Super-E Power Saving Mode (PSM) with the screen off most of the time, will consume around 35mA and you might get 10hrs before a recharge. - + * Using the GPS in Power Saving Mode On/Off (PSMOO) with suitable settings can reduce the average consumption to around 15mA. A simple test using a 120s update period, 6s search period was still running with 45% battery 20 hours after it started. -## Settings +## Settings App The Settings App enables you set the options below. Either start the App from the launcher or go to Settings, select App/Widgets and then @@ -38,11 +38,11 @@ used. These settings will remain for all apps that use the GPS. - Power Mode: - - SuperE - the factory default setup for the GPS. The recommended + - **SuperE** - the factory default setup for the GPS. The recommended power saving mode. If you need frequent (every second) updates on position, then this is the mode for you. - - PSMOO - On/Off power saving mode. Configured by interval and + - **PSMOO** - On/Off power saving mode. Configured by interval and search time. Choose this mode if you are happy to get a GPS position update less often (say every 1 or 2 minutes). The longer the interval the more time the GPS will spend sleeping in low @@ -55,6 +55,37 @@ used. These settings will remain for all apps that use the GPS. - search - the time between two acquisition attempts if the receiver is unable to get a position fix. +## Module + +A module is provided that'll allow you to set GPS configuration from your own +app. To use it: + +``` +// This will set up the GPS to current saved defaults. It's not normally +// needed unless the watch's battery has run down +require("gpssetup").setPowerMode(); + +// This sets up the PSMOO mode. update/search are optional in seconds +require("gpssetup").setPowerMode({ + power_mode:"PSMOO", + update:optional (default 120), + search:optional (default 5)}) + +// This sets up SuperE +require("gpssetup").setPowerMode({power_mode:"SuperE"}) +``` + +`setPowerMode` returns a promise, which is completed when the GPS is set up. + +So you can for instance do the following to turn the GPS off once it +has been configured: + +``` +require("gpssetup").setPowerMode().then(function() { + Bangle.setGPSPower(0); +}); +``` + ## References * [UBLOX M8 Receiver Data Sheet](https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_%28UBX-13003221%29.pdf) @@ -63,4 +94,3 @@ used. These settings will remain for all apps that use the GPS. * Some useful code on Github can be found [here](https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control) and [here](https://github.com/thasti/utrak/blob/master/gps.c) - diff --git a/apps/gpssetup/app.js b/apps/gpssetup/app.js index 6b69271a1..e0d188af5 100644 --- a/apps/gpssetup/app.js +++ b/apps/gpssetup/app.js @@ -5,16 +5,21 @@ * UBLOX power modes: * SuperE - will provide updates every second and consume 35mA, 75mA with LCD on * PSMOO - will sleep for update time and consume around 7mA during that period - * after acquiring satelite fixes the GPS will settle into a cycle of + * after acquiring satelite fixes the GPS will settle into a cycle of * obtaining fix, sleeping for update seconds, wake up, get fix and sleep. * * See README file for more details - * + * */ Bangle.loadWidgets(); Bangle.drawWidgets(); +function log_debug(o) { + //let timestamp = new Date().getTime(); + //console.log(timestamp + " : " + o); +} + const SETTINGS_FILE = "gpssetup.settings.json"; let settings = undefined; let settings_changed = false; @@ -35,174 +40,15 @@ function loadSettings() { /*********** GPS Power and Setup Functions ******************/ -function log_debug(o) { - //let timestamp = new Date().getTime(); - //console.log(timestamp + " : " + o); -} - function setupGPS() { Bangle.setGPSPower(1); - if (settings.power_mode === "PSMOO") { - setupPSMOO(); - } else { - setupSuperE(); - } + setTimeout(function() { + require("gpssetup").setPowerMode().then(function() { + Bangle.setGPSPower(0); + }); + }, 100); } -function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -function setupSuperE() { - log_debug("setupGPS() Super-E"); - Promise.resolve().then(function() { - UBX_CFG_RESET(); - return delay(100); - }).then(function() { - UBX_CFG_PMS(); - return delay(20); - }).then(function() { - UBX_CFG_SAVE(); - return delay(20); - }).then(function() { - log_debug("Powering GPS Off"); - /* - * must be part of the promise chain to ensure that - * setup does not return and powerOff before config functions - * have run - * - */ - Bangle.setGPSPower(0); - return delay(20); - }); -} - -function setupPSMOO() { - log_debug("setupGPS() PSMOO"); - Promise.resolve().then(function() { - UBX_CFG_RESET(); - return delay(100); - }).then(function() { - UBX_CFG_PM2(settings.update, settings.search); - return delay(20); - }).then(function() { - UBX_CFG_RXM(); - return delay(20); - }).then(function() { - UBX_CFG_SAVE(); - return delay(20); - }).then(function() { - log_debug("Powering GPS Off"); - /* - * must be part of the promise chain to ensure that - * setup does not return and powerOff before config functions - * have run - * - */ - Bangle.setGPSPower(0); - return delay(20); - }); -} - -function writeGPScmd(cmd) { - var d = [0xB5,0x62]; // sync chars - d = d.concat(cmd); - var a=0,b=0; - for (var i=2;i>8; - } while (i); - - return bytes; -} - -/* - * Extended Power Management - * update and search are in milli seconds - * settings are loaded little endian, lsb first - * - * https://github.com/thasti/utrak/blob/master/gps.c - */ -function UBX_CFG_PM2(update,search) { - log_debug("UBX_CFG_PM2()"); - - var u = int_2_bytes(update*1000); - var s = int_2_bytes(search*1000); - - writeGPScmd([0x06, 0x3B, /* class id */ - 44, 0, /* length */ - 0x01, 0x00, 0x00, 0x00, /* v1, reserved 1..3 */ - 0x00, 0x10, 0x00, 0x00, /* on/off-mode, update ephemeris */ - u[3], u[2], u[1], u[0], /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */ - s[3], s[2], s[1], s[0], /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */ - 0x00, 0x00, 0x00, 0x00, /* grid offset */ - 0x00, 0x00, /* on-time after first fix */ - 0x01, 0x00, /* minimum acquisition time */ - 0x00, 0x00, 0x00, 0x00, /* reserved 4,5 */ - 0x00, 0x00, 0x00, 0x00, /* reserved 6 */ - 0x00, 0x00, 0x00, 0x00, /* reserved 7 */ - 0x00, 0x00, 0x00, 0x00, /* reserved 8,9,10 */ - 0x00, 0x00, 0x00, 0x00]); /* reserved 11 */ -} - -// enable power saving mode, after configured with PM2 -function UBX_CFG_RXM() { - log_debug("UBX_CFG_RXM()"); - writeGPScmd([0x06, 0x11, /* UBX-CFG-RXM */ - 2, 0, /* length */ - 0x08, 0x01]); /* reserved, enable power save mode */ -} - - -/* - * Save configuration otherwise it will reset when the GPS wakes up - * - */ -function UBX_CFG_SAVE() { - log_debug("UBX_CFG_SAVE()"); - writeGPScmd([0x06, 0x09, // class id - 0x0D, 0x00, // length - 0x00, 0x00, 0x00, 0x00, // clear mask - 0xFF, 0xFF, 0x00, 0x00, // save mask - 0x00, 0x00, 0x00, 0x00, // load mask - 0x07]); // b2=eeprom b1=flash b0=bat backed ram -} - -/* - * Reset to factory settings using clear mask in UBX_CFG_CFG - * https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control - */ -function UBX_CFG_RESET() { - log_debug("UBX_CFG_RESET()"); - writeGPScmd([0x06, 0x09, // class id - 0x0D, 0x00, - 0xFF, 0xFB, 0x00, 0x00, // clear mask - 0x00, 0x00, 0x00, 0x00, // save mask - 0xFF, 0xFF, 0x00, 0x00, // load mask - 0x17]); -} - - /*********** GPS Setup Menu App *****************************/ function showMainMenu() { @@ -217,18 +63,17 @@ function showMainMenu() { format: v => power_options[v], onchange: v => { settings.power_mode = power_options[v]; - updateSettings(); + updateSettings(); }, }, - 'Update (s)': { value: settings.update, min: 10, max: 1800, step: 10, onchange: v => { - settings.update =v; - updateSettings(); + settings.update = v; + updateSettings(); } }, 'Search (s)': { @@ -237,8 +82,8 @@ function showMainMenu() { max: 65, step: 1, onchange: v => { - settings.search = v; - updateSettings(); + settings.search = v; + updateSettings(); } } }; @@ -262,4 +107,3 @@ function exitSetup() { loadSettings(); showMainMenu(); - diff --git a/apps/gpssetup/gpssetup.js b/apps/gpssetup/gpssetup.js new file mode 100644 index 000000000..f8fed68ff --- /dev/null +++ b/apps/gpssetup/gpssetup.js @@ -0,0 +1,179 @@ +const SETTINGS_FILE = "gpssetup.settings.json"; + +function log_debug(o) { + //let timestamp = new Date().getTime(); + //console.log(timestamp + " : " + o); +} + +function writeGPScmd(cmd) { + var d = [0xB5,0x62]; // sync chars + d = d.concat(cmd); + var a=0,b=0; + for (var i=2;i>8; + } while (i); + return bytes; + } + + var u = int_2_bytes(update*1000); + var s = int_2_bytes(search*1000); + + writeGPScmd([0x06, 0x3B, /* class id */ + 44, 0, /* length */ + 0x01, 0x00, 0x00, 0x00, /* v1, reserved 1..3 */ + 0x00, 0x10, 0x00, 0x00, /* on/off-mode, update ephemeris */ + u[3], u[2], u[1], u[0], /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */ + s[3], s[2], s[1], s[0], /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */ + 0x00, 0x00, 0x00, 0x00, /* grid offset */ + 0x00, 0x00, /* on-time after first fix */ + 0x01, 0x00, /* minimum acquisition time */ + 0x00, 0x00, 0x00, 0x00, /* reserved 4,5 */ + 0x00, 0x00, 0x00, 0x00, /* reserved 6 */ + 0x00, 0x00, 0x00, 0x00, /* reserved 7 */ + 0x00, 0x00, 0x00, 0x00, /* reserved 8,9,10 */ + 0x00, 0x00, 0x00, 0x00]); /* reserved 11 */ +} + +// enable power saving mode, after configured with PM2 +function UBX_CFG_RXM() { + log_debug("UBX_CFG_RXM()"); + writeGPScmd([0x06, 0x11, /* UBX-CFG-RXM */ + 2, 0, /* length */ + 0x08, 0x01]); /* reserved, enable power save mode */ +} + +/* + * Save configuration otherwise it will reset when the GPS wakes up + */ +function UBX_CFG_SAVE() { + log_debug("UBX_CFG_SAVE()"); + writeGPScmd([0x06, 0x09, // class id + 0x0D, 0x00, // length + 0x00, 0x00, 0x00, 0x00, // clear mask + 0xFF, 0xFF, 0x00, 0x00, // save mask + 0x00, 0x00, 0x00, 0x00, // load mask + 0x07]); // b2=eeprom b1=flash b0=bat backed ram +} + +/* + * Reset to factory settings using clear mask in UBX_CFG_CFG + * https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control + */ +function UBX_CFG_RESET() { + log_debug("UBX_CFG_RESET()"); + writeGPScmd([0x06, 0x09, // class id + 0x0D, 0x00, + 0xFF, 0xFB, 0x00, 0x00, // clear mask + 0x00, 0x00, 0x00, 0x00, // save mask + 0xFF, 0xFF, 0x00, 0x00, // load mask + 0x17]); +} + +function delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +function setupSuperE() { + log_debug("setupGPS() Super-E"); + return Promise.resolve().then(function() { + UBX_CFG_RESET(); + return delay(100); + }).then(function() { + UBX_CFG_PMS(); + return delay(20); + }).then(function() { + UBX_CFG_SAVE(); + return delay(20); + }).then(function() { + log_debug("Powering GPS Off"); + /* + * must be part of the promise chain to ensure that + * setup does not return and powerOff before config functions + * have run + */ + return delay(20); + }); +} + +function setupPSMOO(settings) { + log_debug("setupGPS() PSMOO"); + return Promise.resolve().then(function() { + UBX_CFG_RESET(); + return delay(100); + }).then(function() { + UBX_CFG_PM2(settings.update, settings.search); + return delay(20); + }).then(function() { + UBX_CFG_RXM(); + return delay(20); + }).then(function() { + UBX_CFG_SAVE(); + return delay(20); + }).then(function() { + log_debug("Powering GPS Off"); + /* + * must be part of the promise chain to ensure that + * setup does not return and powerOff before config functions + * have run + */ + return delay(20); + }); +} + +/** Set GPS power mode (assumes GPS on), returns a promise. +Either: + +require("gpssetup").setPowerMode() // <-- set up GPS to current saved defaults +require("gpssetup").setPowerMode({power_mode:"PSMOO", update:optional, search:optional}) // <-- PSMOO mode +require("gpssetup").setPowerMode({power_mode:"SuperE"}) // <-- Super E mode + +See the README for more information + */ +exports.setPowerMode = function(options) { + settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; + if (options) { + if (options.update) settings.update = options.update; + if (options.search) settings.search = options.search; + if (options.power_mode) settings.power_mode = options.power_mode; + } + settings.update = settings.update||120; + settings.search = settings.search||5; + settings.power_mode = settings.power_mode||"SuperE"; + if (options) require("Storage").write(SETTINGS_FILE, settings); + if (settings.power_mode === "PSMOO") { + return setupPSMOO(settings); + } else { + return setupSuperE(); + } +};