Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DMBasicGUI by
Application/AppTouchCalibration.cpp
- Committer:
- embeddedartists
- Date:
- 2014-12-19
- Revision:
- 4:a73760d09423
- Parent:
- 3:3fabfe3339b8
- Child:
- 8:19a6b70d42b1
File content as of revision 4:a73760d09423:
/*
* Copyright 2014 Embedded Artists AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "AppTouchCalibration.h"
#include "lpc_swim_font.h"
/******************************************************************************
* Defines and typedefs
*****************************************************************************/
#define BTN_WIDTH 65
#define BTN_HEIGHT 40
#define BTN_OFF 20
/******************************************************************************
* Global variables
*****************************************************************************/
/******************************************************************************
* Private functions
*****************************************************************************/
static void buttonClicked(uint32_t x)
{
bool* done = (bool*)x;
*done = true;
}
void AppTouchCalibration::draw()
{
// Prepare fullscreen
swim_window_open(_win,
_disp->width(), _disp->height(), // full size
(COLOR_T*)_fb,
0,0,_disp->width()-1, _disp->height()-1, // window position and size
1, // border
WHITE, WHITE, BLACK); // colors: pen, backgr, forgr
swim_set_title(_win, "Touch Calibration", BLACK);
// Prepare status area in the middle
swim_window_open(_msg,
_disp->width(), _disp->height(), // full size
(COLOR_T*)_fb,
50,_disp->height()/2-15,_disp->width()-50, _disp->height()/2+15, // window position and size
0, // border
BLACK, WHITE, BLACK); // colors: pen, backgr, forgr
showStatus("Press the crosshairs in each of the corners");
// Create (but don't show) the button
_btn = new Button("Done", _win->fb, _win->xpmax - BTN_OFF - BTN_WIDTH, _win->ypmax - BTN_OFF - BTN_HEIGHT, BTN_WIDTH, BTN_HEIGHT);
}
void AppTouchCalibration::drawMarker(uint16_t x, uint16_t y, bool erase)
{
// The markers must be drawn at exact locations to get a good calibration.
// However the lpc_swim functions take the window's title bar into
// consideration which will move them. To combat this the marker's
// coordinates will have to be moved
x -= _win->xpvmin;
y -= _win->ypvmin;
swim_set_pen_color(_win, (erase ? _win->bkg : BLACK));
swim_put_line(_win, x-15, y, x+15, y);
swim_put_line(_win, x, y-15, x, y+15);
swim_put_circle(_win, x, y, 10, false);
}
bool AppTouchCalibration::calibrate()
{
bool morePoints = true;
bool lastPoint = false;
uint16_t x, y;
int point = 0;
do {
if (_touch->calibrateStart() != TouchPanel::TouchError_Ok) {
showStatus("Failed to start calibration\n");
break;
}
while (morePoints) {
if (point++ > 0) {
// erase old location
drawMarker(x, y, true);
}
if (_touch->getNextCalibratePoint(&x, &y, &lastPoint) != TouchPanel::TouchError_Ok) {
showStatus("Failed to get calibration point\n");
break;
}
drawMarker(x, y, false);
if (lastPoint) {
showStatus("Last calibration point. After this the data will");
showStatus("be saved, which can take a couple of seconds!", 1);
}
if (_touch->waitForCalibratePoint(&morePoints, 0) != TouchPanel::TouchError_Ok) {
showStatus("Failed to get user click\n");
break;
}
}
if (morePoints) {
// aborted calibration due to error(s)
break;
}
// erase old location
drawMarker(x, y, true);
} while(0);
return !morePoints;
}
void AppTouchCalibration::showStatus(const char* message, int line)
{
if (line == 0) {
swim_clear_screen(_msg, _msg->bkg);
swim_put_text_centered_win(_msg, message, 0);
} else {
swim_put_text_centered_win(_msg, message, line*swim_get_font_height(_msg));
}
DMBoard::instance().logger()->printf("[CALIB] %s\n", message);
}
/******************************************************************************
* Public functions
*****************************************************************************/
AppTouchCalibration::AppTouchCalibration() : _disp(NULL), _touch(NULL), _win(NULL), _fb(NULL), _btn(NULL)
{
}
AppTouchCalibration::~AppTouchCalibration()
{
teardown();
}
bool AppTouchCalibration::setup()
{
_disp = DMBoard::instance().display();
_touch = DMBoard::instance().touchPanel();
_win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
_msg = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
_fb = _disp->allocateFramebuffer();
return (_win != NULL && _msg != NULL && _fb != NULL);
}
void AppTouchCalibration::runToCompletion()
{
// Alternative 1: use the calling thread's context to run in
bool done = false;
draw();
_btn->setAction(buttonClicked, (uint32_t)&done);
void* oldFB = _disp->swapFramebuffer(_fb);
// Run calibration
if (calibrate()) {
showStatus("Calibration Completed. Test to draw!");
_btn->draw();
} else {
// Something went wrong. The error is already shown!
// Without touch there is no point in continuing, ask
// user to reset.
swim_put_text_centered_win(_win, "Without touch there is nothing to do. Press RESET !", 2*_disp->height()/3);
while(1) {
Thread::wait(5000);
}
}
// Allow user to draw. Exit by pressing button
swim_set_pen_color(_win, BLACK);
TouchPanel::touchCoordinate_t coord;
while(!done) {
if (_touch->read(coord) == TouchPanel::TouchError_Ok) {
if (coord.z > 0) {
//swim_put_pixel(_win, coord.x, coord.y);
swim_put_box(_win, coord.x-1, coord.y-1, coord.x+1, coord.y+1);
}
if (_btn->handle(coord.x, coord.y, coord.z > 0)) {
_btn->draw();
}
}
}
// User has clicked the button, restore the original FB
_disp->swapFramebuffer(oldFB);
swim_window_close(_win);
swim_window_close(_msg);
}
bool AppTouchCalibration::teardown()
{
if (_win != NULL) {
free(_win);
_win = NULL;
}
if (_msg != NULL) {
free(_msg);
_msg = NULL;
}
if (_fb != NULL) {
free(_fb);
_fb = NULL;
}
if (_btn != NULL) {
delete _btn;
_btn = NULL;
}
return true;
}
