2021-10-19 01:02:29 +00:00
/ *
Speed and Altitude [ speedalt2 ]
Mike Bennett mike [ at ] kereru . com
2021-10-29 09:19:35 +00:00
1.10 : add inverted colours
2022-02-03 08:45:34 +00:00
1.14 : Add VMG screen
2022-02-04 02:17:25 +00:00
1.34 : Add bluetooth data stream for Droidscript
2021-10-19 01:02:29 +00:00
* /
2022-02-04 20:52:30 +00:00
var v = '1.41' ;
2021-10-19 01:02:29 +00:00
/*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */
var KalmanFilter = ( function ( ) {
'use strict' ;
function _classCallCheck ( instance , Constructor ) {
if ( ! ( instance instanceof Constructor ) ) {
throw new TypeError ( "Cannot call a class as a function" ) ;
}
}
function _defineProperties ( target , props ) {
for ( var i = 0 ; i < props . length ; i ++ ) {
var descriptor = props [ i ] ;
descriptor . enumerable = descriptor . enumerable || false ;
descriptor . configurable = true ;
if ( "value" in descriptor ) descriptor . writable = true ;
Object . defineProperty ( target , descriptor . key , descriptor ) ;
}
}
function _createClass ( Constructor , protoProps , staticProps ) {
if ( protoProps ) _defineProperties ( Constructor . prototype , protoProps ) ;
if ( staticProps ) _defineProperties ( Constructor , staticProps ) ;
return Constructor ;
}
/ * *
* KalmanFilter
* @ class
* @ author Wouter Bulten
* @ see { @ link http : //github.com/wouterbulten/kalmanjs}
* @ version Version : 1.0 . 0 - beta
* @ copyright Copyright 2015 - 2018 Wouter Bulten
* @ license MIT License
* @ preserve
* /
var KalmanFilter =
/*#__PURE__*/
function ( ) {
/ * *
* Create 1 - dimensional kalman filter
* @ param { Number } options . R Process noise
* @ param { Number } options . Q Measurement noise
* @ param { Number } options . A State vector
* @ param { Number } options . B Control vector
* @ param { Number } options . C Measurement vector
* @ return { KalmanFilter }
* /
function KalmanFilter ( ) {
var _ref = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : { } ,
_ref$R = _ref . R ,
R = _ref$R === void 0 ? 1 : _ref$R ,
_ref$Q = _ref . Q ,
Q = _ref$Q === void 0 ? 1 : _ref$Q ,
_ref$A = _ref . A ,
A = _ref$A === void 0 ? 1 : _ref$A ,
_ref$B = _ref . B ,
B = _ref$B === void 0 ? 0 : _ref$B ,
_ref$C = _ref . C ,
C = _ref$C === void 0 ? 1 : _ref$C ;
_classCallCheck ( this , KalmanFilter ) ;
this . R = R ; // noise power desirable
this . Q = Q ; // noise power estimated
this . A = A ;
this . C = C ;
this . B = B ;
this . cov = NaN ;
this . x = NaN ; // estimated signal without noise
}
/ * *
* Filter a new value
* @ param { Number } z Measurement
* @ param { Number } u Control
* @ return { Number }
* /
_createClass ( KalmanFilter , [ {
key : "filter" ,
value : function filter ( z ) {
var u = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : 0 ;
if ( isNaN ( this . x ) ) {
this . x = 1 / this . C * z ;
this . cov = 1 / this . C * this . Q * ( 1 / this . C ) ;
} else {
// Compute prediction
var predX = this . predict ( u ) ;
var predCov = this . uncertainty ( ) ; // Kalman gain
var K = predCov * this . C * ( 1 / ( this . C * predCov * this . C + this . Q ) ) ; // Correction
this . x = predX + K * ( z - this . C * predX ) ;
this . cov = predCov - K * this . C * predCov ;
}
return this . x ;
}
/ * *
* Predict next value
* @ param { Number } [ u ] Control
* @ return { Number }
* /
} , {
key : "predict" ,
value : function predict ( ) {
var u = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : 0 ;
return this . A * this . x + this . B * u ;
}
/ * *
* Return uncertainty of filter
* @ return { Number }
* /
} , {
key : "uncertainty" ,
value : function uncertainty ( ) {
return this . A * this . cov * this . A + this . R ;
}
/ * *
* Return the last filtered measurement
* @ return { Number }
* /
} , {
key : "lastMeasurement" ,
value : function lastMeasurement ( ) {
return this . x ;
}
/ * *
* Set measurement noise Q
* @ param { Number } noise
* /
} , {
key : "setMeasurementNoise" ,
value : function setMeasurementNoise ( noise ) {
this . Q = noise ;
}
/ * *
* Set the process noise R
* @ param { Number } noise
* /
} , {
key : "setProcessNoise" ,
value : function setProcessNoise ( noise ) {
this . R = noise ;
}
} ] ) ;
return KalmanFilter ;
} ( ) ;
return KalmanFilter ;
} ( ) ) ;
var buf = Graphics . createArrayBuffer ( 240 , 160 , 2 , { msb : true } ) ;
2021-10-29 03:14:40 +00:00
let LED = // LED as minimal and only definition (as instance / singleton)
{ isOn : false // status on / off, not needed if you don't need to ask for it
, set : function ( v ) { // turn on w/ no arg or truey, else off
2021-10-29 03:43:54 +00:00
g . setColor ( ( this . isOn = ( v === undefined || ! ! v ) ) ? 1 : 0 , 0 , 0 ) . fillCircle ( 40 , 10 , 10 ) ; }
2021-10-29 03:14:40 +00:00
, reset : function ( ) { this . set ( false ) ; } // turn off
, write : function ( v ) { this . set ( v ) ; } // turn on w/ no arg or truey, else off
, toggle : function ( ) { this . set ( ! this . isOn ) ; } // toggle the LED
} , LED1 = LED ; // LED1 as 'synonym' for LED
2021-10-19 01:02:29 +00:00
var lf = { fix : 0 , satellites : 0 } ;
var showMax = 0 ; // 1 = display the max values. 0 = display the cur fix
var pwrSav = 1 ; // 1 = default power saving with watch screen off and GPS to PMOO mode. 0 = screen kept on.
var canDraw = 1 ;
var tmrLP ; // Timer for delay in switching to low power after screen turns off
2021-10-29 03:14:40 +00:00
var maxSpd = 0 ;
var maxAlt = 0 ;
var maxN = 0 ; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data.
2021-10-19 01:02:29 +00:00
var emulator = ( process . env . BOARD == "EMSCRIPTEN" ) ? 1 : 0 ; // 1 = running in emulator. Supplies test values;
2022-02-04 01:36:40 +00:00
var bt = 0 ; // 0 = bluetooth data feed off. 1 = on
2022-02-04 08:52:29 +00:00
var btLast = 0 ; // time of last bt transmit
2021-10-19 01:02:29 +00:00
var wp = { } ; // Waypoint to use for distance from cur position.
2021-10-29 03:14:40 +00:00
function nxtWp ( ) {
cfg . wp ++ ;
2021-10-19 01:02:29 +00:00
loadWp ( ) ;
}
function loadWp ( ) {
var w = require ( "Storage" ) . readJSON ( 'waypoints.json' ) || [ { name : "NONE" } ] ;
if ( cfg . wp >= w . length ) cfg . wp = 0 ;
if ( cfg . wp < 0 ) cfg . wp = w . length - 1 ;
savSettings ( ) ;
wp = w [ cfg . wp ] ;
}
function radians ( a ) {
return a * Math . PI / 180 ;
}
2022-02-03 08:45:34 +00:00
function degrees ( a ) {
var d = a * 180 / Math . PI ;
return ( d + 360 ) % 360 ;
}
function bearing ( a , b ) {
var delta = radians ( b . lon - a . lon ) ;
var alat = radians ( a . lat ) ;
var blat = radians ( b . lat ) ;
var y = Math . sin ( delta ) * Math . cos ( blat ) ;
var x = Math . cos ( alat ) * Math . sin ( blat ) -
Math . sin ( alat ) * Math . cos ( blat ) * Math . cos ( delta ) ;
return Math . round ( degrees ( Math . atan2 ( y , x ) ) ) ;
}
2021-10-19 01:02:29 +00:00
function distance ( a , b ) {
var x = radians ( a . lon - b . lon ) * Math . cos ( radians ( ( a . lat + b . lat ) / 2 ) ) ;
var y = radians ( b . lat - a . lat ) ;
2022-02-03 08:45:34 +00:00
// Distance in metres
2021-10-19 01:02:29 +00:00
var d = Math . sqrt ( x * x + y * y ) * 6371000 ;
return d ;
}
function drawScrn ( dat ) {
if ( ! canDraw ) return ;
buf . clear ( ) ;
2021-10-29 09:19:35 +00:00
buf . setBgColor ( 0 ) ;
2021-10-19 01:02:29 +00:00
var n ;
n = dat . val . toString ( ) ;
2021-10-19 03:09:29 +00:00
var s = 50 ; // Font size
2021-10-19 01:02:29 +00:00
var l = n . length ;
2021-10-19 03:09:29 +00:00
if ( l <= 7 ) s = 55 ;
if ( l <= 6 ) s = 60 ;
if ( l <= 5 ) s = 80 ;
if ( l <= 4 ) s = 100 ;
if ( l <= 3 ) s = 120 ;
2021-10-19 01:02:29 +00:00
2021-10-19 03:09:29 +00:00
buf . setFontAlign ( 0 , 0 ) ; //Centre
2021-10-19 01:02:29 +00:00
buf . setColor ( 1 ) ;
buf . setFontVector ( s ) ;
2021-10-19 03:09:29 +00:00
buf . drawString ( n , 126 , 52 ) ;
2021-10-19 01:02:29 +00:00
// Primary Units
buf . setFontAlign ( - 1 , 1 ) ; //left, bottom
buf . setColor ( 2 ) ;
buf . setFontVector ( 35 ) ;
buf . drawString ( dat . unit , 5 , 164 ) ;
2021-10-29 03:14:40 +00:00
drawMax ( dat . max ) ; // MAX display indicator
drawWP ( dat . wp ) ; // Waypoint name
drawSats ( dat . sats ) ;
2021-10-19 01:02:29 +00:00
g . reset ( ) ;
g . drawImage ( img , 0 , 40 ) ;
2021-10-19 03:58:58 +00:00
2021-10-29 03:14:40 +00:00
LED1 . write ( ! pwrSav ) ;
2021-10-19 03:09:29 +00:00
2021-10-19 01:02:29 +00:00
}
2021-10-20 01:39:46 +00:00
function drawPosn ( dat ) {
if ( ! canDraw ) return ;
buf . clear ( ) ;
2021-10-29 09:19:35 +00:00
buf . setBgColor ( 0 ) ;
2021-10-20 01:39:46 +00:00
var x , y ;
x = 210 ;
y = 0 ;
buf . setFontAlign ( 1 , - 1 ) ;
buf . setFontVector ( 60 ) ;
buf . setColor ( 1 ) ;
2021-10-20 06:47:15 +00:00
buf . drawString ( dat . lat , x , y ) ;
buf . drawString ( dat . lon , x , y + 70 ) ;
2021-10-20 01:39:46 +00:00
x = 240 ;
buf . setColor ( 2 ) ;
buf . setFontVector ( 40 ) ;
2021-10-20 06:47:15 +00:00
buf . drawString ( dat . ns , x , y ) ;
buf . drawString ( dat . ew , x , y + 70 ) ;
2021-10-20 01:39:46 +00:00
2021-10-29 03:14:40 +00:00
drawSats ( dat . sats ) ;
2021-10-20 06:47:15 +00:00
2021-10-20 01:39:46 +00:00
g . reset ( ) ;
g . drawImage ( img , 0 , 40 ) ;
2021-10-20 06:47:15 +00:00
2021-10-29 03:14:40 +00:00
LED1 . write ( ! pwrSav ) ;
2021-10-20 01:39:46 +00:00
}
2021-10-19 01:02:29 +00:00
function drawClock ( ) {
if ( ! canDraw ) return ;
2021-10-20 05:12:03 +00:00
2021-10-19 01:02:29 +00:00
buf . clear ( ) ;
2021-10-29 09:19:35 +00:00
buf . setBgColor ( 0 ) ;
2021-10-19 01:02:29 +00:00
var x , y ;
2021-10-20 01:39:46 +00:00
x = 185 ;
2021-10-19 01:02:29 +00:00
y = 0 ;
2021-10-20 01:39:46 +00:00
buf . setFontAlign ( 1 , - 1 ) ;
buf . setFontVector ( 94 ) ;
2021-10-19 01:02:29 +00:00
time = require ( "locale" ) . time ( new Date ( ) , 1 ) ;
2021-10-20 01:39:46 +00:00
2021-10-20 05:12:03 +00:00
buf . setColor ( 1 ) ;
2021-10-20 01:39:46 +00:00
buf . drawString ( time . substring ( 0 , 2 ) , x , y ) ;
buf . drawString ( time . substring ( 3 , 5 ) , x , y + 80 ) ;
2021-10-19 01:02:29 +00:00
g . reset ( ) ;
g . drawImage ( img , 0 , 40 ) ;
2021-10-20 05:23:43 +00:00
2021-10-29 03:14:40 +00:00
LED1 . write ( ! pwrSav ) ;
2021-10-19 01:02:29 +00:00
}
2021-10-29 03:14:40 +00:00
function drawWP ( wp ) {
2021-10-29 05:53:58 +00:00
buf . setColor ( 3 ) ;
2021-10-19 01:02:29 +00:00
buf . setFontAlign ( 0 , 1 ) ; //left, bottom
2022-02-03 08:45:34 +00:00
buf . setFontVector ( 40 ) ;
buf . drawString ( wp , 120 , 132 ) ;
2021-10-19 01:02:29 +00:00
}
function drawSats ( sats ) {
buf . setColor ( 3 ) ;
buf . setFont ( "6x8" , 2 ) ;
buf . setFontAlign ( 1 , 1 ) ; //right, bottom
buf . drawString ( sats , 240 , 160 ) ;
}
2021-10-29 03:14:40 +00:00
function drawMax ( max ) {
2021-10-19 01:02:29 +00:00
buf . setFontVector ( 30 ) ;
buf . setColor ( 2 ) ;
buf . setFontAlign ( 0 , 1 ) ; //centre, bottom
2021-10-29 03:14:40 +00:00
buf . drawString ( max , 120 , 164 ) ;
2021-10-19 01:02:29 +00:00
}
function onGPS ( fix ) {
2021-10-29 03:14:40 +00:00
if ( emulator ) {
2021-10-19 01:02:29 +00:00
fix . fix = 1 ;
fix . speed = 10 + ( Math . random ( ) * 5 ) ;
fix . alt = 354 + ( Math . random ( ) * 50 ) ;
fix . lat = - 38.92 ;
fix . lon = 175.7613350 ;
fix . course = 245 ;
fix . satellites = 12 ;
fix . time = new Date ( ) ;
fix . smoothed = 0 ;
}
var m ;
var sp = '---' ;
2022-02-03 08:45:34 +00:00
var al = sp ;
var di = sp ;
var brg = '' ; // bearing
var crs = '' ; // course
var age = sp ;
2021-10-20 06:47:15 +00:00
var lat = '---.--' ;
var ns = '' ;
var ew = '' ;
var lon = '---.--' ;
2022-02-03 08:45:34 +00:00
var sats = sp ;
var vmg = sp ;
2021-10-20 06:47:15 +00:00
2021-10-29 05:51:39 +00:00
// Waypoint name
var wpName = wp . name ;
if ( wpName == undefined || wpName == 'NONE' ) wpName = '' ;
wpName = wpName . substring ( 0 , 8 ) ;
2021-10-19 01:02:29 +00:00
if ( fix . fix ) lf = fix ;
2021-10-29 03:14:40 +00:00
2021-10-19 01:02:29 +00:00
if ( lf . fix ) {
// Smooth data
if ( lf . smoothed !== 1 ) {
if ( cfg . spdFilt ) lf . speed = spdFilter . filter ( lf . speed ) ;
if ( cfg . altFilt ) lf . alt = altFilter . filter ( lf . alt ) ;
lf . smoothed = 1 ;
2021-10-29 03:14:40 +00:00
if ( maxN <= 15 ) maxN ++ ;
2021-10-19 01:02:29 +00:00
}
2022-02-03 08:45:34 +00:00
// Bearing to waypoint
brg = bearing ( lf , wp ) ;
// Current course
crs = lf . course ;
// Relative angle to wp
var a = Math . max ( crs , brg ) - Math . min ( crs , brg ) ;
if ( a >= 180 ) a = 360 - a ;
2021-10-20 06:47:15 +00:00
2021-10-19 01:02:29 +00:00
// Speed
2022-02-03 08:45:34 +00:00
sp = parseFloat ( lf . speed ) / parseFloat ( cfg . spd ) ; // Calculate for selected units
// vmg
if ( a >= 90 ) vmg = sp * Math . cos ( radians ( 180 - a ) ) * - 1 ; // moving away from WP
else vmg = sp * Math . cos ( radians ( a ) ) ; // towards wp
2021-10-31 22:58:16 +00:00
2021-10-19 01:02:29 +00:00
if ( sp < 10 ) sp = sp . toFixed ( 1 ) ;
else sp = Math . round ( sp ) ;
2021-10-29 03:31:23 +00:00
if ( isNaN ( sp ) ) sp = '---' ;
2021-10-29 03:14:40 +00:00
if ( parseFloat ( sp ) > parseFloat ( maxSpd ) && maxN > 15 ) maxSpd = sp ;
2021-10-19 01:02:29 +00:00
2022-02-03 08:45:34 +00:00
if ( Math . abs ( vmg ) >= 0.05 && Math . abs ( vmg ) < 10 ) vmg = vmg . toFixed ( 1 ) ;
else vmg = Math . round ( vmg ) ;
if ( isNaN ( vmg ) ) vmg = '---' ;
2021-10-19 01:02:29 +00:00
// Altitude
al = lf . alt ;
al = Math . round ( parseFloat ( al ) / parseFloat ( cfg . alt ) ) ;
2021-10-29 03:14:40 +00:00
if ( parseFloat ( al ) > parseFloat ( maxAlt ) && maxN > 15 ) maxAlt = al ;
2021-10-29 03:31:23 +00:00
if ( isNaN ( al ) ) al = '---' ;
2021-10-19 01:02:29 +00:00
2021-10-31 22:39:30 +00:00
// Distance to waypoint
2021-10-19 01:02:29 +00:00
di = distance ( lf , wp ) ;
2022-02-03 08:45:34 +00:00
di = ( di / parseFloat ( cfg . dist ) ) . toFixed ( 2 ) ;
if ( di >= 100 ) di = parseFloat ( di ) . toFixed ( 1 ) ;
if ( di >= 1000 ) di = parseFloat ( di ) . toFixed ( 0 ) ;
if ( isNaN ( di ) ) di = '------' ;
2021-10-19 01:02:29 +00:00
// Age of last fix (secs)
age = Math . max ( 0 , Math . round ( getTime ( ) ) - ( lf . time . getTime ( ) / 1000 ) ) ;
2021-10-20 06:47:15 +00:00
// Lat / Lon
ns = 'N' ;
if ( lf . lat < 0 ) ns = 'S' ;
lat = Math . abs ( lf . lat . toFixed ( 2 ) ) ;
ew = 'E' ;
if ( lf . lon < 0 ) ew = 'W' ;
lon = Math . abs ( lf . lon . toFixed ( 2 ) ) ;
2021-10-29 03:14:40 +00:00
// Sats
if ( age > 10 ) {
2021-10-29 03:31:23 +00:00
sats = 'Age:' + Math . round ( age ) ;
2021-10-29 03:14:40 +00:00
if ( age > 90 ) sats = 'Age:>90' ;
}
else sats = 'Sats:' + lf . satellites ;
2021-10-20 06:47:15 +00:00
2021-10-19 01:02:29 +00:00
}
2022-02-04 02:33:45 +00:00
2022-02-04 02:17:25 +00:00
// Bluetooth send data
btSend ( {
2022-02-04 20:52:30 +00:00
v : v ,
m : cfg . modeA ,
2022-02-04 02:17:25 +00:00
spd _unit : cfg . spd _unit ,
alt _unit : cfg . alt _unit ,
dist _unit : cfg . dist _unit ,
wp : wpName ,
sp : sp ,
al : al ,
2022-02-04 04:39:26 +00:00
di : di ,
2022-02-04 02:17:25 +00:00
sats : sats ,
vmg : vmg
} ) ;
2022-02-04 02:33:45 +00:00
2021-10-19 01:02:29 +00:00
if ( cfg . modeA == 0 ) {
// Speed
2022-02-04 02:17:25 +00:00
if ( showMax ) {
2021-10-19 01:02:29 +00:00
drawScrn ( {
2021-10-29 03:14:40 +00:00
val : maxSpd ,
2021-10-19 01:02:29 +00:00
unit : cfg . spd _unit ,
2021-10-29 03:14:40 +00:00
sats : sats ,
2021-10-19 01:02:29 +00:00
age : age ,
2021-10-29 03:14:40 +00:00
max : 'MAX' ,
wp : ''
2021-10-19 01:02:29 +00:00
} ) ; // Speed maximums
2022-02-04 02:17:25 +00:00
}
else {
2021-10-19 01:02:29 +00:00
drawScrn ( {
val : sp ,
unit : cfg . spd _unit ,
2021-10-29 03:14:40 +00:00
sats : sats ,
2021-10-19 01:02:29 +00:00
age : age ,
2021-10-31 20:24:24 +00:00
max : 'SPD' ,
2021-10-29 03:14:40 +00:00
wp : ''
2021-10-19 01:02:29 +00:00
} ) ;
2022-02-04 02:17:25 +00:00
}
2021-10-19 01:02:29 +00:00
}
if ( cfg . modeA == 1 ) {
// Alt
2022-02-04 02:17:25 +00:00
if ( showMax ) {
2021-10-19 01:02:29 +00:00
drawScrn ( {
2021-10-29 03:14:40 +00:00
val : maxAlt ,
2021-10-19 01:02:29 +00:00
unit : cfg . alt _unit ,
2021-10-29 03:14:40 +00:00
sats : sats ,
2021-10-19 01:02:29 +00:00
age : age ,
2021-10-29 03:14:40 +00:00
max : 'MAX' ,
wp : ''
2021-10-19 01:02:29 +00:00
} ) ; // Alt maximums
2022-02-04 02:17:25 +00:00
}
else {
2021-10-19 01:02:29 +00:00
drawScrn ( {
val : al ,
unit : cfg . alt _unit ,
2021-10-29 03:14:40 +00:00
sats : sats ,
2021-10-19 01:02:29 +00:00
age : age ,
2021-10-31 20:24:24 +00:00
max : 'ALT' ,
2021-10-29 03:14:40 +00:00
wp : ''
2021-10-19 01:02:29 +00:00
} ) ;
2022-02-04 02:17:25 +00:00
}
2021-10-19 01:02:29 +00:00
}
if ( cfg . modeA == 2 ) {
// Dist
drawScrn ( {
val : di ,
unit : cfg . dist _unit ,
2021-10-29 03:14:40 +00:00
sats : sats ,
2021-10-19 01:02:29 +00:00
age : age ,
2021-10-31 20:24:24 +00:00
max : 'DST' ,
2021-10-29 03:14:40 +00:00
wp : wpName
2021-10-19 01:02:29 +00:00
} ) ;
}
2021-10-20 01:39:46 +00:00
if ( cfg . modeA == 3 ) {
2022-02-03 08:45:34 +00:00
// VMG
drawScrn ( {
val : vmg ,
unit : cfg . spd _unit ,
sats : sats ,
age : age ,
max : 'VMG' ,
wp : wpName
} ) ;
}
if ( cfg . modeA == 4 ) {
2021-10-20 01:39:46 +00:00
// Position
2021-10-29 03:14:40 +00:00
drawPosn ( {
sats : sats ,
2021-10-20 01:39:46 +00:00
age : age ,
2021-10-20 06:47:15 +00:00
lat : lat ,
lon : lon ,
ns : ns ,
2021-10-29 03:14:40 +00:00
ew : ew
2021-10-20 01:39:46 +00:00
} ) ;
}
2021-10-19 01:02:29 +00:00
2022-02-03 08:45:34 +00:00
if ( cfg . modeA == 5 ) {
2021-10-19 01:02:29 +00:00
// Large clock
drawClock ( ) ;
}
}
2021-10-20 02:11:01 +00:00
function prevScrn ( ) {
cfg . modeA = cfg . modeA - 1 ;
2022-02-03 08:45:34 +00:00
if ( cfg . modeA < 0 ) cfg . modeA = 5 ;
2021-10-20 02:11:01 +00:00
savSettings ( ) ;
onGPS ( lf ) ;
}
function nextScrn ( ) {
cfg . modeA = cfg . modeA + 1 ;
2022-02-03 08:45:34 +00:00
if ( cfg . modeA > 5 ) cfg . modeA = 0 ;
2021-10-20 02:11:01 +00:00
savSettings ( ) ;
onGPS ( lf ) ;
}
2021-10-20 03:50:20 +00:00
// Next function on a screen
2021-10-20 04:01:09 +00:00
function nextFunc ( dur ) {
2021-10-19 01:02:29 +00:00
if ( cfg . modeA == 0 || cfg . modeA == 1 ) {
// Spd+Alt mode - Switch between fix and MAX
if ( dur < 2 ) showMax = ! showMax ; // Short press toggle fix/max display
2021-10-29 03:14:40 +00:00
else { maxSpd = 0 ; maxAlt = 0 ; } // Long press resets max values.
2021-10-19 01:02:29 +00:00
}
2022-02-03 08:45:34 +00:00
else if ( cfg . modeA == 2 || cfg . modeA == 3 ) nxtWp ( ) ; // Dist or VMG mode - Select next waypoint
2021-10-19 01:02:29 +00:00
onGPS ( lf ) ;
2021-10-20 03:50:20 +00:00
}
2021-10-21 21:59:37 +00:00
function updateClock ( ) {
if ( ! canDraw ) return ;
2022-02-03 08:45:34 +00:00
if ( cfg . modeA != 5 ) return ;
2021-10-21 21:59:37 +00:00
drawClock ( ) ;
2021-10-29 03:14:40 +00:00
if ( emulator ) { maxSpd ++ ; maxAlt ++ ; }
2021-10-21 21:59:37 +00:00
}
function startDraw ( ) {
canDraw = true ;
g . clear ( ) ;
Bangle . drawWidgets ( ) ;
setLpMode ( 'SuperE' ) ; // off
onGPS ( lf ) ; // draw app screen
}
function stopDraw ( ) {
canDraw = false ;
if ( ! tmrLP ) tmrLP = setInterval ( function ( ) { if ( lf . fix ) setLpMode ( 'PSMOO' ) ; } , 10000 ) ; //Drop to low power in 10 secs. Keep lp mode off until we have a first fix.
}
function savSettings ( ) {
require ( "Storage" ) . write ( 'speedalt2.json' , cfg ) ;
}
function setLpMode ( m ) {
if ( tmrLP ) { clearInterval ( tmrLP ) ; tmrLP = false ; } // Stop any scheduled drop to low power
if ( ! gpssetup ) return ;
gpssetup . setPowerMode ( { power _mode : m } ) ;
}
2022-02-04 20:50:53 +00:00
// == Droidscript bluetooth data
2022-02-03 19:16:29 +00:00
2022-02-04 01:23:40 +00:00
function btOn ( b ) {
2022-02-04 20:50:53 +00:00
bt = b ; // Turn data transmit on/off
}
function btSetMode ( m ) {
cfg . modeA = m ; // Set a disply mode
2022-02-04 01:23:40 +00:00
}
function btSend ( dat ) {
2022-02-04 08:52:29 +00:00
if ( ! bt ) return ; // bt transmit off
var dur = getTime ( ) - btLast ;
2022-02-04 20:50:53 +00:00
if ( dur < 1.2 ) return ; // Don't need to transmit more than every 1.2 secs.
2022-02-04 08:52:29 +00:00
btLast = getTime ( ) ;
console . log ( JSON . stringify ( dat ) ) ; // transmit the data
2022-02-03 08:45:34 +00:00
}
2022-02-03 19:16:29 +00:00
2022-02-04 09:06:26 +00:00
function btNextWP ( ) {
if ( cfg . modeA == 2 || cfg . modeA == 3 ) {
nxtWp ( ) ; // Dist or VMG mode - Select next waypoint
onGPS ( lf ) ;
}
}
2022-02-03 08:45:34 +00:00
2021-10-21 21:59:37 +00:00
// == Events
2021-10-20 03:50:20 +00:00
function setButtons ( ) {
// BTN1 - Max speed/alt or next waypoint
setWatch ( function ( e ) {
var dur = e . time - e . lastTime ;
nextFunc ( dur ) ;
2021-10-19 01:02:29 +00:00
} , BTN1 , { edge : "falling" , repeat : true } ) ;
// Power saving on/off
setWatch ( function ( e ) {
pwrSav = ! pwrSav ;
if ( pwrSav ) {
var s = require ( 'Storage' ) . readJSON ( 'setting.json' , 1 ) || { } ;
var t = s . timeout || 10 ;
Bangle . setLCDTimeout ( t ) ;
}
else {
Bangle . setLCDTimeout ( 0 ) ;
2021-10-21 19:16:59 +00:00
// Bangle.setLCDPower(1);
2021-10-19 01:02:29 +00:00
}
2021-10-29 03:14:40 +00:00
LED1 . write ( ! pwrSav ) ;
2021-10-19 01:02:29 +00:00
} , BTN2 , { repeat : true , edge : "falling" } ) ;
// BTN3 - next screen
setWatch ( function ( e ) {
2021-10-20 02:11:01 +00:00
nextScrn ( ) ;
2021-10-19 01:02:29 +00:00
} , BTN3 , { repeat : true , edge : "falling" } ) ;
}
2021-10-21 21:59:37 +00:00
Bangle . on ( 'lcdPower' , function ( on ) {
if ( ! SCREENACCESS . withApp ) return ;
if ( on ) startDraw ( ) ;
else stopDraw ( ) ;
} ) ;
2021-10-19 01:02:29 +00:00
2021-10-21 21:59:37 +00:00
Bangle . on ( 'swipe' , function ( dir ) {
2021-10-24 20:25:06 +00:00
if ( ! cfg . touch ) return ;
2021-10-21 22:16:13 +00:00
if ( dir == 1 ) prevScrn ( ) ;
else nextScrn ( ) ;
2021-10-21 21:59:37 +00:00
} ) ;
2021-10-19 01:02:29 +00:00
2021-10-21 21:59:37 +00:00
Bangle . on ( 'touch' , function ( button ) {
2021-10-24 20:25:06 +00:00
if ( ! cfg . touch ) return ;
2021-10-21 22:16:13 +00:00
nextFunc ( 0 ) ; // Same function as short BTN1
2022-02-03 08:45:34 +00:00
} ) ;
2021-10-21 22:16:13 +00:00
2021-10-21 21:59:37 +00:00
// == Main Prog
2021-10-19 01:02:29 +00:00
// Read settings.
2021-10-19 02:14:44 +00:00
let cfg = require ( 'Storage' ) . readJSON ( 'speedalt2.json' , 1 ) || { } ;
2021-10-19 01:02:29 +00:00
2022-02-03 08:45:34 +00:00
cfg . spd = cfg . spd || 1 ; // Multiplier for speed unit conversions. 0 = use the locale values for speed
cfg . spd _unit = cfg . spd _unit || 'kph' ; // Displayed speed unit
2021-10-19 01:02:29 +00:00
cfg . alt = cfg . alt || 0.3048 ; // Multiplier for altitude unit conversions.
cfg . alt _unit = cfg . alt _unit || 'feet' ; // Displayed altitude units
cfg . dist = cfg . dist || 1000 ; // Multiplier for distnce unit conversions.
cfg . dist _unit = cfg . dist _unit || 'km' ; // Displayed altitude units
cfg . colour = cfg . colour || 0 ; // Colour scheme.
cfg . wp = cfg . wp || 0 ; // Last selected waypoint for dist
2022-02-03 08:45:34 +00:00
cfg . modeA = cfg . modeA || 0 ; // 0=Speed 1=Alt 2=Dist 3 = vmg 4=Position 5=Clock
2021-10-19 01:02:29 +00:00
cfg . primSpd = cfg . primSpd || 0 ; // 1 = Spd in primary, 0 = Spd in secondary
cfg . spdFilt = cfg . spdFilt == undefined ? true : cfg . spdFilt ;
cfg . altFilt = cfg . altFilt == undefined ? true : cfg . altFilt ;
2021-10-24 20:25:06 +00:00
cfg . touch = cfg . touch == undefined ? true : cfg . touch ;
2021-10-19 01:02:29 +00:00
if ( cfg . spdFilt ) var spdFilter = new KalmanFilter ( { R : 0.1 , Q : 1 } ) ;
if ( cfg . altFilt ) var altFilter = new KalmanFilter ( { R : 0.01 , Q : 2 } ) ;
loadWp ( ) ;
/ *
Colour Pallet Idx
0 : Background ( black )
1 : Speed / Alt
2 : Units
3 : Sats
* /
var img = {
width : buf . getWidth ( ) ,
height : buf . getHeight ( ) ,
bpp : 2 ,
buffer : buf . buffer ,
palette : new Uint16Array ( [ 0 , 0x4FE0 , 0xEFE0 , 0x07DB ] )
} ;
if ( cfg . colour == 1 ) img . palette = new Uint16Array ( [ 0 , 0xFFFF , 0xFFF6 , 0xDFFF ] ) ;
2021-10-29 08:55:45 +00:00
if ( cfg . colour == 2 ) img . palette = new Uint16Array ( [ 0 , 0xF800 , 0xFAE0 , 0xF813 ] ) ;
2021-10-29 09:19:35 +00:00
if ( cfg . colour == 3 ) img . palette = new Uint16Array ( [ 0xFFFF , 0x007F , 0x0054 , 0x0054 ] ) ;
2021-10-19 01:02:29 +00:00
var SCREENACCESS = {
withApp : true ,
request : function ( ) { this . withApp = false ; stopDraw ( ) ; } ,
release : function ( ) { this . withApp = true ; startDraw ( ) ; }
} ;
var gpssetup ;
try {
gpssetup = require ( "gpssetup" ) ;
} catch ( e ) {
gpssetup = false ;
}
// All set up. Lets go.
g . clear ( ) ;
Bangle . loadWidgets ( ) ;
Bangle . drawWidgets ( ) ;
onGPS ( lf ) ;
Bangle . setGPSPower ( 1 ) ;
if ( gpssetup ) {
gpssetup . setPowerMode ( { power _mode : "SuperE" } ) . then ( function ( ) { Bangle . setGPSPower ( 1 ) ; } ) ;
}
else {
Bangle . setGPSPower ( 1 ) ;
}
Bangle . on ( 'GPS' , onGPS ) ;
setButtons ( ) ;
setInterval ( updateClock , 10000 ) ;