mirror of https://github.com/espruino/BangleApps
add other apps
parent
fe2a5e6f28
commit
819c67d442
44
apps.json
44
apps.json
|
@ -1,4 +1,13 @@
|
||||||
[
|
[
|
||||||
|
{ "id": "boot",
|
||||||
|
"name": "Bootloader",
|
||||||
|
"icon": "bootloader.png",
|
||||||
|
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
|
||||||
|
"tags": "tool,system",
|
||||||
|
"storage": [
|
||||||
|
{"name":".bootcde","url":"bootloader.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{ "id": "trex",
|
{ "id": "trex",
|
||||||
"name": "T-Rex",
|
"name": "T-Rex",
|
||||||
"icon": "trex.png",
|
"icon": "trex.png",
|
||||||
|
@ -75,6 +84,19 @@
|
||||||
{"name":"*slevel","url":"spiritlevel-icon.js","evaluate":true}
|
{"name":"*slevel","url":"spiritlevel-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "id": "settings",
|
||||||
|
"name": "Settings",
|
||||||
|
"icon": "settings.png",
|
||||||
|
"description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat",
|
||||||
|
"tags": "tool,system",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+settings","url":"settings.json"},
|
||||||
|
{"name":"-settings","url":"settings.js"},
|
||||||
|
{"name":"=settings","url":"settings-init.js"},
|
||||||
|
{"name":"@settings","url":"settings-default.json","evaluate":true},
|
||||||
|
{"name":"*settings","url":"settings-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{ "id": "sbat",
|
{ "id": "sbat",
|
||||||
"name": "Battery Level Widget",
|
"name": "Battery Level Widget",
|
||||||
"icon": "widget-battery.png",
|
"icon": "widget-battery.png",
|
||||||
|
@ -84,6 +106,28 @@
|
||||||
{"name":"=sbat","url":"widget-battery.js"}
|
{"name":"=sbat","url":"widget-battery.js"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "id": "hrm",
|
||||||
|
"name": "Heart Rate Monitor",
|
||||||
|
"icon": "heartrate.png",
|
||||||
|
"description": "Measure your current heart rate",
|
||||||
|
"tags": "health",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+hrm","url":"heartrate.json"},
|
||||||
|
{"name":"-hrm","url":"heartrate.js"},
|
||||||
|
{"name":"*hrm","url":"heartrate-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "id": "swatch",
|
||||||
|
"name": "Stopwatch",
|
||||||
|
"icon": "stopwatch.png",
|
||||||
|
"description": "Simple stopwatch with Lap Time recording",
|
||||||
|
"tags": "health",
|
||||||
|
"storage": [
|
||||||
|
{"name":"+swatch","url":"stopwatch.json"},
|
||||||
|
{"name":"-swatch","url":"stopwatch.js"},
|
||||||
|
{"name":"*swatch","url":"stopwatch-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{ "id": "qrcode",
|
{ "id": "qrcode",
|
||||||
"name": "Custom QR Code",
|
"name": "Custom QR Code",
|
||||||
"icon": "qrcode.png",
|
"icon": "qrcode.png",
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
E.setTimeZone(1);
|
||||||
|
E.setFlags({pretokenise:1});
|
||||||
|
setWatch(function() {
|
||||||
|
Bangle.setLCDMode("direct");
|
||||||
|
g.clear();
|
||||||
|
clearInterval();
|
||||||
|
clearWatch();
|
||||||
|
Bangle.removeAllListeners();
|
||||||
|
|
||||||
|
var s = require("Storage");
|
||||||
|
var apps = s.list().filter(a=>a[0]=='+').map(app=>s.readJSON(app));
|
||||||
|
var selected = 0;
|
||||||
|
var menuScroll = 0;
|
||||||
|
var menuShowing = false;
|
||||||
|
|
||||||
|
function drawMenu() {
|
||||||
|
g.setFont("6x8",2);
|
||||||
|
g.setFontAlign(-1,0);
|
||||||
|
var n = 3;
|
||||||
|
if (selected>=n+menuScroll) menuScroll = 1+selected-n;
|
||||||
|
if (selected<menuScroll) menuScroll = selected;
|
||||||
|
if (menuScroll) g.fillPoly([120,0,100,20,140,20]);
|
||||||
|
else g.clearRect(100,0,140,20);
|
||||||
|
if (apps.length>n+menuScroll) g.fillPoly([120,239,100,219,140,219]);
|
||||||
|
else g.clearRect(100,219,140,239);
|
||||||
|
for (var i=0;i<n;i++) {
|
||||||
|
var app = apps[i+menuScroll];
|
||||||
|
if (!app) break;
|
||||||
|
var y = 24+i*64;
|
||||||
|
if (i+menuScroll==selected) {
|
||||||
|
g.setColor(0.3,0.3,0.3);
|
||||||
|
g.fillRect(0,y,239,y+63);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.drawRect(0,y,239,y+63);
|
||||||
|
} else
|
||||||
|
g.clearRect(0,y,239,y+63);
|
||||||
|
if (app.icon) g.drawImage(s.read(app.icon),8,y+8);
|
||||||
|
g.drawString(app.name,64,y+32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawMenu();
|
||||||
|
setWatch(function() {
|
||||||
|
if (selected>0) {
|
||||||
|
selected--;
|
||||||
|
drawMenu();
|
||||||
|
}
|
||||||
|
}, BTN1, {repeat:true});
|
||||||
|
setWatch(function() {
|
||||||
|
if (selected+1<apps.length) {
|
||||||
|
selected++;
|
||||||
|
drawMenu();
|
||||||
|
}
|
||||||
|
}, BTN3, {repeat:true});
|
||||||
|
setWatch(function() { // run
|
||||||
|
clearWatch();
|
||||||
|
g.clear();
|
||||||
|
g.setFont("6x8",2);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
g.drawString("Loading...",120,120);
|
||||||
|
if (apps[selected].name=="Clock") load();
|
||||||
|
else { // load like this so we ensure we've cleared out our RAM
|
||||||
|
var cmd = 'eval(require("Storage").read("'+apps[selected].src+'"));';
|
||||||
|
setTimeout(cmd,20);
|
||||||
|
}
|
||||||
|
}, BTN2, {repeat:true});
|
||||||
|
}, BTN2, {repeat:false}); // menu on middle button
|
||||||
|
var WIDGETPOS={tl:32,tr:g.getWidth()-32,bl:32,br:g.getWidth()-32};
|
||||||
|
var WIDGETS={};
|
||||||
|
function drawWidgets() {
|
||||||
|
Object.keys(WIDGETS).forEach(k=>WIDGETS[k].draw());
|
||||||
|
}
|
||||||
|
eval(require("Storage").read("-clock"));
|
||||||
|
require("Storage").list().filter(a=>a[0]=='=').forEach(widget=>eval(require("Storage").read(widget)));
|
||||||
|
setTimeout(drawWidgets,100);
|
Binary file not shown.
After Width: | Height: | Size: 741 B |
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwghC/AH4AThnMAAXABJoMHBwgJJAAYMFAAIJLFxImCBJIuLABYuI4gXNNZFCC6AIFkZIQA4szC6vEmdMC60sC6nDmc8C6RDBC4irLC4gTBocymgGBoYXO4UyUwNEAYKrMC4ZEBUwNMVAR7LC4dDCoYBBSYJ7DoZQCC4kCmczkc0JIVM4UzmgaBAAQWD4AXBggJBJAIkBocs4c0BAQXJJARBD4c8oc8HAKZCI4gWCVAYXEJIJoCOovNC4cMUIQPB4RFBTAYAFIwapEC4JyCZAalHGAvCJYZYCVAYuIMIhjE5heGCwxhDMYTtIFw4wFoYsGFxIwF4YuRGAh7DFxxhGFyIYKCxqrGIpwwKFx4YGCyJJFCyQYDCygA/AH4AFA="))
|
|
@ -0,0 +1,69 @@
|
||||||
|
Bangle.setLCDPower(1);
|
||||||
|
Bangle.setLCDTimeout(0);
|
||||||
|
Bangle.ioWr(0x80,0)
|
||||||
|
x=0;
|
||||||
|
var min=0,max=0;
|
||||||
|
var wasHigh = 0, wasLow = 0;
|
||||||
|
var lastHigh = getTime();
|
||||||
|
var hrmList = [];
|
||||||
|
var hrm;
|
||||||
|
|
||||||
|
function readHRM() {
|
||||||
|
var a = analogRead(D29);
|
||||||
|
var h = getTime();
|
||||||
|
min=Math.min(min*0.97+a*0.03,a);
|
||||||
|
max=Math.max(max*0.97+a*0.03,a);
|
||||||
|
y = E.clip(170 - (a*960*4),100,230);
|
||||||
|
if (x==0) {
|
||||||
|
g.clearRect(0,100,239,239);
|
||||||
|
g.moveTo(-100,0);
|
||||||
|
}
|
||||||
|
/*g.setColor(0,1,0);
|
||||||
|
var z = 170 - (min*960*4); g.fillRect(x,z,x,z);
|
||||||
|
var z = 170 - (max*960*4); g.fillRect(x,z,x,z);*/
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.lineTo(x,y);
|
||||||
|
if ((max-min)>0.005) {
|
||||||
|
if (4*a > (min+3*max)) { // high
|
||||||
|
g.setColor(1,0,0);
|
||||||
|
g.fillRect(x,230,x,239);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
if (!wasHigh && wasLow) {
|
||||||
|
var currentHrm = 60/(h-lastHigh);
|
||||||
|
lastHigh = h;
|
||||||
|
if (currentHrm<250) {
|
||||||
|
while (hrmList.length>12) hrmList.shift();
|
||||||
|
hrmList.push(currentHrm);
|
||||||
|
// median filter
|
||||||
|
var t = hrmList.slice(); // copy
|
||||||
|
t.sort();
|
||||||
|
// average the middle 3
|
||||||
|
var mid = t.length>>1;
|
||||||
|
hrm = (t[mid]+t[mid+1]+t[mid+2])/3;
|
||||||
|
g.setFontVector(40);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
g.clearRect(0,0,239,100);
|
||||||
|
var str = Math.round(hrm);
|
||||||
|
var px = 120;
|
||||||
|
g.drawString(str,px,40);
|
||||||
|
px += g.stringWidth(str)/2;
|
||||||
|
g.setFont("6x8");
|
||||||
|
g.drawString("BPM",px+20,60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wasLow = 0;
|
||||||
|
wasHigh = 1;
|
||||||
|
} else if (4*a < (max+3*min)) { // low
|
||||||
|
wasLow = 1;
|
||||||
|
} else { // middle
|
||||||
|
g.setColor(0.5,0,0);
|
||||||
|
g.fillRect(x,230,x,239);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
wasHigh = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
if (x>239)x=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterval(readHRM,50);
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
name:"Heart Rate",
|
||||||
|
icon:"*hrm",
|
||||||
|
src:"-hrm"
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
timeout: 10, // Default LCD timeout in seconds
|
||||||
|
vibrate: true, // Vibration enabled by default. App must support
|
||||||
|
beep: true, // Beep enabled by default. App must support
|
||||||
|
timezone: 0, // Set the timezone for the device
|
||||||
|
HID : false, // BLE HID mode, off by default
|
||||||
|
debug: false, // Debug mode disabled by default. App must support
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwhC/AH4A/ABEIxGAAgwWO/+IAoIECDB0I////GIxGPAoIXR//854DCC54TCAAYXQCYXIDYYXOOIP4xnMAAJgBPoSMKOIP8xgXDGQJ9CGREIOIXMxmICwITBxh9CC5BEBBoIWBOweMMYZKIWwRdBAgQeDBYYXKFAKnFA4YXIKgJeBFwj0DI5UICgIXDOoIXC5gCBYRIXCN4I+CDgQXCYBJIBBwIXGBQIXX9AXJI4QXHI5Z3K/h3LTYanHX4TvLxhICAAaXCd5gnDd4gLDI5X4xj0CAAPIGwbvJIAeIDAQWBIwXPO5EIRIPP/mM5AFB5HIA4IFBC5DZECAPMDQJdB5AUKJQ3IxnvAgIsLC4ZYCAAgXnCIJxCXgQXPYYJxCAgKMMDAoRCAggA/AH4A/AAoA="))
|
|
@ -0,0 +1,55 @@
|
||||||
|
(function() {
|
||||||
|
var s = require('Storage').readJSON('@settings');
|
||||||
|
if (s.HID) {
|
||||||
|
Bangle.HID = new Uint8Array([
|
||||||
|
0x05, 0x01,
|
||||||
|
0x09, 0x06,
|
||||||
|
0xA1, 0x01,
|
||||||
|
0x05, 0x07,
|
||||||
|
0x19, 0xe0,
|
||||||
|
0x29, 0xe7,
|
||||||
|
0x15, 0x00,
|
||||||
|
0x25, 0x01,
|
||||||
|
0x75, 0x01,
|
||||||
|
0x95, 0x08,
|
||||||
|
0x81, 0x02,
|
||||||
|
0x95, 0x01,
|
||||||
|
0x75, 0x08,
|
||||||
|
0x81, 0x01,
|
||||||
|
0x95, 0x05,
|
||||||
|
0x75, 0x01,
|
||||||
|
0x05, 0x08,
|
||||||
|
0x19, 0x01,
|
||||||
|
0x29, 0x05,
|
||||||
|
0x91, 0x02,
|
||||||
|
0x95, 0x01,
|
||||||
|
0x75, 0x03,
|
||||||
|
0x91, 0x01,
|
||||||
|
0x95, 0x06,
|
||||||
|
0x75, 0x08,
|
||||||
|
0x15, 0x00,
|
||||||
|
0x25, 0x73,
|
||||||
|
0x05, 0x07,
|
||||||
|
0x19, 0x00,
|
||||||
|
0x29, 0x73,
|
||||||
|
0x81, 0x00,
|
||||||
|
0x09, 0x05,
|
||||||
|
0x15, 0x00,
|
||||||
|
0x26, 0xFF, 0x00,
|
||||||
|
0x75, 0x08,
|
||||||
|
0x95, 0x02,
|
||||||
|
0xB1, 0x02,
|
||||||
|
0xC0
|
||||||
|
]);
|
||||||
|
NRF.setServices(undefined, {
|
||||||
|
uart: true, hid: Bangle.HID,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s.vibrate) Bangle.buzz=()=>Promise.resolve();
|
||||||
|
if (!s.beep) Bangle.beep=()=>Promise.resolve();
|
||||||
|
Bangle.setLCDTimeout(s.timeout);
|
||||||
|
if (!s.timeout) Bangle.setLCDPower(1);
|
||||||
|
E.setTimeZone(s.timezone);
|
||||||
|
})();
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
Bangle.setLCDPower(1);
|
||||||
|
Bangle.setLCDTimeout(0);
|
||||||
|
|
||||||
|
g.clear();
|
||||||
|
const storage = require('Storage');
|
||||||
|
let settings;
|
||||||
|
|
||||||
|
function debug(msg, arg) {
|
||||||
|
if (settings.debug)
|
||||||
|
console.log(msg, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSettings() {
|
||||||
|
debug('updating settings', settings);
|
||||||
|
storage.erase('@settings');
|
||||||
|
storage.write('@settings', settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetSettings() {
|
||||||
|
settings = {
|
||||||
|
timeout: 10,
|
||||||
|
vibrate: true,
|
||||||
|
beep: true,
|
||||||
|
timezone: 0,
|
||||||
|
HID : false,
|
||||||
|
debug: false,
|
||||||
|
};
|
||||||
|
setLCDTimeout(settings.timeout);
|
||||||
|
updateSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
settings = storage.readJSON('@settings');
|
||||||
|
} catch (e) {}
|
||||||
|
if (!settings) resetSettings();
|
||||||
|
|
||||||
|
const boolFormat = (v) => v ? "On" : "Off";
|
||||||
|
|
||||||
|
function showMainMenu() {
|
||||||
|
const mainmenu = {
|
||||||
|
'': { 'title': 'Settings' },
|
||||||
|
'LCD Timeout': {
|
||||||
|
value: settings.timeout,
|
||||||
|
min: 0,
|
||||||
|
max: 60,
|
||||||
|
step: 5,
|
||||||
|
onchange: v => {
|
||||||
|
settings.timeout = 0 | v;
|
||||||
|
updateSettings();
|
||||||
|
Bangle.setLCDTimeout(settings.timeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Beep': {
|
||||||
|
value: settings.beep,
|
||||||
|
format: boolFormat,
|
||||||
|
onchange: () => {
|
||||||
|
settings.beep = !settings.beep;
|
||||||
|
updateSettings();
|
||||||
|
if (settings.beep) {
|
||||||
|
Bangle.beep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Vibration': {
|
||||||
|
value: settings.vibrate,
|
||||||
|
format: boolFormat,
|
||||||
|
onchange: () => {
|
||||||
|
settings.vibrate = !settings.vibrate;
|
||||||
|
updateSettings();
|
||||||
|
if (settings.vibrate) {
|
||||||
|
VIBRATE.write(1);
|
||||||
|
setTimeout(()=>VIBRATE.write(0), 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Time Zone': {
|
||||||
|
value: settings.timezone,
|
||||||
|
min: -11,
|
||||||
|
max: 12,
|
||||||
|
step: 1,
|
||||||
|
onchange: v => {
|
||||||
|
settings.timezone = 0 | v;
|
||||||
|
updateSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'HID': {
|
||||||
|
value: settings.HID,
|
||||||
|
format: boolFormat,
|
||||||
|
onchange: () => {
|
||||||
|
settings.HID = !settings.HID;
|
||||||
|
updateSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Debug': {
|
||||||
|
value: settings.debug,
|
||||||
|
format: boolFormat,
|
||||||
|
onchange: () => {
|
||||||
|
settings.debug = !settings.debug;
|
||||||
|
updateSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Reset': showResetMenu,
|
||||||
|
'Turn Off': Bangle.off,
|
||||||
|
'< Back': load
|
||||||
|
};
|
||||||
|
return Bangle.menu(mainmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResetMenu() {
|
||||||
|
const resetmenu = {
|
||||||
|
'': { 'title': 'Reset' },
|
||||||
|
'< Back': showMainMenu,
|
||||||
|
'Reset Settings': () => {
|
||||||
|
E.showPrompt('Reset Settings?').then((v) => {
|
||||||
|
if (v) {
|
||||||
|
E.showMessage('Resetting');
|
||||||
|
resetSettings();
|
||||||
|
}
|
||||||
|
setTimeout(showMainMenu, 50);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// this is include for debugging. remove for production
|
||||||
|
/*'Erase': () => {
|
||||||
|
storage.erase('=settings');
|
||||||
|
storage.erase('-settings');
|
||||||
|
storage.erase('@settings');
|
||||||
|
storage.erase('*settings');
|
||||||
|
storage.erase('+settings');
|
||||||
|
E.reboot();
|
||||||
|
}*/
|
||||||
|
};
|
||||||
|
return Bangle.menu(resetmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
showMainMenu();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
name: 'Settings',
|
||||||
|
icon: '*settings',
|
||||||
|
src: '-settings'
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -1,6 +1,13 @@
|
||||||
g.clear();
|
g.clear();
|
||||||
var old = {x:0,y:0};
|
var old = {x:0,y:0};
|
||||||
Bangle.on('accel',function(v) {
|
Bangle.on('accel',function(v) {
|
||||||
|
var max = Math.max(Math.abs(v.x),Math.abs(v.y),Math.abs(v.z));
|
||||||
|
if (Math.abs(v.y)==max) {
|
||||||
|
v = {x:v.x,y:v.z,z:v.y};
|
||||||
|
} else if (Math.abs(v.x)==max) {
|
||||||
|
v = {x:v.z,y:v.y,z:v.x};
|
||||||
|
}
|
||||||
|
|
||||||
var d = Math.sqrt(v.x*v.x+v.y*v.y);
|
var d = Math.sqrt(v.x*v.x+v.y*v.y);
|
||||||
var ang = Math.atan2(d,Math.abs(v.z))*180/Math.PI;
|
var ang = Math.atan2(d,Math.abs(v.z))*180/Math.PI;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwghC/AFECkQACkAX/C/4AKgMRiMQVCYXFGYIWOxAAEgJLPCwuIwRkCCyQABC5sICIUzn/zmYYEFxs//4AC+ZJCL5QuCCwXzDAuAFxeDCYYyDnALBC5YSD+UvGApGKFwYXFGARIIC4OPCIfxj4FD/AXJRgwXFJBQJBCAYXBiYGEC5ReE/8xC4pgBC50hiQXPOwn/iMRMwgXP+QXBVAiQBC8pHCO6rvFC6IAGC5TXFAAzvLUAgAF+YXJhB4GAAiOBwAXJMBReBC5BILIxQXDGBAuBC5RIBGA4uCIxIwDDAoWCFxQwExEzn/zmYGCFxYwEAAwWMDBIWODA4WQAH4AXA=="))
|
|
@ -0,0 +1,84 @@
|
||||||
|
var tStart = Date.now();
|
||||||
|
var tCurrent = Date.now();
|
||||||
|
var started = false;
|
||||||
|
var timeY = 60;
|
||||||
|
var hsXPos = 0;
|
||||||
|
var lapTimes = [];
|
||||||
|
var displayInterval;
|
||||||
|
|
||||||
|
function timeToText(t) {
|
||||||
|
var secs = Math.floor(t/1000)%60;
|
||||||
|
var mins = Math.floor(t/60000);
|
||||||
|
var hs = Math.floor(t/10)%100;
|
||||||
|
return mins+":"+("0"+secs).substr(-2)+"."+("0"+hs).substr(-2);
|
||||||
|
}
|
||||||
|
function updateLabels() {
|
||||||
|
g.clear();
|
||||||
|
g.setFont("6x8",2);
|
||||||
|
g.setFontAlign(0,0,3);
|
||||||
|
g.drawString(started?"STOP":"GO",230,120);
|
||||||
|
if (!started) g.drawString("RESET",230,50);
|
||||||
|
g.drawString("LAP",230,190);
|
||||||
|
g.setFont("6x8",1);
|
||||||
|
g.setFontAlign(-1,-1);
|
||||||
|
for (var i in lapTimes) {
|
||||||
|
g.drawString(i+": "+timeToText(lapTimes[i]),10,timeY + 30 + i*8);
|
||||||
|
}
|
||||||
|
drawsecs();
|
||||||
|
}
|
||||||
|
function drawsecs() {
|
||||||
|
var t = tCurrent-tStart;
|
||||||
|
g.setFont("Vector",48);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
var secs = Math.floor(t/1000)%60;
|
||||||
|
var mins = Math.floor(t/60000);
|
||||||
|
var txt = mins+":"+("0"+secs).substr(-2);
|
||||||
|
var x = 100;
|
||||||
|
g.clearRect(0,timeY-26,200,timeY+26);
|
||||||
|
g.drawString(txt,x,timeY);
|
||||||
|
hsXPos = 5+x+g.stringWidth(txt)/2;
|
||||||
|
drawms();
|
||||||
|
}
|
||||||
|
function drawms() {
|
||||||
|
var t = tCurrent-tStart;
|
||||||
|
var hs = Math.floor(t/10)%100;
|
||||||
|
g.setFontAlign(-1,0);
|
||||||
|
g.setFont("6x8",2);
|
||||||
|
g.clearRect(hsXPos,timeY,220,timeY+20);
|
||||||
|
g.drawString("."+("0"+hs).substr(-2),hsXPos,timeY+10);
|
||||||
|
}
|
||||||
|
|
||||||
|
setWatch(function() { // Start/stop
|
||||||
|
started = !started;
|
||||||
|
if (started)
|
||||||
|
tStart = Date.now()+tStart-tCurrent;
|
||||||
|
tCurrent = Date.now();
|
||||||
|
if (displayInterval) {
|
||||||
|
clearInterval(displayInterval);
|
||||||
|
displayInterval = undefined;
|
||||||
|
}
|
||||||
|
updateLabels();
|
||||||
|
if (started)
|
||||||
|
displayInterval = setInterval(function() {
|
||||||
|
var last = tCurrent;
|
||||||
|
if (started) tCurrent = Date.now();
|
||||||
|
if (Math.floor(last/1000)!=Math.floor(tCurrent/1000))
|
||||||
|
drawsecs();
|
||||||
|
else
|
||||||
|
drawms();
|
||||||
|
}, 20);
|
||||||
|
}, BTN2, {repeat:true});
|
||||||
|
setWatch(function() { // Reset
|
||||||
|
if (!started) {
|
||||||
|
tStart = tCurrent = Date.now();
|
||||||
|
}
|
||||||
|
updateLabels();
|
||||||
|
}, BTN1, {repeat:true});
|
||||||
|
setWatch(function() { // Lap
|
||||||
|
if (started) tCurrent = Date.now();
|
||||||
|
lapTimes.unshift(tCurrent-tStart);
|
||||||
|
tStart = tCurrent;
|
||||||
|
updateLabels();
|
||||||
|
}, BTN3, {repeat:true});
|
||||||
|
|
||||||
|
updateLabels();
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
name:"Stopwatch",
|
||||||
|
icon:"*swatch",
|
||||||
|
src:"-swatch"
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Loading…
Reference in New Issue