Browse Source

completed StaticLibMotors dll (now representing a full interface to BodyActuator.dll), added documentation to staticLibMotors and added documentation to LocalArmbandInterface

Vincenz Mechler 5 years ago
parent
commit
02bb8cab48

+ 40 - 22
SketchAssistant/SketchAssistantWPF/LocalArmbandInterface.cs

@@ -7,38 +7,56 @@ using System.Runtime.InteropServices;
 
 namespace SketchAssistantWPF
 {
+    /// <summary>
+    /// interface providing access to the vibrotactile armband
+    /// accessing the BodyActuator.dll C library via the StaticLibMotors.dll c++ library
+    /// </summary>
     public static class LocalArmbandInterface
     {
-
+        /// <summary>
+        /// initializes the armband (and binds the C dll)
+        /// must be called before calling any other of the methods of this class
+        /// explicitly allocates memory and therefore must only be called once and must be followed by a call to DestroyArmband eventually
+        /// </summary>
+        /// <returns>an integer purely for debugging purposes, -1 means no unexpected behaviour occured and the initialization was successful</returns>
         [DllImport (@"../Debug/StaticLibMotors.dll", EntryPoint = "?setupArmband@ArmbandInterface@@QAAHXZ",
      CallingConvention = CallingConvention.Cdecl)]
-        public static extern int setupArmband();
-
-       [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?startVibrate@ArmbandInterface@@QAAXHM@Z",
-     CallingConvention = CallingConvention.Cdecl)]
-        public static extern void startVibrate(int motorNumber, float intensity);
-
-        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?stopVibrate@ArmbandInterface@@QAAXH@Z",                       
-     CallingConvention = CallingConvention.Cdecl)]
-        public static extern void stopVibration(int motorNumber);
+        public static extern int SetupArmband();
 
-        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?actuate100@ArmbandInterface@@QAAXXZ",
+        /// <summary>
+        /// destroys the armband instance created by SetupArmband (thus freeing its allocated memory)
+        /// </summary>
+        /// <returns></returns>
+        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?destroyArmband@ArmbandInterface@@QAAHXZ",
      CallingConvention = CallingConvention.Cdecl)]
-        public static extern void actuate100();
-
-        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?actuate66@ArmbandInterface@@QAAXXZ",
+        public static extern int DestroyArmband();
+
+        /// <summary>
+        /// starts actuation of the specified tactor (motor) at the specified intensity (until it is stopped)
+        /// </summary>
+        /// <param name="motorNumber">integer from 0 to 7 specifying the number of the tactor to actuate</param>
+        /// <param name="intensity">intensity, ranging from 0.0 to 1.0 by default</param>
+        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?startVibrate@ArmbandInterface@@QAAXHM@Z",
      CallingConvention = CallingConvention.Cdecl)]
-        public static extern void actuate66();
+        public static extern void StartVibrate(int motorNumber, double intensity);
 
-        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?actuate33@ArmbandInterface@@QAAXXZ",
+        /// <summary>
+        /// stop actuation of the specified tactor (motor)
+        /// </summary>
+        /// <param name="motorNumber">integer from 0 to 7 specifying the number of the tactor to stop</param>
+        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?stopVibrate@ArmbandInterface@@QAAXH@Z",                       
      CallingConvention = CallingConvention.Cdecl)]
-        public static extern void actuate33();
-
-      /*  [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?deleteArmband@ArmbandInterface@@QAAXXZ",
+        public static extern void StopVibration(int motorNumber);
+
+        /// <summary>
+        /// starts actuation of the specified tactor (motor) at the specified intensity for a specified amount of time
+        /// </summary>
+        /// <param name="tactor">integer from 0 to 7 specifying the number of the tactor to actuate</param>
+        /// <param name="intensity">intensity, ranging from 0.0 to 1.0 by default</param>
+        /// <param name="duration">number of millisecons to actuate the tactor for</param>
+        [DllImport(@"../Debug/StaticLibMotors.dll", EntryPoint = "?actuate@ArmbandInterface@@QAAXXZ",
      CallingConvention = CallingConvention.Cdecl)]
-        public static extern void deleteArmband(); */
-
-        //public void Vibrate()
+        public static extern void Actuate(int tactor, double intensity, int duration);
 
     }
 }

+ 1 - 1
SketchAssistant/SketchAssistantWPF/MVP_Model.cs

@@ -113,7 +113,7 @@ namespace SketchAssistantWPF
         {
             //TODO remove
             Console.WriteLine("trying to initialize Armband...");
-            int tmp= LocalArmbandInterface.setupArmband();
+            int tmp= LocalArmbandInterface.SetupArmband();
             Console.WriteLine("Armband initialization terminated, exit code: " + tmp);
             programPresenter = presenter;
             historyOfActions = new ActionHistory();

+ 161 - 73
SketchAssistant/StaticLib1/ArmbandInterface.cpp

@@ -6,102 +6,190 @@ extern "C" {
 #include <stdio.h>
 #include "ArmbandInterface.h"
 #include <stdlib.h>
+/*
+This is a static class acting as a interface for the BodActuator dll, which is plain C code and can't be called directly from C# (managed) code.
+Therefore this class will encapsulate all memory management necessary to instantiate and use an Object of the BodyActuator type, aswell as provide all modyfying methods to external callers.
+Basically, this class acts as a single static BodyActuator instance towards outside callers, and can be used from within managed (specifically C#) code.
+(side note: the use of the terms 'function' and 'method' might be a bit messy here...)
+*/
 
+/*
+function handles are defined as a custom type to be able to dynamically bind and use methods from the C dll (no lib, neither source code for BodyActuator available, therefore only dynamic linking is possible)
+*/
+//type of the BodyActuator_init function
 typedef void(__cdecl *InitFunctionType)(BodyActuator*, BodyActuator_Type, char*, int);
-typedef void(__cdecl *StopFunctionType)(BodyActuator*, uint8_t);
-typedef void(__cdecl *StartFunctionType)(BodyActuator*, uint8_t, float);
-typedef void(__cdecl *ActuateFunctionType)(BodyActuator*, uint8_t, float, uint64_t);
+//type of the BodyActuator_clear function
+typedef void(__cdecl *ClearFunctionType)(BodyActuator*);
+//type of the BodyActuator_delete function
 typedef void(__cdecl *DeleteFunctionType)(BodyActuator*);
+//type of the BodyActuator_actuate function
+typedef void(__cdecl *ActuateFunctionType)(BodyActuator*, uint8_t, double, uint64_t);
+//type of the BodyActuator_startActuation function
+typedef void(__cdecl *StartFunctionType)(BodyActuator*, uint8_t, double);
+//type of the BodyActuator_stopActuation function
+typedef void(__cdecl *StopFunctionType)(BodyActuator*, uint8_t);
+//type of the BodyActuator_setFrequency function
+typedef void(__cdecl *SetFrequencyFunctionType)(BodyActuator*, uint8_t, uint16_t);
+//type of the BodyActuator_setIntensityRange function
+typedef void(__cdecl *SetIntensityRangeFunctionType)(BodyActuator*, uint8_t, double, double);
 
+/*
+static variables to hold the dynamically linked function handles, one per linked function in the BodyActuator dll
+*/
+//binding of the BodyActuator_init function
 static InitFunctionType initFunctionHandle;
+//binding of the BodyActuator_clear function
+static ClearFunctionType clearFunctionHandle;
+//binding of the BodyActuator_delete function
+static DeleteFunctionType deleteFunctionHandle;
+//binding of the BodyActuator_actuate function
+static ActuateFunctionType actuateFunctionHandle;
+//binding of the BodyActuator_startActuation function
 static StartFunctionType startFunctionHandle;
+//binding of the BodyActuator_stopActuation function
 static StopFunctionType stopFunctionHandle;
-static ActuateFunctionType actuateFunctionHandle;
-static DeleteFunctionType deleteFunctionHandle;
+//binding of the BodyActuator_setFrequency function
+static SetFrequencyFunctionType setFrequencyFunctionHandle;
+//binding of the BodyActuator_setIntensityRange function
+static SetIntensityRangeFunctionType setIntensityRangeFunctionHandle;
 
-static BodyActuator* armband;
-//static char *port = 
 
+//static variable to hold the dynamically loaded 'BodyActuator.dll' dll after loading for further processing (acquiring function handles)
 static HINSTANCE lib;
 
+//static variable holding the instance of BodyActuator on/with which the methods are called
+static BodyActuator* armband;
+
+//port has to be COM5, as it is hardcoded in the given BodyActuator dll and can not be changed //static char *port = 
+//if the tactor control unit is connected to a different port: under windows 10 the Serial Port of a device can be changed via the device manager
+
+
+//specifies the export to follow C style rules (e.g. C style name mangling), only necessary for 'public' methods
 extern "C" {
+
+	/*
+	 public initialization method for external calls, loading the BodyActuator dll and linking its methods to the previously defined function 
+	 handles, aswell as creating and initializing the single static BodyActuator object afterwards (allocates memory to that pointer without 
+	 releasing it, as the pointer is still needed outside of this method -> mus be freed later)
+	 return value may be used for debugging purposes and holds no other purpose
+	 */
 	DllExport int __cdecl ArmbandInterface::setupArmband() {
-			lib = LoadLibrary(TEXT("BodyActuator.dll"));
-			if (lib == NULL) {
-				printf("ERROR: library could not be loaded");
-				return 0;
-			}
-			initFunctionHandle = (InitFunctionType)GetProcAddress(lib, "BodyActuator_init");
-			if (initFunctionHandle == NULL) {
-				printf("ERROR: init function could not be retrieved");
-				return 1;
-			}
-			startFunctionHandle = (StartFunctionType)GetProcAddress(lib, "BodyActuator_startActuation");
-			if (startFunctionHandle == NULL) {
-				printf("ERROR: start function could not be retrieved");
-				return 2;
-			}
-			stopFunctionHandle = (StopFunctionType)GetProcAddress(lib, "BodyActuator_stopActuation");
+		//load the library at runtime and assign it to the variable
+		lib = LoadLibrary(TEXT("BodyActuator.dll"));
+		if (lib == NULL) {
+			printf("ERROR: library could not be loaded");
+			return 0;
+		}
+		//bind the various function handles
+		initFunctionHandle = (InitFunctionType)GetProcAddress(lib, "BodyActuator_init");
+		if (initFunctionHandle == NULL) {
+			printf("ERROR: init function could not be retrieved");
+			return 1;
+		}
+		clearFunctionHandle = (ClearFunctionType)GetProcAddress(lib, "BodyActuator_clear");
+		if (clearFunctionHandle == NULL) {
+			printf("ERROR: init function could not be retrieved");
+			return 2;
+		}
+		deleteFunctionHandle = (DeleteFunctionType)GetProcAddress(lib, "BodyActuator_delete");
+		if (deleteFunctionHandle == NULL) {
+			printf("ERROR: delete function could not be retrieved");
+			return 3;
+		}
+		startFunctionHandle = (StartFunctionType)GetProcAddress(lib, "BodyActuator_startActuation");
+		if (startFunctionHandle == NULL) {
+			printf("ERROR: start function could not be retrieved");
+			return 4;
+		}
+		stopFunctionHandle = (StopFunctionType)GetProcAddress(lib, "BodyActuator_stopActuation");
 			if (stopFunctionHandle == NULL) {
-				printf("ERROR: stop function could not be retrieved");
-				return 3;
-			}
-			actuateFunctionHandle = (ActuateFunctionType)GetProcAddress(lib, "BodyActuator_actuate");
-			if (actuateFunctionHandle == NULL) {
-				printf("ERROR: actuate function could not be retrieved");
-				return 4;
-			}
-			deleteFunctionHandle = (DeleteFunctionType)GetProcAddress(lib, "BodyActuator_delete");
-			if (deleteFunctionHandle == NULL) {
-				printf("ERROR: delete function could not be retrieved");
-				return 5;
-			}
-			//strcpy(port, "COM5");
-			setupMotors();
-			//actuate100(0, 1.0, 20);
-			//startVibrate(0, 1.0);
-			return -1;
+			printf("ERROR: stop function could not be retrieved");
+			return 5;
 		}
-
-		DllExport void __cdecl ArmbandInterface::startVibrate(int tactor, float intensity) {
-			(startFunctionHandle)(armband, 0, 1.0);
-			printf("sollte gehen");
+		actuateFunctionHandle = (ActuateFunctionType)GetProcAddress(lib, "BodyActuator_actuate");
+			if (actuateFunctionHandle == NULL) {
+			printf("ERROR: actuate function could not be retrieved");
+			return 6;
 		}
-
-		DllExport void __cdecl ArmbandInterface::stopVibrate(int tactor) {
-			(stopFunctionHandle)(armband, (uint8_t)tactor);
+		setFrequencyFunctionHandle = (SetFrequencyFunctionType)GetProcAddress(lib, "BodyActuator_setFrequency");
+		if (setFrequencyFunctionHandle == NULL) {
+			printf("ERROR: setFrequency function could not be retrieved");
+			return 7;
 		}
-		
-		DllExport void __cdecl ArmbandInterface::actuate100() {
-			(actuateFunctionHandle)(armband, 0, 1.0, 20);
+		setIntensityRangeFunctionHandle = (SetIntensityRangeFunctionType)GetProcAddress(lib, "BodyActuator_setIntensityRange");
+		if (setIntensityRangeFunctionHandle == NULL) {
+			printf("ERROR: setIntensityRange function could not be retrieved");
+			return 8;
 		}
+		//initialize the BodyActuator instance
+		setupMotors();
+		return -1;
+	}
 
-		DllExport void __cdecl ArmbandInterface::actuate66() {
-		(actuateFunctionHandle)(armband, 0, 0.66, 20);
-		}
+	/*
+	resets the instance of BodyActuator to a clean state
+	*/
+	DllExport void __cdecl ArmbandInterface::clearArmband() {
+		(clearFunctionHandle)(armband);
+		//printf("armband cleared");
+	}
 
-		DllExport void __cdecl ArmbandInterface::actuate33() {
-		(actuateFunctionHandle)(armband, 0, 0.33, 20);
-		}
+	/*
+	destructor method destroying the instance of BodyActuator and freeing the memory held by the instance pointer
+	*/
+	DllExport void __cdecl ArmbandInterface::deleteArmband() {
+		(deleteFunctionHandle)(armband);
+		free(armband);
+		//printf("armband deleted");
+	}
+
+	/*
+	start vibrating the specified tactor (number from 0 to 7) at the specified intensity until it is stopped (explicitly or implicitly)
+	provides access to the DLLs BodyActuator_startActuation method and handles type conversion to C types required by the DLL which are not available in C#
+	*/
+	DllExport void __cdecl ArmbandInterface::startVibrate(int tactor, double intensity) {
+		(startFunctionHandle)(armband, tactor, intensity);
+		//printf("sollte gehen");
+	}
+			
+	/*
+	explicitly stop actuating the specified tactor (number from 0 to 7)
+	provides access to the DLLs BodyActuator_stopActuation method and handles type conversion to C types required by the DLL which are not available in C#
+	*/
+	DllExport void __cdecl ArmbandInterface::stopVibrate(int tactor) {
+		(stopFunctionHandle)(armband, (uint8_t)tactor);
+	}
 	
-		DllExport void __cdecl ArmbandInterface::deleteArmband() {
-			(deleteFunctionHandle)(armband);
-			printf("armband deleted");
-		}
+	/*
+	make the specified tactor (number from 0 to 7) actuate at a specified intensity (default: between 0.0 and 1.0, but range may be set using the setIntensityRange function) for the specified duration (number of milliseconds) ,or until it is stopped
+	provides access to the DLLs BodyActuator_actuate method and handles type conversion to C types required by the DLL which are not available in C#
+	*/
+	DllExport void __cdecl ArmbandInterface::actuate(int tactor, double intensity, int duration) {
+		(actuateFunctionHandle)(armband, tactor, intensity, duration);
+	}
+
+	/*
+	sets the frequency of the specified tactor to a new value (unit unknown atm...)
+	*/
+	DllExport void __cdecl ArmbandInterface::setFrequency(int tactor, int frequency) {
+		(setFrequencyFunctionHandle)(armband, tactor, frequency);
+	}
+
+	/*
+	sets a new intensity range for a single actuator to make different actuators react differently even when receiving an actuation command with the same intensity (e.g. to to compensate differing tactile sensitivity on different parts of the human body)
+	*/
+	DllExport void __cdecl ArmbandInterface::setIntensityRange(int tactor, double minIntensity, double maxIntensity) {
+		(setIntensityRangeFunctionHandle)(armband, tactor, minIntensity, maxIntensity);
+	}
 }
 
- void ArmbandInterface::setupMotors() {
+/*
+internal method to initialize the BodyActuator object (and handle the memory allocation involved)
+*/
+void ArmbandInterface::setupMotors() {
 	 char* port = (char*) "COM5";//malloc(7);
 	 armband = (BodyActuator*) malloc(sizeof(BodyActuator*));
 	 //strcpy_s(port, "COM5");
-			(initFunctionHandle) (armband, BODYACTUATOR_TYPE_EAI, port, 8);
-			printf("armband initialized");
-		}
-
- /*void ArmbandInterface::deleteArmband() {
-	 (deleteFunctionHandle)(armband);
- }*/
-
- /*void ArmbandInterface::actuate(int tactor, double intensity, int duration) {
-	 (actuateFunctionHandle)(armband, tactor, intensity, duration);
-}*/
+	(initFunctionHandle) (armband, BODYACTUATOR_TYPE_EAI, port, 8);
+	//printf("armband initialized");
+}

+ 48 - 16
SketchAssistant/StaticLib1/ArmbandInterface.h

@@ -6,9 +6,14 @@ extern "C" {
 #include <time.h>
 #include <stdio.h>
 #define DllExport extern "C" __declspec( dllexport )
+/*
+This is the header file of a static class acting as a interface for the BodActuator dll, which is plain C code and can't be called directly from C# (managed) code.
+Therefore this class will encapsulate all memory management necessary to instantiate and use an Object of the BodyActuator type, aswell as provide all modyfying methods to external callers.
+Basically, this class acts as a single static BodyActuator instance towards outside callers, and can be used from within managed (specifically C#) code.
+(side note: the use of the terms 'function' and 'method' might be a bit messy here...)
+*/
 
-
-
+/*
 DllExport int setupArmband();
 DllExport void startVibrate(int tactor, float intensity);
 DllExport void stopVibrate(int tactor);
@@ -16,25 +21,52 @@ DllExport void actuate100();
 DllExport void actuate66();
 DllExport void actuate33();
 DllExport void deleteArmband();
+*/
 
 class ArmbandInterface
 {
-	/*
-	typedef void(__cdecl *InitFunctionType)(BodyActuator*, BodyActuator_Type, char*, int);
-	static InitFunctionType initFunctionHandle;
-	typedef void(__cdecl *StartFunctionType)(BodyActuator*, uint8_t, float);
-	static StartFunctionType startFunctionHandle;
-	typedef void(__cdecl *StopFunctionType)(BodyActuator*, uint8_t);
-	static StopFunctionType stopFunctionHandle; */
-
 	public:
+		/*
+		 public initialization method for external calls, loading the BodyActuator dll and linking its methods to the previously defined function
+		 handles, aswell as creating and initializing the single static BodyActuator object afterwards (allocates memory to that pointer without
+		 releasing it, as the pointer is still needed outside of this method -> mus be freed later)
+		 return value may be used for debugging purposes and holds no other purpose
+		 */
 		__declspec(dllexport) int __cdecl  setupArmband();
-		__declspec(dllexport) void __cdecl startVibrate(int tactor, float intensity);
-		__declspec(dllexport) void __cdecl stopVibrate(int tactor);
-		__declspec(dllexport) void __cdecl actuate100();
-		__declspec(dllexport) void __cdecl actuate66();
-		__declspec(dllexport) void __cdecl actuate33();
+		/*
+		resets the instance of BodyActuator to a clean state
+		*/
+		__declspec(dllexport) void __cdecl clearArmband();
+		/*
+		destructor method destroying the instance of BodyActuator and freeing the memory held by the instance pointer
+		*/
 		__declspec(dllexport) void __cdecl deleteArmband();
+		/*
+		start vibrating the specified tactor (number from 0 to 7) at the specified intensity until it is stopped (explicitly or implicitly)
+		provides access to the DLLs BodyActuator_startActuation method and handles type conversion to C types required by the DLL which are not available in C#
+		*/
+		__declspec(dllexport) void __cdecl startVibrate(int tactor, double intensity);
+		/*
+		explicitly stop actuating the specified tactor (number from 0 to 7)
+		provides access to the DLLs BodyActuator_stopActuation method and handles type conversion to C types required by the DLL which are not available in C#
+		*/
+		__declspec(dllexport) void __cdecl stopVibrate(int tactor);
+		/*
+		make the specified tactor (number from 0 to 7) actuate at a specified intensity (default: between 0.0 and 1.0, but range may be set using the setIntensityRange function) for the specified duration (number of milliseconds) ,or until it is stopped
+		provides access to the DLLs BodyActuator_actuate method and handles type conversion to C types required by the DLL which are not available in C#
+		*/
+		__declspec(dllexport) void __cdecl actuate(int tactor, double intensity, int duration);
+		/*
+		sets the frequency of the specified tactor to a new value (unit unknown atm...)
+		*/
+		__declspec(dllexport) void __cdecl setFrequency(int tactor, int frequency);
+		/*
+		sets a new intensity range for a single actuator to make different actuators react differently even when receiving an actuation command with the same intensity (e.g. to to compensate differing tactile sensitivity on different parts of the human body)
+		*/
+		__declspec(dllexport) void __cdecl setIntensityRange(int tactor, double minIntensity, double maxIntensity);
+	private:
+		/*
+		internal method to initialize the BodyActuator object (and handle the memory allocation involved)
+		*/
 		void setupMotors();
-	//	void actuate(int tactor, double intensity, int duration);
 };