Kaynağa Gözat

Added support for digital input events.

Fredrik Hultin 8 yıl önce
ebeveyn
işleme
b2d7641161

+ 17 - 0
include/openhmd.h

@@ -44,6 +44,7 @@ typedef enum {
 	OHMD_S_UNKNOWN_ERROR = -1,
 	OHMD_S_INVALID_PARAMETER = -2,
 	OHMD_S_UNSUPPORTED = -3,
+	OHMD_S_INVALID_OPERATION = -4,
 
 	/** OHMD_S_USER_RESERVED and below can be used for user purposes, such as errors within ohmd wrappers, etc. */
 	OHMD_S_USER_RESERVED = -16384,
@@ -125,6 +126,14 @@ typedef enum {
 	/** int[1] (get): Physical vertical resolution of the device screen. */
 	OHMD_SCREEN_VERTICAL_RESOLUTION       =  1,
 
+	/** int[1] (get): Get number of events waiting in digital input event queue. */
+	OHMD_BUTTON_EVENT_COUNT               =  2,
+	/** int[1] (get): Get if the there was an overflow in the event queue causing events to be dropped. */
+	OHMD_BUTTON_EVENT_OVERFLOW            =  3,
+	/** int[1] (get): Get the number of physical digital input buttons on the device. */
+	OHMD_BUTTON_COUNT                     =  4,
+	/** int[2] (get): Performs an event pop action. Format: [button_index, button_state], where button_state is either OHMD_BUTTON_DOWN or OHMD_BUTTON_UP */
+	OHMD_BUTTON_POP_EVENT                 =  5,
 } ohmd_int_value;
 
 /** A collection of data information types used for setting information with ohmd_set_data(). */
@@ -146,6 +155,14 @@ typedef enum {
 	OHMD_IDS_AUTOMATIC_UPDATE = 0,
 } ohmd_int_settings;
 
+/** Button states for digital input events. */
+typedef enum {
+	/** Button was pressed. */
+	OHMD_BUTTON_DOWN = 0,
+	/** Button was released. */
+	OHMD_BUTTON_UP   = 1
+} ohmd_button_state;
+
 /** An opaque pointer to a context structure. */
 typedef struct ohmd_context ohmd_context;
 

+ 2 - 1
src/Makefile.am

@@ -9,7 +9,8 @@ libopenhmd_la_SOURCES = \
 	drv_dummy/dummy.c \
 	omath.c \
 	platform-posix.c \
-	fusion.c
+	fusion.c \
+	queue.c
 
 libopenhmd_la_LDFLAGS = -no-undefined -version-info 0:0:0
 libopenhmd_la_CPPFLAGS = -fPIC -I$(top_srcdir)/include -Wall 

+ 43 - 9
src/openhmd.c

@@ -12,7 +12,9 @@
 #include <string.h>
 #include <stdio.h>
 
-// Running automatic updates at 144 Hz
+#define DIGITAL_INPUT_EVENT_QUEUE_SIZE 1024
+
+// Running automatic updates at 1000 Hz
 #define AUTOMATIC_UPDATE_SLEEP (1.0 / 1000.0)
 
 ohmd_context* OHMD_APIENTRY ohmd_ctx_create(void)
@@ -162,6 +164,9 @@ ohmd_device* OHMD_APIENTRY ohmd_list_open_device_s(ohmd_context* ctx, int index,
 		device->active_device_idx = ctx->num_active_devices;
 		ctx->active_devices[ctx->num_active_devices++] = device;
 
+		if(device->properties.digital_button_count > 0)
+			device->digital_input_event_queue = ohmdq_create(ctx, sizeof(ohmd_digital_input_event), DIGITAL_INPUT_EVENT_QUEUE_SIZE);
+
 		ohmd_unlock_mutex(ctx->update_mutex);
 
 		if(device->settings.automatic_update)
@@ -372,15 +377,44 @@ int OHMD_APIENTRY ohmd_device_setf(ohmd_device* device, ohmd_float_value type, c
 
 int OHMD_APIENTRY ohmd_device_geti(ohmd_device* device, ohmd_int_value type, int* out)
 {
+	ohmdq* dinq = device->digital_input_event_queue;
+
 	switch(type){
-	case OHMD_SCREEN_HORIZONTAL_RESOLUTION:
-		*out = device->properties.hres;
-		return OHMD_S_OK;
-	case OHMD_SCREEN_VERTICAL_RESOLUTION:
-		*out = device->properties.vres;
-		return OHMD_S_OK;
-	default:
-		return OHMD_S_INVALID_PARAMETER;
+		case OHMD_SCREEN_HORIZONTAL_RESOLUTION:
+			*out = device->properties.hres;
+			return OHMD_S_OK;
+
+		case OHMD_SCREEN_VERTICAL_RESOLUTION:
+			*out = device->properties.vres;
+			return OHMD_S_OK;
+
+		case OHMD_BUTTON_EVENT_COUNT:
+			*out = dinq ? (int)ohmdq_get_size(dinq) : 0;
+			return OHMD_S_OK;
+
+		case OHMD_BUTTON_EVENT_OVERFLOW:
+			*out = dinq ? (ohmdq_get_size(dinq) == ohmdq_get_max(dinq)) : 0;
+			return OHMD_S_OK;
+
+		case OHMD_BUTTON_COUNT:
+			*out = device->properties.digital_button_count;
+			return OHMD_S_OK;
+
+		case OHMD_BUTTON_POP_EVENT: {
+				ohmd_digital_input_event event;
+
+				if(!ohmdq_pop(dinq, &event)){
+					return OHMD_S_INVALID_OPERATION;
+				}
+
+				out[0] = event.idx;
+				out[1] = event.state;
+
+				return OHMD_S_OK;
+			}
+
+		default:
+				return OHMD_S_INVALID_PARAMETER;
 	}
 }
 

+ 15 - 6
src/openhmdi.h

@@ -10,15 +10,16 @@
 #ifndef OPENHMDI_H
 #define OPENHMDI_H
 
-#include "openhmd.h"
-#include "omath.h"
-#include "platform.h"
-
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "openhmd.h"
+#include "omath.h"
+#include "platform.h"
+#include "queue.h"
+
 #define OHMD_MAX_DEVICES 16
 
 #define OHMD_MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
@@ -28,8 +29,7 @@
 
 typedef struct ohmd_driver ohmd_driver;
 
-typedef struct
-{
+typedef struct {
 	char driver[OHMD_STR_SIZE];
 	char vendor[OHMD_STR_SIZE];
 	char product[OHMD_STR_SIZE];
@@ -43,6 +43,11 @@ typedef struct {
 	ohmd_device_desc devices[OHMD_MAX_DEVICES];
 } ohmd_device_list;
 
+typedef struct {
+	int idx;
+	ohmd_button_state state; 
+} ohmd_digital_input_event;
+
 struct ohmd_driver {
 	void (*get_device_list)(ohmd_driver* driver, ohmd_device_list* list);
 	ohmd_device* (*open_device)(ohmd_driver* driver, ohmd_device_desc* desc);
@@ -53,6 +58,8 @@ struct ohmd_driver {
 typedef struct {
 		int hres;
 		int vres;
+		int digital_button_count;
+
 		float hsize;
 		float vsize;
 
@@ -99,6 +106,8 @@ struct ohmd_device {
 
 	quatf rotation;
 	vec3f position;
+	
+	ohmdq* digital_input_event_queue;
 };
 
 

+ 96 - 0
src/queue.c

@@ -0,0 +1,96 @@
+/*
+ * OpenHMD - Free and Open Source API and drivers for immersive technology.
+ * Copyright (C) 2016 Fredrik Hultin.
+ * Distributed under the Boost 1.0 licence, see LICENSE for full text.
+ */
+
+/* Naive Thread Safe Circular Queue Implementation */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "queue.h"
+#include "openhmdi.h"
+
+struct ohmdq {
+	unsigned read_pos;
+	unsigned write_pos;
+	unsigned size;
+	unsigned max;
+	unsigned elem_size;
+	char* elems;
+	ohmd_mutex* mutex;
+};
+
+ohmdq* ohmdq_create(ohmd_context* ctx, unsigned elem_size, unsigned max)
+{
+	ohmdq* me = ohmd_alloc(ctx, sizeof(ohmdq));
+
+	me->elems = ohmd_alloc(ctx, elem_size * max);
+	me->max = max;
+	me->elem_size = elem_size;
+	me->read_pos = 0;
+	me->write_pos = 0;
+	me->size = 0;
+	me->mutex = ohmd_create_mutex(ctx);
+
+	return me;
+}
+
+bool ohmdq_push(ohmdq* me, const void* elem)
+{
+	bool ret = false;
+
+	ohmd_lock_mutex(me->mutex);	
+
+	if(me->size < me->max){
+		memcpy(me->elems + me->write_pos, elem, me->elem_size);
+		me->write_pos = (me->write_pos + me->elem_size) % (me->max * me->elem_size);
+		me->size++;
+		ret = true;
+	}
+
+	ohmd_unlock_mutex(me->mutex);	
+
+	return ret;
+}
+
+bool ohmdq_pop(ohmdq* me, void* out_elem)
+{
+	bool ret = false;
+	
+	ohmd_lock_mutex(me->mutex);	
+
+	if(me->size > 0){
+		memcpy(out_elem, me->elems + me->read_pos, me->elem_size);
+		me->read_pos = (me->read_pos + me->elem_size) % (me->max * me->elem_size);
+		me->size--;
+		ret = true;
+	}
+	
+	ohmd_unlock_mutex(me->mutex);	
+
+	return ret;
+}
+
+unsigned ohmdq_get_size(ohmdq* me)
+{
+	unsigned ret;
+
+	ohmd_lock_mutex(me->mutex);
+	ret = me->size;
+	ohmd_unlock_mutex(me->mutex);
+
+	return ret;
+}
+
+unsigned ohmdq_get_max(ohmdq* me)
+{
+	return me->max;
+}
+
+void ohmdq_destroy(ohmdq* me)
+{
+	free(me->elems);
+	ohmd_destroy_mutex(me->mutex);
+}

+ 25 - 0
src/queue.h

@@ -0,0 +1,25 @@
+/*
+ * OpenHMD - Free and Open Source API and drivers for immersive technology.
+ * Copyright (C) 2016 Fredrik Hultin.
+ * Distributed under the Boost 1.0 licence, see LICENSE for full text.
+ */
+
+/* Naive Thread Safe Circular Queue */
+
+#ifndef OHMDQUEUE_H
+#define OHMDQUEUE_H
+
+#include <stdbool.h>
+
+typedef struct ohmdq ohmdq;
+typedef struct ohmd_context ohmd_context;
+
+ohmdq* ohmdq_create(ohmd_context* ctx, unsigned elem_size, unsigned max);
+void ohmdq_destroy(ohmdq* me);
+
+bool ohmdq_push(ohmdq* me, const void* elem);
+bool ohmdq_pop(ohmdq* me, void* out_elem);
+unsigned ohmdq_get_size(ohmdq* me);
+unsigned ohmdq_get_max(ohmdq* me);
+
+#endif

+ 1 - 1
tests/unittests/Makefile.am

@@ -1,5 +1,5 @@
 bin_PROGRAMS = unittests
 AM_CPPFLAGS = -Wall -Werror -I$(top_srcdir)/include -I$(top_srcdir)/src -DOHMD_STATIC
-unittests_SOURCES = main.c quat.c vec.c highlevel.c
+unittests_SOURCES = main.c quat.c vec.c highlevel.c queue.c
 unittests_LDADD = $(top_builddir)/src/libopenhmd.la -lm
 unittests_LDFLAGS = -static-libtool-libs

+ 4 - 0
tests/unittests/main.c

@@ -38,6 +38,10 @@ int main()
 	Test(test_highlevel_open_close_device);
 	Test(test_highlevel_open_close_many_devices);
 	printf("\n");
+	
+	printf("queue tests\n");
+	Test(test_ohmdq_push_pop);
+	printf("\n");
 
 	printf("all a-ok\n");
 	return 0;

+ 58 - 0
tests/unittests/queue.c

@@ -0,0 +1,58 @@
+/*
+ * OpenHMD - Free and Open Source API and drivers for immersive technology.
+ * Copyright (C) 2016 Fredrik Hultin.
+ * Distributed under the Boost 1.0 licence, see LICENSE for full text.
+ */
+
+/* Unit Tests - Queue */
+
+#include "tests.h"
+#include "openhmdi.h"
+
+void test_ohmdq_push_pop()
+{
+	ohmd_context* ctx = ohmd_ctx_create();
+	ohmdq* q = ohmdq_create(ctx, sizeof(int), 10);
+	
+	TAssert(ohmdq_get_max(q) == 10);
+
+	for(int i = 0; i < 10; i++){
+		bool ret = ohmdq_push(q, &i);
+		TAssert(ret);
+	}
+
+	TAssert(ohmdq_get_size(q) == 10);
+	
+	int val = 0;
+	bool ret = ohmdq_push(q, &val);
+	TAssert(!ret);
+
+	for(int i = 0; i < 10; i++){
+		int val = 0;
+		bool ret = ohmdq_pop(q, &val);
+		TAssert(ret);
+		TAssert(val == i);
+	}
+	
+	TAssert(ohmdq_get_size(q) == 0);
+	
+	for(int i = 0; i < 10; i++){
+		bool ret = ohmdq_push(q, &i);
+		TAssert(ret);
+	}
+
+	TAssert(ohmdq_get_size(q) == 10);
+	
+	val = 0;
+	ret = ohmdq_push(q, &val);
+	TAssert(!ret);
+
+	for(int i = 0; i < 10; i++){
+		int val = 0;
+		bool ret = ohmdq_pop(q, &val);
+		TAssert(ret);
+		TAssert(val == i);
+	}
+	
+	TAssert(ohmdq_get_size(q) == 0);
+}

+ 3 - 0
tests/unittests/tests.h

@@ -44,4 +44,7 @@ void test_oquatf_get_mat4x4();
 void test_highlevel_open_close_device();
 void test_highlevel_open_close_many_devices();
 
+// queue tests
+void test_ohmdq_push_pop();
+
 #endif