Merge pull request #1892 from halemmerich/calibration
Calibration - Scale the inputs to account for linear variationmaster
commit
62a500deec
|
|
@ -0,0 +1,2 @@
|
|||
1.00: New App!
|
||||
1.01: Use fractional numbers and scale the points to keep working consistently on whole screen
|
||||
|
|
@ -6,6 +6,7 @@ A simple calibration app for the touchscreen
|
|||
Once lauched touch the cross that appear on the screen to make
|
||||
another spawn elsewhere.
|
||||
|
||||
each new touch on the screen will help to calibrate the offset
|
||||
of your finger on the screen. After five or more input, press
|
||||
the button to save the calibration and close the application.
|
||||
Each new touch on the screen will help to calibrate the offset
|
||||
of your finger on the screen. After four or more inputs, press
|
||||
the button to save the calibration and close the application. Quality
|
||||
of the calibration gets better with every touch on a cross.
|
||||
|
|
|
|||
|
|
@ -1,40 +1,60 @@
|
|||
class BanglejsApp {
|
||||
constructor() {
|
||||
this.maxSamples = 16;
|
||||
this.target = {
|
||||
xMin: Math.floor(0.1 * g.getWidth()),
|
||||
xMax: Math.floor(0.9 * g.getWidth()),
|
||||
yMin: Math.floor(0.1 * g.getHeight()),
|
||||
yMax: Math.floor(0.9 * g.getHeight()),
|
||||
};
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.step = 0;
|
||||
this.settings = {
|
||||
xoffset: 0,
|
||||
yoffset: 0,
|
||||
xoffset: [0],
|
||||
yoffset: [0],
|
||||
xMaxActual: [this.target.xMax],
|
||||
yMaxActual: [this.target.yMax],
|
||||
};
|
||||
}
|
||||
|
||||
load_settings() {
|
||||
let settings = require('Storage').readJSON('calibration.json', true) || {active: false};
|
||||
|
||||
// do nothing if the calibration is deactivated
|
||||
if (settings.active === true) {
|
||||
// cancel the calibration offset
|
||||
Bangle.on('touch', function(button, xy) {
|
||||
xy.x += settings.xoffset;
|
||||
xy.y += settings.yoffset;
|
||||
});
|
||||
}
|
||||
if (!settings.xoffset) settings.xoffset = 0;
|
||||
if (!settings.yoffset) settings.yoffset = 0;
|
||||
|
||||
console.log('loaded settings:');
|
||||
console.log(settings);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
save_settings() {
|
||||
this.settings.active = true;
|
||||
this.settings.reload = false;
|
||||
require('Storage').writeJSON('calibration.json', this.settings);
|
||||
getMedian(array){
|
||||
array.sort();
|
||||
let i = Math.floor(array.length/2);
|
||||
if ( array.length % 2 && array.length > 1 ){
|
||||
return (array[i]+array[i+1])/2;
|
||||
} else {
|
||||
return array[i];
|
||||
}
|
||||
}
|
||||
|
||||
console.log('saved settings:');
|
||||
console.log(this.settings);
|
||||
getMedianSettings(){
|
||||
let medianSettings = {
|
||||
xoffset: this.getMedian(this.settings.xoffset),
|
||||
yoffset: this.getMedian(this.settings.yoffset)
|
||||
};
|
||||
|
||||
medianSettings.xscale = this.target.xMax / (medianSettings.xoffset + this.getMedian(this.settings.xMaxActual));
|
||||
medianSettings.yscale = this.target.yMax / (medianSettings.yoffset + this.getMedian(this.settings.yMaxActual));
|
||||
return medianSettings;
|
||||
}
|
||||
|
||||
save_settings() {
|
||||
let settingsToSave = this.getMedianSettings();
|
||||
settingsToSave.active = true;
|
||||
settingsToSave.reload = false;
|
||||
require('Storage').writeJSON('calibration.json', settingsToSave);
|
||||
|
||||
console.log('saved settings:', settingsToSave);
|
||||
}
|
||||
|
||||
explain() {
|
||||
|
|
@ -46,29 +66,78 @@ class BanglejsApp {
|
|||
}
|
||||
|
||||
drawTarget() {
|
||||
this.x = 16 + Math.floor(Math.random() * (g.getWidth() - 32));
|
||||
this.y = 40 + Math.floor(Math.random() * (g.getHeight() - 80));
|
||||
switch (this.step){
|
||||
case 0:
|
||||
this.x = this.target.xMin;
|
||||
this.y = this.target.yMin;
|
||||
break;
|
||||
case 1:
|
||||
this.x = this.target.xMax;
|
||||
this.y = this.target.yMin;
|
||||
break;
|
||||
case 2:
|
||||
this.x = this.target.xMin;
|
||||
this.y = this.target.yMax;
|
||||
break;
|
||||
case 3:
|
||||
this.x = this.target.xMax;
|
||||
this.y = this.target.yMax;
|
||||
break;
|
||||
}
|
||||
|
||||
g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24);
|
||||
g.clearRect(0, 0, g.getWidth(), g.getHeight());
|
||||
g.setColor(g.theme.fg);
|
||||
g.drawLine(this.x, this.y - 5, this.x, this.y + 5);
|
||||
g.drawLine(this.x - 5, this.y, this.x + 5, this.y);
|
||||
g.setFont('Vector', 10);
|
||||
g.drawString('current offset: ' + this.settings.xoffset + ', ' + this.settings.yoffset, 0, 24);
|
||||
let medianSettings = this.getMedianSettings();
|
||||
g.drawString('current offset: ' + medianSettings.xoffset.toFixed(3) + ', ' + medianSettings.yoffset.toFixed(3), 2, (g.getHeight()/2)-6);
|
||||
g.drawString('current scale: ' + medianSettings.xscale.toFixed(3) + ', ' + medianSettings.yscale.toFixed(3), 2, (g.getHeight()/2)+6);
|
||||
}
|
||||
|
||||
setOffset(xy) {
|
||||
this.settings.xoffset = Math.round((this.settings.xoffset + (this.x - Math.floor((this.x + xy.x)/2)))/2);
|
||||
this.settings.yoffset = Math.round((this.settings.yoffset + (this.y - Math.floor((this.y + xy.y)/2)))/2);
|
||||
switch (this.step){
|
||||
case 0:
|
||||
this.settings.xoffset.push(this.x - xy.x);
|
||||
this.settings.yoffset.push(this.y - xy.y);
|
||||
break;
|
||||
case 1:
|
||||
this.settings.xMaxActual.push(xy.x);
|
||||
this.settings.yoffset.push(this.y - xy.y);
|
||||
break;
|
||||
case 2:
|
||||
this.settings.xoffset.push(this.x - xy.x);
|
||||
this.settings.yMaxActual.push(xy.y);
|
||||
break;
|
||||
case 3:
|
||||
this.settings.xMaxActual.push(xy.x);
|
||||
this.settings.yMaxActual.push(xy.y);
|
||||
break;
|
||||
}
|
||||
|
||||
for (let c in this.settings){
|
||||
if (this.settings[c].length > this.maxSamples) this.settings[c] = this.settings[c].slice(1, this.maxSamples);
|
||||
}
|
||||
}
|
||||
|
||||
nextStep() {
|
||||
this.step++;
|
||||
if ( this.step == 4 ) this.step = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
E.srand(Date.now());
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
calibration = new BanglejsApp();
|
||||
calibration.load_settings();
|
||||
Bangle.disableCalibration = true;
|
||||
|
||||
function touchHandler (btn, xy){
|
||||
if (xy) calibration.setOffset(xy);
|
||||
calibration.nextStep();
|
||||
calibration.drawTarget();
|
||||
}
|
||||
|
||||
let modes = {
|
||||
mode : 'custom',
|
||||
|
|
@ -76,10 +145,7 @@ let modes = {
|
|||
calibration.save_settings(this.settings);
|
||||
load();
|
||||
},
|
||||
touch : function(btn, xy) {
|
||||
calibration.setOffset(xy);
|
||||
calibration.drawTarget();
|
||||
},
|
||||
touch : touchHandler,
|
||||
};
|
||||
Bangle.setUI(modes);
|
||||
calibration.drawTarget();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
let cal_settings = require('Storage').readJSON("calibration.json", true) || {active: false};
|
||||
Bangle.on('touch', function(button, xy) {
|
||||
// do nothing if the calibration is deactivated
|
||||
if (cal_settings.active === false) return;
|
||||
if (cal_settings.active === false || Bangle.disableCalibration) return;
|
||||
|
||||
// reload the calibration offset at each touch event /!\ bad for the flash memory
|
||||
if (cal_settings.reload === true) {
|
||||
|
|
@ -9,6 +9,6 @@ Bangle.on('touch', function(button, xy) {
|
|||
}
|
||||
|
||||
// apply the calibration offset
|
||||
xy.x += cal_settings.xoffset;
|
||||
xy.y += cal_settings.yoffset;
|
||||
xy.x = E.clip(Math.round((xy.x + (cal_settings.xoffset || 0)) * (cal_settings.xscale || 1)),0,g.getWidth());
|
||||
xy.y = E.clip(Math.round((xy.y + (cal_settings.yoffset || 0)) * (cal_settings.yscale || 1)),0,g.getHeight());
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Touchscreen Calibration",
|
||||
"shortName":"Calibration",
|
||||
"icon": "calibration.png",
|
||||
"version":"1.00",
|
||||
"version":"1.01",
|
||||
"description": "A simple calibration app for the touchscreen",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
Loading…
Reference in New Issue