Merge pull request #70 from inmarket/master
X11 Driver for GDISP and GINPUT MOUSEremotes/origin_old/ugfx_release_2.6
commit
896e67c900
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* This file is subject to the terms of the GFX License, v1.0. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://chibios-gfx.com/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drivers/multiple/X/gdisp_lld.c
|
||||
* @brief GDISP Graphics Driver subsystem low level driver source for X.
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "gfx.h"
|
||||
|
||||
#if GFX_USE_GDISP
|
||||
|
||||
/* Our threading model - ChibiOS or POSIX */
|
||||
#ifndef GDISP_THREAD_CHIBIOS
|
||||
#define GDISP_THREAD_CHIBIOS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Our color model - Default or 24 bit only.
|
||||
*
|
||||
* At present we don't define this as we don't need to.
|
||||
* It may however be useful later if we implement bitblits.
|
||||
* As this may be dead code we don't include it in gdisp/options.h
|
||||
*/
|
||||
#ifndef GDISP_FORCE_24BIT
|
||||
#define GDISP_FORCE_24BIT FALSE
|
||||
#endif
|
||||
|
||||
#if GINPUT_NEED_MOUSE
|
||||
/* Include mouse support code */
|
||||
#include "ginput/lld/mouse.h"
|
||||
#endif
|
||||
|
||||
/* Include the emulation code for things we don't support */
|
||||
#include "gdisp/lld/emulation.c"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if !GDISP_THREAD_CHIBIOS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifndef GDISP_SCREEN_HEIGHT
|
||||
#define GDISP_SCREEN_HEIGHT 480
|
||||
#endif
|
||||
#ifndef GDISP_SCREEN_WIDTH
|
||||
#define GDISP_SCREEN_WIDTH 640
|
||||
#endif
|
||||
|
||||
Display *dis;
|
||||
int scr;
|
||||
Window win;
|
||||
Pixmap pix;
|
||||
XEvent evt;
|
||||
GC gc;
|
||||
Colormap cmap;
|
||||
XVisualInfo vis;
|
||||
int depth;
|
||||
#if GINPUT_NEED_MOUSE
|
||||
coord_t mousex, mousey;
|
||||
uint16_t mousebuttons;
|
||||
#endif
|
||||
|
||||
static void ProcessEvent(void) {
|
||||
XColor col;
|
||||
|
||||
switch(evt.type) {
|
||||
case Expose:
|
||||
XCopyArea(dis, pix, win, gc,
|
||||
evt.xexpose.x, evt.xexpose.y,
|
||||
evt.xexpose.width, evt.xexpose.height,
|
||||
evt.xexpose.x, evt.xexpose.y);
|
||||
break;
|
||||
#if GINPUT_NEED_MOUSE
|
||||
case ButtonPress:
|
||||
mousex = evt.xbutton.x;
|
||||
mousey = evt.xbutton.y;
|
||||
switch(evt.xbutton.button){
|
||||
case 1: mousebuttons |= GINPUT_MOUSE_BTN_LEFT; break;
|
||||
case 2: mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; break;
|
||||
case 3: mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; break;
|
||||
case 4: mousebuttons |= GINPUT_MOUSE_BTN_4; break;
|
||||
}
|
||||
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
|
||||
ginputMouseWakeup();
|
||||
#endif
|
||||
break;
|
||||
case ButtonRelease:
|
||||
mousex = evt.xbutton.x;
|
||||
mousey = evt.xbutton.y;
|
||||
switch(evt.xbutton.button){
|
||||
case 1: mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; break;
|
||||
case 2: mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; break;
|
||||
case 3: mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; break;
|
||||
case 4: mousebuttons &= ~GINPUT_MOUSE_BTN_4; break;
|
||||
}
|
||||
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
|
||||
ginputMouseWakeup();
|
||||
#endif
|
||||
break;
|
||||
case MotionNotify:
|
||||
mousex = evt.xmotion.x;
|
||||
mousey = evt.xmotion.y;
|
||||
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
|
||||
ginputMouseWakeup();
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* this is the X11 thread which keeps track of all events */
|
||||
#if GDISP_THREAD_CHIBIOS
|
||||
static WORKING_AREA(waXThread, 1024);
|
||||
static msg_t ThreadX(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
while(1) {
|
||||
chThdSleepMilliseconds(100);
|
||||
while(XPending(dis)) {
|
||||
XNextEvent(dis, &evt);
|
||||
ProcessEvent();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static void * ThreadX(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
while(1) {
|
||||
pthread_yield(); // This could be a 100ms delay
|
||||
while(XPending(dis)) {
|
||||
XNextEvent(dis, &evt);
|
||||
ProcessEvent();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int FatalXIOError(Display *d) {
|
||||
(void) d;
|
||||
|
||||
/* The window has closed */
|
||||
fprintf(stderr, "GFX Window closed!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
bool_t gdisp_lld_init(void)
|
||||
{
|
||||
XSizeHints *pSH;
|
||||
XSetWindowAttributes xa;
|
||||
XTextProperty WindowTitle;
|
||||
char * WindowTitleText;
|
||||
#if !GDISP_THREAD_CHIBIOS
|
||||
pthread_attr_t thattr;
|
||||
pthread_t thid;
|
||||
#endif
|
||||
|
||||
#if !GDISP_THREAD_CHIBIOS
|
||||
XInitThreads();
|
||||
#endif
|
||||
|
||||
dis = XOpenDisplay(NULL);
|
||||
scr = DefaultScreen(dis);
|
||||
|
||||
#if GDISP_FORCE_24BIT
|
||||
if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) {
|
||||
fprintf(stderr, "Your display has no TrueColor mode\n");
|
||||
XCloseDisplay(dis);
|
||||
return FALSE;
|
||||
}
|
||||
cmap = XCreateColormap(dis, RootWindow(dis, scr),
|
||||
vis.visual, AllocNone);
|
||||
#else
|
||||
vis.visual = CopyFromParent;
|
||||
vis.depth = DefaultDepth(dis, scr);
|
||||
cmap = DefaultColormap(dis, scr);
|
||||
#endif
|
||||
fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth);
|
||||
|
||||
xa.colormap = cmap;
|
||||
xa.border_pixel = 0xFFFFFF;
|
||||
xa.background_pixel = 0x000000;
|
||||
|
||||
win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16,
|
||||
GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
|
||||
0, vis.depth, InputOutput, vis.visual,
|
||||
CWBackPixel|CWColormap|CWBorderPixel, &xa);
|
||||
XSync(dis, TRUE);
|
||||
|
||||
WindowTitleText = "GFX";
|
||||
XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
|
||||
XSetWMName(dis, win, &WindowTitle);
|
||||
XSetWMIconName(dis, win, &WindowTitle);
|
||||
XSync(dis, TRUE);
|
||||
|
||||
pSH = XAllocSizeHints();
|
||||
pSH->flags = PSize | PMinSize | PMaxSize;
|
||||
pSH->min_width = pSH->max_width = pSH->base_width = GDISP_SCREEN_WIDTH;
|
||||
pSH->min_height = pSH->max_height = pSH->base_height = GDISP_SCREEN_HEIGHT;
|
||||
XSetWMNormalHints(dis, win, pSH);
|
||||
XFree(pSH);
|
||||
XSync(dis, TRUE);
|
||||
|
||||
pix = XCreatePixmap(dis, win,
|
||||
GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth);
|
||||
XSync(dis, TRUE);
|
||||
|
||||
gc = XCreateGC(dis, win, 0, 0);
|
||||
XSetBackground(dis, gc, BlackPixel(dis, scr));
|
||||
XSync(dis, TRUE);
|
||||
|
||||
XSelectInput(dis, win, StructureNotifyMask);
|
||||
XMapWindow(dis, win);
|
||||
do { XNextEvent(dis, &evt); } while (evt.type != MapNotify);
|
||||
|
||||
/* start the X11 thread */
|
||||
XSetIOErrorHandler(FatalXIOError);
|
||||
XSelectInput(dis, win,
|
||||
ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
|
||||
|
||||
#if GDISP_THREAD_CHIBIOS
|
||||
if (!chThdCreateStatic(waXThread, sizeof(waXThread), HIGHPRIO, ThreadX, 0)) {
|
||||
#else
|
||||
if (pthread_attr_init(&thattr)
|
||||
|| pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED)
|
||||
|| pthread_create(&thid, &thattr, ThreadX, 0)) {
|
||||
#endif
|
||||
fprintf(stderr, "Cannot start X Thread\n");
|
||||
XCloseDisplay(dis);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Initialise the GDISP structure to match */
|
||||
GDISP.Orientation = GDISP_ROTATE_0;
|
||||
GDISP.Powermode = powerOn;
|
||||
GDISP.Backlight = 100;
|
||||
GDISP.Contrast = 50;
|
||||
GDISP.Width = GDISP_SCREEN_WIDTH;
|
||||
GDISP.Height = GDISP_SCREEN_HEIGHT;
|
||||
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
|
||||
GDISP.clipx0 = 0;
|
||||
GDISP.clipy0 = 0;
|
||||
GDISP.clipx1 = GDISP.Width;
|
||||
GDISP.clipy1 = GDISP.Height;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color)
|
||||
{
|
||||
XColor col;
|
||||
|
||||
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
|
||||
// Clip pre orientation change
|
||||
if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
|
||||
#endif
|
||||
|
||||
col.red = RED_OF(color) << 8;
|
||||
col.green = GREEN_OF(color) << 8;
|
||||
col.blue = BLUE_OF(color) << 8;
|
||||
XAllocColor(dis, cmap, &col);
|
||||
XSetForeground(dis, gc, col.pixel);
|
||||
XDrawPoint(dis, pix, gc, (int)x, (int)y );
|
||||
XDrawPoint(dis, win, gc, (int)x, (int)y );
|
||||
XFlush(dis);
|
||||
}
|
||||
|
||||
void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
|
||||
XColor col;
|
||||
|
||||
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
|
||||
// Clip pre orientation change
|
||||
if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
|
||||
if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
|
||||
if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
|
||||
if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
|
||||
if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
|
||||
#endif
|
||||
|
||||
col.red = RED_OF(color) << 8;
|
||||
col.green = GREEN_OF(color) << 8;
|
||||
col.blue = BLUE_OF(color) << 8;
|
||||
XAllocColor(dis, cmap, &col);
|
||||
XSetForeground(dis, gc, col.pixel);
|
||||
XFillRectangle(dis, pix, gc, x, y, cx, cy);
|
||||
XFillRectangle(dis, win, gc, x, y, cx, cy);
|
||||
XFlush(dis);
|
||||
}
|
||||
|
||||
// Start of Bitblit code
|
||||
//XImage bitmap;
|
||||
//pixel_t *bits;
|
||||
// bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
|
||||
// bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
|
||||
// 0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
|
||||
// 0, 0);
|
||||
|
||||
#if GINPUT_NEED_MOUSE
|
||||
|
||||
void ginput_lld_mouse_init(void) {}
|
||||
|
||||
void ginput_lld_mouse_get_reading(MouseReading *pt) {
|
||||
pt->x = mousex;
|
||||
pt->y = mousey;
|
||||
pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
|
||||
pt->buttons = mousebuttons;
|
||||
}
|
||||
|
||||
#endif /* GINPUT_NEED_MOUSE */
|
||||
|
||||
#endif /* GFX_USE_GDISP */
|
||||
/** @} */
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# List the required driver.
|
||||
GFXSRC += $(GFXLIB)/drivers/multiple/X/gdisp_lld.c
|
||||
|
||||
# Required include directories
|
||||
GFXINC += $(GFXLIB)/drivers/multiple/X
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* This file is subject to the terms of the GFX License, v1.0. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://chibios-gfx.com/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drivers/multiple/X/gdisp_lld_config.h
|
||||
* @brief GDISP Graphic Driver subsystem low level driver header for the X11 display.
|
||||
*
|
||||
* @addtogroup GDISP
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GDISP_LLD_CONFIG_H
|
||||
#define _GDISP_LLD_CONFIG_H
|
||||
|
||||
#if GFX_USE_GDISP
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver hardware support. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define GDISP_DRIVER_NAME "Linux emulator - X11"
|
||||
|
||||
#define GDISP_HARDWARE_CLEARS FALSE
|
||||
#define GDISP_HARDWARE_FILLS TRUE
|
||||
#define GDISP_HARDWARE_BITFILLS FALSE
|
||||
#define GDISP_HARDWARE_SCROLL FALSE
|
||||
#define GDISP_HARDWARE_PIXELREAD FALSE
|
||||
#define GDISP_HARDWARE_CONTROL FALSE
|
||||
#define GDISP_HARDWARE_CIRCLES FALSE
|
||||
#define GDISP_HARDWARE_CIRCLEFILLS FALSE
|
||||
#define GDISP_HARDWARE_ARCS FALSE
|
||||
#define GDISP_HARDWARE_ARCFILLS FALSE
|
||||
|
||||
#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
|
||||
|
||||
#endif /* GFX_USE_GDISP */
|
||||
|
||||
#endif /* _GDISP_LLD_CONFIG_H */
|
||||
/** @} */
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* This file is subject to the terms of the GFX License, v1.0. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://chibios-gfx.com/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drivers/multiple/X/ginput_lld_mouse_config.h
|
||||
* @brief GINPUT LLD header file for mouse/touch driver.
|
||||
*
|
||||
* @defgroup Mouse Mouse
|
||||
* @ingroup GINPUT
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _LLD_GINPUT_MOUSE_CONFIG_H
|
||||
#define _LLD_GINPUT_MOUSE_CONFIG_H
|
||||
|
||||
// This driver supports being both a mouse or a touch device (we don't actually know which it really is)
|
||||
// When operating in mouse mode a long left button click does not generate a context click.
|
||||
// When operating in touch mode we allow sloppier clicks etc
|
||||
#if 1
|
||||
#define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE
|
||||
#define GINPUT_MOUSE_CLICK_TIME TIME_INFINITE // Long click != Context Click
|
||||
#define GINPUT_MOUSE_NEED_CALIBRATION FALSE
|
||||
#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
|
||||
#define GINPUT_MOUSE_READ_CYCLES 1
|
||||
#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1
|
||||
#define GINPUT_MOUSE_MAX_CLICK_JITTER 0
|
||||
#define GINPUT_MOUSE_MAX_MOVE_JITTER 0
|
||||
#else
|
||||
#define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH
|
||||
#define GINPUT_MOUSE_CLICK_TIME 700 // Long click = Context Click
|
||||
#define GINPUT_MOUSE_NEED_CALIBRATION FALSE // Can be set to TRUE just for testing
|
||||
#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE
|
||||
#define GINPUT_MOUSE_READ_CYCLES 1
|
||||
#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 2
|
||||
#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
|
||||
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
|
||||
#endif
|
||||
|
||||
// This driver supports both an "interrupt" mode, and a polled mode
|
||||
#define GINPUT_MOUSE_POLL_PERIOD TIME_INFINITE // Interrupt driven by the Window thread
|
||||
//#define GINPUT_MOUSE_POLL_PERIOD 25 // Poll driven
|
||||
|
||||
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */
|
||||
/** @} */
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
To use this driver:
|
||||
|
||||
This driver is special in that it implements both the gdisp low level driver
|
||||
and a touchscreen driver.
|
||||
|
||||
1. Add in your gfxconf.h:
|
||||
a) #define GFX_USE_GDISP TRUE
|
||||
b) #define GFX_USE_GINPUT TRUE
|
||||
#define GINPUT_USE_MOUSE TRUE
|
||||
c) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
|
||||
d) Optionally the following (with appropriate values):
|
||||
#define GDISP_SCREEN_WIDTH 640
|
||||
#define GDISP_SCREEN_HEIGHT 480
|
||||
e) Optionally change the threading model to POSIX (instead of ChibiOS)
|
||||
#define GDISP_THREAD_CHIBIOS FALSE
|
||||
|
||||
2. To your makefile add the following lines:
|
||||
include $(GFXLIB)/gfx.mk
|
||||
include $(GFXLIB)/drivers/multiple/X/gdisp_lld.mk
|
||||
|
||||
3. Modify your makefile to add -lX11 to the DLIBS line. i.e.
|
||||
DLIBS = -lX11
|
||||
|
||||
3. If you changed your threading model to POSIX modify your makefile
|
||||
to add -pthread to the CC (or DDEFS) line. i.e.
|
||||
CC = $(TRGT)gcc -pthread
|
||||
|
|
@ -122,6 +122,7 @@
|
|||
#define GDISP_USE_GPIO
|
||||
#define TDISP_COLUMNS 16
|
||||
#define TDISP_ROWS 2
|
||||
#define GDISP_THREAD_CHIBIOS TRUE
|
||||
*/
|
||||
|
||||
#endif /* _GFXCONF_H */
|
||||
|
|
|
@ -276,6 +276,12 @@
|
|||
*/
|
||||
/* #define GDISP_SCREEN_WIDTH nnnn */
|
||||
/* #define GDISP_SCREEN_HEIGHT nnnn */
|
||||
/**
|
||||
* @brief Define which threading model to use.
|
||||
* @details Optional for the X11 driver.
|
||||
* @note Defaults to TRUE. Setting to FALSE causes POSIX threads to be used
|
||||
*/
|
||||
/* #define GDISP_THREAD_CHIBIOS FALSE */
|
||||
/**
|
||||
* @brief Define which bus interface to use.
|
||||
* @details Only required by the SSD1963 driver.
|
||||
|
|
Loading…
Reference in New Issue