ArmbandInterface.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include "stdafx.h"
  2. extern "C" {
  3. #include "MotorHeader/BodyActuator.h"
  4. }
  5. #include <time.h>
  6. #include <stdio.h>
  7. #include "ArmbandInterface.h"
  8. #include <stdlib.h>
  9. /*
  10. 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.
  11. 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.
  12. Basically, this class acts as a single static BodyActuator instance towards outside callers, and can be used from within managed (specifically C#) code.
  13. (side note: the use of the terms 'function' and 'method' might be a bit messy here...)
  14. */
  15. /*
  16. 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)
  17. */
  18. //type of the BodyActuator_init function
  19. typedef void(__cdecl *InitFunctionType)(BodyActuator*, BodyActuator_Type, char*, int);
  20. //type of the BodyActuator_clear function
  21. typedef void(__cdecl *ClearFunctionType)(BodyActuator*);
  22. //type of the BodyActuator_delete function
  23. typedef void(__cdecl *DeleteFunctionType)(BodyActuator*);
  24. //type of the BodyActuator_actuate function
  25. typedef void(__cdecl *ActuateFunctionType)(BodyActuator*, uint8_t, float, uint64_t);
  26. //type of the BodyActuator_startActuation function
  27. typedef void(__cdecl *StartFunctionType)(BodyActuator*, uint8_t, float);
  28. //type of the BodyActuator_stopActuation function
  29. typedef void(__cdecl *StopFunctionType)(BodyActuator*, uint8_t);
  30. //type of the BodyActuator_setFrequency function
  31. typedef void(__cdecl *SetFrequencyFunctionType)(BodyActuator*, uint8_t, uint16_t);
  32. //type of the BodyActuator_setIntensityRange function
  33. typedef void(__cdecl *SetIntensityRangeFunctionType)(BodyActuator*, uint8_t, float, float);
  34. /*
  35. static variables to hold the dynamically linked function handles, one per linked function in the BodyActuator dll
  36. */
  37. //binding of the BodyActuator_init function
  38. static InitFunctionType initFunctionHandle;
  39. //binding of the BodyActuator_clear function
  40. static ClearFunctionType clearFunctionHandle;
  41. //binding of the BodyActuator_delete function
  42. static DeleteFunctionType deleteFunctionHandle;
  43. //binding of the BodyActuator_actuate function
  44. static ActuateFunctionType actuateFunctionHandle;
  45. //binding of the BodyActuator_startActuation function
  46. static StartFunctionType startFunctionHandle;
  47. //binding of the BodyActuator_stopActuation function
  48. static StopFunctionType stopFunctionHandle;
  49. //binding of the BodyActuator_setFrequency function
  50. static SetFrequencyFunctionType setFrequencyFunctionHandle;
  51. //binding of the BodyActuator_setIntensityRange function
  52. static SetIntensityRangeFunctionType setIntensityRangeFunctionHandle;
  53. //static variable to hold the dynamically loaded 'BodyActuator.dll' dll after loading for further processing (acquiring function handles)
  54. static HINSTANCE lib;
  55. //static variable holding the instance of BodyActuator on/with which the methods are called
  56. static BodyActuator* armband;
  57. //port has to be COM5, as it is hardcoded in the given BodyActuator dll and can not be changed //static char *port =
  58. //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
  59. //specifies the export to follow C style rules (e.g. C style name mangling), only necessary for 'public' methods
  60. extern "C" {
  61. /*
  62. public initialization method for external calls, loading the BodyActuator dll and linking its methods to the previously defined function
  63. handles, aswell as creating and initializing the single static BodyActuator object afterwards (allocates memory to that pointer without
  64. releasing it, as the pointer is still needed outside of this method -> mus be freed later)
  65. return value may be used for debugging purposes and holds no other purpose
  66. */
  67. DllExport int __cdecl ArmbandInterface::setupArmband() {
  68. //load the library at runtime and assign it to the variable
  69. lib = LoadLibrary(TEXT("BodyActuator.dll"));
  70. if (lib == NULL) {
  71. printf("ERROR: library could not be loaded");
  72. return 0;
  73. }
  74. //bind the various function handles
  75. initFunctionHandle = (InitFunctionType)GetProcAddress(lib, "BodyActuator_init");
  76. if (initFunctionHandle == NULL) {
  77. printf("ERROR: init function could not be retrieved");
  78. return 1;
  79. }
  80. clearFunctionHandle = (ClearFunctionType)GetProcAddress(lib, "BodyActuator_clear");
  81. if (clearFunctionHandle == NULL) {
  82. printf("ERROR: init function could not be retrieved");
  83. return 2;
  84. }
  85. deleteFunctionHandle = (DeleteFunctionType)GetProcAddress(lib, "BodyActuator_delete");
  86. if (deleteFunctionHandle == NULL) {
  87. printf("ERROR: delete function could not be retrieved");
  88. return 3;
  89. }
  90. startFunctionHandle = (StartFunctionType)GetProcAddress(lib, "BodyActuator_startActuation");
  91. if (startFunctionHandle == NULL) {
  92. printf("ERROR: start function could not be retrieved");
  93. return 4;
  94. }
  95. stopFunctionHandle = (StopFunctionType)GetProcAddress(lib, "BodyActuator_stopActuation");
  96. if (stopFunctionHandle == NULL) {
  97. printf("ERROR: stop function could not be retrieved");
  98. return 5;
  99. }
  100. actuateFunctionHandle = (ActuateFunctionType)GetProcAddress(lib, "BodyActuator_actuate");
  101. if (actuateFunctionHandle == NULL) {
  102. printf("ERROR: actuate function could not be retrieved");
  103. return 6;
  104. }
  105. setFrequencyFunctionHandle = (SetFrequencyFunctionType)GetProcAddress(lib, "BodyActuator_setFrequency");
  106. if (setFrequencyFunctionHandle == NULL) {
  107. printf("ERROR: setFrequency function could not be retrieved");
  108. return 7;
  109. }
  110. setIntensityRangeFunctionHandle = (SetIntensityRangeFunctionType)GetProcAddress(lib, "BodyActuator_setIntensityRange");
  111. if (setIntensityRangeFunctionHandle == NULL) {
  112. printf("ERROR: setIntensityRange function could not be retrieved");
  113. return 8;
  114. }
  115. //initialize the BodyActuator instance
  116. return setupMotors();
  117. }
  118. /*
  119. resets the instance of BodyActuator to a clean state
  120. */
  121. DllExport void __cdecl ArmbandInterface::clearArmband() {
  122. (clearFunctionHandle)(armband);
  123. //printf("armband cleared");
  124. }
  125. /*
  126. destructor method destroying the instance of BodyActuator and freeing the memory held by the instance pointer
  127. */
  128. DllExport void __cdecl ArmbandInterface::deleteArmband() {
  129. (deleteFunctionHandle)(armband);
  130. free(armband);
  131. //printf("armband deleted");
  132. }
  133. /*
  134. start vibrating the specified tactor (number from 0 to 7) at the specified intensity until it is stopped (explicitly or implicitly)
  135. 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#
  136. */
  137. DllExport void __cdecl ArmbandInterface::startVibrate(int tactor, double intensity) {
  138. (startFunctionHandle)(armband, tactor, intensity);
  139. //printf("sollte gehen");
  140. }
  141. /*
  142. explicitly stop actuating the specified tactor (number from 0 to 7)
  143. 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#
  144. */
  145. DllExport void __cdecl ArmbandInterface::stopVibrate(int tactor) {
  146. (stopFunctionHandle)(armband, (uint8_t)tactor);
  147. }
  148. /*
  149. make the specified tactor (number from 0 to 7) actuate at intensity 1.0 (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
  150. 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#
  151. */
  152. DllExport void __cdecl ArmbandInterface::actuate100(int tactor, double intensity, int duration) {
  153. (actuateFunctionHandle)(armband, tactor, 1.0, duration);
  154. }
  155. /*
  156. make the specified tactor (number from 0 to 7) actuate at a intensity 0.66 (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
  157. 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#
  158. */
  159. DllExport void __cdecl ArmbandInterface::actuate66(int tactor, double intensity, int duration) {
  160. (actuateFunctionHandle)(armband, tactor, 0.66, duration);
  161. }
  162. /*
  163. make the specified tactor (number from 0 to 7) actuate at intensity 0.33 (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
  164. 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#
  165. */
  166. DllExport void __cdecl ArmbandInterface::actuate33(int tactor, double intensity, int duration) {
  167. (actuateFunctionHandle)(armband, tactor, 0.33, duration);
  168. }
  169. /*
  170. sets the frequency of the specified tactor to a new value (unit unknown atm...)
  171. */
  172. DllExport void __cdecl ArmbandInterface::setFrequency(int tactor, int frequency) {
  173. (setFrequencyFunctionHandle)(armband, tactor, frequency);
  174. }
  175. /*
  176. 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)
  177. */
  178. DllExport void __cdecl ArmbandInterface::setIntensityRange(int tactor, double minIntensity, double maxIntensity) {
  179. (setIntensityRangeFunctionHandle)(armband, tactor, minIntensity, maxIntensity);
  180. }
  181. }
  182. /*
  183. internal method to initialize the BodyActuator object (and handle the memory allocation involved)
  184. */
  185. int ArmbandInterface::setupMotors() {
  186. char* port = (char*) "COM5";//malloc(7);
  187. armband = (BodyActuator*) malloc(sizeof(BodyActuator*));
  188. //strcpy_s(port, "COM5");
  189. try {
  190. (initFunctionHandle)(armband, BODYACTUATOR_TYPE_EAI, port, 8);
  191. return -1;
  192. }
  193. catch (...) {
  194. return -99;
  195. }
  196. //printf("armband initialized");
  197. }