Merge pull request #25 from inmarket/master

Bug fixes + new driver + extend touch demo
This commit is contained in:
Tectu 2012-12-02 03:05:21 -08:00
commit 24e75d96e1
8 changed files with 477 additions and 175 deletions

View File

@ -26,18 +26,22 @@
#include "gwin.h" #include "gwin.h"
static GConsoleObject gc; static GConsoleObject gc;
static GButtonObject gNext;
static GButtonObject gPrev;
static GListener gl; static GListener gl;
/*------------------------------------------------------------------------* /*------------------------------------------------------------------------*
* GINPUT Touch Driver Calibrator. * * GINPUT Touch Driver Calibrator. *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
int main(void) { int main(void) {
GSourceHandle gs; GSourceHandle gs, gsNext, gsPrev;
GEvent *pe;
GEventMouse *pem; GEventMouse *pem;
GEventGWinButton *peb;
coord_t swidth, sheight; coord_t swidth, sheight;
GHandle ghc; GHandle ghc, ghNext, ghPrev;
BaseSequentialStream *gp; BaseSequentialStream *gp;
unsigned testnum; GEventType deviceType;
halInit(); // Initialise the Hardware halInit(); // Initialise the Hardware
chSysInit(); // Initialize the OS chSysInit(); // Initialize the OS
@ -46,7 +50,7 @@ int main(void) {
// Get the display dimensions // Get the display dimensions
swidth = gdispGetWidth(); swidth = gdispGetWidth();
sheight = gdispGetHeight(); sheight = gdispGetHeight();
testnum = 0; ghNext = ghPrev = 0;
// Create our title // Create our title
gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", &fontUI2, Red, White, justifyCenter); gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", &fontUI2, Red, White, justifyCenter);
@ -65,52 +69,87 @@ int main(void) {
* Test: Device Type * Test: Device Type
*/ */
StepDeviceType:
gwinClear(ghc); gwinClear(ghc);
gwinSetColor(ghc, Yellow); gwinSetColor(ghc, Yellow);
chprintf(gp, "\n%u. DEVICE TYPE\n\n", ++testnum); chprintf(gp, "\n1. DEVICE TYPE\n\n");
pem = (GEventMouse *)&gl.event; pem = (GEventMouse *)&gl.event;
ginputGetMouseStatus(0, pem); ginputGetMouseStatus(0, pem);
deviceType = pem->type;
gwinSetColor(ghc, White); gwinSetColor(ghc, White);
chprintf(gp, "This is detected as a %s device\n\n", chprintf(gp, "This is detected as a %s device\n\n",
pem->type == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN")); deviceType == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN"));
chprintf(gp, "Press and release your finger (or mouse button) to move on to the next test.\n"); if (ghNext)
chprintf(gp, "Press Next or Back to continue.\n");
else if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Click the mouse button to move on to the next test.\n");
else
chprintf(gp, "Press and release your finger to move on to the next test.\n");
do { while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); pe = geventEventWait(&gl, TIME_INFINITE);
if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check if (pe->type == GEVENT_GWIN_BUTTON) {
continue; peb = (GEventGWinButton *)pe;
if (peb->button == ghPrev)
} while (!(pem->meta & GMETA_MOUSE_UP)); goto StepClickJitter;
if (peb->button == ghNext)
break;
}
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
break;
}
}
/* /*
* Test: Mouse raw reading jitter * Test: Mouse raw reading jitter
*/ */
StepRawJitter:
gwinClear(ghc); gwinClear(ghc);
gwinSetColor(ghc, Yellow); gwinSetColor(ghc, Yellow);
chprintf(gp, "\n%u. GINPUT_MOUSE_READ_CYCLES\n\n", ++testnum); chprintf(gp, "\n2. GINPUT_MOUSE_READ_CYCLES\n\n");
gwinSetColor(ghc, White); gwinSetColor(ghc, White);
chprintf(gp, "Press on the surface (or press and hold the mouse button).\n\n"); if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Press and hold the mouse button.\n\n");
else
chprintf(gp, "Press and hold on the surface.\n\n");
chprintf(gp, "Numbers will display in this window.\n" chprintf(gp, "Numbers will display in this window.\n"
"Ensure that values don't jump around very much when your finger is stationary.\n\n" "Ensure that values don't jump around very much when your finger is stationary.\n\n"
"Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n" "Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n");
"Releasing your finger (or mouse button) will move on to the next test.\n\n");
if (ghNext)
chprintf(gp, "Press Next or Back to continue.\n");
else if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Release the mouse button to move on to the next test.\n");
else
chprintf(gp, "Release your finger to move on to the next test.\n");
// For this test turn on ALL mouse movement events // For this test turn on ALL mouse movement events
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER); geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
do { while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); pe = geventEventWait(&gl, TIME_INFINITE);
if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check if (pe->type == GEVENT_GWIN_BUTTON) {
continue; peb = (GEventGWinButton *)pe;
if (peb->button == ghPrev)
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) goto StepDeviceType;
chprintf(gp, "%u:%u\n", pem->x, pem->y); if (peb->button == ghNext)
} while (!(pem->meta & GMETA_MOUSE_UP)); break;
}
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
chprintf(gp, "%u:%u\n", pem->x, pem->y);
if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
break;
}
}
// Reset to just changed movements. // Reset to just changed movements.
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA); geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
@ -119,60 +158,124 @@ int main(void) {
* Test: Calibration * Test: Calibration
*/ */
StepCalibrate:
gwinClear(ghc); gwinClear(ghc);
gwinSetColor(ghc, Yellow); gwinSetColor(ghc, Yellow);
chprintf(gp, "\n%u. GINPUT_MOUSE_CALIBRATION_ERROR\n\n", ++testnum); chprintf(gp, "\n3. GINPUT_MOUSE_CALIBRATION_ERROR\n\n");
gwinSetColor(ghc, Gray); gwinSetColor(ghc, Gray);
chprintf(gp, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n"); chprintf(gp, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n");
gwinSetColor(ghc, White); gwinSetColor(ghc, White);
chprintf(gp, "When you press and release the surface, calibration will start.\n");
chprintf(gp, "You will be presented with a number of points to touch.\nPress them in turn.\n\n" chprintf(gp, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
"If the calibration repeatedly fails increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n"); "If the calibration repeatedly fails, increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n\n");
do { if (ghNext)
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); chprintf(gp, "Press Next to start the calibration.\n");
if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check else if (deviceType == GEVENT_MOUSE)
continue; chprintf(gp, "Click the mouse button to start the calibration.\n");
else
chprintf(gp, "Press and release your finger to start the calibration.\n");
} while (!(pem->meta & GMETA_MOUSE_UP)); while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
if (pe->type == GEVENT_GWIN_BUTTON) {
peb = (GEventGWinButton *)pe;
if (peb->button == ghPrev)
goto StepRawJitter;
if (peb->button == ghNext)
break;
}
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if (!ghNext && (pem->meta & GMETA_MOUSE_UP))
break;
}
}
// Calibrate // Calibrate
ginputCalibrateMouse(0); ginputCalibrateMouse(0);
// Calibration uses the whole screen - re-establish our title /* From now on we can use Next and Previous Buttons */
if (!ghNext) {
ghNext = gwinCreateButton(&gNext, swidth-50, 0, 50, 20, &fontUI2, GBTN_NORMAL);
gwinSetButtonText(ghNext, "Next", FALSE);
gsNext = gwinGetButtonSource(ghNext);
geventAttachSource(&gl, gsNext, 0);
gwinAttachButtonMouseSource(ghNext, gs);
ghPrev = gwinCreateButton(&gPrev, swidth-100, 0, 50, 20, &fontUI2, GBTN_NORMAL);
gwinSetButtonText(ghPrev, "Back", FALSE);
gsPrev = gwinGetButtonSource(ghPrev);
geventAttachSource(&gl, gsPrev, 0);
gwinAttachButtonMouseSource(ghPrev, gs);
#if 0
{
GSourceHandle gsButton1, gsButton2;
// Attach a couple of hardware toggle buttons to our Next and Back buttons as well.
// We can always use the mouse to trigger the buttons if you don't want to use hardware toggles.
// This code depends on your hardware. Turn it on only if you have
// defined a board definition for your toggle driver. Then change
// the next two lines to be correct for your hardware. The values
// below are correct for the Win32 toggle driver.
gsButton1 = ginputGetToggle(GINPUT_TOGGLE_MOMENTARY1);
gsButton2 = ginputGetToggle(GINPUT_TOGGLE_MOMENTARY2);
gwinAttachButtonToggleSource(ghNext, gsButton2);
gwinAttachButtonToggleSource(ghPrev, gsButton1);
}
#endif
}
// Calibration used the whole screen - re-establish our title
gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", &fontUI2, Green, White, justifyCenter); gdispFillStringBox(0, 0, swidth, 20, "Touch Calibration", &fontUI2, Green, White, justifyCenter);
gwinButtonDraw(ghNext);
gwinButtonDraw(ghPrev);
/* /*
* Test: Mouse movement jitter * Test: Mouse movement jitter
*/ */
StepJitter:
gwinClear(ghc); gwinClear(ghc);
gwinSetColor(ghc, Yellow); gwinSetColor(ghc, Yellow);
chprintf(gp, "\n%u. GINPUT_MOUSE_MOVE_JITTER\n\n", ++testnum); chprintf(gp, "\n4. GINPUT_MOUSE_MOVE_JITTER\n\n");
gwinSetColor(ghc, White); gwinSetColor(ghc, White);
chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n"); if (deviceType == GEVENT_MOUSE)
chprintf(gp, "Press and hold the mouse button and move around as if to draw.\n\n");
else
chprintf(gp, "Press firmly on the surface and move around as if to draw.\n\n");
chprintf(gp, "Dots will display in this window. Ensure that when you stop moving your finger that " chprintf(gp, "Dots will display in this window. Ensure that when you stop moving your finger that "
"new dots stop displaying.\nNew dots should only display when your finger is moving.\n\n" "new dots stop displaying.\nNew dots should only display when your finger is moving.\n\n"
"Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n" "Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n");
"Releasing your finger (or mouse button) will move on to the next test.\n\n"); chprintf(gp, "Press Next or Back to continue.\n\n");
do { while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); pe = geventEventWait(&gl, TIME_INFINITE);
if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check if (pe->type == GEVENT_GWIN_BUTTON) {
continue; peb = (GEventGWinButton *)pe;
if (peb->button == ghPrev)
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT)) goto StepCalibrate;
chprintf(gp, "."); if (peb->button == ghNext)
} while (!(pem->meta & GMETA_MOUSE_UP)); break;
}
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
chprintf(gp, ".");
}
}
/* /*
* Test: Polling frequency * Test: Polling frequency
*/ */
StepPolling:
gwinClear(ghc); gwinClear(ghc);
gwinSetColor(ghc, Yellow); gwinSetColor(ghc, Yellow);
chprintf(gp, "\n%u. GINPUT_MOUSE_POLL_PERIOD\n\n", ++testnum); chprintf(gp, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n");
gwinSetColor(ghc, White); gwinSetColor(ghc, White);
chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n"); chprintf(gp, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
@ -180,26 +283,33 @@ int main(void) {
"Adjust GINPUT_MOUSE_POLL_PERIOD to the highest value that provides a line without " "Adjust GINPUT_MOUSE_POLL_PERIOD to the highest value that provides a line without "
"gaps that are too big.\nDecreasing the value increases CPU usage.\n" "gaps that are too big.\nDecreasing the value increases CPU usage.\n"
"About 25 (millisecs) normally produces good results." "About 25 (millisecs) normally produces good results."
"This test can be ignored for interrupt driven drivers.\n\n" "This test can be ignored for interrupt driven drivers.\n\n");
"Releasing your finger (or mouse button) will move on to the next test.\n"); chprintf(gp, "Press Next or Back to continue.\n\n");
do {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check
continue;
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
gdispDrawPixel(pem->x, pem->y, Green);
} while (!(pem->meta & GMETA_MOUSE_UP));
while(1) {
pe = geventEventWait(&gl, TIME_INFINITE);
if (pe->type == GEVENT_GWIN_BUTTON) {
peb = (GEventGWinButton *)pe;
if (peb->button == ghPrev)
goto StepJitter;
if (peb->button == ghNext)
break;
}
if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
pem = (GEventMouse *)pe;
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
gdispDrawPixel(pem->x, pem->y, Green);
}
}
/* /*
* Test: Click Jitter * Test: Click Jitter
*/ */
StepClickJitter:
gwinClear(ghc); gwinClear(ghc);
gwinSetColor(ghc, Yellow); gwinSetColor(ghc, Yellow);
chprintf(gp, "\n%u. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n", ++testnum); chprintf(gp, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n");
gwinSetColor(ghc, White); gwinSetColor(ghc, White);
chprintf(gp, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n"); chprintf(gp, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
@ -209,21 +319,31 @@ int main(void) {
"Adjust GINPUT_MOUSE_CLICK_JITTER to the smallest value that this reliably works for.\n" "Adjust GINPUT_MOUSE_CLICK_JITTER to the smallest value that this reliably works for.\n"
"Adjust GINPUT_MOUSE_CLICK_TIME to adjust distinguishing short vs long presses.\n" "Adjust GINPUT_MOUSE_CLICK_TIME to adjust distinguishing short vs long presses.\n"
"TIME_INFINITE means there are no long presses (although a right mouse button will still work).\n\n" "TIME_INFINITE means there are no long presses (although a right mouse button will still work).\n\n"
"Note: moving your finger (mouse) during a click cancels it." "Note: moving your finger (mouse) during a click cancels it.\n\n");
"This test does not end.\n\n"); chprintf(gp, "This is the last test but you can press Next or Back to continue.\n\n");
while(1) { while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE); pe = geventEventWait(&gl, TIME_INFINITE);
if (pem->type != GEVENT_MOUSE && pem->type != GEVENT_TOUCH) // Safety Check if (pe->type == GEVENT_GWIN_BUTTON) {
continue; peb = (GEventGWinButton *)pe;
if (peb->button == ghPrev)
if ((pem->meta & GMETA_MOUSE_CLICK)) { goto StepPolling;
gwinSetColor(ghc, Yellow); if (peb->button == ghNext)
chprintf(gp, "-"); break;
} }
if ((pem->meta & GMETA_MOUSE_CXTCLICK)) { if (pe->type == GEVENT_MOUSE || pe->type == GEVENT_TOUCH) {
gwinSetColor(ghc, Red); pem = (GEventMouse *)pe;
chprintf(gp, "x"); if ((pem->meta & GMETA_MOUSE_CLICK)) {
gwinSetColor(ghc, Yellow);
chprintf(gp, "-");
}
if ((pem->meta & GMETA_MOUSE_CXTCLICK)) {
gwinSetColor(ghc, Red);
chprintf(gp, "x");
}
} }
} }
// Can't let this really exit
goto StepDeviceType;
} }

View File

@ -32,12 +32,6 @@
#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
/* Include mouse support code */
#include "lld/ginput/mouse.h"
/* Include the emulation code for things we don't support */
#include "lld/gdisp/emulation.c"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -45,11 +39,41 @@
#include <wingdi.h> #include <wingdi.h>
#include <assert.h> #include <assert.h>
#ifndef GINPUT_NEED_TOGGLE
#define GINPUT_NEED_TOGGLE FALSE
#endif
#ifndef GINPUT_NEED_MOUSE
#define GINPUT_NEED_MOUSE FALSE
#endif
#if GINPUT_NEED_TOGGLE
/* Include toggle support code */
#include "lld/ginput/toggle.h"
const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
{0, 0xFF, 0x00, PAL_MODE_INPUT},
};
#endif
#if GINPUT_NEED_MOUSE
/* Include mouse support code */
#include "ginput.h"
#include "lld/ginput/mouse.h"
#endif
/* Include the emulation code for things we don't support */
#include "lld/gdisp/emulation.c"
/*===========================================================================*/ /*===========================================================================*/
/* Driver local routines . */ /* Driver local routines . */
/*===========================================================================*/ /*===========================================================================*/
#define WIN32_USE_MSG_REDRAW FALSE #define WIN32_USE_MSG_REDRAW FALSE
#if GINPUT_NEED_TOGGLE
#define WIN32_BUTTON_AREA 16
#else
#define WIN32_BUTTON_AREA 0
#endif
#define APP_NAME "GDISP" #define APP_NAME "GDISP"
@ -61,37 +85,104 @@ static HDC dcBuffer = NULL;
static HBITMAP dcBitmap = NULL; static HBITMAP dcBitmap = NULL;
static HBITMAP dcOldBitmap; static HBITMAP dcOldBitmap;
static volatile bool_t isReady = FALSE; static volatile bool_t isReady = FALSE;
static coord_t mousex, mousey; static coord_t wWidth, wHeight;
static uint16_t mousebuttons;
#if GINPUT_NEED_MOUSE
static coord_t mousex, mousey;
static uint16_t mousebuttons;
#endif
#if GINPUT_NEED_TOGGLE
static uint8_t toggles = 0;
#endif
static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{ {
HDC dc; HDC dc;
PAINTSTRUCT ps; PAINTSTRUCT ps;
#if GINPUT_NEED_TOGGLE
HBRUSH hbrOn, hbrOff;
HPEN pen;
RECT rect;
HGDIOBJ old;
POINT p;
coord_t pos;
uint8_t bit;
#endif
switch (Msg) { switch (Msg) {
case WM_CREATE: case WM_CREATE:
break; break;
#if GINPUT_NEED_MOUSE
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
mousebuttons = 0x0001; #if GINPUT_NEED_MOUSE
goto mousemove; if ((coord_t)HIWORD(lParam) < wHeight) {
mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
goto mousemove;
}
#endif
#if GINPUT_NEED_TOGGLE
bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth);
toggles ^= bit;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;
rect.bottom = wHeight + WIN32_BUTTON_AREA;
InvalidateRect(hWnd, &rect, FALSE);
UpdateWindow(hWnd);
#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
ginputToggleWakeup();
#endif
#endif
break;
case WM_LBUTTONUP: case WM_LBUTTONUP:
mousebuttons &= ~0x0001; #if GINPUT_NEED_TOGGLE
goto mousemove; if ((toggles & 0xF0)) {
toggles &= 0x0F;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;
rect.bottom = wHeight + WIN32_BUTTON_AREA;
InvalidateRect(hWnd, &rect, FALSE);
UpdateWindow(hWnd);
#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
ginputToggleWakeup();
#endif
}
#endif
#if GINPUT_NEED_MOUSE
if ((coord_t)HIWORD(lParam) < wHeight) {
mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
goto mousemove;
}
#endif
break;
#if GINPUT_NEED_MOUSE
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
mousebuttons = 0x0004; if ((coord_t)HIWORD(lParam) < wHeight) {
goto mousemove; mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
goto mousemove;
}
break;
case WM_MBUTTONUP: case WM_MBUTTONUP:
mousebuttons &= ~0x0004; if ((coord_t)HIWORD(lParam) < wHeight) {
goto mousemove; mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
goto mousemove;
}
break;
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
mousebuttons = 0x0002; if ((coord_t)HIWORD(lParam) < wHeight) {
goto mousemove; mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
goto mousemove;
}
break;
case WM_RBUTTONUP: case WM_RBUTTONUP:
mousebuttons &= ~0x0002; if ((coord_t)HIWORD(lParam) < wHeight) {
goto mousemove; mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
goto mousemove;
}
break;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if ((coord_t)HIWORD(lParam) >= wHeight)
break;
mousemove: mousemove:
mousex = (coord_t)LOWORD(lParam); mousex = (coord_t)LOWORD(lParam);
mousey = (coord_t)HIWORD(lParam); mousey = (coord_t)HIWORD(lParam);
@ -114,8 +205,32 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
dc = BeginPaint(hWnd, &ps); dc = BeginPaint(hWnd, &ps);
BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top, BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top, (ps.rcPaint.bottom > wHeight ? wHeight : ps.rcPaint.bottom) - ps.rcPaint.top,
dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
#if GINPUT_NEED_TOGGLE
if (ps.rcPaint.bottom >= wHeight) {
pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black));
hbrOn = CreateSolidBrush(COLOR2BGR(Blue));
hbrOff = CreateSolidBrush(COLOR2BGR(Gray));
old = SelectObject(dc, pen);
MoveToEx(dc, 0, wHeight, &p);
LineTo(dc, wWidth, wHeight);
for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) {
rect.left = pos;
rect.right = pos + wWidth/8;
rect.top = wHeight;
rect.bottom = wHeight + WIN32_BUTTON_AREA;
FillRect(dc, &rect, (toggles & bit) ? hbrOn : hbrOff);
if (pos > 0) {
MoveToEx(dc, rect.left, rect.top, &p);
LineTo(dc, rect.left, rect.bottom);
}
}
DeleteObject(hbrOn);
DeleteObject(hbrOff);
SelectObject(dc, old);
}
#endif
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
break; break;
case WM_DESTROY: case WM_DESTROY:
@ -154,8 +269,8 @@ static DWORD WINAPI WindowThread(LPVOID lpParameter) {
wc.lpszClassName = APP_NAME; wc.lpszClassName = APP_NAME;
RegisterClass(&wc); RegisterClass(&wc);
rect.top = 0; rect.bottom = GDISP.Height; rect.top = 0; rect.bottom = wHeight+WIN32_BUTTON_AREA;
rect.left = 0; rect.right = GDISP.Width; rect.left = 0; rect.right = wWidth;
AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0); AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0, winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0,
rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL); rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL);
@ -163,11 +278,11 @@ static DWORD WINAPI WindowThread(LPVOID lpParameter) {
GetClientRect(winRootWindow, &rect); GetClientRect(winRootWindow, &rect);
GDISP.Width = rect.right-rect.left; wWidth = rect.right-rect.left;
GDISP.Height = rect.bottom - rect.top; wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA;
dc = GetDC(winRootWindow); dc = GetDC(winRootWindow);
dcBitmap = CreateCompatibleBitmap(dc, GDISP.Width, GDISP.Height); dcBitmap = CreateCompatibleBitmap(dc, wWidth, wHeight);
dcBuffer = CreateCompatibleDC(dc); dcBuffer = CreateCompatibleDC(dc);
ReleaseDC(winRootWindow, dc); ReleaseDC(winRootWindow, dc);
dcOldBitmap = SelectObject(dcBuffer, dcBitmap); dcOldBitmap = SelectObject(dcBuffer, dcBitmap);
@ -205,12 +320,12 @@ bool_t GDISP_LLD(init)(void) {
/* Set the window dimensions */ /* Set the window dimensions */
GetWindowRect(GetDesktopWindow(), &rect); GetWindowRect(GetDesktopWindow(), &rect);
GDISP.Width = rect.right - rect.left; wWidth = rect.right - rect.left;
GDISP.Height = rect.bottom - rect.top; wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA;
if (GDISP.Width > GDISP_SCREEN_WIDTH) if (wWidth > GDISP_SCREEN_WIDTH)
GDISP.Width = GDISP_SCREEN_WIDTH; wWidth = GDISP_SCREEN_WIDTH;
if (GDISP.Height > GDISP_SCREEN_HEIGHT) if (wHeight > GDISP_SCREEN_HEIGHT)
GDISP.Height = GDISP_SCREEN_HEIGHT; wHeight = GDISP_SCREEN_HEIGHT;
/* Initialise the window */ /* Initialise the window */
CreateThread(0, 0, WindowThread, 0, 0, 0); CreateThread(0, 0, WindowThread, 0, 0, 0);
@ -222,6 +337,8 @@ bool_t GDISP_LLD(init)(void) {
GDISP.Powermode = powerOn; GDISP.Powermode = powerOn;
GDISP.Backlight = 100; GDISP.Backlight = 100;
GDISP.Contrast = 50; GDISP.Contrast = 50;
GDISP.Width = wWidth;
GDISP.Height = wHeight;
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
GDISP.clipx0 = 0; GDISP.clipx0 = 0;
GDISP.clipy0 = 0; GDISP.clipy0 = 0;
@ -841,33 +958,26 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) {
* @notapi * @notapi
*/ */
void GDISP_LLD(control)(unsigned what, void *value) { void GDISP_LLD(control)(unsigned what, void *value) {
RECT rect;
switch(what) { switch(what) {
case GDISP_CONTROL_ORIENTATION: case GDISP_CONTROL_ORIENTATION:
if (GDISP.Orientation == (gdisp_orientation_t)value) if (GDISP.Orientation == (gdisp_orientation_t)value)
return; return;
GetClientRect(winRootWindow, &rect);
switch((gdisp_orientation_t)value) { switch((gdisp_orientation_t)value) {
case GDISP_ROTATE_0: case GDISP_ROTATE_0:
/* Code here */ GDISP.Width = wWidth;
GDISP.Width = rect.right-rect.left; GDISP.Height = wHeight;
GDISP.Height = rect.bottom - rect.top;
break; break;
case GDISP_ROTATE_90: case GDISP_ROTATE_90:
/* Code here */ GDISP.Height = wWidth;
GDISP.Height = rect.right-rect.left; GDISP.Width = wHeight;
GDISP.Width = rect.bottom - rect.top;
break; break;
case GDISP_ROTATE_180: case GDISP_ROTATE_180:
/* Code here */ GDISP.Width = wWidth;
GDISP.Width = rect.right-rect.left; GDISP.Height = wHeight;
GDISP.Height = rect.bottom - rect.top;
break; break;
case GDISP_ROTATE_270: case GDISP_ROTATE_270:
/* Code here */ GDISP.Height = wWidth;
GDISP.Height = rect.right-rect.left; GDISP.Width = wHeight;
GDISP.Width = rect.bottom - rect.top;
break; break;
default: default:
return; return;
@ -892,16 +1002,21 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) {
#if GINPUT_NEED_MOUSE #if GINPUT_NEED_MOUSE
#include "lld/ginput/mouse.h" void ginput_lld_mouse_init(void) {}
void ginput_lld_mouse_init(void) {} void ginput_lld_mouse_get_reading(MouseReading *pt) {
pt->x = mousex;
pt->y = mousey > wHeight ? wHeight : mousey;
pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
pt->buttons = mousebuttons;
}
void ginput_lld_mouse_get_reading(MouseReading *pt) { #endif /* GINPUT_NEED_MOUSE */
pt->x = mousex;
pt->y = mousey; #if GINPUT_NEED_TOGGLE
pt->z = (mousebuttons & 0x0001) ? 100 : 0;
pt->buttons = mousebuttons; // We auto-magicaly know that the mousebutton bits match the MouseReading bits. void ginput_lld_toggle_init(const GToggleConfig *ptc) { (void) ptc; }
} unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { (void) ptc; return toggles; }
#endif /* GINPUT_NEED_MOUSE */ #endif /* GINPUT_NEED_MOUSE */

View File

@ -0,0 +1,51 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
This file is part of ChibiOS/GFX.
ChibiOS/GFX 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 3 of the License, or
(at your option) any later version.
ChibiOS/GFX 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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file drivers/multiple/Win32/ginput_lld_toggle_config.h
* @brief GINPUT Toggle Driver configuration header.
*
* @addtogroup GINPUT_TOGGLE
* @{
*/
#ifndef _GINPUT_LLD_TOGGLE_CONFIG_H
#define _GINPUT_LLD_TOGGLE_CONFIG_H
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - ether works here)
#define GINPUT_TOGGLE_NUM_PORTS 8 // The total number of toggle inputs
#define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries
#define GINPUT_TOGGLE_SW1 0 // Switch 1 - Toggle
#define GINPUT_TOGGLE_SW2 1 // Switch 2 - Toggle
#define GINPUT_TOGGLE_SW3 2 // Switch 3 - Toggle
#define GINPUT_TOGGLE_SW4 3 // Switch 4 - Toggle
#define GINPUT_TOGGLE_MOMENTARY1 4 // Switch 5 - Momentary
#define GINPUT_TOGGLE_MOMENTARY2 5 // Switch 6 - Momentary
#define GINPUT_TOGGLE_MOMENTARY3 6 // Switch 7 - Momentary
#define GINPUT_TOGGLE_MOMENTARY4 7 // Switch 8 - Momentary
#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */
#endif /* _GINPUT_LLD_TOGGLE_CONFIG_H */
/** @} */

View File

@ -129,8 +129,15 @@ extern "C" {
// Get the source handle so the application can listen for events // Get the source handle so the application can listen for events
#define gwinGetButtonSource(gh) ((GSourceHandle)(gh)) #define gwinGetButtonSource(gh) ((GSourceHandle)(gh))
// Attach a source to this button. Sources recognised: Mouse, Touch and Toggle - others are ignored (returns false). #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
bool_t gwinAttachButtonSource(GHandle gh, GSourceHandle gsh, GEventType type); // Attach a mouse source to this button.
bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh);
#endif
#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
// Attach a toggle source to this button.
bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -65,7 +65,7 @@
// n - Millisecs between poll's // n - Millisecs between poll's
#ifndef GINPUT_MOUSE_POLL_PERIOD #ifndef GINPUT_MOUSE_POLL_PERIOD
#define GINPUT_MOUSE_POLL_PERIOD 100 #define GINPUT_MOUSE_POLL_PERIOD 25
#endif #endif
// n - Movement allowed without discarding the CLICK or CLICKCXT event (+/- pixels) // n - Movement allowed without discarding the CLICK or CLICKCXT event (+/- pixels)

View File

@ -30,22 +30,28 @@
#ifndef GFX_USE_GINPUT #ifndef GFX_USE_GINPUT
#define GFX_USE_GINPUT FALSE #define GFX_USE_GINPUT FALSE
#endif #endif
#ifndef GINPUT_NEED_TOGGLE
#if GFX_USE_GINPUT || defined(__DOXYGEN__) #define GINPUT_NEED_TOGGLE FALSE
#if GINPUT_NEED_TOGGLE
// Describes how the toggle bits are obtained
typedef struct GToggleConfig_t {
void *id;
unsigned mask;
unsigned invert;
iomode_t mode;
} GToggleConfig;
#endif #endif
#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || defined(__DOXYGEN__)
// Describes how the toggle bits are obtained
typedef struct GToggleConfig_t {
void *id;
unsigned mask;
unsigned invert;
iomode_t mode;
} GToggleConfig;
// This must be included after the above type definition // This must be included after the above type definition
#include "ginput.h" #include "ginput.h"
// n - Millisecs between poll's
#ifndef GINPUT_TOGGLE_POLL_PERIOD
#define GINPUT_TOGGLE_POLL_PERIOD 200
#endif
/*===========================================================================*/ /*===========================================================================*/
/* External declarations. */ /* External declarations. */
/*===========================================================================*/ /*===========================================================================*/
@ -54,18 +60,26 @@
extern "C" { extern "C" {
#endif #endif
#if GINPUT_NEED_TOGGLE
extern const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES]; extern const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES];
void ginput_lld_toggle_init(const GToggleConfig *ptc); void ginput_lld_toggle_init(const GToggleConfig *ptc);
unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc); unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc);
#endif
/* This routine is provided to low level drivers to wakeup a value read from a thread context.
* Particularly useful if GINPUT_TOGGLE_POLL_PERIOD = TIME_INFINITE
*/
void ginputToggleWakeup(void);
/* This routine is provided to low level drivers to wakeup a value read from an ISR
* Particularly useful if GINPUT_TOGGLE_POLL_PERIOD = TIME_INFINITE
*/
void ginputToggleWakeupI(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* GFX_USE_GINPUT */ #endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */
#endif /* _LLD_GINPUT_TOGGLE_H */ #endif /* _LLD_GINPUT_TOGGLE_H */
/** @} */ /** @} */

View File

@ -34,10 +34,6 @@
#include "lld/ginput/toggle.h" #include "lld/ginput/toggle.h"
#ifndef GINPUT_TOGGLE_POLL_PERIOD
#define GINPUT_TOGGLE_POLL_PERIOD 250
#endif
#define GINPUT_TOGGLE_ISON 0x01 #define GINPUT_TOGGLE_ISON 0x01
#define GINPUT_TOGGLE_INVERT 0x02 #define GINPUT_TOGGLE_INVERT 0x02
@ -157,5 +153,15 @@ bool_t ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle) {
return TRUE; return TRUE;
} }
/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
void ginputToggleWakeup(void) {
gtimerJab(&ToggleTimer);
}
/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
void ginputToggleWakeupI(void) {
gtimerJabI(&ToggleTimer);
}
#endif /* GINPUT_NEED_TOGGLE */ #endif /* GINPUT_NEED_TOGGLE */
/** @} */ /** @} */

View File

@ -297,34 +297,23 @@ void gwinButtonDraw(GHandle gh) {
#undef gbw #undef gbw
} }
// Attach a source to this button. Sources recognised: Mouse, Touch and Toggle - others are ignored (returns false). #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
bool_t gwinAttachButtonSource(GHandle gh, GSourceHandle gsh, GEventType type) { bool_t gwinAttachButtonMouseSource(GHandle gh, GSourceHandle gsh) {
#define gbw ((GButtonObject *)gh) if (gh->type != GW_BUTTON)
unsigned flags; return FALSE;
switch (type) { return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_MOUSEMETA);
#if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
flags = 0;
break;
#endif
#if defined(GINPUT_NEED_TOUCH) && GINPUT_NEED_TOUCH
case GEVENT_TOUCH:
flags = 0;
break;
#endif
#if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
case GEVENT_TOGGLE:
flags = GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON;
break;
#endif
default:
return FALSE;
} }
return geventAttachSource(&gbw->listener, gsh, flags); #endif
#undef gbw #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE
} bool_t gwinAttachButtonToggleSource(GHandle gh, GSourceHandle gsh) {
if (gh->type != GW_BUTTON)
return FALSE;
return geventAttachSource(&((GButtonObject *)gh)->listener, gsh, GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON);
}
#endif
#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */ #endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
/** @} */ /** @} */