hackathon-dev #1
|
@ -2,7 +2,7 @@ BUILDUTILS=../buildutils
|
||||||
RESOURCES=../resources
|
RESOURCES=../resources
|
||||||
SPLASHSCREEN=splash-vmwcblk.png
|
SPLASHSCREEN=splash-vmwcblk.png
|
||||||
|
|
||||||
OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_upiwin_tmp.o ep_util.o fbinit.o fontengine.o fbprimitive.o \
|
OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_upiwin_tmp.o ep_util.o fbinit.o rect.o fontengine.o fbprimitive.o \
|
||||||
log.o gpio.o msg_queue.o time_func.o config.o splash.o
|
log.o gpio.o msg_queue.o time_func.o config.o splash.o
|
||||||
LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm
|
LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm
|
||||||
CFLAGS=-I/usr/include/python3.7m -I/usr/include/freetype2 -I/usr/include/libpng16 \
|
CFLAGS=-I/usr/include/python3.7m -I/usr/include/freetype2 -I/usr/include/libpng16 \
|
||||||
|
|
31
src/gfxtype.h
Executable file
31
src/gfxtype.h
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef __GFXTYPE_H_INCLUDED
|
||||||
|
#define __GFXTYPE_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wintype.h"
|
||||||
|
|
||||||
|
typedef struct tagPOINT {
|
||||||
|
INT32 x;
|
||||||
|
INT32 y;
|
||||||
|
} POINT, *PPOINT;
|
||||||
|
|
||||||
|
typedef struct tagRECT {
|
||||||
|
INT32 left;
|
||||||
|
INT32 top;
|
||||||
|
INT32 right;
|
||||||
|
INT32 bottom;
|
||||||
|
} RECT, *PRECT;
|
||||||
|
|
||||||
|
typedef const POINT *PCPOINT;
|
||||||
|
typedef const RECT *PCRECT;
|
||||||
|
|
||||||
|
extern BOOL G_set_rect(PRECT rect, int left, int top, int right, int bottom);
|
||||||
|
extern BOOL G_set_rect_empty(PRECT rect);
|
||||||
|
extern BOOL G_inflate_rect(PRECT rect, int dx, int dy);
|
||||||
|
extern BOOL G_offset_rect(PRECT rect, int dx, int dy);
|
||||||
|
extern BOOL G_is_rect_empty(PCRECT rect);
|
||||||
|
extern BOOL G_point_in_rect(PCRECT rect, PCPOINT pt);
|
||||||
|
extern BOOL G_rect_equal(PCRECT rect1, PCRECT rect2);
|
||||||
|
extern BOOL G_rect_intersect(PRECT dest, PCRECT src1, PCRECT src2);
|
||||||
|
extern BOOL G_rect_union(PRECT dest, PCRECT src1, PCRECT src2);
|
||||||
|
|
||||||
|
#endif /* __GFXTYPE_H_INCLUDED */
|
|
@ -93,3 +93,12 @@ BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags)
|
||||||
pthread_mutex_unlock(&(queue->mutex));
|
pthread_mutex_unlock(&(queue->mutex));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL Mq_is_empty(PMSG_QUEUE queue)
|
||||||
|
{
|
||||||
|
BOOL rc;
|
||||||
|
pthread_mutex_lock(&(queue->mutex));
|
||||||
|
rc = (queue->head == queue->tail);
|
||||||
|
pthread_mutex_unlock(&(queue->mutex));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ extern void Mq_destroy(PMSG_QUEUE queue);
|
||||||
extern void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs);
|
extern void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs);
|
||||||
extern void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2);
|
extern void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2);
|
||||||
extern BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags);
|
extern BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags);
|
||||||
|
extern BOOL Mq_is_empty(PMSG_QUEUE queue);
|
||||||
|
|
||||||
#define Mq_post0(q, tgt, msg) Mq_post2(q, tgt, msg, 0, 0)
|
#define Mq_post0(q, tgt, msg) Mq_post2(q, tgt, msg, 0, 0)
|
||||||
#define Mq_post1(q, tgt, msg, attr) Mq_post2(q, tgt, msg, attr, 0)
|
#define Mq_post1(q, tgt, msg, attr) Mq_post2(q, tgt, msg, attr, 0)
|
||||||
|
|
91
src/rect.c
Executable file
91
src/rect.c
Executable file
|
@ -0,0 +1,91 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "gfxtype.h"
|
||||||
|
|
||||||
|
BOOL G_set_rect(PRECT rect, int left, int top, int right, int bottom)
|
||||||
|
{
|
||||||
|
rect->left = left;
|
||||||
|
rect->top = top;
|
||||||
|
rect->right = right;
|
||||||
|
rect->bottom = bottom;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_set_rect_empty(PRECT rect)
|
||||||
|
{
|
||||||
|
memset(rect, 0, sizeof(RECT));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_inflate_rect(PRECT rect, int dx, int dy)
|
||||||
|
{
|
||||||
|
rect->left += dx;
|
||||||
|
rect->top += dy;
|
||||||
|
rect->right -= dx;
|
||||||
|
rect->bottom -= dy;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_offset_rect(PRECT rect, int dx, int dy)
|
||||||
|
{
|
||||||
|
rect->left += dx;
|
||||||
|
rect->top += dy;
|
||||||
|
rect->right += dx;
|
||||||
|
rect->bottom += dy;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_is_rect_empty(PCRECT rect)
|
||||||
|
{
|
||||||
|
return (rect->right <= rect.left) || (rect->bottom <= rect.top);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_point_in_rect(PCRECT rect, PCPOINT pt)
|
||||||
|
{
|
||||||
|
return (rect->left <= pt->x) && (pt->x < rect->right) && (rect->top <= pt->y) && (pt->y < rect->bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_rect_equal(PCRECT rect1, PCRECT rect2)
|
||||||
|
{
|
||||||
|
return (memcmp(rect1, rect2, sizeof(RECT)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_rect_intersect(PRECT dest, PCRECT src1, PCRECT src2)
|
||||||
|
{
|
||||||
|
if (G_is_rect_empty(src1) || G_is_rect_empty(src2))
|
||||||
|
{
|
||||||
|
memset(dest, 0, sizeof(RECT));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if ((src1->left >= src2->right) || (src2->left >= src1->right) || (src1->top >= src2->bottom) || (src2->top >= src1->bottom))
|
||||||
|
{
|
||||||
|
memset(dest, 0, sizeof(RECT));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
dest->left = MAX(src1->left, src2->left);
|
||||||
|
dest->top = MAX(src1->top, src2->top);
|
||||||
|
dest->right = MIN(src1->right, src2->right);
|
||||||
|
dest->bottom = MIN(src1->bottom, src2->bottom);
|
||||||
|
ASSERT(dest->left <= dest->right);
|
||||||
|
ASSERT(dest->top <= dest->bottom);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL G_rect_union(PRECT dest, PCRECT src1, PCRECT src2)
|
||||||
|
{
|
||||||
|
if (G_is_rect_empty(src1))
|
||||||
|
{
|
||||||
|
memcpy(dest, src2, sizeof(RECT));
|
||||||
|
return !G_is_rect_empty(src2);
|
||||||
|
}
|
||||||
|
else if (G_is_rect_empty(src2))
|
||||||
|
{
|
||||||
|
memcpy(dest, src1, sizeof(RECT));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
dest->left = MIN(src1->left, src2->left);
|
||||||
|
dest->top = MIN(src1->top, src2->top);
|
||||||
|
dest->right = MAX(src1->right, src2->right);
|
||||||
|
dest->bottom = MAX(src1->bottom, src2->bottom);
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -21,6 +21,9 @@ static int ts_fd = 0; /* file descriptor for touchscreen */
|
||||||
static pthread_t ithread; /* input thread handle */
|
static pthread_t ithread; /* input thread handle */
|
||||||
static volatile sig_atomic_t running = 1; /* "running" flag for input thread */
|
static volatile sig_atomic_t running = 1; /* "running" flag for input thread */
|
||||||
|
|
||||||
|
static pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER; /* mutex for waiting on input */
|
||||||
|
static pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER; /* condition for waiting on input */
|
||||||
|
|
||||||
/* Local data for poll_buttons() */
|
/* Local data for poll_buttons() */
|
||||||
static UINT32 last_bstate = 0; /* previous button state */
|
static UINT32 last_bstate = 0; /* previous button state */
|
||||||
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT]; /* timestamps to debounce events */
|
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT]; /* timestamps to debounce events */
|
||||||
|
@ -30,8 +33,9 @@ static UINT_PTR touch_x = 0; /* X coordinate to send with next
|
||||||
static UINT_PTR touch_y = 0; /* Y coordinate to send with next message */
|
static UINT_PTR touch_y = 0; /* Y coordinate to send with next message */
|
||||||
static UINT32 touch_nextmsg = WM_TOUCHMOVE; /* identifier of next message to send */
|
static UINT32 touch_nextmsg = WM_TOUCHMOVE; /* identifier of next message to send */
|
||||||
|
|
||||||
static void poll_buttons(void)
|
static BOOL poll_buttons(void)
|
||||||
{
|
{
|
||||||
|
BOOL posted = FALSE;
|
||||||
UINT32 st, down, up, mask;
|
UINT32 st, down, up, mask;
|
||||||
UINT_PTR attr;
|
UINT_PTR attr;
|
||||||
TIMESTAMP now;
|
TIMESTAMP now;
|
||||||
|
@ -46,22 +50,28 @@ static void poll_buttons(void)
|
||||||
for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1)
|
for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1)
|
||||||
{
|
{
|
||||||
if (now < button_event_ok[attr - 1])
|
if (now < button_event_ok[attr - 1])
|
||||||
continue; /* this is a "contact bounce" event, don't bother */
|
continue; /* this is a "contact bounce" event, don't bother */
|
||||||
if (up & mask)
|
if (up & mask)
|
||||||
{
|
{
|
||||||
/* reset contact bounce timer - only seems to happen after button releases */
|
/* reset contact bounce timer - only seems to happen after button releases */
|
||||||
button_event_ok[attr - 1] = now + Gconfig.button_debounce;
|
button_event_ok[attr - 1] = now + Gconfig.button_debounce;
|
||||||
Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
|
Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
|
||||||
|
posted = TRUE;
|
||||||
}
|
}
|
||||||
else if (down & mask)
|
else if (down & mask)
|
||||||
Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr);
|
{
|
||||||
|
Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr);
|
||||||
|
posted = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last_bstate = st;
|
last_bstate = st;
|
||||||
}
|
}
|
||||||
|
return posted;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void poll_touchscreen(void)
|
static BOOL poll_touchscreen(void)
|
||||||
{
|
{
|
||||||
|
BOOL posted = FALSE;
|
||||||
int nb, nev, xerrno, i;
|
int nb, nev, xerrno, i;
|
||||||
struct input_event buffer[INPUT_EVENT_BATCH];
|
struct input_event buffer[INPUT_EVENT_BATCH];
|
||||||
|
|
||||||
|
@ -89,33 +99,37 @@ static void poll_touchscreen(void)
|
||||||
switch (buffer[i].type)
|
switch (buffer[i].type)
|
||||||
{
|
{
|
||||||
case EV_SYN:
|
case EV_SYN:
|
||||||
if (buffer[i].code == SYN_REPORT)
|
if (buffer[i].code == SYN_REPORT)
|
||||||
{
|
{
|
||||||
Mq_post2(Sys_Queue, 0, touch_nextmsg, touch_x, touch_y);
|
Mq_post2(Sys_Queue, 0, touch_nextmsg, touch_x, touch_y);
|
||||||
touch_nextmsg = WM_TOUCHMOVE;
|
touch_nextmsg = WM_TOUCHMOVE;
|
||||||
}
|
posted = TRUE;
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case EV_ABS:
|
case EV_ABS:
|
||||||
if (buffer[i].code == ABS_X)
|
if (buffer[i].code == ABS_X)
|
||||||
touch_x = buffer[i].value;
|
touch_x = buffer[i].value;
|
||||||
else if (buffer[i].code == ABS_Y)
|
else if (buffer[i].code == ABS_Y)
|
||||||
touch_y = buffer[i].value;
|
touch_y = buffer[i].value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EV_KEY:
|
case EV_KEY:
|
||||||
if (buffer[i].code == BTN_TOUCH)
|
if (buffer[i].code == BTN_TOUCH)
|
||||||
touch_nextmsg = (buffer[i].value ? WM_TOUCHDOWN : WM_TOUCHUP);
|
touch_nextmsg = (buffer[i].value ? WM_TOUCHDOWN : WM_TOUCHUP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return posted;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *input_thread(void *arg)
|
static void *input_thread(void *arg)
|
||||||
{
|
{
|
||||||
|
BOOL gotinput;
|
||||||
|
|
||||||
/* clear all state at startup */
|
/* clear all state at startup */
|
||||||
last_bstate = 0;
|
last_bstate = 0;
|
||||||
memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP));
|
memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP));
|
||||||
|
@ -124,8 +138,14 @@ static void *input_thread(void *arg)
|
||||||
|
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
poll_buttons();
|
gotinput = poll_buttons();
|
||||||
poll_touchscreen();
|
gotinput = poll_touchscreen() || gotinput;
|
||||||
|
if (gotinput)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&wait_mutex);
|
||||||
|
pthread_cond_signal(&wait_cond);
|
||||||
|
pthread_mutex_unlock(&wait_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -178,4 +198,15 @@ HRESULT Sys_enable_input(void)
|
||||||
do_disable_input();
|
do_disable_input();
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
error_0:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_wait_for_input(void)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&wait_mutex);
|
||||||
|
while (Mq_is_empty(Sys_Queue))
|
||||||
|
pthread_cond_wait(&wait_cond);
|
||||||
|
pthread_mutex_unlock(&wait_mutex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,6 @@
|
||||||
extern PMSG_QUEUE Sys_Queue;
|
extern PMSG_QUEUE Sys_Queue;
|
||||||
|
|
||||||
extern HRESULT Sys_enable_input(void);
|
extern HRESULT Sys_enable_input(void);
|
||||||
|
extern void Sys_wait_for_input(void);
|
||||||
|
|
||||||
#endif /* __SYSINPUT_H_INCLUDED */
|
#endif /* __SYSINPUT_H_INCLUDED */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user