diff --git a/_examples/touch_calibration/touch_calibration.cpp b/_examples/touch_calibration/touch_calibration.cpp
new file mode 100644
index 0000000..09e900e
--- /dev/null
+++ b/_examples/touch_calibration/touch_calibration.cpp
@@ -0,0 +1,185 @@
+/***************************************************************************
+ * Copyright (C) 2010, 2011, 2012, 2013, 2014 by Terraneo Federico *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * As a special exception, if other files instantiate templates or use *
+ * macros or inline functions from this file, or you compile this file *
+ * and link it with other works to produce a work based on this file, *
+ * this file does not by itself cause the resulting work to be covered *
+ * by the GNU General Public License. However the source code for this *
+ * file must still be made available in accordance with the GNU General *
+ * Public License. This exception does not invalidate any other reasons *
+ * why a work based on this file might be covered by the GNU General *
+ * Public License. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+#include "mxgui/entry.h"
+#include "mxgui/display.h"
+#include "mxgui/misc_inst.h"
+#include "mxgui/level2/input.h"
+#include
+#include
+#include
+
+using namespace mxgui;
+
+// function to draw the crosses
+static void drawCross(DrawingContext &dc, Point c, int r)
+{
+ dc.line(Point(c.x() - r, c.y()), Point(c.x() + r, c.y()), white);
+ dc.line(Point(c.x(), c.y() - r), Point(c.x(), c.y() + r), white);
+}
+
+struct Calib
+{
+ double min, max;
+};
+
+// The transformation from RAW to pixels is performed through a linear transformation of the form:
+// pixel = a * raw + b
+static void calibrationFrom2Points(double raw1, double pix1, double raw2, double pix2, double W, Calib &out)
+{
+ double a = (pix2 - pix1) / (raw2 - raw1);
+ double b = pix1 - a * raw1;
+
+ out.min = -b / a;
+ out.max = (W - b) / a;
+}
+
+ENTRY()
+{
+ Display &display = DisplayManager::instance().getDisplay();
+ InputHandler &backend = InputHandler::instance();
+
+ // calibration reset
+ backend.setTouchscreenCalibration(0.0, 0.0, 0.0, 0.0);
+
+ const short w = display.getWidth() - 1;
+ const short h = display.getHeight() - 1;
+
+ short oldX = 0, oldY = 0;
+
+ // cross points array
+ Point targets[] = {
+ Point(30, 30),
+ Point(w - 30, 30),
+ Point(w - 30, h - 30),
+ Point(30, h - 30)};
+
+ enum State
+ {
+ WAIT_DOWN,
+ WAIT_UP
+ };
+ State state = WAIT_DOWN;
+
+ int idx = 0;
+
+ DrawingContext dc(display);
+ drawCross(dc, targets[idx], 20);
+
+ Point rawDatas[4];
+
+ for (;;)
+ {
+ Event e = backend.getEvent();
+
+ if (e.getEvent() != EventType::TouchDown && e.getEvent() != EventType::TouchMove && e.getEvent() != EventType::TouchUp)
+ {
+ continue;
+ }
+
+ if (state == WAIT_DOWN)
+ {
+ if (e.getEvent() == EventType::TouchDown)
+ {
+ rawDatas[idx] = e.getPoint();
+
+ // I wait for the touch-up before showing the next cross.
+ state = WAIT_UP;
+ }
+ }
+ else
+ {
+ if (e.getEvent() == EventType::TouchUp)
+ {
+ idx++;
+ if (idx >= 4)
+ {
+ dc.clear(black);
+
+ // compute the calibration parameters
+ Calib cx1, cy1, cx2, cy2;
+
+ calibrationFrom2Points((double)rawDatas[0].x(), (double)targets[0].x(),
+ (double)rawDatas[2].x(), (double)targets[2].x(),
+ w, cx1);
+
+ calibrationFrom2Points((double)rawDatas[0].y(), (double)targets[0].y(),
+ (double)rawDatas[2].y(), (double)targets[2].y(),
+ h, cy1);
+
+ calibrationFrom2Points((double)rawDatas[1].x(), (double)targets[1].x(),
+ (double)rawDatas[3].x(), (double)targets[3].x(),
+ w, cx2);
+
+ calibrationFrom2Points((double)rawDatas[1].y(), (double)targets[1].y(),
+ (double)rawDatas[3].y(), (double)targets[3].y(),
+ h, cy2);
+
+ cx1.max = (cx1.max + cx2.max) / 2;
+ cx1.min = (cx1.min + cx2.min) / 2;
+ cy1.max = (cy1.max + cy2.max) / 2;
+ cy1.min = (cy1.min + cy2.min) / 2;
+
+ backend.setTouchscreenCalibration(cx1.min, cx1.max, cy1.min, cy1.max);
+ for (;;)
+ {
+ Event e2 = backend.getEvent();
+ switch (e2.getEvent())
+ {
+ case EventType::ButtonA:
+ display.turnOff();
+ return 0;
+ case EventType::TouchDown:
+ case EventType::TouchUp:
+ case EventType::TouchMove:
+ {
+ dc.line(Point(0, oldY), Point(w, oldY), black);
+ dc.line(Point(oldX, 0), Point(oldX, h), black);
+ oldX = e2.getPoint().x();
+ oldY = e2.getPoint().y();
+
+ dc.line(Point(0, oldY), Point(w, oldY), white);
+ dc.line(Point(oldX, 0), Point(oldX, h), white);
+ char line[128];
+ siprintf(line, "(%d, %d) ", oldX, oldY);
+ dc.write(Point(0, 0), line);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ // mostra prossima croce
+ dc.clear(black);
+ drawCross(dc, targets[idx], 20);
+
+ state = WAIT_DOWN;
+ }
+ }
+ }
+}
diff --git a/drivers/event_st25dvdiscovery.cpp b/drivers/event_st25dvdiscovery.cpp
index 3f6671b..eae5e8d 100644
--- a/drivers/event_st25dvdiscovery.cpp
+++ b/drivers/event_st25dvdiscovery.cpp
@@ -35,6 +35,7 @@
#include "event_st25dvdiscovery.h"
#include "miosix.h"
+#include "kernel/scheduler/scheduler.h"
#include "util/software_i2c.h"
#include
@@ -43,10 +44,20 @@ using namespace miosix;
static Semaphore touchIntSema;
+/**
+ * Touchscreen interrupt
+ */
+void __attribute__((naked)) EXTI9_5_IRQHandler()
+{
+ saveContext();
+ asm volatile("bl EXTI9_5_HandlerImpl");
+ restoreContext();
+}
+
/**
* Touchscreen interrupt actual implementation
*/
-void EXTI9_5_HandlerImpl()
+extern "C" void __attribute__((used)) EXTI9_5_HandlerImpl()
{
EXTI->PR = EXTI_PR_PR5;
touchIntSema.IRQsignal();
@@ -54,6 +65,11 @@ void EXTI9_5_HandlerImpl()
namespace mxgui {
+static int g_xMin;
+static int g_xMax;
+static int g_yMin;
+static int g_yMax;
+
typedef Gpio buttonKey;
typedef Gpio joySel;
typedef Gpio joyLeft;
@@ -219,10 +235,17 @@ class STMPE811
const int xMax = 3800;
const int yMin = 220;
const int yMax = 3700;
- x = (x - xMin) * 240 / (xMax - xMin);
- y = (y - yMin) * 320 / (yMax - yMin);
- x=min(239,max(0,x));
- y=min(319,max(0,y));
+ int x = static_cast(tsData[0]) << 4 | tsData[1] >> 4;
+ int y = ((static_cast(tsData[1]) & 0xf) << 8) | tsData[2];
+ y = 4095 - y; // Y is swapped
+
+ if (g_xMax != g_xMin && g_yMax != g_yMin)
+ {
+ x = (x - g_xMin) * 240 / (g_xMax - g_xMin);
+ y = (y - g_yMin) * 320 / (g_yMax - g_yMin);
+ x = min(239, max(0, x));
+ y = min(319, max(0, y));
+ }
#if defined(MXGUI_ORIENTATION_VERTICAL)
lastTouchPoint=Point(x,y);
@@ -263,7 +286,7 @@ static std::function eventCallback;
static void callback(Event e)
{
{
- FastGlobalIrqLock dLock;
+ FastInterruptDisableLock dLock;
if(eventQueue.IRQput(e)==false) return;
}
if(eventCallback) eventCallback();
@@ -370,8 +393,7 @@ static void eventThread(void *)
InputHandlerImpl::InputHandlerImpl()
{
{
- GlobalIrqLock dLock;
- IRQregisterIrq(dLock,EXTI9_5_IRQn,&EXTI9_5_HandlerImpl);
+ FastInterruptDisableLock dLock;
buttonKey::mode(Mode::INPUT);
interrupt::mode(Mode::INPUT);
joySel::mode(Mode::INPUT);
@@ -401,6 +423,14 @@ InputHandlerImpl::InputHandlerImpl()
Thread::create(eventThread,STACK_MIN);
}
+void InputHandlerImpl::setTouchscreenCalibration(double xMin, double xMax, double yMin, double yMax)
+{
+ g_xMin = (int)xMin;
+ g_xMax = (int)xMax;
+ g_yMin = (int)yMin;
+ g_yMax = (int)yMax;
+}
+
Event InputHandlerImpl::getEvent()
{
Event result;
@@ -410,7 +440,7 @@ Event InputHandlerImpl::getEvent()
Event InputHandlerImpl::popEvent()
{
- FastGlobalIrqLock dLock;
+ FastInterruptDisableLock dLock;
Event result;
if(eventQueue.isEmpty() == false) {
eventQueue.IRQget(result);
diff --git a/drivers/event_st25dvdiscovery.h b/drivers/event_st25dvdiscovery.h
index eb0b9e9..e010efb 100644
--- a/drivers/event_st25dvdiscovery.h
+++ b/drivers/event_st25dvdiscovery.h
@@ -71,6 +71,8 @@ class InputHandlerImpl
* \return the previous callback
*/
std::function registerEventCallback(std::function cb);
+
+ void setTouchscreenCalibration(double xMin, double xMax, double yMin, double yMax);
};
} //namespace mxgui
diff --git a/level2/input.cpp b/level2/input.cpp
index 27057e9..b52a07e 100644
--- a/level2/input.cpp
+++ b/level2/input.cpp
@@ -70,6 +70,13 @@ function InputHandler::registerEventCallback(function cb)
return pImpl->registerEventCallback(cb);
}
+#if defined(_BOARD_STM32F415VG_ST25DVDISCOVERY)
+void InputHandler::setTouchscreenCalibration(double xMin, double xMax, double yMin, double yMax)
+{
+ pImpl->setTouchscreenCalibration(xMin, xMax, yMin, yMax);
+}
+#endif
+
InputHandler::InputHandler(InputHandlerImpl *impl) : pImpl(impl) {}
} //namespace mxgui
diff --git a/level2/input.h b/level2/input.h
index 77c4c31..d527934 100644
--- a/level2/input.h
+++ b/level2/input.h
@@ -201,6 +201,10 @@ class InputHandler
*/
std::function registerEventCallback(std::function cb);
+ #if defined(_BOARD_STM32F415VG_ST25DVDISCOVERY)
+ void setTouchscreenCalibration(double xMin, double xMax, double yMin, double yMax);
+ #endif
+
private:
/**
* Class cannot be copied