mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-23 16:25:19 +03:00
crude port
This commit is contained in:
parent
706cb4c36f
commit
25c8a6f61c
15 changed files with 50864 additions and 4 deletions
BIN
images/osd-bg-1.jpg
Normal file
BIN
images/osd-bg-1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 299 KiB |
44
js/gui.js
44
js/gui.js
|
@ -1,3 +1,4 @@
|
||||||
|
/*global $*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var TABS = {}; // filled by individual tab js file
|
var TABS = {}; // filled by individual tab js file
|
||||||
|
@ -35,7 +36,8 @@ var GUI_control = function () {
|
||||||
'receiver',
|
'receiver',
|
||||||
'sensors',
|
'sensors',
|
||||||
'servos',
|
'servos',
|
||||||
'setup'
|
'setup',
|
||||||
|
'osd'
|
||||||
];
|
];
|
||||||
this.allowedTabs = this.defaultAllowedTabsWhenDisconnected;
|
this.allowedTabs = this.defaultAllowedTabsWhenDisconnected;
|
||||||
|
|
||||||
|
@ -239,6 +241,44 @@ GUI_control.prototype.tab_switch_cleanup = function (callback) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GUI_control.prototype.switchery = function() {
|
||||||
|
$('.togglesmall').each(function(index, elem) {
|
||||||
|
var switchery = new Switchery(elem, {
|
||||||
|
size: 'small',
|
||||||
|
color: '#ffbb00',
|
||||||
|
secondaryColor: '#c4c4c4'
|
||||||
|
});
|
||||||
|
$(elem).on("change", function (evt) {
|
||||||
|
switchery.setPosition();
|
||||||
|
});
|
||||||
|
$(elem).removeClass('togglesmall');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.toggle').each(function(index, elem) {
|
||||||
|
var switchery = new Switchery(elem, {
|
||||||
|
color: '#ffbb00',
|
||||||
|
secondaryColor: '#c4c4c4'
|
||||||
|
});
|
||||||
|
$(elem).on("change", function (evt) {
|
||||||
|
switchery.setPosition();
|
||||||
|
});
|
||||||
|
$(elem).removeClass('toggle');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.togglemedium').each(function(index, elem) {
|
||||||
|
var switchery = new Switchery(elem, {
|
||||||
|
className: 'switcherymid',
|
||||||
|
color: '#ffbb00',
|
||||||
|
secondaryColor: '#c4c4c4'
|
||||||
|
});
|
||||||
|
$(elem).on("change", function (evt) {
|
||||||
|
switchery.setPosition();
|
||||||
|
});
|
||||||
|
$(elem).removeClass('togglemedium');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
GUI_control.prototype.content_ready = function (callback) {
|
GUI_control.prototype.content_ready = function (callback) {
|
||||||
|
|
||||||
$('.togglesmall').each(function(index, elem) {
|
$('.togglesmall').each(function(index, elem) {
|
||||||
|
@ -303,7 +343,7 @@ GUI_control.prototype.content_ready = function (callback) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
}
|
};
|
||||||
|
|
||||||
// initialize object into GUI variable
|
// initialize object into GUI variable
|
||||||
var GUI = new GUI_control();
|
var GUI = new GUI_control();
|
||||||
|
|
92
js/injected_methods.js
Normal file
92
js/injected_methods.js
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
Number.prototype.clamp = function(min, max) {
|
||||||
|
return Math.min(Math.max(this, min), max);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String formatting now supports currying (partial application).
|
||||||
|
* For a format string with N replacement indices, you can call .format
|
||||||
|
* with M <= N arguments. The result is going to be a format string
|
||||||
|
* with N-M replacement indices, properly counting from 0 .. N-M.
|
||||||
|
* The following Example should explain the usage of partial applied format:
|
||||||
|
* "{0}:{1}:{2}".format("a","b","c") === "{0}:{1}:{2}".format("a","b").format("c")
|
||||||
|
* "{0}:{1}:{2}".format("a").format("b").format("c") === "{0}:{1}:{2}".format("a").format("b", "c")
|
||||||
|
**/
|
||||||
|
String.prototype.format = function () {
|
||||||
|
var args = arguments;
|
||||||
|
return this.replace(/\{(\d+)\}/g, function (t, i) {
|
||||||
|
return args[i] !== void 0 ? args[i] : "{"+(i-args.length)+"}";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Array.prototype.push8 = function(val) {
|
||||||
|
this.push(0xFF & val);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Array.prototype.push16 = function(val) {
|
||||||
|
// low byte
|
||||||
|
this.push(0x00FF & val);
|
||||||
|
// high byte
|
||||||
|
this.push(val >> 8);
|
||||||
|
// chainable
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
Array.prototype.push32 = function(val) {
|
||||||
|
this.push8(val)
|
||||||
|
.push8(val >> 8)
|
||||||
|
.push8(val >> 16)
|
||||||
|
.push8(val >> 24);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.offset = 0;
|
||||||
|
DataView.prototype.readU8 = function() {
|
||||||
|
if (this.byteLength >= this.offset+1) {
|
||||||
|
return this.getUint8(this.offset++);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.readU16 = function() {
|
||||||
|
if (this.byteLength >= this.offset+2) {
|
||||||
|
return this.readU8() + this.readU8()*256;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.readU32 = function() {
|
||||||
|
if (this.byteLength >= this.offset+4) {
|
||||||
|
return this.readU16() + this.readU16()*65536;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.read8 = function() {
|
||||||
|
if (this.byteLength >= this.offset+1) {
|
||||||
|
return this.getInt8(this.offset++, 1);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.read16 = function() {
|
||||||
|
this.offset += 2;
|
||||||
|
if (this.byteLength >= this.offset) {
|
||||||
|
return this.getInt16(this.offset-2, 1);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.read32 = function() {
|
||||||
|
this.offset += 4;
|
||||||
|
if (this.byteLength >= this.offset) {
|
||||||
|
return this.getInt32(this.offset-4, 1);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
31
js/libraries/inflection.min.js
vendored
Normal file
31
js/libraries/inflection.min.js
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*!
|
||||||
|
* inflection
|
||||||
|
* Copyright(c) 2011 Ben Lin <ben@dreamerslab.com>
|
||||||
|
* MIT Licensed
|
||||||
|
*
|
||||||
|
* @fileoverview
|
||||||
|
* A port of inflection-js to node.js module.
|
||||||
|
*/
|
||||||
|
(function(a,b){if(typeof define==="function"&&define.amd){define([],b);
|
||||||
|
}else{if(typeof exports==="object"){module.exports=b();}else{a.inflection=b();}}}(this,function(){var d=["accommodation","adulthood","advertising","advice","aggression","aid","air","aircraft","alcohol","anger","applause","arithmetic","assistance","athletics","bacon","baggage","beef","biology","blood","botany","bread","butter","carbon","cardboard","cash","chalk","chaos","chess","crossroads","countryside","dancing","deer","dignity","dirt","dust","economics","education","electricity","engineering","enjoyment","envy","equipment","ethics","evidence","evolution","fame","fiction","flour","flu","food","fuel","fun","furniture","gallows","garbage","garlic","genetics","gold","golf","gossip","grammar","gratitude","grief","guilt","gymnastics","happiness","hardware","harm","hate","hatred","health","heat","help","homework","honesty","honey","hospitality","housework","humour","hunger","hydrogen","ice","importance","inflation","information","innocence","iron","irony","jam","jewelry","judo","karate","knowledge","lack","laughter","lava","leather","leisure","lightning","linguine","linguini","linguistics","literature","litter","livestock","logic","loneliness","luck","luggage","macaroni","machinery","magic","management","mankind","marble","mathematics","mayonnaise","measles","methane","milk","money","mud","music","mumps","nature","news","nitrogen","nonsense","nurture","nutrition","obedience","obesity","oxygen","pasta","patience","physics","poetry","pollution","poverty","pride","psychology","publicity","punctuation","quartz","racism","relaxation","reliability","research","respect","revenge","rice","rubbish","rum","safety","scenery","seafood","seaside","series","shame","sheep","shopping","sleep","smoke","smoking","snow","soap","software","soil","spaghetti","species","steam","stuff","stupidity","sunshine","symmetry","tennis","thirst","thunder","timber","traffic","transportation","trust","underwear","unemployment","unity","validity","veal","vegetation","vegetarianism","vengeance","violence","vitality","warmth","wealth","weather","welfare","wheat","wildlife","wisdom","yoga","zinc","zoology"];
|
||||||
|
var i={plural:{men:new RegExp("^(m|wom)en$","gi"),people:new RegExp("(pe)ople$","gi"),children:new RegExp("(child)ren$","gi"),tia:new RegExp("([ti])a$","gi"),analyses:new RegExp("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$","gi"),hives:new RegExp("(hi|ti)ves$","gi"),curves:new RegExp("(curve)s$","gi"),lrves:new RegExp("([lr])ves$","gi"),foves:new RegExp("([^fo])ves$","gi"),movies:new RegExp("(m)ovies$","gi"),aeiouyies:new RegExp("([^aeiouy]|qu)ies$","gi"),series:new RegExp("(s)eries$","gi"),xes:new RegExp("(x|ch|ss|sh)es$","gi"),mice:new RegExp("([m|l])ice$","gi"),buses:new RegExp("(bus)es$","gi"),oes:new RegExp("(o)es$","gi"),shoes:new RegExp("(shoe)s$","gi"),crises:new RegExp("(cris|ax|test)es$","gi"),octopi:new RegExp("(octop|vir)i$","gi"),aliases:new RegExp("(alias|canvas|status|campus)es$","gi"),summonses:new RegExp("^(summons)es$","gi"),oxen:new RegExp("^(ox)en","gi"),matrices:new RegExp("(matr)ices$","gi"),vertices:new RegExp("(vert|ind)ices$","gi"),feet:new RegExp("^feet$","gi"),teeth:new RegExp("^teeth$","gi"),geese:new RegExp("^geese$","gi"),quizzes:new RegExp("(quiz)zes$","gi"),whereases:new RegExp("^(whereas)es$","gi"),criteria:new RegExp("^(criteri)a$","gi"),genera:new RegExp("^genera$","gi"),ss:new RegExp("ss$","gi"),s:new RegExp("s$","gi")},singular:{man:new RegExp("^(m|wom)an$","gi"),person:new RegExp("(pe)rson$","gi"),child:new RegExp("(child)$","gi"),ox:new RegExp("^(ox)$","gi"),axis:new RegExp("(ax|test)is$","gi"),octopus:new RegExp("(octop|vir)us$","gi"),alias:new RegExp("(alias|status|canvas|campus)$","gi"),summons:new RegExp("^(summons)$","gi"),bus:new RegExp("(bu)s$","gi"),buffalo:new RegExp("(buffal|tomat|potat)o$","gi"),tium:new RegExp("([ti])um$","gi"),sis:new RegExp("sis$","gi"),ffe:new RegExp("(?:([^f])fe|([lr])f)$","gi"),hive:new RegExp("(hi|ti)ve$","gi"),aeiouyy:new RegExp("([^aeiouy]|qu)y$","gi"),x:new RegExp("(x|ch|ss|sh)$","gi"),matrix:new RegExp("(matr)ix$","gi"),vertex:new RegExp("(vert|ind)ex$","gi"),mouse:new RegExp("([m|l])ouse$","gi"),foot:new RegExp("^foot$","gi"),tooth:new RegExp("^tooth$","gi"),goose:new RegExp("^goose$","gi"),quiz:new RegExp("(quiz)$","gi"),whereas:new RegExp("^(whereas)$","gi"),criterion:new RegExp("^(criteri)on$","gi"),genus:new RegExp("^genus$","gi"),s:new RegExp("s$","gi"),common:new RegExp("$","gi")}};
|
||||||
|
var g=[[i.plural.men],[i.plural.people],[i.plural.children],[i.plural.tia],[i.plural.analyses],[i.plural.hives],[i.plural.curves],[i.plural.lrves],[i.plural.foves],[i.plural.aeiouyies],[i.plural.series],[i.plural.movies],[i.plural.xes],[i.plural.mice],[i.plural.buses],[i.plural.oes],[i.plural.shoes],[i.plural.crises],[i.plural.octopi],[i.plural.aliases],[i.plural.summonses],[i.plural.oxen],[i.plural.matrices],[i.plural.feet],[i.plural.teeth],[i.plural.geese],[i.plural.quizzes],[i.plural.whereases],[i.plural.criteria],[i.plural.genera],[i.singular.man,"$1en"],[i.singular.person,"$1ople"],[i.singular.child,"$1ren"],[i.singular.ox,"$1en"],[i.singular.axis,"$1es"],[i.singular.octopus,"$1i"],[i.singular.alias,"$1es"],[i.singular.summons,"$1es"],[i.singular.bus,"$1ses"],[i.singular.buffalo,"$1oes"],[i.singular.tium,"$1a"],[i.singular.sis,"ses"],[i.singular.ffe,"$1$2ves"],[i.singular.hive,"$1ves"],[i.singular.aeiouyy,"$1ies"],[i.singular.matrix,"$1ices"],[i.singular.vertex,"$1ices"],[i.singular.x,"$1es"],[i.singular.mouse,"$1ice"],[i.singular.foot,"feet"],[i.singular.tooth,"teeth"],[i.singular.goose,"geese"],[i.singular.quiz,"$1zes"],[i.singular.whereas,"$1es"],[i.singular.criterion,"$1a"],[i.singular.genus,"genera"],[i.singular.s,"s"],[i.singular.common,"s"]];
|
||||||
|
var a=[[i.singular.man],[i.singular.person],[i.singular.child],[i.singular.ox],[i.singular.axis],[i.singular.octopus],[i.singular.alias],[i.singular.summons],[i.singular.bus],[i.singular.buffalo],[i.singular.tium],[i.singular.sis],[i.singular.ffe],[i.singular.hive],[i.singular.aeiouyy],[i.singular.x],[i.singular.matrix],[i.singular.mouse],[i.singular.foot],[i.singular.tooth],[i.singular.goose],[i.singular.quiz],[i.singular.whereas],[i.singular.criterion],[i.singular.genus],[i.plural.men,"$1an"],[i.plural.people,"$1rson"],[i.plural.children,"$1"],[i.plural.genera,"genus"],[i.plural.criteria,"$1on"],[i.plural.tia,"$1um"],[i.plural.analyses,"$1$2sis"],[i.plural.hives,"$1ve"],[i.plural.curves,"$1"],[i.plural.lrves,"$1f"],[i.plural.foves,"$1fe"],[i.plural.movies,"$1ovie"],[i.plural.aeiouyies,"$1y"],[i.plural.series,"$1eries"],[i.plural.xes,"$1"],[i.plural.mice,"$1ouse"],[i.plural.buses,"$1"],[i.plural.oes,"$1"],[i.plural.shoes,"$1"],[i.plural.crises,"$1is"],[i.plural.octopi,"$1us"],[i.plural.aliases,"$1"],[i.plural.summonses,"$1"],[i.plural.oxen,"$1"],[i.plural.matrices,"$1ix"],[i.plural.vertices,"$1ex"],[i.plural.feet,"foot"],[i.plural.teeth,"tooth"],[i.plural.geese,"goose"],[i.plural.quizzes,"$1"],[i.plural.whereases,"$1"],[i.plural.ss,"ss"],[i.plural.s,""]];
|
||||||
|
var c=["and","or","nor","a","an","the","so","but","to","of","at","by","from","into","on","onto","off","out","in","over","with","for"];var k=new RegExp("(_ids|_id)$","g");
|
||||||
|
var f=new RegExp("_","g");var j=new RegExp("[ _]","g");var e=new RegExp("([A-Z])","g");var h=new RegExp("^_");var b={_apply_rules:function(q,p,o,n){if(n){q=n;
|
||||||
|
}else{var r=(b.indexOf(o,q.toLowerCase())>-1);if(!r){var m=0;var l=p.length;for(;m<l;m++){if(q.match(p[m][0])){if(p[m][1]!==undefined){q=q.replace(p[m][0],p[m][1]);
|
||||||
|
}break;}}}}return q;},indexOf:function(l,r,q,m){if(!q){q=-1;}var o=-1;var p=q;var n=l.length;for(;p<n;p++){if(l[p]===r||m&&m(l[p],r)){o=p;break;}}return o;
|
||||||
|
},pluralize:function(m,l){return b._apply_rules(m,g,d,l);},singularize:function(m,l){return b._apply_rules(m,a,d,l);},inflect:function(o,n,m,l){n=parseInt(n,10);
|
||||||
|
if(isNaN(n)){return o;}if(n===0||n>1){return b._apply_rules(o,g,d,l);}else{return b._apply_rules(o,a,d,m);}},camelize:function(t,o){var v=t.split("/");
|
||||||
|
var r=0;var q=v.length;var u,m,p,n,s;for(;r<q;r++){u=v[r].split("_");p=0;n=u.length;for(;p<n;p++){if(p!==0){u[p]=u[p].toLowerCase();}s=u[p].charAt(0);s=o&&r===0&&p===0?s.toLowerCase():s.toUpperCase();
|
||||||
|
u[p]=s+u[p].substring(1);}v[r]=u.join("");}return v.join("::");},underscore:function(o,p){if(p&&o===o.toUpperCase()){return o;}var l=o.split("::");var n=0;
|
||||||
|
var m=l.length;for(;n<m;n++){l[n]=l[n].replace(e,"_$1");l[n]=l[n].replace(h,"");}return l.join("/").toLowerCase();},humanize:function(m,l){m=m.toLowerCase();
|
||||||
|
m=m.replace(k,"");m=m.replace(f," ");if(!l){m=b.capitalize(m);}return m;},capitalize:function(l){l=l.toLowerCase();return l.substring(0,1).toUpperCase()+l.substring(1);
|
||||||
|
},dasherize:function(l){return l.replace(j,"-");},titleize:function(s){s=s.toLowerCase().replace(f," ");var q=s.split(" ");var p=0;var o=q.length;var r,n,m;
|
||||||
|
for(;p<o;p++){r=q[p].split("-");n=0;m=r.length;for(;n<m;n++){if(b.indexOf(c,r[n].toLowerCase())<0){r[n]=b.capitalize(r[n]);}}q[p]=r.join("-");}s=q.join(" ");
|
||||||
|
s=s.substring(0,1).toUpperCase()+s.substring(1);return s;},demodulize:function(m){var l=m.split("::");return l[l.length-1];},tableize:function(l){l=b.underscore(l);
|
||||||
|
l=b.pluralize(l);return l;},classify:function(l){l=b.camelize(l);l=b.singularize(l);return l;},foreign_key:function(m,l){m=b.demodulize(m);m=b.underscore(m)+((l)?(""):("_"))+"id";
|
||||||
|
return m;},ordinalize:function(s){var q=s.split(" ");var o=0;var n=q.length;for(;o<n;o++){var m=parseInt(q[o],10);if(!isNaN(m)){var r=q[o].substring(q[o].length-2);
|
||||||
|
var p=q[o].substring(q[o].length-1);var l="th";if(r!="11"&&r!="12"&&r!="13"){if(p==="1"){l="st";}else{if(p==="2"){l="nd";}else{if(p==="3"){l="rd";}}}}q[o]+=l;
|
||||||
|
}}return q.join(" ");},transform:function(o,l){var n=0;var m=l.length;for(;n<m;n++){var p=l[n];if(this.hasOwnProperty(p)){o=this[p](o);}}return o;}};b.version="1.10.0";
|
||||||
|
return b;}));
|
9
js/libraries/jquery.ba-throttle-debounce.min.js
vendored
Normal file
9
js/libraries/jquery.ba-throttle-debounce.min.js
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* jQuery throttle / debounce - v1.1 - 3/7/2010
|
||||||
|
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 "Cowboy" Ben Alman
|
||||||
|
* Dual licensed under the MIT and GPL licenses.
|
||||||
|
* http://benalman.com/about/license/
|
||||||
|
*/
|
||||||
|
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
|
11
js/msp.js
11
js/msp.js
|
@ -45,6 +45,7 @@ var MSP_codes = {
|
||||||
MSP_SET_BLACKBOX_CONFIG: 81,
|
MSP_SET_BLACKBOX_CONFIG: 81,
|
||||||
MSP_TRANSPONDER_CONFIG: 82,
|
MSP_TRANSPONDER_CONFIG: 82,
|
||||||
MSP_SET_TRANSPONDER_CONFIG: 83,
|
MSP_SET_TRANSPONDER_CONFIG: 83,
|
||||||
|
MSP_OSD_CONFIG: 84,
|
||||||
|
|
||||||
MSP_ADVANCED_CONFIG: 90,
|
MSP_ADVANCED_CONFIG: 90,
|
||||||
MSP_SET_ADVANCED_CONFIG: 91,
|
MSP_SET_ADVANCED_CONFIG: 91,
|
||||||
|
@ -1180,6 +1181,8 @@ var MSP = {
|
||||||
case MSP_codes.MSP_SET_FAILSAFE_CONFIG:
|
case MSP_codes.MSP_SET_FAILSAFE_CONFIG:
|
||||||
console.log('Failsafe config saved');
|
console.log('Failsafe config saved');
|
||||||
break;
|
break;
|
||||||
|
case MSP_codes.MSP_OSD_CONFIG:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Unknown code detected: ' + code);
|
console.log('Unknown code detected: ' + code);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1282,6 +1285,14 @@ var MSP = {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
promise: function(code, data) {
|
||||||
|
var self = this;
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
self.send_message(code, data, false, function(data) {
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
callbacks_cleanup: function () {
|
callbacks_cleanup: function () {
|
||||||
for (var i = 0; i < this.callbacks.length; i++) {
|
for (var i = 0; i < this.callbacks.length; i++) {
|
||||||
clearInterval(this.callbacks[i].timer);
|
clearInterval(this.callbacks[i].timer);
|
||||||
|
|
|
@ -217,8 +217,10 @@ function onOpen(openInfo) {
|
||||||
// continue as usually
|
// continue as usually
|
||||||
CONFIGURATOR.connectionValid = true;
|
CONFIGURATOR.connectionValid = true;
|
||||||
GUI.allowedTabs = GUI.defaultAllowedTabsWhenConnected.slice();
|
GUI.allowedTabs = GUI.defaultAllowedTabsWhenConnected.slice();
|
||||||
if (semver.lt(CONFIG.apiVersion, "1.4.0")) {
|
//TODO here we can remove led_strip tab from NAZE and CC3D at least!
|
||||||
GUI.allowedTabs.splice(GUI.allowedTabs.indexOf('led_strip'), 1);
|
//FIXME add real version here
|
||||||
|
if (false && semver.lt(CONFIG.flightControllerVersion, "1.4.0")) {
|
||||||
|
GUI.allowedTabs.splice(GUI.allowedTabs.indexOf('osd'), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
onConnect();
|
onConnect();
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<link type="text/css" rel="stylesheet" href="./tabs/auxiliary.css" media="all" />
|
<link type="text/css" rel="stylesheet" href="./tabs/auxiliary.css" media="all" />
|
||||||
<link type="text/css" rel="stylesheet" href="./tabs/failsafe.css" media="all" />
|
<link type="text/css" rel="stylesheet" href="./tabs/failsafe.css" media="all" />
|
||||||
<link type="text/css" rel="stylesheet" href="./tabs/transponder.css" media="all" />
|
<link type="text/css" rel="stylesheet" href="./tabs/transponder.css" media="all" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="./tabs/osd.css" media="all" />
|
||||||
<link type="text/css" rel="stylesheet" href="./css/opensans_webfontkit/fonts.css" media="all" />
|
<link type="text/css" rel="stylesheet" href="./css/opensans_webfontkit/fonts.css" media="all" />
|
||||||
<link type="text/css" rel="stylesheet" href="./css/dropdown-lists/css/style_lists.css" media="all" />
|
<link type="text/css" rel="stylesheet" href="./css/dropdown-lists/css/style_lists.css" media="all" />
|
||||||
<link type="text/css" rel="stylesheet" href="./js/libraries/switchery/switchery.css" media="all" />
|
<link type="text/css" rel="stylesheet" href="./js/libraries/switchery/switchery.css" media="all" />
|
||||||
|
@ -44,6 +45,9 @@
|
||||||
<script type="text/javascript" src="./js/libraries/semver.js"></script>
|
<script type="text/javascript" src="./js/libraries/semver.js"></script>
|
||||||
<script type="text/javascript" src="./js/libraries/jbox/jBox.min.js"></script>
|
<script type="text/javascript" src="./js/libraries/jbox/jBox.min.js"></script>
|
||||||
<script type="text/javascript" src="./js/libraries/switchery/switchery.js"></script>
|
<script type="text/javascript" src="./js/libraries/switchery/switchery.js"></script>
|
||||||
|
<script type="text/javascript" src="./js/libraries/jquery.ba-throttle-debounce.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./js/libraries/inflection.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./js/injected_methods.js"></script>
|
||||||
<script type="text/javascript" src="./js/port_handler.js"></script>
|
<script type="text/javascript" src="./js/port_handler.js"></script>
|
||||||
<script type="text/javascript" src="./js/port_usage.js"></script>
|
<script type="text/javascript" src="./js/port_usage.js"></script>
|
||||||
<script type="text/javascript" src="./js/serial.js"></script>
|
<script type="text/javascript" src="./js/serial.js"></script>
|
||||||
|
@ -80,6 +84,7 @@
|
||||||
<script type="text/javascript" src="./tabs/firmware_flasher.js"></script>
|
<script type="text/javascript" src="./tabs/firmware_flasher.js"></script>
|
||||||
<script type="text/javascript" src="./tabs/failsafe.js"></script>
|
<script type="text/javascript" src="./tabs/failsafe.js"></script>
|
||||||
<script type="text/javascript" src="./tabs/transponder.js"></script>
|
<script type="text/javascript" src="./tabs/transponder.js"></script>
|
||||||
|
<script type="text/javascript" src="./tabs/osd.js"></script>
|
||||||
<title></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -217,6 +222,7 @@
|
||||||
<li class="tab_servos"><a href="#" i18n="tabServos" class="tabicon ic_servo" title="Servos"></a></li>
|
<li class="tab_servos"><a href="#" i18n="tabServos" class="tabicon ic_servo" title="Servos"></a></li>
|
||||||
<li class="tab_gps"><a href="#" i18n="tabGPS" class="tabicon ic_gps" title="GPS"></a></li>
|
<li class="tab_gps"><a href="#" i18n="tabGPS" class="tabicon ic_gps" title="GPS"></a></li>
|
||||||
<li class="tab_motors"><a href="#" i18n="tabMotorTesting" class="tabicon ic_motor" title="Motors"></a></li>
|
<li class="tab_motors"><a href="#" i18n="tabMotorTesting" class="tabicon ic_motor" title="Motors"></a></li>
|
||||||
|
<li class="tab_osd"><a href="#" i18n="tabOSD" class="tabicon ic_osd" title="OSD"></a></li>
|
||||||
<li class="tab_transponder"><a href="#" i18n="tabTransponder" class="tabicon ic_transponder" title="Transponder"></a></li>
|
<li class="tab_transponder"><a href="#" i18n="tabTransponder" class="tabicon ic_transponder" title="Transponder"></a></li>
|
||||||
<li class="tab_led_strip"><a href="#" i18n="tabLedStrip" class="tabicon ic_led" title="LED Strip"></a></li>
|
<li class="tab_led_strip"><a href="#" i18n="tabLedStrip" class="tabicon ic_led" title="LED Strip"></a></li>
|
||||||
<li class="tab_sensors"><a href="#" i18n="tabRawSensorData" class="tabicon ic_sensors" title="Sensors"></a></li>
|
<li class="tab_sensors"><a href="#" i18n="tabRawSensorData" class="tabicon ic_sensors" title="Sensors"></a></li>
|
||||||
|
|
4
main.js
4
main.js
|
@ -1,3 +1,4 @@
|
||||||
|
/*global $, chrome*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Google Analytics
|
// Google Analytics
|
||||||
|
@ -163,6 +164,9 @@ $(document).ready(function () {
|
||||||
case 'motors':
|
case 'motors':
|
||||||
TABS.motors.initialize(content_ready);
|
TABS.motors.initialize(content_ready);
|
||||||
break;
|
break;
|
||||||
|
case 'osd':
|
||||||
|
TABS.osd.initialize(content_ready);
|
||||||
|
break;
|
||||||
case 'sensors':
|
case 'sensors':
|
||||||
TABS.sensors.initialize(content_ready);
|
TABS.sensors.initialize(content_ready);
|
||||||
break;
|
break;
|
||||||
|
|
16385
resources/osd/bold.mcm
Normal file
16385
resources/osd/bold.mcm
Normal file
File diff suppressed because it is too large
Load diff
16385
resources/osd/default.mcm
Normal file
16385
resources/osd/default.mcm
Normal file
File diff suppressed because it is too large
Load diff
16385
resources/osd/large.mcm
Normal file
16385
resources/osd/large.mcm
Normal file
File diff suppressed because it is too large
Load diff
460
tabs/osd.css
Normal file
460
tabs/osd.css
Normal file
|
@ -0,0 +1,460 @@
|
||||||
|
.tab-osd .info {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .info .progressLabel {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 26px;
|
||||||
|
top: 0px;
|
||||||
|
left: 0;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 24px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
/* text-shadow: 1px 0px 2px rgba(0, 0, 0, 0.9);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.darkgrey {
|
||||||
|
background-color: #575757;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .spacer_box_title {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .info {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progressLabel a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progressLabel a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress {
|
||||||
|
width: 100%;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress::-webkit-progress-bar {
|
||||||
|
background-color: #4f4f4f;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: inset 0px 0px 5px #2f2f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress::-webkit-progress-value {
|
||||||
|
background-color: #F86008;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress.valid::-webkit-progress-bar {
|
||||||
|
background-color: #56ac1d;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress.valid::-webkit-progress-value {
|
||||||
|
background-color: #56ac1d;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress.invalid::-webkit-progress-bar {
|
||||||
|
background-color: #A62E32;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .progress.invalid::-webkit-progress-value {
|
||||||
|
background-color: #A62E32;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd ul li {
|
||||||
|
list-style: initial;
|
||||||
|
list-style-type: circle;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options label input {
|
||||||
|
float: left;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options label span {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options select {
|
||||||
|
width: 300px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options .releases select {
|
||||||
|
width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .option.releases {
|
||||||
|
margin: 0 0 2px 0;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options .description {
|
||||||
|
position: relative;
|
||||||
|
left: 0px;
|
||||||
|
font-style: italic;
|
||||||
|
color: #818181;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .cf_table td:last-child {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options .flash_on_connect_wrapper {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .options .manual_baud_rate select {
|
||||||
|
width: 75px;
|
||||||
|
margin-left: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info .title {
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
border-bottom: 1px solid silver;
|
||||||
|
background-color: #3f4241;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info .target {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info p {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info p a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info p a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .release_info .notes {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .git_info {
|
||||||
|
display: none;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 1px solid silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .git_info .title {
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
border-bottom: 1px solid silver;
|
||||||
|
background-color: #3f4241;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .git_info p {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .git_info p a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .git_info p a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
margin-top: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons a {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
padding: 0 15px 0 15px;
|
||||||
|
height: 28px;
|
||||||
|
line-height: 28px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid silver;
|
||||||
|
background-color: #ececec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons a:hover {
|
||||||
|
background-color: #dedcdc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons a.flash_font.locked {
|
||||||
|
background-color: #b8b8b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons a.flash_font.locked:hover {
|
||||||
|
cursor: default;
|
||||||
|
background-color: #b8b8b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons a.load_remote_file.locked {
|
||||||
|
background-color: #b8b8b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons a.load_remote_file.locked:hover {
|
||||||
|
cursor: default;
|
||||||
|
background-color: #b8b8b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .buttons .back {
|
||||||
|
float: right;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .btn .disabled {
|
||||||
|
cursor: default;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #AFAFAF;
|
||||||
|
border: none;
|
||||||
|
pointer-events: none;
|
||||||
|
text-shadow: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-layout label {
|
||||||
|
margin: .25em .1em;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-layout input {
|
||||||
|
margin: .1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-layout input.position{
|
||||||
|
width: 5em;
|
||||||
|
border-bottom: 1px solid #ccc
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .note {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .col {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .right {
|
||||||
|
float: right;
|
||||||
|
margin-top: -7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview .gui_box_titlebar {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview .char {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .char.mouseover {
|
||||||
|
background: rgba(255,255,255,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .char.dragging {
|
||||||
|
background: rgba(255,255,255,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .char-label.mouseover {
|
||||||
|
background: rgba(255,255,255,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview .char[draggable="true"] {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview-logo {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview .row {
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .content_wrapper {
|
||||||
|
height: calc(100% - 41px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .content_toolbar {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .content_toolbar button {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 4px 10px !important;
|
||||||
|
font-family: 'open_sanssemibold', Arial;
|
||||||
|
font-size: 9pt !important;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fontbuttons {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
right: 1.2em;
|
||||||
|
top: .8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-field {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-field.mouseover {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-field input {
|
||||||
|
float: right;
|
||||||
|
width: 50px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding:2px;
|
||||||
|
margin-top: -2px;
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-field label {
|
||||||
|
margin-left: 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .display-fields {
|
||||||
|
float: left;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer_box_title span {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: 'open_sansregular', 'Segoe UI', Tahoma, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer_box div input {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer_box div label {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tab-osd .display-field:last-child {
|
||||||
|
border-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview {
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .preview {
|
||||||
|
/* please don't copy the generic background image from another project
|
||||||
|
* and replace the one that @nathantsoi took :)
|
||||||
|
*/
|
||||||
|
background: url(/images/osd-bg-1.jpg);
|
||||||
|
background-size: cover;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .alarms label {
|
||||||
|
display: block;
|
||||||
|
width:100%;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin-top:5px;
|
||||||
|
padding-bottom: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .alarms label:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-osd .alarms input {
|
||||||
|
width: 55px;
|
||||||
|
padding-left: 3px;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: left;
|
||||||
|
border: 1px solid silver;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-right: 11px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1055px) , only screen and (max-device-width: 1055px) {
|
||||||
|
.tab-osd .content_wrapper {
|
||||||
|
height: calc(100% - 30px);
|
||||||
|
}
|
||||||
|
}
|
127
tabs/osd.html
Normal file
127
tabs/osd.html
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
<div class="tab-osd toolbar_fixed_bottom">
|
||||||
|
<div class="content_wrapper">
|
||||||
|
<h1 class="tab_title">
|
||||||
|
OSD
|
||||||
|
</h1>
|
||||||
|
<div class="cf_doc_version_bt">
|
||||||
|
<a id="button-documentation" href="" target="_blank"></a>
|
||||||
|
</div>
|
||||||
|
<div class="unsupported hide">
|
||||||
|
<p class="note">Your flight controller isn't responding to OSD commands. This probably means that it does not have an integrated BetaFlight OSD.</p>
|
||||||
|
<p class="note">Note that some flight controllers have an onboard <a href="https://www.youtube.com/watch?v=ikKH_6SQ-Tk" target="_blank">MinimOSD</a> that can be flashed and configured with <a href="https://github.com/ShikOfTheRa/scarab-osd/releases/latest" target="_blank">scarab-osd</a>, however the MinimOSD cannot be configured through this interface.</p>
|
||||||
|
</div>
|
||||||
|
<div class="supported hide">
|
||||||
|
<div class="cf_column third_left elements">
|
||||||
|
<div class="spacer_right">
|
||||||
|
<div class="gui_box grey">
|
||||||
|
<div
|
||||||
|
class="gui_box_titlebar"
|
||||||
|
style="margin-bottom: 0px;">
|
||||||
|
<div class="spacer_box_title">
|
||||||
|
Elements
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="display-fields"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cf_column twothird">
|
||||||
|
<div class="gui_box grey preview" style="float: left;">
|
||||||
|
<div class="gui_box_titlebar image">
|
||||||
|
<div class="spacer_box_title">
|
||||||
|
Preview <span>(drag to change position)</span><span class="preview-logo cf_tip" title="Show or hide the logo in the preview window. This will not change any settings on the flight controller."></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="display-layout">
|
||||||
|
<div class="col right">
|
||||||
|
<div class="preview">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cf_column third_right" style="width: calc(100% - 377px);">
|
||||||
|
<div class="gui_box grey">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title">Video
|
||||||
|
Format
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="video-types"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gui_box grey units-container" style="display:none;">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title">Units
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="units"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gui_box grey alarms-container" style="display:none;">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title">
|
||||||
|
Alarms
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="alarms"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gui_box grey" style="display:none;">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title">VTX
|
||||||
|
Settings
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="vtx-settings"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gui_box grey" style="display:none;">
|
||||||
|
<div class="gui_box_titlebar">
|
||||||
|
<div class="spacer_box_title">Craft Name
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_box">
|
||||||
|
<div class="callsign"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="fontmanagercontent" style="display:none; width:600px;">
|
||||||
|
<div class="font-picker" style="margin-bottom: 10px;">
|
||||||
|
<h1 class="tab_title">Font presets:</h1>
|
||||||
|
<div class="content_wrapper font-preview"></div>
|
||||||
|
<div class="fontbuttons">
|
||||||
|
<button data-font-file="default">Default</button>
|
||||||
|
<button data-font-file="bold">Bold</button>
|
||||||
|
<button data-font-file="large">Large</button>
|
||||||
|
<button class="load_font_file">Open Font File</button>
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<a name="progressbar"></a>
|
||||||
|
<progress class="progress" value="0" min="0" max="100"></progress>
|
||||||
|
<div class="progressLabel" style="margin-top: -21px; width: 95%; text-align: center; color: white; position: absolute;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="default_btn green" style="width:100%; float:left; margin-bottom: 0px;
|
||||||
|
">
|
||||||
|
<a class="flash_font active">Upload Font</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clear-both"></div>
|
||||||
|
<div class="content_toolbar supported hide" style="left:0;">
|
||||||
|
<div class="btn">
|
||||||
|
<a class="active save" href="#" >Save</a>
|
||||||
|
</div>
|
||||||
|
<div class="btn">
|
||||||
|
<a class="fonts" id="fontmanager" href="#" >Font Manager</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
923
tabs/osd.js
Normal file
923
tabs/osd.js
Normal file
|
@ -0,0 +1,923 @@
|
||||||
|
/*global $*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var SYM = SYM || {};
|
||||||
|
SYM.VOLT = 0x06;
|
||||||
|
SYM.RSSI = 0x01;
|
||||||
|
SYM.AH_RIGHT = 0x02;
|
||||||
|
SYM.AH_LEFT = 0x03;
|
||||||
|
SYM.THR = 0x04;
|
||||||
|
SYM.THR1 = 0x05;
|
||||||
|
SYM.FLY_M = 0x9C;
|
||||||
|
SYM.ON_M = 0x9B;
|
||||||
|
SYM.AH_CENTER_LINE = 0x26;
|
||||||
|
SYM.AH_CENTER_LINE_RIGHT = 0x27;
|
||||||
|
SYM.AH_CENTER = 0x7E;
|
||||||
|
SYM.AH_BAR9_0 = 0x80;
|
||||||
|
SYM.AH_DECORATION = 0x13;
|
||||||
|
SYM.LOGO = 0xA0;
|
||||||
|
SYM.AMP = 0x9A;
|
||||||
|
SYM.MAH = 0x07;
|
||||||
|
SYM.METRE = 0xC;
|
||||||
|
SYM.FEET = 0xF;
|
||||||
|
SYM.GPS_SAT = 0x1F;
|
||||||
|
|
||||||
|
|
||||||
|
var FONT = FONT || {};
|
||||||
|
|
||||||
|
//FIXME This is hack!
|
||||||
|
var MSPCodes = MSP_codes;
|
||||||
|
|
||||||
|
FONT.initData = function () {
|
||||||
|
if (FONT.data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FONT.data = {
|
||||||
|
// default font file name
|
||||||
|
loaded_font_file: 'default',
|
||||||
|
// array of arry of image bytes ready to upload to fc
|
||||||
|
characters_bytes: [],
|
||||||
|
// array of array of image bits by character
|
||||||
|
characters: [],
|
||||||
|
// an array of base64 encoded image strings by character
|
||||||
|
character_image_urls: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FONT.constants = {
|
||||||
|
SIZES: {
|
||||||
|
/** NVM ram size for one font char, actual character bytes **/
|
||||||
|
MAX_NVM_FONT_CHAR_SIZE: 54,
|
||||||
|
/** NVM ram field size for one font char, last 10 bytes dont matter **/
|
||||||
|
MAX_NVM_FONT_CHAR_FIELD_SIZE: 64,
|
||||||
|
CHAR_HEIGHT: 18,
|
||||||
|
CHAR_WIDTH: 12,
|
||||||
|
LINE: 30
|
||||||
|
},
|
||||||
|
COLORS: {
|
||||||
|
// black
|
||||||
|
0: 'rgba(0, 0, 0, 1)',
|
||||||
|
// also the value 3, could yield transparent according to
|
||||||
|
// https://www.sparkfun.com/datasheets/BreakoutBoards/MAX7456.pdf
|
||||||
|
1: 'rgba(255, 255, 255, 0)',
|
||||||
|
// white
|
||||||
|
2: 'rgba(255,255,255, 1)'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each line is composed of 8 asci 1 or 0, representing 1 bit each for a total of 1 byte per line
|
||||||
|
*/
|
||||||
|
FONT.parseMCMFontFile = function (data) {
|
||||||
|
var data = data.split("\n");
|
||||||
|
// clear local data
|
||||||
|
FONT.data.characters.length = 0;
|
||||||
|
FONT.data.characters_bytes.length = 0;
|
||||||
|
FONT.data.character_image_urls.length = 0;
|
||||||
|
// make sure the font file is valid
|
||||||
|
if (data.shift().trim() != 'MAX7456') {
|
||||||
|
var msg = 'that font file doesnt have the MAX7456 header, giving up';
|
||||||
|
console.debug(msg);
|
||||||
|
Promise.reject(msg);
|
||||||
|
}
|
||||||
|
var character_bits = [];
|
||||||
|
var character_bytes = [];
|
||||||
|
// hexstring is for debugging
|
||||||
|
FONT.data.hexstring = [];
|
||||||
|
var pushChar = function () {
|
||||||
|
FONT.data.characters_bytes.push(character_bytes);
|
||||||
|
FONT.data.characters.push(character_bits);
|
||||||
|
FONT.draw(FONT.data.characters.length - 1);
|
||||||
|
//$log.debug('parsed char ', i, ' as ', character);
|
||||||
|
character_bits = [];
|
||||||
|
character_bytes = [];
|
||||||
|
};
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
var line = data[i];
|
||||||
|
// hexstring is for debugging
|
||||||
|
FONT.data.hexstring.push('0x' + parseInt(line, 2).toString(16));
|
||||||
|
// every 64 bytes (line) is a char, we're counting chars though, which are 2 bits
|
||||||
|
if (character_bits.length == FONT.constants.SIZES.MAX_NVM_FONT_CHAR_FIELD_SIZE * (8 / 2)) {
|
||||||
|
pushChar()
|
||||||
|
}
|
||||||
|
for (var y = 0; y < 8; y = y + 2) {
|
||||||
|
var v = parseInt(line.slice(y, y + 2), 2);
|
||||||
|
character_bits.push(v);
|
||||||
|
}
|
||||||
|
character_bytes.push(parseInt(line, 2));
|
||||||
|
}
|
||||||
|
// push the last char
|
||||||
|
pushChar();
|
||||||
|
return FONT.data.characters;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FONT.openFontFile = function ($preview) {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: [
|
||||||
|
{extensions: ['mcm']}
|
||||||
|
]}, function (fileEntry) {
|
||||||
|
FONT.data.loaded_font_file = fileEntry.name;
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error(chrome.runtime.lastError.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fileEntry.file(function (file) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onloadend = function (e) {
|
||||||
|
if (e.total != 0 && e.total == e.loaded) {
|
||||||
|
FONT.parseMCMFontFile(e.target.result);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error('could not load whole font file');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a canvas image with the character on it
|
||||||
|
*/
|
||||||
|
var drawCanvas = function (charAddress) {
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
// TODO: do we want to be able to set pixel size? going to try letting the consumer scale the image.
|
||||||
|
var pixelSize = pixelSize || 1;
|
||||||
|
var width = pixelSize * FONT.constants.SIZES.CHAR_WIDTH;
|
||||||
|
var height = pixelSize * FONT.constants.SIZES.CHAR_HEIGHT;
|
||||||
|
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
|
||||||
|
for (var y = 0; y < height; y++) {
|
||||||
|
for (var x = 0; x < width; x++) {
|
||||||
|
if (!(charAddress in FONT.data.characters)) {
|
||||||
|
console.log('charAddress', charAddress, ' is not in ', FONT.data.characters.length);
|
||||||
|
}
|
||||||
|
var v = FONT.data.characters[charAddress][(y * width) + x];
|
||||||
|
ctx.fillStyle = FONT.constants.COLORS[v];
|
||||||
|
ctx.fillRect(x, y, pixelSize, pixelSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return canvas;
|
||||||
|
};
|
||||||
|
|
||||||
|
FONT.draw = function (charAddress) {
|
||||||
|
var cached = FONT.data.character_image_urls[charAddress];
|
||||||
|
if (!cached) {
|
||||||
|
cached = FONT.data.character_image_urls[charAddress] = drawCanvas(charAddress).toDataURL('image/png');
|
||||||
|
}
|
||||||
|
return cached;
|
||||||
|
};
|
||||||
|
|
||||||
|
FONT.msp = {
|
||||||
|
encode: function (charAddress) {
|
||||||
|
return [charAddress].concat(FONT.data.characters_bytes[charAddress].slice(0, FONT.constants.SIZES.MAX_NVM_FONT_CHAR_SIZE));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FONT.upload = function ($progress) {
|
||||||
|
return Promise.mapSeries(FONT.data.characters, function (data, i) {
|
||||||
|
$progress.val((i / FONT.data.characters.length) * 100);
|
||||||
|
return MSP.promise(MSPCodes.MSP_OSD_CHAR_WRITE, FONT.msp.encode(i));
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
OSD.GUI.jbox.close();
|
||||||
|
return MSP.promise(MSPCodes.MSP_SET_REBOOT);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
FONT.preview = function ($el) {
|
||||||
|
$el.empty()
|
||||||
|
for (var i = 0; i < SYM.LOGO; i++) {
|
||||||
|
var url = FONT.data.character_image_urls[i];
|
||||||
|
$el.append('<img src="' + url + '" title="0x' + i.toString(16) + '"></img>');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FONT.symbol = function (hexVal) {
|
||||||
|
return String.fromCharCode(hexVal);
|
||||||
|
};
|
||||||
|
|
||||||
|
var OSD = OSD || {};
|
||||||
|
|
||||||
|
// parsed fc output and output to fc, used by to OSD.msp.encode
|
||||||
|
OSD.initData = function () {
|
||||||
|
OSD.data = {
|
||||||
|
video_system: null,
|
||||||
|
unit_mode: null,
|
||||||
|
alarms: [],
|
||||||
|
display_items: [],
|
||||||
|
last_positions: {},
|
||||||
|
preview_logo: false,
|
||||||
|
preview: []
|
||||||
|
};
|
||||||
|
};
|
||||||
|
OSD.initData();
|
||||||
|
|
||||||
|
OSD.constants = {
|
||||||
|
VISIBLE: 0x0800,
|
||||||
|
VIDEO_TYPES: [
|
||||||
|
'AUTO',
|
||||||
|
'PAL',
|
||||||
|
'NTSC'
|
||||||
|
],
|
||||||
|
VIDEO_LINES: {
|
||||||
|
PAL: 16,
|
||||||
|
NTSC: 13
|
||||||
|
},
|
||||||
|
VIDEO_BUFFER_CHARS: {
|
||||||
|
PAL: 480,
|
||||||
|
NTSC: 390
|
||||||
|
},
|
||||||
|
UNIT_TYPES: [
|
||||||
|
'IMPERIAL',
|
||||||
|
'METRIC'
|
||||||
|
],
|
||||||
|
AHISIDEBARWIDTHPOSITION: 7,
|
||||||
|
AHISIDEBARHEIGHTPOSITION: 3,
|
||||||
|
|
||||||
|
// All display fields, from every version, do not remove elements, only add!
|
||||||
|
ALL_DISPLAY_FIELDS: {
|
||||||
|
MAIN_BATT_VOLTAGE: {
|
||||||
|
name: 'MAIN_BATT_VOLTAGE',
|
||||||
|
default_position: -29,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.VOLT) + '16.8'
|
||||||
|
},
|
||||||
|
RSSI_VALUE: {
|
||||||
|
name: 'RSSI_VALUE',
|
||||||
|
default_position: -59,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.RSSI) + '99'
|
||||||
|
},
|
||||||
|
TIMER: {
|
||||||
|
name: 'TIMER',
|
||||||
|
default_position: -39,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.ON_M) + ' 11:11'
|
||||||
|
},
|
||||||
|
THROTTLE_POSITION: {
|
||||||
|
name: 'THROTTLE_POSITION',
|
||||||
|
default_position: -9,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.THR) + FONT.symbol(SYM.THR1) + ' 69'
|
||||||
|
},
|
||||||
|
CPU_LOAD: {
|
||||||
|
name: 'CPU_LOAD',
|
||||||
|
default_position: 26,
|
||||||
|
positionable: true,
|
||||||
|
preview: '15'
|
||||||
|
},
|
||||||
|
VTX_CHANNEL: {
|
||||||
|
name: 'VTX_CHANNEL',
|
||||||
|
default_position: 1,
|
||||||
|
positionable: true,
|
||||||
|
preview: 'CH:1'
|
||||||
|
},
|
||||||
|
VOLTAGE_WARNING: {
|
||||||
|
name: 'VOLTAGE_WARNING',
|
||||||
|
default_position: -80,
|
||||||
|
positionable: true,
|
||||||
|
preview: 'LOW VOLTAGE'
|
||||||
|
},
|
||||||
|
ARMED: {
|
||||||
|
name: 'ARMED',
|
||||||
|
default_position: -107,
|
||||||
|
positionable: true,
|
||||||
|
preview: 'ARMED'
|
||||||
|
},
|
||||||
|
DISARMED: {
|
||||||
|
name: 'DISARMED',
|
||||||
|
default_position: -109,
|
||||||
|
positionable: true,
|
||||||
|
preview: 'DISARMED'
|
||||||
|
},
|
||||||
|
CROSSHAIRS: {
|
||||||
|
name: 'CROSSHAIRS',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: false
|
||||||
|
},
|
||||||
|
ARTIFICIAL_HORIZON: {
|
||||||
|
name: 'ARTIFICIAL_HORIZON',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: false
|
||||||
|
},
|
||||||
|
HORIZON_SIDEBARS: {
|
||||||
|
name: 'HORIZON_SIDEBARS',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: false
|
||||||
|
},
|
||||||
|
CURRENT_DRAW: {
|
||||||
|
name: 'CURRENT_DRAW',
|
||||||
|
default_position: -23,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.AMP) + '42.0'
|
||||||
|
},
|
||||||
|
MAH_DRAWN: {
|
||||||
|
name: 'MAH_DRAWN',
|
||||||
|
default_position: -18,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.MAH) + '690'
|
||||||
|
},
|
||||||
|
CRAFT_NAME: {
|
||||||
|
name: 'CRAFT_NAME',
|
||||||
|
default_position: -77,
|
||||||
|
positionable: true,
|
||||||
|
preview: '[CRAFT_NAME]'
|
||||||
|
},
|
||||||
|
ALTITUDE: {
|
||||||
|
name: 'ALTITUDE',
|
||||||
|
default_position: 62,
|
||||||
|
positionable: true,
|
||||||
|
preview: function (osd_data) {
|
||||||
|
return '399.7' + FONT.symbol(osd_data.unit_mode === 0 ? SYM.FEET : SYM.METRE)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ONTIME: {
|
||||||
|
name: 'ONTIME',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.ON_M) + ' 4:11'
|
||||||
|
},
|
||||||
|
FLYTIME: {
|
||||||
|
name: 'FLYTIME',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.FLY_M) + ' 4:11'
|
||||||
|
},
|
||||||
|
FLYMODE: {
|
||||||
|
name: 'FLYMODE',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: true,
|
||||||
|
preview: 'STAB'
|
||||||
|
},
|
||||||
|
GPS_SPEED: {
|
||||||
|
name: 'GPS_SPEED',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: true,
|
||||||
|
preview: '40'
|
||||||
|
},
|
||||||
|
GPS_SATS: {
|
||||||
|
name: 'GPS_SATS',
|
||||||
|
default_position: -1,
|
||||||
|
positionable: true,
|
||||||
|
preview: FONT.symbol(SYM.GPS_SAT) + '14'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pick display fields by version, order matters, so these are going in an array... pry could iterate the example map instead
|
||||||
|
OSD.chooseFields = function () {
|
||||||
|
var F = OSD.constants.ALL_DISPLAY_FIELDS;
|
||||||
|
OSD.constants.DISPLAY_FIELDS = [
|
||||||
|
F.RSSI_VALUE,
|
||||||
|
F.MAIN_BATT_VOLTAGE,
|
||||||
|
F.CROSSHAIRS,
|
||||||
|
F.ARTIFICIAL_HORIZON,
|
||||||
|
F.HORIZON_SIDEBARS,
|
||||||
|
F.ONTIME,
|
||||||
|
F.FLYTIME,
|
||||||
|
F.FLYMODE,
|
||||||
|
F.CRAFT_NAME,
|
||||||
|
F.THROTTLE_POSITION,
|
||||||
|
F.VTX_CHANNEL,
|
||||||
|
F.CURRENT_DRAW,
|
||||||
|
F.MAH_DRAWN,
|
||||||
|
F.GPS_SPEED,
|
||||||
|
F.GPS_SATS,
|
||||||
|
F.ALTITUDE
|
||||||
|
]
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD.updateDisplaySize = function () {
|
||||||
|
var video_type = OSD.constants.VIDEO_TYPES[OSD.data.video_system];
|
||||||
|
if (video_type == 'AUTO') {
|
||||||
|
video_type = 'PAL';
|
||||||
|
}
|
||||||
|
// compute the size
|
||||||
|
OSD.data.display_size = {
|
||||||
|
x: FONT.constants.SIZES.LINE,
|
||||||
|
y: OSD.constants.VIDEO_LINES[video_type],
|
||||||
|
total: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OSD.msp = {
|
||||||
|
/**
|
||||||
|
* Note, unsigned 16 bit int for position ispacked:
|
||||||
|
* 0: unused
|
||||||
|
* v: visible flag
|
||||||
|
* b: blink flag
|
||||||
|
* y: y coordinate
|
||||||
|
* x: x coordinate
|
||||||
|
* 0000 vbyy yyyx xxxx
|
||||||
|
*/
|
||||||
|
helpers: {
|
||||||
|
unpack: {
|
||||||
|
position: function (bits, c) {
|
||||||
|
var display_item = {};
|
||||||
|
// size * y + x
|
||||||
|
display_item.position = FONT.constants.SIZES.LINE * ((bits >> 5) & 0x001F) + (bits & 0x001F);
|
||||||
|
display_item.isVisible = (bits & OSD.constants.VISIBLE) != 0;
|
||||||
|
return display_item;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pack: {
|
||||||
|
position: function (display_item) {
|
||||||
|
var isVisible = display_item.isVisible;
|
||||||
|
var position = display_item.position;
|
||||||
|
return (isVisible ? 0x0800 : 0) | (((position / FONT.constants.SIZES.LINE) & 0x001F) << 5) | (position % FONT.constants.SIZES.LINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
encodeOther: function () {
|
||||||
|
var result = [-1, OSD.data.video_system];
|
||||||
|
result.push8(OSD.data.unit_mode);
|
||||||
|
// watch out, order matters! match the firmware
|
||||||
|
result.push8(OSD.data.alarms.rssi.value);
|
||||||
|
result.push16(OSD.data.alarms.cap.value);
|
||||||
|
result.push16(OSD.data.alarms.time.value);
|
||||||
|
result.push16(OSD.data.alarms.alt.value);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
encode: function (display_item) {
|
||||||
|
var buffer = [];
|
||||||
|
buffer.push8(display_item.index);
|
||||||
|
buffer.push16(this.helpers.pack.position(display_item));
|
||||||
|
return buffer;
|
||||||
|
},
|
||||||
|
// Currently only parses MSP_MAX_OSD responses, add a switch on payload.code if more codes are handled
|
||||||
|
decode: function (payload) {
|
||||||
|
var view = payload.data;
|
||||||
|
var d = OSD.data;
|
||||||
|
d.compiled_in = view.readU8();
|
||||||
|
d.video_system = view.readU8();
|
||||||
|
|
||||||
|
d.unit_mode = view.readU8();
|
||||||
|
d.alarms = {};
|
||||||
|
d.alarms['rssi'] = { display_name: 'Rssi', value: view.readU8() };
|
||||||
|
d.alarms['cap'] = { display_name: 'Capacity', value: view.readU16() };
|
||||||
|
d.alarms['time'] = { display_name: 'Minutes', value: view.readU16() };
|
||||||
|
d.alarms['alt'] = { display_name: 'Altitude', value: view.readU16() };
|
||||||
|
|
||||||
|
d.display_items = [];
|
||||||
|
// start at the offset from the other fields
|
||||||
|
while (view.offset < view.byteLength) {
|
||||||
|
var v = null;
|
||||||
|
v = view.readU16();
|
||||||
|
|
||||||
|
var j = d.display_items.length;
|
||||||
|
var c = OSD.constants.DISPLAY_FIELDS[j];
|
||||||
|
if (c) {
|
||||||
|
d.display_items.push($.extend({
|
||||||
|
name: c.name,
|
||||||
|
index: j,
|
||||||
|
positionable: c.positionable,
|
||||||
|
preview: typeof(c.preview) === 'function' ? c.preview(d) : c.preview
|
||||||
|
}, this.helpers.unpack.position(v, c)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OSD.updateDisplaySize();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OSD.GUI = {};
|
||||||
|
OSD.GUI.preview = {
|
||||||
|
onMouseEnter: function () {
|
||||||
|
if (!$(this).data('field')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('.field-' + $(this).data('field').index).addClass('mouseover')
|
||||||
|
},
|
||||||
|
onMouseLeave: function () {
|
||||||
|
if (!$(this).data('field')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('.field-' + $(this).data('field').index).removeClass('mouseover')
|
||||||
|
},
|
||||||
|
onDragStart: function (e) {
|
||||||
|
var ev = e.originalEvent;
|
||||||
|
ev.dataTransfer.setData("text/plain", $(ev.target).data('field').index);
|
||||||
|
ev.dataTransfer.setDragImage($(this).data('field').preview_img, 6, 9);
|
||||||
|
},
|
||||||
|
onDragOver: function (e) {
|
||||||
|
var ev = e.originalEvent;
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.dataTransfer.dropEffect = "move";
|
||||||
|
$(this).css({
|
||||||
|
background: 'rgba(0,0,0,.5)'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onDragLeave: function (e) {
|
||||||
|
// brute force unstyling on drag leave
|
||||||
|
$(this).removeAttr('style');
|
||||||
|
},
|
||||||
|
onDrop: function (e) {
|
||||||
|
var ev = e.originalEvent;
|
||||||
|
var position = $(this).removeAttr('style').data('position');
|
||||||
|
var field_id = parseInt(ev.dataTransfer.getData('text'))
|
||||||
|
var display_item = OSD.data.display_items[field_id];
|
||||||
|
var overflows_line = FONT.constants.SIZES.LINE - ((position % FONT.constants.SIZES.LINE) + display_item.preview.length);
|
||||||
|
if (overflows_line < 0) {
|
||||||
|
position += overflows_line;
|
||||||
|
}
|
||||||
|
$('input.' + field_id + '.position').val(position).change();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TABS.osd = {};
|
||||||
|
TABS.osd.initialize = function (callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (GUI.active_tab != 'osd') {
|
||||||
|
GUI.active_tab = 'osd';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#content').load("./tabs/osd.html", function () {
|
||||||
|
// translate to user-selected language
|
||||||
|
localize();
|
||||||
|
|
||||||
|
// Open modal window
|
||||||
|
OSD.GUI.jbox = new jBox('Modal', {
|
||||||
|
width: 600,
|
||||||
|
height: 240,
|
||||||
|
closeButton: 'title',
|
||||||
|
animation: false,
|
||||||
|
attach: $('#fontmanager'),
|
||||||
|
title: 'OSD Font Manager',
|
||||||
|
content: $('#fontmanagercontent')
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2 way binding... sorta
|
||||||
|
function updateOsdView() {
|
||||||
|
// ask for the OSD config data
|
||||||
|
MSP.promise(MSPCodes.MSP_OSD_CONFIG)
|
||||||
|
.then(function (info) {
|
||||||
|
console.log(info);
|
||||||
|
OSD.chooseFields();
|
||||||
|
if (!info.length) {
|
||||||
|
$('.unsupported').fadeIn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('.supported').fadeIn();
|
||||||
|
OSD.msp.decode(info);
|
||||||
|
|
||||||
|
// show Betaflight logo in preview
|
||||||
|
var $previewLogo = $('.preview-logo').empty();
|
||||||
|
$previewLogo.append(
|
||||||
|
$('<label for="preview-logo">Logo: </label><input type="checkbox" name="preview-logo" class="togglesmall"></input>')
|
||||||
|
.attr('checked', OSD.data.preview_logo)
|
||||||
|
.change(function (e) {
|
||||||
|
OSD.data.preview_logo = $(this).attr('checked') == undefined;
|
||||||
|
updateOsdView();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// video mode
|
||||||
|
var $videoTypes = $('.video-types').empty();
|
||||||
|
for (var i = 0; i < OSD.constants.VIDEO_TYPES.length; i++) {
|
||||||
|
var type = OSD.constants.VIDEO_TYPES[i];
|
||||||
|
var $checkbox = $('<label/>').append($('<input name="video_system" type="radio"/>' + type + '</label>')
|
||||||
|
.prop('checked', i === OSD.data.video_system)
|
||||||
|
.data('type', type)
|
||||||
|
.data('type', i)
|
||||||
|
);
|
||||||
|
$videoTypes.append($checkbox);
|
||||||
|
}
|
||||||
|
$videoTypes.find(':radio').click(function (e) {
|
||||||
|
OSD.data.video_system = $(this).data('type');
|
||||||
|
MSP.promise(MSPCodes.MSP_SET_OSD_CONFIG, OSD.msp.encodeOther())
|
||||||
|
.then(function () {
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// units
|
||||||
|
$('.units-container').show();
|
||||||
|
var $unitMode = $('.units').empty();
|
||||||
|
for (var i = 0; i < OSD.constants.UNIT_TYPES.length; i++) {
|
||||||
|
var type = OSD.constants.UNIT_TYPES[i];
|
||||||
|
var $checkbox = $('<label/>').append($('<input name="unit_mode" type="radio"/>' + type + '</label>')
|
||||||
|
.prop('checked', i === OSD.data.unit_mode)
|
||||||
|
.data('type', type)
|
||||||
|
.data('type', i)
|
||||||
|
);
|
||||||
|
$unitMode.append($checkbox);
|
||||||
|
}
|
||||||
|
$unitMode.find(':radio').click(function (e) {
|
||||||
|
OSD.data.unit_mode = $(this).data('type');
|
||||||
|
MSP.promise(MSPCodes.MSP_SET_OSD_CONFIG, OSD.msp.encodeOther())
|
||||||
|
.then(function () {
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// alarms
|
||||||
|
$('.alarms-container').show();
|
||||||
|
var $alarms = $('.alarms').empty();
|
||||||
|
for (let k in OSD.data.alarms) {
|
||||||
|
var alarm = OSD.data.alarms[k];
|
||||||
|
var alarmInput = $('<input name="alarm" type="number" id="' + k + '"/>' + alarm.display_name + '</label>');
|
||||||
|
alarmInput.val(alarm.value);
|
||||||
|
alarmInput.blur(function (e) {
|
||||||
|
OSD.data.alarms[$(this)[0].id].value = $(this)[0].value;
|
||||||
|
MSP.promise(MSPCodes.MSP_SET_OSD_CONFIG, OSD.msp.encodeOther())
|
||||||
|
.then(function () {
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var $input = $('<label/>').append(alarmInput);
|
||||||
|
$alarms.append($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// display fields on/off and position
|
||||||
|
var $displayFields = $('.display-fields').empty();
|
||||||
|
for (let field of
|
||||||
|
OSD.data.display_items
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// versioning related, if the field doesn't exist at the current flight controller version, just skip it
|
||||||
|
if (!field.name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var checked = field.isVisible ? 'checked' : '';
|
||||||
|
var $field = $('<div class="display-field field-' + field.index + '"/>');
|
||||||
|
$field.append(
|
||||||
|
$('<input type="checkbox" name="' + field.name + '" class="togglesmall"></input>')
|
||||||
|
.data('field', field)
|
||||||
|
.attr('checked', field.isVisible)
|
||||||
|
.change(function (e) {
|
||||||
|
var field = $(this).data('field');
|
||||||
|
var $position = $(this).parent().find('.position.' + field.name);
|
||||||
|
field.isVisible = !field.isVisible;
|
||||||
|
if (field.isVisible) {
|
||||||
|
$position.show();
|
||||||
|
} else {
|
||||||
|
$position.hide();
|
||||||
|
}
|
||||||
|
MSP.promise(MSPCodes.MSP_SET_OSD_CONFIG, OSD.msp.encode(field))
|
||||||
|
.then(function () {
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
$field.append('<label for="' + field.name + '" class="char-label">' + inflection.titleize(field.name) + '</label>');
|
||||||
|
if (field.positionable && field.isVisible) {
|
||||||
|
$field.append(
|
||||||
|
$('<input type="number" class="' + field.index + ' position"></input>')
|
||||||
|
.data('field', field)
|
||||||
|
.val(field.position)
|
||||||
|
.change($.debounce(250, function (e) {
|
||||||
|
var field = $(this).data('field');
|
||||||
|
field.position = parseInt($(this).val());
|
||||||
|
MSP.promise(MSPCodes.MSP_SET_OSD_CONFIG, OSD.msp.encode(field))
|
||||||
|
.then(function () {
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$displayFields.append($field);
|
||||||
|
}
|
||||||
|
GUI.switchery();
|
||||||
|
// buffer the preview
|
||||||
|
OSD.data.preview = [];
|
||||||
|
OSD.data.display_size.total = OSD.data.display_size.x * OSD.data.display_size.y;
|
||||||
|
for (let field of
|
||||||
|
OSD.data.display_items
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// reset fields that somehow end up off the screen
|
||||||
|
if (field.position > OSD.data.display_size.total) {
|
||||||
|
field.position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear the buffer
|
||||||
|
for (var i = 0; i < OSD.data.display_size.total; i++) {
|
||||||
|
OSD.data.preview.push([null, ' '.charCodeAt(0)]);
|
||||||
|
}
|
||||||
|
// logo first, so it gets overwritten by subsequent elements
|
||||||
|
if (OSD.data.preview_logo) {
|
||||||
|
var x = 160;
|
||||||
|
for (var i = 1; i < 5; i++) {
|
||||||
|
for (var j = 3; j < 27; j++)
|
||||||
|
OSD.data.preview[i * 30 + j] = [
|
||||||
|
{name: 'LOGO', positionable: false},
|
||||||
|
x++
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// draw all the displayed items and the drag and drop preview images
|
||||||
|
for (let field of
|
||||||
|
OSD.data.display_items
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!field.preview || !field.isVisible) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var j = (field.position >= 0) ? field.position : field.position + OSD.data.display_size.total;
|
||||||
|
// create the preview image
|
||||||
|
field.preview_img = new Image();
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
// fill the screen buffer
|
||||||
|
for (var i = 0; i < field.preview.length; i++) {
|
||||||
|
var charCode = field.preview.charCodeAt(i);
|
||||||
|
OSD.data.preview[j++] = [field, charCode];
|
||||||
|
// draw the preview
|
||||||
|
var img = new Image();
|
||||||
|
img.src = FONT.draw(charCode);
|
||||||
|
ctx.drawImage(img, i * 12, 0);
|
||||||
|
}
|
||||||
|
field.preview_img.src = canvas.toDataURL('image/png');
|
||||||
|
}
|
||||||
|
var centerishPosition = 194;
|
||||||
|
// artificial horizon
|
||||||
|
if ($('input[name="ARTIFICIAL_HORIZON"]').prop('checked')) {
|
||||||
|
for (var i = 0; i < 9; i++) {
|
||||||
|
OSD.data.preview[centerishPosition - 4 + i] = SYM.AH_BAR9_0 + 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// crosshairs
|
||||||
|
if ($('input[name="CROSSHAIRS"]').prop('checked')) {
|
||||||
|
OSD.data.preview[centerishPosition - 1] = SYM.AH_CENTER_LINE;
|
||||||
|
OSD.data.preview[centerishPosition + 1] = SYM.AH_CENTER_LINE_RIGHT;
|
||||||
|
OSD.data.preview[centerishPosition] = SYM.AH_CENTER;
|
||||||
|
}
|
||||||
|
// sidebars
|
||||||
|
if ($('input[name="HORIZON_SIDEBARS"]').prop('checked')) {
|
||||||
|
var hudwidth = OSD.constants.AHISIDEBARWIDTHPOSITION;
|
||||||
|
var hudheight = OSD.constants.AHISIDEBARHEIGHTPOSITION;
|
||||||
|
for (var i = -hudheight; i <= hudheight; i++) {
|
||||||
|
OSD.data.preview[centerishPosition - hudwidth + (i * FONT.constants.SIZES.LINE)] = SYM.AH_DECORATION;
|
||||||
|
OSD.data.preview[centerishPosition + hudwidth + (i * FONT.constants.SIZES.LINE)] = SYM.AH_DECORATION;
|
||||||
|
}
|
||||||
|
// AH level indicators
|
||||||
|
OSD.data.preview[centerishPosition - hudwidth + 1] = SYM.AH_LEFT;
|
||||||
|
OSD.data.preview[centerishPosition + hudwidth - 1] = SYM.AH_RIGHT;
|
||||||
|
}
|
||||||
|
// render
|
||||||
|
var $preview = $('.display-layout .preview').empty();
|
||||||
|
var $row = $('<div class="row"/>');
|
||||||
|
for (var i = 0; i < OSD.data.display_size.total;) {
|
||||||
|
var charCode = OSD.data.preview[i];
|
||||||
|
if (typeof charCode === 'object') {
|
||||||
|
var field = OSD.data.preview[i][0];
|
||||||
|
var charCode = OSD.data.preview[i][1];
|
||||||
|
}
|
||||||
|
var $img = $('<div class="char"><img src=' + FONT.draw(charCode) + '></img></div>')
|
||||||
|
.on('mouseenter', OSD.GUI.preview.onMouseEnter)
|
||||||
|
.on('mouseleave', OSD.GUI.preview.onMouseLeave)
|
||||||
|
.on('dragover', OSD.GUI.preview.onDragOver)
|
||||||
|
.on('dragleave', OSD.GUI.preview.onDragLeave)
|
||||||
|
.on('drop', OSD.GUI.preview.onDrop)
|
||||||
|
.data('field', field)
|
||||||
|
.data('position', i);
|
||||||
|
if (field && field.positionable) {
|
||||||
|
$img
|
||||||
|
.addClass('field-' + field.index)
|
||||||
|
.data('field', field)
|
||||||
|
.prop('draggable', true)
|
||||||
|
.on('dragstart', OSD.GUI.preview.onDragStart);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
$row.append($img);
|
||||||
|
if (++i % OSD.data.display_size.x == 0) {
|
||||||
|
$preview.append($row);
|
||||||
|
$row = $('<div class="row"/>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$('a.save').click(function () {
|
||||||
|
var self = this;
|
||||||
|
MSP.promise(MSPCodes.MSP_EEPROM_WRITE);
|
||||||
|
GUI.log('OSD settings saved');
|
||||||
|
var oldText = $(this).text();
|
||||||
|
$(this).html("Saved");
|
||||||
|
setTimeout(function () {
|
||||||
|
$(self).html(oldText);
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// font preview window
|
||||||
|
var $preview = $('.font-preview');
|
||||||
|
|
||||||
|
// init structs once, also clears current font
|
||||||
|
FONT.initData();
|
||||||
|
|
||||||
|
var $fontPicker = $('.fontbuttons button');
|
||||||
|
$fontPicker.click(function (e) {
|
||||||
|
if (!$(this).data('font-file')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$fontPicker.removeClass('active');
|
||||||
|
$(this).addClass('active');
|
||||||
|
$.get('/resources/osd/' + $(this).data('font-file') + '.mcm', function (data) {
|
||||||
|
FONT.parseMCMFontFile(data);
|
||||||
|
FONT.preview($preview);
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// load the first font when we change tabs
|
||||||
|
$fontPicker.first().click();
|
||||||
|
|
||||||
|
$('button.load_font_file').click(function () {
|
||||||
|
$fontPicker.removeClass('active');
|
||||||
|
FONT.openFontFile().then(function () {
|
||||||
|
FONT.preview($preview);
|
||||||
|
updateOsdView();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// font upload
|
||||||
|
$('a.flash_font').click(function () {
|
||||||
|
if (!GUI.connect_lock) { // button disabled while flashing is in progress
|
||||||
|
$('.progressLabel').text('Uploading...');
|
||||||
|
FONT.upload($('.progress').val(0)).then(function () {
|
||||||
|
var msg = 'Uploaded all ' + FONT.data.characters.length + ' characters';
|
||||||
|
console.log(msg);
|
||||||
|
$('.progressLabel').text(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', 'span.progressLabel a.save_font', function () {
|
||||||
|
chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'baseflight', accepts: [
|
||||||
|
{extensions: ['mcm']}
|
||||||
|
]}, function (fileEntry) {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error(chrome.runtime.lastError.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.fileSystem.getDisplayPath(fileEntry, function (path) {
|
||||||
|
console.log('Saving firmware to: ' + path);
|
||||||
|
|
||||||
|
// check if file is writable
|
||||||
|
chrome.fileSystem.isWritableEntry(fileEntry, function (isWritable) {
|
||||||
|
if (isWritable) {
|
||||||
|
var blob = new Blob([intel_hex], {type: 'text/plain'});
|
||||||
|
|
||||||
|
fileEntry.createWriter(function (writer) {
|
||||||
|
var truncated = false;
|
||||||
|
|
||||||
|
writer.onerror = function (e) {
|
||||||
|
console.error(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
writer.onwriteend = function () {
|
||||||
|
if (!truncated) {
|
||||||
|
// onwriteend will be fired again when truncation is finished
|
||||||
|
truncated = true;
|
||||||
|
writer.truncate(blob.size);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
writer.write(blob);
|
||||||
|
}, function (e) {
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('You don\'t have write permissions for this file, sorry.');
|
||||||
|
GUI.log('You don\'t have <span style="color: red">write permissions</span> for this file');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).keypress(function (e) {
|
||||||
|
if (e.which == 13) { // enter
|
||||||
|
// Trigger regular Flashing sequence
|
||||||
|
$('a.flash_font').click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GUI.content_ready(callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
TABS.osd.cleanup = function (callback) {
|
||||||
|
PortHandler.flush_callbacks();
|
||||||
|
|
||||||
|
// unbind "global" events
|
||||||
|
$(document).unbind('keypress');
|
||||||
|
$(document).off('click', 'span.progressLabel a');
|
||||||
|
|
||||||
|
if (callback) callback();
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue