diff --git a/apps/speedalt/app.js b/apps/speedalt/app.js index eb1f5cd49..3b5a5440e 100644 --- a/apps/speedalt/app.js +++ b/apps/speedalt/app.js @@ -1,24 +1,17 @@ /* Speed and Altitude [speedalt] -Ver : 0.1 +Ver : 0.01 +Mike Bennett mike[at]kereru.com */ -var buf = Graphics.createArrayBuffer(240,120,2,{msb:true}); +const dbg = 1; + +var buf = Graphics.createArrayBuffer(240,160,2,{msb:true}); + +// Load fonts +require("Font7x11Numeric7Seg").add(Graphics); + /* -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]) -}; - var mainmenu = { "" : { "title" : "-- Units --" }, "default" : function() { setUnits(0,''); }, @@ -30,119 +23,173 @@ var mainmenu = { "Feet (alt)" : function() { setUnitsAlt(0.3048,'feet'); }, "Exit" : function() { exitMenu(); }, // remove the menu and restore }; +*/ var lastFix = {fix:0,satellites:0}; -var mode = 's'; // s = Primary display speed. a = Altitude -var multi = 0; // Multiplier for speed unit conversions. 0 = use the locale values for speed -var multi_alt = 1; // Multiplier for altitude unit conversions. -var units = ''; // Displayed speed unit -var units_alt = 'm'; // Displayed altitude units -var btnToggle=false; // ID of the toggle display button -var btnMenu=false; // ID of the menu button -var inMenu = 0; -var emulator = 1; // 1 = running in emulator. Supplies test value; +var showSpeed = 1; // 1 = Speed in primary display. 0 = alt in primary +var showMax = 0; // 1 = display the max values. 0 = display the cur fix +//var inMenu = 0; +var maxPress = 0; // Time max button pressed. Used to calculate short or long press. -/* +var timeBright = 0; // Time of last activity that keeps the display bright +var isDim = 0; // Current brightness state +var gpsPwr = 1; -const storage = require('Storage'); -let settings; +var time = ''; // Last time string displayed. Re displayed in background colour to remove before drawing new time. -function updateSettings() { - storage.write('speedalt.json', settings); -} +var max = {}; +max.spd = 0; +max.alt = 0; -function resetSettings() { - settings = { - day : 17, - month : 6, - year: 1981 - }; - updateSettings(); -} - -*/ +var emulator = 0; +if (process.env.BOARD=="EMSCRIPTEN") emulator = 1; // 1 = running in emulator. Supplies test values; function drawFix(speed,units,sats,alt,alt_units) { - var str = ''; + var val = ''; + var u=''; - // Size fonts to always maximise the display fit - var s; - // Primary Display - str = speed.toString(); - if ( mode == 'a' ) str = alt.toString(); + val = speed.toString(); + if ( !showSpeed ) val = alt.toString(); - s=40; // Font size - if ( str.length <= 7 ) s=48; - if ( str.length <= 6 ) s=55; - if ( str.length <= 5 ) s=68; - if ( str.length <= 4 ) s=85; - if ( str.length <= 3 ) s=110; - - buf.setFontAlign(0,-1); //Centre - buf.setColor(1); - - buf.setFontVector(s); - buf.drawString(str,110,0); - - // Primary Units - str = units; - if ( mode == 'a' ) str = alt_units; - buf.setFontAlign(1,-1,3); //right - buf.setColor(2); - buf.setFontVector(25); - buf.drawString(str,210,0); + // Primary Units + u = settings.spd_unit; + if ( !showSpeed ) u = alt_units; + drawPrimary(val,u); + // Secondary Display - str = alt.toString(); - if ( mode == 'a' ) str = speed.toString(); + val = alt.toString(); + if ( !showSpeed ) val = speed.toString(); - s=115; // minor units X position - if ( str.length <= 7 ) s=120; - if ( str.length <= 6 ) s=105; - if ( str.length <= 5 ) s=87; - if ( str.length <= 4 ) s=70; - if ( str.length <= 3 ) s=55; - if ( str.length <= 2 ) s=40; - if ( str.length <= 1 ) s=25; - - buf.setFontAlign(-1,1); //left, bottom - buf.setColor(1); - buf.setFontVector(25); - buf.drawString(str,5,120); - // Secondary Units - str = alt_units; - if ( mode == 'a' ) str = units; - buf.setFontAlign(-1,1); //left, bottom - buf.setColor(2); - buf.setFontVector(20); - buf.drawString(str,s,120); + u = alt_units; + if ( !showSpeed ) u = settings.spd_unit; + drawSecondary(val,u); + + // Time + drawTime(); //Sats - buf.setFontAlign(1,1); //right, bottom - buf.setColor(3); - buf.setFontVector(18); - buf.drawString(" Sats:"+sats,240,120); + drawSats(sats); } function drawNoFix(sats) { - + var u; + buf.setFontAlign(0,0); buf.setColor(3); - - buf.setFontVector(18); - buf.drawString(" Sats:"+sats,120,10); buf.setFontVector(25); buf.drawString("Waiting for GPS",120,56); + + // Time + drawTime(); + + //Sats + drawSats(sats); + } +function drawPrimary(n,u) { + + // Primary Display + + var s=40; // Font size + if ( n.length <= 7 ) s=48; + if ( n.length <= 6 ) s=55; + if ( n.length <= 5 ) s=68; + if ( n.length <= 4 ) s=85; + if ( n.length <= 3 ) s=110; + + buf.setFontAlign(0,-1); //Centre + buf.setColor(1); + + buf.setFontVector(s); + buf.drawString(n,110,0); + + // Primary Units + buf.setFontAlign(1,-1,3); //right + buf.setColor(2); + buf.setFontVector(25); + buf.drawString(u,210,0); +} + +function drawSecondary(n,u) { + + var s=180; // units X position + if ( n.length <= 5 ) s=155; + if ( n.length <= 4 ) s=125; + if ( n.length <= 3 ) s=100; + if ( n.length <= 2 ) s=65; + if ( n.length <= 1 ) s=35; + + buf.setFontAlign(-1,1); //left, bottom + buf.setColor(1); + buf.setFontVector(45); + buf.drawString(n,5,140); + + // Secondary Units + buf.setFontAlign(-1,1); //left, bottom + buf.setColor(2); + buf.setFontVector(25); + buf.drawString(u,s,135); +} + + +function drawTime() { + var x = 0; + var y = 160; + + if ( gpsPwr ) { + buf.setFont("7x11Numeric7Seg", 1); + buf.setFontAlign(-1,1); //left, bottom + } + else { +// buf.setFont("7x11Numeric7Seg", 6); + buf.setFontAlign(1,-1); //right, top + buf.setColor(2); + buf.setFont("6x8", 1); + buf.drawString('GPS On >',240,0); + + buf.setFontVector(80); + buf.setFontAlign(0,0); //centre + x = 120; + y = 80; + } + + buf.setColor(0); + buf.drawString(time,x,y); + time = require("locale").time(new Date(),1); + buf.setColor(3); + buf.drawString(time,x,y); +} + +function drawSats(sats) { + buf.setFontAlign(1,1); //right, bottom + buf.setColor(3); + buf.setFont("6x8", 1); + if ( showMax ) { + buf.setColor(2); + buf.drawString("MAX",240,160); + } + else buf.drawString("Sats:"+sats,240,160); +} + +function drawClockLarge() { + buf.clear(); + drawTime(); + g.reset(); + g.drawImage(img,0,40); + g.flip(); +} + + function onGPS(fix) { lastFix = fix; @@ -151,48 +198,56 @@ function onGPS(fix) { var m; if (fix.fix || emulator) { + //==== Speed ==== - // Default to locale speed units - if ( multi == 0 ) { + if ( settings.spd == 0 ) { var strSpeed = require("locale").speed(fix.speed); m = strSpeed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units if ( emulator ) { speed = '125'; //testing only - units = 'kph'; + settings.spd_unit = 'kph'; } else { speed = m[1]; - units = m[2]; + settings.spd_unit = m[2]; } } // Calculate for selected units else { speed = fix.speed; if ( emulator ) speed = '100'; - speed = Math.round(parseFloat(speed)/parseFloat(multi),0); + speed = Math.round(parseFloat(speed)/parseFloat(settings.spd),0); } // ==== Altitude ==== alt = fix.alt; if ( emulator ) alt = '360'; - alt = Math.round(parseFloat(alt)/parseFloat(multi_alt),0); + alt = Math.round(parseFloat(alt)/parseFloat(settings.alt),0); - drawFix(speed,units,fix.satellites,alt,units_alt); + // Record max values + if (parseFloat(speed) > parseFloat(max.spd) ) max.spd = parseFloat(speed); + if (parseFloat(alt) > parseFloat(max.alt) ) max.alt = parseFloat(alt); + + if ( showMax ) drawFix(max.spd,settings.spd_unit,fix.satellites,max.alt,settings.alt_unit); + else drawFix(speed,settings.spd_unit,fix.satellites,alt,settings.alt_unit); } else { drawNoFix(fix.satellites); } g.reset(); - g.drawImage(img,0,70); + g.drawImage(img,0,40); g.flip(); } -function setUnits(m,u) { - multi = m; - units = u; +/* +function setUnits(m,u) { + settings.spd = m; + settings.spd_unit = u; + require('Storage').writeJSON('speedalt.json',settings); + inMenu = 0; E.showMenu(); // remove the menu @@ -200,8 +255,9 @@ function setUnits(m,u) { } function setUnitsAlt(m,u) { - multi_alt = m; - units_alt = u; + settings.alt = m; + settings.alt_unit = u; + require('Storage').write('speedalt.json',settings); inMenu = 0; @@ -222,34 +278,175 @@ function exitMenu() { } +*/ + function toggleDisplay() { - if ( inMenu ) return; - if ( mode == 's' ) mode = 'a'; - else mode = 's'; + + if ( isDim ) { + onBright(); + return; + } + + if ( ! gpsPwr ) return; + + showSpeed = !showSpeed; onGPS(lastFix); // Back to Speed display } +function toggleMax() { +// if ( inMenu ) return; + showMax = !showMax; + onGPS(lastFix); // Back to Speed display +} + +function gpsPower() { + + if ( isDim ) { + onBright(); + return; + } + + gpsPwr = !gpsPwr; + if ( dbg ) print('GPS Power : '+gpsPwr); + + Bangle.setGPSPower(gpsPwr); + + if ( gpsPwr ) { + // Display GPS speed/alt + g.clear(); + onGPS(lastFix); + } + else { + // Display simple clock + drawClockLarge(); + } + +} + // How to disable these while in menu? Interim using inMenu flag. function setButtons(){ - // Touch screen to toggle display - btnToggle = setWatch(toggleDisplay, BTN4, {repeat:true,edge:"falling"}); - btnToggle = setWatch(toggleDisplay, BTN5, {repeat:true,edge:"falling"}); - - // Units menu - btnMenu = setWatch(enterMenu, BTN3,{repeat:true,edge:"falling"}); + // Turn GPS on/off + setWatch(gpsPower, BTN1,{repeat:true,edge:"falling"}); - // setWatch(nextwp.bind(null,1), BTN3, {repeat:true,edge:"falling"}); + // Show launcher when middle button pressed + setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + + // Switch between fix and max display + setWatch(maxPressed, BTN3,{repeat:true,edge:"rising"}); + setWatch(maxReleased, BTN3,{repeat:true,edge:"falling"}); + + // Touch screen to toggle display + setWatch(toggleDisplay, BTN4, {repeat:true,edge:"falling"}); + setWatch(toggleDisplay, BTN5, {repeat:true,edge:"falling"}); + + } -g.clear(); -setUnitsAlt(0.3048,'feet'); // Default alt in feet +function maxPressed() { + if ( isDim ) { + onBright(); + return; + } + if ( ! gpsPwr ) return; + + maxPress = getTime(); +} + +function maxReleased() { + var dur = getTime()-maxPress; + + if ( ! gpsPwr ) return; + + if ( dur < 2 ) toggleMax(); // Short press toggle fix/max display + else { + max.spd = 0; // Long press resets max values. + max.alt = 0; + onGPS(lastFix); // redraw display + } +} + +function onBright() { + if ( dbg ) print('Undimming'); + Bangle.setLCDBrightness(1); + timeBright = getTime(); + isDim = 0; +} + +function onDim() { + if ( ! settings.dim_m ) { + return; + } + if ( getTime() > timeBright+(settings.dim_m*60) ) { + // Time to dim the lcd. Screen tap or BTN3 will restore to 100% + if ( dbg ) print('Dimming'); + Bangle.setLCDBrightness(settings.dim_b); + isDim = 1; + } +} + +function updateClock() { + if ( dbg ) print('Updating clock'); + drawTime(); + g.reset(); + g.drawImage(img,0,40); + g.flip(); + + // Something different to display in the emulator + if ( emulator ) { + max.spd++; + max.alt++; + } + + onDim(); // Check if time to dim the LCD +} + +// Read settings. +let settings = require('Storage').readJSON('speedalt.json',1)||{}; +settings.spd = settings.spd||0; // Multiplier for speed unit conversions. 0 = use the locale values for speed +settings.spd_unit = settings.spd_unit||''; // Displayed speed unit +settings.alt = settings.alt||0.3048;// Multiplier for altitude unit conversions. +settings.alt_unit = settings.alt_unit||'feet'; // Displayed altitude units +settings.dim_b = settings.dim_b||0.5; // Auto dim brightness +settings.dim_m = settings.dim_m||5; // Time in mins before auto dim. +settings.colour = settings.colour||0; // Colour scheme. + +/* +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 ( settings.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFFF,0xFFFF]); +if ( settings.colour == 2 ) img.palette = new Uint16Array([0,0xFF800,0xF800,0xF800]); + + +// Find speed unit if using locale speed +if ( settings.spd == 0 ) { + var strSpeed = require("locale").speed(1); + m = strSpeed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units + settings.spd_unit = m[2]; +} + + +// Main prog +onBright(); // Start with display not dimmed + +g.clear(); onGPS(lastFix); Bangle.loadWidgets(); Bangle.drawWidgets(); - Bangle.on('GPS', onGPS); Bangle.setGPSPower(1); - setButtons(); +setInterval(updateClock, 30000);